Skip to content

Commit 7805e1a

Browse files
author
BiffoBear
committed
Move all socket calls to _receive_dhcp_response and _handle_dhcp_message.
1 parent a5a6d60 commit 7805e1a

File tree

1 file changed

+52
-79
lines changed

1 file changed

+52
-79
lines changed

adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py

Lines changed: 52 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ def __init__(
147147

148148
# Set socket interface
149149
self._eth = eth
150-
self._wiz_sock = None
151150

152151
# DHCP state machine
153152
self._dhcp_state = _STATE_INIT
@@ -211,45 +210,6 @@ def _dsm_reset(self) -> None:
211210
self._increment_transaction_id()
212211
self._start_time = time.monotonic()
213212

214-
def _socket_release(self) -> None:
215-
"""Close the socket if it exists."""
216-
debug_msg("Releasing socket.", self._debug)
217-
if self._wiz_sock is not None:
218-
self._eth.socket_close(self._wiz_sock)
219-
self._wiz_sock = None
220-
debug_msg(" Socket released.", self._debug)
221-
222-
def _dhcp_connection_setup(self, timeout: float = 5.0) -> None:
223-
"""Initialise a UDP socket.
224-
225-
Attempt to initialise a UDP socket. If the finite state machine (FSM) is in
226-
blocking mode, repeat failed attempts until a socket is initialised or
227-
the operation times out, then raise an exception. If the FSM is in non-blocking
228-
mode, ignore the error and return.
229-
230-
:param int timeout: Time to keep retrying if the FSM is in blocking mode.
231-
Defaults to 5.
232-
233-
:raises TimeoutError: If the FSM is in blocking mode and a socket cannot be
234-
initialised.
235-
"""
236-
stop_time = time.monotonic() + timeout
237-
debug_msg("Setting up connection for DHCP.", self._debug)
238-
while self._wiz_sock is None and time.monotonic() < stop_time:
239-
self._wiz_sock = self._eth.get_socket()
240-
if self._wiz_sock == 0xFF:
241-
self._wiz_sock = None
242-
while time.monotonic() < stop_time:
243-
self._eth.write_snmr(self._wiz_sock, 0x02) # Set UDP connection
244-
self._eth.write_sock_port(self._wiz_sock, 68) # Set DHCP client port.
245-
self._eth.write_sncr(self._wiz_sock, 0x01) # Open the socket.
246-
if self._eth.read_snsr(self._wiz_sock) == 0x22:
247-
self._eth.write_sndport(2, _DHCP_SERVER_PORT)
248-
debug_msg("+ Connection OK, port set.", self._debug)
249-
return
250-
self._wiz_sock = None
251-
raise RuntimeError("Unable to initialize UDP socket.")
252-
253213
def _increment_transaction_id(self) -> None:
254214
"""Increment the transaction ID and roll over from 0x7fffffff to 0."""
255215
debug_msg("Incrementing transaction ID", self._debug)
@@ -278,7 +238,7 @@ def _next_retry_time(self, *, attempt: int, interval: int = 4) -> float:
278238
delay = 2**attempt * interval + randint(-1, 1) + time.monotonic()
279239
return delay
280240

281-
def _receive_dhcp_response(self, timeout: float) -> int:
241+
def _receive_dhcp_response(self, socket_num: int, timeout: float) -> int:
282242
"""
283243
Receive data from the socket in response to a DHCP query.
284244
@@ -288,23 +248,22 @@ def _receive_dhcp_response(self, timeout: float) -> int:
288248
If the packet is too short, it is discarded and zero is returned. The
289249
maximum packet size is limited by the size of the global buffer.
290250
291-
:param float timeout: time.monotonic at which attempt should timeout.
251+
:param int socket_num: Socket to read from.
252+
:param float timeout: time.monotonic at which attempt should time out.
292253
293254
:returns int: The number of bytes stored in the global buffer.
294255
"""
295256
debug_msg("Receiving a DHCP response.", self._debug)
296257
while time.monotonic() < timeout:
297258
# DHCP returns the query plus additional data. The query length is 236 bytes.
298-
if self._eth.socket_available(self._wiz_sock, _SNMR_UDP) > 236:
299-
bytes_count, bytes_read = self._eth.read_udp(
300-
self._wiz_sock, _BUFF_LENGTH
301-
)
259+
if self._eth.socket_available(socket_num, _SNMR_UDP) > 236:
260+
bytes_count, bytes_read = self._eth.read_udp(socket_num, _BUFF_LENGTH)
302261
_BUFF[:bytes_count] = bytes_read
303262
debug_msg("Received {} bytes".format(bytes_count), self._debug)
304263
del bytes_read
305264
gc.collect()
306265
return bytes_count
307-
raise TimeoutError("No DHCP response received.")
266+
return 0 # No bytes received.
308267

309268
def _process_messaging_states(self, *, message_type: int):
310269
"""
@@ -355,6 +314,7 @@ def _handle_dhcp_message(self) -> int:
355314
:raises TimeoutError: If the FSM is in blocking mode and no valid response has
356315
been received before the timeout expires.
357316
"""
317+
# pylint: disable=too-many-branches
358318
debug_msg("Processing SELECTING or REQUESTING state.", self._debug)
359319
if self._dhcp_state == _STATE_SELECTING:
360320
msg_type_out = _DHCP_DISCOVER
@@ -364,40 +324,53 @@ def _handle_dhcp_message(self) -> int:
364324
raise ValueError(
365325
"FSM can only send messages while in SELECTING or REQUESTING states."
366326
)
367-
self._dhcp_connection_setup()
368-
message_length = self._generate_dhcp_message(message_type=msg_type_out)
369-
for attempt in range(4): # Initial attempt plus 3 retries.
370-
if self._renew:
371-
dhcp_server_address = self.dhcp_server_ip
372-
else:
373-
dhcp_server_address = _BROADCAST_SERVER_ADDR
374-
self._eth.write_sndipr(self._wiz_sock, dhcp_server_address)
375-
self._eth.write_sndport(self._wiz_sock, _DHCP_SERVER_PORT)
376-
self._eth.socket_write(self._wiz_sock, _BUFF[:message_length])
377-
next_resend = self._next_retry_time(attempt=attempt)
378-
while time.monotonic() < next_resend:
379-
if self._receive_dhcp_response(next_resend):
380-
try:
381-
msg_type_in = self._parse_dhcp_response()
327+
debug_msg("Setting up connection for DHCP.", self._debug)
328+
if self._renew:
329+
dhcp_server = self.dhcp_server_ip
330+
else:
331+
dhcp_server = _BROADCAST_SERVER_ADDR
332+
sock_num = None
333+
deadline = time.monotonic() + 5.0
334+
try:
335+
while sock_num is None:
336+
sock_num = self._eth.get_socket()
337+
if sock_num == 0xFF:
338+
sock_num = None
339+
if time.monotonic() > deadline:
340+
raise RuntimeError("Unable to initialize UDP socket.")
341+
342+
self._eth.src_port = 68
343+
self._eth.socket_connect(
344+
sock_num, dhcp_server, _DHCP_SERVER_PORT, conn_mode=0x02
345+
)
346+
self._eth.src_port = 0
347+
348+
message_length = self._generate_dhcp_message(message_type=msg_type_out)
349+
for attempt in range(4): # Initial attempt plus 3 retries.
350+
self._eth.socket_write(sock_num, _BUFF[:message_length])
351+
next_resend = self._next_retry_time(attempt=attempt)
352+
while time.monotonic() < next_resend:
353+
if self._receive_dhcp_response(sock_num, next_resend):
354+
try:
355+
msg_type_in = self._parse_dhcp_response()
356+
debug_msg(
357+
"Received message type {}".format(msg_type_in),
358+
self._debug,
359+
)
360+
return msg_type_in
361+
except ValueError as error:
362+
debug_msg(error, self._debug)
363+
if not self._blocking or self._renew:
382364
debug_msg(
383-
"Received message type {}".format(msg_type_in), self._debug
365+
"No message, FSM is nonblocking or renewing, exiting loop.",
366+
self._debug,
384367
)
385-
return msg_type_in
386-
except ValueError as error:
387-
debug_msg(error, self._debug)
388-
finally:
389-
self._socket_release()
390-
if not self._blocking or self._renew:
391-
debug_msg(
392-
"No message, FSM is nonblocking or renewing, exiting loop.",
393-
self._debug,
394-
)
395-
self._socket_release()
396-
return 0 # Did not receive a response in a single attempt.
397-
self._socket_release()
398-
raise TimeoutError(
399-
"No response from DHCP server after {} retries.".format(attempt)
400-
)
368+
return 0 # Did not receive a response in a single attempt.
369+
raise TimeoutError(
370+
"No response from DHCP server after {} retries.".format(attempt)
371+
)
372+
finally:
373+
self._eth.socket_close(sock_num) # Close the socket whatever happens.
401374

402375
def _dhcp_state_machine(self, *, blocking: bool = False) -> None:
403376
"""

0 commit comments

Comments
 (0)