From 4cc2888cb087fdd29c6492be5d4604e48df18a7f Mon Sep 17 00:00:00 2001 From: ChillerDragon Date: Sat, 3 Jun 2023 10:43:09 +0200 Subject: [PATCH] Fix 0.6.5 connless header --- tests/packets6/conless_info6_test.py | 49 ++++++++++++++++++++++++++++ twnet_parser/packet.py | 18 +++++++--- 2 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 tests/packets6/conless_info6_test.py diff --git a/tests/packets6/conless_info6_test.py b/tests/packets6/conless_info6_test.py new file mode 100644 index 0000000..7bde4e3 --- /dev/null +++ b/tests/packets6/conless_info6_test.py @@ -0,0 +1,49 @@ +from twnet_parser.packet import parse6, TwPacket, PacketHeader6 +from twnet_parser.messages6.connless.info import MsgInfo + +def test_unpack_info(): + """ + Sent by a vanilla 0.6.5 server + copied from a real traffic capture + """ + data = \ + b'\xff\xff' \ + b'\xff\xff\xff\xff\xff\xff\xff\xff\x69\x6e\x66\x33\x32\x00\x30\x2e' \ + b'\x36\x2e\x35\x00\x75\x6e\x6e\x61\x6d\x65\x64\x20\x73\x65\x72\x76' \ + b'\x65\x72\x00\x42\x6c\x6d\x61\x70\x43\x68\x69\x6c\x6c\x00\x44\x4d' \ + b'\x00\x30\x00\x31\x00\x38\x00\x31\x00\x38\x00\x6e\x61\x6d\x65\x6c' \ + b'\x65\x73\x73\x20\x74\x65\x65\x00\x00\x2d\x31\x00\x30\x00\x31\x00' + + packet = parse6(data) + + assert packet.version == '0.6' + assert packet.header.ack == 0 + assert packet.header.num_chunks == None + assert packet.header.token == b'\xff\xff\xff\xff' + assert packet.header.flags.token is False + assert packet.header.flags.control is False + assert packet.header.flags.connless is True + assert packet.header.flags.resend is False + assert packet.header.flags.compression is False + + assert len(packet.messages) == 1 + + msg: MsgInfo = packet.messages[0] + + assert msg.message_name == 'connless.info' + assert msg.token == 2 + assert msg.version == '0.6.5' + assert msg.name == "unnamed server" + assert msg.map == "BlmapChill" + assert msg.game_type == "DM" + assert msg.flags == 0 + assert msg.num_players == 1 + assert msg.max_players == 8 + assert msg.num_clients == 1 + assert msg.max_clients == 8 + + repack = packet.pack() + assert repack == data + + + diff --git a/twnet_parser/packet.py b/twnet_parser/packet.py index e3e14bd..baac822 100644 --- a/twnet_parser/packet.py +++ b/twnet_parser/packet.py @@ -36,6 +36,7 @@ CHUNKFLAG7_RESEND = 2 PACKET_HEADER7_SIZE = 7 CONNLESS_PACKET_HEADER7_SIZE = 9 +CONNLESS_PACKET_HEADER6_SIZE = 6 class PacketFlags7(PrettyPrint): def __init__(self) -> None: @@ -115,9 +116,7 @@ class PacketHeader6(PrettyPrint): if self.num_chunks is None: self.num_chunks = 0 if self.flags.connless: - return bytes([ \ - ((PACKETFLAG6_CONNLESS<<2)&0xfc) | (self.connless_version&0x03) - ]) + self.token + self.response_token + return b'\xff\xff\xff\xff\xff\xff' packed = bytes([ \ ((flags << 2)&0xfc) | ((self.ack>>8)&0x03), \ self.ack&0xff, \ @@ -250,6 +249,15 @@ class PacketHeaderParser6(): flags.connless = (flag_bits & PACKETFLAG6_CONNLESS) != 0 flags.resend = (flag_bits & PACKETFLAG6_RESEND) != 0 flags.compression = (flag_bits & PACKETFLAG6_COMPRESSION) != 0 + if flags.connless: + # conless packets send FF + # as the flag byte + # but setting the connless bit basically means + # all other flags are false implicitly + flags.token = False + flags.control = False + flags.resend = False + flags.compression = False return flags def parse_ack(self, header_bytes: bytes) -> int: @@ -396,7 +404,7 @@ class PacketParser(): pck.header = PacketHeaderParser6().parse_header(data) header_size = PACKET_HEADER7_SIZE if pck.header.flags.connless: - header_size = CONNLESS_PACKET_HEADER7_SIZE + header_size = CONNLESS_PACKET_HEADER6_SIZE elif not pck.header.flags.token: header_size = 3 pck.payload_raw = data[header_size:] @@ -406,7 +414,7 @@ class PacketParser(): pck.messages.append(ctrl_msg) return pck if pck.header.flags.connless: - connless_msg: ConnlessMessage = match_connless6(data[header_size:17], data[17:]) + connless_msg: ConnlessMessage = match_connless6(data[header_size:14], data[14:]) pck.messages.append(connless_msg) return pck if pck.header.flags.compression: