96 lines
2.5 KiB
Python
96 lines
2.5 KiB
Python
import struct
|
|
|
|
|
|
class UnknownArgumentType(Exception):
|
|
pass
|
|
|
|
|
|
class PacketMissingArgument(Exception):
|
|
pass
|
|
|
|
|
|
def decode_args(types, data):
|
|
args = []
|
|
for argtype in types:
|
|
if argtype == "I":
|
|
elem, data = data[:4], data[4:]
|
|
result = struct.unpack(">I", elem)[0]
|
|
|
|
elif argtype == "S":
|
|
length = struct.unpack(">H", data[:2])[0]
|
|
result = data[2:2 + length].decode("utf-8", "ignore")
|
|
data = data[2 + length:]
|
|
|
|
elif argtype == "B":
|
|
length = struct.unpack(">H", data[:2])[0]
|
|
result = data[2:2 + length]
|
|
data = data[2 + length:]
|
|
|
|
elif argtype == "G":
|
|
result, data = data[:5], data[5:]
|
|
# Convert result (5 bytes) to a long. Can't use
|
|
# struct.unpack(">Q", "\x00"*3 + result), since we
|
|
# can't rely on "long long" being available.
|
|
high, low = struct.unpack(">BI", result)
|
|
result = (high << 32) + low
|
|
|
|
elif argtype == "i":
|
|
length = struct.unpack(">H", data[:2])[0]
|
|
result = struct.unpack(">%sI" % length, data[2:2 + 4 * length])
|
|
data = data[2 + 4 * length:]
|
|
|
|
elif argtype == "s":
|
|
length = struct.unpack(">H", data[:2])[0]
|
|
data = data[2:]
|
|
result = []
|
|
while length:
|
|
slength = struct.unpack(">H", data[:2])[0]
|
|
result.append(data[2:2 + slength].decode("utf-8"))
|
|
data = data[2 + slength:]
|
|
length -= 1
|
|
|
|
else:
|
|
raise UnknownArgumentType(argtype)
|
|
|
|
args.append(result)
|
|
|
|
return args
|
|
|
|
|
|
def encode_args(types, args):
|
|
data = b""
|
|
|
|
for argtype in types:
|
|
if not args:
|
|
raise PacketMissingArgument
|
|
|
|
it = args[0]
|
|
del args[0]
|
|
|
|
if argtype == "I":
|
|
data += struct.pack(">I", it)
|
|
|
|
elif argtype == "S":
|
|
encoded = it.encode("utf-8")
|
|
data += struct.pack(">H", len(encoded))
|
|
data += encoded
|
|
|
|
elif argtype == "G":
|
|
data += struct.pack(">BI", it >> 32, it & 0xffffffff)
|
|
|
|
elif argtype == "s":
|
|
data += struct.pack(">H", len(it))
|
|
for it_elem in it:
|
|
encoded = it_elem.encode("utf-8")
|
|
data += struct.pack(">H", len(encoded))
|
|
data += encoded
|
|
|
|
else:
|
|
raise UnknownArgumentType(argtype)
|
|
|
|
return data
|
|
|
|
|
|
class Packet:
|
|
pass
|