Example #1
0
def message_writer(to_socket, account_name='Anonymous'):
    """
    function requests message text and returns him,
    also it may leave program, by necessity
    :param to_socket:
    :param account_name:
    :return formed_dict_to_send:
    """
    to_receiver = input('Send message to user: '******'Enter text message: ')
    message_dict = {
        ACTION: MESSAGE,
        SENDER: account_name,
        DESTINATION: to_receiver,
        TIME: time.time(),
        MESSAGE_TEXT: message
    }
    CLIENT_SIDE_LOGGER.debug(f'message dict formed: {message_dict}')
    try:
        send_message(to_socket, message_dict)
        CLIENT_SIDE_LOGGER.info(f'message to {to_receiver} was sent')
    except:
        CLIENT_SIDE_LOGGER.critical('something going wrong, '
                                    'connection with server will be lost')
        sys.exit(1)
Example #2
0
def client_initializer():
    """
    Loading param of cmd and do init of socket
    with transfer by result
    """
    try:
        server_addr = sys.argv[1]
        server_port = int(sys.argv[2])
        if server_port < 1024 or server_port > 65535:
            raise ValueError
    except IndexError:
        server_addr = DEFAULT_IP_ADDRESS
        server_port = DEFAULT_PORT
    except ValueError:
        print(
            'Only a number between 1024 and 65535 can be specified as a port.')
        sys.exit(1)

    transfer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    transfer.connect((server_addr, server_port))
    confirmation_for_server = launch_presence()
    send_message(transfer, confirmation_for_server)
    try:
        answer = server_response(get_message(transfer))
        print(answer)
    except (ValueError, json.JSONDecodeError):
        print('Failed to decode server message.')
Example #3
0
def client_initializer():
    """
    Loading param of cmd and do init of socket
    with transfer by result
    """
    server_addr, server_port, client_mode = argument_parser()

    CLIENT_SIDE_LOGGER.info(
        f'client application was launched with parameters: '
        f'server address: {server_addr} '
        f'port: {server_port}, mode: {client_mode}')
    try:
        transfer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        transfer.connect((server_addr, server_port))
        send_message(transfer, launch_presence())
        answer = server_response(get_message(transfer))
        CLIENT_SIDE_LOGGER.info(f'received response from server {answer}')
        print('Сonnection to the server has been established')
    except json.JSONDecodeError:
        CLIENT_SIDE_LOGGER.error(f'failed to decode received Json string')
        sys.exit(1)
    except ExceptionServerError as error:
        CLIENT_SIDE_LOGGER.error(
            f'during attempt to connect, server return error: {error.text}')
        sys.exit(1)
    except RequestedFieldAbsentError as missing_error:
        CLIENT_SIDE_LOGGER.error(f'in server response has no requested field'
                                 f'{missing_error.missing_field}')
        sys.exit(1)
    except ConnectionRefusedError:
        CLIENT_SIDE_LOGGER.critical(
            f'connection to server is unavailable {server_addr}:{server_port}, '
            f'request to connect was refused')
        sys.exit(1)
    else:
        if client_mode == 'send':
            print('Status - preparing to send messages')
        else:
            print('Status - receiving messages')
        while True:
            if client_mode == 'send':
                try:
                    send_message(transfer, message_writer(transfer))
                except (ConnectionResetError, ConnectionError,
                        ConnectionAbortedError):
                    CLIENT_SIDE_LOGGER.error(
                        f'connection with server {server_addr} was lost')
                    sys.exit(1)

            if client_mode == 'listen':
                try:
                    server_msg_handler(get_message(transfer))
                except (ConnectionResetError, ConnectionError,
                        ConnectionAbortedError):
                    CLIENT_SIDE_LOGGER.error(
                        f'connection with server {server_addr} was lost')
                    sys.exit(1)
