1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-03-14 11: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 
Fixes 
Fixes 
Fixes 
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
libraries/Ethernet/src

@ -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();
signed long snow = (long)now;
int rc=DHCP_CHECK_NONE;
signed long factor; unsigned long now = millis();
//calc how many ms past the timeout we are unsigned long elapsed = now - _lastCheckLeaseMillis;
factor = snow - (long)_secTimeout;
//if on or passed the timeout, reduce the counters // if more then one sec passed, reduce the counters accordingly
if ( factor >= 0 ){ if (elapsed >= 1000) {
//next timeout should be now plus 1000 ms minus parts of second in factor // set the new timestamps
_secTimeout = snow + 1000 - factor % 1000; _lastCheckLeaseMillis = now - (elapsed % 1000);
//how many seconds late are we, minimum 1 elapsed = elapsed / 1000;
factor = factor / 1000 +1;
// decrease the counters by elapsed seconds
//reduce the counters by that mouch // we assume that the cycle time (elapsed) is fairly constant
//if we can assume that the cycle time (factor) is fairly constant // if the remainder is less than cycle time * 2
//and if the remainder is less than cycle time * 2 // do it early instead of late
//do it early instead of late if (_renewInSec < elapsed * 2)
if(_renewInSec < factor*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();

@ -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;