|
|
@ -184,31 +184,20 @@ class TransportV2(Transport):
|
|
|
|
|
|
|
|
|
|
|
|
data = bytearray(msg.SerializeToString())
|
|
|
|
data = bytearray(msg.SerializeToString())
|
|
|
|
|
|
|
|
|
|
|
|
# Convert to unsigned in python2
|
|
|
|
dataheader = struct.pack(">LL", mapping.get_type(msg), len(data))
|
|
|
|
checksum = binascii.crc32(data) & 0xffffffff
|
|
|
|
data = dataheader + data
|
|
|
|
|
|
|
|
seq = -1
|
|
|
|
|
|
|
|
|
|
|
|
header1 = struct.pack(">L", self.session_id)
|
|
|
|
|
|
|
|
header2 = struct.pack(">LL", mapping.get_type(msg), len(data))
|
|
|
|
|
|
|
|
footer = struct.pack(">L", checksum)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data = header2 + data + footer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
first = True
|
|
|
|
|
|
|
|
while len(data):
|
|
|
|
while len(data):
|
|
|
|
if first:
|
|
|
|
if seq < 0:
|
|
|
|
# Magic character, header1, header2, data padded to 64 bytes
|
|
|
|
repheader = struct.pack(">BL", 0x01, self.session_id)
|
|
|
|
datalen = 63 - len(header1)
|
|
|
|
|
|
|
|
chunk = b'H' + header1 + \
|
|
|
|
|
|
|
|
data[:datalen] + b'\0' * (datalen - len(data[:datalen]))
|
|
|
|
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
# Magic character, header1, data padded to 64 bytes
|
|
|
|
repheader = struct.pack(">BLL", 0x02, self.session_id, seq)
|
|
|
|
datalen = 63 - len(header1)
|
|
|
|
datalen = 64 - len(repheader)
|
|
|
|
chunk = b'D' + header1 + \
|
|
|
|
chunk = repheader + data[:datalen] + b'\0' * (datalen - len(data[:datalen]))
|
|
|
|
data[:datalen] + b'\0' * (datalen - len(data[:datalen]))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self._write_chunk(chunk)
|
|
|
|
self._write_chunk(chunk)
|
|
|
|
data = data[datalen:]
|
|
|
|
data = data[datalen:]
|
|
|
|
first = False
|
|
|
|
seq += 1
|
|
|
|
|
|
|
|
|
|
|
|
def _read(self):
|
|
|
|
def _read(self):
|
|
|
|
if not self.session_id:
|
|
|
|
if not self.session_id:
|
|
|
@ -216,9 +205,8 @@ class TransportV2(Transport):
|
|
|
|
|
|
|
|
|
|
|
|
chunk = self._read_chunk()
|
|
|
|
chunk = self._read_chunk()
|
|
|
|
(session_id, msg_type, datalen, data) = self.parse_first(chunk)
|
|
|
|
(session_id, msg_type, datalen, data) = self.parse_first(chunk)
|
|
|
|
payloadlen = datalen + 4 # For the checksum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while len(data) < payloadlen:
|
|
|
|
while len(data) < datalen:
|
|
|
|
chunk = self._read_chunk()
|
|
|
|
chunk = self._read_chunk()
|
|
|
|
(next_session_id, next_data) = self.parse_next(chunk)
|
|
|
|
(next_session_id, next_data) = self.parse_next(chunk)
|
|
|
|
|
|
|
|
|
|
|
@ -227,64 +215,47 @@ class TransportV2(Transport):
|
|
|
|
|
|
|
|
|
|
|
|
data.extend(next_data)
|
|
|
|
data.extend(next_data)
|
|
|
|
|
|
|
|
|
|
|
|
data = data[:payloadlen] # Strip padding zeros
|
|
|
|
data = data[:datalen] # Strip padding
|
|
|
|
footer = data[-4:]
|
|
|
|
|
|
|
|
data = data[:-4]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
csum, = struct.unpack('>L', footer)
|
|
|
|
|
|
|
|
csum_comp = binascii.crc32(data) & 0xffffffff
|
|
|
|
|
|
|
|
if csum != csum_comp:
|
|
|
|
|
|
|
|
raise Exception("Message checksum mismatch. Expected %d, got %d" %
|
|
|
|
|
|
|
|
(csum_comp, csum))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (session_id, msg_type, data)
|
|
|
|
return (session_id, msg_type, data)
|
|
|
|
|
|
|
|
|
|
|
|
def parse_first(self, chunk):
|
|
|
|
def parse_first(self, chunk):
|
|
|
|
if chunk[0:1] != b"H":
|
|
|
|
|
|
|
|
raise Exception("Unexpected magic character")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
headerlen = struct.calcsize(">LLL")
|
|
|
|
headerlen = struct.calcsize(">BLLL")
|
|
|
|
(session_id, msg_type, datalen) = struct.unpack(">LLL", bytes(chunk[1:1 + headerlen]))
|
|
|
|
(magic, session_id, msg_type, datalen) = struct.unpack(">BLLL", bytes(chunk[:headerlen]))
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
raise Exception("Cannot parse header")
|
|
|
|
raise Exception("Cannot parse header")
|
|
|
|
|
|
|
|
if magic != 0x01:
|
|
|
|
data = chunk[1 + headerlen:]
|
|
|
|
raise Exception("Unexpected magic character")
|
|
|
|
return (session_id, msg_type, datalen, data)
|
|
|
|
return (session_id, msg_type, datalen, chunk[headerlen:])
|
|
|
|
|
|
|
|
|
|
|
|
def parse_next(self, chunk):
|
|
|
|
def parse_next(self, chunk):
|
|
|
|
if chunk[0:1] != b"D":
|
|
|
|
|
|
|
|
raise Exception("Unexpected magic characters")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
headerlen = struct.calcsize(">L")
|
|
|
|
headerlen = struct.calcsize(">BLL")
|
|
|
|
(session_id,) = struct.unpack(">L", bytes(chunk[1:1 + headerlen]))
|
|
|
|
(magic, session_id, sequence) = struct.unpack(">BLL", bytes(chunk[:headerlen]))
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
raise Exception("Cannot parse header")
|
|
|
|
raise Exception("Cannot parse header")
|
|
|
|
|
|
|
|
if magic != 0x02:
|
|
|
|
data = chunk[1 + headerlen:]
|
|
|
|
raise Exception("Unexpected magic characters")
|
|
|
|
return (session_id, data)
|
|
|
|
return (session_id, chunk[headerlen:])
|
|
|
|
|
|
|
|
|
|
|
|
def parse_session_open(self, chunk):
|
|
|
|
def parse_session_open(self, chunk):
|
|
|
|
if chunk[0:1] != b"O":
|
|
|
|
|
|
|
|
raise Exception("Unexpected magic character")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
headerlen = struct.calcsize(">L")
|
|
|
|
headerlen = struct.calcsize(">BL")
|
|
|
|
(session_id,) = struct.unpack(">L", bytes(chunk[1:1 + headerlen]))
|
|
|
|
(magic, session_id) = struct.unpack(">BL", bytes(chunk[:headerlen]))
|
|
|
|
except:
|
|
|
|
except:
|
|
|
|
raise Exception("Cannot parse header")
|
|
|
|
raise Exception("Cannot parse header")
|
|
|
|
|
|
|
|
if magic != 0x03:
|
|
|
|
|
|
|
|
raise Exception("Unexpected magic character")
|
|
|
|
return session_id
|
|
|
|
return session_id
|
|
|
|
|
|
|
|
|
|
|
|
def _session_begin(self):
|
|
|
|
def _session_begin(self):
|
|
|
|
self._write_chunk(bytearray(b'O' + b'\0' * 63))
|
|
|
|
self._write_chunk(bytearray(b'\x03' + b'\0' * 63))
|
|
|
|
self.session_id = self.parse_session_open(self._read_chunk())
|
|
|
|
self.session_id = self.parse_session_open(self._read_chunk())
|
|
|
|
|
|
|
|
|
|
|
|
def _session_end(self):
|
|
|
|
def _session_end(self):
|
|
|
|
header = struct.pack(">L", self.session_id)
|
|
|
|
header = struct.pack(">L", self.session_id)
|
|
|
|
self._write_chunk(bytearray(b'C' + header + b'\0' * (63 - len(header))))
|
|
|
|
self._write_chunk(bytearray(b'\x04' + header + b'\0' * (63 - len(header))))
|
|
|
|
if self._read_chunk()[0] != ord('C'):
|
|
|
|
if self._read_chunk()[0] != 0x04:
|
|
|
|
raise Exception("Expected session close")
|
|
|
|
raise Exception("Expected session close")
|
|
|
|
self.session_id = None
|
|
|
|
self.session_id = None
|
|
|
|
|
|
|
|
|
|
|
|