Exemplo n.º 1
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        uic.loadUi(os.path.join(UI_DIR, 'config_server_window.ui'), self)
        self.storage = ServerStorage()
        self.__init_ui()

    def __init_ui(self):
        def switch_refresh():
            if self.action_refresh.isChecked():
                self.timer_refresh.start()
            else:
                self.timer_refresh.stop()

        def open_config_func():
            win = ConfigWindow(self)
            win.exec_()

        self.open_config.triggered.connect(lambda: open_config_func())
        self.action_refresh.triggered.connect(lambda: switch_refresh())
        self.refresh()

        self.timer_refresh = QTimer()
        self.timer_refresh.setInterval(10000)
        self.timer_refresh.timeout.connect(self.refresh)

    def refresh(self):
        self.load_users()
        self.load_users_online()
        self.load_users_stats()
        self.load_history()

    def load_users(self):
        users = self.storage.get_users()  # temp
        tbl = self.users_tbl
        fiil_table(tbl, users, ['id', 'name'], ['id', 'name'])

    def load_users_online(self):
        online = self.storage.get_users_online()
        tbl = self.users_online_tbl
        fiil_table(tbl, online, ['name'], ['name'])

    def load_users_stats(self):
        stats = self.storage.get_user_stats()
        tbl = self.user_stats_tbl
        fiil_table(tbl, stats, ['name', 'sent', 'recv'],
                   ['User.name', 'UserStat.mes_sent', 'UserStat.mes_recv'])

    def load_history(self):
        history = self.storage.get_history()
        tbl = self.history_tbl
        fiil_table(tbl, history, ['id', 'name', 'date', 'ip'], [
            'LoginHistory.id', 'User.name', 'LoginHistory.datetime',
            'LoginHistory.ip'
        ])
Exemplo n.º 2
0
class Server:
    __slots__ = ('bind_addr', '_port', 'logger', 'socket', 'clients', 'users',
                 'storage', 'commands', 'listener')

    TCP = (AF_INET, SOCK_STREAM)
    TIMEOUT = 5

    port = Port('_port')

    def __init__(self, bind_addr, port):
        self.logger = logging.getLogger(log_config.LOGGER_NAME)
        self.bind_addr = bind_addr
        self.port = port
        self.clients = []
        self.users = {}
        self.storage = ServerStorage()
        self.__init_commands()

    def __init_commands(self):
        self.commands = {
            'get_users': self.storage.get_users_online,
            'add_contact': self.storage.add_contact,
            'rem_contact': self.storage.remove_contact,
            'get_contacts': self.storage.get_contacts,
        }

    def start(self, request_count=5):
        self.socket = socket(*self.TCP)
        self.socket.settimeout(0.5)
        self.socket.bind((self.bind_addr, self.port))
        self.logger.info(
            f'Config server port - {self.port}| Bind address - {self.bind_addr}'
        )

        self.socket.listen(request_count)
        # self.__listen()

        self.listener = ServerThread(self.__listen, self.logger)
        self.listener.start()
        # self.__console()

    def __console(self):
        while True:
            msg = input('Enter command:\n')
            if msg.upper() == 'Q':
                break
            if msg[0] == '#':
                msg = msg[1:]

            command, *args = msg.split(' ')
            if command in self.commands:
                res = self.commands[command](*args)
                print(res)

    def __listen(self):
        self.logger.info('Start listen')
        while True:
            try:
                client, addr = self.socket.accept()
            except OSError:
                pass
            except Exception as ex:
                self.logger.error(ex)
            else:
                self.logger.info(f'Connection from {addr}')
                self.clients.append(client)

            i_clients, o_clients = [], []
            try:
                i_clients, o_clients, ex = select(self.clients, self.clients,
                                                  [], self.TIMEOUT)
            except OSError:
                pass
            except Exception as ex:
                self.logger.error(ex)

            requests = self.__get_requests(i_clients)
            if requests:
                self.__send_responses(requests, o_clients)

    @try_except_wrapper
    def __get_requests(self, i_clients):
        requests = {}
        for client in i_clients:
            try:
                request = get_data(client)
                requests[client] = request

                if request.action == RequestAction.PRESENCE:
                    if request.body in self.users:
                        requests.pop(client)
                        send_data(client, Response(CONFLICT))
                        self.clients.remove(client)
                    else:
                        self.users[request.body] = client
                        self.storage.login_user(request.body,
                                                client.getpeername()[0])
                elif request.action == RequestAction.QUIT:
                    self.__client_disconnect(client)
            except (ConnectionError, ValueError):
                self.__client_disconnect(client)
            except Exception as e:
                raise e
        return requests

    @try_except_wrapper
    def __send_responses(self, requests, o_clients):

        for client, i_req in requests.items():
            other_clients = [c for c in o_clients if c != client]
            self.logger.info(client)
            self.logger.info(i_req)

            if i_req.action == RequestAction.PRESENCE:
                self.__send_to_client(client, Response(OK))
                self.__send_to_all(other_clients,
                                   Response(BASIC, f'{i_req.body} connected'))
            elif i_req.action == RequestAction.QUIT:
                self.__client_disconnect(client)
            elif i_req.action == RequestAction.MESSAGE:
                msg = Msg.from_dict(i_req.body)
                self.storage.user_stat_update(msg.sender, ch_sent=1)
                if msg.to.upper() != 'ALL' and msg.to in self.users:
                    self.storage.user_stat_update(msg.to, ch_recv=1)
                    self.__send_to_client(self.users[msg.to],
                                          Response(BASIC, str(msg)))
                else:
                    self.__send_to_all(other_clients,
                                       Response(BASIC, str(msg)))
                    for u in self.storage.get_users_online():
                        if str(u) == msg.sender:
                            continue
                        self.storage.user_stat_update(str(u), ch_recv=1)

            elif i_req.action == RequestAction.COMMAND:
                command, *args = i_req.body.split()
                user = [u for u, c in self.users.items() if c == client].pop()
                args.insert(0, user)
                # o_resp = Response(ANSWER, self.__execute_command(command, *args))
                o_resp = self.__execute_command(command, *args)
                self.__send_to_client(client, o_resp)
            else:
                self.__send_to_client(client, Response(INCORRECT_REQUEST))
                self.logger.error(f'Incorrect request:\n {i_req}')

    @try_except_wrapper
    def __send_to_client(self, client, resp):
        try:
            send_data(client, resp)
        except ConnectionError:
            self.__client_disconnect(client)
        except Exception as e:
            raise e

    def __send_to_all(self, clients, resp):
        for cl in clients:
            self.__send_to_client(cl, resp)

    @try_except_wrapper
    def __client_disconnect(self, client):
        self.clients.remove(client)
        disconnected_user = [u for u, c in self.users.items()
                             if c == client].pop()
        self.users.pop(disconnected_user)
        self.storage.logout_user(disconnected_user)
        disconnection_response = Response(BASIC,
                                          f'{disconnected_user} disconnected')
        for cl in self.clients:
            send_data(cl, disconnection_response)

    def __execute_command(self, command, *args):
        if command in self.commands:
            answer = self.commands[command](*args)
            if answer is False:
                return Response(SERVER_ERROR, 'Command error')
            elif isinstance(answer, list):
                answer = [str(a) for a in answer]
                return Response(ANSWER, answer)
            elif answer is None:
                return Response(ANSWER, 'Done')
            return Response(ANSWER, answer)
        else:
            return Response(INCORRECT_REQUEST, 'Command not found')