Skip to content

Commit 95608f7

Browse files
committed
Add padding
1 parent 64b9177 commit 95608f7

File tree

4 files changed

+62
-52
lines changed

4 files changed

+62
-52
lines changed

README.rst

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ must end with `/` when provided as a full path.
100100

101101
All numbers are unsigned.
102102

103+
All values are aligned with respect to the start of the packet.
104+
103105
Status bytes are `0x01` for OK and `0x02` for error. Other values for error may be used for specific commands.
104106

105107
`0x10` - Read a file
@@ -110,14 +112,16 @@ Given a full path, returns the full contents of the file.
110112
The header is four fixed entries and a variable length path:
111113

112114
* Command: Single byte. Always `0x10`.
115+
* 1 Byte reserved for padding.
116+
* Path length: 16-bit number encoding the encoded length of the path string.
113117
* Chunk offset: 32-bit number encoding the offset into the file to start the first chunk.
114118
* Chunk size: 32-bit number encoding the amount of data that the client can handle in the first reply.
115-
* Path length: 16-bit number encoding the encoded length of the path string.
116119
* Path: UTF-8 encoded string that is *not* null terminated. (We send the length instead.)
117120

118121
The server will respond with:
119122
* Command: Single byte. Always `0x11`.
120123
* Status: Single byte.
124+
* 2 Bytes reserved for padding.
121125
* Chunk offset: 32-bit number encoding the offset into the file of this chunk.
122126
* Total length: 32-bit number encoding the total file length.
123127
* Chunk length: 32-bit number encoding the length of the read data up to the chunk size provided in the header.
@@ -126,6 +130,7 @@ The server will respond with:
126130
If the chunk length is smaller than the total length, then the client will request more data by sending:
127131
* Command: Single byte. Always `0x12`.
128132
* Status: Single byte. Always OK for now.
133+
* 2 Bytes reserved for padding.
129134
* Chunk offset: 32-bit number encoding the offset into the file to start the next chunk.
130135
* Chunk size: 32-bit number encoding the number of bytes to read. May be different than the original size. Does not need to be limited by the total size.
131136

@@ -141,20 +146,23 @@ Offset larger than the existing file size will introduce zeros into the gap.
141146
The header is four fixed entries and a variable length path:
142147

143148
* Command: Single byte. Always `0x20`.
149+
* 1 Byte reserved for padding.
150+
* Path length: 16-bit number encoding the encoded length of the path string.
144151
* Offset: 32-bit number encoding the starting offset to write.
145152
* Total size: 32-bit number encoding the total length of the file contents.
146-
* Path length: 16-bit number encoding the encoded length of the path string.
147153
* Path: UTF-8 encoded string that is *not* null terminated. (We send the length instead.)
148154

149155
The server will repeatedly respond until the total length has been transferred with:
150156
* Command: Single byte. Always `0x21`.
151157
* Status: Single byte. `0x01` if OK. `0x02` if any parent directory is missing or a file.
158+
* 2 Bytes reserved for padding.
152159
* Offset: 32-bit number encoding the starting offset to write. (Should match the offset from the previous 0x20 or 0x22 message)
153160
* Free space: 32-bit number encoding the amount of data the client can send.
154161

155162
The client will repeatedly respond until the total length has been transferred with:
156163
* Command: Single byte. Always `0x22`.
157164
* Status: Single byte. Always `0x01` for OK.
165+
* 2 Bytes reserved for padding.
158166
* Offset: 32-bit number encoding the offset to write.
159167
* Data size: 32-bit number encoding the amount of data the client is sending.
160168
* Data
@@ -170,6 +178,7 @@ Deletes the file or directory at the given full path. Directories must be empty
170178
The header is two fixed entries and a variable length path:
171179

172180
* Command: Single byte. Always `0x30`.
181+
* 1 Byte reserved for padding.
173182
* Path length: 16-bit number encoding the encoded length of the path string.
174183
* Path: UTF-8 encoded string that is *not* null terminated. (We send the length instead.)
175184

@@ -185,6 +194,7 @@ Creates a new directory at the given full path. If a parent directory does not e
185194
The header is two fixed entries and a variable length path:
186195

