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' ])
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')