@@ -147,7 +147,6 @@ def __init__(
147
147
148
148
# Set socket interface
149
149
self ._eth = eth
150
- self ._wiz_sock = None
151
150
152
151
# DHCP state machine
153
152
self ._dhcp_state = _STATE_INIT
@@ -211,45 +210,6 @@ def _dsm_reset(self) -> None:
211
210
self ._increment_transaction_id ()
212
211
self ._start_time = time .monotonic ()
213
212
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
-
253
213
def _increment_transaction_id (self ) -> None :
254
214
"""Increment the transaction ID and roll over from 0x7fffffff to 0."""
255
215
debug_msg ("Incrementing transaction ID" , self ._debug )
@@ -278,7 +238,7 @@ def _next_retry_time(self, *, attempt: int, interval: int = 4) -> float:
278
238
delay = 2 ** attempt * interval + randint (- 1 , 1 ) + time .monotonic ()
279
239
return delay
280
240
281
- def _receive_dhcp_response (self , timeout : float ) -> int :
241
+ def _receive_dhcp_response (self , socket_num : int , timeout : float ) -> int :
282
242
"""
283
243
Receive data from the socket in response to a DHCP query.
284
244
@@ -288,23 +248,22 @@ def _receive_dhcp_response(self, timeout: float) -> int:
288
248
If the packet is too short, it is discarded and zero is returned. The
289
249
maximum packet size is limited by the size of the global buffer.
290
250
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.
292
253
293
254
:returns int: The number of bytes stored in the global buffer.
294
255
"""
295
256
debug_msg ("Receiving a DHCP response." , self ._debug )
296
257
while time .monotonic () < timeout :
297
258
# 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 )
302
261
_BUFF [:bytes_count ] = bytes_read
303
262
debug_msg ("Received {} bytes" .format (bytes_count ), self ._debug )
304
263
del bytes_read
305
264
gc .collect ()
306
265
return bytes_count
307
- raise TimeoutError ( "No DHCP response received." )
266
+ return 0 # No bytes received.
308
267
309
268
def _process_messaging_states (self , * , message_type : int ):
310
269
"""
@@ -355,6 +314,7 @@ def _handle_dhcp_message(self) -> int:
355
314
:raises TimeoutError: If the FSM is in blocking mode and no valid response has
356
315
been received before the timeout expires.
357
316
"""
317
+ # pylint: disable=too-many-branches
358
318
debug_msg ("Processing SELECTING or REQUESTING state." , self ._debug )
359
319
if self ._dhcp_state == _STATE_SELECTING :
360
320
msg_type_out = _DHCP_DISCOVER
@@ -364,40 +324,53 @@ def _handle_dhcp_message(self) -> int:
364
324
raise ValueError (
365
325
"FSM can only send messages while in SELECTING or REQUESTING states."
366
326
)
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 :
382
364
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 ,
384
367
)
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.
401
374
402
375
def _dhcp_state_machine (self , * , blocking : bool = False ) -> None :
403
376
"""
0 commit comments