Esempio n. 1
0
    def send_client_message(self, message: dict):
        """
        Handles the exchange of messages between clients.
        Validates the message and sends it if correct

        :param message: dictionary with the message
        """
        if message[DESTINATION] in self.nicknames and \
                self.nicknames[message[DESTINATION]] in \
                self.sockets_list:
            send_message(self.nicknames[message[DESTINATION]], message)
            SERVER_LOGGER.info('Было отправлено сообщение пользователю '
                               '%s от пользователя %s.' %
                               (message[DESTINATION], message[SENDER]))
        elif message[DESTINATION] in self.nicknames and \
                self.nicknames[message[DESTINATION]] \
                not in self.sockets_list:
            SERVER_LOGGER.error('Потеряна связь с клиентом %s, '
                                'отправка сообщения не возможна.' %
                                self.nicknames[message[DESTINATION]])
            self.delete_client(self.nicknames[message[DESTINATION]])
        else:
            SERVER_LOGGER.error(
                'Пользователь %s не зарегистрирован на сервере, '
                'отправка сообщения не возможна.' % message[DESTINATION])
Esempio n. 2
0
def main():
    global CONFIGS
    CONFIGS = load_configs(is_server=False)
    try:
        server_address = sys.argv[1]
        server_port = int(sys.argv[2])
        if not 65535 >= server_port >= 1024:
            raise ValueError
    except IndexError:
        server_address = CONFIGS.get('DEFAULT_IP_ADDRESS')
        server_port = CONFIGS.get('DEFAULT_PORT')
    except ValueError:
        print('The port should be in the range of 1024 and 65535')
        sys.exit(1)

    transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    transport.connect((server_address, server_port))
    presence_message = create_presence_message('Guest')
    send_message(transport, presence_message, CONFIGS)
    try:
        response = get_message(transport, CONFIGS)
        handled_response = handle_response(response)
        print(f'The response from the server: {response}')
        print(handled_response)
    except (ValueError, json.JSONDecodeError):
        print('Error message decoding ')
Esempio n. 3
0
 def update_list(self):
     """
     Generates the message with 205 code that triggers the update of contact
     and active users' lists for all active clients.
     """
     for name in self.nicknames:
         try:
             send_message(self.nicknames[name], {RESPONSE: 205})
         except OSError:
             self.delete_client(self.nicknames[name])
Esempio n. 4
0
 def process_message(self, message, listen_socks):
     if message['to'] in self.names and self.names[message['to']] in listen_socks:
         send_message(self.names[message['to']], message)
         logger.info(f'Отправлено сообщение пользователю {message["to"]} от пользователя {message["from"]}.')
         print(f'Отправлено сообщение пользователю {message["to"]} от пользователя {message["from"]}.')
     elif message['to'] in self.names and self.names[message['to']] not in listen_socks:
         raise ConnectionError
     else:
         logger.error(
             f'Пользователь {message["to"]} не зарегистрирован на сервере, отправка сообщения невозможна.')
Esempio n. 5
0
 def shutdown_socket(self):
     """
     Handles the socket shutdown. Sets the running flag to False,
     generates the exit message to the server and sends it.
     """
     self.running = False
     message = {
         ACTION: EXIT,
         TIME: time(),
         ACCOUNT_NAME: self.client_nickname
     }
     with socket_lock:
         try:
             send_message(self.client_socket, message)
         except OSError:
             pass
     SOCKET_LOGGER.debug('Клиентский сокет завершает работу.')
     sleep(1)
Esempio n. 6
0
def main():
    global CONFIGS
    CONFIGS = load_configs()
    try:
        if '-p' in sys.argv:
            listen_port = int(sys.argv[sys.argv.index('-p') + 1])
        else:
            listen_port = CONFIGS.get('DEFAULT_PORT')
        if not 65536 >= listen_port >= 1025:
            raise ValueError
    except IndexError:
        print('After -\'p\' should be specified the port')
        sys.exit(1)
    except ValueError:
        print('The port should be specified in the range from 1024 to 65535')
        sys.exit(1)

    try:
        if '-a' in sys.argv:
            listen_address = sys.argv[sys.argv.index('-a') + 1]
        else:
            listen_address = ''
    except IndexError:
        print('After -\'a\' - requires specify address for ')
        sys.exit(1)

    transport = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    transport.bind((listen_address, listen_port))

    transport.listen(CONFIGS.get('MAX_CONNECTIONS'))

    while True:
        client, client_address = transport.accept()
        try:
            message = get_message(client, CONFIGS)
            response = handle_message(message)
            send_message(client, response, CONFIGS)
            # client.close()
        except (ValueError, json.JSONDecodeError):
            print('Received inappropriate message from a client')
        finally:
            client.close()
