Skip to content

Commit be71b45

Browse files
author
Tom Thompson
committed
Fixed issues with UDP datagram receives
1. socket.recvfrom did not return remote address 2. datagrams were not delimited on message boundaries 3. the scheme for keeping track of partially read datagrams failed if multiple datagrams were being received at once. Also, the _dns attribute is not initted to a tuple in case it is read before it is ever explicitly set.
1 parent 4e5909c commit be71b45

File tree

2 files changed

+43
-23
lines changed

2 files changed

+43
-23
lines changed

adafruit_wiznet5k/adafruit_wiznet5k.py

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,6 @@
122122
W5100_MAX_SOCK_NUM = const(0x04)
123123
SOCKET_INVALID = const(255)
124124

125-
# UDP socket struct.
126-
UDP_SOCK = {"bytes_remaining": 0, "remote_ip": 0, "remote_port": 0}
127125

128126
# Source ports in use
129127
SRC_PORTS = [0] * W5200_W5500_MAX_SOCK_NUM
@@ -181,7 +179,11 @@ def __init__(
181179
# Set MAC address
182180
self.mac_address = mac
183181
self.src_port = 0
184-
self._dns = 0
182+
self._dns = (0,0,0,0)
183+
# udp related
184+
self.udp_datasize = [0] * self.max_sockets
185+
self.udp_from_ip = [b"\x00\x00\x00\x00"] * self.max_sockets
186+
self.udp_from_port = [0] * self.max_sockets
185187

186188
# First, wait link status is on
187189
# to avoid the code during DHCP, socket listen, connect ...
@@ -495,11 +497,6 @@ def write(self, addr, callback, data):
495497
bus_device.write(bytes([data[i]])) # pylint: disable=no-member
496498

497499
# Socket-Register API
498-
def udp_remaining(self):
499-
"""Returns amount of bytes remaining in a udp socket."""
500-
if self._debug:
501-
print("* UDP Bytes Remaining: ", UDP_SOCK["bytes_remaining"])
502-
return UDP_SOCK["bytes_remaining"]
503500

504501
def socket_available(self, socket_num, sock_type=SNMR_TCP):
505502
"""Returns the amount of bytes to be read from the socket.
@@ -520,16 +517,16 @@ def socket_available(self, socket_num, sock_type=SNMR_TCP):
520517
if sock_type == SNMR_TCP:
521518
return res
522519
if res > 0:
523-
if UDP_SOCK["bytes_remaining"]:
524-
return UDP_SOCK["bytes_remaining"]
520+
if self.udp_datasize[socket_num]:
521+
return self.udp_datasize[socket_num]
525522
# parse the udp rx packet
526523
# read the first 8 header bytes
527524
ret, self._pbuff = self.socket_read(socket_num, 8)
528525
if ret > 0:
529-
UDP_SOCK["remote_ip"] = self._pbuff[:4]
530-
UDP_SOCK["remote_port"] = (self._pbuff[4] << 8) + self._pbuff[5]
531-
UDP_SOCK["bytes_remaining"] = (self._pbuff[6] << 8) + self._pbuff[7]
532-
ret = UDP_SOCK["bytes_remaining"]
526+
self.udp_from_ip[socket_num] = self._pbuff[:4]
527+
self.udp_from_port[socket_num] = (self._pbuff[4] << 8) + self._pbuff[5]
528+
self.udp_datasize[socket_num] = (self._pbuff[6] << 8) + self._pbuff[7]
529+
ret = self.udp_datasize[socket_num]
533530
return ret
534531
return 0
535532

@@ -573,7 +570,7 @@ def socket_connect(self, socket_num, dest, port, conn_mode=SNMR_TCP):
573570
if self.socket_status(socket_num)[0] == SNSR_SOCK_CLOSED:
574571
raise RuntimeError("Failed to establish connection.")
575572
elif conn_mode == SNMR_UDP:
576-
UDP_SOCK["bytes_remaining"] = 0
573+
self.udp_datasize[socket_num] = 0
577574
return 1
578575

579576
def _send_socket_cmd(self, socket, cmd):
@@ -765,14 +762,15 @@ def socket_read(self, socket_num, length):
765762
return ret, resp
766763

767764
def read_udp(self, socket_num, length):
768-
"""Read UDP socket's remaining bytes."""
769-
if UDP_SOCK["bytes_remaining"] > 0:
770-
if UDP_SOCK["bytes_remaining"] <= length:
771-
ret, resp = self.socket_read(socket_num, UDP_SOCK["bytes_remaining"])
765+
"""Read UDP socket's current message bytes."""
766+
if self.udp_datasize[socket_num] > 0:
767+
if self.udp_datasize[socket_num] <= length:
768+
ret, resp = self.socket_read(socket_num, self.udp_datasize[socket_num])
772769
else:
773770
ret, resp = self.socket_read(socket_num, length)
774-
if ret > 0:
775-
UDP_SOCK["bytes_remaining"] -= ret
771+
# just consume the rest, it is lost to the higher layers
772+
self.socket_read(socket_num, self.udp_datasize[socket_num] - length)
773+
self.udp_datasize[socket_num] = 0
776774
return ret, resp
777775
return -1
778776

adafruit_wiznet5k/adafruit_wiznet5k_socket.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ def recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches
294294
]
295295
elif self._sock_type == SOCK_DGRAM:
296296
self._buffer += _the_interface.read_udp(self.socknum, avail)[1]
297+
break
297298
else:
298299
break
299300
gc.collect()
@@ -315,6 +316,7 @@ def recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches
315316
)[1]
316317
elif self._sock_type == SOCK_DGRAM:
317318
recv = _the_interface.read_udp(self.socknum, min(to_read, avail))[1]
319+
to_read = len(recv) # only get this dgram
318320
recv = bytes(recv)
319321
received.append(recv)
320322
to_read -= len(recv)
@@ -333,6 +335,26 @@ def recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches
333335
gc.collect()
334336
return ret
335337

338+
def embed_recv(self, bufsize=0, flags=0): # pylint: disable=too-many-branches
339+
"""Reads some bytes from the connected remote address and then return recv().
340+
:param int bufsize: Maximum number of bytes to receive.
341+
:param int flags: ignored, present for compatibility.
342+
"""
343+
# print("Socket read", bufsize)
344+
ret = None
345+
avail = self.available()
346+
if avail:
347+
if self._sock_type == SOCK_STREAM:
348+
self._buffer += _the_interface.socket_read(self.socknum, avail)[1]
349+
elif self._sock_type == SOCK_DGRAM:
350+
self._buffer += _the_interface.read_udp(self.socknum, avail)[1]
351+
gc.collect()
352+
ret = self._buffer
353+
# print("RET ptr:", id(ret), id(self._buffer))
354+
self._buffer = b""
355+
gc.collect()
356+
return ret
357+
336358
def recvfrom(self, bufsize=0, flags=0):
337359
"""Reads some bytes from the connected remote address.
338360
@@ -343,8 +365,8 @@ def recvfrom(self, bufsize=0, flags=0):
343365
return (
344366
self.recv(bufsize),
345367
(
346-
_the_interface.remote_ip(self.socknum),
347-
_the_interface.remote_port(self.socknum),
368+
_the_interface.pretty_ip(_the_interface.udp_from_ip[self.socknum]),
369+
_the_interface.udp_from_port[self.socknum],
348370
),
349371
)
350372

0 commit comments

Comments
 (0)