UIPEthernet library for Arduino IDE, Eclipse with arduino plugin and MBED/SMeshStudio (AVR,STM32F,ESP8266,Intel ARC32,Nordic nRF51,Teensy boards,Realtek Ameba(RTL8195A,RTL8710)), ENC28j60 network chip. Compatible with Wiznet W5100 Ethernet library API. Compiled and tested on Nucleo-F302R8. Master repository is: https://github.com/UIPEthernet/UIPEthernet/

Committer:
cassyarduino
Date:
Tue Jan 23 15:08:43 2018 +0100
Revision:
39:deeb00b81cc9
Parent:
38:645b253e6b50
Release: 2.0.4

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cassyarduino 0:e3fb1267e3c3 1 // DHCP Library v0.3 - April 25, 2009
cassyarduino 0:e3fb1267e3c3 2 // Author: Jordan Terrell - blog.jordanterrell.com
cassyarduino 0:e3fb1267e3c3 3
cassyarduino 0:e3fb1267e3c3 4 #include <string.h>
cassyarduino 0:e3fb1267e3c3 5 #include <stdlib.h>
cassyarduino 33:7ba5d53df0f2 6 #include "utility/uipopt.h"
cassyarduino 33:7ba5d53df0f2 7 #if UIP_UDP
cassyarduino 0:e3fb1267e3c3 8 #include "Dhcp.h"
cassyarduino 0:e3fb1267e3c3 9 #if defined(ARDUINO)
cassyarduino 0:e3fb1267e3c3 10 #include <Arduino.h>
cassyarduino 0:e3fb1267e3c3 11 #endif
cassyarduino 0:e3fb1267e3c3 12 #if defined(__MBED__)
cassyarduino 0:e3fb1267e3c3 13 #include <mbed.h>
cassyarduino 0:e3fb1267e3c3 14 #include "mbed/millis.h"
cassyarduino 0:e3fb1267e3c3 15 #define delay(x) wait_ms(x)
cassyarduino 0:e3fb1267e3c3 16 #endif
cassyarduino 0:e3fb1267e3c3 17 #include "utility/logging.h"
cassyarduino 0:e3fb1267e3c3 18 #include "utility/uip.h"
cassyarduino 0:e3fb1267e3c3 19
cassyarduino 38:645b253e6b50 20 int DhcpClass::beginWithDHCP(uint8_t *mac)
cassyarduino 0:e3fb1267e3c3 21 {
cassyarduino 33:7ba5d53df0f2 22 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 23 LogObject.uart_send_strln(F("DhcpClass::beginWithDHCP(uint8_t *mac) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 24 #endif
cassyarduino 0:e3fb1267e3c3 25 _dhcpLeaseTime=0;
cassyarduino 0:e3fb1267e3c3 26 _dhcpT1=0;
cassyarduino 0:e3fb1267e3c3 27 _dhcpT2=0;
cassyarduino 0:e3fb1267e3c3 28 _lastCheck=0;
cassyarduino 0:e3fb1267e3c3 29
cassyarduino 0:e3fb1267e3c3 30 // zero out _dhcpMacAddr
cassyarduino 0:e3fb1267e3c3 31 memset(_dhcpMacAddr, 0, 6);
cassyarduino 0:e3fb1267e3c3 32 reset_DHCP_lease();
cassyarduino 0:e3fb1267e3c3 33
cassyarduino 0:e3fb1267e3c3 34 memcpy((void*)_dhcpMacAddr, (void*)mac, 6);
cassyarduino 0:e3fb1267e3c3 35 _dhcp_state = STATE_DHCP_START;
cassyarduino 0:e3fb1267e3c3 36 return request_DHCP_lease();
cassyarduino 0:e3fb1267e3c3 37 }
cassyarduino 0:e3fb1267e3c3 38
cassyarduino 0:e3fb1267e3c3 39 void DhcpClass::reset_DHCP_lease(void){
cassyarduino 33:7ba5d53df0f2 40 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 41 LogObject.uart_send_strln(F("DhcpClass::reset_DHCP_lease(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 42 #endif
cassyarduino 38:645b253e6b50 43 // zero out _dhcpipv4struct.SubnetMask, _dhcpipv4struct.GatewayIp, _dhcpipv4struct.LocalIp, _dhcpipv4struct.DhcpServerIp, _dhcpipv4struct.DnsServerIp
cassyarduino 38:645b253e6b50 44 memset(&_dhcpipv4struct, 0, sizeof(_dhcpipv4struct));
cassyarduino 0:e3fb1267e3c3 45 }
cassyarduino 0:e3fb1267e3c3 46
cassyarduino 0:e3fb1267e3c3 47 //return:0 on error, 1 if request is sent and response is received
cassyarduino 0:e3fb1267e3c3 48 int DhcpClass::request_DHCP_lease(void){
cassyarduino 33:7ba5d53df0f2 49 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 50 LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 51 #endif
cassyarduino 0:e3fb1267e3c3 52
cassyarduino 0:e3fb1267e3c3 53 uint8_t messageType = 0;
cassyarduino 0:e3fb1267e3c3 54
cassyarduino 0:e3fb1267e3c3 55
cassyarduino 0:e3fb1267e3c3 56
cassyarduino 0:e3fb1267e3c3 57 // Pick an initial transaction ID
cassyarduino 0:e3fb1267e3c3 58 #if defined(ARDUINO)
cassyarduino 0:e3fb1267e3c3 59 _dhcpTransactionId = random(1UL, 2000UL);
cassyarduino 0:e3fb1267e3c3 60 #endif
cassyarduino 0:e3fb1267e3c3 61 #if defined(__MBED__)
cassyarduino 0:e3fb1267e3c3 62 _dhcpTransactionId = (rand() % 2000UL) + 1;
cassyarduino 0:e3fb1267e3c3 63 #endif
cassyarduino 0:e3fb1267e3c3 64 _dhcpInitialTransactionId = _dhcpTransactionId;
cassyarduino 0:e3fb1267e3c3 65
cassyarduino 0:e3fb1267e3c3 66 _dhcpUdpSocket.stop();
cassyarduino 0:e3fb1267e3c3 67 if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0)
cassyarduino 0:e3fb1267e3c3 68 {
cassyarduino 0:e3fb1267e3c3 69 // Couldn't get a socket
cassyarduino 0:e3fb1267e3c3 70 return 0;
cassyarduino 0:e3fb1267e3c3 71 }
cassyarduino 0:e3fb1267e3c3 72
cassyarduino 0:e3fb1267e3c3 73 presend_DHCP();
cassyarduino 0:e3fb1267e3c3 74
cassyarduino 0:e3fb1267e3c3 75 int result = 0;
cassyarduino 0:e3fb1267e3c3 76
cassyarduino 0:e3fb1267e3c3 77 unsigned long startTime = millis();
cassyarduino 0:e3fb1267e3c3 78
cassyarduino 0:e3fb1267e3c3 79 while(_dhcp_state != STATE_DHCP_LEASED)
cassyarduino 0:e3fb1267e3c3 80 {
cassyarduino 0:e3fb1267e3c3 81 if(_dhcp_state == STATE_DHCP_START)
cassyarduino 0:e3fb1267e3c3 82 {
cassyarduino 33:7ba5d53df0f2 83 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 84 LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_START -> send_DHCP_MESSAGE DHCP_DISCOVER"));
cassyarduino 33:7ba5d53df0f2 85 #endif
cassyarduino 0:e3fb1267e3c3 86 _dhcpTransactionId++;
cassyarduino 0:e3fb1267e3c3 87
cassyarduino 0:e3fb1267e3c3 88 send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000));
cassyarduino 0:e3fb1267e3c3 89 _dhcp_state = STATE_DHCP_DISCOVER;
cassyarduino 0:e3fb1267e3c3 90 }
cassyarduino 0:e3fb1267e3c3 91 else if(_dhcp_state == STATE_DHCP_REREQUEST){
cassyarduino 33:7ba5d53df0f2 92 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 93 LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_REREQUEST -> send_DHCP_MESSAGE DHCP_REQUEST"));
cassyarduino 33:7ba5d53df0f2 94 #endif
cassyarduino 0:e3fb1267e3c3 95 _dhcpTransactionId++;
cassyarduino 0:e3fb1267e3c3 96 send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
cassyarduino 0:e3fb1267e3c3 97 _dhcp_state = STATE_DHCP_REQUEST;
cassyarduino 0:e3fb1267e3c3 98 }
cassyarduino 0:e3fb1267e3c3 99 else if(_dhcp_state == STATE_DHCP_DISCOVER)
cassyarduino 0:e3fb1267e3c3 100 {
cassyarduino 0:e3fb1267e3c3 101 uint32_t respId;
cassyarduino 38:645b253e6b50 102 messageType = parseDHCPResponse(respId);
cassyarduino 0:e3fb1267e3c3 103 if(messageType == DHCP_OFFER)
cassyarduino 0:e3fb1267e3c3 104 {
cassyarduino 33:7ba5d53df0f2 105 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 106 LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_DISCOVER,messageType=DHCP_OFFER -> send_DHCP_MESSAGE DHCP_REQUEST"));
cassyarduino 33:7ba5d53df0f2 107 #endif
cassyarduino 0:e3fb1267e3c3 108 // We'll use the transaction ID that the offer came with,
cassyarduino 0:e3fb1267e3c3 109 // rather than the one we were up to
cassyarduino 0:e3fb1267e3c3 110 _dhcpTransactionId = respId;
cassyarduino 0:e3fb1267e3c3 111 send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000));
cassyarduino 0:e3fb1267e3c3 112 _dhcp_state = STATE_DHCP_REQUEST;
cassyarduino 0:e3fb1267e3c3 113 }
cassyarduino 0:e3fb1267e3c3 114 }
cassyarduino 0:e3fb1267e3c3 115 else if(_dhcp_state == STATE_DHCP_REQUEST)
cassyarduino 0:e3fb1267e3c3 116 {
cassyarduino 0:e3fb1267e3c3 117 uint32_t respId;
cassyarduino 38:645b253e6b50 118 messageType = parseDHCPResponse(respId);
cassyarduino 0:e3fb1267e3c3 119 if(messageType == DHCP_ACK)
cassyarduino 0:e3fb1267e3c3 120 {
cassyarduino 33:7ba5d53df0f2 121 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 122 LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_REQUEST,messageType=DHCP_ACK"));
cassyarduino 33:7ba5d53df0f2 123 #endif
cassyarduino 0:e3fb1267e3c3 124 _dhcp_state = STATE_DHCP_LEASED;
cassyarduino 0:e3fb1267e3c3 125 result = 1;
cassyarduino 0:e3fb1267e3c3 126 //use default lease time if we didn't get it
cassyarduino 0:e3fb1267e3c3 127 if(_dhcpLeaseTime == 0){
cassyarduino 0:e3fb1267e3c3 128 _dhcpLeaseTime = DEFAULT_LEASE;
cassyarduino 0:e3fb1267e3c3 129 }
cassyarduino 0:e3fb1267e3c3 130 //calculate T1 & T2 if we didn't get it
cassyarduino 0:e3fb1267e3c3 131 if(_dhcpT1 == 0){
cassyarduino 0:e3fb1267e3c3 132 //T1 should be 50% of _dhcpLeaseTime
cassyarduino 0:e3fb1267e3c3 133 _dhcpT1 = _dhcpLeaseTime >> 1;
cassyarduino 0:e3fb1267e3c3 134 }
cassyarduino 0:e3fb1267e3c3 135 if(_dhcpT2 == 0){
cassyarduino 0:e3fb1267e3c3 136 //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime
cassyarduino 0:e3fb1267e3c3 137 _dhcpT2 = _dhcpT1 << 1;
cassyarduino 0:e3fb1267e3c3 138 }
cassyarduino 0:e3fb1267e3c3 139 _renewInSec = _dhcpT1;
cassyarduino 0:e3fb1267e3c3 140 _rebindInSec = _dhcpT2;
cassyarduino 0:e3fb1267e3c3 141 }
cassyarduino 0:e3fb1267e3c3 142 else if(messageType == DHCP_NAK)
cassyarduino 0:e3fb1267e3c3 143 _dhcp_state = STATE_DHCP_START;
cassyarduino 0:e3fb1267e3c3 144 }
cassyarduino 0:e3fb1267e3c3 145
cassyarduino 0:e3fb1267e3c3 146 if(messageType == 255)
cassyarduino 0:e3fb1267e3c3 147 {
cassyarduino 0:e3fb1267e3c3 148 messageType = 0;
cassyarduino 0:e3fb1267e3c3 149 _dhcp_state = STATE_DHCP_START;
cassyarduino 0:e3fb1267e3c3 150 }
cassyarduino 0:e3fb1267e3c3 151
cassyarduino 38:645b253e6b50 152 if(result != 1 && ((millis() - startTime) > DHCP_TIMEOUT))
cassyarduino 0:e3fb1267e3c3 153 break;
cassyarduino 38:645b253e6b50 154 #if defined(ESP8266)
cassyarduino 38:645b253e6b50 155 wdt_reset();
cassyarduino 38:645b253e6b50 156 #endif
cassyarduino 0:e3fb1267e3c3 157 }
cassyarduino 0:e3fb1267e3c3 158
cassyarduino 0:e3fb1267e3c3 159 // We're done with the socket now
cassyarduino 0:e3fb1267e3c3 160 _dhcpUdpSocket.stop();
cassyarduino 0:e3fb1267e3c3 161 _dhcpTransactionId++;
cassyarduino 0:e3fb1267e3c3 162
cassyarduino 0:e3fb1267e3c3 163 return result;
cassyarduino 0:e3fb1267e3c3 164 }
cassyarduino 0:e3fb1267e3c3 165
cassyarduino 0:e3fb1267e3c3 166 void DhcpClass::presend_DHCP(void)
cassyarduino 0:e3fb1267e3c3 167 {
cassyarduino 33:7ba5d53df0f2 168 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 169 LogObject.uart_send_strln(F("DhcpClass::presend_DHCP(void) DEBUG_V1:Function started (Empty function)"));
cassyarduino 33:7ba5d53df0f2 170 #endif
cassyarduino 0:e3fb1267e3c3 171 }
cassyarduino 0:e3fb1267e3c3 172
cassyarduino 0:e3fb1267e3c3 173 void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
cassyarduino 0:e3fb1267e3c3 174 {
cassyarduino 33:7ba5d53df0f2 175 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 176 LogObject.uart_send_strln(F("DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 177 #endif
cassyarduino 0:e3fb1267e3c3 178 uint8_t buffer[32];
cassyarduino 0:e3fb1267e3c3 179 memset(buffer, 0, 32);
cassyarduino 0:e3fb1267e3c3 180 IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address
cassyarduino 0:e3fb1267e3c3 181
cassyarduino 0:e3fb1267e3c3 182 if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT))
cassyarduino 0:e3fb1267e3c3 183 {
cassyarduino 0:e3fb1267e3c3 184 // FIXME Need to return errors
cassyarduino 0:e3fb1267e3c3 185 return;
cassyarduino 0:e3fb1267e3c3 186 }
cassyarduino 0:e3fb1267e3c3 187
cassyarduino 0:e3fb1267e3c3 188 buffer[0] = DHCP_BOOTREQUEST; // op
cassyarduino 0:e3fb1267e3c3 189 buffer[1] = DHCP_HTYPE10MB; // htype
cassyarduino 0:e3fb1267e3c3 190 buffer[2] = DHCP_HLENETHERNET; // hlen
cassyarduino 0:e3fb1267e3c3 191 buffer[3] = DHCP_HOPS; // hops
cassyarduino 0:e3fb1267e3c3 192
cassyarduino 0:e3fb1267e3c3 193 // xid
cassyarduino 0:e3fb1267e3c3 194 unsigned long xid = htonl(_dhcpTransactionId);
cassyarduino 0:e3fb1267e3c3 195 memcpy(buffer + 4, &(xid), 4);
cassyarduino 0:e3fb1267e3c3 196
cassyarduino 0:e3fb1267e3c3 197 // 8, 9 - seconds elapsed
cassyarduino 0:e3fb1267e3c3 198 buffer[8] = ((secondsElapsed & 0xff00) >> 8);
cassyarduino 0:e3fb1267e3c3 199 buffer[9] = (secondsElapsed & 0x00ff);
cassyarduino 0:e3fb1267e3c3 200
cassyarduino 0:e3fb1267e3c3 201 // flags
cassyarduino 0:e3fb1267e3c3 202 unsigned short flags = htons(DHCP_FLAGSBROADCAST);
cassyarduino 0:e3fb1267e3c3 203 memcpy(buffer + 10, &(flags), 2);
cassyarduino 0:e3fb1267e3c3 204
cassyarduino 0:e3fb1267e3c3 205 // ciaddr: already zeroed
cassyarduino 0:e3fb1267e3c3 206 // yiaddr: already zeroed
cassyarduino 0:e3fb1267e3c3 207 // siaddr: already zeroed
cassyarduino 0:e3fb1267e3c3 208 // giaddr: already zeroed
cassyarduino 0:e3fb1267e3c3 209
cassyarduino 0:e3fb1267e3c3 210 //put data in W5100 transmit buffer
cassyarduino 0:e3fb1267e3c3 211 _dhcpUdpSocket.write(buffer, 28);
cassyarduino 0:e3fb1267e3c3 212
cassyarduino 0:e3fb1267e3c3 213 memset(buffer, 0, 32); // clear local buffer
cassyarduino 0:e3fb1267e3c3 214
cassyarduino 0:e3fb1267e3c3 215 memcpy(buffer, _dhcpMacAddr, 6); // chaddr
cassyarduino 0:e3fb1267e3c3 216
cassyarduino 0:e3fb1267e3c3 217 //put data in W5100 transmit buffer
cassyarduino 0:e3fb1267e3c3 218 _dhcpUdpSocket.write(buffer, 16);
cassyarduino 0:e3fb1267e3c3 219
cassyarduino 0:e3fb1267e3c3 220 memset(buffer, 0, 32); // clear local buffer
cassyarduino 0:e3fb1267e3c3 221
cassyarduino 0:e3fb1267e3c3 222 // leave zeroed out for sname && file
cassyarduino 0:e3fb1267e3c3 223 // put in W5100 transmit buffer x 6 (192 bytes)
cassyarduino 0:e3fb1267e3c3 224
cassyarduino 0:e3fb1267e3c3 225 for(int i = 0; i < 6; i++) {
cassyarduino 0:e3fb1267e3c3 226 _dhcpUdpSocket.write(buffer, 32);
cassyarduino 0:e3fb1267e3c3 227 }
cassyarduino 0:e3fb1267e3c3 228
cassyarduino 0:e3fb1267e3c3 229 // OPT - Magic Cookie
cassyarduino 0:e3fb1267e3c3 230 buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF);
cassyarduino 0:e3fb1267e3c3 231 buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF);
cassyarduino 0:e3fb1267e3c3 232 buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF);
cassyarduino 0:e3fb1267e3c3 233 buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF);
cassyarduino 0:e3fb1267e3c3 234
cassyarduino 0:e3fb1267e3c3 235 // OPT - message type
cassyarduino 0:e3fb1267e3c3 236 buffer[4] = dhcpMessageType;
cassyarduino 0:e3fb1267e3c3 237 buffer[5] = 0x01;
cassyarduino 0:e3fb1267e3c3 238 buffer[6] = messageType; //DHCP_REQUEST;
cassyarduino 0:e3fb1267e3c3 239
cassyarduino 0:e3fb1267e3c3 240 // OPT - client identifier
cassyarduino 0:e3fb1267e3c3 241 buffer[7] = dhcpClientIdentifier;
cassyarduino 0:e3fb1267e3c3 242 buffer[8] = 0x07;
cassyarduino 0:e3fb1267e3c3 243 buffer[9] = 0x01;
cassyarduino 0:e3fb1267e3c3 244 memcpy(buffer + 10, _dhcpMacAddr, 6);
cassyarduino 0:e3fb1267e3c3 245
cassyarduino 0:e3fb1267e3c3 246 // OPT - host name
cassyarduino 0:e3fb1267e3c3 247 buffer[16] = hostName;
cassyarduino 0:e3fb1267e3c3 248 buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address
cassyarduino 0:e3fb1267e3c3 249 strcpy((char*)&(buffer[18]), HOST_NAME);
cassyarduino 0:e3fb1267e3c3 250
cassyarduino 0:e3fb1267e3c3 251 printByte((char*)&(buffer[24]), _dhcpMacAddr[3]);
cassyarduino 0:e3fb1267e3c3 252 printByte((char*)&(buffer[26]), _dhcpMacAddr[4]);
cassyarduino 0:e3fb1267e3c3 253 printByte((char*)&(buffer[28]), _dhcpMacAddr[5]);
cassyarduino 0:e3fb1267e3c3 254
cassyarduino 0:e3fb1267e3c3 255 //put data in W5100 transmit buffer
cassyarduino 0:e3fb1267e3c3 256 _dhcpUdpSocket.write(buffer, 30);
cassyarduino 0:e3fb1267e3c3 257
cassyarduino 0:e3fb1267e3c3 258 if(messageType == DHCP_REQUEST)
cassyarduino 0:e3fb1267e3c3 259 {
cassyarduino 0:e3fb1267e3c3 260 buffer[0] = dhcpRequestedIPaddr;
cassyarduino 0:e3fb1267e3c3 261 buffer[1] = 0x04;
cassyarduino 38:645b253e6b50 262 buffer[2] = _dhcpipv4struct.LocalIp[0];
cassyarduino 38:645b253e6b50 263 buffer[3] = _dhcpipv4struct.LocalIp[1];
cassyarduino 38:645b253e6b50 264 buffer[4] = _dhcpipv4struct.LocalIp[2];
cassyarduino 38:645b253e6b50 265 buffer[5] = _dhcpipv4struct.LocalIp[3];
cassyarduino 0:e3fb1267e3c3 266
cassyarduino 0:e3fb1267e3c3 267 buffer[6] = dhcpServerIdentifier;
cassyarduino 0:e3fb1267e3c3 268 buffer[7] = 0x04;
cassyarduino 38:645b253e6b50 269 buffer[8] = _dhcpipv4struct.DhcpServerIp[0];
cassyarduino 38:645b253e6b50 270 buffer[9] = _dhcpipv4struct.DhcpServerIp[1];
cassyarduino 38:645b253e6b50 271 buffer[10] = _dhcpipv4struct.DhcpServerIp[2];
cassyarduino 38:645b253e6b50 272 buffer[11] = _dhcpipv4struct.DhcpServerIp[3];
cassyarduino 0:e3fb1267e3c3 273
cassyarduino 0:e3fb1267e3c3 274 //put data in W5100 transmit buffer
cassyarduino 0:e3fb1267e3c3 275 _dhcpUdpSocket.write(buffer, 12);
cassyarduino 0:e3fb1267e3c3 276 }
cassyarduino 0:e3fb1267e3c3 277
cassyarduino 0:e3fb1267e3c3 278 buffer[0] = dhcpParamRequest;
cassyarduino 0:e3fb1267e3c3 279 buffer[1] = 0x06;
cassyarduino 0:e3fb1267e3c3 280 buffer[2] = subnetMask;
cassyarduino 0:e3fb1267e3c3 281 buffer[3] = routersOnSubnet;
cassyarduino 0:e3fb1267e3c3 282 buffer[4] = dns;
cassyarduino 0:e3fb1267e3c3 283 buffer[5] = domainName;
cassyarduino 0:e3fb1267e3c3 284 buffer[6] = dhcpT1value;
cassyarduino 0:e3fb1267e3c3 285 buffer[7] = dhcpT2value;
cassyarduino 0:e3fb1267e3c3 286 buffer[8] = endOption;
cassyarduino 0:e3fb1267e3c3 287
cassyarduino 0:e3fb1267e3c3 288 //put data in W5100 transmit buffer
cassyarduino 0:e3fb1267e3c3 289 _dhcpUdpSocket.write(buffer, 9);
cassyarduino 0:e3fb1267e3c3 290
cassyarduino 0:e3fb1267e3c3 291 _dhcpUdpSocket.endPacket();
cassyarduino 0:e3fb1267e3c3 292 }
cassyarduino 0:e3fb1267e3c3 293
cassyarduino 38:645b253e6b50 294 uint8_t DhcpClass::parseDHCPResponse(uint32_t& transactionId)
cassyarduino 0:e3fb1267e3c3 295 {
cassyarduino 33:7ba5d53df0f2 296 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 297 LogObject.uart_send_strln(F("DhcpClass::parseDHCPResponse(uint32_t& transactionId) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 298 #endif
cassyarduino 0:e3fb1267e3c3 299 uint8_t type = 0;
cassyarduino 0:e3fb1267e3c3 300 uint8_t opt_len = 0;
cassyarduino 0:e3fb1267e3c3 301
cassyarduino 0:e3fb1267e3c3 302 unsigned long startTime = millis();
cassyarduino 0:e3fb1267e3c3 303
cassyarduino 0:e3fb1267e3c3 304 while(_dhcpUdpSocket.parsePacket() <= 0)
cassyarduino 0:e3fb1267e3c3 305 {
cassyarduino 38:645b253e6b50 306 if((millis() - startTime) > DHCP_RESPONSE_TIMEOUT)
cassyarduino 0:e3fb1267e3c3 307 {
cassyarduino 0:e3fb1267e3c3 308 return 255;
cassyarduino 0:e3fb1267e3c3 309 }
cassyarduino 0:e3fb1267e3c3 310 delay(50);
cassyarduino 0:e3fb1267e3c3 311 }
cassyarduino 0:e3fb1267e3c3 312 // start reading in the packet
cassyarduino 0:e3fb1267e3c3 313 RIP_MSG_FIXED fixedMsg;
cassyarduino 0:e3fb1267e3c3 314 _dhcpUdpSocket.read((char*)&fixedMsg, sizeof(RIP_MSG_FIXED));
cassyarduino 0:e3fb1267e3c3 315
cassyarduino 0:e3fb1267e3c3 316 if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT)
cassyarduino 0:e3fb1267e3c3 317 {
cassyarduino 0:e3fb1267e3c3 318 transactionId = ntohl(fixedMsg.xid);
cassyarduino 0:e3fb1267e3c3 319 if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId))
cassyarduino 0:e3fb1267e3c3 320 {
cassyarduino 0:e3fb1267e3c3 321 // Need to read the rest of the packet here regardless
cassyarduino 0:e3fb1267e3c3 322 _dhcpUdpSocket.flush();
cassyarduino 0:e3fb1267e3c3 323 return 0;
cassyarduino 0:e3fb1267e3c3 324 }
cassyarduino 0:e3fb1267e3c3 325
cassyarduino 38:645b253e6b50 326 memcpy(_dhcpipv4struct.LocalIp, fixedMsg.yiaddr, 4);
cassyarduino 0:e3fb1267e3c3 327
cassyarduino 0:e3fb1267e3c3 328 // Skip to the option part
cassyarduino 0:e3fb1267e3c3 329 // Doing this a byte at a time so we don't have to put a big buffer
cassyarduino 0:e3fb1267e3c3 330 // on the stack (as we don't have lots of memory lying around)
cassyarduino 0:e3fb1267e3c3 331 for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++)
cassyarduino 0:e3fb1267e3c3 332 {
cassyarduino 0:e3fb1267e3c3 333 _dhcpUdpSocket.read(); // we don't care about the returned byte
cassyarduino 0:e3fb1267e3c3 334 }
cassyarduino 0:e3fb1267e3c3 335
cassyarduino 0:e3fb1267e3c3 336 while (_dhcpUdpSocket.available() > 0)
cassyarduino 0:e3fb1267e3c3 337 {
cassyarduino 0:e3fb1267e3c3 338 switch (_dhcpUdpSocket.read())
cassyarduino 0:e3fb1267e3c3 339 {
cassyarduino 0:e3fb1267e3c3 340 case endOption :
cassyarduino 0:e3fb1267e3c3 341 break;
cassyarduino 0:e3fb1267e3c3 342
cassyarduino 0:e3fb1267e3c3 343 case padOption :
cassyarduino 0:e3fb1267e3c3 344 break;
cassyarduino 0:e3fb1267e3c3 345
cassyarduino 0:e3fb1267e3c3 346 case dhcpMessageType :
cassyarduino 0:e3fb1267e3c3 347 opt_len = _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 348 type = _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 349 break;
cassyarduino 0:e3fb1267e3c3 350
cassyarduino 0:e3fb1267e3c3 351 case subnetMask :
cassyarduino 0:e3fb1267e3c3 352 opt_len = _dhcpUdpSocket.read();
cassyarduino 38:645b253e6b50 353 _dhcpUdpSocket.read((char*)_dhcpipv4struct.SubnetMask, 4);
cassyarduino 0:e3fb1267e3c3 354 break;
cassyarduino 0:e3fb1267e3c3 355
cassyarduino 0:e3fb1267e3c3 356 case routersOnSubnet :
cassyarduino 0:e3fb1267e3c3 357 opt_len = _dhcpUdpSocket.read();
cassyarduino 38:645b253e6b50 358 _dhcpUdpSocket.read((char*)_dhcpipv4struct.GatewayIp, 4);
cassyarduino 0:e3fb1267e3c3 359 for (int i = 0; i < opt_len-4; i++)
cassyarduino 0:e3fb1267e3c3 360 {
cassyarduino 0:e3fb1267e3c3 361 _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 362 }
cassyarduino 0:e3fb1267e3c3 363 break;
cassyarduino 0:e3fb1267e3c3 364
cassyarduino 0:e3fb1267e3c3 365 case dns :
cassyarduino 0:e3fb1267e3c3 366 opt_len = _dhcpUdpSocket.read();
cassyarduino 38:645b253e6b50 367 _dhcpUdpSocket.read((char*)_dhcpipv4struct.DnsServerIp, 4);
cassyarduino 0:e3fb1267e3c3 368 for (int i = 0; i < opt_len-4; i++)
cassyarduino 0:e3fb1267e3c3 369 {
cassyarduino 0:e3fb1267e3c3 370 _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 371 }
cassyarduino 0:e3fb1267e3c3 372 break;
cassyarduino 0:e3fb1267e3c3 373
cassyarduino 0:e3fb1267e3c3 374 case dhcpServerIdentifier :
cassyarduino 0:e3fb1267e3c3 375 opt_len = _dhcpUdpSocket.read();
cassyarduino 38:645b253e6b50 376 if( IPAddress(_dhcpipv4struct.DhcpServerIp) == IPAddress(0,0,0,0) ||
cassyarduino 38:645b253e6b50 377 IPAddress(_dhcpipv4struct.DhcpServerIp) == _dhcpUdpSocket.remoteIP() )
cassyarduino 0:e3fb1267e3c3 378 {
cassyarduino 38:645b253e6b50 379 _dhcpUdpSocket.read((char*)_dhcpipv4struct.DhcpServerIp, sizeof(_dhcpipv4struct.DhcpServerIp));
cassyarduino 0:e3fb1267e3c3 380 }
cassyarduino 0:e3fb1267e3c3 381 else
cassyarduino 0:e3fb1267e3c3 382 {
cassyarduino 0:e3fb1267e3c3 383 // Skip over the rest of this option
cassyarduino 0:e3fb1267e3c3 384 while (opt_len--)
cassyarduino 0:e3fb1267e3c3 385 {
cassyarduino 0:e3fb1267e3c3 386 _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 387 }
cassyarduino 0:e3fb1267e3c3 388 }
cassyarduino 0:e3fb1267e3c3 389 break;
cassyarduino 0:e3fb1267e3c3 390
cassyarduino 0:e3fb1267e3c3 391 case dhcpT1value :
cassyarduino 0:e3fb1267e3c3 392 opt_len = _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 393 _dhcpUdpSocket.read((char*)&_dhcpT1, sizeof(_dhcpT1));
cassyarduino 0:e3fb1267e3c3 394 _dhcpT1 = ntohl(_dhcpT1);
cassyarduino 0:e3fb1267e3c3 395 break;
cassyarduino 0:e3fb1267e3c3 396
cassyarduino 0:e3fb1267e3c3 397 case dhcpT2value :
cassyarduino 0:e3fb1267e3c3 398 opt_len = _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 399 _dhcpUdpSocket.read((char*)&_dhcpT2, sizeof(_dhcpT2));
cassyarduino 0:e3fb1267e3c3 400 _dhcpT2 = ntohl(_dhcpT2);
cassyarduino 0:e3fb1267e3c3 401 break;
cassyarduino 0:e3fb1267e3c3 402
cassyarduino 0:e3fb1267e3c3 403 case dhcpIPaddrLeaseTime :
cassyarduino 0:e3fb1267e3c3 404 opt_len = _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 405 _dhcpUdpSocket.read((char*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime));
cassyarduino 0:e3fb1267e3c3 406 _dhcpLeaseTime = ntohl(_dhcpLeaseTime);
cassyarduino 0:e3fb1267e3c3 407 _renewInSec = _dhcpLeaseTime;
cassyarduino 0:e3fb1267e3c3 408 break;
cassyarduino 0:e3fb1267e3c3 409
cassyarduino 0:e3fb1267e3c3 410 default :
cassyarduino 0:e3fb1267e3c3 411 opt_len = _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 412 // Skip over the rest of this option
cassyarduino 0:e3fb1267e3c3 413 while (opt_len--)
cassyarduino 0:e3fb1267e3c3 414 {
cassyarduino 0:e3fb1267e3c3 415 _dhcpUdpSocket.read();
cassyarduino 0:e3fb1267e3c3 416 }
cassyarduino 0:e3fb1267e3c3 417 break;
cassyarduino 0:e3fb1267e3c3 418 }
cassyarduino 0:e3fb1267e3c3 419 }
cassyarduino 0:e3fb1267e3c3 420 }
cassyarduino 0:e3fb1267e3c3 421
cassyarduino 0:e3fb1267e3c3 422 // Need to skip to end of the packet regardless here
cassyarduino 0:e3fb1267e3c3 423 _dhcpUdpSocket.flush();
cassyarduino 0:e3fb1267e3c3 424
cassyarduino 0:e3fb1267e3c3 425 return type;
cassyarduino 0:e3fb1267e3c3 426 }
cassyarduino 0:e3fb1267e3c3 427
cassyarduino 0:e3fb1267e3c3 428
cassyarduino 0:e3fb1267e3c3 429 /*
cassyarduino 0:e3fb1267e3c3 430 returns:
cassyarduino 0:e3fb1267e3c3 431 0/DHCP_CHECK_NONE: nothing happened
cassyarduino 0:e3fb1267e3c3 432 1/DHCP_CHECK_RENEW_FAIL: renew failed
cassyarduino 0:e3fb1267e3c3 433 2/DHCP_CHECK_RENEW_OK: renew success
cassyarduino 0:e3fb1267e3c3 434 3/DHCP_CHECK_REBIND_FAIL: rebind fail
cassyarduino 0:e3fb1267e3c3 435 4/DHCP_CHECK_REBIND_OK: rebind success
cassyarduino 0:e3fb1267e3c3 436 */
cassyarduino 0:e3fb1267e3c3 437 int DhcpClass::checkLease(void){
cassyarduino 33:7ba5d53df0f2 438 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 439 LogObject.uart_send_strln(F("DhcpClass::checkLease(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 440 #endif
cassyarduino 33:7ba5d53df0f2 441
cassyarduino 0:e3fb1267e3c3 442 //this uses a signed / unsigned trick to deal with millis overflow
cassyarduino 0:e3fb1267e3c3 443 unsigned long now = millis();
cassyarduino 0:e3fb1267e3c3 444 signed long snow = (long)now;
cassyarduino 0:e3fb1267e3c3 445 int rc=DHCP_CHECK_NONE;
cassyarduino 0:e3fb1267e3c3 446 if (_lastCheck != 0){
cassyarduino 0:e3fb1267e3c3 447 signed long factor;
cassyarduino 0:e3fb1267e3c3 448 //calc how many ms past the timeout we are
cassyarduino 0:e3fb1267e3c3 449 factor = snow - (long)_secTimeout;
cassyarduino 0:e3fb1267e3c3 450 //if on or passed the timeout, reduce the counters
cassyarduino 0:e3fb1267e3c3 451 if ( factor >= 0 ){
cassyarduino 0:e3fb1267e3c3 452 //next timeout should be now plus 1000 ms minus parts of second in factor
cassyarduino 0:e3fb1267e3c3 453 _secTimeout = snow + 1000 - factor % 1000;
cassyarduino 0:e3fb1267e3c3 454 //how many seconds late are we, minimum 1
cassyarduino 0:e3fb1267e3c3 455 factor = factor / 1000 +1;
cassyarduino 0:e3fb1267e3c3 456
cassyarduino 0:e3fb1267e3c3 457 //reduce the counters by that mouch
cassyarduino 0:e3fb1267e3c3 458 //if we can assume that the cycle time (factor) is fairly constant
cassyarduino 0:e3fb1267e3c3 459 //and if the remainder is less than cycle time * 2
cassyarduino 0:e3fb1267e3c3 460 //do it early instead of late
cassyarduino 0:e3fb1267e3c3 461 if(_renewInSec < factor*2 )
cassyarduino 0:e3fb1267e3c3 462 _renewInSec = 0;
cassyarduino 0:e3fb1267e3c3 463 else
cassyarduino 0:e3fb1267e3c3 464 _renewInSec -= factor;
cassyarduino 0:e3fb1267e3c3 465
cassyarduino 0:e3fb1267e3c3 466 if(_rebindInSec < factor*2 )
cassyarduino 0:e3fb1267e3c3 467 _rebindInSec = 0;
cassyarduino 0:e3fb1267e3c3 468 else
cassyarduino 0:e3fb1267e3c3 469 _rebindInSec -= factor;
cassyarduino 0:e3fb1267e3c3 470 }
cassyarduino 0:e3fb1267e3c3 471
cassyarduino 0:e3fb1267e3c3 472 //if we have a lease but should renew, do it
cassyarduino 0:e3fb1267e3c3 473 if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){
cassyarduino 0:e3fb1267e3c3 474 _dhcp_state = STATE_DHCP_REREQUEST;
cassyarduino 0:e3fb1267e3c3 475 rc = 1 + request_DHCP_lease();
cassyarduino 0:e3fb1267e3c3 476 }
cassyarduino 0:e3fb1267e3c3 477
cassyarduino 0:e3fb1267e3c3 478 //if we have a lease or is renewing but should bind, do it
cassyarduino 0:e3fb1267e3c3 479 if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){
cassyarduino 0:e3fb1267e3c3 480 //this should basically restart completely
cassyarduino 0:e3fb1267e3c3 481 _dhcp_state = STATE_DHCP_START;
cassyarduino 0:e3fb1267e3c3 482 reset_DHCP_lease();
cassyarduino 0:e3fb1267e3c3 483 rc = 3 + request_DHCP_lease();
cassyarduino 0:e3fb1267e3c3 484 }
cassyarduino 0:e3fb1267e3c3 485 }
cassyarduino 0:e3fb1267e3c3 486 else{
cassyarduino 0:e3fb1267e3c3 487 _secTimeout = snow + 1000;
cassyarduino 0:e3fb1267e3c3 488 }
cassyarduino 0:e3fb1267e3c3 489
cassyarduino 0:e3fb1267e3c3 490 _lastCheck = now;
cassyarduino 0:e3fb1267e3c3 491 return rc;
cassyarduino 0:e3fb1267e3c3 492 }
cassyarduino 0:e3fb1267e3c3 493
cassyarduino 0:e3fb1267e3c3 494 IPAddress DhcpClass::getLocalIp(void)
cassyarduino 0:e3fb1267e3c3 495 {
cassyarduino 33:7ba5d53df0f2 496 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 497 LogObject.uart_send_strln(F("DhcpClass::getLocalIp(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 498 #endif
cassyarduino 38:645b253e6b50 499 return IPAddress(_dhcpipv4struct.LocalIp);
cassyarduino 0:e3fb1267e3c3 500 }
cassyarduino 0:e3fb1267e3c3 501
cassyarduino 0:e3fb1267e3c3 502 IPAddress DhcpClass::getSubnetMask(void)
cassyarduino 0:e3fb1267e3c3 503 {
cassyarduino 33:7ba5d53df0f2 504 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 505 LogObject.uart_send_strln(F("DhcpClass::getSubnetMask(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 506 #endif
cassyarduino 38:645b253e6b50 507 return IPAddress(_dhcpipv4struct.SubnetMask);
cassyarduino 0:e3fb1267e3c3 508 }
cassyarduino 0:e3fb1267e3c3 509
cassyarduino 0:e3fb1267e3c3 510 IPAddress DhcpClass::getGatewayIp(void)
cassyarduino 0:e3fb1267e3c3 511 {
cassyarduino 33:7ba5d53df0f2 512 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 513 LogObject.uart_send_strln(F("DhcpClass::getGatewayIp(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 514 #endif
cassyarduino 38:645b253e6b50 515 return IPAddress(_dhcpipv4struct.GatewayIp);
cassyarduino 0:e3fb1267e3c3 516 }
cassyarduino 0:e3fb1267e3c3 517
cassyarduino 0:e3fb1267e3c3 518 IPAddress DhcpClass::getDhcpServerIp(void)
cassyarduino 0:e3fb1267e3c3 519 {
cassyarduino 33:7ba5d53df0f2 520 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 521 LogObject.uart_send_strln(F("DhcpClass::getDhcpServerIp(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 522 #endif
cassyarduino 38:645b253e6b50 523 return IPAddress(_dhcpipv4struct.DhcpServerIp);
cassyarduino 0:e3fb1267e3c3 524 }
cassyarduino 0:e3fb1267e3c3 525
cassyarduino 0:e3fb1267e3c3 526 IPAddress DhcpClass::getDnsServerIp(void)
cassyarduino 0:e3fb1267e3c3 527 {
cassyarduino 33:7ba5d53df0f2 528 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 529 LogObject.uart_send_strln(F("DhcpClass::getDnsServerIp(void) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 530 #endif
cassyarduino 38:645b253e6b50 531 return IPAddress(_dhcpipv4struct.DnsServerIp);
cassyarduino 0:e3fb1267e3c3 532 }
cassyarduino 0:e3fb1267e3c3 533
cassyarduino 0:e3fb1267e3c3 534 void DhcpClass::printByte(char * buf, uint8_t n ) {
cassyarduino 33:7ba5d53df0f2 535 #if ACTLOGLEVEL>=LOG_DEBUG_V1
cassyarduino 38:645b253e6b50 536 LogObject.uart_send_strln(F("DhcpClass::printByte(char * buf, uint8_t n ) DEBUG_V1:Function started"));
cassyarduino 33:7ba5d53df0f2 537 #endif
cassyarduino 0:e3fb1267e3c3 538 char *str = &buf[1];
cassyarduino 0:e3fb1267e3c3 539 buf[0]='0';
cassyarduino 0:e3fb1267e3c3 540 do {
cassyarduino 0:e3fb1267e3c3 541 unsigned long m = n;
cassyarduino 0:e3fb1267e3c3 542 n /= 16;
cassyarduino 0:e3fb1267e3c3 543 char c = m - 16 * n;
cassyarduino 0:e3fb1267e3c3 544 *str-- = c < 10 ? c + '0' : c + 'A' - 10;
cassyarduino 0:e3fb1267e3c3 545 } while(n);
cassyarduino 0:e3fb1267e3c3 546 }
cassyarduino 33:7ba5d53df0f2 547 #endif