This is the Interface library for WIZnet W5500 chip which forked of EthernetInterfaceW5500, WIZnetInterface and WIZ550ioInterface. This library has simple name as "W5500Interface". and can be used for Wiz550io users also.

Dependents:   EvrythngApi Websocket_Ethernet_HelloWorld_W5500 Websocket_Ethernet_W5500 CurrentWeatherData_W5500 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DNSClient.cpp Source File

DNSClient.cpp

00001 // DNSClient.cpp 2013/8/27
00002 #include "mbed.h"
00003 #include "mbed_debug.h"
00004 #include "DNSClient.h"
00005 #include "UDPSocket.h"
00006 #include "dnsname.h"
00007 #include "wiznet.h"
00008 
00009 #define DBG_DNS 0
00010 
00011 #if DBG_DNS
00012 #define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
00013 #else
00014 #define DBG2(...) while(0);
00015 #endif
00016 
00017 DNSClient::DNSClient(const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) {
00018     m_hostname = hostname;
00019 }
00020 
00021 DNSClient::DNSClient(Endpoint* pHost) : m_state(MYNETDNS_START), m_udp(NULL) {
00022 }
00023 
00024 DNSClient::~DNSClient() {
00025     if (m_udp) {
00026         delete m_udp;
00027     }
00028 }
00029 
00030 void DNSClient::callback()
00031 {
00032     uint8_t buf[512];
00033     Endpoint host;
00034     int len = m_udp->receiveFrom(host, (char*)buf, sizeof(buf));
00035     if (len < 0) {
00036         return;
00037     }
00038     if (memcmp(buf+0, m_id, 2) != 0) { //verify
00039         return;
00040     }
00041     int rcode = response(buf, len);
00042     if (rcode == 0) {
00043         m_state = MYNETDNS_OK;
00044     } else {
00045         m_state = MYNETDNS_NOTFOUND;
00046     }
00047 }
00048 
00049 int DNSClient::response(uint8_t buf[], int size) {
00050     int rcode = buf[3] & 0x0f;
00051     if (rcode != 0) {
00052         return rcode;
00053     }
00054     int qdcount = buf[4]<<8|buf[5];
00055     int ancount = buf[6]<<8|buf[7];
00056     int pos = 12;
00057     while(qdcount-- > 0) {
00058         dnsname qname(buf);
00059         pos = qname.decode(pos); // qname
00060         pos += 4; // qtype qclass
00061     }
00062     while(ancount-- > 0) {
00063         dnsname name(buf);
00064         pos = name.decode(pos); // name
00065         int type = buf[pos]<<8|buf[pos+1];
00066         pos += 8; // type class TTL  
00067         int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2;
00068         int rdata_pos = pos;
00069         pos += rdlength;
00070         if (type == 1) { // A record
00071             ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3];
00072         }
00073 #if DBG_DNS
00074         printf("%s", name.str.c_str());
00075         if (type == 1) {
00076             printf(" A %d.%d.%d.%d\n", 
00077                 buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
00078         } else if (type == 5) {
00079             dnsname rdname(buf);
00080             rdname.decode(rdata_pos);
00081             printf(" CNAME %s\n", rdname.str.c_str());
00082         } else {
00083             printf(" TYPE:%d", type);
00084             printfBytes(" RDATA:", &buf[rdata_pos], rdlength);
00085         }
00086 #endif
00087     }
00088     return rcode;
00089 }
00090 
00091 int DNSClient::query(uint8_t buf[], int size, const char* hostname) {
00092     const uint8_t header[] = {
00093         0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0
00094         0x00,0x01,0x00,0x00, // qdcount=1 ancount=0
00095         0x00,0x00,0x00,0x00};// nscount=0 arcount=0 
00096     const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN
00097     memcpy(buf, header, sizeof(header));
00098     int t = rand();
00099     m_id[0] = t>>8;
00100     m_id[1] = t;
00101     memcpy(buf, m_id, 2); 
00102     dnsname qname(buf);
00103     int pos = qname.encode(sizeof(header), (char*)hostname);
00104     memcpy(buf+pos, tail, sizeof(tail));
00105     pos += sizeof(tail);
00106     return pos;
00107 }
00108 
00109 void DNSClient::resolve(const char* hostname) {
00110     if (m_udp == NULL) {
00111         m_udp = new UDPSocket;
00112     }
00113     m_udp->init();
00114     m_udp->set_blocking(false);
00115     Endpoint server;
00116     server.set_address("8.8.8.8", 53); // DNS
00117     m_udp->bind(rand()&0x7fff);
00118     uint8_t buf[256];                
00119     int size = query(buf, sizeof(buf), hostname);
00120 #if DBG_DNS
00121     printf("hostname:[%s]\n", hostname);
00122     printHex(buf, size);
00123 #endif
00124     m_udp->sendTo(server, (char*)buf, size);
00125     m_interval.reset();
00126     m_interval.start();
00127 }
00128 
00129 void DNSClient::poll() {
00130 #if DBG_DNS
00131     printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
00132     wait_ms(400);
00133 #endif
00134     switch(m_state) {
00135         case MYNETDNS_START:
00136             m_retry = 0;
00137             resolve(m_hostname);
00138             m_state = MYNETDNS_PROCESSING;
00139             break;
00140         case MYNETDNS_PROCESSING: 
00141             break;
00142         case MYNETDNS_NOTFOUND: 
00143             break;
00144         case MYNETDNS_ERROR: 
00145             break;
00146         case MYNETDNS_OK:
00147             DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms());
00148             break;
00149     }
00150     if (m_interval.read_ms() > 1000) {
00151         m_interval.stop();
00152         DBG2("timeout m_retry=%d\n", m_retry);
00153         if (++m_retry >= 2) {
00154             m_state = MYNETDNS_ERROR;
00155         } else {
00156             resolve(m_hostname);
00157             m_state = MYNETDNS_PROCESSING;
00158         }
00159     }
00160 }
00161 
00162 bool DNSClient::lookup(const char* hostname) {
00163     m_hostname = hostname;
00164     m_state = MYNETDNS_START;
00165     while(1) {
00166         poll();
00167         callback();
00168         if (m_state != MYNETDNS_PROCESSING) {
00169             break;
00170         } 
00171     }
00172     return m_state == MYNETDNS_OK;
00173 }