Esempio n. 1
0
    def connection_init(self, port, ip):
        self.transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.transport.settimeout(5)

        connected = False
        for i in range(5):
            logger.info(f'attempt to connect №{i + 1}')
            try:
                self.transport.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)

        if not connected:
            logger.critical('Connection with server lost.')
            raise ServerError('Connection with server lost!')

        logger.debug('connection established')

        try:
            with socket_lock:
                send_message(self.transport, self.create_presence())
                self.process_server_ans(get_message(self.transport))
        except (OSError, json.JSONDecodeError):
            logger.critical('Connection with server lost.')
            raise ServerError('Connection with server lost!')

        logger.info('connection established.')
Esempio n. 2
0
    def __init__(self, port, ip_address, database, username, passwd, keys):
        threading.Thread.__init__(self)
        QObject.__init__(self)

        self.database = database
        # Имя пользователя
        self.username = username
        # Сокет для работы с сервером
        self.transport = None
        # Пароль
        self.password = passwd
        # Набор ключей для шифрования
        self.keys = keys
        # Устанавливаем соединение:
        self.connection_init(port, ip_address)
        # Обновление таблиц известных пользователей и контактов
        try:
            self.user_list_request()
            self.contacts_list_request()
        except OSError as e:
            if e.errno:
                LOGGER.critical(f'Соединение с сервером потеряно')
                raise ServerError(f'Соедниение с сервером потеряно')
            LOGGER.error('Таймаут соединения при обновлении списков пользователей')
        except json.JSONDecodeError:
            LOGGER.critical(f'Соединение с сервером потеряно')
            raise ServerError(f'Соединение с сервером потеряно')
        self.running = True
Esempio n. 3
0
    def __init__(self, port, ip_address, database, username, passwd, keys):
        # Вызываем конструктор предка
        #threading.Thread.__init__(self)
        QObject.__init__(self)

        # Класс База данных - работа с базой
        self.database = database
        # Имя пользователя
        self.username = username
        # Пароль
        self.password = passwd
        # Сокет для работы с сервером
        self.transfer_socket = None
        # Набор ключей для шифрования
        self.keys = keys
        # Устанавливаем соединение:
        self.connection_init(port, ip_address)
        # Обновляем таблицы известных пользователей и контактов
        try:
            self.user_list_update()
            self.contacts_list_update()
        except OSError as err:
            if err.errno:
                client_logger.critical(f'Потеряно соединение с сервером.')
                raise ServerError('Потеряно соединение с сервером!')
            client_logger.error(
                'Timeout соединения при обновлении списков пользователей.')
        except json.JSONDecodeError:
            client_logger.critical(f'Потеряно соединение с сервером.')
            raise ServerError('Потеряно соединение с сервером!')
            # Флаг продолжения работы транспорта.
        self.running = True
Esempio n. 4
0
    def connection_init(self, port, ip):
        """Метод отвечающий за устанновку соединения с сервером."""

        self.transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.transport.settimeout(5)

        connected = False
        for i in range(5):
            logger.info(f'Попытка подключения №{i + 1}')
            try:
                self.transport.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)

        if not connected:
            logger.critical('Не удалось установить соединение с сервером')
            raise ServerError('Не удалось установить соединение с сервером')

        logger.debug('Установлено соединение с сервером')

        passwd_bytes = self.password.encode('utf-8')
        salt = self.username.lower().encode('utf-8')
        passwd_hash = hashlib.pbkdf2_hmac('sha512', passwd_bytes, salt, 10000)
        passwd_hash_string = binascii.hexlify(passwd_hash)
        pubkey = self.keys.publickey().export_key().decode('ascii')

        with socket_lock:
            presense = {
                ACTION: PRESENCE,
                TIME: time.time(),
                USER: {
                    ACCOUNT_NAME: self.username,
                    PUBLIC_KEY: pubkey
                }
            }
            try:
                send_message(self.transport, presense)
                ans = get_message(self.transport)
                if RESPONSE in ans:
                    if ans[RESPONSE] == 400:
                        raise ServerError(ans[ERROR])
                    elif ans[RESPONSE] == 511:
                        ans_data = ans[DATA]
                        hash = hmac.new(passwd_hash_string,
                                        ans_data.encode('utf-8'))
                        digest = hash.digest()
                        my_ans = RESPONSE_511
                        my_ans[DATA] = binascii.b2a_base64(digest).decode(
                            'ascii')
                        send_message(self.transport, my_ans)
                        self.process_server_ans(get_message(self.transport))
            except (OSError, json.JSONDecodeError):
                raise ServerError('Сбой соединения в процессе авторизации.')
