Example #1
0
    def run(self):
        """
        Method for starting the process of receiving messages from the server.
        :return:
        """
        LOGGER.debug('Запущен процесс - приёмник сообщений с сервера.')
        while self.running:
            # If you do not delay, sending can wait a long time until the socket is released.
            time.sleep(1)
            message = None
            with SOCK_LOCK:
                try:
                    self.client_sock.settimeout(0.5)
                    message = get_message(self.client_sock)
                except OSError as err:
                    if err.errno:
                        LOGGER.critical('Потеряно соединение с сервером.')
                        self.running = False
                        self.connection_loss.emit()
                except (ConnectionError, ConnectionResetError,
                        ConnectionAbortedError, TypeError, JSONDecodeError):
                    LOGGER.critical('Потеряно соединение с сервером.')
                    self.running = False
                    self.connection_loss.emit()
                finally:
                    self.client_sock.settimeout(5)

            if message:
                LOGGER.debug(f'Принято сообщение с сервера: {message}')
                self.receive_message(message)
Example #2
0
 def remove_contact_to_server(self, contact):
     """
     The function sends contact deletion information to the server.
     :param {str} contact: username to remove from the contact list.
     :return:
     """
     LOGGER.debug(f'Удаление контакта {contact}.')
     del_contact_dict = DEL_CONTACT_DICT
     del_contact_dict[USER] = self.username
     del_contact_dict[ACCOUNT_NAME] = contact
     # Send a message to the server.
     with SOCK_LOCK:
         send_message(self.client_sock, del_contact_dict)
         # Get a response from the server.
         self.receive_message(get_message(self.client_sock))
Example #3
0
 def add_contact_to_server(self, contact):
     """
     The method sends information about adding a contact to the server.
     :param {str} contact: username to add to your contact list.
     :return:
     """
     LOGGER.debug(f'Создание контакта {contact}.')
     add_contact_dict = ADD_CONTACT_DICT
     add_contact_dict[USER] = self.username
     add_contact_dict[ACCOUNT_NAME] = contact
     # Send a message to the server.
     with SOCK_LOCK:
         send_message(self.client_sock, add_contact_dict)
         # Get a response from the server.
         self.receive_message(get_message(self.client_sock))
Example #4
0
 def get_key_from_server(self, username):
     """
     The method requests the public key from the server.
     :param {str} username: username.
     :return:
     """
     LOGGER.debug(f'Запрос публичного ключа для {username}.')
     dict_message = GET_PUBLIC_KEY
     dict_message[USER] = username
     with SOCK_LOCK:
         send_message(self.client_sock, dict_message)
         server_answer = get_message(self.client_sock)
     if RESPONSE in server_answer and server_answer[RESPONSE] == 511 \
             and DATA in server_answer:
         return server_answer[DATA]
     LOGGER.error(f'Не удалось получить ключ собеседника{username}.')
Example #5
0
 def create_message(self, recipient, message):
     """
     Method for sending a message to the server.
     :param {obj} recipient: socket object.
     :param {str} message: message to the recipient.
     :return:
     """
     dict_message = DICT_MESSAGE
     dict_message[SENDER] = self.username
     dict_message[RECIPIENT] = recipient
     dict_message[MESSAGE_TEXT] = message
     LOGGER.debug(f'Сформирован словарь-сообщение: {dict_message}.')
     # Send a message to the server.
     with SOCK_LOCK:
         send_message(self.client_sock, dict_message)
         self.receive_message(get_message(self.client_sock))
         LOGGER.info(f'Сообщение отправлено пользователю {recipient}.')
Example #6
0
 def get_registered_user_from_server(self):
     """
     The method requests from the server a list of registered users.
     :return {list}: list of registered users.
     """
     LOGGER.debug(f'Запрос зарегистрированных пользователей {self.username}.')
     get_registered_dict = GET_REGISTERED_DICT
     get_registered_dict[USER] = self.username
     # Send a message to the server.
     LOGGER.debug(f'Сформирован запрос {get_registered_dict}.')
     with SOCK_LOCK:
         send_message(self.client_sock, get_registered_dict)
         # Get a response from the server.
         server_answer = get_message(self.client_sock)
     LOGGER.debug(f'Получен ответ {server_answer}.')
     if RESPONSE in server_answer and server_answer[RESPONSE] == 202 \
             and DATA in server_answer:
         self.database.add_register_users(server_answer[DATA])
         return server_answer[DATA]
     else:
         LOGGER.error('Не удалось обновить список известных пользователей.')
