Commit Iniziale, progetto funzionante caricato su box ETcontroller in
cantina
This commit is contained in:
174
WIZnetInterface/DNSClient/DNSClient.cpp
Normal file
174
WIZnetInterface/DNSClient/DNSClient.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
// DNSClient.cpp 2013/8/27
|
||||
#include "mbed.h"
|
||||
#include "mbed_debug.h"
|
||||
#include "DNSClient.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "dnsname.h"
|
||||
#include "wiznet.h"
|
||||
|
||||
#define DBG_DNS 0
|
||||
|
||||
#if DBG_DNS
|
||||
#define DBG2(...) do{debug("[DNS]%p %d %s ", this,__LINE__,__PRETTY_FUNCTION__); debug(__VA_ARGS__); } while(0);
|
||||
#else
|
||||
#define DBG2(...) while(0);
|
||||
#endif
|
||||
|
||||
DNSClient::DNSClient(const char* hostname) : m_state(MYNETDNS_START), m_udp(NULL) {
|
||||
m_hostname = hostname;
|
||||
}
|
||||
|
||||
DNSClient::DNSClient(Endpoint* pHost) : m_state(MYNETDNS_START), m_udp(NULL) {
|
||||
}
|
||||
|
||||
DNSClient::~DNSClient() {
|
||||
if (m_udp) {
|
||||
delete m_udp;
|
||||
}
|
||||
}
|
||||
|
||||
void DNSClient::callback()
|
||||
{
|
||||
uint8_t buf[512];
|
||||
Endpoint host;
|
||||
int len = m_udp->receiveFrom(host, (char*)buf, sizeof(buf));
|
||||
if (len < 0) {
|
||||
return;
|
||||
}
|
||||
if (memcmp(buf+0, m_id, 2) != 0) { //verify
|
||||
return;
|
||||
}
|
||||
int rcode = response(buf, len);
|
||||
if (rcode == 0) {
|
||||
m_state = MYNETDNS_OK;
|
||||
} else {
|
||||
m_state = MYNETDNS_NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
int DNSClient::response(uint8_t buf[], int size) {
|
||||
int rcode = buf[3] & 0x0f;
|
||||
if (rcode != 0) {
|
||||
return rcode;
|
||||
}
|
||||
int qdcount = buf[4]<<8|buf[5];
|
||||
int ancount = buf[6]<<8|buf[7];
|
||||
int pos = 12;
|
||||
while(qdcount-- > 0) {
|
||||
dnsname qname(buf);
|
||||
pos = qname.decode(pos); // qname
|
||||
pos += 4; // qtype qclass
|
||||
}
|
||||
while(ancount-- > 0) {
|
||||
dnsname name(buf);
|
||||
pos = name.decode(pos); // name
|
||||
int type = buf[pos]<<8|buf[pos+1];
|
||||
pos += 8; // type class TTL
|
||||
int rdlength = buf[pos]<<8|buf[pos+1]; pos += 2;
|
||||
int rdata_pos = pos;
|
||||
pos += rdlength;
|
||||
if (type == 1) { // A record
|
||||
ip = (buf[rdata_pos]<<24) | (buf[rdata_pos+1]<<16) | (buf[rdata_pos+2]<<8) | buf[rdata_pos+3];
|
||||
}
|
||||
#if DBG_DNS
|
||||
printf("%s", name.str.c_str());
|
||||
if (type == 1) {
|
||||
printf(" A %d.%d.%d.%d\n",
|
||||
buf[rdata_pos],buf[rdata_pos+1],buf[rdata_pos+2],buf[rdata_pos+3]);
|
||||
} else if (type == 5) {
|
||||
dnsname rdname(buf);
|
||||
rdname.decode(rdata_pos);
|
||||
printf(" CNAME %s\n", rdname.str.c_str());
|
||||
} else {
|
||||
printf(" TYPE:%d", type);
|
||||
printfBytes(" RDATA:", &buf[rdata_pos], rdlength);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
int DNSClient::query(uint8_t buf[], int size, const char* hostname) {
|
||||
const uint8_t header[] = {
|
||||
0x00,0x00,0x01,0x00, // id=0x0000 QR=0 rd=1 opcode=0 rcode=0
|
||||
0x00,0x01,0x00,0x00, // qdcount=1 ancount=0
|
||||
0x00,0x00,0x00,0x00};// nscount=0 arcount=0
|
||||
const uint8_t tail[] = {0x00,0x01,0x00,0x01}; // qtype=A qclass=IN
|
||||
memcpy(buf, header, sizeof(header));
|
||||
int t = rand();
|
||||
m_id[0] = t>>8;
|
||||
m_id[1] = t;
|
||||
memcpy(buf, m_id, 2);
|
||||
dnsname qname(buf);
|
||||
int pos = qname.encode(sizeof(header), (char*)hostname);
|
||||
memcpy(buf+pos, tail, sizeof(tail));
|
||||
pos += sizeof(tail);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void DNSClient::resolve(const char* hostname) {
|
||||
if (m_udp == NULL) {
|
||||
m_udp = new UDPSocket;
|
||||
}
|
||||
m_udp->init();
|
||||
m_udp->set_blocking(false);
|
||||
Endpoint server;
|
||||
server.set_address("8.8.8.8", 53); // DNS
|
||||
m_udp->bind(rand()&0x7fff);
|
||||
uint8_t buf[256];
|
||||
int size = query(buf, sizeof(buf), hostname);
|
||||
#if DBG_DNS
|
||||
printf("hostname:[%s]\n", hostname);
|
||||
printHex(buf, size);
|
||||
#endif
|
||||
m_udp->sendTo(server, (char*)buf, size);
|
||||
m_interval.reset();
|
||||
m_interval.start();
|
||||
}
|
||||
|
||||
void DNSClient::poll() {
|
||||
#if DBG_DNS
|
||||
printf("%p m_state: %d, m_udp: %p\n", this, m_state, m_udp);
|
||||
wait_ms(400);
|
||||
#endif
|
||||
switch(m_state) {
|
||||
case MYNETDNS_START:
|
||||
m_retry = 0;
|
||||
resolve(m_hostname);
|
||||
m_state = MYNETDNS_PROCESSING;
|
||||
break;
|
||||
case MYNETDNS_PROCESSING:
|
||||
break;
|
||||
case MYNETDNS_NOTFOUND:
|
||||
break;
|
||||
case MYNETDNS_ERROR:
|
||||
break;
|
||||
case MYNETDNS_OK:
|
||||
DBG2("m_retry=%d, m_interval=%d\n", m_retry, m_interval.read_ms());
|
||||
break;
|
||||
}
|
||||
if (m_interval.read_ms() > 1000) {
|
||||
m_interval.stop();
|
||||
DBG2("timeout m_retry=%d\n", m_retry);
|
||||
if (++m_retry >= 2) {
|
||||
m_state = MYNETDNS_ERROR;
|
||||
} else {
|
||||
resolve(m_hostname);
|
||||
m_state = MYNETDNS_PROCESSING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DNSClient::lookup(const char* hostname) {
|
||||
m_hostname = hostname;
|
||||
m_state = MYNETDNS_START;
|
||||
while(1) {
|
||||
poll();
|
||||
callback();
|
||||
if (m_state != MYNETDNS_PROCESSING) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return m_state == MYNETDNS_OK;
|
||||
}
|
||||
|
||||
35
WIZnetInterface/DNSClient/DNSClient.h
Normal file
35
WIZnetInterface/DNSClient/DNSClient.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// DNSClient.h 2013/4/5
|
||||
#pragma once
|
||||
|
||||
#include "UDPSocket.h"
|
||||
|
||||
class DNSClient {
|
||||
public:
|
||||
DNSClient(const char* hostname = NULL);
|
||||
DNSClient(Endpoint* pHost);
|
||||
virtual ~DNSClient();
|
||||
bool lookup(const char* hostname = NULL);
|
||||
uint32_t ip;
|
||||
protected:
|
||||
void poll();
|
||||
void callback();
|
||||
int response(uint8_t buf[], int size);
|
||||
int query(uint8_t buf[], int size, const char* hostname);
|
||||
void resolve(const char* hostname);
|
||||
uint8_t m_id[2];
|
||||
Timer m_interval;
|
||||
int m_retry;
|
||||
const char* m_hostname;
|
||||
private:
|
||||
enum MyNetDnsState
|
||||
{
|
||||
MYNETDNS_START,
|
||||
MYNETDNS_PROCESSING, //Req has not completed
|
||||
MYNETDNS_NOTFOUND,
|
||||
MYNETDNS_ERROR,
|
||||
MYNETDNS_OK
|
||||
};
|
||||
MyNetDnsState m_state;
|
||||
UDPSocket *m_udp;
|
||||
};
|
||||
|
||||
52
WIZnetInterface/DNSClient/dnsname.h
Normal file
52
WIZnetInterface/DNSClient/dnsname.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// dnsname.h 2013/8/27
|
||||
#pragma once
|
||||
//#include <string>
|
||||
#include "pico_string.h"
|
||||
class dnsname {
|
||||
public:
|
||||
uint8_t *buf;
|
||||
pico_string str;
|
||||
dnsname(uint8_t *s) {
|
||||
buf = s;
|
||||
}
|
||||
int decode(int pos) {
|
||||
while(1) {
|
||||
int len = buf[pos++];
|
||||
if (len == 0x00) {
|
||||
break;
|
||||
}
|
||||
if ((len&0xc0) == 0xc0) { //compress
|
||||
int offset = (len&0x3f)<<8|buf[pos];
|
||||
decode(offset);
|
||||
return pos+1;
|
||||
}
|
||||
if (!str.empty()) {
|
||||
str.append(".");
|
||||
}
|
||||
str.append((const char*)(buf+pos), len);
|
||||
pos += len;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
int encode(int pos, char* s) {
|
||||
while(*s) {
|
||||
char *f = strchr(s, '.');
|
||||
if (f == NULL) {
|
||||
int len = strlen(s);
|
||||
buf[pos++] = len;
|
||||
memcpy(buf+pos, s, len);
|
||||
pos += len;
|
||||
break;
|
||||
}
|
||||
int len = f - s;
|
||||
buf[pos++] = len;
|
||||
memcpy(buf+pos, s, len);
|
||||
s = f+1;
|
||||
pos += len;
|
||||
}
|
||||
buf[pos++] = 0x00;
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user