예제 #1
0
    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()
예제 #2
0
    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()
예제 #3
0
 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())
예제 #4
0
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()
예제 #5
0
 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()
예제 #6
0
 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()
예제 #7
0
 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())
예제 #8
0
    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()
예제 #9
0
 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())
예제 #10
0
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}')
예제 #11
0
    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()
예제 #12
0
파일: LoginServer.py 프로젝트: lyrl/wowcore
    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()
예제 #13
0
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)
예제 #14
0
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()
예제 #15
0
파일: core.py 프로젝트: dv1x3r/amazing-core
 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()
예제 #16
0
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}')
예제 #17
0
 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()
예제 #18
0
    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
예제 #19
0
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()
예제 #20
0
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()