Skip to content

Commit

Permalink
Merge pull request #30 from AdamCummick/accept-method
Browse files Browse the repository at this point in the history
Accept method
  • Loading branch information
brentru authored Jan 21, 2021
2 parents 0e9c7e9 + 6bbc692 commit f71ca90
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 7 deletions.
26 changes: 23 additions & 3 deletions adafruit_wiznet5k/adafruit_wiznet5k.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# SPDX-FileCopyrightText: 2018 Paul Stoffregen
# SPDX-FileCopyrightText: 2020 Brent Rubell for Adafruit Industries
# SPDX-FileCopyrightText: 2021 Patrick Van Oosterwijck
# SPDX-FileCopyrightText: 2021 Adam Cummick
#
# SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -328,10 +329,13 @@ def link_status(self):
return data[0] & 0x01
return 0

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

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

def socket_accept(self, socket_num):
"""Gets the dest IP and port from an incoming connection.
Returns the next socket number so listening can continue
:parm int socket_num: socket number
"""
dest_ip = self.remote_ip(socket_num)
dest_port = self.remote_port(socket_num)
next_socknum = self.get_socket()
if self._debug:
print(
"* Dest is ({}, {}), Next listen socknum is #{}".format(
dest_ip, dest_port, next_socknum
)
)
return next_socknum, (dest_ip, dest_port)

def socket_open(self, socket_num, conn_mode=SNMR_TCP):
"""Opens a TCP or UDP socket. By default, we use
'conn_mode'=SNMR_TCP but we may also use SNMR_UDP.
Expand Down
63 changes: 59 additions & 4 deletions adafruit_wiznet5k/adafruit_wiznet5k_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
A socket compatible interface with the Wiznet5k module.
* Author(s): ladyada, Brent Rubell, Patrick Van Oosterwijck
* Author(s): ladyada, Brent Rubell, Patrick Van Oosterwijck, Adam Cummick
"""
import gc
Expand Down Expand Up @@ -108,11 +108,31 @@ def __init__(
if self._socknum == SOCKET_INVALID:
raise RuntimeError("Failed to allocate socket.")

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self.disconnect()
stamp = time.monotonic()
while self.status == adafruit_wiznet5k.SNSR_SOCK_FIN_WAIT:
if time.monotonic() - stamp > 1000:
raise RuntimeError("Failed to disconnect socket")
self.close()
stamp = time.monotonic()
while self.status != adafruit_wiznet5k.SNSR_SOCK_CLOSED:
if time.monotonic() - stamp > 1000:
raise RuntimeError("Failed to close socket")

@property
def socknum(self):
"""Returns the socket object's socket number."""
return self._socknum

@property
def status(self):
"""Returns the status of the socket"""
return _the_interface.socket_status(self.socknum)[0]

@property
def connected(self):
"""Returns whether or not we are connected to the socket."""
Expand Down Expand Up @@ -147,10 +167,16 @@ def inet_aton(self, ip_string):
return self._buffer

def bind(self, address):
"""Bind the socket to the listen port, we ignore the host.
:param tuple address: local socket as a (host, port) tuple, host is ignored.
"""Bind the socket to the listen port, if host is specified the interface
will be reconfigured to that IP.
:param tuple address: local socket as a (host, port) tuple.
"""
_, self._listen_port = address
if address[0] is not None:
ip_address = _the_interface.unpretty_ip(address[0])
current_ip, subnet_mask, gw_addr, dns = _the_interface.ifconfig
if ip_address != current_ip:
_the_interface.ifconfig = (ip_address, subnet_mask, gw_addr, dns)
self._listen_port = address[1]

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

def accept(self):
"""Accept a connection. The socket must be bound to an address and listening for
connections. The return value is a pair (conn, address) where conn is a new
socket object usable to send and receive data on the connection, and address is
the address bound to the socket on the other end of the connection.
"""
stamp = time.monotonic()
while self.status not in (
adafruit_wiznet5k.SNSR_SOCK_SYNRECV,
adafruit_wiznet5k.SNSR_SOCK_ESTABLISHED,
):
if self._timeout > 0 and time.monotonic() - stamp > self._timeout:
return None
if self.status == adafruit_wiznet5k.SNSR_SOCK_CLOSED:
self.close()
self.listen()

new_listen_socknum, addr = _the_interface.socket_accept(self.socknum)
current_socknum = self.socknum
# Create a new socket object and swap socket nums so we can continue listening
client_sock = socket()
client_sock._socknum = current_socknum # pylint: disable=protected-access
self._socknum = new_listen_socknum # pylint: disable=protected-access
self.bind((None, self._listen_port))
self.listen()
while self.status != adafruit_wiznet5k.SNSR_SOCK_LISTEN:
raise RuntimeError("Failed to open new listening socket")
return client_sock, addr

def connect(self, address, conntype=None):
"""Connect to a remote socket at address. (The format of address depends
on the address family — see above.)
Expand Down
36 changes: 36 additions & 0 deletions examples/wiznet5k_simpleserver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-FileCopyrightText: 2021 Adam Cummick
#
# SPDX-License-Identifier: MIT

import board
import busio
import digitalio
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket

print("Wiznet5k SimpleServer Test")

# For Adafruit Ethernet FeatherWing
cs = digitalio.DigitalInOut(board.D10)
# For Particle Ethernet FeatherWing
# cs = digitalio.DigitalInOut(board.D5)
spi_bus = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

# Initialize ethernet interface
eth = WIZNET5K(spi_bus, cs, is_dhcp=False)

# Initialize a socket for our server
socket.set_interface(eth)
server = socket.socket() # Allocate socket for the server
server_ip = "192.168.10.1" # IP address of server
server_port = 50007 # Port to listen on
server.bind((server_ip, server_port)) # Bind to IP and Port
server.listen() # Begin listening for incoming clients

while True:
conn, addr = server.accept() # Wait for a connection from a client.
with conn:
data = conn.recv()
print(data)
conn.send(data) # Echo message back to client

0 comments on commit f71ca90

Please sign in to comment.