Esempio n. 5
0
    def process_server_ans(self, message):
        """Метод обработчик поступающих сообщений с сервера."""
        logger.debug(f'Разбор сообщения от сервера: {message}')

        if RESPONSE in message:
            if message[RESPONSE] == 200:
                return
            elif message[RESPONSE] == 400:
                raise ServerError(f'{message[ERROR]}')
            elif message[RESPONSE] == 205:
                self.user_list_update()
                self.contacts_list_update()
                self.message_205.emit()
            else:
                logger.error(
                    f'Принят неизвестный код подтверждения {message[RESPONSE]}'
                )

        elif ACTION in message and message[ACTION] == MESSAGE and \
                SENDER in message and DESTINATION in message \
                and MESSAGE_TEXT in message and message[DESTINATION] == self.username:
            logger.debug(
                f'Получено сообщение от пользователя {message[SENDER]}:{message[MESSAGE_TEXT]}'
            )
            self.new_message.emit(message)
Esempio n. 6
0
    def proc_answer(self, message):
        client_logger.debug(f'Разбор сообщения от сервера: {message}')

        # Если это подтверждение чего-либо
        if RESPONSE in message:
            if message[RESPONSE] == 200:
                return
            elif message[RESPONSE] == 400:
                raise ServerError(f'{message[ERROR]}')
            elif message[RESPONSE] == 205:
                self.user_list_update()
                self.contacts_list_update()
                self.message_205.emit()
            else:
                client_logger.debug(
                    f'Принят неизвестный код подтверждения {message[RESPONSE]}'
                )

        # Если это сообщение от пользователя добавляем в базу, даём сигнал о
        # новом сообщении
        elif ACTION in message and message[ACTION] == MESSAGE and SENDER in message and DESTINATION in message \
                and MESSAGE_TEXT in message and message[DESTINATION] == self.username:
            client_logger.debug(
                f'Получено сообщение от пользователя {message[SENDER]}:{message[MESSAGE_TEXT]}'
            )
            #self.database.save_message(message[SENDER], 'in', message[MESSAGE_TEXT])
            self.new_message.emit(message)
Esempio n. 7
0
    def process_server_ans(self, message):
        """Метод обработчик поступающих сообщений с сервера."""
        client_logger.debug(f'Разбор сообщения от сервера: {message}')

        # Если это подтверждение чего-либо
        if CONFIGS.get('RESPONSE') in message:
            if message[CONFIGS.get('RESPONSE')] == 200:
                return
            elif message[CONFIGS.get('RESPONSE')] == 400:
                raise ServerError(f'{message[CONFIGS.get("ERROR")]}')
            elif message[CONFIGS.get('RESPONSE')] == 205:
                self.user_list_update()
                self.contacts_list_update()
                self.message_205.emit()
            else:
                client_logger.debug(f'Принят неизвестный код подтверждения '
                                    f'{CONFIGS.get("RESPONSE")}')

        # Если это сообщение от пользователя добавляем в базу, даём сигнал о
        # новом сообщении
        elif CONFIGS.get('ACTION') in message and \
                message[CONFIGS.get('ACTION')] == CONFIGS.get('MESSAGE') and \
                CONFIGS.get('FROM_USER') in message and CONFIGS.get('TO_USER')\
                in message and CONFIGS.get('MESSAGE_TEXT') in message and \
                message[CONFIGS.get('TO_USER')] == self.username:
            client_logger.debug(f'Получено сообщение от пользователя '
                                f'{message[CONFIGS.get("FROM_USER")]}:'
                                f'{message[CONFIGS.get("MESSAGE_TEXT")]}')
            self.new_message.emit(message)
