def decode(cls, msg: ClientMessage) -> Optional[Awaitable]:
     debug(f"Handling packet: {msg}")
     func = getattr(
         cls,
         "decode_" + msg.name,
         lambda _, err=f"Unhandled packet type: {msg.name}": error(err))
     return func(msg)
Beispiel #2
0
 async def write_loop(self):
     while self.do_loop:
         if self.messages:
             msg = self.messages.pop(0)
             debug(f"Sending to client: {msg}")
             await self.client.send_all(msg)
         else:
             await sleep(0.00001)  # Allow other tasks to run
Beispiel #3
0
    async def serve_loop(self):
        data = b""
        run_again = False
        async with create_task_group() as tg:
            while self.do_loop:
                await sleep(0.0001)
                if not run_again:
                    try:
                        line = await self.client.receive_some(1024)
                    except ConnectionError:
                        line = b""

                    if line == b"":
                        try:
                            warn(f"Closing connection to {self.client.server_hostname}")
                        except TLSRequired:
                            pass

                        self.do_loop = False
                        break

                    data += self.cipher.decrypt(line)

                try:
                    rest_bytes, event = self.packet_decoder.decode(data)
                    event._conn = self
                    # debug(f"Left after parsing: {rest_bytes}")
                except AssertionError:
                    run_again = False
                    continue
                else:
                    data = rest_bytes
                    if data != b"":
                        run_again = True

                debug(event)

                for lock in self._locks:
                    if lock["name"] == event.event:
                        self._locks.remove(lock)
                        lock["result"] = event
                        await lock["lock"].set()
                        break

                if event.event == "handshake":
                    await self.handle_msg(event)
                else:
                    await tg.spawn(self.handle_msg, event)

            for lock in self._locks:
                await lock["lock"].set()
            if self.packet_decoder.status == 3:
                # User was logged in
                debug("Player left, removing from game...")
                await EventHandler.handle_event(PlayerLeaveEvent("player_leave", self.player))  # TODO: Use PlayerLeaveEvent
                PlayerRegistry.players.remove(self.player)
Beispiel #4
0
 def close_connection(self, reason: str = None):
     debug(f"Closing connection with reason: {reason}")
     if self.conn.do_loop and reason is not None:
         # Kick the player if possible.
         if self.conn.protocol_state == "play":
             self.send_packet("disconnect",
                              self.buffer_type.pack_chat(reason))
         elif self.conn.protocol_state == "login":
             self.send_packet(
                 "login_disconnect",
                 self.buffer_type.pack_chat(reason))
    async def serve_loop(self):
        data = b""
        run_again = False
        async with create_task_group() as tg:
            while self.do_loop:
                if not run_again:
                    try:
                        line = await self.client.receive_some(1024)
                    except ConnectionError:
                        line = b""

                    if line == b"":
                        try:
                            warn(f"Closing connection to {self.client.server_hostname}")
                        except TLSRequired:
                            pass

                        self.do_loop = False
                        break

                    data += self.cipher.decrypt(line)

                try:
                    msg = ClientMessage(self, data, self.protocol_version)
                except BufferUnderrun:
                    run_again = False
                    continue
                else:
                    data = data[msg.old_len:]
                    if data != b"":
                        run_again = True

                for lock in self._locks:
                    if lock["name"] == msg.name:
                        self._locks.remove(lock)
                        lock["result"] = msg.buffer
                        await lock["lock"].set()
                        break

                if msg.name == "handshake":
                    await self.handle_msg(msg)
                else:
                    await tg.spawn(self.handle_msg, msg)

            for lock in self._locks:
                await lock["lock"].set()
            if self.protocol_state == "play":
                # User was logged in
                debug("Player left, removing from game...")
                # TODO: Fix EventHandler
                # Requires: client_message.py:22
                # EventHandler.event_player_leave(self.player)
                PlayerRegistry.players.remove(self.player)
    def decode(self, packet: bytes):
        assert packet != b""

        self.buffer = io.BytesIO(packet)

        if packet[0] == 254:
            # TODO: handle 1.6 connection attempt
            data = self.decode_connection_16()
            return self.buffer.read(), data

        packet_length = self.read_varint()
        pos = self.buffer.tell()
        assert len(self.buffer.read()) >= packet_length
        self.buffer.seek(pos)

        packet_id = self.read_varint()
        # debug(f"Packet identifier: {packet_id}")
        if packet_id == 0:
            if self.status == 0:
                data = self.decode_handshake()
            elif self.status == 1:
                data = self.decode_status()
            elif self.status == 2:
                data = self.decode_start_login()
        elif packet_id == 1:
            if self.status == 1:
                data = self.decode_ping()
            elif self.status == 2:
                data = self.decode_encryption()

        try:
            data
        except NameError:
            debug(packet)
            raise Exception(
                f"Unhandled packet ID {packet_id} with data {self.buffer.read()} "
                f"while in state {self.status}")

        # Seek in case we leave some data by accident
        self.buffer.seek(pos + packet_length)
        return self.buffer.read(
        ), data  # read the buffer to return remaining bytes