Пример #1
0
 def service_update_lists(self):
     """Метод реализующий отправки сервисного сообщения 205 клиентам."""
     for client in self.names:
         try:
             sending_message(self.names[client], {RESPONSE: 205})
         except OSError:
             self.remove_client(self.names[client])
Пример #2
0
 def test_sending_message(self):
     """
     Тестируем корректность работы фукции отправки,
     создадим тестовый сокет и проверим корректность отправки словаря
     """
     # экземпляр тестового словаря, хранит собственно тестовый словарь
     test_sock_obj = TestSocket(self.test_dictionary_send)
     # вызов тестируемой функции, результаты будут сохранены в тестовом сокете
     sending_message(test_sock_obj, self.test_dictionary_send)
     # проверка корретности кодирования словаря.
     # сравниваем результат довренного кодирования и результат от тестируемой функции
     self.assertEqual(test_sock_obj.encoded_message,
                      test_sock_obj.received_message)
Пример #3
0
 def process_message(self, message):
     """
     Метод отправки сообщения клиенту.
     """
     if message[TO] in self.names and self.names[
             message[TO]] in self.listen_sockets:
         try:
             sending_message(self.names[message[TO]], message)
             SERVER_LOGGER.info(
                 f'Отправлено сообщение пользователю {message[TO]} от пользователя {message[FROM]}.'
             )
         except OSError:
             self.remove_client(message[TO])
     elif message[TO] in self.names and self.names[
             message[TO]] not in self.listen_sockets:
         SERVER_LOGGER.error(
             f'Связь с клиентом {message[TO]} была потеряна. Соединение закрыто, доставка невозможна.'
         )
         self.remove_client(self.names[message[TO]])
     else:
         SERVER_LOGGER.error(
             f'Пользователь {message[TO]} не зарегистрирован на сервере, отправка сообщения невозможна.'
         )
Пример #4
0
 def autorize_user(self, message, sock):
     """Метод реализующий авторизцию пользователей."""
     # Если имя пользователя уже занято то возвращаем 400
     SERVER_LOGGER.debug(f'Start auth process for {message[USER]}')
     if message[USER][ACCOUNT_NAME] in self.names.keys():
         try:
             SERVER_LOGGER.debug('Username busy, sending 400')
             sending_message(sock, {RESPONSE: 400, ERROR: 'Bad request'})
         except OSError:
             SERVER_LOGGER.debug('OS Error')
             pass
         self.clients.remove(sock)
         sock.close()
     # Проверяем что пользователь зарегистрирован на сервере.
     elif not self.database.check_user(message[USER][ACCOUNT_NAME]):
         try:
             SERVER_LOGGER.debug('Unknown username, sending 400')
             sending_message(sock, {
                 RESPONSE: 400,
                 ERROR: 'Пользователь не зарегистрирован.'
             })
         except OSError:
             pass
         self.clients.remove(sock)
         sock.close()
     else:
         SERVER_LOGGER.debug('Correct username, starting passwd check.')
         # Иначе отвечаем 511 и проводим процедуру авторизации
         # Словарь - заготовка
         message_auth = {RESPONSE: 511, DATA: None}
         # Набор байтов в hex представлении
         random_str = binascii.hexlify(os.urandom(64))
         # В словарь байты нельзя, декодируем (json.dumps -> TypeError)
         message_auth[DATA] = random_str.decode('ascii')
         # Создаём хэш пароля и связки с рандомной строкой, сохраняем
         # серверную версию ключа
         hash = hmac.new(
             self.database.get_hash(message[USER][ACCOUNT_NAME]),
             random_str, 'MD5')
         digest = hash.digest()
         SERVER_LOGGER.debug(f'Auth message = {message_auth}')
         try:
             # Обмен с клиентом
             sending_message(sock, message_auth)
             ans = getting_message(sock)
         except OSError as err:
             SERVER_LOGGER.debug('Error in auth, data:', exc_info=err)
             sock.close()
             return
         client_digest = binascii.a2b_base64(ans[DATA])
         # Если ответ клиента корректный, то сохраняем его в список
         # пользователей.
         if RESPONSE in ans and ans[RESPONSE] == 511 \
                 and hmac.compare_digest(digest, client_digest):
             self.names[message[USER][ACCOUNT_NAME]] = sock
             client_ip, client_port = sock.getpeername()
             try:
                 sending_message(sock, {RESPONSE: 200})
             except OSError:
                 self.remove_client(message[USER][ACCOUNT_NAME])
             # добавляем пользователя в список активных и если у него изменился открытый ключ
             # сохраняем новый
             self.database.user_login(message[USER][ACCOUNT_NAME],
                                      client_ip, client_port,
                                      message[USER][PUBLIC_KEY])
         else:
             try:
                 sending_message(sock, {
                     RESPONSE: 400,
                     ERROR: 'Пользователь не зарегистрирован.'
                 })
             except OSError:
                 pass
             self.clients.remove(sock)
             sock.close()