Example #7
0
    def get_contact_list_from_server(self):
        """
        The method requests a list of user contacts from the server.
        :return {list}: user contact list.
        """
        self.database.clear_contacts()
        LOGGER.debug(f'Запрос списка контактов пользователя {self.username}.')
        get_contacts_dict = GET_CONTACTS_DICT
        get_contacts_dict[USER] = self.username
        LOGGER.debug(f'Сформирован запрос {get_contacts_dict}.')

        # Send a message to the server.
        with SOCK_LOCK:
            send_message(self.client_sock, get_contacts_dict)
            # Get a response from the server.
            server_answer = get_message(self.client_sock)
        LOGGER.debug(f'Получен ответ {server_answer}.')

        if RESPONSE in server_answer and server_answer[RESPONSE] == 202 \
                and DATA in server_answer:
            for contact in server_answer[DATA]:
                self.database.add_contact(contact)
        else:
            LOGGER.error('Не удалось обновить список контактов.')
Example #8
0
    def connection_init(self, ip_address, port):
        """
        The method initiates a connection to the server.
        :param {str} ip_address: server IP-address.
        :param {int} port: server port
        :return:
        """
        # Create a socket (AF_INET - network socket, SOCK_STREAM - work with TCP packets).
        self.client_sock = socket(AF_INET, SOCK_STREAM)
        # A timeout is required to free the socket.
        self.client_sock.settimeout(5)

        # Connect, 5 connection attempts, set success flag to True if possible.
        connected = False
        for attempt in range(5):
            LOGGER.info(f'Попытка подключения №{attempt + 1}.')
            try:
                self.client_sock.connect((ip_address, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            time.sleep(1)

        # If connection failed, return an exception.
        if not connected:
            LOGGER.critical('Не удалось установить соединение с сервером.')
            raise ServerError('Не удалось установить соединение с сервером.')

        LOGGER.info(f'Установлено соединение с сервером {ip_address}:{port}.')

        # Start Authorization Procedure.
        # Get password hash.
        password_bytes = self.password.encode(ENCODING)
        salt = self.username.lower().encode(ENCODING)
        password_hash = pbkdf2_hmac('sha512', password_bytes, salt, 10000)
        password_hash_string = hexlify(password_hash)

        # Get the public key and decode it from bytes.
        public_key = self.keys.publickey().export_key().decode('ascii')

        # Authorization on the server.
        with SOCK_LOCK:
            presence_dict = CONFIRM_PRESENCE
            presence_dict[USER] = self.username
            presence_dict[PUBLIC_KEY] = public_key
        # Send server confirmation of presence.
            try:
                send_message(self.client_sock, presence_dict)
                server_answer = get_message(self.client_sock)
                if RESPONSE in server_answer:

                    if server_answer[RESPONSE] == 400 and ERROR in server_answer:
                        LOGGER.error(f'Сервер не смог обработать клиентский'
                                     f' запрос. Получен ответ "Response 400:'
                                     f' {server_answer[ERROR]}".')
                        raise ServerError(server_answer[ERROR])

                    elif server_answer[RESPONSE] == 511 and DATA in server_answer:
                        answer_data = server_answer[DATA]
                        answer_hash = hmac.new(
                            password_hash_string,
                            answer_data.encode(ENCODING)
                        )
                        hash_digest = answer_hash.digest()
                        client_answer = RESPONSE_511
                        client_answer[DATA] = b2a_base64(hash_digest).decode('ascii')
                        send_message(self.client_sock, client_answer)
                        self.receive_message(get_message(self.client_sock))

            except (OSError, JSONDecodeError):
                LOGGER.critical('Потеряно соединение с сервером.')
                raise ServerError('Потеряно соединение с сервером.')