From 0cd474601a480e6830a7f07b8c32383ed295a3b1 Mon Sep 17 00:00:00 2001 From: Sunpy Date: Sat, 4 Apr 2020 23:12:24 +0200 Subject: [PATCH] Packet handling order of operations notes --- notes/packet_writeup.md | 19 +++++++++++++++++++ sampy/client/player.py | 12 ++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/notes/packet_writeup.md b/notes/packet_writeup.md index 611b4ba..c788f02 100644 --- a/notes/packet_writeup.md +++ b/notes/packet_writeup.md @@ -11,6 +11,25 @@ ## Shared * Can be internal packet +* If packet is smaller then 3 bytes; forward to plugin handlers (*)before handling them (len(data) <= 2) + +## Order of operations +1. Check if banned (if true, cancel rest and handle) [^1] +2. If first byte in data is (0x19, 0x1d, 0x1f, 0x24 or 0x18) custom code flow required [^2] +3. HandleSocketReceiveFromConnectedPlayer (cancel rest if handled) +4. Check if cheat (modified) packet (unexpected at this time, there are some packets we can expect) [^3] + +[^1]: this could be changed in custom implementation (dont allow inital connection instead) +[^2]: if (0x18 and length == 2) or (0x19 and length <= 2): + handle packet and return +elif (0x1d or 0x1f or 0x24) and length <= 2: + handle packet, but continue +[^3]: if ((0x18 or 0x1a) and length <= 3) or ((0x19 or 0x1d) and length <= 2) or + ((0x08 or 0x07 or 0x27) and length >= 5) or (0x37 and length < 400): + We expect this packet, everything is ok? +else: + This is a cheat (modified / injected) packet that should not arrive at this time + Send a packet to client that you received a modified packet (0x26) # Internal packet |condition|name|bit length|type|notes| diff --git a/sampy/client/player.py b/sampy/client/player.py index 04b6013..2de6713 100644 --- a/sampy/client/player.py +++ b/sampy/client/player.py @@ -8,16 +8,19 @@ logger = logging.getLogger(__name__) STATE_CONNECTING = 0 STATE_AUTH = 1 +STATE_CONNECTED = 2 class PlayerClient(BaseClient): def __init__(self, server: "__ServerInstance__", ip: str, port: int): super().__init__(server, ip, port) logger.debug("Client resolved to PlayerClient") + # TODO: check if banned and handle here + self.state = STATE_CONNECTING self.handlers = { - 0x18: self.on_connection_request, + STATE_CONNECTING: self.on_connection_request, #0x00: self.on_state_dependent_handle } @@ -26,10 +29,7 @@ class PlayerClient(BaseClient): try: packet = self.server.compressor.decompress(packet) - - - - await self.handlers.get(packet[0], self.on_unimplemented)(packet) + await self.handlers.get(self.state, self.on_unimplemented)(packet) except Exception as err: logger.error(err) @@ -54,7 +54,7 @@ class PlayerClient(BaseClient): logger.debug("challenge: passed") - self.state = STATE_AUTH + self.state = STATE_CONNECTED await self.send(b"\x19\x00") # Challenge passed async def parse_internal_packet(self, packet: bytes):