class Server:
    """Класс с логикой сервера"""
    def __init__(self, port_number: int) -> None:

        logger.info(f"Запуск сервера..")
        self.port_number = port_number
        self.sock = None
        self.database = DataProcessing()
        self.socket_init()

        # Список авторизации
        self.authenticated_list = []
        # Список ip, которым надо пройти регистрацию
        self.reg_list = []

        self.ip2username_dict = {}

        logger.info(f"Сервер инициализировался, слушает порт {port_number}")

        self.connection_thread = None
        self.play_command()

        self.input_processing()

    def connection_processing(self):
        """
        Метод ожидания подключений клиентов
        Запускается в отдельном потоке
        """
        # Ожидаем новое соединение
        while self.receive_data:
            # Новое соединение
            conn, addr = self.sock.accept()

            logger.info(f"Новое соединение от {addr[0]}")
            t = threading.Thread(target=self.server_router, args=(conn, addr))
            t.daemon = True
            t.start()

    def input_processing(self):
        """
        Метод ввода команд для управления сервером
        1. Отключение сервера (завершение программы);
        2. Пауза (остановка прослушивание порта);
        3. Показ логов;
        4. Очистка логов;
        5. Очистка файла идентификации.
        """
        commands_dict = {
            "exit": {
                "command": self.exit_command,
                "description": "Выход из программы"
            },
            "pause": {
                "command": self.stop_command,
                "description": "Приостановить получение новых соединений",
            },
            "stop": {
                "command": self.stop_command,
                "description": "Приостановить получение новых соединений",
            },
            "play": {
                "command": self.play_command,
                "description": "Продолжить получение новых соединений",
            },
            "start": {
                "command": self.play_command,
                "description": "Продолжить получение новых соединений",
            },
            "start logs": {
                "command": self.start_logs_command,
                "description": "Выводить логи в консоли",
            },
            "stop logs": {
                "command": self.stop_logs_command,
                "description": "Не выводить логи в консоли",
            },
            "clear auth": {
                "command": self.clear_auth_command,
                "description": "Отчистка файла для авторизации пользователей",
            },
            "clear logs": {
                "command": self.clear_logs_command,
                "description": "Отчистка файла логирования",
            },
        }

        while True:
            command_str = input()
            if command_str in commands_dict:
                commands_dict[command_str]["command"]()
            else:
                commands_str = "\n".join([
                    f"{k} - {v['description']}"
                    for k, v in commands_dict.items()
                ])
                print(
                    f"Команда не найдена\nДоступные команды:\n{commands_str}")

    def exit_command(self):
        """Обработчик завершения работы сервера"""
        logger.info("Завершаем работу сервера")
        sys.exit()

    def stop_command(self):
        """Команда приостановки"""
        if self.connection_thread is None:
            raise ValueError(
                "Нельзя остановить поток подключений, если он не был запущен!")
        self.receive_data = False
        logger.info("Приостановили поток получения данных клиентов")

    def clear_auth_command(self):
        """Отчистка файла авторизации"""
        self.database.clear()
        logger.info("Отчистили файл аворизации пользователей")

    def start_logs_command(self):
        """Показывает логи"""
        if stream_handler not in logger.handlers:
            logger.addHandler(stream_handler)
            logger.info("Возобновили показ логов в консоли")

    def stop_logs_command(self):
        """Стопает показ логов в консоли"""
        if stream_handler in logger.handlers:
            logger.removeHandler(stream_handler)
            logger.info("Приостановили показ логов в консоли")

    def clear_logs_command(self):
        """Отчистка файла логов"""
        open(LOGGER_FILE, "w").close()
        logger.info("Отчистили файл логов")

    def play_command(self):
        # Поток обработки подлючений от клиентов
        self.receive_data = True
        t = threading.Thread(target=self.connection_processing)
        t.daemon = True
        t.start()
        self.connection_thread = t

    def send_message(self, conn, data: Union[str, Dict[str, Any]],
                     ip: str) -> None:
        """Отправка данных"""
        data_text = data
        if type(data) == dict:
            data = json.dumps(data, ensure_ascii=False)

        data += END_MESSAGE_FLAG
        data = data.encode()
        conn.send(data)
        logger.info(f"Сообщение {data_text} было отправлено клиенту {ip}")

    def socket_init(self):
        """Инициализация сокета"""
        sock = socket.socket()
        sock.bind(("", self.port_number))
        sock.listen(0)
        # Наш сокет
        self.sock = sock

    def new_event_logic(self, conn, client_ip):
        """
        Логика обработки новых событий, которые приходят с клиента
        """
        data = ""

        # Имя пользователя по его ip
        username = self.ip2username_dict[client_ip]
        # Экземпляр класса для работы с файлами конкретного пользователя
        userfiles_logic = FTPFileProcessing(username)

        while True:
            # Получаем данные и собираем их по кусочкам
            chunk = conn.recv(1024)
            data += chunk.decode()

            # Если это конец сообщения, то значит, что мы все собрали и можем отдавать данные каждому соединению
            if END_MESSAGE_FLAG in data:

                data = data.replace(END_MESSAGE_FLAG, "")

                # Проверяем то, что это: файл или команда

                # Это файл
                if FILE_DETECT_FLAG in data:
                    logger.info(
                        f"Получили файл {data} от клиента {client_ip} ({username})"
                    )
                    # Записываем файл

                    file_name, file_content = data.split(FILE_DETECT_FLAG)
                    transfer_flag = userfiles_logic.client2server_transfer(
                        file_name, file_content)
                    if transfer_flag:
                        out_data = {
                            "result": True,
                            "description": "file received"
                        }
                    else:
                        out_data = {
                            "result": False,
                            "description": "file saving error"
                        }
                    self.send_message(conn, out_data, client_ip)

                # Команда для получения файла пользователя с сервера
                elif "get" in data:

                    description, is_result = userfiles_logic.server2client_transfer(
                        data)
                    out_data = {
                        "result": is_result,
                        "description": description
                    }
                    self.send_message(conn, out_data, client_ip)

                # Это одна из стандартных команд FTPFileProcessing
                else:

                    logger.info(
                        f"Получили команду {data} от клиента {client_ip} ({username})"
                    )

                    command = data.split(" ")

                    # Остановка работы программы
                    if command[0] == "exit":
                        break

                    # Получаем результат существования команды
                    result = userfiles_logic.router(command[0])

                    out_data = {"result": None, "description": None}

                    # Если есть такая команда
                    if result:
                        try:
                            description_str = result(*command[1:])
                            out_data = {
                                "result": True,
                                "description": description_str
                            }

                        except TypeError:
                            description_str = f"Команда {command[0]} была вызвана с некорректными аргументами"
                            out_data = {
                                "result": False,
                                "description": description_str
                            }
                    else:
                        commands_str = "\n".join([
                            f"{key} - {value}" for (
                                key,
                                value,
                            ) in userfiles_logic.get_commands().items()
                        ])
                        description_str = f"Команда {command[0]} не найдена! Список команд:\n{commands_str}"
                        out_data = {
                            "result": False,
                            "description": description_str
                        }

                    self.send_message(conn, out_data, client_ip)

                # Обнуляем буфер сообщений
                data = ""

            # Значит пришла только часть большого сообщения
            else:
                logger.info(
                    f"Приняли часть данных от клиента {client_ip}: '{data}'")

            # Если вообще ничего не пришло - это конец всего соединения
            if not chunk:
                break

    def reg_logic(self, conn, addr):
        """
        Логика регистрации пользователя
        """
        newuser_ip = addr[0]
        try:
            data = json.loads(conn.recv(1024).decode())
        except JSONDecodeError:
            if newuser_ip in self.reg_list:
                self.reg_list.remove(newuser_ip)
            return
        newuser_password, newuser_username = hash(
            data["password"]), data["username"]

        self.database.user_reg(newuser_ip, newuser_password, newuser_username)
        logger.info(f"Клиент {newuser_ip} -> регистрация прошла успешно")
        create_flag = FTPFileProcessing.new_user_reg(newuser_username)
        if create_flag:
            logger.info(
                f"Клиент {newuser_ip} -> создали root-директорию {newuser_username}"
            )
        else:
            logger.error(
                f"Клиент {newuser_ip} -> не удалось создать root-директорию {newuser_username}"
            )

        data = {"result": True}
        if newuser_ip in self.reg_list:
            self.reg_list.remove(newuser_ip)
            logger.info(f"Удалили клиента {newuser_ip} из списка регистрации")

        self.send_message(conn, data, newuser_ip)
        logger.info(
            f"Клиент {newuser_ip}. Отправили данные о результате регистрации")

    def auth_logic(self, conn, addr):
        """
        Логика авторизации клиента
        Запрос авторизации у нас априори меньше 1024, так что никакой цикл не запускаем
        """
        try:
            user_password = hash(
                json.loads(conn.recv(1024).decode())["password"])
        except JSONDecodeError:
            return
        client_ip = addr[0]

        # Проверяем на существование данных
        auth_result, username = self.database.user_auth(
            client_ip, user_password)

        # Если авторизация прошла успешно
        if auth_result == 1:
            logger.info(f"Клиент {client_ip} -> авторизация прошла успешно")
            data = {"result": True, "body": {"username": username}}
            if client_ip not in self.authenticated_list:
                self.authenticated_list.append(client_ip)
                self.ip2username_dict[client_ip] = username
                logger.info(
                    f"Добавили клиента {client_ip} в список авторизации")
        # Если авторизация не удалась, но пользователь с таким ip существует
        elif auth_result == 0:
            logger.info(f"Клиент {client_ip} -> авторизация не удалась")
            data = {"result": False, "description": "wrong auth"}
        # Если пользователя с таким ip не существует, то необходима регистрация
        else:
            logger.info(
                f"Клиент {client_ip} -> необходима предварительная регистрация в системе"
            )
            data = {"result": False, "description": "registration required"}
            if client_ip not in self.reg_list:
                self.reg_list.append(client_ip)
                logger.info(
                    f"Добавили клиента {client_ip} в список регистрации")

        self.send_message(conn, data, client_ip)
        logger.info(
            f"Клиент {client_ip}. Отправили данные о результате авторизации")

        # Если была успешная авторизация - принимаем последующие сообщения от пользователя
        if auth_result == 1:
            self.new_event_logic(conn, client_ip)

    def server_router(self, conn, addr):
        """
        Роутинг в зависимости от авторизации клиента
        """
        logger.info("Server router работает в отдельном потоке!")
        client_ip = addr[0]

        # Если клиенту нужна авторизация
        if client_ip in self.reg_list:
            self.reg_logic(conn, addr)

        # Если ip не авторизован - надо авторизовать
        elif client_ip not in self.authenticated_list:
            self.auth_logic(conn, addr)

        # Если уже был авторизован
        else:
            self.new_event_logic(conn, client_ip)

        logger.info(f"Отключение клиента {client_ip}")
        # Если клиент был в списке авторизации - удаляем его
        if client_ip in self.authenticated_list:
            self.authenticated_list.remove(client_ip)
            logger.info(f"Удалили клиента {client_ip} из списка авторизации")

    def __del__(self):
        logger.info(f"Остановка сервера")
class Server:
    def __init__(self, port_number: int) -> None:

        logger.info(f"Запуск сервера..")
        self.port_number = port_number
        self.sock = None
        self.database = DataProcessing()
        self.socket_init()

        # Список авторизации
        self.authenticated_list = []
        # Список ip, которым надо пройти регистрацию
        self.reg_list = []
        # Список соединений, по которым рассылаются сообщения
        self.connections_list = []

        self.ip2username_dict = {}
        logger.info(f"Сервер инициализировался, слушает порт {port_number}")

        self.connection_thread = None
        self.play_command()

        self.input_processing()

    def connection_processing(self):
        """
        Метод ожидания подключений клиентов
        Запускается в отдельном потоке
        """
        # Ожидаем новое соединение
        while self.receive_data:
            # Новое соединение
            conn, addr = self.sock.accept()

            # Добавляем новое соединение
            self.connections_list.append((conn, addr))
            logger.info(f"Новое соединение от {addr[0]}")
            t = threading.Thread(target=self.router, args=(conn, addr))
            t.daemon = True
            t.start()

    def input_processing(self):
        """
        Метод ввода команд для управления сервером
        1. Отключение сервера (завершение программы);
        2. Пауза (остановка прослушивание порта);
        3. Показ логов;
        4. Очистка логов;
        5. Очистка файла идентификации.
        """
        commands_dict = {
            "exit": {"command": self.exit_command, "description": "Выход из программы"},
            "pause": {
                "command": self.stop_command,
                "description": "Приостановить получение новых соединений",
            },
            "stop": {
                "command": self.stop_command,
                "description": "Приостановить получение новых соединений",
            },
            "play": {
                "command": self.play_command,
                "description": "Продолжить получение новых соединений",
            },
            "start": {
                "command": self.play_command,
                "description": "Продолжить получение новых соединений",
            },
            "start logs": {
                "command": self.start_logs_command,
                "description": "Выводить логи в консоли",
            },
            "stop logs": {
                "command": self.stop_logs_command,
                "description": "Не выводить логи в консоли",
            },
            "clear auth": {
                "command": self.clear_auth_command,
                "description": "Отчистка файла для авторизации пользователей",
            },
            "clear logs": {
                "command": self.clear_logs_command,
                "description": "Отчистка файла логирования",
            },
        }

        while True:
            command_str = input()
            if command_str in commands_dict:
                commands_dict[command_str]["command"]()
            else:
                commands_str = "\n".join(
                    [f"{k} - {v['description']}" for k, v in commands_dict.items()]
                )
                print(f"Команда не найдена\nДоступные команды:\n{commands_str}")

    def exit_command(self):
        """Обработчик завершения работы сервера"""
        logger.info("Завершаем работу сервера")
        sys.exit()

    def stop_command(self):
        """Команда приостановки"""
        if self.connection_thread is None:
            raise ValueError(
                "Нельзя остановить поток подключений, если он не был запущен!"
            )
        self.receive_data = False
        logger.info("Приостановили поток получения данных клиентов")

    def clear_auth_command(self):
        """Отчистка файла авторизации"""
        self.database.clear()
        logger.info("Отчистили файл аворизации пользователей")

    def start_logs_command(self):
        """Показывает логи"""
        if stream_handler not in logger.handlers:
            logger.addHandler(stream_handler)
            logger.info("Возобновили показ логов в консоли")

    def stop_logs_command(self):
        """Стопает показ логов в консоли"""
        if stream_handler in logger.handlers:
            logger.removeHandler(stream_handler)
            logger.info("Приостановили показ логов в консоли")

    def clear_logs_command(self):
        """Отчистка файла логов"""
        open(LOGGER_FILE, "w").close()
        logger.info("Отчистили файл логов")

    def play_command(self):
        # Поток обработки подлючений от клиентов
        self.receive_data = True
        t = threading.Thread(target=self.connection_processing)
        t.daemon = True
        t.start()
        self.connection_thread = t

    def send_message(self, conn, data: Union[str, Dict[str, Any]], ip: str) -> None:
        """Отправка данных"""
        data_text = data
        if type(data) == dict:
            data = json.dumps(data, ensure_ascii=False)

        data = data.encode()
        conn.send(data)
        logger.info(f"Сообщение {data_text} было отправлено клиенту {ip}")

    def socket_init(self):
        """Инициализация сокета"""
        sock = socket.socket()
        sock.bind(("", self.port_number))
        sock.listen(0)
        # Наш сокет
        self.sock = sock

    def message_logic(self, conn, client_ip):
        """
        Получение сообщений
        """
        data = ""
        while True:
            # Получаем данные и собираем их по кусочкам
            chunk = conn.recv(1024)
            data += chunk.decode()

            # Если это конец сообщения, то значит, что мы все собрали и можем отдавать данные каждому соединению
            if END_MESSAGE_FLAG in data:

                username = self.ip2username_dict[client_ip]
                logger.info(
                    f"Получили сообщение {data} от клиента {client_ip} ({username})"
                )
                data = {"username": username, "text": data}

                # Рассылка по каждому соединению
                logger.info(
                    f"Текущее кол-во подключений к серверу: {len(self.connections_list)}"
                )
                for connection in self.connections_list:
                    current_conn, current_ip = connection
                    try:
                        self.send_message(current_conn, data, current_ip)
                    # Если вдруг у нас появилсоь соедиение, которое уже неактивно
                    except BrokenPipeError:
                        continue

                # Обнуляемся
                data = ""

            # Значит пришла только часть большого сообщения
            else:
                logger.info(f"Приняли часть данных от клиента {client_ip}: '{data}'")

            # Если вообще ничего не пришло - это конец всего соединения
            if not chunk:
                break

    def reg_logic(self, conn, addr):
        """
        Логика регистрации пользователя
        """
        newuser_ip = addr[0]
        try:
            data = json.loads(conn.recv(1024).decode())
        except JSONDecodeError:
            if newuser_ip in self.reg_list:
                self.reg_list.remove(newuser_ip)
            return
        newuser_password, newuser_username = hash(data["password"]), data["username"]

        self.database.user_reg(newuser_ip, newuser_password, newuser_username)
        logger.info(f"Клиент {newuser_ip} -> регистрация прошла успешно")
        data = {"result": True}
        if newuser_ip in self.reg_list:
            self.reg_list.remove(newuser_ip)
            logger.info(f"Удалили клиента {newuser_ip} из списка регистрации")

        self.send_message(conn, data, newuser_ip)
        logger.info(f"Клиент {newuser_ip}. Отправили данные о результате регистрации")

    def auth_logic(self, conn, addr):
        """
        Логика авторизации клиента
        Запрос авторизации у нас априори меньше 1024, так что никакой цикл не запускаем
        """
        try:
            user_password = hash(json.loads(conn.recv(1024).decode())["password"])
        except JSONDecodeError:
            return
        client_ip = addr[0]

        # Проверяем на существование данных
        auth_result, username = self.database.user_auth(client_ip, user_password)

        # Если авторизация прошла успешно
        if auth_result == 1:
            logger.info(f"Клиент {client_ip} -> авторизация прошла успешно")
            data = {"result": True, "body": {"username": username}}
            if client_ip not in self.authenticated_list:
                self.authenticated_list.append(client_ip)
                self.ip2username_dict[client_ip] = username
                logger.info(f"Добавили клиента {client_ip} в список авторизации")
        # Если авторизация не удалась, но пользователь с таким ip существует
        elif auth_result == 0:
            logger.info(f"Клиент {client_ip} -> авторизация не удалась")
            data = {"result": False, "description": "wrong auth"}
        # Если пользователя с таким ip не существует, то необходима регистрация
        else:
            logger.info(
                f"Клиент {client_ip} -> необходима предварительная регистрация в системе"
            )
            data = {"result": False, "description": "registration required"}
            if client_ip not in self.reg_list:
                self.reg_list.append(client_ip)
                logger.info(f"Добавили клиента {client_ip} в список регистрации")

        self.send_message(conn, data, client_ip)
        logger.info(f"Клиент {client_ip}. Отправили данные о результате авторизации")

        # Если была успешная авторизация - принимаем последующие сообщения от пользователя
        if auth_result == 1:
            self.message_logic(conn, client_ip)

    def router(self, conn, addr):
        """
        Роутинг в зависимости от авторизации клиента
        """
        logger.info("Router работает в отдельном потоке!")
        client_ip = addr[0]

        # Если клиенту нужна авторизация
        if client_ip in self.reg_list:
            self.reg_logic(conn, addr)

        # Если ip не авторизован - надо авторизовать
        elif client_ip not in self.authenticated_list:
            self.auth_logic(conn, addr)

        # Если уже был авторизован
        else:
            self.message_logic(conn, client_ip)

        logger.info(f"Отключение клиента {client_ip}")
        self.connections_list.remove((conn, addr))
        # Если клиент был в списке авторизации - удаляем его
        if client_ip in self.authenticated_list:
            self.authenticated_list.remove(client_ip)
            print("Список соединений:")
            print(self.connections_list)
            logger.info(f"Удалили клиента {client_ip} из списка авторизации")

    def __del__(self):
        logger.info(f"Остановка сервера")
