M2X Ethernet demo using Seeed Ethernet W5200 Shield

Dependencies:   LM75B M2XStreamClient jsonlite mbed-rtos mbed Nucleo_Sensor_Shield

Fork of m2x-seeed_ethernet_demo by Sean Newton

Committer:
dangriffin
Date:
Wed Dec 17 20:45:13 2014 +0000
Revision:
11:40d8cfc941ed
Parent:
7:a94ba2e0cd04
Use the public Nucleo Sensor Shield library.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
SeanNewton 7:a94ba2e0cd04 1 // DHCPClient.cpp 2013/4/10
SeanNewton 7:a94ba2e0cd04 2 #include "mbed.h"
SeanNewton 7:a94ba2e0cd04 3 #include "mbed_debug.h"
SeanNewton 7:a94ba2e0cd04 4 #include "UDPSocket.h"
SeanNewton 7:a94ba2e0cd04 5 #include "DHCPClient.h"
SeanNewton 7:a94ba2e0cd04 6
SeanNewton 7:a94ba2e0cd04 7 #define DBG_DHCP 0
SeanNewton 7:a94ba2e0cd04 8
SeanNewton 7:a94ba2e0cd04 9 #if DBG_DHCP
SeanNewton 7:a94ba2e0cd04 10 #define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0);
SeanNewton 7:a94ba2e0cd04 11 #define DBG_HEX(A,B) do{debug("[%s:%d]\r\n", __PRETTY_FUNCTION__,__LINE__);debug_hex(A,B);} while(0);
SeanNewton 7:a94ba2e0cd04 12 #else
SeanNewton 7:a94ba2e0cd04 13 #define DBG(...) while(0);
SeanNewton 7:a94ba2e0cd04 14 #define DBG_HEX(A,B) while(0);
SeanNewton 7:a94ba2e0cd04 15 #endif
SeanNewton 7:a94ba2e0cd04 16
SeanNewton 7:a94ba2e0cd04 17 int DHCPClient::discover()
SeanNewton 7:a94ba2e0cd04 18 {
SeanNewton 7:a94ba2e0cd04 19 m_pos = 0;
SeanNewton 7:a94ba2e0cd04 20 const uint8_t header[] = {0x01,0x01,0x06,0x00};
SeanNewton 7:a94ba2e0cd04 21 add_buf((uint8_t*)header, sizeof(header));
SeanNewton 7:a94ba2e0cd04 22 uint32_t x = time(NULL) + rand();
SeanNewton 7:a94ba2e0cd04 23 xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x;
SeanNewton 7:a94ba2e0cd04 24 add_buf(xid, 4);
SeanNewton 7:a94ba2e0cd04 25 fill_buf(20, 0x00);
SeanNewton 7:a94ba2e0cd04 26 add_buf(chaddr, 6);
SeanNewton 7:a94ba2e0cd04 27 fill_buf(10+192, 0x00);
SeanNewton 7:a94ba2e0cd04 28 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
SeanNewton 7:a94ba2e0cd04 29 53,1,DHCPDISCOVER, // DHCP option 53: DHCP Discover
SeanNewton 7:a94ba2e0cd04 30 55,4,1,3,15,6,
SeanNewton 7:a94ba2e0cd04 31 255};
SeanNewton 7:a94ba2e0cd04 32 add_buf((uint8_t*)options, sizeof(options));
SeanNewton 7:a94ba2e0cd04 33 return m_pos;
SeanNewton 7:a94ba2e0cd04 34 }
SeanNewton 7:a94ba2e0cd04 35
SeanNewton 7:a94ba2e0cd04 36 int DHCPClient::request()
SeanNewton 7:a94ba2e0cd04 37 {
SeanNewton 7:a94ba2e0cd04 38 m_pos = 0;
SeanNewton 7:a94ba2e0cd04 39 const uint8_t header[] = {0x01,0x01,0x06,0x00};
SeanNewton 7:a94ba2e0cd04 40 add_buf((uint8_t*)header, sizeof(header));
SeanNewton 7:a94ba2e0cd04 41 add_buf(xid, 4);
SeanNewton 7:a94ba2e0cd04 42 fill_buf(12, 0x00);
SeanNewton 7:a94ba2e0cd04 43 add_buf(siaddr, 4);
SeanNewton 7:a94ba2e0cd04 44 fill_buf(4, 0x00); // giaddr
SeanNewton 7:a94ba2e0cd04 45 add_buf(chaddr, 6);
SeanNewton 7:a94ba2e0cd04 46 fill_buf(10+192, 0x00);
SeanNewton 7:a94ba2e0cd04 47 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie
SeanNewton 7:a94ba2e0cd04 48 53,1,DHCPREQUEST, // DHCP option 53: DHCP Request
SeanNewton 7:a94ba2e0cd04 49 55,4,1,3,15,6, // DHCP option 55:
SeanNewton 7:a94ba2e0cd04 50 };
SeanNewton 7:a94ba2e0cd04 51 add_buf((uint8_t*)options, sizeof(options));
SeanNewton 7:a94ba2e0cd04 52 add_option(50, yiaddr, 4);
SeanNewton 7:a94ba2e0cd04 53 add_option(54, siaddr, 4);
SeanNewton 7:a94ba2e0cd04 54 add_option(255);
SeanNewton 7:a94ba2e0cd04 55 return m_pos;
SeanNewton 7:a94ba2e0cd04 56 }
SeanNewton 7:a94ba2e0cd04 57
SeanNewton 7:a94ba2e0cd04 58 int DHCPClient::offer(uint8_t buf[], int size) {
SeanNewton 7:a94ba2e0cd04 59 memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4);
SeanNewton 7:a94ba2e0cd04 60 memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4);
SeanNewton 7:a94ba2e0cd04 61 uint8_t *p;
SeanNewton 7:a94ba2e0cd04 62 int msg_type = -1;
SeanNewton 7:a94ba2e0cd04 63 p = buf + DHCP_OFFSET_OPTIONS;
SeanNewton 7:a94ba2e0cd04 64 while(*p != 255 && p < (buf+size)) {
SeanNewton 7:a94ba2e0cd04 65 uint8_t code = *p++;
SeanNewton 7:a94ba2e0cd04 66 if (code == 0) { // Pad Option
SeanNewton 7:a94ba2e0cd04 67 continue;
SeanNewton 7:a94ba2e0cd04 68 }
SeanNewton 7:a94ba2e0cd04 69 int len = *p++;
SeanNewton 7:a94ba2e0cd04 70
SeanNewton 7:a94ba2e0cd04 71 DBG("DHCP option: %d\r\n", code);
SeanNewton 7:a94ba2e0cd04 72 DBG_HEX(p, len);
SeanNewton 7:a94ba2e0cd04 73
SeanNewton 7:a94ba2e0cd04 74 switch(code) {
SeanNewton 7:a94ba2e0cd04 75 case 53:
SeanNewton 7:a94ba2e0cd04 76 msg_type = *p;
SeanNewton 7:a94ba2e0cd04 77 break;
SeanNewton 7:a94ba2e0cd04 78 case 1:
SeanNewton 7:a94ba2e0cd04 79 memcpy(netmask, p, 4); // Subnet mask address
SeanNewton 7:a94ba2e0cd04 80 break;
SeanNewton 7:a94ba2e0cd04 81 case 3:
SeanNewton 7:a94ba2e0cd04 82 memcpy(gateway, p, 4); // Gateway IP address
SeanNewton 7:a94ba2e0cd04 83 break;
SeanNewton 7:a94ba2e0cd04 84 case 6: // DNS server
SeanNewton 7:a94ba2e0cd04 85 memcpy(dnsaddr, p, 4);
SeanNewton 7:a94ba2e0cd04 86 break;
SeanNewton 7:a94ba2e0cd04 87 case 51: // IP lease time
SeanNewton 7:a94ba2e0cd04 88 break;
SeanNewton 7:a94ba2e0cd04 89 case 54: // DHCP server
SeanNewton 7:a94ba2e0cd04 90 memcpy(siaddr, p, 4);
SeanNewton 7:a94ba2e0cd04 91 break;
SeanNewton 7:a94ba2e0cd04 92 }
SeanNewton 7:a94ba2e0cd04 93 p += len;
SeanNewton 7:a94ba2e0cd04 94 }
SeanNewton 7:a94ba2e0cd04 95 return msg_type;
SeanNewton 7:a94ba2e0cd04 96 }
SeanNewton 7:a94ba2e0cd04 97
SeanNewton 7:a94ba2e0cd04 98 bool DHCPClient::verify(uint8_t buf[], int len) {
SeanNewton 7:a94ba2e0cd04 99 if (len < DHCP_OFFSET_OPTIONS) {
SeanNewton 7:a94ba2e0cd04 100 return false;
SeanNewton 7:a94ba2e0cd04 101 }
SeanNewton 7:a94ba2e0cd04 102 if (buf[DHCP_OFFSET_OP] != 0x02) {
SeanNewton 7:a94ba2e0cd04 103 return false;
SeanNewton 7:a94ba2e0cd04 104 }
SeanNewton 7:a94ba2e0cd04 105 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) {
SeanNewton 7:a94ba2e0cd04 106 return false;
SeanNewton 7:a94ba2e0cd04 107 }
SeanNewton 7:a94ba2e0cd04 108 return true;
SeanNewton 7:a94ba2e0cd04 109 }
SeanNewton 7:a94ba2e0cd04 110
SeanNewton 7:a94ba2e0cd04 111 void DHCPClient::callback()
SeanNewton 7:a94ba2e0cd04 112 {
SeanNewton 7:a94ba2e0cd04 113 Endpoint host;
SeanNewton 7:a94ba2e0cd04 114 int recv_len = m_udp->receiveFrom(host, (char*)m_buf, sizeof(m_buf));
SeanNewton 7:a94ba2e0cd04 115 if (recv_len < 0) {
SeanNewton 7:a94ba2e0cd04 116 return;
SeanNewton 7:a94ba2e0cd04 117 }
SeanNewton 7:a94ba2e0cd04 118 if (!verify(m_buf, recv_len)) {
SeanNewton 7:a94ba2e0cd04 119 return;
SeanNewton 7:a94ba2e0cd04 120 }
SeanNewton 7:a94ba2e0cd04 121 int r = offer(m_buf, recv_len);
SeanNewton 7:a94ba2e0cd04 122 if (r == DHCPOFFER) {
SeanNewton 7:a94ba2e0cd04 123 int send_size = request();
SeanNewton 7:a94ba2e0cd04 124 m_udp->sendTo(m_server, (char*)m_buf, send_size);
SeanNewton 7:a94ba2e0cd04 125 } else if (r == DHCPACK) {
SeanNewton 7:a94ba2e0cd04 126 exit_flag = true;
SeanNewton 7:a94ba2e0cd04 127 }
SeanNewton 7:a94ba2e0cd04 128 }
SeanNewton 7:a94ba2e0cd04 129
SeanNewton 7:a94ba2e0cd04 130 void DHCPClient::add_buf(uint8_t c)
SeanNewton 7:a94ba2e0cd04 131 {
SeanNewton 7:a94ba2e0cd04 132 m_buf[m_pos++] = c;
SeanNewton 7:a94ba2e0cd04 133 }
SeanNewton 7:a94ba2e0cd04 134
SeanNewton 7:a94ba2e0cd04 135 void DHCPClient::add_buf(uint8_t* buf, int len)
SeanNewton 7:a94ba2e0cd04 136 {
SeanNewton 7:a94ba2e0cd04 137 for(int i = 0; i < len; i++) {
SeanNewton 7:a94ba2e0cd04 138 add_buf(buf[i]);
SeanNewton 7:a94ba2e0cd04 139 }
SeanNewton 7:a94ba2e0cd04 140 }
SeanNewton 7:a94ba2e0cd04 141
SeanNewton 7:a94ba2e0cd04 142 void DHCPClient::fill_buf(int len, uint8_t data)
SeanNewton 7:a94ba2e0cd04 143 {
SeanNewton 7:a94ba2e0cd04 144 while(len-- > 0) {
SeanNewton 7:a94ba2e0cd04 145 add_buf(data);
SeanNewton 7:a94ba2e0cd04 146 }
SeanNewton 7:a94ba2e0cd04 147 }
SeanNewton 7:a94ba2e0cd04 148
SeanNewton 7:a94ba2e0cd04 149 void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len)
SeanNewton 7:a94ba2e0cd04 150 {
SeanNewton 7:a94ba2e0cd04 151 add_buf(code);
SeanNewton 7:a94ba2e0cd04 152 if (len > 0) {
SeanNewton 7:a94ba2e0cd04 153 add_buf((uint8_t)len);
SeanNewton 7:a94ba2e0cd04 154 add_buf(buf, len);
SeanNewton 7:a94ba2e0cd04 155 }
SeanNewton 7:a94ba2e0cd04 156 }
SeanNewton 7:a94ba2e0cd04 157
SeanNewton 7:a94ba2e0cd04 158 int DHCPClient::setup(int timeout_ms)
SeanNewton 7:a94ba2e0cd04 159 {
SeanNewton 7:a94ba2e0cd04 160 eth = WIZnet_Chip::getInstance();
SeanNewton 7:a94ba2e0cd04 161 if (eth == NULL) {
SeanNewton 7:a94ba2e0cd04 162 return -1;
SeanNewton 7:a94ba2e0cd04 163 }
SeanNewton 7:a94ba2e0cd04 164 eth->reg_rd_mac(SHAR, chaddr);
SeanNewton 7:a94ba2e0cd04 165 int interval_ms = 5*1000; // 5000msec
SeanNewton 7:a94ba2e0cd04 166 if (timeout_ms < interval_ms) {
SeanNewton 7:a94ba2e0cd04 167 interval_ms = timeout_ms;
SeanNewton 7:a94ba2e0cd04 168 }
SeanNewton 7:a94ba2e0cd04 169 m_udp = new UDPSocket;
SeanNewton 7:a94ba2e0cd04 170 m_udp->init();
SeanNewton 7:a94ba2e0cd04 171 m_udp->set_blocking(false);
SeanNewton 7:a94ba2e0cd04 172 eth->reg_wr<uint32_t>(SIPR, 0x00000000); // local ip "0.0.0.0"
SeanNewton 7:a94ba2e0cd04 173 m_udp->bind(68); // local port
SeanNewton 7:a94ba2e0cd04 174 m_server.set_address("255.255.255.255", 67); // DHCP broadcast
SeanNewton 7:a94ba2e0cd04 175 exit_flag = false;
SeanNewton 7:a94ba2e0cd04 176 int err = 0;
SeanNewton 7:a94ba2e0cd04 177 int seq = 0;
SeanNewton 7:a94ba2e0cd04 178 int send_size;
SeanNewton 7:a94ba2e0cd04 179 while(!exit_flag) {
SeanNewton 7:a94ba2e0cd04 180 switch(seq) {
SeanNewton 7:a94ba2e0cd04 181 case 0:
SeanNewton 7:a94ba2e0cd04 182 m_retry = 0;
SeanNewton 7:a94ba2e0cd04 183 seq++;
SeanNewton 7:a94ba2e0cd04 184 DBG("case 0: seq: %d\n", seq);
SeanNewton 7:a94ba2e0cd04 185 break;
SeanNewton 7:a94ba2e0cd04 186 case 1:
SeanNewton 7:a94ba2e0cd04 187 send_size = discover();
SeanNewton 7:a94ba2e0cd04 188 m_udp->sendTo(m_server, (char*)m_buf, send_size);
SeanNewton 7:a94ba2e0cd04 189 m_interval.reset();
SeanNewton 7:a94ba2e0cd04 190 m_interval.start();
SeanNewton 7:a94ba2e0cd04 191 seq++;
SeanNewton 7:a94ba2e0cd04 192 DBG("case 1: seq: %d\n", seq);
SeanNewton 7:a94ba2e0cd04 193 break;
SeanNewton 7:a94ba2e0cd04 194 case 2:
SeanNewton 7:a94ba2e0cd04 195 callback();
SeanNewton 7:a94ba2e0cd04 196 if (m_interval.read_ms() > interval_ms) {
SeanNewton 7:a94ba2e0cd04 197 DBG("m_retry: %d\n", m_retry);
SeanNewton 7:a94ba2e0cd04 198 if (++m_retry >= (timeout_ms/interval_ms)) {
SeanNewton 7:a94ba2e0cd04 199 err = -1;
SeanNewton 7:a94ba2e0cd04 200 exit_flag = true;
SeanNewton 7:a94ba2e0cd04 201 }
SeanNewton 7:a94ba2e0cd04 202 seq--;
SeanNewton 7:a94ba2e0cd04 203 }
SeanNewton 7:a94ba2e0cd04 204 DBG("case 2: seq: %d\n", seq);
SeanNewton 7:a94ba2e0cd04 205 break;
SeanNewton 7:a94ba2e0cd04 206 }
SeanNewton 7:a94ba2e0cd04 207 }
SeanNewton 7:a94ba2e0cd04 208 DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms());
SeanNewton 7:a94ba2e0cd04 209 delete m_udp;
SeanNewton 7:a94ba2e0cd04 210 return err;
SeanNewton 7:a94ba2e0cd04 211 }
SeanNewton 7:a94ba2e0cd04 212
SeanNewton 7:a94ba2e0cd04 213 DHCPClient::DHCPClient() {
SeanNewton 7:a94ba2e0cd04 214 }
SeanNewton 7:a94ba2e0cd04 215