async def submit_message(stream_for_write, msg):
    reader, writer = stream_for_write
    msg = sanitize_message(msg)
    end_of_msg = ''
    writer.write(str.encode(f'{msg}\n'))
    writer.write(str.encode(f'{end_of_msg}\n'))
    await writer.drain()
    if msg:
        broadcast_logger.info(f'MESSAGE SENDED "{msg}"')
async def handle_connection(host, port_sender, port_listener, token):
    connection_timeout_seconds = 15
    connection_max_retry = 1000
    ping_pong_connection_delay_seconds = 70

    async with create_handy_nursery() as nursery:
        async_queues["status_updates_queue"].put_nowait(
            gui.ReadConnectionStateChanged.INITIATED)
        async_queues["status_updates_queue"].put_nowait(
            gui.SendingConnectionStateChanged.INITIATED)
        if not token:
            _, stream_for_write = await \
                get_connection_streams(host, port_sender, port_listener,
                                       connection_timeout_seconds,
                                       connection_max_retry)
            new_username = get_new_username()
            if new_username:
                token, name = await register(stream_for_write, new_username)
                await write_to_file(f"\nTOKEN='{token}'", filepath='.env')
                async_queues["watchdog_queue"].put_nowait(
                    f"Connection is alive. Source: Registration as {name}")
                broadcast_logger.info(
                    f'REGISTER AS "{name}" WITH TOKEN "{token}"')

        nursery.start_soon(
            gui.draw(async_queues["messages_queue"],
                     async_queues["sending_queue"],
                     async_queues["status_updates_queue"]))

        stream_for_read, stream_for_write = await \
            get_connection_streams(host, port_sender, port_listener,
                                   connection_timeout_seconds,
                                   connection_max_retry)
        nursery.start_soon(
            ping_pong_connection(timeout=connection_timeout_seconds,
                                 delay=ping_pong_connection_delay_seconds,
                                 stream_for_write=stream_for_write))

        nursery.start_soon(
            start_chat_process(stream_for_write=stream_for_write,
                               stream_for_read=stream_for_read,
                               token=token))

        nursery.start_soon(watch_for_connection(connection_timeout_seconds))

        async_queues["status_updates_queue"].put_nowait(
            gui.SendingConnectionStateChanged.ESTABLISHED)
        async_queues["status_updates_queue"].put_nowait(
            gui.ReadConnectionStateChanged.ESTABLISHED)
async def authorise(stream_for_write, token):
    reader, writer = stream_for_write
    await reader.readline()
    writer.write(str.encode(f'{token}\n'))
    await writer.drain()
    reply = await reader.readline()
    try:
        authorization_success_msg = json.loads(reply.decode())
        if not authorization_success_msg:
            return None
        nickname = authorization_success_msg['nickname']
        broadcast_logger.info(f'AUTORIZED AS "{nickname}"')
        return reader, writer, nickname
    except json.decoder.JSONDecodeError:
        return None
async def start_chat_process(stream_for_read, stream_for_write, token):
    authorisation_data = await authorise(stream_for_write, token)
    if not authorisation_data:
        broadcast_logger.info(f'NOT AUTORIZED WITH TOKEN "{token}"')
        raise InvalidTokenError
    _, _, nickname = authorisation_data
    event = gui.NicknameReceived(nickname)
    for _history in await load_log_from_file('chat_logs'):
        async_queues["messages_queue"].put_nowait(_history.strip())
    async_queues["status_updates_queue"].put_nowait(event)
    async_queues["watchdog_queue"].put_nowait(f"Connection is alive. Source: "
                                              f"Authorisation as {nickname}")
    async with create_handy_nursery() as nursery:
        nursery.start_soon(broadcast_chat(stream_for_read, stream_for_write))
        nursery.start_soon(send_message(stream_for_write))
        nursery.start_soon(save_history())
async def get_connection_streams(host, port_sender, port_listener,
                                 connection_timeout_seconds,
                                 connection_max_retry):
    for counter in range(1, connection_max_retry + 1):
        try:
            stream_for_write = await asyncio.open_connection(host=host,
                                                             port=port_sender)
            stream_for_read = await asyncio.open_connection(host=host,
                                                            port=port_listener)
            if stream_for_read and stream_for_write:
                broadcast_logger.info('CONNECTION SUCCESSFUL')
            return stream_for_read, stream_for_write
        except (socket.gaierror, ConnectionResetError, ConnectionError,
                ConnectionRefusedError, TimeoutError):
            broadcast_logger.info(f'CONNECTION ERROR! '
                                  f'TRY CONNECT {counter} '
                                  f'OF {connection_max_retry}')

            await asyncio.sleep(connection_timeout_seconds)
            if counter == connection_max_retry:
                raise MaximumRetryConnectionError