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 Sean Newton

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?

UserRevisionLine numberNew 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