From 5fd12457dbda5c717149d5dbb45e154a7467733d Mon Sep 17 00:00:00 2001
From: BiffoBear <martin@martinstehens.net>
Date: Wed, 21 Jun 2023 08:26:04 +0700
Subject: [PATCH 1/6] Move message generation outside loop.

---
 adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
index 8d42ca7..ccc6f76 100644
--- a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
+++ b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
@@ -366,9 +366,8 @@ def _handle_dhcp_message(self) -> int:
             raise ValueError(
                 "FSM can only send messages while in SELECTING or REQUESTING states."
             )
+        message_length = self._generate_dhcp_message(message_type=msg_type_out)
         for attempt in range(4):  # Initial attempt plus 3 retries.
-            message_length = self._generate_dhcp_message(message_type=msg_type_out)
-
             if self._renew:
                 dhcp_server_address = self.dhcp_server_ip
             else:

From ba001b791a887b745c955dc254650d81a7e87210 Mon Sep 17 00:00:00 2001
From: BiffoBear <martin@martinstehens.net>
Date: Wed, 21 Jun 2023 08:29:51 +0700
Subject: [PATCH 2/6] Move move get UDP port to _handle_dhcp_message.

---
 adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
index ccc6f76..51292b3 100644
--- a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
+++ b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
@@ -197,7 +197,6 @@ def _dsm_reset(self) -> None:
         state machine INIT state."""
         debug_msg("Resetting DHCP state machine.", self._debug)
         self._socket_release()
-        self._dhcp_connection_setup()
         self.dhcp_server_ip = _BROADCAST_SERVER_ADDR
         self._eth.ifconfig = (
             _UNASSIGNED_IP_ADDR,
@@ -366,6 +365,7 @@ def _handle_dhcp_message(self) -> int:
             raise ValueError(
                 "FSM can only send messages while in SELECTING or REQUESTING states."
             )
+        self._dhcp_connection_setup()
         message_length = self._generate_dhcp_message(message_type=msg_type_out)
         for attempt in range(4):  # Initial attempt plus 3 retries.
             if self._renew:
@@ -431,7 +431,6 @@ def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
             if self._dhcp_state == _STATE_RENEWING:
                 debug_msg("FSM state is RENEWING.", self._debug)
                 self._renew = "renew"
-                self._dhcp_connection_setup()
                 self._start_time = time.monotonic()
                 self._dhcp_state = _STATE_REQUESTING
 
@@ -439,7 +438,6 @@ def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
                 debug_msg("FSM state is REBINDING.", self._debug)
                 self._renew = "rebind"
                 self.dhcp_server_ip = _BROADCAST_SERVER_ADDR
-                self._dhcp_connection_setup()
                 self._start_time = time.monotonic()
                 self._dhcp_state = _STATE_REQUESTING
 

From a5a6d60ece3099f9c7437c47023fd4198e24fa25 Mon Sep 17 00:00:00 2001
From: BiffoBear <martin@martinstehens.net>
Date: Wed, 21 Jun 2023 08:45:37 +0700
Subject: [PATCH 3/6] Move close UDP port to _handle_dhcp_message.

---
 adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
index 51292b3..dd03cd9 100644
--- a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
+++ b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
@@ -196,7 +196,6 @@ def _dsm_reset(self) -> None:
         """Close the socket and set attributes to default values used by the
         state machine INIT state."""
         debug_msg("Resetting DHCP state machine.", self._debug)
-        self._socket_release()
         self.dhcp_server_ip = _BROADCAST_SERVER_ADDR
         self._eth.ifconfig = (
             _UNASSIGNED_IP_ADDR,
@@ -215,7 +214,7 @@ def _dsm_reset(self) -> None:
     def _socket_release(self) -> None:
         """Close the socket if it exists."""
         debug_msg("Releasing socket.", self._debug)
-        if self._wiz_sock:
+        if self._wiz_sock is not None:
             self._eth.socket_close(self._wiz_sock)
             self._wiz_sock = None
         debug_msg("  Socket released.", self._debug)
@@ -386,12 +385,16 @@ def _handle_dhcp_message(self) -> int:
                         return msg_type_in
                     except ValueError as error:
                         debug_msg(error, self._debug)
+                    finally:
+                        self._socket_release()
                 if not self._blocking or self._renew:
                     debug_msg(
                         "No message, FSM is nonblocking or renewing, exiting loop.",
                         self._debug,
                     )
+                    self._socket_release()
                     return 0  # Did not receive a response in a single attempt.
+        self._socket_release()
         raise TimeoutError(
             "No response from DHCP server after {} retries.".format(attempt)
         )
@@ -409,7 +412,6 @@ def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
                 now = time.monotonic()
                 if now < self._t1:
                     debug_msg("No timers have expired. Exiting FSM.", self._debug)
-                    self._socket_release()
                     return
                 if now > self._lease:
                     debug_msg(

From 7805e1a3958de591ffb61ceb52084ade6eae274e Mon Sep 17 00:00:00 2001
From: BiffoBear <martin@martinstehens.net>
Date: Wed, 21 Jun 2023 14:20:08 +0700
Subject: [PATCH 4/6] Move all socket calls to _receive_dhcp_response and
 _handle_dhcp_message.

---
 adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py | 131 ++++++++------------
 1 file changed, 52 insertions(+), 79 deletions(-)

diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
index dd03cd9..b4ff581 100644
--- a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
+++ b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py
@@ -147,7 +147,6 @@ def __init__(
 
         # Set socket interface
         self._eth = eth
-        self._wiz_sock = None
 
         # DHCP state machine
         self._dhcp_state = _STATE_INIT
@@ -211,45 +210,6 @@ def _dsm_reset(self) -> None:
         self._increment_transaction_id()
         self._start_time = time.monotonic()
 
-    def _socket_release(self) -> None:
-        """Close the socket if it exists."""
-        debug_msg("Releasing socket.", self._debug)
-        if self._wiz_sock is not None:
-            self._eth.socket_close(self._wiz_sock)
-            self._wiz_sock = None
-        debug_msg("  Socket released.", self._debug)
-
-    def _dhcp_connection_setup(self, timeout: float = 5.0) -> None:
-        """Initialise a UDP socket.
-
-        Attempt to initialise a UDP socket. If the finite state machine (FSM) is in
-        blocking mode, repeat failed attempts until a socket is initialised or
-        the operation times out, then raise an exception. If the FSM is in non-blocking
-        mode, ignore the error and return.
-
-        :param int timeout: Time to keep retrying if the FSM is in blocking mode.
-            Defaults to 5.
-
-        :raises TimeoutError: If the FSM is in blocking mode and a socket cannot be
-            initialised.
-        """
-        stop_time = time.monotonic() + timeout
-        debug_msg("Setting up connection for DHCP.", self._debug)
-        while self._wiz_sock is None and time.monotonic() < stop_time:
-            self._wiz_sock = self._eth.get_socket()
-            if self._wiz_sock == 0xFF:
-                self._wiz_sock = None
-        while time.monotonic() < stop_time:
-            self._eth.write_snmr(self._wiz_sock, 0x02)  # Set UDP connection
-            self._eth.write_sock_port(self._wiz_sock, 68)  # Set DHCP client port.
-            self._eth.write_sncr(self._wiz_sock, 0x01)  # Open the socket.
-            if self._eth.read_snsr(self._wiz_sock) == 0x22:
-                self._eth.write_sndport(2, _DHCP_SERVER_PORT)
-                debug_msg("+ Connection OK, port set.", self._debug)
-                return
-        self._wiz_sock = None
-        raise RuntimeError("Unable to initialize UDP socket.")
-
     def _increment_transaction_id(self) -> None:
         """Increment the transaction ID and roll over from 0x7fffffff to 0."""
         debug_msg("Incrementing transaction ID", self._debug)
@@ -278,7 +238,7 @@ def _next_retry_time(self, *, attempt: int, interval: int = 4) -> float:
         delay = 2**attempt * interval + randint(-1, 1) + time.monotonic()
         return delay
 
-    def _receive_dhcp_response(self, timeout: float) -> int:
+    def _receive_dhcp_response(self, socket_num: int, timeout: float) -> int:
         """
         Receive data from the socket in response to a DHCP query.
 
