Skip to content

Commit f71ca90

Browse files
authored
Merge pull request #30 from AdamCummick/accept-method
Accept method
2 parents 0e9c7e9 + 6bbc692 commit f71ca90

File tree

3 files changed

+118
-7
lines changed

3 files changed

+118
-7
lines changed

adafruit_wiznet5k/adafruit_wiznet5k.py

+23-3
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

@@ -328,10 +329,13 @@ def link_status(self):
328329
return data[0] & 0x01
329330
return 0
330331

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

336340
@property
337341
def ifconfig(self):
@@ -598,6 +602,22 @@ def socket_listen(self, socket_num, port):
598602
if status[0] == SNSR_SOCK_CLOSED:
599603
raise RuntimeError("Listening socket closed.")
600604

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

adafruit_wiznet5k/adafruit_wiznet5k_socket.py

+59-4
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,31 @@ 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+
stamp = time.monotonic()
117+
while self.status == adafruit_wiznet5k.SNSR_SOCK_FIN_WAIT:
118+
if time.monotonic() - stamp > 1000:
119+
raise RuntimeError("Failed to disconnect socket")
120+
self.close()
121+
stamp = time.monotonic()
122+
while self.status != adafruit_wiznet5k.SNSR_SOCK_CLOSED:
123+
if time.monotonic() - stamp > 1000:
124+
raise RuntimeError("Failed to close socket")
125+
111126
@property
112127
def socknum(self):
113128
"""Returns the socket object's socket number."""
114129
return self._socknum
115130

131+
@property
132+
def status(self):
133+
"""Returns the status of the socket"""
134+
return _the_interface.socket_status(self.socknum)[0]
135+
116136
@property
117137
def connected(self):
118138
"""Returns whether or not we are connected to the socket."""
@@ -147,10 +167,16 @@ def inet_aton(self, ip_string):
147167
return self._buffer
148168

149169
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.
170+
"""Bind the socket to the listen port, if host is specified the interface
171+
will be reconfigured to that IP.
172+
:param tuple address: local socket as a (host, port) tuple.
152173
"""
153-
_, self._listen_port = address
174+
if address[0] is not None:
175+
ip_address = _the_interface.unpretty_ip(address[0])
176+
current_ip, subnet_mask, gw_addr, dns = _the_interface.ifconfig
177+
if ip_address != current_ip:
178+
_the_interface.ifconfig = (ip_address, subnet_mask, gw_addr, dns)
179+
self._listen_port = address[1]
154180

155181
def listen(self, backlog=None):
156182
"""Listen on the port specified by bind.
@@ -160,6 +186,35 @@ def listen(self, backlog=None):
160186
_the_interface.socket_listen(self.socknum, self._listen_port)
161187
self._buffer = b""
162188

189+
def accept(self):
190+
"""Accept a connection. The socket must be bound to an address and listening for
191+
connections. The return value is a pair (conn, address) where conn is a new
192+
socket object usable to send and receive data on the connection, and address is
193+
the address bound to the socket on the other end of the connection.
194+
"""
195+
stamp = time.monotonic()
196+
while self.status not in (
197+
adafruit_wiznet5k.SNSR_SOCK_SYNRECV,
198+
adafruit_wiznet5k.SNSR_SOCK_ESTABLISHED,
199+
):
200+
if self._timeout > 0 and time.monotonic() - stamp > self._timeout:
201+
return None
202+
if self.status == adafruit_wiznet5k.SNSR_SOCK_CLOSED:
203+
self.close()
204+
self.listen()
205+
206+
new_listen_socknum, addr = _the_interface.socket_accept(self.socknum)
207+
current_socknum = self.socknum
208+
# Create a new socket object and swap socket nums so we can continue listening
209+
client_sock = socket()
210+
client_sock._socknum = current_socknum # pylint: disable=protected-access
211+
self._socknum = new_listen_socknum # pylint: disable=protected-access
212+
self.bind((None, self._listen_port))
213+
self.listen()
214+
while self.status != adafruit_wiznet5k.SNSR_SOCK_LISTEN:
215+
raise RuntimeError("Failed to open new listening socket")
216+
return client_sock, addr
217+
163218
def connect(self, address, conntype=None):
164219
"""Connect to a remote socket at address. (The format of address depends
165220
on the address family — see above.)

examples/wiznet5k_simpleserver.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
2+
# SPDX-FileCopyrightText: 2021 Adam Cummick
3+
#
4+
# SPDX-License-Identifier: MIT
5+
6+
import board
7+
import busio
8+
import digitalio
9+
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
10+
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
11+
12+
print("Wiznet5k SimpleServer Test")
13+
14+
# For Adafruit Ethernet FeatherWing
15+
cs = digitalio.DigitalInOut(board.D10)
16+
# For Particle Ethernet FeatherWing
17+
# cs = digitalio.DigitalInOut(board.D5)
18+
spi_bus = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
19+
20+
# Initialize ethernet interface
21+
eth = WIZNET5K(spi_bus, cs, is_dhcp=False)
22+
23+
# Initialize a socket for our server
24+
socket.set_interface(eth)
25+
server = socket.socket() # Allocate socket for the server
26+
server_ip = "192.168.10.1" # IP address of server
27+
server_port = 50007 # Port to listen on
28+
server.bind((server_ip, server_port)) # Bind to IP and Port
29+
server.listen() # Begin listening for incoming clients
30+
31+
while True:
32+
conn, addr = server.accept() # Wait for a connection from a client.
33+
with conn:
34+
data = conn.recv()
35+
print(data)
36+
conn.send(data) # Echo message back to client

0 commit comments

Comments
 (0)