Skip to content

Commit c0a5637

Browse files
committed
Fix recv, recv_into logic and have same behavior as ESP32SPI
1 parent f3070a3 commit c0a5637

File tree

1 file changed

+47
-21
lines changed

1 file changed

+47
-21
lines changed

adafruit_wiznet5k/adafruit_wiznet5k_socket.py

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -495,21 +495,9 @@ def recv(
495495
496496
:return bytes: Data from the socket.
497497
"""
498-
stamp = time.monotonic()
499-
while not self._available():
500-
if self._timeout and 0 < self._timeout < time.monotonic() - stamp:
501-
break
502-
time.sleep(0.05)
503-
bytes_on_socket = self._available()
504-
if not bytes_on_socket:
505-
return b""
506-
bytes_to_read = min(bytes_on_socket, bufsize)
507-
if self._sock_type == SOCK_STREAM:
508-
bytes_read = _the_interface.socket_read(self._socknum, bytes_to_read)[1]
509-
else:
510-
bytes_read = _the_interface.read_udp(self._socknum, bytes_to_read)[1]
511-
gc.collect()
512-
return bytes(bytes_read)
498+
buf = bytearray(bufsize)
499+
self.recv_into(buf, bufsize)
500+
return bytes(buf)
513501

514502
def _embed_recv(
515503
self, bufsize: int = 0, flags: int = 0
@@ -568,12 +556,42 @@ def recv_into(self, buffer: bytearray, nbytes: int = 0, flags: int = 0) -> int:
568556
569557
:return int: the number of bytes received
570558
"""
571-
if nbytes == 0:
572-
nbytes = len(buffer)
573-
bytes_received = self.recv(nbytes)
574-
nbytes = len(bytes_received)
575-
buffer[:nbytes] = bytes_received
576-
return nbytes
559+
if not 0 <= nbytes <= len(buffer):
560+
raise ValueError("nbytes must be 0 to len(buffer)")
561+
562+
last_read_time = time.monotonic()
563+
num_to_read = len(buffer) if nbytes == 0 else nbytes
564+
num_read = 0
565+
while num_to_read > 0:
566+
# we might have read socket data into the self._buffer with:
567+
# _readline
568+
if len(self._buffer) > 0:
569+
bytes_to_read = min(num_to_read, len(self._buffer))
570+
buffer[num_read : num_read + bytes_to_read] = self._buffer[:bytes_to_read]
571+
num_read += bytes_to_read
572+
num_to_read -= bytes_to_read
573+
self._buffer = self._buffer[bytes_to_read:]
574+
# explicitly recheck num_to_read to avoid extra checks
575+
continue
576+
577+
num_avail = self._available()
578+
if num_avail > 0:
579+
last_read_time = time.monotonic()
580+
bytes_to_read = min(num_to_read, num_avail)
581+
if self._sock_type == SOCK_STREAM:
582+
bytes_read = _the_interface.socket_read(self._socknum, bytes_to_read)[1]
583+
else:
584+
bytes_read = _the_interface.read_udp(self._socknum, bytes_to_read)[1]
585+
buffer[num_read : num_read + len(bytes_read)] = bytes_read
586+
num_read += len(bytes_read)
587+
num_to_read -= len(bytes_read)
588+
elif num_read > 0:
589+
# We got a message, but there are no more bytes to read, so we can stop.
590+
break
591+
# No bytes yet, or more bytes requested.
592+
if self._timeout > 0 and time.monotonic() - last_read_time > self._timeout:
593+
raise timeout("timed out")
594+
return num_read
577595

578596
@_check_socket_closed
579597
def recvfrom_into(
@@ -730,3 +748,11 @@ def type(self):
730748
def proto(self):
731749
"""Socket protocol (always 0x00 in this implementation)."""
732750
return 0
751+
752+
753+
class timeout(TimeoutError):
754+
"""TimeoutError class. An instance of this error will be raised by recv_into() if
755+
the timeout has elapsed and we haven't received any data yet."""
756+
757+
def __init__(self, msg):
758+
super().__init__(msg)

0 commit comments

Comments
 (0)