@@ -288,23 +248,22 @@ def _receive_dhcp_response(self, timeout: float) -> int:
         If the packet is too short, it is discarded and zero is returned. The
         maximum packet size is limited by the size of the global buffer.
 
-        :param float timeout: time.monotonic at which attempt should timeout.
+        :param int socket_num: Socket to read from.
+        :param float timeout: time.monotonic at which attempt should time out.
 
         :returns int: The number of bytes stored in the global buffer.
         """
         debug_msg("Receiving a DHCP response.", self._debug)
         while time.monotonic() < timeout:
             # DHCP returns the query plus additional data. The query length is 236 bytes.
-            if self._eth.socket_available(self._wiz_sock, _SNMR_UDP) > 236:
-                bytes_count, bytes_read = self._eth.read_udp(
-                    self._wiz_sock, _BUFF_LENGTH
-                )
+            if self._eth.socket_available(socket_num, _SNMR_UDP) > 236:
+                bytes_count, bytes_read = self._eth.read_udp(socket_num, _BUFF_LENGTH)
                 _BUFF[:bytes_count] = bytes_read
                 debug_msg("Received {} bytes".format(bytes_count), self._debug)
                 del bytes_read
                 gc.collect()
                 return bytes_count
-        raise TimeoutError("No DHCP response received.")
+        return 0  # No bytes received.
 
     def _process_messaging_states(self, *, message_type: int):
         """