Esempio n. 8
0
    def make_response(self, response, response_status=ResponseStatus.success):
        """解析响应结果,返回指定类型

        :param response: 返回结果对象
        """
        if response is None:
            result = {self.config['plain_result_key']: ""}
        elif isinstance(response, (dict, list, tuple, set)):
            result = response
        elif isinstance(response, self.BUILTIN_TYPES):
            result = {self.config['plain_result_key']: response}
        else:
            raise ServerError("Could not serialize '{}' to JSON".format(
                type(response).__name__))
        status_code = int(response_status)
        self.set_status(status_code)

        # 写json格式的日志供logstash解析
        eslogger.write(
            status=status_code,
            request_uri=self.request.uri,
            remote_ip=self.request.remote_ip,
            request_args=str(self.request.arguments),
            user=(self.current_user['account'] if self.current_user else ''))

        if status_code in (204, 304):
            return self.finish()
        self._write_dict(result)
Esempio n. 9
0
    def connection_init(self, port, ip):
        """Based socket constructor. """
        self.transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.transport.settimeout(5)
        connected = False
        for i in range(5):
            logger.info(f'Connection attempt №{i + 1}')
            try:
                self.transport.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)
        if not connected:
            logger.critical('Failed connect to server')
            raise ServerError('Failed connect to server')
        logger.debug('Connection successfully')

        passwd_bytes = self.password.encode('utf-8')
        salt = self.username.lower().encode('utf-8')
        passwd_hash = hashlib.pbkdf2_hmac('sha512', passwd_bytes, salt, 10000)
        passwd_hash_string = binascii.hexlify(passwd_hash)
        pubkey = self.keys.publickey().export_key().decode('ascii')

        with socket_lock:
            try:
                send_message(self.transport, self.create_presence(pubkey))
                ans = (get_message(self.transport))
                if ans[RESPONSE] == 400:
                    raise ServerError(ans[ERROR])
                elif ans[RESPONSE] == 511:
                    ans_data = ans[DATA]
                    hash = hmac.new(passwd_hash_string,
                                    ans_data.encode('utf-8'))
                    digest = hash.digest()
                    my_ans = RESPONSE_511
                    my_ans[DATA] = binascii.b2a_base64(digest).decode('ascii')
                    send_message(self.transport, my_ans)
                    self.process_server_ans(get_message(self.transport))
            except (OSError, json.JSONDecodeError):
                logger.critical('Connection has been lost')
                raise ServerError('Connection has been lost')
        logger.info('Connection to server successfully')
Esempio n. 10
0
 def _get_info(self, request):
     LOGGER.debug(f'Formed request {request}')
     with LOCK_SOCKET:
         send_msg(self.connection, request)
         answer = get_msg(self.connection)
     if RESPONSE in answer and answer[RESPONSE] == 202:
         return answer[LIST_INFO]
     else:
         raise ServerError('Invalid server response.')
Esempio n. 11
0
 def __init__(self, port, ip_address, database, username):
     threading.Thread.__init__(self)
     QObject.__init__(self)
     self.database = database
     self.username = username
     self.transport = None
     self.connection_init(port, ip_address)
     try:
         self.user_list_update()
         self.contacts_list_update()
     except OSError as err:
         if err.errno:
             logger.critical(f'Connection with server lost.')
             raise ServerError('Connection with server lost!')
         logger.error('Connection timeout during update users list.')
     except json.JSONDecodeError:
         logger.critical(f'Connection with server lost.')
         raise ServerError('Connection with server lost!')
     self.running = True
