W5200(WIZ820io) network interface

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MyNetDnsRequest.cpp Source File

MyNetDnsRequest.cpp

00001 // MyNetDnsRequest.cpp 2012/4/19
00002 #include "mbed.h"
00003 #include "MyNetDnsRequest.h"
00004 #include "UDPSocket.h"
00005 #include <string>
00006 #include "dnsname.h"
00007 #include "W5200NetIf.h"
00008 //#define __DEBUG
00009 #include "dbg/dbg.h"
00010 
00011 #ifdef __DEBUG
00012 #define DBG2(...) do{ DebugStream::debug("%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); DebugStream::debug(__VA_ARGS__); } while(0);
00013 #else
00014 #define DBG2(...) while(0);
00015 #endif //__DEBUG
00016 
00017 //#define DEBUG
00018 
00019 #ifdef DEBUG
00020 #include "Utils.h"
00021 #define PRINT_FUNC() printf("%p %d:%s\n", this,__LINE__,__PRETTY_FUNCTION__)
00022 #else //DEBUG
00023 #define PRINT_FUNC()
00024 #endif //DEBUG
00025 
00026 
00027 MyNetDnsRequest::MyNetDnsRequest(const char* hostname) : NetDnsRequest(hostname), 
00028     m_state(MYNETDNS_START), m_cbFired(false), m_closing(false), m_udp(NULL) {
00029     PRINT_FUNC();
00030 }
00031 
00032 MyNetDnsRequest::MyNetDnsRequest(Host* pHost) : NetDnsRequest(pHost), 
00033     m_state(MYNETDNS_START), m_cbFired(false), m_closing(false), m_udp(NULL) {
00034     PRINT_FUNC();
00035 }
00036 
00037 MyNetDnsRequest::~MyNetDnsRequest() {
00038     PRINT_FUNC();
00039     if (m_udp) {
00040         delete m_udp;
00041     }
00042 }
00043 
00044 void MyNetDnsRequest::callback(UDPSocketEvent e)
00045 {
00046     PRINT_FUNC();
00047     DBG2("m_id[]=%02x:%02x\n", m_id[0], m_id[1]);
00048     uint8_t buf[512];
00049     Host host;
00050     int len = m_udp->recvfrom((char*)buf, sizeof(buf), &host);
00051     if (memcmp(buf+0, m_id, 2) != 0) { //verify
00052         return;
00053     }
00054     int rcode = response(buf, len);
00055     if (rcode == 0) {
00056         m_state = MYNETDNS_OK;
00057     } else {
00058         m_state = MYNETDNS_NOTFOUND;
00059     }
00060 }
00061 
00062 int MyNetDnsRequest::response(uint8_t buf[], int size) {
00063     PRINT_FUNC();
00064 #ifdef DEBUG
00065     printHex(buf, size);
00066 #endif //DEBUG
00067     int rcode = buf[3] & 0x0f;
00068     if (rcode != 0) {
00069         return rcode;
00070     }
00071     int qdcount = buf[4]<<8|buf[5];
00072     int ancount = buf[6]<<8|buf[7];
00073     int pos = 12;
00074     while(qdcount-- > 0) {
00075         dnsname qname(buf);
00076         pos = qname.decode(pos); // qname
00077         pos += 4; // qtype qclass
00078     }
00079     while(ancount-- > 0) {
00080         dnsname name(buf);
00081         pos = name.decode(pos); // name
00082         int type = buf[pos]<<8|buf[pos+1];
00083         pos += 8; // type class TTL  
00084         int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2;
00085         int rdata_pos = pos;
00086         pos += rdlength;
00087         if (type == 1) { // A record
00088             m_ip = IpAddr(buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
00089         }
00090 #ifdef DEBUG
00091         printf("%s", name.str.c_str());
00092         if (type == 1) {
00093             printf(" A %d.%d.%d.%d\n", 
00094                 buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
00095         } else if (type == 5) {
00096             dnsname rdname(buf);
00097             rdname.decode(rdata_pos);
00098             printf(" CNAME %s\n", rdname.str.c_str());
00099         } else {
00100             printf(" TYPE:%d", type);
00101             printfBytes(" RDATA:", &buf[rdata_pos], rdlength);
00102         }
00103 #endif //DEBUG
00104     }
00105     return rcode;
00106 }
00107 
00108 int MyNetDnsRequest::query(uint8_t buf[], int size, const char* hostname) {
00109     PRINT_FUNC();
00110     const uint8_t header[] = {
00111         0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0
00112         0x00,0x01,0x00,0x00, // qdcount=1 ancount=0
00113         0x00,0x00,0x00,0x00};// nscount=0 arcount=0 
00114     const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN
00115     memcpy(buf, header, sizeof(header));
00116     int t = clock();
00117     m_id[0] = t>>8;
00118     m_id[1] = t;
00119     memcpy(buf, m_id, 2); 
00120     dnsname qname(buf);
00121     int pos = qname.encode(sizeof(header), (char*)hostname);
00122     memcpy(buf+pos, tail, sizeof(tail));
00123     pos += sizeof(tail);
00124     return pos;
00125 }
00126 
00127 void MyNetDnsRequest::resolve(const char* hostname) {
00128     PRINT_FUNC();
00129     if (m_udp == NULL) {
00130         m_udp = new UDPSocket;
00131     }
00132     m_udp->setOnEvent(this, &MyNetDnsRequest::callback);
00133     Host local(IpAddr(0,0,0,0), 1024 + rand()&0x7fff);
00134     IpAddr dns(8,8,8,8);
00135     NetIf* pIf = Net::getDefaultIf();
00136     if (pIf) {
00137         dns = ((W5200NetIf*)pIf)->m_dns;
00138     }
00139     Host server(dns, 53); // DNS
00140     m_udp->bind(local);
00141     uint8_t buf[256];                
00142     int size = query(buf, sizeof(buf), hostname);
00143 #ifdef DEBUG
00144     printf("hostname:[%s]\n", hostname);
00145     printHex(buf, size);
00146 #endif
00147     m_udp->sendto((char*)buf, size, &server);
00148     m_interval.reset();
00149     m_interval.start();
00150 }
00151 
00152 void MyNetDnsRequest::poll() {
00153     PRINT_FUNC();
00154 #ifdef DEBUG
00155     printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
00156     wait_ms(400);
00157 #endif //DEBUG
00158     switch(m_state) {
00159         case MYNETDNS_START:
00160             m_retry = 0;
00161             resolve(m_hostname);
00162             m_state = MYNETDNS_PROCESSING;
00163             break;
00164         case MYNETDNS_PROCESSING: 
00165             break;
00166         case MYNETDNS_NOTFOUND: 
00167             onReply(NETDNS_FOUND); 
00168             break;
00169         case MYNETDNS_ERROR: 
00170             onReply(NETDNS_ERROR);
00171             break;
00172         case MYNETDNS_OK:
00173             DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms());
00174             onReply(NETDNS_FOUND); 
00175             break;
00176     }
00177     if (m_interval.read_ms() > 1000) {
00178         m_interval.stop();
00179         DBG2("timeout m_retry=%d\n", m_retry);
00180         if (++m_retry > 1) {
00181             m_state = MYNETDNS_ERROR;
00182         } else {
00183             resolve(m_hostname);
00184             m_state = MYNETDNS_PROCESSING;
00185         }
00186     }
00187     if(m_closing && (m_state!=MYNETDNS_PROCESSING)) {
00188         NetDnsRequest::close();
00189     }
00190 }
00191 
00192 void MyNetDnsRequest::close() {
00193     PRINT_FUNC();
00194     if(m_state != MYNETDNS_PROCESSING) {
00195         NetDnsRequest::close();
00196     } else {
00197         m_closing = true;
00198     }
00199 }