jk, just continue to build ontop (added better debug prints, colors, bitstream additions, continuation for bitstream parsing, and currently working on acks)

This commit is contained in:
2021-05-10 22:45:41 +02:00
parent 4812d9c35d
commit c258c520a5
10 changed files with 503 additions and 130 deletions

185
test.py
View File

@@ -1,85 +1,128 @@
from sampy.raknet.bitstream import Bitstream
from sampy.client.player import PlayerClient
bitstream = Bitstream(b"\x00" * 4)
MAGIC_BYTES = b"\x01\xff\x02"
MAGIC_BITS = [int(bit) for bit in " ".join([format(byte, "08b") for byte in MAGIC_BYTES]) if bit in ("0", "1")]
fail = 0
import struct
def print_pretty(prefix, msg):
prefix += " " * (40 - len(prefix))
print(prefix, msg)
class Packet:
def __init__(self, data: bytes, is_client: bool):
self.data = data
self.is_client = is_client
self.bitstream = Bitstream(bytearray.fromhex(self.data))
def reset_bitstream():
bitstream._buffer = bytearray(b"\x00" * len(bitstream._buffer))
bitstream._offset = 0
PACKETS = [
Packet("18 69 69", True),
Packet("1a 18 be", False),
Packet("18 71 d7", True),
Packet("19 00", False),
Packet("00 00 43 80 0b", True),
Packet("e3 00 00", False),
Packet("00 00 42 98 0c 11 33 30 45 39 33 39 33 33 36 39 42 35 36 38 43 32 00", False)
]
def test_write_bit(var_bits):
global fail
print_pretty("<Test bitstream.write_bit:in>", bitstream.pretty())
for bit in var_bits:
if not bitstream.write_bit(bit):
print_pretty("<Test bitstream.write_bit>", "Failed")
fail += 1
print_pretty("<Test bitstream.write_bit:out>", bitstream.pretty())
#client = PlayerClient(None, "127.0.0.1", 7777)
#client.state = 1
def test_read_bit(var_compare_bits):
global fail
print_pretty("<Test bitstream.read_bit:in>", bitstream.pretty())
for bit in var_compare_bits:
ok, bit2 = bitstream.read_bit()
if not ok:
print_pretty("<Test bitstream.read_bit>", "Failed (ok)")
fail += 1
continue
if bit2 != bit:
print_pretty("<Test bitstream.read_bit>", "Failed (match)")
fail += 1
continue
print_pretty("<Test bitstream.read_bit:out>", bitstream.pretty())
def pbs(bitstream: Bitstream, prefix: str = ""):
print(prefix, bitstream.pretty())
def test_write(var_bytes):
global fail
print_pretty("<Test bitstream.write:in>", bitstream.pretty())
if not bitstream.write(var_bytes, len(var_bytes) << 3):
print_pretty("<Test bitstream.write>", "Failed")
fail += 1
print_pretty("<Test bitstream.write:out>", bitstream.pretty())
def deserialize(bitstream: Bitstream): # TODO: Something weird with range thing DS_RangeList.h@L92
success, count = bitstream.read_compressed(0x10, True)
if not success:
return False
count, = struct.unpack(b"<H", count)
def test_read(var_compare_bytes):
global fail
print_pretty("<Test bitstream.read:in>", bitstream.pretty())
ok, bytez = bitstream.read(len(var_compare_bytes) << 3)
if ok:
print(var_compare_bytes, bytez)
if bytez != var_compare_bytes:
print_pretty("<Test bitstream.read>", "Failed (match)")
fail += 1
else:
print_pretty("<Test bitstream.read>", "Failed (ok)")
fail += 1
print_pretty("<Test bitstream.read:out>", bitstream.pretty())
min, max = 0, 0
for i in range(count):
_, max_equal_to_min = bitstream.read_bit()
success, min = bitstream.read_bits(0x10)
if not success:
return False
min, = struct.unpack(b"<H", min)
def test_rw_bit(offset):
bitstream._offset = offset
test_write_bit(MAGIC_BITS)
bitstream._offset = offset
test_read_bit(MAGIC_BITS)
if not max_equal_to_min:
success, max = bitstream.read_bits(0x10)
if not success:
return False
max, = struct.unpack(b"<H", max)
def test_rw_bytes(offset):
bitstream._offset = offset
test_write(MAGIC_BYTES)
bitstream._offset = offset
test_read(MAGIC_BYTES)
if max < min:
return False
else:
max = min
# Test all edges
for i in range(9):
reset_bitstream()
test_rw_bit(i)
return True
reset_bitstream()
def on_player_packet(packet: bytes):
bitstream = Bitstream(packet)
pbs(bitstream, "Created")
for i in range(9):
reset_bitstream()
test_rw_bytes(i)
_, has_acks = bitstream.read_bit()
pbs(bitstream, "has_acks")
if has_acks:
print("has_acks: True")
if not deserialize(bitstream):
return False
return
handled = handle_internal_packet(bitstream)
if not handled:
print("Internal packet were not handled")
def handle_internal_packet(bitstream: Bitstream) -> bool:
if bitstream.length - bitstream.offset < 0x10:
return False
print("Failed: %d" % fail)
_, message_number = bitstream.read_bits(0x10)
pbs(bitstream, "message_number")
_, reliability = bitstream.read_bits(0x04)
pbs(bitstream, "reliability")
if reliability in (7, 9, 10):
success, ordering_channel = bitstream.read_bits(0x05)
pbs(bitstream, "ordering_channel")
if not success:
return False
success, ordering_index = bitstream.read_bits(0x10)
pbs(bitstream, "ordering_index")
if not success:
return False
_, is_split_packet = bitstream.read_bit()
pbs(bitstream, "is_split_packet")
if is_split_packet:
print("Skipping split packet")
return
# TODO: set global split_packet index and count back to 0
# Something I dont understand yet
# TODO: ReadCompressed
#bitstream.offset += 1
success, data_bit_length = bitstream.read_compressed(0x10, True)
pbs(bitstream, "data_bit_length")
if not success:
return False
#_, unknown = bitstream.read(0x01)
#_, bit_length = bitstream.read(0x08)
##
#logger.debug("bit_length: %d" % bit_length)
#logger.debug("bitstream: %s" % bitstream)
data_bit_length, = struct.unpack(b"<H", data_bit_length)
print("data_bit_length:", data_bit_length)
# TODO: ReadAlignedBytes
#_, data = bitstream.read(bit_length)
_, data = bitstream.read_aligned_bytes((data_bit_length + 7) >> 3)
pbs(bitstream, "data")
print("data: %s" % data)
on_player_packet(PACKETS[-2].bitstream._buffer)