Esempio n. 12
0
 def answer_server_presence(self, msg):
     LOGGER.debug(f'Parsing a message from the server - {msg}')
     if RESPONSE in msg:
         if msg[RESPONSE] == 511:
             return 'OK: 511'
         elif msg[RESPONSE] == 200:
             return 'OK: 200'
         elif msg[RESPONSE] == 400:
             LOGGER.info(f'ERROR 400: {msg[ERROR]}')
             raise ServerError(f'{msg[ERROR]}')
         else:
             raise IncorrectCodeError(msg[RESPONSE])
     raise FieldMissingError(RESPONSE)
Esempio n. 13
0
    def connection_init(self, port, ip):
        # Инициализация сокета и сообщение серверу о нашем появлении
        self.transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # Таймаут необходим для освобождения сокета.
        self.transport.settimeout(5)

        # Соединяемся, 5 попыток соединения, флаг успеха ставим в True если удалось
        connected = False
        for i in range(5):
            logger.info(f'Попытка подключения №{i + 1}')
            try:
                self.transport.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)

        # Если соединится не удалось - исключение
        if not connected:
            logger.critical('Не удалось установить соединение с сервером')
            raise ServerError('Не удалось установить соединение с сервером')

        logger.debug('Установлено соединение с сервером')

        # Посылаем серверу приветственное сообщение и получаем ответ что всё нормально или ловим исключение.
        try:
            with socket_lock:
                send_message(self.transport, self.create_presence())
                self.process_server_ans(get_message(self.transport))
        except (OSError, json.JSONDecodeError):
            logger.critical('Потеряно соединение с сервером!')
            raise ServerError('Потеряно соединение с сервером!')

        # Раз всё хорошо, сообщение о установке соединения.
        logger.info('Соединение с сервером успешно установлено.')
Esempio n. 14
0
 def del_contact_server(self, del_contact_name):
     message = {
         ACTION: DELETE_CONTACT,
         TIME: time.time(),
         USER: self.client_login,
         ACCOUNT_NAME: del_contact_name
     }
     with LOCK_SOCKET:
         send_msg(self.connection, message)
         answer = get_msg(self.connection)
     if RESPONSE in answer and answer[RESPONSE] == 200:
         logging.debug(f'Successfully delete a contact {del_contact_name} at the user {self.client_login}')
     else:
         raise ServerError('Client uninstall error.')
Esempio n. 15
0
    def __init__(self, port, ip_address, database, username, passwd, keys):
        threading.Thread.__init__(self)
        QObject.__init__(self)

        self.database = database
        self.username = username
        self.password = passwd
        self.transport = None
        self.keys = keys
        self.connection_init(port, ip_address)
        try:
            self.user_list_update()
            self.contacts_list_update()
        except OSError as err:
            if err.errno:
                logger.critical(f'Потеряно соединение с сервером.')
                raise ServerError('Потеряно соединение с сервером!')
            logger.error(
                'Timeout соединения при обновлении списков пользователей.')
        except json.JSONDecodeError:
            logger.critical(f'Потеряно соединение с сервером.')
            raise ServerError('Потеряно соединение с сервером!')
        self.running = True
Esempio n. 16
0
 def add_contact_server(self, new_contact_name):
     LOGGER.debug(f'Create a new contact {new_contact_name} at the user {self.client_login}.')
     message = {
         ACTION: ADD_CONTACT,
         TIME: time.time(),
         USER: self.client_login,
         ACCOUNT_NAME: new_contact_name
     }
     with LOCK_SOCKET:
         send_msg(self.connection, message)
         answer = get_msg(self.connection)
     if RESPONSE in answer and answer[RESPONSE] == 200:
         logging.debug(f'Successful contact creation {new_contact_name} at the user {self.client_login}.')
     else:
         raise ServerError('Error creating contact.')