Esempio n. 7
0
    def remove_contact(self, contact: str):
        """
        Handles the adding of a new contact on the socket's side.
        Generates the relevant message and sends it to the server.

        :param contact: contact to be deleted
        """
        SOCKET_LOGGER.debug('Удаление контакта %s для пользователя %s' % (
            contact,
            self.client_nickname,
        ))
        request = {
            ACTION: REMOVE_CONTACT,
            TIME: time(),
            USER: self.client_nickname,
            ACCOUNT_NAME: contact
        }
        with socket_lock:
            send_message(self.client_socket, request)
            self.process_answer(receive_message(self.client_socket))
Esempio n. 8
0
    def create_message(self, recipient: str, message: str):
        """
        Creates and sends the dictionary with the message from one client to another.

        :param recipient: message's recipient
        :param message: message text
        """
        message_to_send_dict = {
            ACTION: MESSAGE,
            SENDER: self.client_nickname,
            DESTINATION: recipient,
            TIME: time(),
            MESSAGE_TEXT: message
        }
        SOCKET_LOGGER.debug('Сформирован словарь сообщения: %s' %
                            message_to_send_dict)
        with socket_lock:
            send_message(self.client_socket, message_to_send_dict)
            self.process_answer(receive_message(self.client_socket))
            SOCKET_LOGGER.info('Отправлено сообщение пользователю %s' %
                               recipient)
Esempio n. 9
0
 def request_user_list(self):
     """
     Requests a list of existing users from the server.
     If the status code of the server's response is 202, updates
     the list in the client's DB.
     """
     SOCKET_LOGGER.info(
         'Пользователь %s запрашивает список всех пользователей.' %
         self.client_nickname)
     request = {
         ACTION: USER_REQUEST,
         TIME: time(),
         ACCOUNT_NAME: self.client_nickname
     }
     with socket_lock:
         send_message(self.client_socket, request)
         response = receive_message(self.client_socket)
     if RESPONSE in response and response[RESPONSE] == 202:
         self.database.add_existing_users(response[LIST_INFO])
     else:
         SOCKET_LOGGER.error(
             'Не удалось обновить список известных пользователей.')
Esempio n. 10
0
    def request_pub_key(self, user: str) -> str:
        """
        Requests a public RSA key for a client in user's contact list.
        If the status code in the server's response is 511, returns the key.

        :param user: contact
        """
        SOCKET_LOGGER.debug('Запрос публичного ключа для пользователя %s' %
                            user)
        request = {
            ACTION: PUBLIC_KEY_REQUEST,
            TIME: time(),
            ACCOUNT_NAME: user
        }
        with socket_lock:
            send_message(self.client_socket, request)
            response = receive_message(self.client_socket)
            if RESPONSE in response and response[RESPONSE] == 511:
                return response[DATA]
            else:
                SOCKET_LOGGER.error('Не удалось получить публичный ключ '
                                    'пользователя %s' % user)
Esempio n. 11
0
def save_jd_pin(flow):
    headers_json = dict(flow.request.headers.items())
    cookie = headers_json.get("cookie")
    regMatch = cookieReg.match(cookie)
    cookies = regMatch.groupdict()
    pin = cookies.get("pin")
    wskey = cookies.get("wskey")
    if pin is not None and wskey is not None:
        query = Jd.select().where(Jd.pin == pin)
        if query.exists():
            Jd.update(
                pin=pin,
                wskey=wskey,
            ).where(Jd.pin == pin).execute()
            logger.info("更新京东用户【{}】信息".format(pin))
            send_message("更新京东用户【{}】信息".format(pin))
        else:
            Jd.insert(
                pin=pin,
                wskey=wskey,
            ).execute()
            logger.info("添加京东用户【{}】信息".format(pin))
            send_message("添加京东用户【{}】信息".format(pin))
