1414from __future__ import annotations
1515
1616try :
17- from typing import TYPE_CHECKING , Optional
17+ from typing import TYPE_CHECKING , Optional , Tuple
1818
1919 if TYPE_CHECKING :
2020 from esp32spi .adafruit_esp32spi import ESP_SPIcontrol # noqa: UP007
@@ -40,7 +40,7 @@ class SocketPool:
4040 SOCK_STREAM = const (1 )
4141 SOCK_DGRAM = const (2 )
4242 AF_INET = const (2 )
43- SOL_SOCKET = const (0xfff )
43+ SOL_SOCKET = const (0xFFF )
4444 SO_REUSEADDR = const (0x0004 )
4545
4646 # implementation specific constants
@@ -95,6 +95,7 @@ def __init__(
9595 self ._type = type
9696 self ._buffer = b""
9797 self ._socknum = socknum if socknum is not None else self ._interface .get_socket ()
98+ self ._bound = ()
9899 self .settimeout (0 )
99100
100101 def __enter__ (self ):
@@ -156,12 +157,12 @@ def recv_into(self, buffer, nbytes: int = 0):
156157 if not 0 <= nbytes <= len (buffer ):
157158 raise ValueError ("nbytes must be 0 to len(buffer)" )
158159
159- last_read_time = time .monotonic ()
160+ last_read_time = time .monotonic_ns ()
160161 num_to_read = len (buffer ) if nbytes == 0 else nbytes
161162 num_read = 0
162163 while num_to_read > 0 :
163164 # we might have read socket data into the self._buffer with:
164- # esp32spi_wsgiserver: socket_readline
165+ # adafruit_wsgi. esp32spi_wsgiserver: socket_readline
165166 if len (self ._buffer ) > 0 :
166167 bytes_to_read = min (num_to_read , len (self ._buffer ))
167168 buffer [num_read : num_read + bytes_to_read ] = self ._buffer [:bytes_to_read ]
@@ -173,24 +174,38 @@ def recv_into(self, buffer, nbytes: int = 0):
173174
174175 num_avail = self ._available ()
175176 if num_avail > 0 :
176- last_read_time = time .monotonic ()
177- bytes_read = self ._interface .socket_read (self ._socknum , min (num_to_read , num_avail ))
177+ last_read_time = time .monotonic_ns ()
178+ bytes_read = self ._interface .socket_read (
179+ self ._socknum , min (num_to_read , num_avail )
180+ )
178181 buffer [num_read : num_read + len (bytes_read )] = bytes_read
179182 num_read += len (bytes_read )
180183 num_to_read -= len (bytes_read )
181184 elif num_read > 0 :
182185 # We got a message, but there are no more bytes to read, so we can stop.
183186 break
184187 # No bytes yet, or more bytes requested.
185- if self ._timeout > 0 and time .monotonic () - last_read_time > self ._timeout :
188+
189+ if self ._timeout == 0 : # if in non-blocking mode, stop now.
190+ break
191+
192+ # Time out if there's a positive timeout set.
193+ delta = (time .monotonic_ns () - last_read_time ) // 1_000_000
194+ if self ._timeout > 0 and delta > self ._timeout :
186195 raise OSError (errno .ETIMEDOUT )
187196 return num_read
188197
189198 def settimeout (self , value ):
190- """Set the read timeout for sockets.
191- If value is 0 socket reads will block until a message is available .
199+ """Set the read timeout for sockets in seconds .
200+ ``0`` means non-blocking. ``None`` means block indefinitely .
192201 """
193- self ._timeout = value
202+ if value is None :
203+ self ._timeout = - 1
204+ else :
205+ if value < 0 :
206+ raise ValueError ("Timeout cannot be a negative number" )
207+ # internally in milliseconds as an int
208+ self ._timeout = int (value * 1000 )
194209
195210 def _available (self ):
196211 """Returns how many bytes of data are available to be read (up to the MAX_PACKET length)"""
@@ -230,35 +245,41 @@ def close(self):
230245
231246 def setsockopt (self , * opts , ** kwopts ):
232247 """Dummy call for compatibility."""
233- # FIXME
234- pass
235248
236- def listen (self , backlog ):
237- """Dummy call for compatibility."""
238- # FIXME
239- # probably nothing to do actually
240- # maybe check that we have called bind or something ?
241- pass
249+ def setblocking (self , flag : bool ):
250+ """Set the blocking behaviour of this socket.
251+ :param bool flag: False means non-blocking, True means block indefinitely.
252+ """
253+ if flag :
254+ self .settimeout (None )
255+ else :
256+ self .settimeout (0 )
242257
243- def setblocking (self , blocking ):
244- """Dummy call for compatibility."""
245- # FIXME
246- # is this settimeout(0) ? (if True) or something else ?
247- pass
258+ def bind (self , address : Tuple [str , int ]):
259+ """Bind a socket to an address"""
260+ self ._bound = address
248261
249- def bind (self , host_port ):
250- host , port = host_port
262+ def listen (self , backlog : int ): # pylint: disable=unused-argument
263+ """Set socket to listen for incoming connections.
264+ :param int backlog: length of backlog queue for waiting connections (ignored)
265+ """
266+ if not self ._bound :
267+ self ._bound = (self ._interface .ip_address , 80 )
268+ port = self ._bound [1 ]
251269 self ._interface .start_server (port , self ._socknum )
252- print (f"Binding to { self ._socknum } " )
253270
254271 def accept (self ):
272+ """Accept a connection on a listening socket of type SOCK_STREAM,
273+ creating a new socket of type SOCK_STREAM. Returns a tuple of
274+ (new_socket, remote_address)
275+ """
255276 client_sock_num = self ._interface .socket_available (self ._socknum )
256277 if client_sock_num != SocketPool .NO_SOCKET_AVAIL :
257278 sock = Socket (self ._socket_pool , socknum = client_sock_num )
258279 # get remote information (addr and port)
259280 remote = self ._interface .get_remote_data (client_sock_num )
260- IP_ADDRESS = "{}.{}.{}.{}" .format (* remote [' ip_addr' ])
261- PORT = remote [' port' ]
262- client_address = (IP_ADDRESS , PORT )
281+ ip_address = "{}.{}.{}.{}" .format (* remote [" ip_addr" ])
282+ port = remote [" port" ]
283+ client_address = (ip_address , port )
263284 return sock , client_address
264285 raise OSError (errno .ECONNRESET )
0 commit comments