Esempio n. 17
0
 def __init__(self, port, ip_address, database, username, passwd, keys):
     threading.Thread.__init__(self)
     QObject.__init__(self)
     self.database = database
     self.username = username
     self.password = passwd
     self.keys = keys
     self.transport = None
     self.connection_init(port, ip_address)
     try:
         self.user_list_update()
         self.contacts_list_update()
     except OSError as err:
         if err.errno:
             print(err)
             logger.critical(f'Connection has been lost.')
             raise ServerError('Connection has been lost')
         logger.error('Timeout connection while refreshing contact list.')
     except json.JSONDecodeError:
         logger.critical(f'Connection has been lost')
         raise ServerError('Connection has been lost')
     except Exception as b:
         print(b)
     self.running = True
Esempio n. 18
0
 def process_server_ans(self, message):
     """Parsing answer from server. """
     logger.debug(f'Checking server message: {message}')
     if RESPONSE in message:
         if message[RESPONSE] == 200:
             return
         elif message[RESPONSE] == 400:
             raise ServerError(f'{message[ERROR]}')
         else:
             logger.debug(f'Received unknown code {message[RESPONSE]}')
     elif ACTION in message and message[ACTION] == MESSAGE and SENDER in message and DESTINATION in message \
             and MESSAGE_TEXT in message and message[DESTINATION] == self.username:
         logger.debug(
             f'Message from {message[SENDER]}:{message[MESSAGE_TEXT]}')
         self.database.save_message(message[SENDER], 'in',
                                    message[MESSAGE_TEXT])
         self.new_message.emit(message[SENDER])
Esempio n. 19
0
    def send_avatar_to_server(self):
        with open(get_path_avatar(self.client_login), 'rb') as image_file:
            encoded_img = base64.b64encode(image_file.read()).decode('utf8')

        message = {
            ACTION: SEND_AVATAR,
            USER: {
                ACCOUNT_NAME: self.client_login,
                IMAGE: encoded_img
            }
        }
        with LOCK_SOCKET:
            send_msg(self.connection, message)
            answer = get_msg(self.connection)
        if RESPONSE in answer and answer[RESPONSE] == 200:
            logging.debug(f'Successfully saved avatar.')
        else:
            raise ServerError('Server error. Unsuccessfully saved avatar.')
Esempio n. 20
0
    def process_ans(self, message):
        """Функция разбирает ответ сервера. Генерирует исключение при ошибке"""
        LOGGER.debug(f'Разбор сообщения от сервера: {message}')
        if RESPONSE in message:
            if message[RESPONSE] == 200:
                return
            elif message[RESPONSE] == 400:
                raise ServerError(f'400 : {message[ERROR]}')
            elif message[RESPONSE] == 205:
                self.user_list_request()
                self.contacts_list_request()
                self.message_205.emit()
            else:
                LOGGER.debug('Неизвестный код подтверждения')

        # Если сообщение от пользователя, добавляем в базу
        elif ACTION in message and message[ACTION] == MESSAGE and SENDER in message and DESTINATION in message \
                and MESSAGE_TEXT in message and message[DESTINATION] == self.username:
            print(f'Получено сообщение от пользователя {message[SENDER]}: {message[MESSAGE_TEXT]}')
            LOGGER.debug(f'Получено сообщение от пользователя {message[SENDER]}: {message[MESSAGE_TEXT]}')

            self.new_message.emit(message)
