Skip to content

Commit a33c93b

Browse files
committed
Ethernet: fixed wrong handling of timeouts in DHCP
The signed math doesn't handle correctly cases where the lease time is set to infinity (0xFFFFFFFF). Fixes #2571 Fixes #2601 Fixes #2642 Fixes #985
1 parent 50dff34 commit a33c93b

File tree

2 files changed

+27
-31
lines changed

2 files changed

+27
-31
lines changed

libraries/Ethernet/src/Dhcp.cpp

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ int DhcpClass::request_DHCP_lease(){
124124
_dhcpUdpSocket.stop();
125125
_dhcpTransactionId++;
126126

127-
_secTimeout = millis() + 1000;
127+
_lastCheckLeaseMillis = millis();
128128
return result;
129129
}
130130

@@ -392,45 +392,41 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr
392392
4/DHCP_CHECK_REBIND_OK: rebind success
393393
*/
394394
int DhcpClass::checkLease(){
395-
//this uses a signed / unsigned trick to deal with millis overflow
395+
int rc = DHCP_CHECK_NONE;
396+
396397
unsigned long now = millis();
397-
signed long snow = (long)now;
398-
int rc=DHCP_CHECK_NONE;
399-
400-
signed long factor;
401-
//calc how many ms past the timeout we are
402-
factor = snow - (long)_secTimeout;
403-
//if on or passed the timeout, reduce the counters
404-
if ( factor >= 0 ){
405-
//next timeout should be now plus 1000 ms minus parts of second in factor
406-
_secTimeout = snow + 1000 - factor % 1000;
407-
//how many seconds late are we, minimum 1
408-
factor = factor / 1000 +1;
409-
410-
//reduce the counters by that mouch
411-
//if we can assume that the cycle time (factor) is fairly constant
412-
//and if the remainder is less than cycle time * 2
413-
//do it early instead of late
414-
if(_renewInSec < factor*2 )
398+
unsigned long elapsed = now - _lastCheckLeaseMillis;
399+
400+
// if more then one sec passed, reduce the counters accordingly
401+
if (elapsed >= 1000) {
402+
// set the new timestamps
403+
_lastCheckLeaseMillis = now - (elapsed % 1000);
404+
elapsed = elapsed / 1000;
405+
406+
// decrease the counters by elapsed seconds
407+
// we assume that the cycle time (elapsed) is fairly constant
408+
// if the remainder is less than cycle time * 2
409+
// do it early instead of late
410+
if (_renewInSec < elapsed * 2)
415411
_renewInSec = 0;
416412
else
417-
_renewInSec -= factor;
413+
_renewInSec -= elapsed;
418414

419-
if(_rebindInSec < factor*2 )
415+
if (_rebindInSec < elapsed * 2)
420416
_rebindInSec = 0;
421417
else
422-
_rebindInSec -= factor;
418+
_rebindInSec -= elapsed;
423419
}
424420

425-
//if we have a lease but should renew, do it
426-
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
421+
// if we have a lease but should renew, do it
422+
if (_renewInSec == 0 &&_dhcp_state == STATE_DHCP_LEASED) {
427423
_dhcp_state = STATE_DHCP_REREQUEST;
428424
rc = 1 + request_DHCP_lease();
429425
}
430426

431-
//if we have a lease or is renewing but should bind, do it
432-
if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
433-
//this should basically restart completely
427+
// if we have a lease or is renewing but should bind, do it
428+
if (_rebindInSec == 0 && (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START)) {
429+
// this should basically restart completely
434430
_dhcp_state = STATE_DHCP_START;
435431
reset_DHCP_lease();
436432
rc = 3 + request_DHCP_lease();

libraries/Ethernet/src/Dhcp.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ class DhcpClass {
148148
uint8_t _dhcpDnsServerIp[4];
149149
uint32_t _dhcpLeaseTime;
150150
uint32_t _dhcpT1, _dhcpT2;
151-
signed long _renewInSec;
152-
signed long _rebindInSec;
151+
unsigned long _renewInSec;
152+
unsigned long _rebindInSec;
153153
unsigned long _timeout;
154154
unsigned long _responseTimeout;
155-
unsigned long _secTimeout;
155+
unsigned long _lastCheckLeaseMillis;
156156
uint8_t _dhcp_state;
157157
EthernetUDP _dhcpUdpSocket;
158158

0 commit comments

Comments
 (0)