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