W5500 driver for mbed OS 5

Dependents:   http-webserver-example mbed-os-example-sockets

Fork of W5500Interface by Sergei G

Committer:
Bongjun
Date:
Thu Aug 16 07:33:40 2018 +0000
Revision:
18:afec30f0922a
Parent:
6:e2ab76b2be07
change spi frame bits : 32->8

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bongjun 6:e2ab76b2be07 1 // DNSClient.cpp 2013/8/27
Bongjun 6:e2ab76b2be07 2 #include "mbed.h"
Bongjun 6:e2ab76b2be07 3 #include "mbed_debug.h"
Bongjun 6:e2ab76b2be07 4 #include "DNSClient.h"
Bongjun 6:e2ab76b2be07 5 #include "UDPSocket.h"
Bongjun 6:e2ab76b2be07 6 #include "dnsname.h"
Bongjun 6:e2ab76b2be07 7 #include "wiznet.h"
Bongjun 6:e2ab76b2be07 8
Bongjun 6:e2ab76b2be07 9 #if DBG_DNS
Bongjun 6:e2ab76b2be07 10 #define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
Bongjun 6:e2ab76b2be07 11 #else
Bongjun 6:e2ab76b2be07 12 #define DBG2(...) while(0);
Bongjun 6:e2ab76b2be07 13 #endif
Bongjun 6:e2ab76b2be07 14
Bongjun 6:e2ab76b2be07 15 static SocketAddress theDnsServer;
Bongjun 6:e2ab76b2be07 16
Bongjun 6:e2ab76b2be07 17 DNSClient::DNSClient() : m_state(MYNETDNS_START), m_udp(NULL) {
Bongjun 6:e2ab76b2be07 18 m_ns = NULL;
Bongjun 6:e2ab76b2be07 19
Bongjun 6:e2ab76b2be07 20 //default to google
Bongjun 6:e2ab76b2be07 21 theDnsServer.set_ip_address("8.8.8.8"); // DNS
Bongjun 6:e2ab76b2be07 22 theDnsServer.set_port(53); // DNS
Bongjun 6:e2ab76b2be07 23 }
Bongjun 6:e2ab76b2be07 24
Bongjun 6:e2ab76b2be07 25 DNSClient::DNSClient(NetworkStack *ns, const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) {
Bongjun 6:e2ab76b2be07 26 m_hostname = hostname;
Bongjun 6:e2ab76b2be07 27 m_ns = ns;
Bongjun 6:e2ab76b2be07 28
Bongjun 6:e2ab76b2be07 29 //default to google
Bongjun 6:e2ab76b2be07 30 theDnsServer.set_ip_address("8.8.8.8"); // DNS
Bongjun 6:e2ab76b2be07 31 theDnsServer.set_port(53); // DNS
Bongjun 6:e2ab76b2be07 32 }
Bongjun 6:e2ab76b2be07 33
Bongjun 6:e2ab76b2be07 34 DNSClient::DNSClient(NetworkStack *ns, SocketAddress* pHost) : m_state(MYNETDNS_START), m_udp(NULL) {
Bongjun 6:e2ab76b2be07 35 m_ns = ns;
Bongjun 6:e2ab76b2be07 36
Bongjun 6:e2ab76b2be07 37 //default to google
Bongjun 6:e2ab76b2be07 38 theDnsServer.set_ip_address("8.8.8.8"); // DNS
Bongjun 6:e2ab76b2be07 39 theDnsServer.set_port(53); // DNS
Bongjun 6:e2ab76b2be07 40 }
Bongjun 6:e2ab76b2be07 41
Bongjun 6:e2ab76b2be07 42 DNSClient::~DNSClient() {
Bongjun 6:e2ab76b2be07 43 if (m_udp) {
Bongjun 6:e2ab76b2be07 44 delete m_udp;
Bongjun 6:e2ab76b2be07 45 }
Bongjun 6:e2ab76b2be07 46 }
Bongjun 6:e2ab76b2be07 47
Bongjun 6:e2ab76b2be07 48 int DNSClient::setup(NetworkStack *ns) {
Bongjun 6:e2ab76b2be07 49 m_ns = ns;
Bongjun 6:e2ab76b2be07 50 return 0;
Bongjun 6:e2ab76b2be07 51 }
Bongjun 6:e2ab76b2be07 52
Bongjun 6:e2ab76b2be07 53 bool DNSClient::set_server(const char* serverip, int port) {
Bongjun 6:e2ab76b2be07 54 theDnsServer.set_ip_address(serverip);
Bongjun 6:e2ab76b2be07 55 theDnsServer.set_port(port);
Bongjun 6:e2ab76b2be07 56 return true;
Bongjun 6:e2ab76b2be07 57 }
Bongjun 6:e2ab76b2be07 58
Bongjun 6:e2ab76b2be07 59 void DNSClient::callback()
Bongjun 6:e2ab76b2be07 60 {
Bongjun 6:e2ab76b2be07 61 uint8_t buf[512];
Bongjun 6:e2ab76b2be07 62 SocketAddress host;
Bongjun 6:e2ab76b2be07 63 int len = m_udp->recvfrom(&host, (char*)buf, sizeof(buf));
Bongjun 6:e2ab76b2be07 64 if (len < 0) {
Bongjun 6:e2ab76b2be07 65 return;
Bongjun 6:e2ab76b2be07 66 }
Bongjun 6:e2ab76b2be07 67 if (memcmp(buf+0, m_id, 2) != 0) { //verify
Bongjun 6:e2ab76b2be07 68 return;
Bongjun 6:e2ab76b2be07 69 }
Bongjun 6:e2ab76b2be07 70
Bongjun 6:e2ab76b2be07 71 int rcode = response(buf, len);
Bongjun 6:e2ab76b2be07 72 if (rcode == 0) {
Bongjun 6:e2ab76b2be07 73 m_state = MYNETDNS_OK;
Bongjun 6:e2ab76b2be07 74 } else {
Bongjun 6:e2ab76b2be07 75 m_state = MYNETDNS_NOTFOUND;
Bongjun 6:e2ab76b2be07 76 }
Bongjun 6:e2ab76b2be07 77 }
Bongjun 6:e2ab76b2be07 78
Bongjun 6:e2ab76b2be07 79 int DNSClient::response(uint8_t buf[], int size) {
Bongjun 6:e2ab76b2be07 80 int rcode = buf[3] & 0x0f;
Bongjun 6:e2ab76b2be07 81 if (rcode != 0) {
Bongjun 6:e2ab76b2be07 82 return rcode;
Bongjun 6:e2ab76b2be07 83 }
Bongjun 6:e2ab76b2be07 84 int qdcount = buf[4]<<8|buf[5];
Bongjun 6:e2ab76b2be07 85 int ancount = buf[6]<<8|buf[7];
Bongjun 6:e2ab76b2be07 86 int pos = 12;
Bongjun 6:e2ab76b2be07 87 while(qdcount-- > 0) {
Bongjun 6:e2ab76b2be07 88 dnsname qname(buf);
Bongjun 6:e2ab76b2be07 89 pos = qname.decode(pos); // qname
Bongjun 6:e2ab76b2be07 90 pos += 4; // qtype qclass
Bongjun 6:e2ab76b2be07 91 }
Bongjun 6:e2ab76b2be07 92 while(ancount-- > 0) {
Bongjun 6:e2ab76b2be07 93 dnsname name(buf);
Bongjun 6:e2ab76b2be07 94 pos = name.decode(pos); // name
Bongjun 6:e2ab76b2be07 95 int type = buf[pos]<<8|buf[pos+1];
Bongjun 6:e2ab76b2be07 96 pos += 8; // type class TTL
Bongjun 6:e2ab76b2be07 97 int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2;
Bongjun 6:e2ab76b2be07 98 int rdata_pos = pos;
Bongjun 6:e2ab76b2be07 99 pos += rdlength;
Bongjun 6:e2ab76b2be07 100 if (type == 1) { // A record
Bongjun 6:e2ab76b2be07 101 m_ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3];
Bongjun 6:e2ab76b2be07 102 sprintf(m_ipaddr, "%d.%d.%d.%d", buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
Bongjun 6:e2ab76b2be07 103 }
Bongjun 6:e2ab76b2be07 104 #if DBG_DNS
Bongjun 6:e2ab76b2be07 105 printf("%s", name.str.c_str());
Bongjun 6:e2ab76b2be07 106 if (type == 1) {
Bongjun 6:e2ab76b2be07 107 printf(" A %d.%d.%d.%d\n",
Bongjun 6:e2ab76b2be07 108 buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
Bongjun 6:e2ab76b2be07 109 } else if (type == 5) {
Bongjun 6:e2ab76b2be07 110 dnsname rdname(buf);
Bongjun 6:e2ab76b2be07 111 rdname.decode(rdata_pos);
Bongjun 6:e2ab76b2be07 112 printf(" CNAME %s\n", rdname.str.c_str());
Bongjun 6:e2ab76b2be07 113 } else {
Bongjun 6:e2ab76b2be07 114 printf(" TYPE:%d", type);
Bongjun 6:e2ab76b2be07 115 printfBytes(" RDATA:", &buf[rdata_pos], rdlength);
Bongjun 6:e2ab76b2be07 116 }
Bongjun 6:e2ab76b2be07 117 #endif
Bongjun 6:e2ab76b2be07 118 }
Bongjun 6:e2ab76b2be07 119 return rcode;
Bongjun 6:e2ab76b2be07 120 }
Bongjun 6:e2ab76b2be07 121
Bongjun 6:e2ab76b2be07 122 int DNSClient::query(uint8_t buf[], int size, const char* hostname) {
Bongjun 6:e2ab76b2be07 123 const uint8_t header[] = {
Bongjun 6:e2ab76b2be07 124 0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0
Bongjun 6:e2ab76b2be07 125 0x00,0x01,0x00,0x00, // qdcount=1 ancount=0
Bongjun 6:e2ab76b2be07 126 0x00,0x00,0x00,0x00};// nscount=0 arcount=0
Bongjun 6:e2ab76b2be07 127 const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN
Bongjun 6:e2ab76b2be07 128 memcpy(buf, header, sizeof(header));
Bongjun 6:e2ab76b2be07 129 int t = rand();
Bongjun 6:e2ab76b2be07 130 m_id[0] = t>>8;
Bongjun 6:e2ab76b2be07 131 m_id[1] = t;
Bongjun 6:e2ab76b2be07 132 memcpy(buf, m_id, 2);
Bongjun 6:e2ab76b2be07 133 dnsname qname(buf);
Bongjun 6:e2ab76b2be07 134 int pos = qname.encode(sizeof(header), (char*)hostname);
Bongjun 6:e2ab76b2be07 135 memcpy(buf+pos, tail, sizeof(tail));
Bongjun 6:e2ab76b2be07 136 pos += sizeof(tail);
Bongjun 6:e2ab76b2be07 137 return pos;
Bongjun 6:e2ab76b2be07 138 }
Bongjun 6:e2ab76b2be07 139
Bongjun 6:e2ab76b2be07 140 void DNSClient::resolve(const char* hostname) {
Bongjun 6:e2ab76b2be07 141 if (m_udp == NULL) {
Bongjun 6:e2ab76b2be07 142 m_udp = new UDPSocket;
Bongjun 6:e2ab76b2be07 143 m_udp->open(m_ns);
Bongjun 6:e2ab76b2be07 144 }
Bongjun 6:e2ab76b2be07 145 m_udp->set_blocking(false);
Bongjun 6:e2ab76b2be07 146 m_udp->bind(rand()&0x7fff);
Bongjun 6:e2ab76b2be07 147 uint8_t buf[256];
Bongjun 6:e2ab76b2be07 148 int size = query(buf, sizeof(buf), hostname);
Bongjun 6:e2ab76b2be07 149 #if DBG_DNS
Bongjun 6:e2ab76b2be07 150 printf("hostname:[%s]\n", hostname);
Bongjun 6:e2ab76b2be07 151 printHex(buf, size);
Bongjun 6:e2ab76b2be07 152 #endif
Bongjun 6:e2ab76b2be07 153 m_udp->sendto(theDnsServer, (char*)buf, size);
Bongjun 6:e2ab76b2be07 154 m_interval.reset();
Bongjun 6:e2ab76b2be07 155 m_interval.start();
Bongjun 6:e2ab76b2be07 156 }
Bongjun 6:e2ab76b2be07 157
Bongjun 6:e2ab76b2be07 158 void DNSClient::poll() {
Bongjun 6:e2ab76b2be07 159 #if DBG_DNS
Bongjun 6:e2ab76b2be07 160 printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
Bongjun 6:e2ab76b2be07 161 wait_ms(400);
Bongjun 6:e2ab76b2be07 162 #endif
Bongjun 6:e2ab76b2be07 163 switch(m_state) {
Bongjun 6:e2ab76b2be07 164 case MYNETDNS_START:
Bongjun 6:e2ab76b2be07 165 m_retry = 0;
Bongjun 6:e2ab76b2be07 166 resolve(m_hostname);
Bongjun 6:e2ab76b2be07 167 m_state = MYNETDNS_PROCESSING;
Bongjun 6:e2ab76b2be07 168 break;
Bongjun 6:e2ab76b2be07 169 case MYNETDNS_PROCESSING:
Bongjun 6:e2ab76b2be07 170 break;
Bongjun 6:e2ab76b2be07 171 case MYNETDNS_NOTFOUND:
Bongjun 6:e2ab76b2be07 172 break;
Bongjun 6:e2ab76b2be07 173 case MYNETDNS_ERROR:
Bongjun 6:e2ab76b2be07 174 break;
Bongjun 6:e2ab76b2be07 175 case MYNETDNS_OK:
Bongjun 6:e2ab76b2be07 176 DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms());
Bongjun 6:e2ab76b2be07 177 break;
Bongjun 6:e2ab76b2be07 178 }
Bongjun 6:e2ab76b2be07 179 if (m_interval.read_ms() > 1000) {
Bongjun 6:e2ab76b2be07 180 m_interval.stop();
Bongjun 6:e2ab76b2be07 181 DBG2("timeout m_retry=%d\n", m_retry);
Bongjun 6:e2ab76b2be07 182 if (++m_retry >= 2) {
Bongjun 6:e2ab76b2be07 183 m_state = MYNETDNS_ERROR;
Bongjun 6:e2ab76b2be07 184 } else {
Bongjun 6:e2ab76b2be07 185 resolve(m_hostname);
Bongjun 6:e2ab76b2be07 186 m_state = MYNETDNS_PROCESSING;
Bongjun 6:e2ab76b2be07 187 }
Bongjun 6:e2ab76b2be07 188 }
Bongjun 6:e2ab76b2be07 189 }
Bongjun 6:e2ab76b2be07 190
Bongjun 6:e2ab76b2be07 191 //tests for a valid IP address, returns 0 if invalid IP address format, returns ip address if valid
Bongjun 6:e2ab76b2be07 192 static uint32_t
Bongjun 6:e2ab76b2be07 193 isValidIP(const char* ip) {
Bongjun 6:e2ab76b2be07 194 int i1, i2, i3, i4;
Bongjun 6:e2ab76b2be07 195 int len = strlen(ip);
Bongjun 6:e2ab76b2be07 196
Bongjun 6:e2ab76b2be07 197 if (len < 7) return 0;
Bongjun 6:e2ab76b2be07 198
Bongjun 6:e2ab76b2be07 199 //count the number of dots, there must be 3
Bongjun 6:e2ab76b2be07 200 int dotcount = 0;
Bongjun 6:e2ab76b2be07 201 for (int i = 0; i < len; i++) {
Bongjun 6:e2ab76b2be07 202 if (ip[i] == '.' ) dotcount++;
Bongjun 6:e2ab76b2be07 203 }
Bongjun 6:e2ab76b2be07 204
Bongjun 6:e2ab76b2be07 205 //there must be exactly 3 dots
Bongjun 6:e2ab76b2be07 206 if (dotcount != 3) return 0;
Bongjun 6:e2ab76b2be07 207
Bongjun 6:e2ab76b2be07 208 sscanf((char*)ip, "%d.%d.%d.%d", &i1, &i2, &i3, &i4);
Bongjun 6:e2ab76b2be07 209
Bongjun 6:e2ab76b2be07 210 if (strlen(ip) <= 16 && (i1 >= 0 && i1 <= 255) && (i2 >= 0 && i2 <= 255) &&
Bongjun 6:e2ab76b2be07 211 (i3 >= 0 && i3 <= 255) && (i4 >= 0 && i4 <= 255)) {
Bongjun 6:e2ab76b2be07 212 return ((i1<<24) | (i2<<16) | (i3<<8) | i4);
Bongjun 6:e2ab76b2be07 213 }
Bongjun 6:e2ab76b2be07 214 return 0;
Bongjun 6:e2ab76b2be07 215 }
Bongjun 6:e2ab76b2be07 216
Bongjun 6:e2ab76b2be07 217 bool DNSClient::lookup(const char* hostname) {
Bongjun 6:e2ab76b2be07 218 m_hostname = hostname;
Bongjun 6:e2ab76b2be07 219
Bongjun 6:e2ab76b2be07 220 uint32_t ip = isValidIP(hostname);
Bongjun 6:e2ab76b2be07 221
Bongjun 6:e2ab76b2be07 222 //check if hostname is an IP address
Bongjun 6:e2ab76b2be07 223 if (ip > 0) {
Bongjun 6:e2ab76b2be07 224 //if it is already an IP address just return immediately
Bongjun 6:e2ab76b2be07 225 m_ip = ip;
Bongjun 6:e2ab76b2be07 226 strcpy(m_ipaddr, hostname);
Bongjun 6:e2ab76b2be07 227 m_state = MYNETDNS_OK;
Bongjun 6:e2ab76b2be07 228 return true;
Bongjun 6:e2ab76b2be07 229 }
Bongjun 6:e2ab76b2be07 230
Bongjun 6:e2ab76b2be07 231 m_state = MYNETDNS_START;
Bongjun 6:e2ab76b2be07 232 while(1) {
Bongjun 6:e2ab76b2be07 233 poll();
Bongjun 6:e2ab76b2be07 234 callback();
Bongjun 6:e2ab76b2be07 235 if (m_state != MYNETDNS_PROCESSING) {
Bongjun 6:e2ab76b2be07 236 break;
Bongjun 6:e2ab76b2be07 237 }
Bongjun 6:e2ab76b2be07 238 }
Bongjun 6:e2ab76b2be07 239
Bongjun 6:e2ab76b2be07 240 if (m_udp) {
Bongjun 6:e2ab76b2be07 241 delete m_udp;
Bongjun 6:e2ab76b2be07 242 m_udp = NULL;
Bongjun 6:e2ab76b2be07 243 }
Bongjun 6:e2ab76b2be07 244 return m_state == MYNETDNS_OK;
Bongjun 6:e2ab76b2be07 245 }