X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=AEpy%2FAESession.py;fp=AEpy%2FAESession.py;h=145fff759266bb883d16d07d006109ccff510d19;hb=f06df88629c6ae1205f522148102a0c3d04d1cf2;hp=0000000000000000000000000000000000000000;hpb=8fc49cd8badf6ceb6b6dfe03deb961cadf61839f;p=fuse-aexplorer.git diff --git a/AEpy/AESession.py b/AEpy/AESession.py new file mode 100644 index 0000000..145fff7 --- /dev/null +++ b/AEpy/AESession.py @@ -0,0 +1,96 @@ +import binascii +import serial +import struct + + +class AESession: + def __init__(self, link): + self.link = link + self.seq = 1 + self.sendInit() + self.packetsize = 512 + + + def recvMsg(self): + rawHeader = self.link.recv(12) + if len(rawHeader) != 12: + print('recvMsg: len(rawHeader) == ' + str(len(rawHeader)) + ' data: ' + binascii.hexlify(rawHeader)) + #assert len(rawHeader) == 12 + + (type, datalen, seq, crc) = struct.unpack('!HHLL', rawHeader) + assert crc == (binascii.crc32(rawHeader[0:8]) & 0xffffffff) + # TODO: Send PkRs if CRC mismatches + + data = b'' + + if datalen > 0: + data = self.link.recv(datalen) + assert len(data) == datalen + + # Note: Python calculates signed CRCs. + # Thus, we parse the incoming CRC as signed. + datacrc = self.link.recv(4) + assert len(datacrc) == 4 + (datacrc,) = struct.unpack('!L', datacrc) + + assert datacrc == (binascii.crc32(data) & 0xffffffff) + # TODO: Send PkRs if CRC mismatches + + self.link.send(b'PkOk') + + # seq is currently ignored when receiving + return (type, data) + + + def sendMsg(self, type, data): + stream = struct.pack('!HHL', type, len(data), self.seq) + stream += struct.pack('!L', binascii.crc32(stream) & 0xffffffff) + + if len(data) > 0: + stream += data + stream += struct.pack('!L', binascii.crc32(data) & 0xffffffff) + + self.link.send(stream) + + # TODO: Re-send on 'PkRs' + assert self.link.recv(4) == b'PkOk' + + self.seq += 1; + + + + def sendInit(self): + self.sendMsg(2, b'Cloanto(r)') + # TBD: Password support. + # It is CRC32'd and the CRC is appended to the string above. + + # TODO: Recover from desynced state + #if not self.isAcked(): + # self.sendAck() + # return self.sendInit() + + (type, data) = self.recvMsg() + assert type == 2 + assert data.startswith(b'Cloanto') + + + def sendClose(self): + print('sendClose') + + self.sendMsg(0x6d, b'') + + (type, data) = self.recvMsg() + assert type == 0x0a + if data != b'\0\0\0\0\0': + print('sendClose: data == ' + binascii.hexlify(data)) + # Format of data returned: + # Byte 0: ? + # Byte 1: ? + # Byte 2: ? + # Byte 3: 00 - No error + # 06 - File no longer exists + # 1c - Timed out waiting for host to request next read block + # Byte 4: Path in case of error 06. + # Empty (null-terminated) otherwise? + # Null-terminated string. + #assert data == b'\0\0\0\0\0'