Example #4
0
def client_initializer():
    """
    Loading param of cmd and do init of socket
    with transfer by result
    """
    print('Welcome to MikeT messenger!')
    server_addr, server_port, client_name = argument_parser()

    if not client_name:
        client_name = input('Enter your name: ')

    CLIENT_SIDE_LOGGER.info(
        f'client application was launched with parameters: '
        f'server address: {server_addr} '
        f'port: {server_port}, mode: {client_name}')
    try:
        transfer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        transfer.connect((server_addr, server_port))
        send_message(transfer, launch_presence(client_name))
        answer = server_response(get_message(transfer))
        CLIENT_SIDE_LOGGER.info(f'received response from server {answer}')
        print('Сonnection to the server has been established')
    except json.JSONDecodeError:
        CLIENT_SIDE_LOGGER.error(f'failed to decode received Json string')
        sys.exit(1)
    except ExceptionServerError as error:
        CLIENT_SIDE_LOGGER.error(
            f'during attempt to connect, server return error: {error.text}')
        sys.exit(1)
    except RequestedFieldAbsentError as missing_error:
        CLIENT_SIDE_LOGGER.error(f'in server response has no requested field'
                                 f'{missing_error.missing_field}')
        sys.exit(1)
    except (ConnectionRefusedError, ConnectionError):
        CLIENT_SIDE_LOGGER.critical(f'connection to server is not available'
                                    f' {server_addr}:{server_port}, '
                                    f'request to connect was refused')
        sys.exit(1)
    else:
        target_side = threading.Thread(target=server_msg_handler,
                                       args=(transfer, client_name))
        target_side.daemon = True
        target_side.start()

        user_side = threading.Thread(target=user_online,
                                     args=(transfer, client_name))
        user_side.daemon = True
        user_side.start()
        CLIENT_SIDE_LOGGER.debug('process started')

        while True:
            time.sleep(1)
            if target_side.is_alive() and user_side.is_alive():
                continue
            break
Example #5
0
 def test_send_message(self):
     """
     testing correct work of delivery fucntion
     creating test socket and checking correct of
     dictionary sends
     """
     test_socket = TestSocket(self.test_dict_send)
     send_message(test_socket, self.test_dict_send)
     self.assertEqual(test_socket.encoded_message,
                      test_socket.received_message)
     with self.assertRaises(Exception):
         send_message(test_socket, test_socket)
Example #6
0
def server_launcher():
    """
    loading params of cmd, if they're not set,
    will defined by default, after that function detects
    addr which will be listen, prepares port and
    starts to receive a information
    """
    try:
        if '-p' in sys.argv:
            port_data = int(sys.argv[sys.argv.index('-p') + 1])
        else:
            port_data = DEFAULT_PORT
        if port_data < 1024 or port_data > 65535:
            raise ValueError
    except IndexError:
        print('After the parameter -\'p\' must be specified the port'
              ' number.')
        sys.exit(1)
    except ValueError:
        print('Only a number between 1024 and 65535 can be specified'
              ' as a port.')
        sys.exit(1)

    try:
        if '-a' in sys.argv:
            addr_data = sys.argv[sys.argv.index('-a') + 1]
        else:
            addr_data = ''

    except IndexError:
        print('After the parameter \'a\'- must be specified the address'
              ' that the server will listen to.')
        sys.exit(1)

    transfer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    transfer.bind((addr_data, port_data))
    transfer.listen(MAX_CONNECTIONS)

    while True:
        client_socket_box, client_addr = transfer.accept()
        try:
            message_receiver = get_message(client_socket_box)
            print(message_receiver)
            response = analyzer(message_receiver)
            send_message(client_socket_box, response)
            client_socket_box.close()
        except (ValueError, json.JSONDecodeError):
            print('Incorrect message was received from client side')
            client_socket_box.close()