@@ -355,6 +314,7 @@ def _handle_dhcp_message(self) -> int:
         :raises TimeoutError: If the FSM is in blocking mode and no valid response has
             been received before the timeout expires.
         """
+        # pylint: disable=too-many-branches
         debug_msg("Processing SELECTING or REQUESTING state.", self._debug)
         if self._dhcp_state == _STATE_SELECTING:
             msg_type_out = _DHCP_DISCOVER
@@ -364,40 +324,53 @@ def _handle_dhcp_message(self) -> int:
             raise ValueError(
                 "FSM can only send messages while in SELECTING or REQUESTING states."
             )
-        self._dhcp_connection_setup()
-        message_length = self._generate_dhcp_message(message_type=msg_type_out)
-        for attempt in range(4):  # Initial attempt plus 3 retries.
-            if self._renew:
-                dhcp_server_address = self.dhcp_server_ip
-            else:
-                dhcp_server_address = _BROADCAST_SERVER_ADDR
-            self._eth.write_sndipr(self._wiz_sock, dhcp_server_address)
-            self._eth.write_sndport(self._wiz_sock, _DHCP_SERVER_PORT)
-            self._eth.socket_write(self._wiz_sock, _BUFF[:message_length])
-            next_resend = self._next_retry_time(attempt=attempt)
-            while time.monotonic() < next_resend:
-                if self._receive_dhcp_response(next_resend):
-                    try:
-                        msg_type_in = self._parse_dhcp_response()
+        debug_msg("Setting up connection for DHCP.", self._debug)
+        if self._renew:
+            dhcp_server = self.dhcp_server_ip
+        else:
+            dhcp_server = _BROADCAST_SERVER_ADDR
+        sock_num = None
+        deadline = time.monotonic() + 5.0
+        try:
+            while sock_num is None:
+                sock_num = self._eth.get_socket()
+                if sock_num == 0xFF:
+                    sock_num = None
+                if time.monotonic() > deadline:
+                    raise RuntimeError("Unable to initialize UDP socket.")
+
+            self._eth.src_port = 68
+            self._eth.socket_connect(
+                sock_num, dhcp_server, _DHCP_SERVER_PORT, conn_mode=0x02
+            )
+            self._eth.src_port = 0
+
+            message_length = self._generate_dhcp_message(message_type=msg_type_out)
+            for attempt in range(4):  # Initial attempt plus 3 retries.
+                self._eth.socket_write(sock_num, _BUFF[:message_length])
+                next_resend = self._next_retry_time(attempt=attempt)
+                while time.monotonic() < next_resend:
+                    if self._receive_dhcp_response(sock_num, next_resend):
+                        try:
+                            msg_type_in = self._parse_dhcp_response()
+                            debug_msg(
+                                "Received message type {}".format(msg_type_in),
+                                self._debug,
+                            )
+                            return msg_type_in
+                        except ValueError as error:
+                            debug_msg(error, self._debug)
+                    if not self._blocking or self._renew:
                         debug_msg(
-                            "Received message type {}".format(msg_type_in), self._debug
+                            "No message, FSM is nonblocking or renewing, exiting loop.",
+                            self._debug,
                         )
-                        return msg_type_in
-                    except ValueError as error:
-                        debug_msg(error, self._debug)
-                    finally:
-                        self._socket_release()
-                if not self._blocking or self._renew:
-                    debug_msg(
-                        "No message, FSM is nonblocking or renewing, exiting loop.",
-                        self._debug,
-                    )
-                    self._socket_release()
-                    return 0  # Did not receive a response in a single attempt.
-        self._socket_release()
-        raise TimeoutError(
-            "No response from DHCP server after {} retries.".format(attempt)
-        )
+                        return 0  # Did not receive a response in a single attempt.
+            raise TimeoutError(
+                "No response from DHCP server after {} retries.".format(attempt)
+            )
+        finally:
+            self._eth.socket_close(sock_num)  # Close the socket whatever happens.
 
     def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
         """