Esempio n. 21
0
    def connection_init(self, port, ip):
        """Метод отвечающий за устанновку соединения с сервером."""
        # Инициализация сокета и сообщение серверу о нашем появлении
        self.transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        # Таймаут необходим для освобождения сокета.
        self.transport.settimeout(5)

        # Соединяемся, 5 попыток соединения, флаг успеха ставим в True если
        # удалось
        connected = False
        for i in range(5):
            client_logger.info(f'Попытка подключения №{i + 1}')
            try:
                self.transport.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                client_logger.debug("Connection established.")
                break
            time.sleep(1)

        # Если соединится не удалось - исключение
        if not connected:
            client_logger.critical(
                'Не удалось установить соединение с сервером')
            raise ServerError('Не удалось установить соединение с сервером')

        client_logger.debug('Starting auth dialog.')

        # Запускаем процедуру авторизации
        # Получаем хэш пароля
        passwd_bytes = self.password.encode('utf-8')
        salt = self.username.lower().encode('utf-8')
        passwd_hash = hashlib.pbkdf2_hmac('sha512', passwd_bytes, salt, 10000)
        passwd_hash_string = binascii.hexlify(passwd_hash)

        client_logger.debug(f'Passwd hash ready: {passwd_hash_string}')

        # Получаем публичный ключ и декодируем его из байтов
        pubkey = self.keys.publickey().export_key().decode('ascii')

        # Авторизируемся на сервере
        with socket_lock:
            presense = {
                CONFIGS.get('ACTION'): CONFIGS.get('PRESENCE'),
                CONFIGS.get('TIME'): time.time(),
                CONFIGS.get('USER'): {
                    CONFIGS.get('ACCOUNT_NAME'): self.username,
                    CONFIGS.get('PUBLIC_KEY'): pubkey
                }
            }
            client_logger.debug(f"Presence message = {presense}")
            # Отправляем серверу приветственное сообщение.
            try:
                send_message(self.transport, presense, CONFIGS)
                ans = get_message(self.transport, CONFIGS)
                client_logger.debug(f'Server response = {ans}.')
                # Если сервер вернул ошибку, бросаем исключение.
                if CONFIGS.get('RESPONSE') in ans:
                    if ans[CONFIGS.get('RESPONSE')] == 400:
                        raise ServerError(ans[CONFIGS.get('ERROR')])
                    elif ans[CONFIGS.get('RESPONSE')] == 511:
                        # Если всё нормально, то продолжаем процедуру
                        # авторизации.
                        ans_data = ans[CONFIGS.get('DATA')]
                        hash = hmac.new(passwd_hash_string,
                                        ans_data.encode('utf-8'), 'MD5')
                        digest = hash.digest()
                        my_ans = RESPONSE_511
                        my_ans[CONFIGS.get('DATA')] = binascii.b2a_base64(
                            digest).decode('ascii')
                        send_message(self.transport, my_ans, CONFIGS)
                        self.process_server_ans(
                            get_message(self.transport, CONFIGS))
            except (OSError, json.JSONDecodeError) as err:
                client_logger.debug(f'Connection error.', exc_info=err)
                raise ServerError('Сбой соединения в процессе авторизации.')
Esempio n. 22
0
    def connection_init(self, port, ip):
        # Инициализация сокета и сообщение серверу о нашем появлении
        self.transfer_socket = socket.socket(socket.AF_INET,
                                             socket.SOCK_STREAM)

        # Таймаут необходим для освобождения сокета.
        self.transfer_socket.settimeout(5)

        # Соединяемся, 5 попыток соединения, флаг успеха ставим в True если
        # удалось
        connected = False
        for i in range(5):
            client_logger.info(f'Попытка подключения №{i + 1}')
            try:
                self.transfer_socket.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)

        # Если соединится не удалось - исключение
        if not connected:
            client_logger.critical(
                'Не удалось установить соединение с сервером')
            raise ServerError('Не удалось установить соединение с сервером')

        client_logger.debug('Установлено соединение с сервером')

        # Запускаем процедуру авторизации
        # Получаем хэш пароля
        passwd_bytes = self.password.encode('utf-8')
        salt = self.username.lower().encode('utf-8')
        passwd_hash = hashlib.pbkdf2_hmac('sha512', passwd_bytes, salt, 10000)
        passwd_hash_string = binascii.hexlify(passwd_hash)

        # Получаем публичный ключ и декодируем его из байтов
        pubkey = self.keys.publickey().export_key().decode('ascii')

        # Авторизируемся на сервере
        with socket_lock:
            presense = {
                ACTION: PRESENCE,
                TIME: time.time(),
                USER: {
                    ACCOUNT_NAME: self.username,
                    PUBLIC_KEY: pubkey
                }
            }
            # Отправляем серверу приветственное сообщение.
            try:
                send_message(self.transfer_socket, presense)
                ans = get_message(self.transfer_socket)
                # Если сервер вернул ошибку, бросаем исключение.
                if RESPONSE in ans:
                    if ans[RESPONSE] == 400:
                        raise ServerError(ans[ERROR])
                    elif ans[RESPONSE] == 511:
                        # Если всё нормально, то продолжаем процедуру
                        # авторизации.
                        ans_data = ans[DATA]
                        hash = hmac.new(passwd_hash_string,
                                        ans_data.encode('utf-8'))
                        digest = hash.digest()
                        my_ans = RESPONSE_511
                        my_ans[DATA] = binascii.b2a_base64(digest).decode(
                            'ascii')
                        send_message(self.transfer_socket, my_ans)
                        self.proc_answer(get_message(self.transfer_socket))
            except (OSError, json.JSONDecodeError):
                raise ServerError('Сбой соединения в процессе авторизации.')
