99
1010A 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"""
1515import 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.)
0 commit comments