Esempio n. 12
0
 def request_contacts(self):
     """
     Requests a contact list from the server.
     If the status code of the server's response is 202, updates
     the contact list in the client's DB.
     """
     SOCKET_LOGGER.debug('Запрос списка контактов пользователя: %s' %
                         self.client_nickname)
     self.database.cleat_contact_list()
     request = {
         ACTION: GET_CONTACTS,
         TIME: time(),
         USER: self.client_nickname
     }
     SOCKET_LOGGER.debug('Сформирован запрос к серверу: %s' % request)
     with socket_lock:
         send_message(self.client_socket, request)
         response = receive_message(self.client_socket)
     SOCKET_LOGGER.debug('Получен ответ от сервера: %s' % response)
     if RESPONSE in response and response[RESPONSE] == 202:
         for contact in response[LIST_INFO]:
             self.database.add_user_to_contacts(contact)
     else:
         SOCKET_LOGGER.error('Не удалось обновить список контактов.')
Esempio n. 13
0
def callback_reg():
    data = json.loads(request.data)
    token = CONFIG.VK_TOCKEN
    if 'type' not in data.keys():
        return 'not vk'
    elif data['type'] == 'message_new':
        user_id = data['object']['user_id']
        text = data['object']['body'].split()
        if text[0] in ["!группа", "!гр"]:
            sess = db_session.create_session()
            if not sess.query(VkUser.id).filter(VkUser.id == user_id).first():
                if Group.if_group_already_created__vk('_'.join(text[1::])):
                    group_id = sess.query(Group.id).filter(
                        Group.name == '_'.join(text[1::])).first()[0]
                    user_group = VkUser(id=user_id,
                                        user_name=text[-1],
                                        group_id=group_id)
                    sess.add(user_group)
                    sess.commit()
                    send_message(user_id, 'Вы добавлены в группу')
                    return 'ok'
                else:
                    send_message(user_id, 'Такой группы не существует')
                    return 'ok'
            else:
                send_message(user_id, 'Вы уже добавлены в группу')
                return 'ok'
        elif text[0] in ["!дз"]:
            sess = db_session.create_session()
            if len(text) == 1:
                date = dt.now().strftime('%Y-%m-%d')
            else:
                date = text[1]
            user_group_id = sess.query(
                VkUser.group_id).filter(VkUser.id == user_id).first()[0]
            tasks = sess.query(Task.subject, Task.author, Task.task).filter(
                Task.group_id == user_group_id, Task.date_task == date)
            if tasks:
                send_message(
                    user_id, '\n'.join([
                        f'{task[0]} @{task[1]}\n{task[2]}\n' for task in tasks
                    ]))
                return 'ok'
            else:
                send_message(user_id, 'Заданий нет')
                return 'ok'
        elif text[0] in ['!задание']:  # TODO: need research and DB-refactor
            sess = db_session.create_session()
            author, group_id = sess.query(
                VkUser.user_name,
                VkUser.group_id).filter(VkUser.id == user_id).first()
            task = Task(date_task=text[1],
                        subject=' '.join(text[2].split('_')),
                        task=' '.join(text[2::]),
                        author=author,
                        group_id=group_id)
            sess.add(task)
            sess.commit()
            send_message(user_id, 'Задание добавлено')
            return 'ok'
        elif text[0] in ['!help', '!помощь', '!команды']:
            send_message(
                user_id,
                '!гр <группа> <ваще имя> - привязывает ваш профиль к группе\n!дз <date> - показывает задание на заданную дату (либо не сегодня если не задана)\n'
            )
            return 'ok'
    else:
        return 'ok'
