Fix 0.6.5 connless header

This commit is contained in:
ChillerDragon 2023-06-03 10:43:09 +02:00
parent 6c158c8841
commit 4cc2888cb0
2 changed files with 62 additions and 5 deletions

View file

@ -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

View file

@ -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: