async def handle_connection(self, reader: StreamReader, writer: StreamWriter): temp_ref = TempRef() world_packet_manager = WorldPacketManager(temp_ref=temp_ref, reader=reader, writer=writer) peername = writer.get_extra_info('peername') Logger.debug('[World Server]: Accept connection from {}'.format(peername)) Logger.info('[World Server]: trying to process auth session') auth = AuthManager(reader, writer, temp_ref=temp_ref, world_packet_manager=world_packet_manager) await auth.process(step=AuthStep.SECOND) self._register_tasks() while True: try: request = await asyncio.wait_for(reader.read(4096), timeout=1.0) if request: response = await asyncio.wait_for(world_packet_manager.process(request), timeout=1.0) if response: for packet in response: writer.write(packet) await writer.drain() except TimeoutError: continue except Exception as e: Logger.error('[World Server]: exception, {}'.format(e)) traceback.print_exc() break writer.close()
async def handle_connection(self, reader: StreamReader, writer: StreamWriter): peername = writer.get_extra_info('peername') Logger.info('[Login Server]: Accepted connection from {}'.format(peername)) temp_ref = TempRef() auth = AuthManager(reader, writer, temp_ref=temp_ref) await auth.process(step=AuthStep.FIRST) writer.close()
async def callback(reader: StreamReader, writer: StreamWriter): content = b'{ fail to parse' writer.write( f'content-length: {len(content)}\r\n\r\n'.encode() + content) raw_content_length = await reader.readline() content_length = int( raw_content_length.decode().split(':')[-1].strip()) self.empty_line = await reader.readline() raw_response = await reader.readexactly(content_length) writer.close() self.response = json.loads(raw_response.decode())
async def client_connected(reader: StreamReader, writer: StreamWriter, jobs_table: JobsTable): line = await read_long_line(reader) command = deserialize_command(line) reply = await handle_command(command, jobs_table) if reply is not None: reply_json = reply.serialize() writer.write(reply_json.encode()) writer.close() await writer.wait_closed()
async def client(reader: StreamReader, writer: StreamWriter): try: send_initialize(writer) response = await wait_for_response(reader) print(response) send_initialized(writer) response = await wait_for_response(reader) print(response) except Exception as err: self.err = err finally: writer.close()
async def callback(reader: StreamReader, writer: StreamWriter): content = json.dumps( {'message': 'Hello, World!'}).encode() writer.write( f'content-length: {len(content)}\r\n\r\n'.encode() + content) raw_content_length = await reader.readline() content_length = int( raw_content_length.decode().split(':')[-1].strip()) self.empty_line = await reader.readline() raw_response = await reader.readexactly(content_length) self.response = json.loads(raw_response.decode()) writer.close()
async def callback(reader: StreamReader, writer: StreamWriter): self.stub['method'] = 'this method does not exist' content = json.dumps(self.stub).encode() writer.write( f'content-length: {len(content)}\r\n\r\n'.encode() + content) raw_content_length = await reader.readline() content_length = int( raw_content_length.decode().split(':')[-1].strip()) self.empty_line = await reader.readline() raw_response = await reader.readexactly(content_length) writer.close() self.response = json.loads(raw_response.decode())
async def handle_connection(self, reader: StreamReader, writer: StreamWriter): self._register_tasks() temp_ref = TempRef() world_packet_manager = WorldPacketManager(temp_ref=temp_ref, reader=reader, writer=writer) Logger.info('[World Server]: trying to process auth session') auth = AuthManager(reader, writer, temp_ref=temp_ref, world_packet_manager=world_packet_manager, session_keys=self.session_keys) is_authenticated = await auth.process(step=AuthStep.SECOND) if is_authenticated: peer_name = writer.get_extra_info('peername') Logger.success( '[World Server]: Accept connection from {}'.format(peer_name)) while True: try: request = await asyncio.wait_for(reader.read(4096), timeout=0.01) if request: response = await asyncio.wait_for( world_packet_manager.process(request), timeout=0.01) if response: for packet in response: writer.write(packet) await writer.drain() except TimeoutError: pass except BrokenPipeError: pass except Exception as e: Logger.error('[World Server]: exception, {}'.format(e)) traceback.print_exc() break finally: await asyncio.sleep(0.01) writer.close()
async def callback(reader: StreamReader, writer: StreamWriter): self.stub['method'] = 'initialize' # If initialize is called without a `rootUri` param, it will raise, causing an InternalError del self.stub['params']['rootUri'] content = json.dumps(self.stub).encode() writer.write( f'content-length: {len(content)}\r\n\r\n'.encode() + content) raw_content_length = await reader.readline() content_length = int( raw_content_length.decode().split(':')[-1].strip()) self.empty_line = await reader.readline() raw_response = await reader.readexactly(content_length) writer.close() self.response = json.loads(raw_response.decode())
async def process(reader: StreamReader, writer: StreamWriter): host, port = writer.transport.get_extra_info('peername') print(f'Connected to: {host}:{port}') factory = CommandFactory(reader, writer) try: while True: line = (await reader.readline()).decode().strip() command = factory.get_command(line) await command.execute() except ConnectionResetError: writer.close() print(f'Disconnected from {host}:{port}')
async def async_http(reader: StreamReader, writer: StreamWriter) -> None: log.info('start callback') request_line: bytes = await reader.readline() if not request_line: writer.close() data = request_line.decode() request = await parse_http(data) response = handle_request(args, request) response.write_to(writer) await writer.drain() log.info('end callback') writer.close()
async def handle_connection(self, reader: StreamReader, writer: StreamWriter): peername = writer.get_extra_info('peername') Logger.info( '[Login Server]: Accepted connection from {}'.format(peername)) auth = AuthManager(reader, writer) while not reader.at_eof(): response = await auth.process() if not response: break Logger.warning('[Login Server]: closing...') writer.close()
async def make_client(reader: StreamReader, writer: StreamWriter): # get peer name peer_name = writer.get_extra_info(PEER_NAME) print(f"Recieved request for peer: {peer_name}") # get subscriber channel and add to list subscriber_chan = await read_msg(reader) # adding this writer to subscriber list as well SUBSCRIBER_LIST[subscriber_chan].append(writer) # spawn a async task for this writer to pull msgs off to queue and send to subscribers asyncio.create_task(msg_writer(writer, SEND_QUEUE[writer])) try: while True: chan = await read_msg(reader) if chan not in CHAN_QUEUE: # create a queue where we will enqueue msgs for given channel CHAN_QUEUE[chan] = Queue(maxsize=CHAN_QUEUE_SIZE) # spawn up new channel sender asyncio.create_task(channel_sender(chan)) data = await read_msg(reader) """ put the msg onto the queue for this channel channel sender will pull msg off this queue and then put it in the respective writers queues """ await CHAN_QUEUE[chan].put(data) except asyncio.CancelledError: print(f"remote peer closing : {peer_name}") writer.close() await writer.wait_closed() except asyncio.IncompleteReadError: print(f"remote peer {peer_name} disconnected") finally: print(f"remote peer {peer_name} closed") # remove our writer form channel list SUBSCRIBER_LIST[subscriber_chan].remove(writer) # close async task for this writer await SEND_QUEUE[writer].put(None)
async def callback(reader: StreamReader, writer: StreamWriter) -> None: while True: data = await reader.read(100) message = data.decode().strip() if message == 'calendar': answer = datetime.now().strftime("%d.%m.%Y %H:%M") elif message.startswith(ECHO_PREFIX): answer = message[len(ECHO_PREFIX):] elif message == 'stop': break else: answer = HELP_TEXT answer += NEWLINE writer.write(answer.encode()) await writer.drain() writer.close()
async def client_connected(self, reader: StreamReader, writer: StreamWriter): peer_name = writer.transport.get_extra_info('peername') log(LogLevel.INFO, f'{peer_name} connected') while True: try: data = await self.bit_protocol.read_data(reader) response = await self.process_message(peer_name, data) if response: await self.bit_protocol.write_message( writer, response.data) except ConnectionError as err: log(LogLevel.INFO, f'{peer_name} disconnected: {err}') break except NotImplementedError as err: log(LogLevel.ERROR, f'{peer_name}: {data}') except Exception as err: log(LogLevel.FATAL, f'{peer_name} disconnected: {data}') break writer.close()
async def process(reader: StreamReader, writer: StreamWriter): host, port = writer.transport.get_extra_info('peername') logging.info(f'Client {host}:{port} is connected!') factory = CommandFactory(reader, writer) try: while True: line = (await reader.readline()).decode().strip() command = factory.get_command(line) # while True: # line = input('=> ') # command: AbstractCommand = factory.get_command(line) # command.execute() await command.execute() except ConnectionResetError: writer.close() logging.info(f'Disconnected from {host}:{port}')
async def client_connected(self, reader: StreamReader, writer: StreamWriter): peer_name = writer.transport.get_extra_info('peername') log(f'{peer_name} connected', LogLevel.INFO) session = Session() try: while True: data = await self.bit_protocol.read_data(reader) try: response = await session.process_message(peer_name, data) except NotImplementedError as err: log(f'{peer_name} {err}', LogLevel.ERROR) except Exception as err: log(f'{peer_name} {err}', LogLevel.FATAL) raise err # print traceback somewhere if response: await self.bit_protocol.write_message( writer, response.data) except ConnectionError as err: log(f'{peer_name} disconnected: {err}', LogLevel.INFO) finally: writer.close()
async def initial_connection_check(self, reader: StreamReader, writer: StreamWriter): host_port = writer.get_extra_info('peername') new_user: Optional[User] = None try: # 1. send plain message writer.write(b'hello') await writer.drain() # 2. receive other's header try: received = await asyncio.wait_for(reader.read(BUFFER_SIZE), 5.0) if len(received) == 0: raise PeerToPeerError('empty msg receive') header = json.loads(received.decode()) except asyncio.TimeoutError: raise PeerToPeerError('timeout on other\'s header receive') except json.JSONDecodeError: raise PeerToPeerError( 'json decode error on other\'s header receive') # 3. generate new user user_header = UserHeader(**header) new_user = User(user_header, self.number, reader, writer, host_port, AESCipher.create_key(), SERVER_SIDE) self.number += 1 if new_user.header.name == V.SERVER_NAME: raise ConnectionAbortedError('Same origin connection') # 4. send my public key my_sec, my_pub = generate_keypair() send = json.dumps({'public-key': my_pub}).encode() await new_user.send(send) self.traffic.put_traffic_up(send) # 5. receive public key try: receive = await new_user.recv() self.traffic.put_traffic_down(receive) if len(receive) == 0: raise ConnectionAbortedError('received msg is zero.') data = json.loads(receive.decode()) except asyncio.TimeoutError: raise PeerToPeerError('timeout on public key receive') except json.JSONDecodeError: raise PeerToPeerError( 'json decode error on public key receive') # 6. encrypt and send AES key and header send = json.dumps({ 'aes-key': new_user.aeskey, 'header': self.get_server_header(), }) key = generate_shared_key(my_sec, data['public-key']) encrypted = AESCipher.encrypt(key, send.encode()) await new_user.send(encrypted) self.traffic.put_traffic_up(encrypted) # 7. receive accept signal try: encrypted = await new_user.recv() self.traffic.put_traffic_down(encrypted) except asyncio.TimeoutError: raise PeerToPeerError('timeout on accept signal receive') receive = AESCipher.decrypt(new_user.aeskey, encrypted) if receive != b'accept': raise PeerToPeerError(f"Not accept signal! {receive}") # 8. accept connection log.info( f"established connection as server from {new_user.header.name} {new_user.get_host_port()}" ) asyncio.ensure_future(self.receive_loop(new_user)) # server port's reachable check await asyncio.sleep(1.0) await self.check_reachable(new_user) return except (ConnectionAbortedError, ConnectionResetError) as e: msg = f"disconnect error {host_port} {e}" except PeerToPeerError as e: msg = f"peer2peer error {host_port} {e}" except Exception as e: msg = "InitialConnCheck: {}".format(e) log.error(msg, exc_info=True) # EXCEPTION! if new_user: # remove user self.remove_connection(new_user, msg) else: # close socket log.debug(msg) try: writer.write(msg.encode()) await writer.drain() except Exception: pass try: writer.close() except Exception: pass
class NeoProtocol(StreamReaderProtocol): def __init__(self, *args, **kwargs): """ Args: *args: **kwargs: """ sr = StreamReader() self._stream_reader_orig = sr self._stream_reader_wr = weakref.ref(sr) self._stream_writer = None self.client = node.NeoNode(self) self._loop = events.get_event_loop() super().__init__(sr) def connection_made(self, transport: asyncio.transports.BaseTransport) -> None: super().connection_made(transport) self._stream_writer = StreamWriter(transport, self, self._stream_reader_orig, self._loop) if self.client: asyncio.create_task(self.client.connection_made(transport)) def connection_lost(self, exc: Optional[Exception] = None) -> None: if self.client: task = asyncio.create_task(self.client.connection_lost(exc)) task.add_done_callback( lambda args: super(NeoProtocol, self).connection_lost(exc)) else: super().connection_lost(exc) async def send_message(self, message: Message) -> None: try: self._stream_writer.write(message.to_array()) await self._stream_writer.drain() except ConnectionResetError: print("connection reset") self.connection_lost(ConnectionResetError()) except ConnectionError: print("connection error") self.connection_lost(ConnectionError()) except asyncio.CancelledError: print("task cancelled, closing connection") # mypy can't seem to deduce that CancelledError still derives from Exception self.connection_lost(asyncio.CancelledError()) # type: ignore except Exception as e: print(f"***** woah what happened here?! {traceback.format_exc()}") self.connection_lost(Exception()) async def read_message(self, timeout: Optional[int] = 30) -> Optional[Message]: if timeout == 0: # avoid memleak. See: https://bugs.python.org/issue37042 timeout = None async def _read(): try: # readexactly can throw ConnectionResetError message_header = await self._stream_reader_orig.readexactly(3) payload_length = message_header[2] if payload_length == 0xFD: len_bytes = await self._stream_reader_orig.readexactly(2) payload_length, = struct.unpack("<H", len_bytes) elif payload_length == 0xFE: len_bytes = await self._stream_reader_orig.readexactly(4) payload_length, = struct.unpack("<I", len_bytes) elif payload_length == 0xFE: len_bytes = await self._stream_reader_orig.readexactly(8) payload_length, = struct.unpack("<Q", len_bytes) else: len_bytes = b'' if payload_length > Message.PAYLOAD_MAX_SIZE: raise ValueError("Invalid format") payload_data = await self._stream_reader_orig.readexactly( payload_length) raw = message_header + len_bytes + payload_data with serialization.BinaryReader(raw) as br: m = Message() try: m.deserialize(br) return m except Exception: logger.debug( f"Failed to deserialize message: {traceback.format_exc()}" ) return None except (ConnectionResetError, ValueError) as e: # ensures we break out of the main run() loop of Node, which triggers a disconnect callback to clean up self.client.disconnecting = True logger.debug( f"Failed to read message data for reason: {traceback.format_exc()}" ) return None except (asyncio.CancelledError, asyncio.IncompleteReadError): return None except Exception: # ensures we break out of the main run() loop of Node, which triggers a disconnect callback to clean up logger.debug(f"error read message 1 {traceback.format_exc()}") return None try: # logger.debug("trying to read message") return await asyncio.wait_for(_read(), timeout) except (asyncio.TimeoutError, asyncio.CancelledError): return None except Exception: logger.debug("error read message 2") traceback.print_exc() return None def disconnect(self) -> None: if self._stream_writer: self._stream_writer.close()
class NeoProtocol(StreamReaderProtocol): def __init__(self, *args, quality_check=False, **kwargs): """ Args: *args: quality_check (bool): there are times when we only establish a connection to check the quality of the node/address **kwargs: """ self._stream_reader = StreamReader() self._stream_writer = None nodemanager = kwargs.pop('nodemanager') self.client = NeoNode(self, nodemanager, quality_check) self._loop = events.get_event_loop() super().__init__(self._stream_reader) def connection_made(self, transport: asyncio.transports.BaseTransport) -> None: super().connection_made(transport) self._stream_writer = StreamWriter(transport, self, self._stream_reader, self._loop) if self.client: asyncio.create_task(self.client.connection_made(transport)) def connection_lost(self, exc: Optional[Exception] = None) -> None: if self.client: task = asyncio.create_task(self.client.connection_lost(exc)) task.add_done_callback( lambda args: super(NeoProtocol, self).connection_lost(exc)) else: super().connection_lost(exc) def eof_received(self) -> bool: self._stream_reader.feed_eof() self.connection_lost() return True # False == Do not keep connection open, this makes sure that `connection_lost` gets called. # return False async def send_message(self, message: Message) -> None: try: self._stream_writer.write(message.to_array()) await self._stream_writer.drain() except ConnectionResetError: # print("connection reset") self.connection_lost(ConnectionResetError) except ConnectionError: # print("connection error") self.connection_lost(ConnectionError) except asyncio.CancelledError: # print("task cancelled, closing connection") self.connection_lost(asyncio.CancelledError) except Exception as e: # print(f"***** woah what happened here?! {traceback.format_exc()}") self.connection_lost() async def read_message(self, timeout: int = 30) -> Message: if timeout == 0: # avoid memleak. See: https://bugs.python.org/issue37042 timeout = None async def _read(): try: message_header = await self._stream_reader.readexactly(24) magic, command, payload_length, checksum = struct.unpack( 'I 12s I I', message_header) # uint32, 12byte-string, uint32, uint32 payload_data = await self._stream_reader.readexactly( payload_length) payload, = struct.unpack('{}s'.format(payload_length), payload_data) except Exception: # ensures we break out of the main run() loop of Node, which triggers a disconnect callback to clean up self.client.disconnecting = True return None m = Message(magic, command.rstrip(b'\x00').decode('utf-8'), payload) if checksum != m.get_checksum(payload): logger.debug("Message checksum incorrect") return None else: return m try: return await asyncio.wait_for(_read(), timeout) except Exception: return None def disconnect(self) -> None: if self._stream_writer: self._stream_writer.close()