From 79668f482757248d7c5f52d8171de934657d59f3 Mon Sep 17 00:00:00 2001
From: BiffoBear <martin@martinstehens.net>
Date: Wed, 21 Jun 2023 15:14:25 +0700
Subject: [PATCH 5/6] Refactor, rename methods to reflect their private status.

---
 adafruit_wiznet5k/adafruit_wiznet5k.py | 62 +++++++++++++-------------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/adafruit_wiznet5k/adafruit_wiznet5k.py b/adafruit_wiznet5k/adafruit_wiznet5k.py
index 278b886..5452f82 100644
--- a/adafruit_wiznet5k/adafruit_wiznet5k.py
+++ b/adafruit_wiznet5k/adafruit_wiznet5k.py
@@ -156,7 +156,7 @@
 _MR_RST = const(0x80)  # Mode Register RST
 # Socket mode register
 _SNMR_CLOSE = const(0x00)
-SNMR_TCP = const(0x21)
+_SNMR_TCP = const(0x21)
 SNMR_UDP = const(0x02)
 _SNMR_IPRAW = const(0x03)
 _SNMR_MACRAW = const(0x04)
@@ -492,7 +492,7 @@ def ifconfig(
 
     # *** Public Socket Methods ***
 
-    def socket_available(self, socket_num: int, sock_type: int = SNMR_TCP) -> int:
+    def socket_available(self, socket_num: int, sock_type: int = _SNMR_TCP) -> int:
         """
         Number of bytes available to be read from the socket.
 
@@ -514,7 +514,7 @@ def socket_available(self, socket_num: int, sock_type: int = SNMR_TCP) -> int:
         self._sock_num_in_range(socket_num)
 
         number_of_bytes = self._get_rx_rcv_size(socket_num)
-        if self.read_snsr(socket_num) == SNMR_UDP:
+        if self._read_snsr(socket_num) == SNMR_UDP:
             number_of_bytes -= 8  # Subtract UDP header from packet size.
         if number_of_bytes < 0:
             raise ValueError("Negative number of bytes found on socket.")
@@ -533,14 +533,14 @@ def socket_status(self, socket_num: int) -> int:
 
         :return int: The connection status.
         """
-        return self.read_snsr(socket_num)
+        return self._read_snsr(socket_num)
 
     def socket_connect(
         self,
         socket_num: int,
         dest: IpAddress4Raw,
         port: int,
-        conn_mode: int = SNMR_TCP,
+        conn_mode: int = _SNMR_TCP,
     ) -> int:
         """
         Open and verify a connection from a socket to a destination IPv4 address
@@ -567,11 +567,11 @@ def socket_connect(
         # initialize a socket and set the mode
         self.socket_open(socket_num, conn_mode=conn_mode)
         # set socket destination IP and port
-        self.write_sndipr(socket_num, dest)
-        self.write_sndport(socket_num, port)
-        self.write_sncr(socket_num, _CMD_SOCK_CONNECT)
+        self._write_sndipr(socket_num, dest)
+        self._write_sndport(socket_num, port)
+        self._write_sncr(socket_num, _CMD_SOCK_CONNECT)
 
-        if conn_mode == SNMR_TCP:
+        if conn_mode == _SNMR_TCP:
             # wait for tcp connection establishment
             while self.socket_status(socket_num) != SNSR_SOCK_ESTABLISHED:
                 time.sleep(0.001)
@@ -638,7 +638,7 @@ def release_socket(self, socket_number):
         WIZNET5K._sockets_reserved[socket_number - 1] = False
 
     def socket_listen(
-        self, socket_num: int, port: int, conn_mode: int = SNMR_TCP
+        self, socket_num: int, port: int, conn_mode: int = _SNMR_TCP
     ) -> None:
         """
         Listen on a socket's port.
@@ -665,7 +665,7 @@ def socket_listen(
         self.socket_open(socket_num, conn_mode=conn_mode)
         self.src_port = 0
         # Send listen command
-        self.write_sncr(socket_num, _CMD_SOCK_LISTEN)
+        self._write_sncr(socket_num, _CMD_SOCK_LISTEN)
         # Wait until ready
         status = SNSR_SOCK_CLOSED
         while status not in (
@@ -673,7 +673,7 @@ def socket_listen(
             SNSR_SOCK_ESTABLISHED,
             _SNSR_SOCK_UDP,
         ):
-            status = self.read_snsr(socket_num)
+            status = self._read_snsr(socket_num)
             if status == SNSR_SOCK_CLOSED:
                 raise RuntimeError("Listening socket closed.")
 
@@ -703,7 +703,7 @@ def socket_accept(self, socket_num: int) -> Tuple[int, Tuple[str, int]]:
         )
         return next_socknum, (dest_ip, dest_port)
 
-    def socket_open(self, socket_num: int, conn_mode: int = SNMR_TCP) -> None:
+    def socket_open(self, socket_num: int, conn_mode: int = _SNMR_TCP) -> None:
         """
         Open an IP socket.
 
@@ -720,7 +720,7 @@ def socket_open(self, socket_num: int, conn_mode: int = SNMR_TCP) -> None:
         self._sock_num_in_range(socket_num)
         self._check_link_status()
         debug_msg("*** Opening socket {}".format(socket_num), self._debug)
-        if self.read_snsr(socket_num) not in (
+        if self._read_snsr(socket_num) not in (
             SNSR_SOCK_CLOSED,
             SNSR_SOCK_TIME_WAIT,
             SNSR_SOCK_FIN_WAIT,
@@ -732,22 +732,22 @@ def socket_open(self, socket_num: int, conn_mode: int = SNMR_TCP) -> None:
         debug_msg("* Opening W5k Socket, protocol={}".format(conn_mode), self._debug)
         time.sleep(0.00025)
 
-        self.write_snmr(socket_num, conn_mode)
+        self._write_snmr(socket_num, conn_mode)
         self.write_snir(socket_num, 0xFF)
 
         if self.src_port > 0:
             # write to socket source port
-            self.write_sock_port(socket_num, self.src_port)
+            self._write_sock_port(socket_num, self.src_port)
         else:
             s_port = randint(49152, 65535)
             while s_port in self._src_ports_in_use:
                 s_port = randint(49152, 65535)
-            self.write_sock_port(socket_num, s_port)
+            self._write_sock_port(socket_num, s_port)
             self._src_ports_in_use[socket_num] = s_port
 
         # open socket
-        self.write_sncr(socket_num, _CMD_SOCK_OPEN)
-        if self.read_snsr(socket_num) not in [_SNSR_SOCK_INIT, _SNSR_SOCK_UDP]:
+        self._write_sncr(socket_num, _CMD_SOCK_OPEN)
+        if self._read_snsr(socket_num) not in [_SNSR_SOCK_INIT, _SNSR_SOCK_UDP]:
             raise RuntimeError("Could not open socket in TCP or UDP mode.")
 
     def socket_close(self, socket_num: int) -> None:
@@ -760,14 +760,14 @@ def socket_close(self, socket_num: int) -> None:
         """
         debug_msg("*** Closing socket {}".format(socket_num), self._debug)
         self._sock_num_in_range(socket_num)
-        self.write_sncr(socket_num, _CMD_SOCK_CLOSE)
+        self._write_sncr(socket_num, _CMD_SOCK_CLOSE)
         debug_msg("  Waiting for socket to close…", self._debug)
         timeout = time.monotonic() + 5.0
-        while self.read_snsr(socket_num) != SNSR_SOCK_CLOSED:
+        while self._read_snsr(socket_num) != SNSR_SOCK_CLOSED:
             if time.monotonic() > timeout:
                 raise RuntimeError(
                     "Wiznet5k failed to close socket, status = {}.".format(
-                        self.read_snsr(socket_num)
+                        self._read_snsr(socket_num)
                     )
                 )
             time.sleep(0.0001)
@@ -783,7 +783,7 @@ def socket_disconnect(self, socket_num: int) -> None:
         """
         debug_msg("*** Disconnecting socket {}".format(socket_num), self._debug)
         self._sock_num_in_range(socket_num)
-        self.write_sncr(socket_num, _CMD_SOCK_DISCON)
+        self._write_sncr(socket_num, _CMD_SOCK_DISCON)
 
     def socket_read(self, socket_num: int, length: int) -> Tuple[int, bytes]:
         """
@@ -819,7 +819,7 @@ def socket_read(self, socket_num: int, length: int) -> Tuple[int, bytes]:
             # After reading the received data, update Sn_RX_RD register.
             pointer = (pointer + bytes_on_socket) & 0xFFFF
             self._write_snrx_rd(socket_num, pointer)
-            self.write_sncr(socket_num, _CMD_SOCK_RECV)
+            self._write_sncr(socket_num, _CMD_SOCK_RECV)
         else:
             # no data on socket
             if self._read_snmr(socket_num) in (
@@ -906,7 +906,7 @@ def socket_write(
         # update sn_tx_wr to the value + data size
         pointer = (pointer + bytes_to_write) & 0xFFFF
         self._write_sntx_wr(socket_num, pointer)
-        self.write_sncr(socket_num, _CMD_SOCK_SEND)
+        self._write_sncr(socket_num, _CMD_SOCK_SEND)
 
         # check data was  transferred correctly
         while not self.read_snir(socket_num) & _SNIR_SEND_OK:
@@ -1175,18 +1175,18 @@ def _read_sndipr(self, sock) -> bytes:
             )
         return bytes(data)
 
-    def write_sndipr(self, sock: int, ip_addr: bytes) -> None:
+    def _write_sndipr(self, sock: int, ip_addr: bytes) -> None:
         """Write to socket destination IP Address."""
         for offset, value in enumerate(ip_addr):
             self._write_socket_register(
                 sock, _REG_SNDIPR[self._chip_type] + offset, value
             )
 
-    def write_sndport(self, sock: int, port: int) -> None:
+    def _write_sndport(self, sock: int, port: int) -> None:
         """Write to socket destination port."""
         self._write_two_byte_sock_reg(sock, _REG_SNDPORT[self._chip_type], port)
 
-    def read_snsr(self, sock: int) -> int:
+    def _read_snsr(self, sock: int) -> int:
         """Read Socket n Status Register."""
         return self._read_socket_register(sock, _REG_SNSR[self._chip_type])
 
@@ -1202,15 +1202,15 @@ def _read_snmr(self, sock: int) -> int:
         """Read the socket MR register."""
         return self._read_socket_register(sock, _REG_SNMR)
 
-    def write_snmr(self, sock: int, protocol: int) -> None:
+    def _write_snmr(self, sock: int, protocol: int) -> None:
         """Write to Socket n Mode Register."""
         self._write_socket_register(sock, _REG_SNMR, protocol)
 
-    def write_sock_port(self, sock: int, port: int) -> None:
+    def _write_sock_port(self, sock: int, port: int) -> None:
         """Write to the socket port number."""
         self._write_two_byte_sock_reg(sock, _REG_SNPORT[self._chip_type], port)
 
-    def write_sncr(self, sock: int, data: int) -> None:
+    def _write_sncr(self, sock: int, data: int) -> None:
         """Write to socket command register."""
         self._write_socket_register(sock, _REG_SNCR[self._chip_type], data)
         # Wait for command to complete before continuing.

From 91d1f31054c656308e689bb3eee0bf9c823256f6 Mon Sep 17 00:00:00 2001
From: BiffoBear <martin@martinstehens.net>
Date: Wed, 21 Jun 2023 16:13:58 +0700
Subject: [PATCH 6/6] Add _read_socket_reservations and _read_sndport methods
 to aid trouble shooting.

---
 adafruit_wiznet5k/adafruit_wiznet5k.py | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/adafruit_wiznet5k/adafruit_wiznet5k.py b/adafruit_wiznet5k/adafruit_wiznet5k.py
index 5452f82..692bc57 100644
--- a/adafruit_wiznet5k/adafruit_wiznet5k.py
+++ b/adafruit_wiznet5k/adafruit_wiznet5k.py
@@ -1057,6 +1057,11 @@ def _check_link_status(self):
         if not self.link_status:
             raise ConnectionError("The Ethernet connection is down.")
 
+    @staticmethod
+    def _read_socket_reservations() -> list[int]:
+        """Return the list of reserved sockets."""
+        return WIZNET5K._sockets_reserved
+
     def _read_mr(self) -> int:
         """Read from the Mode Register (MR)."""
         return int.from_bytes(self._read(_REG_MR[self._chip_type], 0x00), "big")
@@ -1182,6 +1187,10 @@ def _write_sndipr(self, sock: int, ip_addr: bytes) -> None:
                 sock, _REG_SNDIPR[self._chip_type] + offset, value
             )
 
+    def _read_sndport(self, sock: int) -> int:
+        """Read socket destination port."""
+        return self._read_two_byte_sock_reg(sock, _REG_SNDPORT[self._chip_type])
+
     def _write_sndport(self, sock: int, port: int) -> None:
         """Write to socket destination port."""
         self._write_two_byte_sock_reg(sock, _REG_SNDPORT[self._chip_type], port)