示例#3
0
class Server:
    def __init__(self, port_number: int) -> None:

        logger.info(f"Запуск сервера..")
        self.port_number = port_number
        self.sock = None
        self.database = DataProcessing()
        self.socket_init()

        self.authenticated_list = []
        self.reg_list = []
        self.connections_list = []

        self.ip2username_dict = {}
        logger.info(f"Сервер инициализировался, слушает порт {port_number}")

        self.connection_thread = None
        self.play_command()

        self.input_processing()

    def connection_processing(self):
        while self.receive_data:
            conn, addr = self.sock.accept()

            self.connections_list.append((conn, addr))
            logger.info(f"Новое соединение от {addr[0]}")
            t = threading.Thread(target=self.router, args=(conn, addr))
            t.daemon = True
            t.start()

    def input_processing(self):
        commands_dict = {
            "exit": {
                "command": self.exit_command,
                "description": "Выход из программы"
            },
            "pause": {
                "command": self.stop_command,
                "description": "Приостановить получение новых соединений",
            },
            "stop": {
                "command": self.stop_command,
                "description": "Приостановить получение новых соединений",
            },
            "play": {
                "command": self.play_command,
                "description": "Продолжить получение новых соединений",
            },
            "start": {
                "command": self.play_command,
                "description": "Продолжить получение новых соединений",
            },
            "start logs": {
                "command": self.start_logs_command,
                "description": "Выводить логи в консоли",
            },
            "stop logs": {
                "command": self.stop_logs_command,
                "description": "Не выводить логи в консоли",
            },
            "clear auth": {
                "command": self.clear_auth_command,
                "description": "Отчистка файла для авторизации пользователей",
            },
            "clear logs": {
                "command": self.clear_logs_command,
                "description": "Отчистка файла логирования",
            },
        }

        while True:
            command_str = input()
            if command_str in commands_dict:
                commands_dict[command_str]["command"]()
            else:
                commands_str = "\n".join([
                    f"{k} - {v['description']}"
                    for k, v in commands_dict.items()
                ])
                print(
                    f"Команда не найдена\nДоступные команды:\n{commands_str}")

    def exit_command(self):
        logger.info("Завершаем работу сервера")
        sys.exit()

    def stop_command(self):
        if self.connection_thread is None:
            raise ValueError(
                "Нельзя остановить поток подключений, если он не был запущен!")
        self.receive_data = False
        logger.info("Приостановили поток получения данных клиентов")

    def clear_auth_command(self):
        self.database.clear()
        logger.info("Отчистили файл аворизации пользователей")

    def start_logs_command(self):
        if stream_handler not in logger.handlers:
            logger.addHandler(stream_handler)
            logger.info("Возобновили показ логов в консоли")

    def stop_logs_command(self):
        if stream_handler in logger.handlers:
            logger.removeHandler(stream_handler)
            logger.info("Приостановили показ логов в консоли")

    def clear_logs_command(self):
        open(LOGGER_FILE, "w").close()
        logger.info("Отчистили файл логов")

    def play_command(self):
        self.receive_data = True
        t = threading.Thread(target=self.connection_processing)
        t.daemon = True
        t.start()
        self.connection_thread = t

    def send_message(self, conn, data: Union[str, Dict[str, Any]],
                     ip: str) -> None:
        data_text = data
        if type(data) == dict:
            data = json.dumps(data, ensure_ascii=False)

        data = data.encode()
        conn.send(data)
        logger.info(f"Сообщение {data_text} было отправлено клиенту {ip}")

    def socket_init(self):
        sock = socket.socket()
        sock.bind(("", self.port_number))
        sock.listen(0)
        self.sock = sock

    def message_logic(self, conn, client_ip):
        data = ""
        while True:
            chunk = conn.recv(1024)
            data += chunk.decode()

            if END_MESSAGE_FLAG in data:

                username = self.ip2username_dict[client_ip]
                logger.info(
                    f"Получили сообщение {data} от клиента {client_ip} ({username})"
                )
                data = {"username": username, "text": data}

                logger.info(
                    f"Текущее кол-во подключений к серверу: {len(self.connections_list)}"
                )
                for connection in self.connections_list:
                    current_conn, current_ip = connection
                    try:
                        self.send_message(current_conn, data, current_ip)
                    except BrokenPipeError:
                        continue

                data = ""

            else:
                logger.info(
                    f"Приняли часть данных от клиента {client_ip}: '{data}'")

            if not chunk:
                break

    def reg_logic(self, conn, addr):
        newuser_ip = addr[0]
        try:
            data = json.loads(conn.recv(1024).decode())
        except JSONDecodeError:
            if newuser_ip in self.reg_list:
                self.reg_list.remove(newuser_ip)
            return
        newuser_password, newuser_username = hash(
            data["password"]), data["username"]

        self.database.user_reg(newuser_ip, newuser_password, newuser_username)
        logger.info(f"Клиент {newuser_ip} -> регистрация прошла успешно")
        data = {"result": True}
        if newuser_ip in self.reg_list:
            self.reg_list.remove(newuser_ip)
            logger.info(f"Удалили клиента {newuser_ip} из списка регистрации")

        self.send_message(conn, data, newuser_ip)
        logger.info(
            f"Клиент {newuser_ip}. Отправили данные о результате регистрации")

    def auth_logic(self, conn, addr):
        try:
            user_password = hash(
                json.loads(conn.recv(1024).decode())["password"])
        except JSONDecodeError:
            return
        client_ip = addr[0]

        auth_result, username = self.database.user_auth(
            client_ip, user_password)

        if auth_result == 1:
            logger.info(f"Клиент {client_ip} -> авторизация прошла успешно")
            data = {"result": True, "body": {"username": username}}
            if client_ip not in self.authenticated_list:
                self.authenticated_list.append(client_ip)
                self.ip2username_dict[client_ip] = username
                logger.info(
                    f"Добавили клиента {client_ip} в список авторизации")
        elif auth_result == 0:
            logger.info(f"Клиент {client_ip} -> авторизация не удалась")
            data = {"result": False, "description": "wrong auth"}
        else:
            logger.info(
                f"Клиент {client_ip} -> необходима предварительная регистрация в системе"
            )
            data = {"result": False, "description": "registration required"}
            if client_ip not in self.reg_list:
                self.reg_list.append(client_ip)
                logger.info(
                    f"Добавили клиента {client_ip} в список регистрации")

        self.send_message(conn, data, client_ip)
        logger.info(
            f"Клиент {client_ip}. Отправили данные о результате авторизации")

        if auth_result == 1:
            self.message_logic(conn, client_ip)

    def router(self, conn, addr):
        logger.info("Router работает в отдельном потоке!")
        client_ip = addr[0]

        if client_ip in self.reg_list:
            self.reg_logic(conn, addr)

        elif client_ip not in self.authenticated_list:
            self.auth_logic(conn, addr)

        else:
            self.message_logic(conn, client_ip)

        logger.info(f"Отключение клиента {client_ip}")
        self.connections_list.remove((conn, addr))
        if client_ip in self.authenticated_list:
            self.authenticated_list.remove(client_ip)
            print("Список соединений:")
            print(self.connections_list)
            logger.info(f"Удалили клиента {client_ip} из списка авторизации")

    def __del__(self):
        logger.info(f"Остановка сервера")