Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.

Dependents:   mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more

Library for ENC28J60 Ethernet modules.

/media/uploads/hudakz/enc28j60_module01.jpg

Ported to mbed from Norbert Truchsess's UIPEthernet library for Arduino. Thank you Norbert!

  • Full support for persistent (streaming) TCP/IP and UDP connections Client and Server each, ARP, ICMP, DHCP and DNS.
  • Works with both Mbed OS 2 and Mbed OS 5.

Usage:

  • Import the library into your project.
  • Add #include "UipEthernet.h" to main.cpp
  • Create one instance of the UipEthernet class initialized with the MAC address you'd like to use and SPI pins of the connected Mbed board.

Example programs:

Import programWebSwitch_ENC28J60

HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.

Import programHTTPServer_Echo_ENC28J60

A simple HTTP server echoing received requests. Ethernet connection is over an ENC28J60 board. Usage: Type the server's IP address into you web browser and hit <ENTER>.

Import programTcpServer_ENC28J60

Simple TCP/IP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programTcpClient_ENC28J60

Simple TCP/IP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpServer_ENC28J60

Simple UDP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpClient_ENC28J60

Simple UDP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programMQTT_Hello_ENC28J60

MQTT Client example program. Ethernet connection is via an ENC28J60 module.

Committer:
hudakz
Date:
Thu Jul 23 15:30:54 2020 +0000
Revision:
18:8d5738a6646e
Parent:
17:1123c3fe86ca
Mbed library for ENC28J60 Ethernet modules.

Who changed what in which revision?

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