@@ -36,6 +36,29 @@ def find_dir(path):
3636 i += 1
3737 return parent
3838
39+ def read_packets (buf , * , target_size = None ):
40+ if not target_size :
41+ target_size = len (buf )
42+ total_read = 0
43+ buf = memoryview (buf )
44+ while total_read < target_size :
45+ read = service .raw .readinto (buf [total_read :])
46+ total_read += read
47+
48+ return read
49+
50+ def write_packets (buf ):
51+ service .raw .write (buf )
52+
53+ def read_complete_path (starting_path , total_length ):
54+ path = bytearray (total_length )
55+ current_path_length = len (starting_path )
56+ remaining_path = total_length - current_path_length
57+ path [:current_path_length ] = starting_path
58+ if remaining_path > 0 :
59+ read_packets (memoryview (path )[current_path_length :], target_size = remaining_path )
60+ return str (path , "utf-8" )
61+
3962packet_buffer = bytearray (256 )
4063out_buffer = bytearray (256 )
4164while True :
@@ -55,58 +78,47 @@ def find_dir(path):
5578 if command == FileTransferService .WRITE :
5679 content_length , path_length = struct .unpack_from (">IH" , p , offset = 1 )
5780 path_start = struct .calcsize (">BIH" )
58- path = str (p [path_start :path_start + path_length ], "utf-8" )
81+ path = read_complete_path (p [path_start :], path_length )
5982 contents_read = 0
6083 contents = bytearray (content_length )
61- print ("write" , content_length , path )
6284 d = find_dir (path )
6385 filename = path .split ("/" )[- 1 ]
64- print (filename )
6586 while contents_read < content_length :
6687 next_amount = min (10 , content_length - contents_read )
67- #print(FileTransferService.WRITE, FileTransferService.OK)
68- service .raw .write (struct .pack (">BBI" , FileTransferService .WRITE , FileTransferService .OK , next_amount ))
69- read = service .raw .readinto (packet_buffer )
70- while read == 0 :
71- read = service .raw .readinto (packet_buffer )
88+ header = struct .pack (">BBI" , FileTransferService .WRITE , FileTransferService .OK , next_amount )
89+ write_packets (header )
90+ read = read_packets (packet_buffer , target_size = next_amount )
7291 contents [contents_read :contents_read + read ] = packet_buffer [:read ]
7392 contents_read += read
74- print (read , packet_buffer [:read ])
7593 d [filename ] = contents
7694
7795 elif command == adafruit_ble_file_transfer .FileTransferService .READ :
7896 free_space , path_length = struct .unpack_from (">IH" , p , offset = 1 )
7997 path_start = struct .calcsize (">BIH" )
80- path = str (p [path_start :path_start + path_length ], "utf-8" )
81- print ("read" , path )
98+ path = read_complete_path (p [path_start :], path_length )
8299 d = find_dir (path )
83100 filename = path .split ("/" )[- 1 ]
84101 if filename not in d :
85102 print ("missing path" )
86- service .raw .write (struct .pack (">BBII" , FileTransferService .READ , FileTransferService .ERR , 0 , 0 ))
103+ error_response = struct .pack (">BBII" , FileTransferService .READ , FileTransferService .ERR , 0 , 0 )
104+ write_packets (error_response )
87105 continue
88106
89107 contents_sent = 0
90- contents = stored_data [filename ]
108+ contents = d [filename ]
91109 while contents_sent < len (contents ):
92110 remaining = len (contents ) - contents_sent
93111 next_amount = min (remaining , free_space )
94- print ("sending" , next_amount )
95112 header = struct .pack (">BBII" , FileTransferService .READ , FileTransferService .OK , len (contents ), next_amount )
96- service . raw . write (header + contents [contents_sent :contents_sent + next_amount ])
113+ write_packets (header + contents [contents_sent :contents_sent + next_amount ])
97114 contents_sent += next_amount
98115
99- # Wait for the next free amount even if we've sent everything. A 0 free reply can
100- # confirm everything worked.
101- read = service .raw .readinto (packet_buffer )
102- while read == 0 :
103- read = service .raw .readinto (packet_buffer )
116+ read = read_packets (packet_buffer , target_size = struct .calcsize (">BBI" ))
104117 confirm , status , free_space = struct .unpack_from (">BBI" , p )
105118 elif command == adafruit_ble_file_transfer .FileTransferService .MKDIR :
106119 path_length = struct .unpack_from (">H" , p , offset = 1 )[0 ]
107120 path_start = struct .calcsize (">BH" )
108- path = str (p [path_start :path_start + path_length ], "utf-8" )
109- print ("mkdir" , path )
121+ path = read_complete_path (p [path_start :], path_length )
110122 pieces = path .split ("/" )
111123 parent = stored_data
112124 i = 1
@@ -124,30 +136,64 @@ def find_dir(path):
124136 header = struct .pack (">BB" , FileTransferService .WRITE , FileTransferService .OK )
125137 else :
126138 header = struct .pack (">BB" , FileTransferService .WRITE , FileTransferService .ERR )
127- service . raw . write (header )
139+ write_packets (header )
128140 elif command == adafruit_ble_file_transfer .FileTransferService .LISTDIR :
129141 path_length = struct .unpack_from (">H" , p , offset = 1 )[0 ]
130142 path_start = struct .calcsize (">BH" )
131- path = str (p [path_start :path_start + path_length ], "utf-8" )
132- print ("listdir" , path )
143+ path = read_complete_path (p [path_start :], path_length )
133144
134145 # cmd, status, i, total, flags, file_size, path_length = struct.unpack(">BBIIBIH", b)
135146
136147 d = find_dir (path )
137148 if d is None :
138149 error = struct .pack (">BBIIBIH" , FileTransferService .WRITE , FileTransferService .ERR , 0 , 0 , 0 , 0 , 0 )
139- service . raw . write (error )
150+ write_packets (error )
140151
141- print (d , type (d ))
142152 filenames = sorted (d .keys ())
143153 total_files = len (filenames )
144154 for i , filename in enumerate (filenames ):
145- print (i , filename )
146- header = struct .pack (">BBIIBIH" , FileTransferService .WRITE , FileTransferService .OK , i , total_files , 0 , 0 , 0 )
147- service .raw .write (header + filename .encode ("utf-8" ))
148- print ("send last entry" )
155+ encoded_filename = filename .encode ("utf-8" )
156+ flags = 0
157+ contents = d [filename ]
158+ if isinstance (contents , dict ):
159+ flags = FileTransferService .DIRECTORY
160+ else :
161+ content_length = len (contents )
162+ header = struct .pack (">BBIIBIH" , FileTransferService .WRITE , FileTransferService .OK , i , total_files , flags , content_length , len (encoded_filename ))
163+ packet = header + encoded_filename
164+ write_packets (packet )
165+
149166 header = struct .pack (">BBIIBIH" , FileTransferService .WRITE , FileTransferService .OK , total_files , total_files , 0 , 0 , 0 )
150- service .raw .write (header )
167+ write_packets (header )
168+ elif command == adafruit_ble_file_transfer .FileTransferService .DELETE :
169+ path_length = struct .unpack_from (">H" , p , offset = 1 )[0 ]
170+ path_start = struct .calcsize (">BH" )
171+ path = read_complete_path (p [path_start :], path_length )
172+ d = find_dir (path )
173+ filename = path .split ("/" )[- 1 ]
174+ if not filename and d :
175+ print ("trying to delete directory with contents" )
176+ error_response = struct .pack (">BB" , FileTransferService .WRITE , FileTransferService .ERR )
177+ write_packets (error_response )
178+ continue
179+
180+ # We're a directory.
181+ if not filename :
182+ path = path [:- 1 ]
183+ filename = path .split ("/" )[- 1 ]
184+ d = find_dir (path )
185+
186+ if filename not in d :
187+ print ("missing path" )
188+ error_response = struct .pack (">BB" , FileTransferService .WRITE , FileTransferService .ERR )
189+ write_packets (error_response )
190+ continue
191+ ok = True
192+
193+ del d [filename ]
194+
195+ header = struct .pack (">BB" , FileTransferService .WRITE , FileTransferService .OK )
196+ write_packets (header )
151197 else :
152198 print ("unknown command" , command )
153199 print ("disconnected" )
0 commit comments