def __init__(self, code, params=None): message = '{}: {}'.format(code, get_msg(code)) self.code = code if params: self.err_msg = get_msg(code).format(**params) else: self.err_msg = None super().__init__(message)
def avatar_request(self, login): """The function of requesting the avatar of the client from the server.""" LOGGER.debug(f'Avatar request for {login}') request = { ACTION: GET_AVATAR, ACCOUNT_NAME: login } with LOCK_SOCKET: try: send_msg(self.connection, request) answer = get_msg(self.connection) except (OSError, json.JSONDecodeError): return None if RESPONSE in answer and answer[RESPONSE] == 511: LOGGER.debug(f'Loaded avatar for {login}') img = answer[DATA] img_data = base64.b64decode(img) filename = get_path_avatar(login) with open(filename, 'wb') as f: f.write(img_data) return True elif RESPONSE in answer and answer[RESPONSE] == 400: LOGGER.info(f'Answer server {answer[ERROR]}') else: LOGGER.error(f'Failed to get the avatar {login}. ' f'Answer server {answer}')
def build_response(err_code, data=None, err_msg=None): resp = { 'code': err_code, 'msg': err_msg if err_msg else get_msg(err_code), } if data is not None: resp['data'] = data return resp
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.')
def get_message_from_server(self): while True: time.sleep(1) with LOCK_SOCKET: try: message = get_msg(self.connection) except IncorrectDataNotDictError: LOGGER.error(f'Failed to decode received message.') # Connection timed out if errno = None, otherwise connection break. except OSError as err: # print(err.errno) if err.errno: if err.errno != 10038: LOGGER.critical(f'Lost server connection.') self.connection_lost_signal.emit() break else: break except (ConnectionError, ConnectionAbortedError, ConnectionResetError, json.JSONDecodeError): LOGGER.critical(f'Lost server connection.') self.connection_lost_signal.emit() break else: if ACTION in message and message[ACTION] == MESSAGE \ and TO in message and FROM in message \ and MESSAGE_TEXT in message and message[TO] == self.client_login: user_login = message[FROM] decrypted_message = self.encrypt_decrypt.message_decryption(message[MESSAGE_TEXT]) LOGGER.info(f'Received message from user {user_login}:\n{decrypted_message}.') self.database.save_message(user_login, 'in', decrypted_message) self.new_message_signal_chat.emit(user_login) self.new_message_signal_contacts.emit(user_login) elif ACTION in message and message[ACTION] == MESSAGE_GROUP \ and TO in message and FROM in message \ and MESSAGE_TEXT in message: with LOCK_DATABASE: self.database.add_group_message(message[TO], message[FROM], message[MESSAGE_TEXT]) self.new_message_group_signal.emit(message[TO]) elif RESPONSE in message and message[RESPONSE] == 205: with LOCK_DATABASE: self.database.add_known_users(message[LIST_INFO]) self.mongo_db.add_known_users(message[LIST_INFO]) elif RESPONSE in message and message[RESPONSE] == 206: with LOCK_DATABASE: self.database.add_groups(message[LIST_INFO]) self.new_group_signal.emit() else: LOGGER.error(f'Invalid message received from server: {message}')
def start_authorization_procedure(self): pubkey = self.pubkey.decode('ascii') msg_to_server = self.create_presence_msg(self.client_login, pubkey) LOGGER.info(f'A message has been generated to the server - {msg_to_server}.') try: send_msg(self.connection, msg_to_server) LOGGER.debug(f'Message sent to server.') answer_all = get_msg(self.connection) answer_code = self.answer_server_presence(answer_all) LOGGER.info(f'Received response from server - {answer_code}.\n') self.send_hash_password(answer_all) answer_code = self.answer_server_presence(get_msg(self.connection)) except json.JSONDecodeError: LOGGER.error('Failed to decode received Json string.') self.connection_lack() except IncorrectDataNotDictError: LOGGER.error('Invalid data format received.\n') self.connection_lack() except FieldMissingError as missing_error: LOGGER.error(f'No required field - {missing_error}.\n') self.connection_lack() except IncorrectCodeError as wrong_code: LOGGER.error(f'Invalid code in message - {wrong_code}.') self.connection_lack() except ConnectionResetError: LOGGER.critical('Server connection not established.') self.connection_lack() except ServerError as er: LOGGER.critical(f'{er}') self.is_connected = False self.answer_server.emit(f'{er}', 'login') exit(1) else: LOGGER.info(f'Received response from server - {answer_code}.\n') print(f'Server connection established.') self.progressbar_signal.emit()
async def get_messages_clients(self, client): # Receive a message from clients try: message = get_msg(client) except IncorrectDataNotDictError: LOGGER.error('Invalid data format received.') except (ConnectionResetError, json.decoder.JSONDecodeError, ConnectionAbortedError): self.remove_client(client) else: LOGGER.debug(f'Received message from client {message}.') await self.client_msg(message, client)
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.')
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.')
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.')
def start_client_authorization(self, client, message): message_auth = RESPONSE_511 random_str = binascii.hexlify(os.urandom( 64)) # The hexadecimal representation of the binary data # Bytes cannot be in the dictionary, decode (json.dumps -> TypeError) message_auth[DATA] = random_str.decode('ascii') password_hash = self.database.get_hash(message[USER][ACCOUNT_NAME]) hash = hmac.new(password_hash, random_str) server_digest = hash.digest() try: send_msg(client, message_auth) answer = get_msg(client) except OSError: client.close() return client_digest = binascii.a2b_base64(answer[DATA]) if RESPONSE in answer and answer[ RESPONSE] == 511 and hmac.compare_digest( server_digest, client_digest): self.names[message[USER][ACCOUNT_NAME]] = client client_ip, client_port = client.getpeername() try: send_msg(client, RESPONSE_200) except OSError: self.remove_client(message[USER][ACCOUNT_NAME]) self.database.login_user(message[USER][ACCOUNT_NAME], client_ip, client_port, message[USER][PUBLIC_KEY]) LOGGER.info( F'Successful user authentication {message[USER][ACCOUNT_NAME]}' ) self.new_connected_client.emit() else: response = RESPONSE_400 response[ERROR] = 'Wrong password.' try: send_msg(client, response) except OSError: pass self.clients.remove(client) client.close()
def send_group_message(self, group_name, message_text): message = { ACTION: MESSAGE_GROUP, FROM: self.client_login, TO: group_name, TIME: time.time(), MESSAGE_TEXT: message_text } with LOCK_SOCKET: try: send_msg(self.connection, message) answer = get_msg(self.connection) except (ConnectionResetError, ConnectionAbortedError, OSError): LOGGER.critical('Lost server connection.') return False else: if answer[RESPONSE] == 200: LOGGER.info(f'Successfully sent a message for the group {group_name} to the server.') with LOCK_DATABASE: self.database.add_group_message(group_name, self.client_login, message_text) return True
def pubkey_request(self, login): """The function of requesting the public key of the client from the server.""" LOGGER.debug(f'Public key request for {login}') request = { ACTION: PUBLIC_KEY_REQUEST, TIME: time.time(), ACCOUNT_NAME: login } with LOCK_SOCKET: try: send_msg(self.connection, request) answer = get_msg(self.connection) except (OSError, json.JSONDecodeError): # self.connection_lost_signal.emit() return if RESPONSE in answer and answer[RESPONSE] == 511: LOGGER.debug(f'Loaded public key for {login}') return answer[DATA] else: LOGGER.error(f'Failed to get the key of the interlocutor {login}. ' f'Answer server {answer}')
def send_user_message(self, contact_name, message_text): encrypted_message = self.encrypt_decrypt.message_encryption(message_text) message = { ACTION: MESSAGE, FROM: self.client_login, TO: contact_name, TIME: time.time(), MESSAGE_TEXT: encrypted_message } with LOCK_SOCKET: try: send_msg(self.connection, message) answer = get_msg(self.connection) except (ConnectionResetError, ConnectionAbortedError, OSError): LOGGER.critical('Lost server connection.') return False else: if answer[RESPONSE] == 400: LOGGER.info(f'{answer[ERROR]}. User {contact_name} is offline.') return f'User {contact_name} is offline!' LOGGER.debug(f'Message sent: {message},from {self.client_login} username {contact_name}') with LOCK_DATABASE: self.database.save_message(contact_name, 'out', message_text) return True
def test_get_msg(self): test_socket_200 = TestSocket(self.msg_dict_200) test_socket_400 = TestSocket(self.msg_dict_400) self.assertEqual(get_msg(test_socket_200), self.msg_dict_200) self.assertEqual(get_msg(test_socket_400), self.msg_dict_400)