Esempio n. 14
0
    def process_client_message(self, message, client):
        global new_connection
        logger.debug(f'Разбор сообщения от клиента : {message}')

        # Если это сообщение о присутствии, принимаем и отвечаем
        if 'action' in message and message['action'] == 'presence' and 'time' in message and 'user' in message:
            # Если такой пользователь ещё не зарегистрирован, регистрируем, иначе отправляем ответ и завершаем
            # соединение
            if message['user']['account_name'] not in self.names.keys():
                self.names[message['user']['account_name']] = client
                client_ip, client_port = client.getpeername()
                self.database.user_login(message['user']['account_name'], client_ip, client_port)
                send_message(client, {'response': 200})
                logger.debug(f'Клиенту {client} отправлен ответ 200')
                with conflag_lock:
                    new_connection = True

            else:
                response = {
                    'response': 400,
                    'error': 'Имя пользователя занято'
                }
                send_message(client, response)
                logger.debug(f'Клиенту {client} отправлен ответ 400')
                self.clients.remove(client)
                client.close()
            return

        # Если это сообщение, то добавляем его в очередь сообщений.
        elif 'action' in message and message['action'] == 'message' and 'to' in message and 'time' in message \
                and 'from' in message and 'mess_text' in message and self.names[message['from']] == client:
            if message['to'] in self.names:
                self.messages.append(message)
                self.database.process_message(message['from'], message['to'])
                send_message(client, {'response': 200})
            else:
                response = {
                    'response': 400,
                    'error': 'Пользователь не зарегистрирован на сервере'
                }
                send_message(client, response)
            return

        # Если клиент выходит
        elif 'action' in message and message['action'] == 'exit' and 'account_name' in message \
				and self.names[message['account_name']] == client:
            self.database.user_logout(message['account_name'])
            logger.info(f'Клиент {message["account_name"]} корректно отключился от сервера.')
            self.clients.remove(self.names[message['account_name']])
            self.names[message['account_name']].close()
            del self.names[message['account_name']]
            with conflag_lock:
                new_connection = True
            return

        # Если это запрос контакт-листа
        elif 'action' in message and message['action'] == 'get_contacts' and 'user' in message and self.names[message['user']] == client:
            response = {
                        'response': 202,
                        'data_list': None
                        }
            response['data_list'] = self.database.get_contacts(message['user'])
            logger.debug(f'Запрос контакт-листа get_contacts из БД 202 {self.database}: {response["data_list"]}')
            send_message(client, response)
            logger.debug(f'process client message send message {response}')

    # Если это добавление контакта
        elif 'action' in message and message['action'] == 'add' and 'account_name' in message and 'user' in message \
             and self.names[message['user']] == client:
            self.database.add_contact(message['user'], message['account_name'])
            send_message(client, {'response': 200})

    # Если это удаление контакта
        elif 'action' in message and message['action'] == 'remove' and 'account_name' in message and 'user' in message \
            and self.names[message['user']] == client:
            self.database.remove_contact(message['user'], message['account_name'])
            send_message(client, {'response': 200})

    # Если это запрос известных пользователей
        elif 'action' in message and message['action'] == 'get_users' and 'account_name' in message and self.names[message['account_name']] == client:
            response = {
                'response': 202,
                'data_list': None
            }
            response['data_list'] = [user[0] for user in self.database.users_list()]
            send_message(client, response)

        # Иначе отдаём Bad request
        else:
            response = {
            'response': 400,
            'error': 'Запрос некорректен'
            }
            send_message(client, response)
            return
