Import first working version
[fuse-aexplorer.git] / AEpy / AEMultipart.py
1 import struct
2
3
4
5 def recvHeader(session):
6     (type, data) = session.recvMsg()
7     # TODO: Check for type 1, as that means an error.
8     #       For example, a directory can't be listed because it doesn't exist.
9     assert type == 3
10     assert len(data) == 8
11
12     (datalen, pktsize) = struct.unpack('!LL', data)
13
14     return (datalen, pktsize)
15
16
17 def recvBlock(session):
18     # Send empty type 0 message to request next block
19     session.sendMsg(0, b'')
20
21     (type, data) = session.recvMsg()
22
23     if type == 1:
24         print('recvMultipartBlock: Host cancelled transfer.')
25         # Maybe TODO: Raise an exception
26         return (None, None)
27
28     if type == 4:
29         # Last block
30         assert len(data) == 0
31         return (None, None)
32
33     # Expect a data block
34     assert type == 5
35
36     # Any data block has the offset prepended,
37     # followed by up to PACKETSIZE-4 bytes of payload.
38     assert len(data) >= 4
39
40     (offset,) = struct.unpack('!L', data[0:4])
41
42     return (offset, data[4:])
43
44
45 def recv(session):
46     fullData = b''
47
48     (datalen, pktsize) = recvHeader(session)
49
50     offset = 0
51     data = b''
52     while data != None:
53         assert offset == len(fullData)
54         fullData += data
55
56         (offset, data) = recvBlock(session)
57
58     return fullData
59
60
61 def send(session, fullData):
62     # Wait for Amiga to request first block with type 0
63     (type, _) = session.recvMsg()
64
65     # TODO: Handle transfer abort (type 1)
66     # TODO: What happens when sending an ADF != 901120 bytes?
67     assert (type == 0) or (type == 8)
68
69     if type == 8:
70         # Does this confirm that we want to overwrite?
71         session.sendMsg(0, b'')
72
73     # Send length and block size
74     session.sendMsg(3, struct.pack('!LL', len(fullData), session.packetsize))
75
76     bytesSent = 0
77     while bytesSent < len(fullData):
78         # Wait for Amiga to request block with type 0
79         (type, _) = session.recvMsg()
80         assert type == 0
81
82         print("AEMultipart.send: " + str(bytesSent))
83
84         txlen = min(session.packetsize - 4, len(fullData) - bytesSent)
85         session.sendMsg(5, struct.pack('!L', bytesSent) + fullData[bytesSent : bytesSent+txlen])
86
87         bytesSent += txlen
88
89     # Wait for Amiga's type 0
90     (type, _) = session.recvMsg()
91     assert type == 0
92
93     # Finish transfer
94     session.sendMsg(4, b'')