187196
* Command: Single byte. Always `0x40`.
197+
* 1 Byte reserved for padding.
188198
* Path length: 16-bit number encoding the encoded length of the path string.
189199
* Path: UTF-8 encoded string that is *not* null terminated. (We send the length instead.)
190200

@@ -200,19 +210,20 @@ Lists all of the contents in a directory given a full path. Returned paths are *
200210
The header is two fixed entries and a variable length path:
201211

202212
* Command: Single byte. Always `0x50`.
213+
* 1 Byte reserved for padding.
203214
* Path length: 16-bit number encoding the encoded length of the path string.
204215
* Path: UTF-8 encoded string that is *not* null terminated. (We send the length instead.)
205216

206217
The server will reply with n+1 entries for a directory with n files:
207218
* Command: Single byte. Always `0x51`.
208219
* Status: Single byte. `0x01` if the directory exists or `0x02` if it doesn't.
220+
* Path length: 16-bit number encoding the encoded length of the path string.
209221
* Entry number: 32-bit number encoding the entry number.
210222
* Total entries: 32-bit number encoding the total number of entries.
211223
* Flags: 32-bit number encoding data about the entries.
212-
* Bit 0: Set when the entry is a directory
213-
* Bits 1-7: Reserved
224+
- Bit 0: Set when the entry is a directory
225+
- Bits 1-7: Reserved
214226
* File size: 32-bit number encoding the size of the file. Ignore for directories. Value may change.
215-
* Path length: 16-bit number encoding the encoded length of the path string.
216227
* Path: UTF-8 encoded string that is *not* null terminated. (We send the length instead.) These paths are relative so they won't contain `/` at all.
217228

218229
The transaction is complete when the final entry is sent from the server. It will have entry number == total entries and zeros for flags, file size and path length.

