9
9
#include " Arduino.h"
10
10
#include " util.h"
11
11
12
+
12
13
int DhcpClass::beginWithDHCP (uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
13
14
{
15
+ initialize (mac, timeout, responseTimeout);
16
+ int result = 0 ;
17
+ while (result == 0 ) {
18
+ result = successful ();
19
+ }
20
+ return _dhcp_state;
21
+ }
22
+
23
+ void DhcpClass::initialize (uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) {
14
24
_dhcpLeaseTime=0 ;
15
25
_dhcpT1=0 ;
16
26
_dhcpT2=0 ;
@@ -24,107 +34,127 @@ int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long
24
34
25
35
memcpy ((void *)_dhcpMacAddr, (void *)mac, 6 );
26
36
_dhcp_state = STATE_DHCP_START;
27
- return request_DHCP_lease ();
37
+ init_new_DHCP_request ();
28
38
}
29
39
30
40
void DhcpClass::reset_DHCP_lease (){
31
41
// zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
32
42
memset (_dhcpLocalIp, 0 , 20 );
33
43
}
34
44
35
- // return:0 on error, 1 if request is sent and response is received
36
- int DhcpClass::request_DHCP_lease (){
37
-
38
- uint8_t messageType = 0 ;
39
-
40
-
45
+ // 0 = not finished, 1 = finished and successful, 2 = finished but failed
46
+ int DhcpClass::successful () {
47
+ int result = step_DHCP_lease ();
48
+ if ((millis () - _startTime) > _timeout) {
49
+ result = 2 ;
50
+ _dhcp_state = STATE_DHCP_TIMEOUT;
51
+ }
52
+ if (result > 0 ) {
53
+ _dhcpUdpSocket.stop ();
54
+ _dhcpTransactionId++;
55
+ }
56
+ return result;
57
+ }
41
58
59
+ void DhcpClass::init_new_DHCP_request (){
42
60
// Pick an initial transaction ID
43
61
_dhcpTransactionId = random (1UL , 2000UL );
44
62
_dhcpInitialTransactionId = _dhcpTransactionId;
45
63
46
- _dhcpUdpSocket.stop ();
47
64
if (_dhcpUdpSocket.begin (DHCP_CLIENT_PORT) == 0 )
48
65
{
49
- // Couldn't get a socket
50
- return 0 ;
66
+ _dhcp_state = STATE_DHCP_CONNECTION_FAILED;
51
67
}
68
+ _startTime = millis ();
69
+ }
70
+
71
+ // return:0 on error, 1 if request is sent and response is received
72
+ int DhcpClass::request_DHCP_lease (){
73
+ init_new_DHCP_request ();
52
74
53
75
presend_DHCP ();
54
76
55
77
int result = 0 ;
78
+ do {
79
+ result = step_DHCP_lease ();
80
+ } while (result == 0 && ((millis () - _startTime) > _timeout));
81
+
82
+ _dhcpUdpSocket.stop ();
83
+ _dhcpTransactionId++;
84
+
85
+ return result == 1 ;
86
+ }
87
+
88
+ int DhcpClass::step_DHCP_lease (){
89
+ int result = 0 ;
90
+ uint8_t messageType = 0 ;
91
+
92
+ if (_dhcp_state == STATE_DHCP_CONNECTION_FAILED) {
93
+ return 2 ;
94
+ }
95
+ if (_dhcp_state == STATE_DHCP_LEASED) {
96
+ return 1 ;
97
+ }
56
98
57
- unsigned long startTime = millis ();
99
+ if (_dhcp_state == STATE_DHCP_START)
100
+ {
101
+ _dhcpTransactionId++;
58
102
59
- while (_dhcp_state != STATE_DHCP_LEASED)
103
+ send_DHCP_MESSAGE (DHCP_DISCOVER, ((millis () - _startTime) / 1000 ));
104
+ _startResponseTime = millis ();
105
+ _dhcp_state = STATE_DHCP_DISCOVER;
106
+ }
107
+ else if (_dhcp_state == STATE_DHCP_REREQUEST){
108
+ _dhcpTransactionId++;
109
+ send_DHCP_MESSAGE (DHCP_REQUEST, ((millis () - _startTime)/1000 ));
110
+ _startResponseTime = millis ();
111
+ _dhcp_state = STATE_DHCP_REQUEST;
112
+ }
113
+ else if (_dhcp_state == STATE_DHCP_DISCOVER)
60
114
{
61
- if (_dhcp_state == STATE_DHCP_START)
115
+ uint32_t respId;
116
+ messageType = tryParseDHCPResponse (respId);
117
+ if (messageType == DHCP_OFFER)
62
118
{
63
- _dhcpTransactionId++;
64
-
65
- send_DHCP_MESSAGE (DHCP_DISCOVER, ((millis () - startTime) / 1000 ));
66
- _dhcp_state = STATE_DHCP_DISCOVER;
67
- }
68
- else if (_dhcp_state == STATE_DHCP_REREQUEST){
69
- _dhcpTransactionId++;
70
- send_DHCP_MESSAGE (DHCP_REQUEST, ((millis () - startTime)/1000 ));
119
+ // We'll use the transaction ID that the offer came with,
120
+ // rather than the one we were up to
121
+ _dhcpTransactionId = respId;
122
+ send_DHCP_MESSAGE (DHCP_REQUEST, ((millis () - _startTime) / 1000 ));
71
123
_dhcp_state = STATE_DHCP_REQUEST;
72
124
}
73
- else if (_dhcp_state == STATE_DHCP_DISCOVER)
125
+ }
126
+ else if (_dhcp_state == STATE_DHCP_REQUEST)
127
+ {
128
+ uint32_t respId;
129
+ messageType = tryParseDHCPResponse (respId);
130
+ if (messageType == DHCP_ACK)
74
131
{
75
- uint32_t respId;
76
- messageType = parseDHCPResponse (_responseTimeout, respId);
77
- if (messageType == DHCP_OFFER)
78
- {
79
- // We'll use the transaction ID that the offer came with,
80
- // rather than the one we were up to
81
- _dhcpTransactionId = respId;
82
- send_DHCP_MESSAGE (DHCP_REQUEST, ((millis () - startTime) / 1000 ));
83
- _dhcp_state = STATE_DHCP_REQUEST;
132
+ _dhcp_state = STATE_DHCP_LEASED;
133
+ result = 1 ;
134
+ // use default lease time if we didn't get it
135
+ if (_dhcpLeaseTime == 0 ){
136
+ _dhcpLeaseTime = DEFAULT_LEASE;
84
137
}
85
- }
86
- else if (_dhcp_state == STATE_DHCP_REQUEST)
87
- {
88
- uint32_t respId;
89
- messageType = parseDHCPResponse (_responseTimeout, respId);
90
- if (messageType == DHCP_ACK)
91
- {
92
- _dhcp_state = STATE_DHCP_LEASED;
93
- result = 1 ;
94
- // use default lease time if we didn't get it
95
- if (_dhcpLeaseTime == 0 ){
96
- _dhcpLeaseTime = DEFAULT_LEASE;
97
- }
98
- // calculate T1 & T2 if we didn't get it
99
- if (_dhcpT1 == 0 ){
100
- // T1 should be 50% of _dhcpLeaseTime
101
- _dhcpT1 = _dhcpLeaseTime >> 1 ;
102
- }
103
- if (_dhcpT2 == 0 ){
104
- // T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
105
- _dhcpT2 = _dhcpT1 << 1 ;
106
- }
107
- _renewInSec = _dhcpT1;
108
- _rebindInSec = _dhcpT2;
138
+ // calculate T1 & T2 if we didn't get it
139
+ if (_dhcpT1 == 0 ){
140
+ // T1 should be 50% of _dhcpLeaseTime
141
+ _dhcpT1 = _dhcpLeaseTime >> 1 ;
142
+ }
143
+ if (_dhcpT2 == 0 ){
144
+ // T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
145
+ _dhcpT2 = _dhcpT1 << 1 ;
109
146
}
110
- else if (messageType == DHCP_NAK)
111
- _dhcp_state = STATE_DHCP_START ;
147
+ _renewInSec = _dhcpT1;
148
+ _rebindInSec = _dhcpT2 ;
112
149
}
113
-
114
- if (messageType == 255 )
115
- {
116
- messageType = 0 ;
150
+ else if (messageType == DHCP_NAK)
117
151
_dhcp_state = STATE_DHCP_START;
118
- }
119
-
120
- if (result != 1 && ((millis () - startTime) > _timeout))
121
- break ;
122
152
}
123
153
124
- // We're done with the socket now
125
- _dhcpUdpSocket. stop ();
126
- _dhcpTransactionId++;
127
-
154
+ if (messageType == 255 && (( millis () - _startResponseTime) > _responseTimeout))
155
+ {
156
+ _dhcp_state = STATE_DHCP_START; // response timeout, restart DHCP
157
+ }
128
158
return result;
129
159
}
130
160
@@ -250,20 +280,13 @@ void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
250
280
_dhcpUdpSocket.endPacket ();
251
281
}
252
282
253
- uint8_t DhcpClass::parseDHCPResponse ( unsigned long responseTimeout, uint32_t & transactionId)
254
- {
283
+ uint8_t DhcpClass::tryParseDHCPResponse ( uint32_t & transactionId) {
284
+
255
285
uint8_t type = 0 ;
256
286
uint8_t opt_len = 0 ;
257
287
258
- unsigned long startTime = millis ();
259
-
260
- while (_dhcpUdpSocket.parsePacket () <= 0 )
261
- {
262
- if ((millis () - startTime) > responseTimeout)
263
- {
264
- return 255 ;
265
- }
266
- delay (50 );
288
+ if (_dhcpUdpSocket.parsePacket () <= 0 ) {
289
+ return 255 ;
267
290
}
268
291
// start reading in the packet
269
292
RIP_MSG_FIXED fixedMsg;
@@ -382,13 +405,12 @@ uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& tr
382
405
}
383
406
384
407
408
+
385
409
/*
386
410
returns:
387
411
0/DHCP_CHECK_NONE: nothing happened
388
- 1/DHCP_CHECK_RENEW_FAIL: renew failed
389
- 2/DHCP_CHECK_RENEW_OK: renew success
390
- 3/DHCP_CHECK_REBIND_FAIL: rebind fail
391
- 4/DHCP_CHECK_REBIND_OK: rebind success
412
+ 1/DHCP_CHECK_RENEW_STARTED: a new renew was initiated, call successful()
413
+ 2/DHCP_CHECK_REBIND_STARTED: a new rebind was initiated, call successful()
392
414
*/
393
415
int DhcpClass::checkLease (){
394
416
// this uses a signed / unsigned trick to deal with millis overflow
@@ -424,15 +446,17 @@ int DhcpClass::checkLease(){
424
446
// if we have a lease but should renew, do it
425
447
if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0 ){
426
448
_dhcp_state = STATE_DHCP_REREQUEST;
427
- rc = 1 + request_DHCP_lease ();
449
+ init_new_DHCP_request ();
450
+ rc = 1 ;
428
451
}
429
452
430
453
// if we have a lease or is renewing but should bind, do it
431
454
if ( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0 ){
432
455
// this should basically restart completely
433
456
_dhcp_state = STATE_DHCP_START;
434
457
reset_DHCP_lease ();
435
- rc = 3 + request_DHCP_lease ();
458
+ init_new_DHCP_request ();
459
+ rc = 2 ;
436
460
}
437
461
}
438
462
else {
0 commit comments