#!/usr/bin/env python

# Copyright 2017 Mir Calculate. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

from gi.repository import GLib

import dbus
import dbus.service
import dbus.mainloop.glib
import os
import time
import socket

DBUS_INTERFACE="org.calculate.CoreInterface"
DBUS_NAME="org.calculate.Core"
DBUS_OBJECT="/Core"


def check_port(target, port, timeout=5):
    """
    Проверить порт (port) на хосте (target)
    :param target: хост
    :param port: порт
    :param timeout: таймаут
    :return: True - порт открыт, False - нет хоста, порт закрыт, firewall
    """
    try:
        targetIP = socket.gethostbyname(target)
    except socket.gaierror:
        return False

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(timeout)
    try:
        s.connect((targetIP, port))
        s.close()
    except (socket.error, socket.timeout):
        return False
    return True

class CoreObject(dbus.service.Object):

    @dbus.service.method(DBUS_INTERFACE,
                         in_signature='i', out_signature='b')
    def Start(self, port):
        try:
            if not self.check_core(port):
                os.system("source /etc/profile;/sbin/start-stop-daemon --background --start "
                          "--pidfile /var/run/cl_core.pid "
                          "--exec /usr/sbin/cl-core -- "
                          "--pid-file /var/run/cl_core.pid --close-on-inactive --start")
                for x in range(0, 24):
                    if self.check_core(port):
                        return True
                    time.sleep(0.5)
                else:
                    return False
            return True
        finally:
            self.mainloop.quit()

    @dbus.service.method(DBUS_INTERFACE,
                         in_signature='i', out_signature='b')
    def Ping(self, port):
        try:
            return self.check_core(port)
        finally:
            self.mainloop.quit()

    def check_core(self, port):
        return check_port("127.0.0.1", port)
        

    @dbus.service.method(DBUS_INTERFACE, in_signature='', out_signature='s')
    def ServerHostname(self):
        try:
            import OpenSSL
            cert_file = "/var/calculate/server/ca/server.crt"
            if os.path.exists(cert_file):
                with open(cert_file) as f:
                    cert = f.read()
                    cert_obj = OpenSSL.crypto.load_certificate(
                        OpenSSL.SSL.FILETYPE_PEM, cert)
                    subject = cert_obj.get_subject().get_components()
                    for subj in subject:
                        if subj[0] == b'CN':
                            return str(subj[1], 'utf-8')
        except Exception:
            pass
        return "localhost"

if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    system_bus = dbus.SystemBus()
    name = dbus.service.BusName(DBUS_NAME, system_bus)
    obj = CoreObject(system_bus, DBUS_OBJECT)
    obj.mainloop = GLib.MainLoop()
    obj.mainloop.run()