adafruit_ble_file_transfer.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -144,16 +144,16 @@ def read(self, path, *, offset=0):
144144
chunk_size = CHUNK_SIZE
145145
encoded = (
146146
struct.pack(
147-
"<BIIH", FileTransferService.READ, offset, chunk_size, len(path)
147+
"<BxHII", FileTransferService.READ, len(path), offset, chunk_size
148148
)
149149
+ path
150150
)
151151
self._write(encoded)
152-
b = bytearray(struct.calcsize("<BBIII") + chunk_size)
152+
b = bytearray(struct.calcsize("<BBxxIII") + chunk_size)
153153
current_offset = offset
154154
content_length = None
155155
buf = None
156-
data_header_size = struct.calcsize("<BBIII")
156+
data_header_size = struct.calcsize("<BBxxIII")
157157
while content_length is None or current_offset < content_length:
158158
read = self._readinto(b)
159159
(
@@ -162,7 +162,7 @@ def read(self, path, *, offset=0):
162162
current_offset,
163163
content_length,
164164
_,
165-
) = struct.unpack_from("<BBIII", b)
165+
) = struct.unpack_from("<BBxxIII", b)
166166
if cmd != FileTransferService.READ_DATA:
167167
raise ProtocolError("Incorrect reply")
168168
if status != FileTransferService.OK:
@@ -178,7 +178,7 @@ def read(self, path, *, offset=0):
178178
if chunk_size == 0:
179179
break
180180
encoded = struct.pack(
181-
"<BBII",
181+
"<BBxxII",
182182
FileTransferService.READ_PACING,
183183
FileTransferService.OK,
184184
current_offset,
@@ -195,16 +195,16 @@ def write(self, path, contents, *, offset=0):
195195
total_length = len(contents) + offset
196196
encoded = (
197197
struct.pack(
198-
"<BIIH", FileTransferService.WRITE, offset, total_length, len(path)
198+
"<BxHII", FileTransferService.WRITE, len(path), offset, total_length
199199
)
200200
+ path
201201
)
202202
self._write(encoded)
203-
b = bytearray(struct.calcsize("<BBII"))
203+
b = bytearray(struct.calcsize("<BBxxII"))
204204
written = 0
205205
while written < len(contents):
206206
self._readinto(b)
207-
cmd, status, current_offset, free_space = struct.unpack("<BBII", b)
207+
cmd, status, current_offset, free_space = struct.unpack("<BBxxII", b)
208208
if status != FileTransferService.OK:
209209
raise RuntimeError()
210210
if (
@@ -213,7 +213,7 @@ def write(self, path, contents, *, offset=0):
213213
):
214214
self._write(
215215
struct.pack(
216-
"<BBII",
216+
"<BBxxII",
217217
FileTransferService.WRITE_DATA,
218218
FileTransferService.ERROR_PROTOCOL,
219219
0,
@@ -224,7 +224,7 @@ def write(self, path, contents, *, offset=0):
224224

225225
self._write(
226226
struct.pack(
227-
"<BBII",
227+
"<BBxxII",
228228
FileTransferService.WRITE_DATA,
229229
FileTransferService.OK,
230230
current_offset,
@@ -236,14 +236,14 @@ def write(self, path, contents, *, offset=0):
236236

237237
# Wait for confirmation that everything was written ok.
238238
self._readinto(b)
239-
cmd, status, offset, free_space = struct.unpack("<BBII", b)
239+
cmd, status, offset, free_space = struct.unpack("<BBxxII", b)
240240
if cmd != FileTransferService.WRITE_PACING or offset != total_length:
241241
raise ProtocolError()
242242

243243
def mkdir(self, path):
244244
"""Makes the directory and any missing parents"""
245245
path = path.encode("utf-8")
246-
encoded = struct.pack("<BH", FileTransferService.MKDIR, len(path)) + path
246+
encoded = struct.pack("<BxH", FileTransferService.MKDIR, len(path)) + path
247247
self._write(encoded)
248248

249249
b = bytearray(struct.calcsize("<BB"))
@@ -258,25 +258,25 @@ def listdir(self, path):
258258
"""Returns a list of tuples, one tuple for each file or directory in the given path"""
259259
paths = []
260260
path = path.encode("utf-8")
261-
encoded = struct.pack("<BH", FileTransferService.LISTDIR, len(path)) + path
261+
encoded = struct.pack("<BxH", FileTransferService.LISTDIR, len(path)) + path
262262
self._write(encoded)
263263
b = bytearray(self._service.raw.incoming_packet_length)
264264
i = 0
265265
total = 10 # starting value that will be replaced by the first response
266-
header_size = struct.calcsize("<BBIIIIH")
266+
header_size = struct.calcsize("<BBHIIII")
267267
while i < total:
268268
read = self._readinto(b)
269269
offset = 0
270270
while offset < read:
271271
(
272272
cmd,
273273
status,
274+
path_length,
274275
i,
275276
total,
276277
flags,
277278
file_size,
278-
path_length,
279-
) = struct.unpack_from("<BBIIIIH", b, offset=offset)
279+
) = struct.unpack_from("<BBHIIII", b, offset=offset)
280280
if cmd != FileTransferService.LISTDIR_ENTRY:
281281
raise ProtocolError()
282282
if i >= total:
@@ -294,7 +294,7 @@ def listdir(self, path):
294294
def delete(self, path):
295295
"""Deletes the file or directory at the given path. Directories must be empty."""
296296
path = path.encode("utf-8")
297-
encoded = struct.pack("<BH", FileTransferService.DELETE, len(path)) + path
297+
encoded = struct.pack("<BxH", FileTransferService.DELETE, len(path)) + path
298298
self._write(encoded)
299299

300300
b = bytearray(struct.calcsize("<BB"))

examples/ble_file_transfer_simpletest.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ def _read(client, filename, *, offset=0):
3434
while True:
3535
try:
3636
while ble.connected:
37-
print("connnnnneeeected")
3837
for connection in ble.connections:
3938
print(
4039
"services", connection._bleio_connection.discover_remote_services()
@@ -44,11 +43,9 @@ def _read(client, filename, *, offset=0):
4443
if not connection.paired:
4544
print("pairing")
4645
connection.pair()
47-
print("connecteeeeeddd")
4846
service = connection[adafruit_ble_file_transfer.FileTransferService]
4947
client = adafruit_ble_file_transfer.FileTransferClient(service)
5048
_write(client, "/hello.txt", "Hello world".encode("utf-8"))
51-
print("write sent")
5249
c = _read(client, "/hello.txt")
5350
print(len(c), c)
5451
client.mkdir("/world/")

0 commit comments

Comments
 (0)