Skip to content

Commit f21e89d

Browse files
fix partial read bug on esp32
1 parent 0c69fc6 commit f21e89d

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

internal_filesystem/lib/aiohttp/aiohttp_ws.py

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,73 @@ async def close(self):
190190
self.closed = True
191191
await self.send(b"", self.CLOSE)
192192

193+
# this fixes the partial self.reader.read()s by requesting the remaining bytes
193194
async def _read_frame(self):
195+
import micropython
196+
import struct
197+
print(f"aiohttp_ws.py thread stack used: {micropython.stack_use()}")
198+
199+
# Read the 2-byte header
200+
header = await self.reader.read(2)
201+
if len(header) != 2: # pragma: no cover
202+
print("aiohttp_ws.py got len header not 2")
203+
opcode = self.CLOSE
204+
payload = b""
205+
return opcode, payload
206+
207+
# Parse the frame header
208+
fin, opcode, has_mask, length = self._parse_frame_header(header)
209+
print(f"aiohttp_ws.py _read_frame got {fin} {opcode} {has_mask} {length}")
210+
211+
# Handle extended length headers
212+
if length == 126: # Magic number, length header is 2 bytes
213+
print("aiohttp_ws.py Magic number, length header is 2 bytes")
214+
length_data = await self.reader.read(2)
215+
if len(length_data) != 2:
216+
print("aiohttp_ws.py failed to read 2-byte length header")
217+
return self.CLOSE, b""
218+
(length,) = struct.unpack("!H", length_data)
219+
elif length == 127: # Magic number, length header is 8 bytes
220+
print("aiohttp_ws.py Magic number, length header is 8 bytes")
221+
length_data = await self.reader.read(8)
222+
if len(length_data) != 8:
223+
print("aiohttp_ws.py failed to read 8-byte length header")
224+
return self.CLOSE, b""
225+
(length,) = struct.unpack("!Q", length_data)
226+
227+
print(f"actual length is {length}")
228+
229+
# Read mask if present
230+
if has_mask: # pragma: no cover
231+
mask = await self.reader.read(4)
232+
if len(mask) != 4:
233+
print("aiohttp_ws.py failed to read mask")
234+
return self.CLOSE, b""
235+
print(f"mask is {mask}")
236+
237+
# Read payload in chunks until the full length is received
238+
payload = b""
239+
remaining_length = length
240+
while remaining_length > 0:
241+
chunk = await self.reader.read(remaining_length)
242+
if not chunk: # Connection closed or error
243+
print(f"aiohttp_ws.py connection closed while reading payload, got {len(payload)}/{length} bytes")
244+
return self.CLOSE, b""
245+
payload += chunk
246+
remaining_length -= len(chunk)
247+
print(f"aiohttp_ws.py read chunk of {len(chunk)} bytes, {remaining_length} bytes remaining")
248+
249+
print(f"payload is {payload} with actual length {len(payload)}")
250+
if len(payload) != length:
251+
print(f"\n\n\nwrong payload length: expected {length}, got {len(payload)}\n\n\n")
252+
253+
# Unmask payload if necessary
254+
if has_mask: # pragma: no cover
255+
payload = bytes(x ^ mask[i % 4] for i, x in enumerate(payload))
256+
257+
return opcode, payload
258+
259+
async def _read_frame_original(self):
194260
import micropython
195261
print(f"aiohttp_ws.py thread stack used: {micropython.stack_use()}")
196262
header = await self.reader.read(2)
@@ -215,7 +281,7 @@ async def _read_frame(self):
215281
payload = await self.reader.read(length)
216282
print(f"payload is {payload} with actual length {len(payload)}")
217283
if len(payload) != length:
218-
print("wrong payload length, this should be ignored!")
284+
print("\n\n\nwrong payload length, this should be ignored!\n\n\n")
219285
if has_mask: # pragma: no cover
220286
payload = bytes(x ^ mask[i % 4] for i, x in enumerate(payload))
221287
return opcode, payload

0 commit comments

Comments
 (0)