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