W5500 driver for mbed OS 5
Dependents: http-webserver-example mbed-os-example-sockets
Fork of W5500Interface by
DHCPClient/DHCPClient.cpp@9:351e20cf7d05, 2018-08-10 (annotated)
- Committer:
- Bongjun
- Date:
- Fri Aug 10 08:51:31 2018 +0000
- Revision:
- 9:351e20cf7d05
- Parent:
- 6:e2ab76b2be07
add comment on DHCPClient files
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Bongjun | 9:351e20cf7d05 | 1 | /* |
Bongjun | 9:351e20cf7d05 | 2 | * DHCPClient.cpp |
Bongjun | 9:351e20cf7d05 | 3 | * Mbed OS5 support added by Sergei G <https://os.mbed.com/users/sgnezdov/> |
Bongjun | 9:351e20cf7d05 | 4 | * Ported here on Aug/09/2018 |
Bongjun | 9:351e20cf7d05 | 5 | * |
Bongjun | 9:351e20cf7d05 | 6 | */ |
Bongjun | 9:351e20cf7d05 | 7 | |
Bongjun | 6:e2ab76b2be07 | 8 | // DHCPClient.cpp 2013/4/10 |
Bongjun | 6:e2ab76b2be07 | 9 | #include "mbed.h" |
Bongjun | 6:e2ab76b2be07 | 10 | #include "mbed_debug.h" |
Bongjun | 6:e2ab76b2be07 | 11 | #include "UDPSocket.h" |
Bongjun | 6:e2ab76b2be07 | 12 | #include "DHCPClient.h" |
Bongjun | 6:e2ab76b2be07 | 13 | |
Bongjun | 6:e2ab76b2be07 | 14 | #define DBG_DHCP 0 |
Bongjun | 6:e2ab76b2be07 | 15 | |
Bongjun | 6:e2ab76b2be07 | 16 | #if DBG_DHCP |
Bongjun | 6:e2ab76b2be07 | 17 | #define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0); |
Bongjun | 6:e2ab76b2be07 | 18 | #define DBG_HEX(A,B) do{debug("[%s:%d]\r\n", __PRETTY_FUNCTION__,__LINE__);debug_hex(A,B);} while(0); |
Bongjun | 6:e2ab76b2be07 | 19 | #else |
Bongjun | 6:e2ab76b2be07 | 20 | #define DBG(...) while(0); |
Bongjun | 6:e2ab76b2be07 | 21 | #define DBG_HEX(A,B) while(0); |
Bongjun | 6:e2ab76b2be07 | 22 | #endif |
Bongjun | 6:e2ab76b2be07 | 23 | |
Bongjun | 6:e2ab76b2be07 | 24 | int DHCPClient::discover() |
Bongjun | 6:e2ab76b2be07 | 25 | { |
Bongjun | 6:e2ab76b2be07 | 26 | m_pos = 0; |
Bongjun | 6:e2ab76b2be07 | 27 | const uint8_t header[] = {0x01,0x01,0x06,0x00}; |
Bongjun | 6:e2ab76b2be07 | 28 | add_buf((uint8_t*)header, sizeof(header)); |
Bongjun | 6:e2ab76b2be07 | 29 | uint32_t x = time(NULL) + rand(); |
Bongjun | 6:e2ab76b2be07 | 30 | xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x; |
Bongjun | 6:e2ab76b2be07 | 31 | add_buf(xid, 4); |
Bongjun | 6:e2ab76b2be07 | 32 | fill_buf(20, 0x00); |
Bongjun | 6:e2ab76b2be07 | 33 | add_buf(chaddr, 6); |
Bongjun | 6:e2ab76b2be07 | 34 | fill_buf(10+192, 0x00); |
Bongjun | 6:e2ab76b2be07 | 35 | const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie |
Bongjun | 6:e2ab76b2be07 | 36 | 53,1,DHCPDISCOVER, // DHCP option 53: DHCP Discover |
Bongjun | 6:e2ab76b2be07 | 37 | 55,4,1,3,15,6, |
Bongjun | 6:e2ab76b2be07 | 38 | 255}; |
Bongjun | 6:e2ab76b2be07 | 39 | add_buf((uint8_t*)options, sizeof(options)); |
Bongjun | 6:e2ab76b2be07 | 40 | return m_pos; |
Bongjun | 6:e2ab76b2be07 | 41 | } |
Bongjun | 6:e2ab76b2be07 | 42 | |
Bongjun | 6:e2ab76b2be07 | 43 | int DHCPClient::request() |
Bongjun | 6:e2ab76b2be07 | 44 | { |
Bongjun | 6:e2ab76b2be07 | 45 | m_pos = 0; |
Bongjun | 6:e2ab76b2be07 | 46 | const uint8_t header[] = {0x01,0x01,0x06,0x00}; |
Bongjun | 6:e2ab76b2be07 | 47 | add_buf((uint8_t*)header, sizeof(header)); |
Bongjun | 6:e2ab76b2be07 | 48 | add_buf(xid, 4); |
Bongjun | 6:e2ab76b2be07 | 49 | fill_buf(12, 0x00); |
Bongjun | 6:e2ab76b2be07 | 50 | add_buf(siaddr, 4); |
Bongjun | 6:e2ab76b2be07 | 51 | fill_buf(4, 0x00); // giaddr |
Bongjun | 6:e2ab76b2be07 | 52 | add_buf(chaddr, 6); |
Bongjun | 6:e2ab76b2be07 | 53 | fill_buf(10+192, 0x00); |
Bongjun | 6:e2ab76b2be07 | 54 | const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie |
Bongjun | 6:e2ab76b2be07 | 55 | 53,1,DHCPREQUEST, // DHCP option 53: DHCP Request |
Bongjun | 6:e2ab76b2be07 | 56 | 55,4,1,3,15,6, // DHCP option 55: |
Bongjun | 6:e2ab76b2be07 | 57 | }; |
Bongjun | 6:e2ab76b2be07 | 58 | add_buf((uint8_t*)options, sizeof(options)); |
Bongjun | 6:e2ab76b2be07 | 59 | add_option(50, yiaddr, 4); |
Bongjun | 6:e2ab76b2be07 | 60 | add_option(54, siaddr, 4); |
Bongjun | 6:e2ab76b2be07 | 61 | add_option(255); |
Bongjun | 6:e2ab76b2be07 | 62 | return m_pos; |
Bongjun | 6:e2ab76b2be07 | 63 | } |
Bongjun | 6:e2ab76b2be07 | 64 | |
Bongjun | 6:e2ab76b2be07 | 65 | int DHCPClient::offer(uint8_t buf[], int size) { |
Bongjun | 6:e2ab76b2be07 | 66 | memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4); |
Bongjun | 6:e2ab76b2be07 | 67 | memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4); |
Bongjun | 6:e2ab76b2be07 | 68 | uint8_t *p; |
Bongjun | 6:e2ab76b2be07 | 69 | int msg_type = -1; |
Bongjun | 6:e2ab76b2be07 | 70 | p = buf + DHCP_OFFSET_OPTIONS; |
Bongjun | 6:e2ab76b2be07 | 71 | while(*p != 255 && p < (buf+size)) { |
Bongjun | 6:e2ab76b2be07 | 72 | uint8_t code = *p++; |
Bongjun | 6:e2ab76b2be07 | 73 | if (code == 0) { // Pad Option |
Bongjun | 6:e2ab76b2be07 | 74 | continue; |
Bongjun | 6:e2ab76b2be07 | 75 | } |
Bongjun | 6:e2ab76b2be07 | 76 | int len = *p++; |
Bongjun | 6:e2ab76b2be07 | 77 | |
Bongjun | 6:e2ab76b2be07 | 78 | DBG("DHCP option: %d\r\n", code); |
Bongjun | 6:e2ab76b2be07 | 79 | DBG_HEX(p, len); |
Bongjun | 6:e2ab76b2be07 | 80 | |
Bongjun | 6:e2ab76b2be07 | 81 | switch(code) { |
Bongjun | 6:e2ab76b2be07 | 82 | case 53: |
Bongjun | 6:e2ab76b2be07 | 83 | msg_type = *p; |
Bongjun | 6:e2ab76b2be07 | 84 | break; |
Bongjun | 6:e2ab76b2be07 | 85 | case 1: |
Bongjun | 6:e2ab76b2be07 | 86 | memcpy(netmask, p, 4); // Subnet mask address |
Bongjun | 6:e2ab76b2be07 | 87 | break; |
Bongjun | 6:e2ab76b2be07 | 88 | case 3: |
Bongjun | 6:e2ab76b2be07 | 89 | memcpy(gateway, p, 4); // Gateway IP address |
Bongjun | 6:e2ab76b2be07 | 90 | break; |
Bongjun | 6:e2ab76b2be07 | 91 | case 6: // DNS server |
Bongjun | 6:e2ab76b2be07 | 92 | memcpy(dnsaddr, p, 4); |
Bongjun | 6:e2ab76b2be07 | 93 | break; |
Bongjun | 6:e2ab76b2be07 | 94 | case 51: // IP lease time |
Bongjun | 6:e2ab76b2be07 | 95 | break; |
Bongjun | 6:e2ab76b2be07 | 96 | case 54: // DHCP server |
Bongjun | 6:e2ab76b2be07 | 97 | memcpy(siaddr, p, 4); |
Bongjun | 6:e2ab76b2be07 | 98 | break; |
Bongjun | 6:e2ab76b2be07 | 99 | } |
Bongjun | 6:e2ab76b2be07 | 100 | p += len; |
Bongjun | 6:e2ab76b2be07 | 101 | } |
Bongjun | 6:e2ab76b2be07 | 102 | return msg_type; |
Bongjun | 6:e2ab76b2be07 | 103 | } |
Bongjun | 6:e2ab76b2be07 | 104 | |
Bongjun | 6:e2ab76b2be07 | 105 | bool DHCPClient::verify(uint8_t buf[], int len) { |
Bongjun | 6:e2ab76b2be07 | 106 | if (len < DHCP_OFFSET_OPTIONS) { |
Bongjun | 6:e2ab76b2be07 | 107 | return false; |
Bongjun | 6:e2ab76b2be07 | 108 | } |
Bongjun | 6:e2ab76b2be07 | 109 | if (buf[DHCP_OFFSET_OP] != 0x02) { |
Bongjun | 6:e2ab76b2be07 | 110 | return false; |
Bongjun | 6:e2ab76b2be07 | 111 | } |
Bongjun | 6:e2ab76b2be07 | 112 | if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { |
Bongjun | 6:e2ab76b2be07 | 113 | return false; |
Bongjun | 6:e2ab76b2be07 | 114 | } |
Bongjun | 6:e2ab76b2be07 | 115 | return true; |
Bongjun | 6:e2ab76b2be07 | 116 | } |
Bongjun | 6:e2ab76b2be07 | 117 | |
Bongjun | 6:e2ab76b2be07 | 118 | void DHCPClient::callback() |
Bongjun | 6:e2ab76b2be07 | 119 | { |
Bongjun | 6:e2ab76b2be07 | 120 | DBG("DHCPClient callback\n"); |
Bongjun | 6:e2ab76b2be07 | 121 | SocketAddress host; |
Bongjun | 6:e2ab76b2be07 | 122 | int recv_len = m_udp->recvfrom(&host, (char*)m_buf, sizeof(m_buf)); |
Bongjun | 6:e2ab76b2be07 | 123 | if (recv_len < 0) { |
Bongjun | 6:e2ab76b2be07 | 124 | return; |
Bongjun | 6:e2ab76b2be07 | 125 | } |
Bongjun | 6:e2ab76b2be07 | 126 | if (!verify(m_buf, recv_len)) { |
Bongjun | 6:e2ab76b2be07 | 127 | return; |
Bongjun | 6:e2ab76b2be07 | 128 | } |
Bongjun | 6:e2ab76b2be07 | 129 | int r = offer(m_buf, recv_len); |
Bongjun | 6:e2ab76b2be07 | 130 | if (r == DHCPOFFER) { |
Bongjun | 6:e2ab76b2be07 | 131 | int send_size = request(); |
Bongjun | 6:e2ab76b2be07 | 132 | m_udp->sendto(m_server, (char*)m_buf, send_size); |
Bongjun | 6:e2ab76b2be07 | 133 | } else if (r == DHCPACK) { |
Bongjun | 6:e2ab76b2be07 | 134 | exit_flag = true; |
Bongjun | 6:e2ab76b2be07 | 135 | } |
Bongjun | 6:e2ab76b2be07 | 136 | } |
Bongjun | 6:e2ab76b2be07 | 137 | |
Bongjun | 6:e2ab76b2be07 | 138 | void DHCPClient::add_buf(uint8_t c) |
Bongjun | 6:e2ab76b2be07 | 139 | { |
Bongjun | 6:e2ab76b2be07 | 140 | m_buf[m_pos++] = c; |
Bongjun | 6:e2ab76b2be07 | 141 | } |
Bongjun | 6:e2ab76b2be07 | 142 | |
Bongjun | 6:e2ab76b2be07 | 143 | void DHCPClient::add_buf(uint8_t* buf, int len) |
Bongjun | 6:e2ab76b2be07 | 144 | { |
Bongjun | 6:e2ab76b2be07 | 145 | for(int i = 0; i < len; i++) { |
Bongjun | 6:e2ab76b2be07 | 146 | add_buf(buf[i]); |
Bongjun | 6:e2ab76b2be07 | 147 | } |
Bongjun | 6:e2ab76b2be07 | 148 | } |
Bongjun | 6:e2ab76b2be07 | 149 | |
Bongjun | 6:e2ab76b2be07 | 150 | void DHCPClient::fill_buf(int len, uint8_t data) |
Bongjun | 6:e2ab76b2be07 | 151 | { |
Bongjun | 6:e2ab76b2be07 | 152 | while(len-- > 0) { |
Bongjun | 6:e2ab76b2be07 | 153 | add_buf(data); |
Bongjun | 6:e2ab76b2be07 | 154 | } |
Bongjun | 6:e2ab76b2be07 | 155 | } |
Bongjun | 6:e2ab76b2be07 | 156 | |
Bongjun | 6:e2ab76b2be07 | 157 | void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len) |
Bongjun | 6:e2ab76b2be07 | 158 | { |
Bongjun | 6:e2ab76b2be07 | 159 | add_buf(code); |
Bongjun | 6:e2ab76b2be07 | 160 | if (len > 0) { |
Bongjun | 6:e2ab76b2be07 | 161 | add_buf((uint8_t)len); |
Bongjun | 6:e2ab76b2be07 | 162 | add_buf(buf, len); |
Bongjun | 6:e2ab76b2be07 | 163 | } |
Bongjun | 6:e2ab76b2be07 | 164 | } |
Bongjun | 6:e2ab76b2be07 | 165 | |
Bongjun | 6:e2ab76b2be07 | 166 | int DHCPClient::setup(NetworkStack *ns, uint8_t mac_addr[6], int timeout_ms) |
Bongjun | 6:e2ab76b2be07 | 167 | { |
Bongjun | 6:e2ab76b2be07 | 168 | memcpy(chaddr, mac_addr, 6); |
Bongjun | 6:e2ab76b2be07 | 169 | |
Bongjun | 6:e2ab76b2be07 | 170 | int interval_ms = 5*1000; // 5000msec |
Bongjun | 6:e2ab76b2be07 | 171 | if (timeout_ms < interval_ms) { |
Bongjun | 6:e2ab76b2be07 | 172 | interval_ms = timeout_ms; |
Bongjun | 6:e2ab76b2be07 | 173 | } |
Bongjun | 6:e2ab76b2be07 | 174 | |
Bongjun | 6:e2ab76b2be07 | 175 | UDPSocket udp_sock; |
Bongjun | 6:e2ab76b2be07 | 176 | m_udp = &udp_sock; |
Bongjun | 6:e2ab76b2be07 | 177 | { |
Bongjun | 6:e2ab76b2be07 | 178 | nsapi_error_t err = udp_sock.open(ns); |
Bongjun | 6:e2ab76b2be07 | 179 | if (err) { |
Bongjun | 6:e2ab76b2be07 | 180 | DBG("setup failed to open UDP socket."); |
Bongjun | 6:e2ab76b2be07 | 181 | return err; |
Bongjun | 6:e2ab76b2be07 | 182 | } |
Bongjun | 6:e2ab76b2be07 | 183 | udp_sock.set_blocking(false); |
Bongjun | 6:e2ab76b2be07 | 184 | err = udp_sock.bind(68); // local port |
Bongjun | 6:e2ab76b2be07 | 185 | if (err) { |
Bongjun | 6:e2ab76b2be07 | 186 | DBG("setup failed in bind: %d", err); |
Bongjun | 6:e2ab76b2be07 | 187 | return err; |
Bongjun | 6:e2ab76b2be07 | 188 | } |
Bongjun | 6:e2ab76b2be07 | 189 | } |
Bongjun | 6:e2ab76b2be07 | 190 | |
Bongjun | 6:e2ab76b2be07 | 191 | m_server.set_ip_address("255.255.255.255"); // DHCP broadcast |
Bongjun | 6:e2ab76b2be07 | 192 | m_server.set_port(67); // DHCP broadcast |
Bongjun | 6:e2ab76b2be07 | 193 | exit_flag = false; |
Bongjun | 6:e2ab76b2be07 | 194 | int err = 0; |
Bongjun | 6:e2ab76b2be07 | 195 | int seq = 0; |
Bongjun | 6:e2ab76b2be07 | 196 | int send_size; |
Bongjun | 6:e2ab76b2be07 | 197 | while(!exit_flag) { |
Bongjun | 6:e2ab76b2be07 | 198 | switch(seq) { |
Bongjun | 6:e2ab76b2be07 | 199 | case 0: |
Bongjun | 6:e2ab76b2be07 | 200 | m_retry = 0; |
Bongjun | 6:e2ab76b2be07 | 201 | seq++; |
Bongjun | 6:e2ab76b2be07 | 202 | break; |
Bongjun | 6:e2ab76b2be07 | 203 | case 1: |
Bongjun | 6:e2ab76b2be07 | 204 | send_size = discover(); |
Bongjun | 6:e2ab76b2be07 | 205 | nsapi_size_or_error_t err2 = udp_sock.sendto(m_server, (char*)m_buf, send_size); |
Bongjun | 6:e2ab76b2be07 | 206 | if (err2 < 0) { |
Bongjun | 6:e2ab76b2be07 | 207 | DBG("setup sendto error: %d\n", err2); |
Bongjun | 6:e2ab76b2be07 | 208 | return err2; |
Bongjun | 6:e2ab76b2be07 | 209 | } |
Bongjun | 6:e2ab76b2be07 | 210 | m_interval.reset(); |
Bongjun | 6:e2ab76b2be07 | 211 | m_interval.start(); |
Bongjun | 6:e2ab76b2be07 | 212 | seq++; |
Bongjun | 6:e2ab76b2be07 | 213 | break; |
Bongjun | 6:e2ab76b2be07 | 214 | case 2: |
Bongjun | 6:e2ab76b2be07 | 215 | callback(); |
Bongjun | 6:e2ab76b2be07 | 216 | if (m_interval.read_ms() > interval_ms) { |
Bongjun | 6:e2ab76b2be07 | 217 | DBG("m_retry: %d\n", m_retry); |
Bongjun | 6:e2ab76b2be07 | 218 | if (++m_retry >= (timeout_ms/interval_ms)) { |
Bongjun | 6:e2ab76b2be07 | 219 | err = -1; |
Bongjun | 6:e2ab76b2be07 | 220 | exit_flag = true; |
Bongjun | 6:e2ab76b2be07 | 221 | } |
Bongjun | 6:e2ab76b2be07 | 222 | seq--; |
Bongjun | 6:e2ab76b2be07 | 223 | } |
Bongjun | 6:e2ab76b2be07 | 224 | break; |
Bongjun | 6:e2ab76b2be07 | 225 | } |
Bongjun | 6:e2ab76b2be07 | 226 | } |
Bongjun | 6:e2ab76b2be07 | 227 | DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms()); |
Bongjun | 6:e2ab76b2be07 | 228 | return err; |
Bongjun | 6:e2ab76b2be07 | 229 | } |
Bongjun | 6:e2ab76b2be07 | 230 | |
Bongjun | 6:e2ab76b2be07 | 231 | DHCPClient::DHCPClient() { |
Bongjun | 6:e2ab76b2be07 | 232 | } |