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