Example #7
0
def server_launcher():
    """
    loading params of cmd, if they're not set,
    will defined by default, after that function detects
    addr which will be listen, prepares port and
    starts to receive a information
    """
    parser = argument_parser()
    namespace = parser.parse_args(sys.argv[1:])
    addr_data = namespace.a
    port_data = namespace.p
    if not 1023 < port_data < 65536:
        SERVER_SIDE_LOGGER.critical(
            f'port was defined incorrectly {port_data} '
            f'port address range available between 1024 and 65535')
        sys.exit(1)
    SERVER_SIDE_LOGGER.info(
        f'server launched, port to connect: {port_data} '
        f'connection from address: {addr_data} '
        f'(If address not defined, connection will be available without it)')

    transfer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    transfer.bind((addr_data, port_data))
    transfer.listen(MAX_CONNECTIONS)

    while True:
        client_socket_box, client_addr = transfer.accept()
        SERVER_SIDE_LOGGER.info(f'connection with {client_addr} stabilized')
        try:
            message_receiver = get_message(client_socket_box)
            SERVER_SIDE_LOGGER.debug(f'message received: {message_receiver}')
            response = analyzer(message_receiver)
            SERVER_SIDE_LOGGER.info(f'response is ready to sent: {response}')
            send_message(client_socket_box, response)
            SERVER_SIDE_LOGGER.debug(
                f'connection with client {client_addr} will be closed')
            client_socket_box.close()
        except (ValueError, json.JSONDecodeError):
            SERVER_SIDE_LOGGER.error(
                f'json file, received from {client_addr} '
                f'was unavailable to decode. Connection will be closed')
            client_socket_box.close()
        except UnreadableReceivedDataError:
            SERVER_SIDE_LOGGER.error(
                f'message format from {client_addr} is unreadable'
                f'the connection will be closed')
Example #8
0
def analyzer(message, message_list, client, clients, names):
    """
    A message handler from clients that accepts a dictionary -
    message from the client, checks the correctness, returns a
    response dictionary for a client
    """
    SERVER_SIDE_LOGGER.debug(f'analyze of client message {message}')
    if ACTION in message and message[ACTION] == PRESENCE and\
            TIME in message and USER in message:
        if message[USER][ACCOUNT_NAME] not in names.keys():
            names[message[USER][ACCOUNT_NAME]] = client
            send_message(client, RESPONSE_200)
        else:
            response = RESPONSE_400
            response[ERROR] = 'name of user is occupied'
            send_message(client, response)
            clients.remove(client)
            client.close()
        return
    elif ACTION in message and message[ACTION] == MESSAGE and \
            DESTINATION in message and TIME in message \
            and SENDER in message and MESSAGE_TEXT in message:
        message_list.append(message)
        return
    elif ACTION in message and message[ACTION] == EXIT \
            and ACCOUNT_NAME in message:
        clients.remove(names[message[ACCOUNT_NAME]])
        names[message[ACCOUNT_NAME]].close()
        del names[message[ACCOUNT_NAME]]
        return
    else:
        response = RESPONSE_400
        response[ERROR] = 'bad request'
        send_message(client, response)
        return
Example #9
0
def process_message(message, names, listen_socks):
    """
    The function of addressing a message to a specific client. Accepts a message dictionary,
    list of registered users and listening sockets. Returns nothing.
    :param message:
    :param names:
    :param listen_socks:
    :return:
    """
    if message[DESTINATION] in names and names[
            message[DESTINATION]] in listen_socks:
        send_message(names[message[DESTINATION]], message)
        SERVER_SIDE_LOGGER.info(
            f'Message was sent to user {message[DESTINATION]} '
            f'from user {message[SENDER]}.')
    elif message[DESTINATION] in names and names[
            message[DESTINATION]] not in listen_socks:
        raise ConnectionError
    else:
        SERVER_SIDE_LOGGER.error(
            f'Пользователь {message[DESTINATION]} не зарегистрирован на сервере, '
            f'отправка сообщения невозможна.')
Example #10
0
def analyzer(client_message, message_list, client):
    """
    A message handler from clients that accepts a dictionary -
    message from the client, checks the correctness, returns a
    response dictionary for a client
    """
    SERVER_SIDE_LOGGER.debug(f'analyze of client message {client_message}')
    if ACTION in client_message and client_message[ACTION] == PRESENCE \
            and TIME in client_message and USER in client_message \
            and client_message[USER][ACCOUNT_NAME] == 'Anonymous':
        send_message(client, {RESPONSE: 200})
        return
    elif ACTION in client_message and client_message[ACTION] == MESSAGE and \
            TIME in client_message and MESSAGE_TEXT in client_message:
        message_list.append((client_message[ACCOUNT_NAME], client_message[MESSAGE_TEXT]))
        return
    else:
        send_message(client, {
            RESPONSE: 400,
            ERROR: 'Bad Request'
        })
        return