Esempio n. 15
0
    def authorize_client(self, message: dict, client: socket):
        """
        Handles the client's authorization. Checks if the username isn't already taken,
        then checks if the user is registered on the server. If those two checks pass,
        the method then initiates the exchange of encrypted passwords with the client.
        If the password is correct, the client is logged onto the server, otherwise the
        client is removed from the server and his socket gets closed.

        :param message: presence message
        :param client: client's socket
        """
        SERVER_LOGGER.debug('Старт процесса авторизации пользователя %s' %
                            message[USER])
        if message[USER][ACCOUNT_NAME] in self.nicknames.keys():
            response = {RESPONSE: 400, ERROR: 'Имя пользователя уже занято'}
            try:
                send_message(client, response)
            except OSError as e:
                SERVER_LOGGER.debug('Произошла ошибка: %s' % e)
                pass
            self.clients_list.remove(client)
            client.close()
        elif not self.server_db.check_existing_user(
                message[USER][ACCOUNT_NAME]):
            response = {
                RESPONSE: 400,
                ERROR: 'Пользователь не зарегистрирован'
            }
            try:
                SERVER_LOGGER.debug('Пользователь %s не зарегистрирован' %
                                    message[USER][ACCOUNT_NAME])
                send_message(client, response)
            except OSError as e:
                SERVER_LOGGER.debug('Произошла ошибка: %s' % e)
                pass
        else:
            SERVER_LOGGER.debug('Начало проверки пароля')
            random_string = hexlify(urandom(64))
            auth_response = {
                RESPONSE: 511,
                DATA: random_string.decode('ascii')
            }
            pwd_hash = new(
                self.server_db.get_user_pwd_hash(message[USER][ACCOUNT_NAME]),
                random_string, 'MD5')
            pwd_digest = pwd_hash.digest()
            SERVER_LOGGER.debug('Подготовлено сообщение для авторизации: %s' %
                                auth_response)
            try:
                send_message(client, auth_response)
                client_response = receive_message(client)
            except OSError as e:
                SERVER_LOGGER.debug('Ошибка при авторизации: ', exc_info=e)
                client.close()
                return
            client_digest = a2b_base64(client_response[DATA])
            if RESPONSE in client_response and \
                    client_response[RESPONSE] == 511 and \
                    compare_digest(pwd_digest, client_digest):
                self.nicknames[message[USER][ACCOUNT_NAME]] = client
                client_addr, client_port = client.getpeername()
                try:
                    send_message(client, {RESPONSE: 200})
                except OSError:
                    self.delete_client(client)
                self.server_db.login_user(message[USER][ACCOUNT_NAME],
                                          client_addr, client_port,
                                          message[USER][PUBLIC_KEY])
            else:
                response = {RESPONSE: 400, ERROR: 'Неверный пароль'}
                try:
                    send_message(client, response)
                except OSError:
                    pass
                self.clients_list.remove(client)
                client.close()
Esempio n. 16
0
    def establish_connection(self, ip_address: str, port: int):
        """
        Establishes connection to the server.
        Makes 5 attempts to do so, if unsuccessful, ends the cycle.
        If successful, sends the presence message to the server,
        and then, sends the encrypted password to the server to
        compare to the one stored in the server's DB.

        :param ip_address: server's IP address
        :param port: server's listening port
        """
        self.client_socket = socket(AF_INET, SOCK_STREAM)
        self.client_socket.settimeout(5)
        connected = False

        for i in range(5):
            SOCKET_LOGGER.info('Попытка соединения №%d' % (i + 1, ))
            try:
                self.client_socket.connect((ip_address, port))
            except (OSError, ConnectionRefusedError):
                pass
            else:
                connected = True
                break
            sleep(1)

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

        SOCKET_LOGGER.debug('Установлено соединение с сервером. '
                            'Начинаю процесс авторизации.')

        password_bytes = self.password.encode('utf-8')
        salt = self.client_nickname.lower().encode('utf-8')
        password_hash = pbkdf2_hmac('sha512', password_bytes, salt, 10000)
        password_hash_str = hexlify(password_hash)

        SOCKET_LOGGER.debug('Подготовлен хэш пароля: %s' % password_hash_str)

        self.pubkey = self.keys.publickey().export_key().decode('ascii')
        with socket_lock:
            msg = self.establish_presence()
            try:
                send_message(self.client_socket, msg)
                server_response = receive_message(self.client_socket)
                SOCKET_LOGGER.debug('Ответ сервера - %s' % server_response)
                if RESPONSE in server_response:
                    if server_response[RESPONSE] == 400:
                        raise ServerError(server_response[ERROR])
                    elif server_response[RESPONSE] == 511:
                        resp_data = server_response[DATA]
                        resp_hash = new(password_hash_str,
                                        resp_data.encode('utf-8'), 'MD5')
                        digest = resp_hash.digest()
                        client_response = {
                            RESPONSE: 511,
                            DATA: b2a_base64(digest).decode('ascii')
                        }
                        send_message(self.client_socket, client_response)
                        self.process_answer(receive_message(
                            self.client_socket))
            except (OSError, JSONDecodeError):
                SOCKET_LOGGER.critical('В процессе авторизации потеряно '
                                       'соединение с сервером')
                raise ServerError('В процессе авторизации потеряно '
                                  'соединение с сервером')
            else:
                SOCKET_LOGGER.info('Соединение успешно установлено.')
