diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_socket.py b/adafruit_wiznet5k/adafruit_wiznet5k_socketpool.py similarity index 63% rename from adafruit_wiznet5k/adafruit_wiznet5k_socket.py rename to adafruit_wiznet5k/adafruit_wiznet5k_socketpool.py index e9f6605..0509a63 100644 --- a/adafruit_wiznet5k/adafruit_wiznet5k_socket.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k_socketpool.py @@ -2,11 +2,8 @@ # SPDX-FileCopyrightText: 2020 Brent Rubell for Adafruit Industries # # SPDX-License-Identifier: MIT -# -# CPython uses type as an argument in socket.socket, so disable checking in Pylint -# pylint: disable=redefined-builtin """ -`adafruit_wiznet5k_socket` +`adafruit_wiznet5k_socketpool` ================================================================================ A socket compatible interface with the Wiznet5k module. @@ -33,197 +30,206 @@ import adafruit_wiznet5k as wiznet5k -# pylint: disable=invalid-name -_the_interface: Optional[WIZNET5K] = None -_default_socket_timeout = None +_SOCKET_TYPE_TO_WIZNET = b"\0\x21\2" +_SOCKET_INVALID = const(255) -def _is_ipv4_string(ipv4_address: str) -> bool: - """Check for a valid IPv4 address in dotted-quad string format - (for example, "123.45.67.89"). +_global_socketpool = {} - :param: str ipv4_address: The string to test. - :return bool: True if a valid IPv4 address, False otherwise. - """ - octets = ipv4_address.split(".", 3) - if len(octets) == 4 and "".join(octets).isdigit(): - if all((0 <= int(octet) <= 255 for octet in octets)): - return True - return False +class SocketPoolContants: # pylint: disable=too-few-public-methods + """Helper class for the constants that are needed everywhere""" + # These must match circuitpython "socketpoool" values. However, we cannot + # depend on socketpool being importable, so hard-code them here. + SOCK_STREAM = 1 + SOCK_DGRAM = 2 -def set_interface(iface: WIZNET5K) -> None: - """ - Helper to set the global internet interface. + SOL_SOCKET = 0xFFF + SO_REUSEADDR = 0x0004 - :param wiznet5k.adafruit_wiznet5k.WIZNET5K iface: The ethernet interface. - """ - global _the_interface # pylint: disable=global-statement, invalid-name - _the_interface = iface + AF_INET = const(3) -def getdefaulttimeout() -> Optional[float]: - """ - Return the default timeout in seconds for new socket objects. A value of - None indicates that new socket objects have no timeout. When the socket module is - first imported, the default is None. - """ - return _default_socket_timeout +class SocketPool(SocketPoolContants): + """WIZNET5K SocketPool library""" + def __new__(cls, iface: WIZNET5K): + # We want to make sure to return the same pool for the same interface + if iface not in _global_socketpool: + _global_socketpool[iface] = super().__new__(cls) + return _global_socketpool[iface] -def setdefaulttimeout(_timeout: Optional[float]) -> None: - """ - Set the default timeout in seconds (float) for new socket objects. When the socket - module is first imported, the default is None. See settimeout() for possible values - and their respective meanings. - - :param Optional[float] _timeout: The default timeout in seconds or None. - """ - global _default_socket_timeout # pylint: disable=global-statement - if _timeout is None or _timeout >= 0: - _default_socket_timeout = _timeout - else: - raise ValueError("Timeout must be None, 0.0 or a positive numeric value.") + def __init__(self, iface: WIZNET5K): + self._interface = iface + self._default_socket_timeout = None + @staticmethod + def _is_ipv4_string(ipv4_address: str) -> bool: + """Check for a valid IPv4 address in dotted-quad string format + (for example, "123.45.67.89"). -def htonl(x: int) -> int: - """ - Convert 32-bit positive integer from host to network byte order. - - :param int x: 32-bit positive integer from host. - - :return int: 32-bit positive integer in network byte order. - """ - if byteorder == "big": - return x - return int.from_bytes(x.to_bytes(4, "little"), "big") + :param: str ipv4_address: The string to test. + :return bool: True if a valid IPv4 address, False otherwise. + """ + octets = ipv4_address.split(".", 3) + if len(octets) == 4 and "".join(octets).isdigit(): + if all((0 <= int(octet) <= 255 for octet in octets)): + return True + return False -def htons(x: int) -> int: - """ - Convert 16-bit positive integer from host to network byte order. + def getdefaulttimeout(self) -> Optional[float]: + """ + Return the default timeout in seconds for new socket objects. A value of + None indicates that new socket objects have no timeout. When the socket module is + first imported, the default is None. + """ + return self._default_socket_timeout - :param int x: 16-bit positive integer from host. + def setdefaulttimeout(self, _timeout: Optional[float]) -> None: + """ + Set the default timeout in seconds (float) for new socket objects. When the socket + module is first imported, the default is None. See settimeout() for possible values + and their respective meanings. - :return int: 16-bit positive integer in network byte order. - """ - if byteorder == "big": - return x - return ((x << 8) & 0xFF00) | ((x >> 8) & 0xFF) + :param Optional[float] _timeout: The default timeout in seconds or None. + """ + if _timeout is None or _timeout >= 0: + self._default_socket_timeout = _timeout + else: + raise ValueError("Timeout must be None, 0.0 or a positive numeric value.") + @staticmethod + def htonl(x: int) -> int: + """ + Convert 32-bit positive integer from host to network byte order. -def inet_aton(ip_address: str) -> bytes: - """ - Convert an IPv4 address from dotted-quad string format (for example, "123.45.67.89") - to 32-bit packed binary format, as a bytes object four characters in length. This is - useful when conversing with a program that uses the standard C library and needs - objects of type struct in_addr, which is the C type for the 32-bit packed binary this - function returns. + :param int x: 32-bit positive integer from host. - :param str ip_address: The IPv4 address to convert. + :return int: 32-bit positive integer in network byte order. + """ + if byteorder == "big": + return x + return int.from_bytes(x.to_bytes(4, "little"), "big") - :return bytes: The converted IPv4 address. - """ - if not _is_ipv4_string(ip_address): - raise ValueError("The IPv4 address must be a dotted-quad string.") - return _the_interface.unpretty_ip(ip_address) + @staticmethod + def htons(x: int) -> int: + """ + Convert 16-bit positive integer from host to network byte order. + :param int x: 16-bit positive integer from host. -def inet_ntoa(ip_address: Union[bytes, bytearray]) -> str: - """ - Convert a 32-bit packed IPv4 address (a bytes-like object four bytes in length) to - its standard dotted-quad string representation (for example, ‘123.45.67.89’). This is - useful when conversing with a program that uses the standard C library and needs - objects of type struct in_addr, which is the C type for the 32-bit packed binary data - this function takes as an argument. + :return int: 16-bit positive integer in network byte order. + """ + if byteorder == "big": + return x + return ((x << 8) & 0xFF00) | ((x >> 8) & 0xFF) - :param Union[bytes, bytearray ip_address: The IPv4 address to convert. + def inet_aton(self, ip_address: str) -> bytes: + """ + Convert an IPv4 address from dotted-quad string format (for example, "123.45.67.89") + to 32-bit packed binary format, as a bytes object four characters in length. This is + useful when conversing with a program that uses the standard C library and needs + objects of type struct in_addr, which is the C type for the 32-bit packed binary this + function returns. - :return str: The converted ip_address: - """ - if len(ip_address) != 4: - raise ValueError("The IPv4 address must be 4 bytes.") - return _the_interface.pretty_ip(ip_address) + :param str ip_address: The IPv4 address to convert. + :return bytes: The converted IPv4 address. + """ + if not self._is_ipv4_string(ip_address): + raise ValueError("The IPv4 address must be a dotted-quad string.") + return self._interface.unpretty_ip(ip_address) -# These must match circuitpython "socketpoool" values. However, we cannot -# depend on socketpool being importable, so hard-code them here. -SOCK_STREAM = 1 -SOCK_DGRAM = 2 + def inet_ntoa(self, ip_address: Union[bytes, bytearray]) -> str: + """ + Convert a 32-bit packed IPv4 address (a bytes-like object four bytes in length) to + its standard dotted-quad string representation (for example, ‘123.45.67.89’). This is + useful when conversing with a program that uses the standard C library and needs + objects of type struct in_addr, which is the C type for the 32-bit packed binary data + this function takes as an argument. -_SOCKET_TYPE_TO_WIZNET = b"\0\x21\2" + :param Union[bytes, bytearray ip_address: The IPv4 address to convert. -SOL_SOCKET = 0xFFF -SO_REUSEADDR = 0x0004 + :return str: The converted ip_address: + """ + if len(ip_address) != 4: + raise ValueError("The IPv4 address must be 4 bytes.") + return self._interface.pretty_ip(ip_address) -AF_INET = const(3) -_SOCKET_INVALID = const(255) + def getaddrinfo( # pylint: disable=redefined-builtin,too-many-arguments,unused-argument + self, + host: str, + port: int, + family: int = 0, + type: int = 0, + proto: int = 0, + flags: int = 0, + ) -> List[Tuple[int, int, int, str, Tuple[str, int]]]: + """ + Translate the host/port argument into a sequence of 5-tuples that contain all the necessary + arguments for creating a socket connected to that service. + :param str host: a domain name, a string representation of an IPv4 address or + None. + :param int port: Port number to connect to (0 - 65536). + :param int family: Ignored and hardcoded as 0x03 (the only family implemented) by the + function. + :param int type: The type of socket, either SOCK_STREAM (0x21) for TCP or SOCK_DGRAM (0x02) + for UDP, defaults to 0. + :param int proto: Unused in this implementation of socket. + :param int flags: Unused in this implementation of socket. -# pylint: disable=too-many-arguments, unused-argument -def getaddrinfo( - host: str, - port: int, - family: int = 0, - type: int = 0, - proto: int = 0, - flags: int = 0, -) -> List[Tuple[int, int, int, str, Tuple[str, int]]]: - """ - Translate the host/port argument into a sequence of 5-tuples that contain all the necessary - arguments for creating a socket connected to that service. - - :param str host: a domain name, a string representation of an IPv4 address or - None. - :param int port: Port number to connect to (0 - 65536). - :param int family: Ignored and hardcoded as 0x03 (the only family implemented) by the function. - :param int type: The type of socket, either SOCK_STREAM (0x21) for TCP or SOCK_DGRAM (0x02) - for UDP, defaults to 0. - :param int proto: Unused in this implementation of socket. - :param int flags: Unused in this implementation of socket. - - :return List[Tuple[int, int, int, str, Tuple[str, int]]]: Address info entries in the form - (family, type, proto, canonname, sockaddr). In these tuples, family, type, proto are meant - to be passed to the socket() function. canonname will always be an empty string, sockaddr - is a tuple describing a socket address, whose format is (address, port), and is meant to be - passed to the socket.connect() method. - """ - if not isinstance(port, int): - raise ValueError("Port must be an integer") - if not _is_ipv4_string(host): - host = gethostbyname(host) - return [(AF_INET, type, proto, "", (host, port))] + :return List[Tuple[int, int, int, str, Tuple[str, int]]]: Address info entries in the form + (family, type, proto, canonname, sockaddr). In these tuples, family, type, proto are + meant to be passed to the socket() function. canonname will always be an empty string, + sockaddr is a tuple describing a socket address, whose format is (address, port), and + is meant to be passed to the socket.connect() method. + """ + if not isinstance(port, int): + raise ValueError("Port must be an integer") + if not self._is_ipv4_string(host): + host = self.gethostbyname(host) + return [(SocketPoolContants.AF_INET, type, proto, "", (host, port))] + def gethostbyname(self, hostname: str) -> str: + """ + Translate a host name to IPv4 address format. The IPv4 address is returned as a string, such + as '100.50.200.5'. If the host name is an IPv4 address itself it is returned unchanged. -def gethostbyname(hostname: str) -> str: - """ - Translate a host name to IPv4 address format. The IPv4 address is returned as a string, such - as '100.50.200.5'. If the host name is an IPv4 address itself it is returned unchanged. + :param str hostname: Hostname to lookup. - :param str hostname: Hostname to lookup. + :return str: IPv4 address (a string of the form '0.0.0.0'). + """ + if self._is_ipv4_string(hostname): + return hostname + address = self._interface.get_host_by_name(hostname) + address = "{}.{}.{}.{}".format(address[0], address[1], address[2], address[3]) + return address - :return str: IPv4 address (a string of the form '0.0.0.0'). - """ - if _is_ipv4_string(hostname): - return hostname - address = _the_interface.get_host_by_name(hostname) - address = "{}.{}.{}.{}".format(address[0], address[1], address[2], address[3]) - return address + def socket( # pylint: disable=redefined-builtin + self, + family: int = SocketPoolContants.AF_INET, + type: int = SocketPoolContants.SOCK_STREAM, + proto: int = 0, + fileno: Optional[int] = None, + ): + """Create a new socket and return it""" + return Socket(self, family, type, proto, fileno) -# pylint: disable=invalid-name, too-many-public-methods -class socket: +class Socket: """ A simplified implementation of the Python 'socket' class for connecting to a Wiznet5k module. """ - # pylint: disable=redefined-builtin,unused-argument - def __init__( + def __init__( # pylint: disable=redefined-builtin,too-many-arguments,unused-argument self, - family: int = AF_INET, - type: int = SOCK_STREAM, + socket_pool: SocketPool, + family: int = SocketPool.AF_INET, + type: int = SocketPool.SOCK_STREAM, proto: int = 0, fileno: Optional[int] = None, ) -> None: @@ -234,43 +240,45 @@ def __init__( :param int proto: Unused, retained for compatibility. :param Optional[int] fileno: Unused, retained for compatibility. """ - if family != AF_INET: + if family != SocketPool.AF_INET: raise RuntimeError("Only AF_INET family supported by W5K modules.") + self._socket_pool = socket_pool + self._interface = self._socket_pool._interface self._socket_closed = False self._sock_type = type self._buffer = b"" - self._timeout = _default_socket_timeout + self._timeout = self._socket_pool._default_socket_timeout self._listen_port = None - self._socknum = _the_interface.get_socket(reserve_socket=True) + self._socknum = self._interface.get_socket(reserve_socket=True) if self._socknum == _SOCKET_INVALID: raise RuntimeError("Failed to allocate socket.") def __del__(self): - _the_interface.release_socket(self._socknum) + self._interface.release_socket(self._socknum) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb) -> None: - _the_interface.release_socket(self._socknum) - if self._sock_type == SOCK_STREAM: - _the_interface.write_snir( + self._interface.release_socket(self._socknum) + if self._sock_type == SocketPool.SOCK_STREAM: + self._interface.write_snir( self._socknum, 0xFF & (~wiznet5k.adafruit_wiznet5k.SNIR_DISCON) ) # Reset socket interrupt register. - _the_interface.socket_disconnect(self._socknum) + self._interface.socket_disconnect(self._socknum) mask = ( wiznet5k.adafruit_wiznet5k.SNIR_TIMEOUT | wiznet5k.adafruit_wiznet5k.SNIR_DISCON ) - while not _the_interface.read_snir(self._socknum) & mask: + while not self._interface.read_snir(self._socknum) & mask: pass - _the_interface.write_snir( + self._interface.write_snir( self._socknum, 0xFF ) # Reset socket interrupt register. - _the_interface.socket_close(self._socknum) + self._interface.socket_close(self._socknum) while ( - _the_interface.socket_status(self._socknum) + self._interface.socket_status(self._socknum) != wiznet5k.adafruit_wiznet5k.SNSR_SOCK_CLOSED ): pass @@ -293,7 +301,7 @@ def _status(self) -> int: :return int: Status of the socket. """ - return _the_interface.socket_status(self._socknum) + return self._interface.socket_status(self._socknum) @property def _connected(self) -> bool: @@ -302,11 +310,10 @@ def _connected(self) -> bool: :return bool: Whether connected. """ - # pylint: disable=protected-access - if self._socknum >= _the_interface.max_sockets: + if self._socknum >= self._interface.max_sockets: return False - status = _the_interface.socket_status(self._socknum) + status = self._interface.socket_status(self._socknum) if ( status == wiznet5k.adafruit_wiznet5k.SNSR_SOCK_CLOSE_WAIT and self._available() == 0 @@ -330,7 +337,7 @@ def getpeername(self) -> Tuple[str, int]: :return Tuple[str, int]: IPv4 address and port the socket is connected to. """ - return _the_interface.remote_ip(self._socknum), _the_interface.remote_port( + return self._interface.remote_ip(self._socknum), self._interface.remote_port( self._socknum ) @@ -360,20 +367,20 @@ def _bind(self, address: Tuple[Optional[str], int]) -> None: :param Tuple[Optional[str], int] address: Address as a (host, port) tuple. """ if address[0]: - if gethostbyname(address[0]) != _the_interface.pretty_ip( - _the_interface.ip_address + if self._socket_pool.gethostbyname(address[0]) != self._interface.pretty_ip( + self._interface.ip_address ): raise ValueError( "The IPv4 address requested must match {}, " "the one assigned to the WIZNET5K interface.".format( - _the_interface.pretty_ip(_the_interface.ip_address) + self._interface.pretty_ip(self._interface.ip_address) ) ) self._listen_port = address[1] # For UDP servers we need to open the socket here because we won't call # listen - if self._sock_type == SOCK_DGRAM: - _the_interface.socket_listen( + if self._sock_type == SocketPool.SOCK_DGRAM: + self._interface.socket_listen( self._socknum, self._listen_port, wiznet5k.adafruit_wiznet5k.SNMR_UDP, @@ -381,7 +388,7 @@ def _bind(self, address: Tuple[Optional[str], int]) -> None: self._buffer = b"" @_check_socket_closed - def listen(self, backlog: int = 0) -> None: + def listen(self, backlog: int = 0) -> None: # pylint: disable=unused-argument """ Enable a server to accept connections. @@ -389,13 +396,13 @@ def listen(self, backlog: int = 0) -> None: """ if self._listen_port is None: raise RuntimeError("Use bind to set the port before listen!") - _the_interface.socket_listen(self._socknum, self._listen_port) + self._interface.socket_listen(self._socknum, self._listen_port) self._buffer = b"" @_check_socket_closed def accept( self, - ) -> Tuple[socket, Tuple[str, int]]: + ) -> Tuple[Socket, Tuple[str, int]]: """ Accept a connection. The socket must be bound to an address and listening for connections. @@ -422,10 +429,10 @@ def accept( self.close() self.listen() - _, addr = _the_interface.socket_accept(self._socknum) + _, addr = self._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 = Socket(self._socket_pool) self._socknum = client_sock._socknum # pylint: disable=protected-access client_sock._socknum = current_socknum # pylint: disable=protected-access self._bind((None, self._listen_port)) @@ -442,14 +449,14 @@ def connect(self, address: Tuple[str, int]) -> None: :param Tuple[str, int] address: Remote socket as a (host, port) tuple. """ if self._listen_port is not None: - _the_interface.src_port = self._listen_port - result = _the_interface.socket_connect( + self._interface.src_port = self._listen_port + result = self._interface.socket_connect( self._socknum, - _the_interface.unpretty_ip(gethostbyname(address[0])), + self._interface.unpretty_ip(self._socket_pool.gethostbyname(address[0])), address[1], _SOCKET_TYPE_TO_WIZNET[self._sock_type], ) - _the_interface.src_port = 0 + self._interface.src_port = 0 if not result: raise RuntimeError("Failed to connect to host ", address[0]) self._buffer = b"" @@ -467,7 +474,7 @@ def send(self, data: Union[bytes, bytearray]) -> int: :return int: Number of bytes sent. """ _timeout = 0 if self._timeout is None else self._timeout - bytes_sent = _the_interface.socket_write(self._socknum, data, _timeout) + bytes_sent = self._interface.socket_write(self._socknum, data, _timeout) gc.collect() return bytes_sent @@ -496,8 +503,7 @@ def sendto(self, data: bytearray, *flags_and_or_address: any) -> int: return self.send(data) @_check_socket_closed - def recv( - # pylint: disable=too-many-branches + def recv( # pylint: disable=unused-argument self, bufsize: int, flags: int = 0, @@ -519,9 +525,9 @@ def recv( return bytes(buf[:nread]) return bytes(buf) - def _embed_recv( + def _embed_recv( # pylint: disable=unused-argument self, bufsize: int = 0, flags: int = 0 - ) -> bytes: # pylint: disable=too-many-branches + ) -> bytes: """ Read from the connected remote address. @@ -533,10 +539,10 @@ def _embed_recv( """ avail = self._available() if avail: - if self._sock_type == SOCK_STREAM: - self._buffer += _the_interface.socket_read(self._socknum, avail)[1] - elif self._sock_type == SOCK_DGRAM: - self._buffer += _the_interface.read_udp(self._socknum, avail)[1] + if self._sock_type == SocketPool.SOCK_STREAM: + self._buffer += self._interface.socket_read(self._socknum, avail)[1] + elif self._sock_type == SocketPool.SOCK_DGRAM: + self._buffer += self._interface.read_udp(self._socknum, avail)[1] gc.collect() ret = self._buffer self._buffer = b"" @@ -544,7 +550,9 @@ def _embed_recv( return ret @_check_socket_closed - def recvfrom(self, bufsize: int, flags: int = 0) -> Tuple[bytes, Tuple[str, int]]: + def recvfrom( # pylint: disable=unused-argument + self, bufsize: int, flags: int = 0 + ) -> Tuple[bytes, Tuple[str, int]]: """ Receive data from the socket. The return value is a pair (bytes, address) where bytes is a bytes object representing the data received and address is the address of the socket @@ -559,13 +567,15 @@ def recvfrom(self, bufsize: int, flags: int = 0) -> Tuple[bytes, Tuple[str, int] return ( self.recv(bufsize), ( - _the_interface.pretty_ip(_the_interface.udp_from_ip[self._socknum]), - _the_interface.udp_from_port[self._socknum], + self._interface.pretty_ip(self._interface.udp_from_ip[self._socknum]), + self._interface.udp_from_port[self._socknum], ), ) @_check_socket_closed - def recv_into(self, buffer: bytearray, nbytes: int = 0, flags: int = 0) -> int: + def recv_into( # pylint: disable=unused-argument + self, buffer: bytearray, nbytes: int = 0, flags: int = 0 + ) -> int: """ Receive up to nbytes bytes from the socket, storing the data into a buffer rather than creating a new bytestring. @@ -600,12 +610,12 @@ def recv_into(self, buffer: bytearray, nbytes: int = 0, flags: int = 0) -> int: if num_avail > 0: last_read_time = ticks_ms() bytes_to_read = min(num_to_read, num_avail) - if self._sock_type == SOCK_STREAM: - bytes_read = _the_interface.socket_read( + if self._sock_type == SocketPool.SOCK_STREAM: + bytes_read = self._interface.socket_read( self._socknum, bytes_to_read )[1] else: - bytes_read = _the_interface.read_udp(self._socknum, bytes_to_read)[ + bytes_read = self._interface.read_udp(self._socknum, bytes_to_read)[ 1 ] buffer[num_read : num_read + len(bytes_read)] = bytes_read @@ -632,7 +642,7 @@ def recv_into(self, buffer: bytearray, nbytes: int = 0, flags: int = 0) -> int: return num_read @_check_socket_closed - def recvfrom_into( + def recvfrom_into( # pylint: disable=unused-argument self, buffer: bytearray, nbytes: int = 0, flags: int = 0 ) -> Tuple[int, Tuple[str, int]]: """ @@ -649,8 +659,8 @@ def recvfrom_into( return ( self.recv_into(buffer, nbytes), ( - _the_interface.remote_ip(self._socknum), - _the_interface.remote_port(self._socknum), + self._interface.remote_ip(self._socknum), + self._interface.remote_port(self._socknum), ), ) @@ -669,10 +679,10 @@ def _readline(self) -> bytes: while b"\r\n" not in self._buffer: avail = self._available() if avail: - if self._sock_type == SOCK_STREAM: - self._buffer += _the_interface.socket_read(self._socknum, avail)[1] - elif self._sock_type == SOCK_DGRAM: - self._buffer += _the_interface.read_udp(self._socknum, avail)[1] + if self._sock_type == SocketPool.SOCK_STREAM: + self._buffer += self._interface.socket_read(self._socknum, avail)[1] + elif self._sock_type == SocketPool.SOCK_DGRAM: + self._buffer += self._interface.read_udp(self._socknum, avail)[1] if ( self._timeout and not avail @@ -686,9 +696,9 @@ def _readline(self) -> bytes: def _disconnect(self) -> None: """Disconnect a TCP socket.""" - if self._sock_type != SOCK_STREAM: + if self._sock_type != SocketPool.SOCK_STREAM: raise RuntimeError("Socket must be a TCP socket.") - _the_interface.socket_disconnect(self._socknum) + self._interface.socket_disconnect(self._socknum) @_check_socket_closed def close(self) -> None: @@ -696,8 +706,8 @@ def close(self) -> None: Mark the socket closed. Once that happens, all future operations on the socket object will fail. The remote end will receive no more data. """ - _the_interface.release_socket(self._socknum) - _the_interface.socket_close(self._socknum) + self._interface.release_socket(self._socknum) + self._interface.socket_close(self._socknum) self._socket_closed = True def _available(self) -> int: @@ -706,12 +716,13 @@ def _available(self) -> int: :return int: Number of bytes available. """ - return _the_interface.socket_available( - self._socknum, _SOCKET_TYPE_TO_WIZNET[self._sock_type] + return self._interface.socket_available( + self._socknum, + _SOCKET_TYPE_TO_WIZNET[self._sock_type], ) @_check_socket_closed - def setsockopt( # pylint: disable=no-self-use + def setsockopt( # pylint: disable=no-self-use,unused-argument self, level: int, opt: int, value: any ) -> None: """ @@ -720,7 +731,7 @@ def setsockopt( # pylint: disable=no-self-use Only SOL_SOCKET SO_REUSEADDR is accepted (and the value is ignored). Other calls result in OSError.""" - if level == SOL_SOCKET and opt == SO_REUSEADDR: + if level == SocketPool.SOL_SOCKET and opt == SocketPool.SO_REUSEADDR: return raise OSError @@ -804,12 +815,9 @@ def proto(self): return 0 -class timeout(TimeoutError): +class timeout(TimeoutError): # pylint: disable=invalid-name """TimeoutError class. An instance of this error will be raised by recv_into() if the timeout has elapsed and we haven't received any data yet.""" def __init__(self, msg): super().__init__(ETIMEDOUT, msg) - - -# pylint: enable=unused-argument, redefined-builtin, invalid-name diff --git a/docs/api.rst b/docs/api.rst index e5d5331..6c431a8 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -7,7 +7,7 @@ .. automodule:: adafruit_wiznet5k.adafruit_wiznet5k :members: -.. automodule:: adafruit_wiznet5k.adafruit_wiznet5k_socket +.. automodule:: adafruit_wiznet5k.adafruit_wiznet5k_socketpool :members: .. automodule:: adafruit_wiznet5k.adafruit_wiznet5k_dhcp diff --git a/examples/wiznet5k_httpserver.py b/examples/wiznet5k_httpserver.py index 7f7d8b3..fcc40e4 100644 --- a/examples/wiznet5k_httpserver.py +++ b/examples/wiznet5k_httpserver.py @@ -5,7 +5,7 @@ import digitalio from adafruit_httpserver import Server, Request, Response from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K -import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket +import adafruit_wiznet5k.adafruit_wiznet5k_socketpool as socketpool print("Wiznet5k HTTPServer Test") @@ -18,11 +18,11 @@ # Initialize ethernet interface with DHCP eth = WIZNET5K(spi_bus, cs) -# set the interface on the socket source -socket.set_interface(eth) +# Create a socket pool +pool = socketpool.SocketPool(eth) # initialize the server -server = Server(socket, "/static", debug=True) +server = Server(pool, "/static", debug=True) @server.route("/") diff --git a/examples/wiznet5k_simpleserver.py b/examples/wiznet5k_simpleserver.py index 82a2cc3..732a76c 100644 --- a/examples/wiznet5k_simpleserver.py +++ b/examples/wiznet5k_simpleserver.py @@ -7,7 +7,7 @@ import busio import digitalio from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K -import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket +import adafruit_wiznet5k.adafruit_wiznet5k_socketpool as socketpool print("Wiznet5k SimpleServer Test") @@ -21,8 +21,8 @@ eth = WIZNET5K(spi_bus, cs, is_dhcp=True) # Initialize a socket for our server -socket.set_interface(eth) -server = socket.socket() # Allocate socket for the server +pool = socketpool.SocketPool(eth) +server = pool.socket() # Allocate socket for the server server_ip = eth.pretty_ip(eth.ip_address) # IP address of server server_port = 50007 # Port to listen on server.bind((server_ip, server_port)) # Bind to IP and Port