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.')
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
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
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('Сбой соединения в процессе авторизации.')
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)
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)
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)
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)
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')
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 __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
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)
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('Соединение с сервером успешно установлено.')
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 __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
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 __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
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])
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 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)
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('Сбой соединения в процессе авторизации.')
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('Сбой соединения в процессе авторизации.')
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('Соединение с сервером установлено успешно')