Esempio n. 17
0
    def process_client_message(self, message: dict, client: socket):
        """
        Handles the messages from clients according to their service codes.
        This method handles authorization, client's exit, contact list, existing users'
        and public key requests, requests to add or delete a contact and messages from
        client to client (this method also records these messages to server DB). This method
        triggers a relevant handler if needed, or tries to send a response with a relevant
        service code (200, 202, 511 or 400 in case of bad request). If sending a message
        was not possible, this method deletes the user from the list of active users.

        :param message: dictionary with a message
        :param client: client's socket
        """
        SERVER_LOGGER.debug('Обработка входящего сообщения: %s.' % message)
        # авторизация клиента
        if ACTION in message and message[ACTION] == PRESENCE \
                and TIME in message and USER in message:
            self.authorize_client(message, client)
        # сообщение от клиента
        elif ACTION in message and message[ACTION] == MESSAGE and \
                SENDER in message and DESTINATION in message and \
                TIME in message and MESSAGE_TEXT in message \
                and self.nicknames[message[SENDER]] == client:
            if message[DESTINATION] in self.nicknames:
                self.messages_queue.append(message)
                self.server_db.record_message_to_history(
                    message[SENDER], message[DESTINATION])
                self.send_client_message(message)
                try:
                    send_message(client, {RESPONSE: 200})
                except OSError:
                    self.delete_client(client)
            else:
                response = {
                    RESPONSE: 400,
                    ERROR: 'Пользователь не зарегистрирован на сервере.'
                }
                try:
                    send_message(client, response)
                except OSError:
                    pass
            return
        # клиент выходит
        elif ACTION in message and message[ACTION] == EXIT and \
                ACCOUNT_NAME in message:
            self.delete_client(client)
        # запрос списка контактов
        elif ACTION in message and message[ACTION] == GET_CONTACTS \
                and USER in message \
                and self.nicknames[message[USER]] == client:
            response = {
                RESPONSE: 202,
                LIST_INFO: self.server_db.get_user_contact_list(message[USER])
            }
            try:
                send_message(client, response)
            except OSError:
                self.delete_client(client)
        # запрос на добавление контакта
        elif ACTION in message and message[ACTION] == ADD_CONTACT \
                and ACCOUNT_NAME in message and USER in message \
                and self.nicknames[message[USER]] == client:
            self.server_db.add_contact_to_list(message[USER],
                                               message[ACCOUNT_NAME])
            try:
                send_message(client, {RESPONSE: 200})
            except OSError:
                self.delete_client(client)
        # запрос на удаление контакта
        elif ACTION in message and message[ACTION] == REMOVE_CONTACT \
                and ACCOUNT_NAME in message and USER in message \
                and self.nicknames[message[USER]] == client:
            self.server_db.remove_contact_from_list(message[USER],
                                                    message[ACCOUNT_NAME])
            try:
                send_message(client, {RESPONSE: 200})
            except OSError:
                self.delete_client(client)
        # запрос списка пользователей
        elif ACTION in message and message[ACTION] == USER_REQUEST \
                and ACCOUNT_NAME in message \
                and self.nicknames[message[ACCOUNT_NAME]] == client:
            response = {
                RESPONSE: 202,
                LIST_INFO:
                [user[0] for user in self.server_db.all_users_list()]
            }
            try:
                send_message(client, response)
            except OSError:
                self.delete_client(client)
        # запрос публичного ключа клиента
        elif ACTION in message and message[ACTION] == \
                PUBLIC_KEY_REQUEST and ACCOUNT_NAME in message:
            response = {
                RESPONSE: 511,
                DATA: self.server_db.get_user_public_key(message[ACCOUNT_NAME])
            }
            if response[DATA]:
                try:
                    send_message(client, response)
                except OSError:
                    self.delete_client(client)
            else:
                response = {
                    RESPONSE: 400,
                    ERROR: 'Отсутствует публичный ключ пользователя.'
                }
                try:
                    send_message(client, response)
                except OSError:
                    self.delete_client(client)
        else:
            response = {RESPONSE: 400, ERROR: 'bad request'}
            try:
                send_message(client, response)
            except OSError:
                self.delete_client(client)