1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-03-15 12:29:26 +01:00

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
This commit is contained in:
Cristian Maglie 2015-06-04 16:41:10 +02:00
parent 50dff341f2
commit a33c93b194
2 changed files with 27 additions and 31 deletions

View File

@ -124,7 +124,7 @@ int DhcpClass::request_DHCP_lease(){
_dhcpUdpSocket.stop(); _dhcpUdpSocket.stop();
_dhcpTransactionId++; _dhcpTransactionId++;
_secTimeout = millis() + 1000; _lastCheckLeaseMillis = millis();
return result; return result;
} }
@ -392,45 +392,41 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr
4/DHCP_CHECK_REBIND_OK: rebind success 4/DHCP_CHECK_REBIND_OK: rebind success
*/ */
int DhcpClass::checkLease(){ int DhcpClass::checkLease(){
//this uses a signed / unsigned trick to deal with millis overflow int rc = DHCP_CHECK_NONE;
unsigned long now = millis(); unsigned long now = millis();
signed long snow = (long)now; unsigned long elapsed = now - _lastCheckLeaseMillis;
int rc=DHCP_CHECK_NONE;
signed long factor; // if more then one sec passed, reduce the counters accordingly
//calc how many ms past the timeout we are if (elapsed >= 1000) {
factor = snow - (long)_secTimeout; // set the new timestamps
//if on or passed the timeout, reduce the counters _lastCheckLeaseMillis = now - (elapsed % 1000);
if ( factor >= 0 ){ elapsed = elapsed / 1000;
//next timeout should be now plus 1000 ms minus parts of second in factor
_secTimeout = snow + 1000 - factor % 1000;
//how many seconds late are we, minimum 1
factor = factor / 1000 +1;
//reduce the counters by that mouch // decrease the counters by elapsed seconds
//if we can assume that the cycle time (factor) is fairly constant // we assume that the cycle time (elapsed) is fairly constant
//and if the remainder is less than cycle time * 2 // if the remainder is less than cycle time * 2
//do it early instead of late // do it early instead of late
if(_renewInSec < factor*2 ) if (_renewInSec < elapsed * 2)
_renewInSec = 0; _renewInSec = 0;
else else
_renewInSec -= factor; _renewInSec -= elapsed;
if(_rebindInSec < factor*2 ) if (_rebindInSec < elapsed * 2)
_rebindInSec = 0; _rebindInSec = 0;
else else
_rebindInSec -= factor; _rebindInSec -= elapsed;
} }
//if we have a lease but should renew, do it // if we have a lease but should renew, do it
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ if (_renewInSec == 0 &&_dhcp_state == STATE_DHCP_LEASED) {
_dhcp_state = STATE_DHCP_REREQUEST; _dhcp_state = STATE_DHCP_REREQUEST;
rc = 1 + request_DHCP_lease(); rc = 1 + request_DHCP_lease();
} }
//if we have a lease or is renewing but should bind, do it // if we have a lease or is renewing but should bind, do it
if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ if (_rebindInSec == 0 && (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START)) {
//this should basically restart completely // this should basically restart completely
_dhcp_state = STATE_DHCP_START; _dhcp_state = STATE_DHCP_START;
reset_DHCP_lease(); reset_DHCP_lease();
rc = 3 + request_DHCP_lease(); rc = 3 + request_DHCP_lease();

View File

@ -148,11 +148,11 @@ private:
uint8_t _dhcpDnsServerIp[4]; uint8_t _dhcpDnsServerIp[4];
uint32_t _dhcpLeaseTime; uint32_t _dhcpLeaseTime;
uint32_t _dhcpT1, _dhcpT2; uint32_t _dhcpT1, _dhcpT2;
signed long _renewInSec; unsigned long _renewInSec;
signed long _rebindInSec; unsigned long _rebindInSec;
unsigned long _timeout; unsigned long _timeout;
unsigned long _responseTimeout; unsigned long _responseTimeout;
unsigned long _secTimeout; unsigned long _lastCheckLeaseMillis;
uint8_t _dhcp_state; uint8_t _dhcp_state;
EthernetUDP _dhcpUdpSocket; EthernetUDP _dhcpUdpSocket;