W5500 driver for mbed OS 5
Dependents: http-webserver-example mbed-os-example-sockets
Fork of W5500Interface by
DHCPClient.cpp
00001 /* 00002 * DHCPClient.cpp 00003 * Mbed OS5 support added by Sergei G <https://os.mbed.com/users/sgnezdov/> 00004 * Ported here on Aug/09/2018 00005 * 00006 */ 00007 00008 // DHCPClient.cpp 2013/4/10 00009 #include "mbed.h" 00010 #include "mbed_debug.h" 00011 #include "UDPSocket.h" 00012 #include "DHCPClient.h" 00013 00014 #define DBG_DHCP 0 00015 00016 #if DBG_DHCP 00017 #define DBG(...) do{debug("[%s:%d]", __PRETTY_FUNCTION__,__LINE__);debug(__VA_ARGS__);} while(0); 00018 #define DBG_HEX(A,B) do{debug("[%s:%d]\r\n", __PRETTY_FUNCTION__,__LINE__);debug_hex(A,B);} while(0); 00019 #else 00020 #define DBG(...) while(0); 00021 #define DBG_HEX(A,B) while(0); 00022 #endif 00023 00024 int DHCPClient::discover() 00025 { 00026 m_pos = 0; 00027 const uint8_t header[] = {0x01,0x01,0x06,0x00}; 00028 add_buf((uint8_t*)header, sizeof(header)); 00029 uint32_t x = time(NULL) + rand(); 00030 xid[0] = x>>24; xid[1] = x>>16; xid[2] = x>>8; xid[3] = x; 00031 add_buf(xid, 4); 00032 fill_buf(20, 0x00); 00033 add_buf(chaddr, 6); 00034 fill_buf(10+192, 0x00); 00035 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00036 53,1,DHCPDISCOVER, // DHCP option 53: DHCP Discover 00037 55,4,1,3,15,6, 00038 255}; 00039 add_buf((uint8_t*)options, sizeof(options)); 00040 return m_pos; 00041 } 00042 00043 int DHCPClient::request() 00044 { 00045 m_pos = 0; 00046 const uint8_t header[] = {0x01,0x01,0x06,0x00}; 00047 add_buf((uint8_t*)header, sizeof(header)); 00048 add_buf(xid, 4); 00049 fill_buf(12, 0x00); 00050 add_buf(siaddr, 4); 00051 fill_buf(4, 0x00); // giaddr 00052 add_buf(chaddr, 6); 00053 fill_buf(10+192, 0x00); 00054 const uint8_t options[] = {0x63,0x82,0x53,0x63, // magic cookie 00055 53,1,DHCPREQUEST, // DHCP option 53: DHCP Request 00056 55,4,1,3,15,6, // DHCP option 55: 00057 }; 00058 add_buf((uint8_t*)options, sizeof(options)); 00059 add_option(50, yiaddr, 4); 00060 add_option(54, siaddr, 4); 00061 add_option(255); 00062 return m_pos; 00063 } 00064 00065 int DHCPClient::offer(uint8_t buf[], int size) { 00066 memcpy(yiaddr, buf+DHCP_OFFSET_YIADDR, 4); 00067 memcpy(siaddr, buf+DHCP_OFFSET_SIADDR, 4); 00068 uint8_t *p; 00069 int msg_type = -1; 00070 p = buf + DHCP_OFFSET_OPTIONS; 00071 while(*p != 255 && p < (buf+size)) { 00072 uint8_t code = *p++; 00073 if (code == 0) { // Pad Option 00074 continue; 00075 } 00076 int len = *p++; 00077 00078 DBG("DHCP option: %d\r\n", code); 00079 DBG_HEX(p, len); 00080 00081 switch(code) { 00082 case 53: 00083 msg_type = *p; 00084 break; 00085 case 1: 00086 memcpy(netmask, p, 4); // Subnet mask address 00087 break; 00088 case 3: 00089 memcpy(gateway, p, 4); // Gateway IP address 00090 break; 00091 case 6: // DNS server 00092 memcpy(dnsaddr, p, 4); 00093 break; 00094 case 51: // IP lease time 00095 break; 00096 case 54: // DHCP server 00097 memcpy(siaddr, p, 4); 00098 break; 00099 } 00100 p += len; 00101 } 00102 return msg_type; 00103 } 00104 00105 bool DHCPClient::verify(uint8_t buf[], int len) { 00106 if (len < DHCP_OFFSET_OPTIONS) { 00107 return false; 00108 } 00109 if (buf[DHCP_OFFSET_OP] != 0x02) { 00110 return false; 00111 } 00112 if (memcmp(buf+DHCP_OFFSET_XID, xid, 4) != 0) { 00113 return false; 00114 } 00115 return true; 00116 } 00117 00118 void DHCPClient::callback() 00119 { 00120 DBG("DHCPClient callback\n"); 00121 SocketAddress host; 00122 int recv_len = m_udp->recvfrom(&host, (char*)m_buf, sizeof(m_buf)); 00123 if (recv_len < 0) { 00124 return; 00125 } 00126 if (!verify(m_buf, recv_len)) { 00127 return; 00128 } 00129 int r = offer(m_buf, recv_len); 00130 if (r == DHCPOFFER) { 00131 int send_size = request(); 00132 m_udp->sendto(m_server, (char*)m_buf, send_size); 00133 } else if (r == DHCPACK) { 00134 exit_flag = true; 00135 } 00136 } 00137 00138 void DHCPClient::add_buf(uint8_t c) 00139 { 00140 m_buf[m_pos++] = c; 00141 } 00142 00143 void DHCPClient::add_buf(uint8_t* buf, int len) 00144 { 00145 for(int i = 0; i < len; i++) { 00146 add_buf(buf[i]); 00147 } 00148 } 00149 00150 void DHCPClient::fill_buf(int len, uint8_t data) 00151 { 00152 while(len-- > 0) { 00153 add_buf(data); 00154 } 00155 } 00156 00157 void DHCPClient::add_option(uint8_t code, uint8_t* buf, int len) 00158 { 00159 add_buf(code); 00160 if (len > 0) { 00161 add_buf((uint8_t)len); 00162 add_buf(buf, len); 00163 } 00164 } 00165 00166 int DHCPClient::setup(NetworkStack *ns, uint8_t mac_addr[6], int timeout_ms) 00167 { 00168 memcpy(chaddr, mac_addr, 6); 00169 00170 int interval_ms = 5*1000; // 5000msec 00171 if (timeout_ms < interval_ms) { 00172 interval_ms = timeout_ms; 00173 } 00174 00175 UDPSocket udp_sock; 00176 m_udp = &udp_sock; 00177 { 00178 nsapi_error_t err = udp_sock.open(ns); 00179 if (err) { 00180 DBG("setup failed to open UDP socket."); 00181 return err; 00182 } 00183 udp_sock.set_blocking(false); 00184 err = udp_sock.bind(68); // local port 00185 if (err) { 00186 DBG("setup failed in bind: %d", err); 00187 return err; 00188 } 00189 } 00190 00191 m_server.set_ip_address("255.255.255.255"); // DHCP broadcast 00192 m_server.set_port(67); // DHCP broadcast 00193 exit_flag = false; 00194 int err = 0; 00195 int seq = 0; 00196 int send_size; 00197 while(!exit_flag) { 00198 switch(seq) { 00199 case 0: 00200 m_retry = 0; 00201 seq++; 00202 break; 00203 case 1: 00204 send_size = discover(); 00205 nsapi_size_or_error_t err2 = udp_sock.sendto(m_server, (char*)m_buf, send_size); 00206 if (err2 < 0) { 00207 DBG("setup sendto error: %d\n", err2); 00208 return err2; 00209 } 00210 m_interval.reset(); 00211 m_interval.start(); 00212 seq++; 00213 break; 00214 case 2: 00215 callback(); 00216 if (m_interval.read_ms() > interval_ms) { 00217 DBG("m_retry: %d\n", m_retry); 00218 if (++m_retry >= (timeout_ms/interval_ms)) { 00219 err = -1; 00220 exit_flag = true; 00221 } 00222 seq--; 00223 } 00224 break; 00225 } 00226 } 00227 DBG("m_retry: %d, m_interval: %d\n", m_retry, m_interval.read_ms()); 00228 return err; 00229 } 00230 00231 DHCPClient::DHCPClient() { 00232 }
Generated on Tue Jul 12 2022 18:48:25 by 1.7.2