Skip to content

Commit 8efe089

Browse files
committed
Adds accept and context manager methods
Adds socket accept API Adds context manager methods for socket Adds setter for socket socknum Adds status property for socket Corrects bug in remote_port method
1 parent 0e9c7e9 commit 8efe089

File tree

2 files changed

+78
-8
lines changed

2 files changed

+78
-8
lines changed

adafruit_wiznet5k/adafruit_wiznet5k.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# SPDX-FileCopyrightText: 2018 Paul Stoffregen
55
# SPDX-FileCopyrightText: 2020 Brent Rubell for Adafruit Industries
66
# SPDX-FileCopyrightText: 2021 Patrick Van Oosterwijck
7+
# SPDX-FileCopyrightText: 2021 Adam Cummick
78
#
89
# SPDX-License-Identifier: MIT
910

@@ -29,7 +30,6 @@
2930
from random import randint
3031
import time
3132
from micropython import const
32-
3333
from adafruit_bus_device.spi_device import SPIDevice
3434
import adafruit_wiznet5k.adafruit_wiznet5k_dhcp as dhcp
3535
import adafruit_wiznet5k.adafruit_wiznet5k_dns as dns
@@ -328,10 +328,13 @@ def link_status(self):
328328
return data[0] & 0x01
329329
return 0
330330

331-
@property
332-
def remote_port(self):
331+
def remote_port(self, socket_num):
333332
"""Returns the port of the host who sent the current incoming packet."""
334-
return self.remote_port
333+
if socket_num >= self.max_sockets:
334+
return self._pbuff
335+
for octet in range(0, 2):
336+
self._pbuff[octet] = self._read_socket(socket_num, REG_SNDPORT + octet)[0]
337+
return int((self._pbuff[0] << 8) | self._pbuff[0])
335338

336339
@property
337340
def ifconfig(self):
@@ -598,6 +601,20 @@ def socket_listen(self, socket_num, port):
598601
if status[0] == SNSR_SOCK_CLOSED:
599602
raise RuntimeError("Listening socket closed.")
600603

604+
def socket_accept(self, socket_num):
605+
"""Gets the dest IP and port from an incoming connection.
606+
Returns the next socket number so listening can continue
607+
:parm int socket_num: socket number
608+
"""
609+
dest_ip = self.remote_ip(socket_num)
610+
dest_port = self.remote_port(socket_num)
611+
next_socknum = self.get_socket()
612+
if self._debug:
613+
print(
614+
f"* Dest is ({dest_ip}, {dest_port}), Next listen socknum is #{next_socknum}"
615+
)
616+
return next_socknum, (dest_ip, dest_port)
617+
601618
def socket_open(self, socket_num, conn_mode=SNMR_TCP):
602619
"""Opens a TCP or UDP socket. By default, we use
603620
'conn_mode'=SNMR_TCP but we may also use SNMR_UDP.

adafruit_wiznet5k/adafruit_wiznet5k_socket.py

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
1010
A socket compatible interface with the Wiznet5k module.
1111
12-
* Author(s): ladyada, Brent Rubell, Patrick Van Oosterwijck
12+
* Author(s): ladyada, Brent Rubell, Patrick Van Oosterwijck, Adam Cummick
1313
1414
"""
1515
import gc
@@ -108,11 +108,30 @@ def __init__(
108108
if self._socknum == SOCKET_INVALID:
109109
raise RuntimeError("Failed to allocate socket.")
110110

111+
def __enter__(self):
112+
return self
113+
114+
def __exit__(self, exc_type, exc_val, exc_tb):
115+
self.disconnect()
116+
while self.status == adafruit_wiznet5k.SNSR_SOCK_FIN_WAIT:
117+
pass
118+
self.close()
119+
111120
@property
112121
def socknum(self):
113122
"""Returns the socket object's socket number."""
114123
return self._socknum
115124

125+
@socknum.setter
126+
def socknum(self, socknum):
127+
"""Sets the socket object's socket number."""
128+
self._socknum = socknum
129+
130+
@property
131+
def status(self):
132+
"""Returns the status of the socket"""
133+
return _the_interface.socket_status(self.socknum)[0]
134+
116135
@property
117136
def connected(self):
118137
"""Returns whether or not we are connected to the socket."""
@@ -147,10 +166,16 @@ def inet_aton(self, ip_string):
147166
return self._buffer
148167

149168
def bind(self, address):
150-
"""Bind the socket to the listen port, we ignore the host.
151-
:param tuple address: local socket as a (host, port) tuple, host is ignored.
169+
"""Bind the socket to the listen port, if host is specified the interface
170+
will be reconfigured to that IP.
171+
:param tuple address: local socket as a (host, port) tuple.
152172
"""
153-
_, self._listen_port = address
173+
if address[0] is not None:
174+
ip_address = _the_interface.unpretty_ip(address[0])
175+
current_ip, subnet_mask, gw_addr, dns = _the_interface.ifconfig
176+
if ip_address != current_ip:
177+
_the_interface.ifconfig = (ip_address, subnet_mask, gw_addr, dns)
178+
self._listen_port = address[1]
154179

155180
def listen(self, backlog=None):
156181
"""Listen on the port specified by bind.
@@ -160,6 +185,34 @@ def listen(self, backlog=None):
160185
_the_interface.socket_listen(self.socknum, self._listen_port)
161186
self._buffer = b""
162187

188+
def accept(self):
189+
"""Mimic python socket accept for compatibility. The socket where the
190+
connection originated is returned while a new socket is allocated and begins
191+
listening.
192+
"""
193+
stamp = time.monotonic()
194+
while self.status not in (
195+
adafruit_wiznet5k.SNSR_SOCK_SYNRECV,
196+
adafruit_wiznet5k.SNSR_SOCK_ESTABLISHED,
197+
):
198+
if self._timeout > 0 and time.monotonic() - stamp > self._timeout:
199+
return None
200+
if self.status == adafruit_wiznet5k.SNSR_SOCK_CLOSED:
201+
self.close()
202+
self.listen()
203+
204+
new_listen_socknum, addr = _the_interface.socket_accept(self.socknum)
205+
current_socknum = self.socknum
206+
# Create a new socket object and swap socket nums so we can continue listening
207+
client_sock = socket()
208+
client_sock.socknum = current_socknum
209+
self.socknum = new_listen_socknum
210+
self.bind((None, self._listen_port))
211+
self.listen()
212+
while self.status != adafruit_wiznet5k.SNSR_SOCK_LISTEN:
213+
print("Waiting for socket to listen")
214+
return client_sock, addr
215+
163216
def connect(self, address, conntype=None):
164217
"""Connect to a remote socket at address. (The format of address depends
165218
on the address family — see above.)

0 commit comments

Comments
 (0)