Esempio n. 23
0
    def connection_init(self, port, ip):
        """Функция инициализации соединения с сервером."""
        # Инициализация сокета и сообщение серверу о нашем появлении
        self.transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.transport.settimeout(5)

        # Попытка соединения
        connected = False
        for i in range(5):
            LOGGER.info(f'Попытка соединения с сервером №{i+1}')
            try:
                self.transport.connect((ip, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)

        # Если соединиться с сервером не удалось
        if not connected:
            LOGGER.critical('Не удалось установить соединение с сервером')
            raise ServerError('Не удалось установить соединение с сервером')

        LOGGER.debug('Запускаем авторизацию пользователя')
        # Запускаем процедуру авторизации
        # Получаем хэш пароля
        passwd_bytes = self.password.encode('utf-8')
        salt = self.username.lower().encode('utf-8')
        passwd_hash = hashlib.pbkdf2_hmac('sha512', passwd_bytes, salt, 10000)
        passwd_hash_string = binascii.hexlify(passwd_hash)

        # Получаем публичный ключ и декодируем его из байтов
        pubkey = self.keys.publickey().export_key().decode('ascii')

        # Авторизируемся на сервере
        with sock_lock:
            presense = {
                ACTION: PRESENCE,
                TIME: time.time(),
                USER: {
                    ACCOUNT_NAME: self.username,
                    PUBLIC_KEY: pubkey
                }
            }
            LOGGER.debug(f'Приветственное сообщение: {presense}')
            # Посылаем серверу приветственное сообщение и получаем ответ что всё нормально или получаем исключение.
            try:
                send_message(self.transport, presense)
                ans = get_message(self.transport)
                LOGGER.debug(f'Ответ сервера: {ans}')
                if RESPONSE in ans:
                    if ans[RESPONSE] == 400:
                        raise ServerError(ans[ERROR])
                    elif ans[RESPONSE] == 511:
                        # Если всё нормально, то продолжаем процедуру авторизации.
                        ans_data = ans[DATA]
                        hash = hmac.new(passwd_hash_string, ans_data.encode('utf-8'))
                        digest = hash.digest()
                        my_ans = RESPONSE_511
                        my_ans[DATA] = binascii.b2a_base64(
                            digest).decode('ascii')
                        send_message(self.transport, my_ans)
                        self.process_server_ans(get_message(self.transport))
            except (OSError, json.JSONDecodeError) as e:
                LOGGER.critical(f'Потеряно соединение с сервером.', exc_info=e)
                raise ServerError('Сбой соединения с сервером в процессе авторизации.')
            # Сообщение об удачной установке соединения.
            LOGGER.debug('Соединение с сервером установлено успешно')