Пример #5
0
    def process_client_message(self, message, client):
        """Метод отбработчик поступающих сообщений."""
        SERVER_LOGGER.debug(f'Разбор сообщения от клиента : {message}')
        # Если это сообщение о присутствии, принимаем и отвечаем
        if ACTION in message and message[ACTION] == PRESENCE \
                and TIME in message \
                and USER in message:
            # Если сообщение о присутствии то вызываем функцию авторизации.
            self.autorize_user(message, client)

        # Если это сообщение, то отправляем его получателю.
        elif ACTION in message and message[ACTION] == MESSAGE \
                and TO in message \
                and TIME in message \
                and FROM in message \
                and MESSAGE in message \
                and self.names[message[FROM]] == client:
            if message[TO] in self.names:
                self.database.process_message(message[FROM], message[TO])
                self.process_message(message)
                try:
                    sending_message(client, {RESPONSE: 200})
                except OSError:
                    self.remove_client(client)
            else:
                try:
                    sending_message(client, {
                        RESPONSE: 400,
                        ERROR: 'Bad request'
                    })
                except OSError:
                    pass
            return

        # если клиент выходит
        elif ACTION in message and message[ACTION] == QUIT \
                and ACCOUNT_NAME in message \
                and self.names[message[ACCOUNT_NAME]] == client:
            self.remove_client(client)

        # если это запрос списка контактов
        elif ACTION in message and message[ACTION] == GET_CONTACTS \
                and USER in message and \
                self.names[message[USER]] == client:
            try:
                sending_message(
                    client, {
                        RESPONSE: 202,
                        LIST_INFO: self.database.get_contacts(message[USER])
                    })
            except OSError:
                self.remove_client(client)

        # если это добавление контакта
        elif ACTION in message and message[ACTION] == ADD_CONTACT \
                and ACCOUNT_NAME in message \
                and USER in message \
                and self.names[message[USER]] == client:
            self.database.add_contact(message[USER], message[ACCOUNT_NAME])
            try:
                sending_message(client, {RESPONSE: 200})
            except OSError:
                self.remove_client(client)

        # если это удаление контакта
        elif ACTION in message and message[ACTION] == REMOVE_CONTACT \
                and ACCOUNT_NAME in message \
                and USER in message \
                and self.names[message[USER]] == client:
            self.database.remove_contact(message[USER], message[ACCOUNT_NAME])
            try:
                sending_message(client, {RESPONSE: 200})
            except OSError:
                self.remove_client(client)

        # если это запрос известных пользователей
        elif ACTION in message and message[ACTION] == USERS_REQUEST and ACCOUNT_NAME in message \
                and self.names[message[ACCOUNT_NAME]] == client:
            try:
                sending_message(
                    client, {
                        RESPONSE: 202,
                        LIST_INFO:
                        [user[0] for user in self.database.users_list()]
                    })
            except OSError:
                self.remove_client(client)

        # Если это запрос публичного ключа пользователя
        elif ACTION in message and message[ACTION] == PUBLIC_KEY_REQUEST \
                and ACCOUNT_NAME in message:
            response = {
                RESPONSE: 511,
                DATA: self.database.get_pubkey(message[ACCOUNT_NAME])
            }
            # может быть, что ключа ещё нет (пользователь никогда не логинился,
            # тогда шлём 400)
            if response[DATA]:
                try:
                    sending_message(client, response)
                except OSError:
                    self.remove_client(client)
            else:
                try:
                    sending_message(
                        client, {
                            RESPONSE: 400,
                            ERROR:
                            'Нет публичного ключа для данного пользователя!'
                        })
                except OSError:
                    self.remove_client(client)

        # Иначе Bad request
        else:
            try:
                sending_message(client, {RESPONSE: 400, ERROR: 'Bad request'})
            except OSError:
                self.remove_client(client)