Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of WIZnetInterface by
Socket/DNSClient.cpp@0:6f28332c466f, 2015-06-15 (annotated)
- Committer:
- Soohwan Kim
- Date:
- Mon Jun 15 11:18:37 2015 +0900
- Revision:
- 0:6f28332c466f
initial version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Soohwan Kim |
0:6f28332c466f | 1 | // DNSClient.cpp 2013/8/27 |
Soohwan Kim |
0:6f28332c466f | 2 | #include "mbed.h" |
Soohwan Kim |
0:6f28332c466f | 3 | #include "mbed_debug.h" |
Soohwan Kim |
0:6f28332c466f | 4 | #include "DNSClient.h" |
Soohwan Kim |
0:6f28332c466f | 5 | #include "UDPSocket.h" |
Soohwan Kim |
0:6f28332c466f | 6 | #include "dnsname.h" |
Soohwan Kim |
0:6f28332c466f | 7 | #include "eth_arch.h" |
Soohwan Kim |
0:6f28332c466f | 8 | |
Soohwan Kim |
0:6f28332c466f | 9 | #define DBG_DNS 0 |
Soohwan Kim |
0:6f28332c466f | 10 | |
Soohwan Kim |
0:6f28332c466f | 11 | #if DBG_DNS |
Soohwan Kim |
0:6f28332c466f | 12 | #define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0); |
Soohwan Kim |
0:6f28332c466f | 13 | #else |
Soohwan Kim |
0:6f28332c466f | 14 | #define DBG2(...) while(0); |
Soohwan Kim |
0:6f28332c466f | 15 | #endif |
Soohwan Kim |
0:6f28332c466f | 16 | |
Soohwan Kim |
0:6f28332c466f | 17 | DNSClient::DNSClient(const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) { |
Soohwan Kim |
0:6f28332c466f | 18 | m_hostname = hostname; |
Soohwan Kim |
0:6f28332c466f | 19 | } |
Soohwan Kim |
0:6f28332c466f | 20 | |
Soohwan Kim |
0:6f28332c466f | 21 | DNSClient::DNSClient(Endpoint* pHost) : m_state(MYNETDNS_START), m_udp(NULL) { |
Soohwan Kim |
0:6f28332c466f | 22 | } |
Soohwan Kim |
0:6f28332c466f | 23 | |
Soohwan Kim |
0:6f28332c466f | 24 | DNSClient::~DNSClient() { |
Soohwan Kim |
0:6f28332c466f | 25 | if (m_udp) { |
Soohwan Kim |
0:6f28332c466f | 26 | delete m_udp; |
Soohwan Kim |
0:6f28332c466f | 27 | } |
Soohwan Kim |
0:6f28332c466f | 28 | } |
Soohwan Kim |
0:6f28332c466f | 29 | |
Soohwan Kim |
0:6f28332c466f | 30 | void DNSClient::callback() |
Soohwan Kim |
0:6f28332c466f | 31 | { |
Soohwan Kim |
0:6f28332c466f | 32 | uint8_t buf[512]; |
Soohwan Kim |
0:6f28332c466f | 33 | Endpoint host; |
Soohwan Kim |
0:6f28332c466f | 34 | int len = m_udp->receiveFrom(host, (char*)buf, sizeof(buf)); |
Soohwan Kim |
0:6f28332c466f | 35 | if (len < 0) { |
Soohwan Kim |
0:6f28332c466f | 36 | return; |
Soohwan Kim |
0:6f28332c466f | 37 | } |
Soohwan Kim |
0:6f28332c466f | 38 | if (memcmp(buf+0, m_id, 2) != 0) { //verify |
Soohwan Kim |
0:6f28332c466f | 39 | return; |
Soohwan Kim |
0:6f28332c466f | 40 | } |
Soohwan Kim |
0:6f28332c466f | 41 | int rcode = response(buf, len); |
Soohwan Kim |
0:6f28332c466f | 42 | if (rcode == 0) { |
Soohwan Kim |
0:6f28332c466f | 43 | m_state = MYNETDNS_OK; |
Soohwan Kim |
0:6f28332c466f | 44 | } else { |
Soohwan Kim |
0:6f28332c466f | 45 | m_state = MYNETDNS_NOTFOUND; |
Soohwan Kim |
0:6f28332c466f | 46 | } |
Soohwan Kim |
0:6f28332c466f | 47 | } |
Soohwan Kim |
0:6f28332c466f | 48 | |
Soohwan Kim |
0:6f28332c466f | 49 | int DNSClient::response(uint8_t buf[], int size) { |
Soohwan Kim |
0:6f28332c466f | 50 | int rcode = buf[3] & 0x0f; |
Soohwan Kim |
0:6f28332c466f | 51 | if (rcode != 0) { |
Soohwan Kim |
0:6f28332c466f | 52 | return rcode; |
Soohwan Kim |
0:6f28332c466f | 53 | } |
Soohwan Kim |
0:6f28332c466f | 54 | int qdcount = buf[4]<<8|buf[5]; |
Soohwan Kim |
0:6f28332c466f | 55 | int ancount = buf[6]<<8|buf[7]; |
Soohwan Kim |
0:6f28332c466f | 56 | int pos = 12; |
Soohwan Kim |
0:6f28332c466f | 57 | while(qdcount-- > 0) { |
Soohwan Kim |
0:6f28332c466f | 58 | dnsname qname(buf); |
Soohwan Kim |
0:6f28332c466f | 59 | pos = qname.decode(pos); // qname |
Soohwan Kim |
0:6f28332c466f | 60 | pos += 4; // qtype qclass |
Soohwan Kim |
0:6f28332c466f | 61 | } |
Soohwan Kim |
0:6f28332c466f | 62 | while(ancount-- > 0) { |
Soohwan Kim |
0:6f28332c466f | 63 | dnsname name(buf); |
Soohwan Kim |
0:6f28332c466f | 64 | pos = name.decode(pos); // name |
Soohwan Kim |
0:6f28332c466f | 65 | int type = buf[pos]<<8|buf[pos+1]; |
Soohwan Kim |
0:6f28332c466f | 66 | pos += 8; // type class TTL |
Soohwan Kim |
0:6f28332c466f | 67 | int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2; |
Soohwan Kim |
0:6f28332c466f | 68 | int rdata_pos = pos; |
Soohwan Kim |
0:6f28332c466f | 69 | pos += rdlength; |
Soohwan Kim |
0:6f28332c466f | 70 | if (type == 1) { // A record |
Soohwan Kim |
0:6f28332c466f | 71 | ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3]; |
Soohwan Kim |
0:6f28332c466f | 72 | } |
Soohwan Kim |
0:6f28332c466f | 73 | #if DBG_DNS |
Soohwan Kim |
0:6f28332c466f | 74 | printf("%s", name.str.c_str()); |
Soohwan Kim |
0:6f28332c466f | 75 | if (type == 1) { |
Soohwan Kim |
0:6f28332c466f | 76 | printf(" A %d.%d.%d.%d\n", |
Soohwan Kim |
0:6f28332c466f | 77 | buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]); |
Soohwan Kim |
0:6f28332c466f | 78 | } else if (type == 5) { |
Soohwan Kim |
0:6f28332c466f | 79 | dnsname rdname(buf); |
Soohwan Kim |
0:6f28332c466f | 80 | rdname.decode(rdata_pos); |
Soohwan Kim |
0:6f28332c466f | 81 | printf(" CNAME %s\n", rdname.str.c_str()); |
Soohwan Kim |
0:6f28332c466f | 82 | } else { |
Soohwan Kim |
0:6f28332c466f | 83 | printf(" TYPE:%d", type); |
Soohwan Kim |
0:6f28332c466f | 84 | printfBytes(" RDATA:", &buf[rdata_pos], rdlength); |
Soohwan Kim |
0:6f28332c466f | 85 | } |
Soohwan Kim |
0:6f28332c466f | 86 | #endif |
Soohwan Kim |
0:6f28332c466f | 87 | } |
Soohwan Kim |
0:6f28332c466f | 88 | return rcode; |
Soohwan Kim |
0:6f28332c466f | 89 | } |
Soohwan Kim |
0:6f28332c466f | 90 | |
Soohwan Kim |
0:6f28332c466f | 91 | int DNSClient::query(uint8_t buf[], int size, const char* hostname) { |
Soohwan Kim |
0:6f28332c466f | 92 | const uint8_t header[] = { |
Soohwan Kim |
0:6f28332c466f | 93 | 0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0 |
Soohwan Kim |
0:6f28332c466f | 94 | 0x00,0x01,0x00,0x00, // qdcount=1 ancount=0 |
Soohwan Kim |
0:6f28332c466f | 95 | 0x00,0x00,0x00,0x00};// nscount=0 arcount=0 |
Soohwan Kim |
0:6f28332c466f | 96 | const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN |
Soohwan Kim |
0:6f28332c466f | 97 | memcpy(buf, header, sizeof(header)); |
Soohwan Kim |
0:6f28332c466f | 98 | int t = rand(); |
Soohwan Kim |
0:6f28332c466f | 99 | m_id[0] = t>>8; |
Soohwan Kim |
0:6f28332c466f | 100 | m_id[1] = t; |
Soohwan Kim |
0:6f28332c466f | 101 | memcpy(buf, m_id, 2); |
Soohwan Kim |
0:6f28332c466f | 102 | dnsname qname(buf); |
Soohwan Kim |
0:6f28332c466f | 103 | int pos = qname.encode(sizeof(header), (char*)hostname); |
Soohwan Kim |
0:6f28332c466f | 104 | memcpy(buf+pos, tail, sizeof(tail)); |
Soohwan Kim |
0:6f28332c466f | 105 | pos += sizeof(tail); |
Soohwan Kim |
0:6f28332c466f | 106 | return pos; |
Soohwan Kim |
0:6f28332c466f | 107 | } |
Soohwan Kim |
0:6f28332c466f | 108 | |
Soohwan Kim |
0:6f28332c466f | 109 | void DNSClient::resolve(const char* hostname) { |
Soohwan Kim |
0:6f28332c466f | 110 | if (m_udp == NULL) { |
Soohwan Kim |
0:6f28332c466f | 111 | m_udp = new UDPSocket; |
Soohwan Kim |
0:6f28332c466f | 112 | } |
Soohwan Kim |
0:6f28332c466f | 113 | m_udp->init(); |
Soohwan Kim |
0:6f28332c466f | 114 | m_udp->set_blocking(false); |
Soohwan Kim |
0:6f28332c466f | 115 | Endpoint server; |
Soohwan Kim |
0:6f28332c466f | 116 | server.set_address("8.8.8.8", 53); // DNS |
Soohwan Kim |
0:6f28332c466f | 117 | m_udp->bind(rand()&0x7fff); |
Soohwan Kim |
0:6f28332c466f | 118 | uint8_t buf[256]; |
Soohwan Kim |
0:6f28332c466f | 119 | int size = query(buf, sizeof(buf), hostname); |
Soohwan Kim |
0:6f28332c466f | 120 | #if DBG_DNS |
Soohwan Kim |
0:6f28332c466f | 121 | printf("hostname:[%s]\n", hostname); |
Soohwan Kim |
0:6f28332c466f | 122 | printHex(buf, size); |
Soohwan Kim |
0:6f28332c466f | 123 | #endif |
Soohwan Kim |
0:6f28332c466f | 124 | m_udp->sendTo(server, (char*)buf, size); |
Soohwan Kim |
0:6f28332c466f | 125 | m_interval.reset(); |
Soohwan Kim |
0:6f28332c466f | 126 | m_interval.start(); |
Soohwan Kim |
0:6f28332c466f | 127 | } |
Soohwan Kim |
0:6f28332c466f | 128 | |
Soohwan Kim |
0:6f28332c466f | 129 | void DNSClient::poll() { |
Soohwan Kim |
0:6f28332c466f | 130 | #if DBG_DNS |
Soohwan Kim |
0:6f28332c466f | 131 | printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp); |
Soohwan Kim |
0:6f28332c466f | 132 | wait_ms(400); |
Soohwan Kim |
0:6f28332c466f | 133 | #endif |
Soohwan Kim |
0:6f28332c466f | 134 | switch(m_state) { |
Soohwan Kim |
0:6f28332c466f | 135 | case MYNETDNS_START: |
Soohwan Kim |
0:6f28332c466f | 136 | m_retry = 0; |
Soohwan Kim |
0:6f28332c466f | 137 | resolve(m_hostname); |
Soohwan Kim |
0:6f28332c466f | 138 | m_state = MYNETDNS_PROCESSING; |
Soohwan Kim |
0:6f28332c466f | 139 | break; |
Soohwan Kim |
0:6f28332c466f | 140 | case MYNETDNS_PROCESSING: |
Soohwan Kim |
0:6f28332c466f | 141 | break; |
Soohwan Kim |
0:6f28332c466f | 142 | case MYNETDNS_NOTFOUND: |
Soohwan Kim |
0:6f28332c466f | 143 | break; |
Soohwan Kim |
0:6f28332c466f | 144 | case MYNETDNS_ERROR: |
Soohwan Kim |
0:6f28332c466f | 145 | break; |
Soohwan Kim |
0:6f28332c466f | 146 | case MYNETDNS_OK: |
Soohwan Kim |
0:6f28332c466f | 147 | DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms()); |
Soohwan Kim |
0:6f28332c466f | 148 | break; |
Soohwan Kim |
0:6f28332c466f | 149 | } |
Soohwan Kim |
0:6f28332c466f | 150 | if (m_interval.read_ms() > 1000) { |
Soohwan Kim |
0:6f28332c466f | 151 | m_interval.stop(); |
Soohwan Kim |
0:6f28332c466f | 152 | DBG2("timeout m_retry=%d\n", m_retry); |
Soohwan Kim |
0:6f28332c466f | 153 | if (++m_retry >= 2) { |
Soohwan Kim |
0:6f28332c466f | 154 | m_state = MYNETDNS_ERROR; |
Soohwan Kim |
0:6f28332c466f | 155 | } else { |
Soohwan Kim |
0:6f28332c466f | 156 | resolve(m_hostname); |
Soohwan Kim |
0:6f28332c466f | 157 | m_state = MYNETDNS_PROCESSING; |
Soohwan Kim |
0:6f28332c466f | 158 | } |
Soohwan Kim |
0:6f28332c466f | 159 | } |
Soohwan Kim |
0:6f28332c466f | 160 | } |
Soohwan Kim |
0:6f28332c466f | 161 | |
Soohwan Kim |
0:6f28332c466f | 162 | bool DNSClient::lookup(const char* hostname) { |
Soohwan Kim |
0:6f28332c466f | 163 | m_hostname = hostname; |
Soohwan Kim |
0:6f28332c466f | 164 | m_state = MYNETDNS_START; |
Soohwan Kim |
0:6f28332c466f | 165 | while(1) { |
Soohwan Kim |
0:6f28332c466f | 166 | poll(); |
Soohwan Kim |
0:6f28332c466f | 167 | callback(); |
Soohwan Kim |
0:6f28332c466f | 168 | if (m_state != MYNETDNS_PROCESSING) { |
Soohwan Kim |
0:6f28332c466f | 169 | break; |
Soohwan Kim |
0:6f28332c466f | 170 | } |
Soohwan Kim |
0:6f28332c466f | 171 | } |
Soohwan Kim |
0:6f28332c466f | 172 | return m_state == MYNETDNS_OK; |
Soohwan Kim |
0:6f28332c466f | 173 | } |
Soohwan Kim |
0:6f28332c466f | 174 |