From 556c9dcc695287a06f26d4a8c3754120347b423c Mon Sep 17 00:00:00 2001 From: HipsterCat Date: Fri, 15 Feb 2019 01:49:34 +0100 Subject: [PATCH] Entering ingame --- dpnet/netserver.py | 208 ++++++++++++++++++++++++++++++++++++++++--- dpnet/packet.py | 2 +- dpnet/session.py | 4 +- plugins/greetings.py | 16 +++- server.py | 2 +- 5 files changed, 215 insertions(+), 17 deletions(-) diff --git a/dpnet/netserver.py b/dpnet/netserver.py index e13efea..8cc8f51 100644 --- a/dpnet/netserver.py +++ b/dpnet/netserver.py @@ -66,7 +66,6 @@ class Netserver(asyncio.DatagramProtocol): pass def datagram_received(self, data, addr): - logger.debug("%s:%s > %s", addr[0], addr[1], data.hex()) loop = asyncio.get_event_loop() loop.create_task(self.handle_new_packet(addr, data)) @@ -78,6 +77,7 @@ class Netserver(asyncio.DatagramProtocol): elif len(bData) >= 12 and first & CFrame.PACKET_COMMAND_FRAME: await self.handle_new_cframe(addr, pPacket) elif first == EnumQuery.LEAD or first == EnumResponse.LEAD: + logger.debug("%s:%s > %s (ENUM)", addr[0], addr[1], bData.hex()) await self.handle_new_enum(addr, pPacket) else: logger.error("Unknown frame received") @@ -90,7 +90,7 @@ class Netserver(asyncio.DatagramProtocol): # EnumQuery try: eq = EnumQuery(data) - logger.debug("Got EnumQuery, sending EnumResponse") + #logger.debug("Got EnumQuery, sending EnumResponse") er = EnumResponse() er.Payload = eq.Payload er.ApplicationDescSize = 0x50 @@ -109,6 +109,7 @@ class Netserver(asyncio.DatagramProtocol): # \x00\x00\x00\x01: # \x9c\x53\xf4\xdd: Three Way Island - Canyons # \x1e\xe9\x39\xe1: Still Winter + # \x9f\xb2\x42\xec: test er.ApplicationReservedData += self.server.currentmap.mapname.encode("ascii")''' appdata = Packet() @@ -123,7 +124,7 @@ class Netserver(asyncio.DatagramProtocol): appdata.write(b'\x00\x00') # original: 0000 - does not seem to affect client appdata.putShort(self.server.detente_time) appdata.write( - b'\x9c\x53\xf4\xdd') # Seems to be a checksum of current map OR linked to the number of chars in the map name + b'\x9f\xb2\x42\xec') # Seems to be a checksum of current map OR linked to the number of chars in the map name appdata.write(self.server.currentmap.mapname.encode("ascii")) appdata.write(b'\x00' * (32 - len(self.server.currentmap.mapname))) er.ApplicationReservedData = appdata.getvalue() @@ -147,6 +148,7 @@ class Netserver(asyncio.DatagramProtocol): session = self.get_session(addr) player = self.get_player(session) if session else None if cframe.ExtOpCode == CFrame.FRAME_EXOPCODE_CONNECT: + logger.debug("%s:%s > %s (CFRAME CONNECT)", addr[0], addr[1], data.getvalue().hex()) # CONNECT CFRAME if session and session.Full: logger.error("Session %s:%s was already fully connected. Ignoring.", session.ip, session.port) @@ -182,6 +184,7 @@ class Netserver(asyncio.DatagramProtocol): self.server.create_temp_player(player) #session.setup_Connect_Retry_Timer() elif cframe.ExtOpCode == CFrame.FRAME_EXOPCODE_CONNECTED: + logger.debug("%s:%s > %s (CFRAME CONNECTED)", addr[0], addr[1], data.getvalue().hex()) # CONNECTED CFRAME # check if already sent a CONNECT packet logger.debug("%s:%s sent back a CONNECTED CFrame.", session.ip, session.port) @@ -198,6 +201,7 @@ class Netserver(asyncio.DatagramProtocol): session.send_dframe_keepalive() elif cframe.ExtOpCode == CFrame.FRAME_EXOPCODE_SACK: + logger.debug("%s:%s > %s (CFRAME SACK)", addr[0], addr[1], data.getvalue().hex()) if not session or not session.Full: logger.error("Received a SACK packet for a non fully connected session") return @@ -227,6 +231,7 @@ class Netserver(asyncio.DatagramProtocol): return #logger.debug("Got a CFrame POLL. Replying with a SACK.") # must send back a ACK + session.send_cframe_sack() except Exception: logger.error("Should have been a CFRAME but could not parse it") @@ -236,7 +241,7 @@ class Netserver(asyncio.DatagramProtocol): async def handle_new_dframe(self, addr, data): try: dframe = DFrame(data) - logger.debug("Received DFRAME") + #logger.debug("Received DFRAME") session = next((x for x in self.addrs if x.ip == addr[0] and x.port == addr[1]), None) if not session: logger.debug("%s sent a DFRAME without having sent a CONNECT before. GTFO.", addr) @@ -267,6 +272,11 @@ class Netserver(asyncio.DatagramProtocol): pass #session.send_dframe_keepalive() + if dframe.Command & DFrame.PACKET_COMMAND_POLL: + #logger.debug("Sending SACK") + #session.send_cframe_sack() + pass + session.next_expected_seq += 1 if dframe.Payload: await self.handle_game_packet(session, dframe.Payload) @@ -279,6 +289,9 @@ class Netserver(asyncio.DatagramProtocol): async def handle_game_packet(self, session, payload): player = self.get_temp_player(session) + logger.debug("%s:%s > %s (GAMEDATA)", session.ip, session.port, payload.hex()) + #logger.debug("OPCODE: %s VALUES: %s", struct.pack("= 0x5c: + await player.session.send_gamedata(bytes.fromhex( + "04" + struct.pack("= 4 and rawbytes[0] & DFrame.PACKET_COMMAND_DATA: self.next_send += 1 @@ -61,6 +60,7 @@ class Session: dframe.Seq = self.next_send dframe.NRcv = self.next_expected_seq dframe.Payload = bPayload + logger.debug(" %s:%s < %s (GAMEDATA)", self.ip, self.port, bPayload.hex()) self.send(dframe) if acknow: await self.lock.acquire() @@ -71,6 +71,7 @@ class Session: response.ExtOpCode = CFrame.FRAME_EXOPCODE_CONNECTED response.RspId = connect.MsgID response.SessID = connect.SessID + logger.debug(" %s:%s < %s (CFRAME CONNECTED)", self.ip, self.port, response.to_packet().getvalue().hex()) self.send(response) def send_cframe_sack(self): @@ -80,6 +81,7 @@ class Session: r.Flags = CFrame.SACK_FLAGS_RESPONSE r.NRecv = self.next_expected_seq r.NSeq = self.next_send + logger.debug(" %s:%s < %s (CFRAME SACK)", self.ip, self.port, r.to_packet().getvalue().hex()) self.send(r) def send_dframe_keepalive(self): diff --git a/plugins/greetings.py b/plugins/greetings.py index 392b542..d3f2dd0 100644 --- a/plugins/greetings.py +++ b/plugins/greetings.py @@ -1,9 +1,23 @@ +import random +import asyncio +import struct + class Greetings: def __init__(self, server): self.server = server + self.messages = ["Welcome %s!", "Beware! %s has arrived!", "A wild %s appears", "%s has come and is ready to pwn."] async def on_player_join(self, player): - await self.server.broadcast_message("Welcome "+player.name+"!") + await self.server.broadcast_message(random.choice(self.messages) % player.name) + #await Greetings.send_ping(player) + + @staticmethod + async def send_ping(player): + while 1: + for ping in range(0, 999): + await player.session.send_gamedata(b"\x2f\x02\x00\x00" + struct.pack("