Example #11
0
def client_initializer():
    """
    Loading param of cmd and do init of socket
    with transfer by result
    """
    parser = argument_parser()
    namespace = parser.parse_args(sys.argv[1:])
    server_addr = namespace.addr
    server_port = namespace.port

    if not 1023 < server_port < 65536:
        CLIENT_SIDE_LOGGER.critical(
            f'attempt to launch client with wrong port: {server_port} '
            f'allowed ports between 1024 and 65535 numbers, process ends')
        sys.exit(1)
    CLIENT_SIDE_LOGGER.info(
        f'client application was launched with parameters: '
        f'server address: {server_addr} '
        f'port: {server_port}')
    try:
        transfer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        transfer.connect((server_addr, server_port))
        confirm_presence_to_server = launch_presence()
        send_message(transfer, confirm_presence_to_server)
        answer = server_response(get_message(transfer))
        CLIENT_SIDE_LOGGER.info(f'received response from server {answer}')
        print(answer)
    except json.JSONDecodeError:
        CLIENT_SIDE_LOGGER.error(f'failed to decode received Json string')
    except RequestedFieldAbsentError as missing_error:
        CLIENT_SIDE_LOGGER.error(f'in server response has no requested field'
                                 f'{missing_error}{missing_field}')
    except ConnectionRefusedError:
        CLIENT_SIDE_LOGGER.critical(
            f'connection to server is unavailable {server_addr}:{server_port}, '
            f'request to connect was refused')
Example #12
0
def user_online(from_socket, client_name):
    """
    function coop with user, requests commands, sends msgs
    :param from_socket:
    :param client_name:
    :return:
    """
    helper()
    while True:
        command = input('Enter command: ')
        if command == 'm':
            message_writer(from_socket, client_name)
        elif command == 'h':
            helper()
        elif command == 'x':
            send_message(from_socket, command_to_exit(client_name))
            print('connection will be closed')
            CLIENT_SIDE_LOGGER.info(f'process will be closed by user request')
            time.sleep(0.8)
            break
        else:
            print('Unknown command, please try again.\n'
                  'To call help(show list of useful commands)'
                  'Enter - h : ')
Example #13
0
def server_launcher():
    """
    loading params of cmd, if they're not set,
    will defined by default, after that function detects
    addr which will be listen, prepares port and
    starts to receive a information
    """
    addr_to_listen, port_to_listen = argument_parser()

    SERVER_SIDE_LOGGER.info(
        f'server launched, port to connect: {port_to_listen} '
        f'connection from address: {addr_to_listen} '
        f'(If address not defined, connection will be available without it)'
    )

    transfer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    transfer.bind((addr_to_listen, port_to_listen))
    transfer.settimeout(0.5)
    clients_online = []
    messages_queue = []
    transfer.listen(MAX_CONNECTIONS)

    while True:
        try:
            client_socket_box, addr_to_listen = transfer.accept()
        except OSError:
            pass
        else:
            SERVER_SIDE_LOGGER.info(f'connection with PC {addr_to_listen} stabilized')
            clients_online.append(client_socket_box)

        data_list_for_receiving = []
        data_list_to_send = []
        data_list_of_err_occured = []

        try:
            if clients_online:
                data_list_for_receiving, data_list_to_send, data_list_of_err_occured = \
                    select.select(clients_online, clients_online, [], 0)
        except OSError:
            pass
        if data_list_for_receiving:
            for msg_by_client in data_list_for_receiving:
                try:
                    analyzer(get_message(msg_by_client),
                             messages_queue, msg_by_client)
                except:
                    SERVER_SIDE_LOGGER.info(f'client {msg_by_client.getpeername()} '
                                            f'disconnected from server')
                    clients_online.remove(msg_by_client)
        if messages_queue and data_list_to_send:
            message = {
                ACTION: MESSAGE,
                SENDER: messages_queue[0][0],
                TIME: time.time(),
                MESSAGE_TEXT: messages_queue[0][1]
            }
            del messages_queue[0]
            for client_from_queue in data_list_to_send:
                try:
                    send_message(client_from_queue, message)
                except:
                    SERVER_SIDE_LOGGER.info(f' client {client_from_queue.getpeername()} '
                                            f'disconnected from server')
                    clients_online.remove(client_from_queue)