1313from __future__ import annotations
1414
1515try :
16- from typing import TYPE_CHECKING , Optional
16+ from typing import TYPE_CHECKING , Optional , Tuple
1717
1818 if TYPE_CHECKING :
1919 from esp32spi .adafruit_esp32spi import ESP_SPIcontrol
@@ -37,7 +37,7 @@ class SocketPool:
3737 SOCK_STREAM = const (1 )
3838 SOCK_DGRAM = const (2 )
3939 AF_INET = const (2 )
40- SOL_SOCKET = const (0xfff )
40+ SOL_SOCKET = const (0xFFF )
4141 SO_REUSEADDR = const (0x0004 )
4242
4343 # implementation specific constants
@@ -94,6 +94,7 @@ def __init__( # pylint: disable=redefined-builtin,too-many-arguments,unused-arg
9494 self ._type = type
9595 self ._buffer = b""
9696 self ._socknum = socknum if socknum is not None else self ._interface .get_socket ()
97+ self ._bound = ()
9798 self .settimeout (0 )
9899
99100 def __enter__ (self ):
@@ -157,12 +158,12 @@ def recv_into(self, buffer, nbytes: int = 0):
157158 if not 0 <= nbytes <= len (buffer ):
158159 raise ValueError ("nbytes must be 0 to len(buffer)" )
159160
160- last_read_time = time .monotonic ()
161+ last_read_time = time .monotonic_ns ()
161162 num_to_read = len (buffer ) if nbytes == 0 else nbytes
162163 num_read = 0
163164 while num_to_read > 0 :
164165 # we might have read socket data into the self._buffer with:
165- # esp32spi_wsgiserver: socket_readline
166+ # adafruit_wsgi. esp32spi_wsgiserver: socket_readline
166167 if len (self ._buffer ) > 0 :
167168 bytes_to_read = min (num_to_read , len (self ._buffer ))
168169 buffer [num_read : num_read + bytes_to_read ] = self ._buffer [
@@ -176,7 +177,7 @@ def recv_into(self, buffer, nbytes: int = 0):
176177
177178 num_avail = self ._available ()
178179 if num_avail > 0 :
179- last_read_time = time .monotonic ()
180+ last_read_time = time .monotonic_ns ()
180181 bytes_read = self ._interface .socket_read (
181182 self ._socknum , min (num_to_read , num_avail )
182183 )
@@ -187,15 +188,27 @@ def recv_into(self, buffer, nbytes: int = 0):
187188 # We got a message, but there are no more bytes to read, so we can stop.
188189 break
189190 # No bytes yet, or more bytes requested.
190- if self ._timeout > 0 and time .monotonic () - last_read_time > self ._timeout :
191+
192+ if self ._timeout == 0 : # if in non-blocking mode, stop now.
193+ break
194+
195+ # Time out if there's a positive timeout set.
196+ delta = (time .monotonic_ns () - last_read_time ) // 1_000_000
197+ if self ._timeout > 0 and delta > self ._timeout :
191198 raise OSError (errno .ETIMEDOUT )
192199 return num_read
193200
194201 def settimeout (self , value ):
195- """Set the read timeout for sockets.
196- If value is 0 socket reads will block until a message is available .
202+ """Set the read timeout for sockets in seconds .
203+ ``0`` means non-blocking. ``None`` means block indefinitely .
197204 """
198- self ._timeout = value
205+ if value is None :
206+ self ._timeout = - 1
207+ else :
208+ if value < 0 :
209+ raise ValueError ("Timeout cannot be a negative number" )
210+ # internally in milliseconds as an int
211+ self ._timeout = int (value * 1000 )
199212
200213 def _available (self ):
201214 """Returns how many bytes of data are available to be read (up to the MAX_PACKET length)"""
@@ -237,35 +250,41 @@ def close(self):
237250
238251 def setsockopt (self , * opts , ** kwopts ):
239252 """Dummy call for compatibility."""
240- # FIXME
241- pass
242253
243- def listen (self , backlog ):
244- """Dummy call for compatibility."""
245- # FIXME
246- # probably nothing to do actually
247- # maybe check that we have called bind or something ?
248- pass
254+ def setblocking (self , flag : bool ):
255+ """Set the blocking behaviour of this socket.
256+ :param bool flag: False means non-blocking, True means block indefinitely.
257+ """
258+ if flag :
259+ self .settimeout (None )
260+ else :
261+ self .settimeout (0 )
249262
250- def setblocking (self , blocking ):
251- """Dummy call for compatibility."""
252- # FIXME
253- # is this settimeout(0) ? (if True) or something else ?
254- pass
263+ def bind (self , address : Tuple [str , int ]):
264+ """Bind a socket to an address"""
265+ self ._bound = address
255266
256- def bind (self , host_port ):
257- host , port = host_port
267+ def listen (self , backlog : int ): # pylint: disable=unused-argument
268+ """Set socket to listen for incoming connections.
269+ :param int backlog: length of backlog queue for waiting connections (ignored)
270+ """
271+ if not self ._bound :
272+ self ._bound = (self ._interface .ip_address , 80 )
273+ port = self ._bound [1 ]
258274 self ._interface .start_server (port , self ._socknum )
259- print (f"Binding to { self ._socknum } " )
260275
261276 def accept (self ):
277+ """Accept a connection on a listening socket of type SOCK_STREAM,
278+ creating a new socket of type SOCK_STREAM. Returns a tuple of
279+ (new_socket, remote_address)
280+ """
262281 client_sock_num = self ._interface .socket_available (self ._socknum )
263282 if client_sock_num != SocketPool .NO_SOCKET_AVAIL :
264283 sock = Socket (self ._socket_pool , socknum = client_sock_num )
265284 # get remote information (addr and port)
266285 remote = self ._interface .get_remote_data (client_sock_num )
267- IP_ADDRESS = "{}.{}.{}.{}" .format (* remote [' ip_addr' ])
268- PORT = remote [' port' ]
269- client_address = (IP_ADDRESS , PORT )
286+ ip_address = "{}.{}.{}.{}" .format (* remote [" ip_addr" ])
287+ port = remote [" port" ]
288+ client_address = (ip_address , port )
270289 return sock , client_address
271290 raise OSError (errno .ECONNRESET )
0 commit comments