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.
Revision 1:4218cacaf696, committed 2010-06-18
- Comitter:
- darran
- Date:
- Fri Jun 18 15:54:21 2010 +0000
- Parent:
- 0:55a05330f8cc
- Commit message:
Changed in this revision
--- a/api/DNSRequest.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/api/DNSRequest.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -75,7 +75,7 @@
m_pCb = pMethod;
}
-#ifdef __LINKER_BUG_SOLVED__
+#if 0 //For doc only
template<class T>
void DNSRequest::setOnReply( T* pItem, void (T::*pMethod)(DNSReply) )
{
--- a/api/TCPSocket.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/api/TCPSocket.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -23,12 +23,12 @@
#include "TCPSocket.h"
-TCPSocket::TCPSocket() : m_pNetTcpSocket(NULL)
+TCPSocket::TCPSocket() : m_pNetTcpSocket(NULL), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL)
{
}
-TCPSocket::TCPSocket(NetTcpSocket* pNetTcpSocket) : m_pNetTcpSocket(pNetTcpSocket)
+TCPSocket::TCPSocket(NetTcpSocket* pNetTcpSocket) : m_pNetTcpSocket(pNetTcpSocket), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL)
{
m_pNetTcpSocket->setOnEvent(this, &TCPSocket::onNetTcpSocketEvent);
}
--- a/api/UDPSocket.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/api/UDPSocket.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -23,7 +23,7 @@
#include "UDPSocket.h"
-UDPSocket::UDPSocket() : m_pNetUdpSocket(NULL)
+UDPSocket::UDPSocket() : m_pNetUdpSocket(NULL), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL)
{
}
--- a/dbg/dbg.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/dbg/dbg.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -54,6 +54,14 @@
//fclose(m_fp);
}
+void DebugStream::breakPoint(const char* file, int line)
+{
+ printf("\r\nBREAK in %s at line %d\r\n", file, line);
+ fflush(stdout);
+ getchar();
+ fflush(stdin);
+}
+
/*
int snprintf(char *str, int size, const char *format, ...)
{
--- a/dbg/dbg.h Fri Jun 18 09:11:35 2010 +0000 +++ b/dbg/dbg.h Fri Jun 18 15:54:21 2010 +0000 @@ -39,21 +39,26 @@ public: static void debug(const char* format, ...); static void release(); +static void breakPoint(const char* file, int line); private: }; #undef DBG #undef DBG_END +#undef BREAK #define DBG DebugStream::debug #define DBG_END DebugStream::release +#define BREAK() DebugStream::breakPoint(__FILE__, __LINE__) #endif #else #undef DBG #undef DBG_END +#undef BREAK #define DBG(...) #define DBG_END() +#define BREAK() #endif #ifdef __LWIP_DEBUG
--- a/drv/gprs/GPRSModem.cpp Fri Jun 18 09:11:35 2010 +0000 +++ b/drv/gprs/GPRSModem.cpp Fri Jun 18 15:54:21 2010 +0000 @@ -24,7 +24,7 @@ #include "GPRSModem.h" #include "mbed.h" -#define __DEBUG +//#define __DEBUG #include "dbg/dbg.h" #define WAIT_BTW_NETW_POLLS 3.
--- a/drv/serial/usb/usbserialif.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/drv/serial/usb/usbserialif.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -35,9 +35,15 @@
UsbEndpoint* pEpIn;
UsbEndpoint* pEpOut;
-USB_INT08U ser_int_found;
+#define DONGLE_STATE_UNKNOWN 0
+#define DONGLE_STATE_CDFS 1
+#define DONGLE_STATE_SERIAL 2
+
+USB_INT08U dongleState;
+
USB_INT32S SerialInit()
{
+ dongleState = DONGLE_STATE_UNKNOWN;
Host_Init(); // Initialize the host controller
USB_INT32S rc = Host_EnumDev(); // Enumerate the device connected
if (rc != OK)
@@ -50,7 +56,7 @@
bool SerialHasToSwitch()
{
- return (ser_int_found == 3);
+ return (dongleState == DONGLE_STATE_CDFS);
}
uint16_t m_vid;
@@ -61,7 +67,7 @@
bool scsi = false;
//Size 31
const unsigned char magicHuawei[] = { 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 0, 0, 0, 0, 0, 0, 0, 0x11, 0x6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- const unsigned char magicVoda[] = { 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12, 0x01, 0, 0, 0, 0x80, 0, 0x06, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ const unsigned char magicVoda[] = { 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12, 0x01, 0, 0, 0, 0x80, 0, 0x06, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
char* magic;
USB_INT32S rc;
if((m_vid == 0x12d1) && (m_pid == 0x1446))
@@ -86,20 +92,15 @@
return -1;
}
-
if(scsi)
{
- //rc = Host_ProcessTD(EDBulkOut, TD_OUT, (volatile USB_INT08U*)magic, 31);
rc = pEpOut->transfer((volatile USB_INT08U*)magic, 31);
while(rc == PROCESSING)
{
- // __WFI();
rc = pEpOut->status();
- }
-
+ }
}
-
-
+
delete pEpOut;
pEpOut = NULL;
return rc;
@@ -125,25 +126,25 @@
m_pid == 0x1446 )
{
PRINT_Log("\r\nHuawei device found in CDFS mode\r\n");
- ser_int_found=3;
+ dongleState = DONGLE_STATE_CDFS;
}
else if( m_vid == 0x12d1 &&//Huawei : Change
m_pid == 0x1001 )
{
PRINT_Log("\r\nHuawei device found in Serial mode\r\n");
- ser_int_found=1;
+ dongleState = DONGLE_STATE_SERIAL;
}
else if( m_vid == 0x0af0 &&//Voda?Qualcomm? : Change
m_pid == 0x7501 )
{
PRINT_Log("\r\nVodafone K3760 found, checking mode...\r\n");
- ser_int_found=3;
+ dongleState = DONGLE_STATE_UNKNOWN;
}
else if( m_vid == 0x12d1 &&//Voda?Qualcomm? : Change
m_pid == 0x1003 )
{
PRINT_Log("\r\nHuawei device found, checking mode...\r\n");
- ser_int_found=3;
+ dongleState = DONGLE_STATE_UNKNOWN;
}
else
{
@@ -176,8 +177,13 @@
if (desc_ptr[5] == 0xFF &&
desc_ptr[6] == 0xFF &&
desc_ptr[7] == 0xFF ) {
- //if(ser_int_found==1)
- ser_int_found=2;
+ dongleState = DONGLE_STATE_SERIAL;
+ }
+ else
+ if (desc_ptr[5] == 0xFF &&
+ desc_ptr[6] == 0xFF &&
+ desc_ptr[7] == 0xFF ) {
+ dongleState = DONGLE_STATE_CDFS;
}
desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
break;
@@ -186,51 +192,13 @@
PRINT_Log("\r\nEp %02x of size %d.\r\n", desc_ptr[2], (ReadLE16U(&desc_ptr[4]) ));
if ( SerialHasToSwitch() )
{
- if( pEpOut == NULL /*desc_ptr[2] == 1*/) //EP 1
+ if( (dongleState == DONGLE_STATE_CDFS) && (pEpOut == NULL) /*desc_ptr[2] == 1*/) //EP 1
{
- #if 0
- EDBulkOut->Control = 1 | /* USB address */
- ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */
- (1 << 11) | /* direction */
- (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */
- #endif
pEpOut = new UsbEndpoint((desc_ptr[2] & 0x7F), false, ReadLE16U(&desc_ptr[4]));
}
- desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
+ /* Move to next descriptor start */
}
- else if ((desc_ptr[3] & 0x03) == 0x02) { /* If it is Bulk endpoint */
- if (desc_ptr[2] & 0x80) { /* If it is In endpoint */
- if(epIn == 0)
- {
- PRINT_Log("\r\nEp %02x is in ep.\r\n", desc_ptr[2]);
- #if 0
- EDBulkIn->Control = 1 | /* USB address */
- ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */
- (2 << 11) | /* direction */
- (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */
- #endif
- // pEpIn = new UsbEndpoint((desc_ptr[2] & 0x7F), true, ReadLE16U(&desc_ptr[4]));
- }
- epIn++;
- desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
- } else { /* If it is Out endpoint */
- if(epOut == 0)
- {
- PRINT_Log("\r\nEp %02x is out ep.\r\n", desc_ptr[2]);
- #if 0
- EDBulkOut->Control = 1 | /* USB address */
- ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */
- (1 << 11) | /* direction */
- (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */
- #endif
- // pEpOut = new UsbEndpoint((desc_ptr[2] & 0x7F), false, ReadLE16U(&desc_ptr[4]));
- }
- epOut++;
- desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
- }
- } else { /* If it is not bulk end point */
- desc_ptr += desc_ptr[0]; /* Move to next descriptor start */
- }
+ desc_ptr += desc_ptr[0];
break;
default: /* If the descriptor is neither interface nor endpoint */
@@ -238,8 +206,8 @@
break;
}
}
- if (ser_int_found==2) {
- PRINT_Log("Virtual Serial Port device %04x:%04x connected, vid=%d, pid=%d, E220=%d\n", m_vid, m_pid, ( m_vid == 0x12d1 ), ( m_pid == 0x1003 ), (( m_vid == 0x12d1 ) && ( m_pid == 0x1003 )));
+ if (dongleState == DONGLE_STATE_SERIAL) {
+ PRINT_Log("Virtual Serial Port device %04x:%04x connected, vid=%d, pid=%d\n", m_vid, m_pid);
if(m_vid==0x0af0) //Voda
{
pEpOut = new UsbEndpoint((0x0a & 0x7F), false, 64);
@@ -254,21 +222,6 @@
pEpIn = new UsbEndpoint((0x82 & 0x7F), true, 64);
PRINT_Log("Huawei E220\r\n");
}
- /*else
- {
- if(( m_vid == 0x12d1 ))
- PRINT_Log("VID OK\r\n");
- else
- PRINT_Log("VID NOK\r\n");
- if(( m_pid == 0x1003 ))
- PRINT_Log("VID OK\r\n");
- else
- PRINT_Log("VID NOK\r\n");
- PRINT_Log("\r\n....\r\n\r\n");
- error("\r\n\r\n");
- }*/
- //}
- #if 1
else /*if ( m_vid == 0x12d1 &&
m_pid == 0x1001 )*/
{
@@ -276,12 +229,11 @@
pEpIn = new UsbEndpoint((0x82 & 0x7F), true, 64);
PRINT_Log("Huawei E1550\r\n");
}
- #endif
PRINT_Log("Virtual Serial Port device %04x:%04x connected\n", m_vid, m_pid);
return (OK);
}
- else if (ser_int_found==3) {
+ else if (dongleState == DONGLE_STATE_CDFS) {
PRINT_Log("CDFS dongle connected, reset\n");
return (OK);
} else {
--- a/if/eth/EthernetNetIf.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/eth/EthernetNetIf.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -25,6 +25,7 @@
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "lwip/dns.h"
+#include "ipv4/lwip/autoip.h"
#include "drv/eth/eth_drv.h"
#include "mbed.h"
@@ -34,7 +35,7 @@
#include "netCfg.h"
#if NET_ETH
-EthernetNetIf::EthernetNetIf() : LwipNetIf(), m_ethArpTicker(), m_dhcpCoarseTicker(), m_dhcpFineTicker(), m_pNetIf(NULL),
+EthernetNetIf::EthernetNetIf() : LwipNetIf(), m_ethArpTimer(), m_dhcpCoarseTimer(), m_dhcpFineTimer(), m_autoIpTimer(), m_pNetIf(NULL),
m_netmask(255,255,255,255), m_gateway(), m_hostname(NULL)
{
m_hostname = NULL;
@@ -42,7 +43,7 @@
m_useDhcp = true;
}
-EthernetNetIf::EthernetNetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns) : LwipNetIf(), m_ethArpTicker(), m_dhcpCoarseTicker(), m_dhcpFineTicker(), m_pNetIf(NULL), m_hostname(NULL) //W/o DHCP
+EthernetNetIf::EthernetNetIf(IpAddr ip, IpAddr netmask, IpAddr gateway, IpAddr dns) : LwipNetIf(), m_ethArpTimer(), m_dhcpCoarseTimer(), m_dhcpFineTimer(), m_autoIpTimer(), m_pNetIf(NULL), m_hostname(NULL) //W/o DHCP
{
m_hostname = NULL;
m_netmask = netmask;
@@ -67,11 +68,15 @@
EthernetErr EthernetNetIf::setup(int timeout_ms /*= 15000*/)
{
LwipNetIf::init();
- m_ethArpTicker.attach_us(ðarp_tmr, ARP_TMR_INTERVAL * 1000); // = 5s in etharp.h
+ //m_ethArpTicker.attach_us(ðarp_tmr, ARP_TMR_INTERVAL * 1000); // = 5s in etharp.h
+ m_ethArpTimer.start();
if(m_useDhcp)
{
- m_dhcpCoarseTicker.attach(&dhcp_coarse_tmr, DHCP_COARSE_TIMER_SECS); // = 60s in dhcp.h
- m_dhcpFineTicker.attach_us(&dhcp_fine_tmr, DHCP_FINE_TIMER_MSECS * 1000); // = 500ms in dhcp.h
+ //m_dhcpCoarseTicker.attach(&dhcp_coarse_tmr, DHCP_COARSE_TIMER_SECS); // = 60s in dhcp.h
+ //m_dhcpFineTicker.attach_us(&dhcp_fine_tmr, DHCP_FINE_TIMER_MSECS * 1000); // = 500ms in dhcp.h
+ m_dhcpCoarseTimer.start();
+ m_dhcpFineTimer.start();
+ m_autoIpTimer.start();
}
m_pNetIf->hwaddr_len = ETHARP_HWADDR_LEN; //6
eth_address((char *)m_pNetIf->hwaddr);
@@ -79,8 +84,7 @@
DBG("\r\nHW Addr is : %02x:%02x:%02x:%02x:%02x:%02x.\r\n",
m_pNetIf->hwaddr[0], m_pNetIf->hwaddr[1], m_pNetIf->hwaddr[2],
m_pNetIf->hwaddr[3], m_pNetIf->hwaddr[4], m_pNetIf->hwaddr[5]);
- DBG("\r\nIn Setup.\r\n");
-
+
m_pNetIf = netif_add(m_pNetIf, &(m_ip.getStruct()), &(m_netmask.getStruct()), &(m_gateway.getStruct()), NULL, eth_init, ip_input);//ethernet_input);// ip_input);
//m_pNetIf->hostname = "mbedDG";//(char *)m_hostname; //Not used for now
netif_set_default(m_pNetIf);
@@ -101,6 +105,24 @@
timeout.start();
while( !netif_is_up(m_pNetIf) ) //Wait until device is up
{
+ if(m_useDhcp)
+ {
+ if(m_dhcpFineTimer.read_ms()>=DHCP_FINE_TIMER_MSECS)
+ {
+ m_dhcpFineTimer.reset();
+ dhcp_fine_tmr();
+ }
+ if(m_dhcpCoarseTimer.read()>=DHCP_COARSE_TIMER_SECS)
+ {
+ m_dhcpCoarseTimer.reset();
+ dhcp_coarse_tmr();
+ }
+ if(m_autoIpTimer.read_ms()>=AUTOIP_TMR_INTERVAL)
+ {
+ m_autoIpTimer.reset();
+ autoip_tmr();
+ }
+ }
poll();
if( timeout.read_ms() > timeout_ms )
{
@@ -123,6 +145,11 @@
void EthernetNetIf::poll()
{
+ if(m_ethArpTimer.read_ms()>=ARP_TMR_INTERVAL)
+ {
+ m_ethArpTimer.reset();
+ etharp_tmr();
+ }
LwipNetIf::poll();
eth_poll();
}
--- a/if/eth/EthernetNetIf.h Fri Jun 18 09:11:35 2010 +0000
+++ b/if/eth/EthernetNetIf.h Fri Jun 18 15:54:21 2010 +0000
@@ -26,7 +26,6 @@
struct netif;
-//class Ticker;
#include "mbed.h"
#include "if/net/net.h"
@@ -51,9 +50,10 @@
virtual void poll();
private:
- Ticker m_ethArpTicker;
- Ticker m_dhcpCoarseTicker;
- Ticker m_dhcpFineTicker;
+ Timer m_ethArpTimer;
+ Timer m_dhcpCoarseTimer;
+ Timer m_dhcpFineTimer;
+ Timer m_autoIpTimer;
bool m_useDhcp;
--- a/if/lwip/LwipNetIf.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/lwip/LwipNetIf.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -31,7 +31,7 @@
//See doc/rawapi.txt for details
-LwipNetIf::LwipNetIf() : NetIf(), m_tcpTicker(), m_dnsTicker(), m_init(false)
+LwipNetIf::LwipNetIf() : NetIf(), m_tcpTimer(), m_dnsTimer(), m_init(false)
{
}
@@ -39,8 +39,7 @@
LwipNetIf::~LwipNetIf()
{
- m_tcpTicker.detach();
- m_dnsTicker.detach();
+
}
void LwipNetIf::init()
@@ -51,8 +50,10 @@
lwip_init(); //init lwip, see init.c for details
//Setup Clocks
- m_tcpTicker.attach_us( tcp_tmr, TCP_TMR_INTERVAL * 1000 ); //TCP_TMR_INTERVAL = 250 ms in tcp_impl.h
- m_dnsTicker.attach_us( dns_tmr, DNS_TMR_INTERVAL * 1000 ); //DNS_TMR_INTERVAL = 1000 ms in dns.h
+ m_tcpTimer.start();
+ m_dnsTimer.start();
+ //m_tcpTicker.attach_us( tcp_tmr, TCP_TMR_INTERVAL * 1000 ); //TCP_TMR_INTERVAL = 250 ms in tcp_impl.h
+ //m_dnsTicker.attach_us( dns_tmr, DNS_TMR_INTERVAL * 1000 ); //DNS_TMR_INTERVAL = 1000 ms in dns.h
}
NetTcpSocket* LwipNetIf::tcpSocket() //Create a new tcp socket
@@ -77,6 +78,16 @@
void LwipNetIf::poll()
{
+ if(m_init && m_tcpTimer.read_ms() >= TCP_TMR_INTERVAL)
+ {
+ m_tcpTimer.reset();
+ tcp_tmr(); //Poll LwIP
+ }
+ if(m_init && m_dnsTimer.read_ms() >= DNS_TMR_INTERVAL)
+ {
+ m_dnsTimer.reset();
+ dns_tmr();
+ }
//Do some stuff...
}
--- a/if/lwip/LwipNetIf.h Fri Jun 18 09:11:35 2010 +0000 +++ b/if/lwip/LwipNetIf.h Fri Jun 18 15:54:21 2010 +0000 @@ -49,8 +49,8 @@ virtual void poll(); private: - Ticker m_tcpTicker; - Ticker m_dnsTicker; + Timer m_tcpTimer; + Timer m_dnsTimer; bool m_init;
--- a/if/lwip/lwipNetDnsRequest.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/lwip/lwipNetDnsRequest.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -31,12 +31,12 @@
//#define __DEBUG
#include "dbg/dbg.h"
-LwipNetDnsRequest::LwipNetDnsRequest(const char* hostname) : NetDnsRequest(hostname), m_state(LWIPNETDNS_START), m_cbFired(false)
+LwipNetDnsRequest::LwipNetDnsRequest(const char* hostname) : NetDnsRequest(hostname), m_state(LWIPNETDNS_START), m_cbFired(false), m_closing(false)
{
DBG("New LwipNetDnsRequest %p\n", this);
}
-LwipNetDnsRequest::LwipNetDnsRequest(Host* pHost) : NetDnsRequest(pHost), m_state(LWIPNETDNS_START), m_cbFired(false)
+LwipNetDnsRequest::LwipNetDnsRequest(Host* pHost) : NetDnsRequest(pHost), m_state(LWIPNETDNS_START), m_cbFired(false), m_closing(false)
{
DBG("New LwipNetDnsRequest %p\n", this);
}
@@ -106,16 +106,36 @@
}
break;
}
-// return m_state;
+ if(m_closing && (m_state!=LWIPNETDNS_PROCESSING)) //Check wether the closure has been reqd
+ {
+ DBG("LwipNetDnsRequest: Closing in poll()\n");
+ NetDnsRequest::close();
+ }
+}
+
+void LwipNetDnsRequest::close()
+{
+ DBG("LwipNetDnsRequest: Close req\n");
+ if(m_state!=LWIPNETDNS_PROCESSING)
+ {
+ DBG("LwipNetDnsRequest: Closing in close()\n");
+ NetDnsRequest::close();
+ }
+ else //Cannot close rightaway, waiting for callback from underlying layer
+ {
+ m_closing = true;
+ }
}
void LwipNetDnsRequest::foundCb(const char *name, ip_addr_t *ipaddr)
{
if( ipaddr == NULL )
{
+ DBG("LwipNetDnsRequest: Callback: Name not found\n");
m_state = LWIPNETDNS_NOTFOUND;
return;
}
+ DBG("LwipNetDnsRequest: Callback: Resolved\n");
m_ip = IpAddr(ipaddr);
m_state = LWIPNETDNS_OK;
}
@@ -123,6 +143,7 @@
void LwipNetDnsRequest::sFoundCb(const char *name, ip_addr_t *ipaddr, void *arg)
{
+ DBG("LwipNetDnsRequest: Static callback\n");
LwipNetDnsRequest* pMe = (LwipNetDnsRequest*) arg;
return pMe->foundCb( name, ipaddr );
}
--- a/if/lwip/lwipNetDnsRequest.h Fri Jun 18 09:11:35 2010 +0000 +++ b/if/lwip/lwipNetDnsRequest.h Fri Jun 18 15:54:21 2010 +0000 @@ -39,6 +39,8 @@ //Execute request & return OK if found, NOTFOUND or ERROR on error, or PROCESSING if the request has not completed yet virtual void poll(); + + virtual void close(); protected: void foundCb(const char *name, ip_addr_t *ipaddr); @@ -58,6 +60,8 @@ //Static callbacks : Transforms into a C++ callback static void sFoundCb(const char *name, ip_addr_t *ipaddr, void *arg); + + bool m_closing; }; #endif
--- a/if/lwip/lwipNetTcpSocket.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/lwip/lwipNetTcpSocket.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -30,7 +30,7 @@
#include "netCfg.h"
#if NET_LWIP_STACK
-LwipNetTcpSocket::LwipNetTcpSocket(tcp_pcb* pPcb /*= NULL*/) : m_pPcb(pPcb), m_lpInNetTcpSocket(), //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
+LwipNetTcpSocket::LwipNetTcpSocket(tcp_pcb* pPcb /*= NULL*/) : NetTcpSocket(), m_pPcb(pPcb), m_lpInNetTcpSocket(), //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
m_pReadPbuf(NULL)
{
DBG("\r\nNew NetTcpSocket %p\r\n", (void*)this);
@@ -163,8 +163,8 @@
return NETTCPSOCKET_OK;
}
-#define MAX(a,b) ((a>b)?a:b)
-#define MIN(a,b) ((a<b)?a:b)
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define MIN(a,b) (((a)<(b))?(a):(b))
int /*if < 0 : NetTcpSocketErr*/ LwipNetTcpSocket::send(const char* buf, int len)
{
--- a/if/lwip/lwipNetUdpSocket.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/lwip/lwipNetUdpSocket.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -30,16 +30,16 @@
#include "netCfg.h"
#if NET_LWIP_STACK
-LwipNetUdpSocket::LwipNetUdpSocket(udp_pcb* pPcb /*= NULL*/) : m_pPcb(pPcb), m_lInPkt() //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
+LwipNetUdpSocket::LwipNetUdpSocket(udp_pcb* pPcb /*= NULL*/) : NetUdpSocket(), m_pPcb(pPcb), m_lInPkt() //Passes a pcb if already created (by an accept req for instance), in that case transfers ownership
{
- DBG("\r\nNew NetUdpSocket %p\r\n", (void*)this);
+ DBG("\r\nNew LwipNetUdpSocket %p (pPCb=%p)\r\n", (void*)this, (void*) pPcb);
if(!m_pPcb)
m_pPcb = udp_new();
- /* if(m_pPcb)
+ if(m_pPcb)
{
//Setup callback
- // udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );
- }*/
+ udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );
+ }
}
LwipNetUdpSocket::~LwipNetUdpSocket()
@@ -51,11 +51,11 @@
{
if(!m_pPcb)
return NETUDPSOCKET_MEM; //NetUdpSocket was not properly initialised, should destroy it & retry
-
+
err_t err = udp_bind( (udp_pcb*) m_pPcb, IP_ADDR_ANY, me.getPort()); //IP_ADDR_ANY : Bind the connection to all local addresses
if(err)
return NETUDPSOCKET_INUSE;
-
+
//Setup callback
udp_recv( (udp_pcb*) m_pPcb, LwipNetUdpSocket::sRecvCb, (void*) this );
@@ -69,12 +69,18 @@
{
if( !m_pPcb ) //Pcb doesn't exist (anymore)
return NETUDPSOCKET_MEM;
- pbuf* p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
+ pbuf* p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_POOL);
if( !p )
return NETUDPSOCKET_MEM;
- memcpy (p->payload, (void*)buf, len);
- //udp_connect( (udp_pcb*) m_pPcb, &(pHost->getIp().getStruct()), pHost->getPort() );
- //err_t err = udp_send( (udp_pcb*) m_pPcb, p);
+ char* pBuf = (char*) buf;
+ pbuf* q = p;
+ do
+ {
+ memcpy (q->payload, (void*)pBuf, q->len);
+ pBuf += q->len;
+ q = q->next;
+ } while(q != NULL);
+
err_t err = udp_sendto( (udp_pcb*) m_pPcb, p, &(pHost->getIp().getStruct()), pHost->getPort() );
pbuf_free( p );
if(err)
@@ -151,7 +157,7 @@
NetUdpSocketErr LwipNetUdpSocket::close()
{
- //DBG("\r\nLwipNetUdpSocket::close() : Closing...\r\n");
+ DBG("\r\nLwipNetUdpSocket::close() : Closing...\r\n");
if(m_closed)
return NETUDPSOCKET_OK; //Already being closed
@@ -160,11 +166,14 @@
if( !m_pPcb ) //Pcb doesn't exist (anymore)
return NETUDPSOCKET_MEM;
+ DBG("\r\nLwipNetUdpSocket::close() : Cleanup...\r\n");
+
//Cleanup incoming data
cleanUp();
+ DBG("\r\nLwipNetUdpSocket::close() : removing m_pPcb...\r\n");
udp_remove( (udp_pcb*) m_pPcb);
-
+
m_pPcb = NULL;
return NETUDPSOCKET_OK;
}
@@ -186,7 +195,7 @@
if( ip_addr_cmp((&((*it).addr)), addr) && ((*it).port == port) )
{
//Let's tail this packet to the previous one
- pbuf_cat((pbuf*)(*it).pBuf, p);
+ pbuf_cat((pbuf*)((*it).pBuf), p);
//No need to queue an event in that case since the read buf has not been processed yet
return;
}
@@ -204,13 +213,18 @@
void LwipNetUdpSocket::cleanUp() //Flush input buffer
{
+ //Ensure that further error won't be followed to this inst (which can be destroyed)
+ if( m_pPcb )
+ {
+ udp_recv( (udp_pcb*) m_pPcb, NULL, (void*) NULL );
+ }
+
list<InPacket>::iterator it;
for ( it = m_lInPkt.begin(); it != m_lInPkt.end(); it++ )
{
//Free buf
- pbuf_free((pbuf*)(*it).pBuf);
+ pbuf_free((pbuf*)((*it).pBuf));
}
- recvfrom(NULL, 0, NULL);
m_lInPkt.clear();
}
--- a/if/net/net.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/net/net.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -39,9 +39,12 @@
void Net::poll()
{
+ //DBG("\r\nNet : Services polling\r\n");
//Poll Services
- NetService::servicesPoll();
+ NetService::servicesPoll();
+
+ //DBG("\r\nNet : Interfaces polling\r\n");
//Poll Interfaces
list<NetIf*>::iterator pIfIt;
@@ -51,6 +54,8 @@
(*pIfIt)->poll();
}
+ //DBG("\r\nNet : Sockets polling\r\n");
+
//Poll Tcp Sockets
list<NetTcpSocket*>::iterator pNetTcpSocketIt;
--- a/if/net/netservice.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/net/netservice.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -54,19 +54,21 @@
void NetService::servicesPoll() //Poll all registered services & destroy closed ones
{
list<NetService*>::iterator it;
-
+ DBG("\r\nServices polling over %d services\r\n", lpServices().size());
for( it = lpServices().begin(); it != lpServices().end(); )
{
if( (*it)->m_owned && (*it)->m_closed )
{
- DBG("\r\nService %p is flagged as closed\r\n", &(*it));
+ DBG("\r\nService %p is flagged as closed\r\n", (*it));
(*it)->m_removed = true;
delete (*it);
it = lpServices().erase(it);
}
else
{
+ //DBG("Service %p polling start\n", (*it));
(*it)->poll();
+ //DBG("Service %p polling end\n", (*it));
it++;
}
}
@@ -75,7 +77,7 @@
void NetService::close()
{
- DBG("\r\nService %p to be closed\r\n", this);
+ DBG("\r\nService %p to be closed (owned = %d)\r\n", this, m_owned);
m_closed = true;
}
--- a/if/net/netudpsocket.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/if/net/netudpsocket.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -38,7 +38,7 @@
//Callbacks
-#ifdef __LINKER_BUG_SOLVED__
+#if 0 //Just for info
void NetUdpSocket::setOnEvent()
{
m_pCbItem = (CDummy*) pItem;
--- a/lwip/core/dns.c Fri Jun 18 09:11:35 2010 +0000
+++ b/lwip/core/dns.c Fri Jun 18 15:54:21 2010 +0000
@@ -1,968 +1,970 @@
-/**
- * @file
- * DNS - host name to IP address resolver.
- *
- */
-
-/**
-
- * This file implements a DNS host name to IP address resolver.
-
- * Port to lwIP from uIP
- * by Jim Pettinato April 2007
-
- * uIP version Copyright (c) 2002-2003, Adam Dunkels.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *
- * DNS.C
- *
- * The lwIP DNS resolver functions are used to lookup a host name and
- * map it to a numerical IP address. It maintains a list of resolved
- * hostnames that can be queried with the dns_lookup() function.
- * New hostnames can be resolved using the dns_query() function.
- *
- * The lwIP version of the resolver also adds a non-blocking version of
- * gethostbyname() that will work with a raw API application. This function
- * checks for an IP address string first and converts it if it is valid.
- * gethostbyname() then does a dns_lookup() to see if the name is
- * already in the table. If so, the IP is returned. If not, a query is
- * issued and the function returns with a ERR_INPROGRESS status. The app
- * using the dns client must then go into a waiting state.
- *
- * Once a hostname has been resolved (or found to be non-existent),
- * the resolver code calls a specified callback function (which
- * must be implemented by the module that uses the resolver).
- */
-
-/*-----------------------------------------------------------------------------
- * RFC 1035 - Domain names - implementation and specification
- * RFC 2181 - Clarifications to the DNS Specification
- *----------------------------------------------------------------------------*/
-
-/** @todo: define good default values (rfc compliance) */
-/** @todo: improve answer parsing, more checkings... */
-/** @todo: check RFC1035 - 7.3. Processing responses */
-
-/*-----------------------------------------------------------------------------
- * Includes
- *----------------------------------------------------------------------------*/
-
-#include "lwip/opt.h"
-
-#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
-
-#include "lwip/udp.h"
-#include "lwip/mem.h"
-#include "lwip/dns.h"
-
-#include <string.h>
-
-/** DNS server IP address */
-#ifndef DNS_SERVER_ADDRESS
-#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
-#endif
-
-/** DNS server port address */
-#ifndef DNS_SERVER_PORT
-#define DNS_SERVER_PORT 53
-#endif
-
-/** DNS maximum number of retries when asking for a name, before "timeout". */
-#ifndef DNS_MAX_RETRIES
-#define DNS_MAX_RETRIES 4
-#endif
-
-/** DNS resource record max. TTL (one week as default) */
-#ifndef DNS_MAX_TTL
-#define DNS_MAX_TTL 604800
-#endif
-
-/* DNS protocol flags */
-#define DNS_FLAG1_RESPONSE 0x80
-#define DNS_FLAG1_OPCODE_STATUS 0x10
-#define DNS_FLAG1_OPCODE_INVERSE 0x08
-#define DNS_FLAG1_OPCODE_STANDARD 0x00
-#define DNS_FLAG1_AUTHORATIVE 0x04
-#define DNS_FLAG1_TRUNC 0x02
-#define DNS_FLAG1_RD 0x01
-#define DNS_FLAG2_RA 0x80
-#define DNS_FLAG2_ERR_MASK 0x0f
-#define DNS_FLAG2_ERR_NONE 0x00
-#define DNS_FLAG2_ERR_NAME 0x03
-
-/* DNS protocol states */
-#define DNS_STATE_UNUSED 0
-#define DNS_STATE_NEW 1
-#define DNS_STATE_ASKING 2
-#define DNS_STATE_DONE 3
-
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/bpstruct.h"
-#endif
-PACK_STRUCT_BEGIN
-/** DNS message header */
-struct dns_hdr {
- PACK_STRUCT_FIELD(u16_t id);
- PACK_STRUCT_FIELD(u8_t flags1);
- PACK_STRUCT_FIELD(u8_t flags2);
- PACK_STRUCT_FIELD(u16_t numquestions);
- PACK_STRUCT_FIELD(u16_t numanswers);
- PACK_STRUCT_FIELD(u16_t numauthrr);
- PACK_STRUCT_FIELD(u16_t numextrarr);
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#ifdef PACK_STRUCT_USE_INCLUDES
-# include "arch/epstruct.h"
-#endif
-#define SIZEOF_DNS_HDR 12
-
-/** DNS query message structure.
- No packing needed: only used locally on the stack. */
-PACK_STRUCT_BEGIN
-struct dns_query {
- /* DNS query record starts with either a domain name or a pointer
- to a name already present somewhere in the packet. */
- u16_t type;
- u16_t cls;
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#define SIZEOF_DNS_QUERY 4
-
-/** DNS answer message structure.
- No packing needed: only used locally on the stack. */
-PACK_STRUCT_BEGIN
-struct dns_answer {
- /* DNS answer record starts with either a domain name or a pointer
- to a name already present somewhere in the packet. */
- u16_t type;
- u16_t cls;
- u32_t ttl;
- u16_t len;
-} PACK_STRUCT_STRUCT;
-PACK_STRUCT_END
-#define SIZEOF_DNS_ANSWER 10
-
-/** DNS table entry */
-struct dns_table_entry {
- u8_t state;
- u8_t numdns;
- u8_t tmr;
- u8_t retries;
- u8_t seqno;
- u8_t err;
- u32_t ttl;
- char name[DNS_MAX_NAME_LENGTH];
- ip_addr_t ipaddr;
- /* pointer to callback on DNS query done */
- dns_found_callback found;
- void *arg;
-};
-
-#if DNS_LOCAL_HOSTLIST
-/** struct used for local host-list */
-struct local_hostlist_entry {
- /** static hostname */
- const char *name;
- /** static host address in network byteorder */
- ip_addr_t addr;
- struct local_hostlist_entry *next;
-};
-
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-/** Local host-list. For hostnames in this list, no
- * external name resolution is performed */
-static struct local_hostlist_entry *local_hostlist_dynamic;
-#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-/** Defining this allows the local_hostlist_static to be placed in a different
- * linker section (e.g. FLASH) */
-#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
-#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
-#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
-/** Defining this allows the local_hostlist_static to be placed in a different
- * linker section (e.g. FLASH) */
-#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
-#define DNS_LOCAL_HOSTLIST_STORAGE_POST
-#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
-DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
- DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
-
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-static void dns_init_local();
-#endif /* DNS_LOCAL_HOSTLIST */
-
-
-/* forward declarations */
-static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
-static void dns_check_entries(void);
-
-/*-----------------------------------------------------------------------------
- * Globales
- *----------------------------------------------------------------------------*/
-
-/* DNS variables */
-static struct udp_pcb *dns_pcb;
-static u8_t dns_seqno;
-static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
-static ip_addr_t dns_servers[DNS_MAX_SERVERS];
-/** Contiguous buffer for processing responses */
-static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
-static u8_t* dns_payload;
-
-/**
- * Initialize the resolver: set up the UDP pcb and configure the default server
- * (DNS_SERVER_ADDRESS).
- */
-void
-dns_init()
-{
- ip_addr_t dnsserver;
-
- dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
-
- /* initialize default DNS server address */
- DNS_SERVER_ADDRESS(&dnsserver);
-
- LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
-
- /* if dns client not yet initialized... */
- if (dns_pcb == NULL) {
- dns_pcb = udp_new();
-
- if (dns_pcb != NULL) {
- /* initialize DNS table not needed (initialized to zero since it is a
- * global variable) */
- LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
- DNS_STATE_UNUSED == 0);
-
- /* initialize DNS client */
- udp_bind(dns_pcb, IP_ADDR_ANY, 0);
- udp_recv(dns_pcb, dns_recv, NULL);
-
- /* initialize default DNS primary server */
- dns_setserver(0, &dnsserver);
- }
- }
-#if DNS_LOCAL_HOSTLIST
- dns_init_local();
-#endif
-}
-
-/**
- * Initialize one of the DNS servers.
- *
- * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
- * @param dnsserver IP address of the DNS server to set
- */
-void
-dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
-{
- if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
- (dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
- dns_servers[numdns] = (*dnsserver);
- }
-}
-
-/**
- * Obtain one of the currently configured DNS server.
- *
- * @param numdns the index of the DNS server
- * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
- * server has not been configured.
- */
-ip_addr_t
-dns_getserver(u8_t numdns)
-{
- if (numdns < DNS_MAX_SERVERS) {
- return dns_servers[numdns];
- } else {
- return *IP_ADDR_ANY;
- }
-}
-
-/**
- * The DNS resolver client timer - handle retries and timeouts and should
- * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
- */
-void
-dns_tmr(void)
-{
- if (dns_pcb != NULL) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
- dns_check_entries();
- }
-}
-
-#if DNS_LOCAL_HOSTLIST
-static void
-dns_init_local()
-{
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
- int i;
- struct local_hostlist_entry *entry;
- /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
- struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
- size_t namelen;
- for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
- struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
- LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
- namelen = strlen(init_entry->name);
- entry = mem_malloc((mem_size_t)(sizeof(struct local_hostlist_entry) + namelen + 1));
- LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
- if (entry != NULL) {
- entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
- MEMCPY((char*)entry->name, init_entry->name, namelen);
- ((char*)entry->name)[namelen] = 0;
- entry->addr = init_entry->addr;
- entry->next = local_hostlist_dynamic;
- local_hostlist_dynamic = entry;
- }
- }
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
-}
-
-/**
- * Scans the local host-list for a hostname.
- *
- * @param hostname Hostname to look for in the local host-list
- * @return The first IP address for the hostname in the local host-list or
- * IPADDR_NONE if not found.
- */
-static u32_t
-dns_lookup_local(const char *hostname)
-{
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
- struct local_hostlist_entry *entry = local_hostlist_dynamic;
- while(entry != NULL) {
- if(strcmp(entry->name, hostname) == 0) {
- return ip4_addr_get_u32(&entry->addr);
- }
- entry = entry->next;
- }
-#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
- int i;
- for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
- if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
- return ip4_addr_get_u32(&local_hostlist_static[i].addr);
- }
- }
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
- return IPADDR_NONE;
-}
-
-#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-/** Remove all entries from the local host-list for a specific hostname
- * and/or IP addess
- *
- * @param hostname hostname for which entries shall be removed from the local
- * host-list
- * @param addr address for which entries shall be removed from the local host-list
- * @return the number of removed entries
- */
-int
-dns_local_removehost(const char *hostname, const ip_addr_t *addr)
-{
- int removed = 0;
- struct local_hostlist_entry *entry = local_hostlist_dynamic;
- struct local_hostlist_entry *last_entry = NULL;
- while (entry != NULL) {
- if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
- ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
- struct local_hostlist_entry *free_entry;
- if (last_entry != NULL) {
- last_entry->next = entry->next;
- } else {
- local_hostlist_dynamic = entry->next;
- }
- free_entry = entry;
- entry = entry->next;
- mem_free(free_entry);
- removed++;
- } else {
- last_entry = entry;
- entry = entry->next;
- }
- }
- return removed;
-}
-
-/**
- * Add a hostname/IP address pair to the local host-list.
- * Duplicates are not checked.
- *
- * @param hostname hostname of the new entry
- * @param addr IP address of the new entry
- * @return ERR_OK if succeeded or ERR_MEM on memory error
- */
-err_t
-dns_local_addhost(const char *hostname, const ip_addr_t *addr)
-{
- struct local_hostlist_entry *entry;
- size_t namelen;
- LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
- namelen = strlen(hostname);
- entry = mem_malloc((mem_size_t)(sizeof(struct local_hostlist_entry) + namelen + 1));
- if (entry == NULL) {
- return ERR_MEM;
- }
- entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
- MEMCPY((char*)entry->name, hostname, namelen);
- ((char*)entry->name)[namelen] = 0;
- ip_addr_copy(entry->addr, *addr);
- entry->next = local_hostlist_dynamic;
- local_hostlist_dynamic = entry;
- return ERR_OK;
-}
-#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
-#endif /* DNS_LOCAL_HOSTLIST */
-
-/**
- * Look up a hostname in the array of known hostnames.
- *
- * @note This function only looks in the internal array of known
- * hostnames, it does not send out a query for the hostname if none
- * was found. The function dns_enqueue() can be used to send a query
- * for a hostname.
- *
- * @param name the hostname to look up
- * @return the hostname's IP address, as u32_t (instead of ip_addr_t to
- * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
- * was not found in the cached dns_table.
- */
-static u32_t
-dns_lookup(const char *name)
-{
- u8_t i;
-#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
- u32_t addr;
-#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
-#if DNS_LOCAL_HOSTLIST
- if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
- return addr;
- }
-#endif /* DNS_LOCAL_HOSTLIST */
-#ifdef DNS_LOOKUP_LOCAL_EXTERN
- if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
- return addr;
- }
-#endif /* DNS_LOOKUP_LOCAL_EXTERN */
-
- /* Walk through name list, return entry if found. If not, return NULL. */
- for (i = 0; i < DNS_TABLE_SIZE; ++i) {
- if ((dns_table[i].state == DNS_STATE_DONE) &&
- (strcmp(name, dns_table[i].name) == 0)) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
- ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
- LWIP_DEBUGF(DNS_DEBUG, ("\n"));
- return ip4_addr_get_u32(&dns_table[i].ipaddr);
- }
- }
-
- return IPADDR_NONE;
-}
-
-#if DNS_DOES_NAME_CHECK
-/**
- * Compare the "dotted" name "query" with the encoded name "response"
- * to make sure an answer from the DNS server matches the current dns_table
- * entry (otherwise, answers might arrive late for hostname not on the list
- * any more).
- *
- * @param query hostname (not encoded) from the dns_table
- * @param response encoded hostname in the DNS response
- * @return 0: names equal; 1: names differ
- */
-static u8_t
-dns_compare_name(unsigned char *query, unsigned char *response)
-{
- unsigned char n;
-
- do {
- n = *response++;
- /** @see RFC 1035 - 4.1.4. Message compression */
- if ((n & 0xc0) == 0xc0) {
- /* Compressed name */
- break;
- } else {
- /* Not compressed name */
- while (n > 0) {
- if ((*query) != (*response)) {
- return 1;
- }
- ++response;
- ++query;
- --n;
- };
- ++query;
- }
- } while (*response != 0);
-
- return 0;
-}
-#endif /* DNS_DOES_NAME_CHECK */
-
-/**
- * Walk through a compact encoded DNS name and return the end of the name.
- *
- * @param query encoded DNS name in the DNS server response
- * @return end of the name
- */
-static unsigned char *
-dns_parse_name(unsigned char *query)
-{
- unsigned char n;
-
- do {
- n = *query++;
- /** @see RFC 1035 - 4.1.4. Message compression */
- if ((n & 0xc0) == 0xc0) {
- /* Compressed name */
- break;
- } else {
- /* Not compressed name */
- while (n > 0) {
- ++query;
- --n;
- };
- }
- } while (*query != 0);
-
- return query + 1;
-}
-
-/**
- * Send a DNS query packet.
- *
- * @param numdns index of the DNS server in the dns_servers table
- * @param name hostname to query
- * @param id index of the hostname in dns_table, used as transaction ID in the
- * DNS query packet
- * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
- */
-static err_t
-dns_send(u8_t numdns, const char* name, u8_t id)
-{
- err_t err;
- struct dns_hdr *hdr;
- struct dns_query qry;
- struct pbuf *p;
- char *query, *nptr;
- const char *pHostname;
- u8_t n;
-
- LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
- (u16_t)(numdns), name));
- LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
- LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
-
- /* if here, we have either a new query or a retry on a previous query to process */
- p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
- SIZEOF_DNS_QUERY, PBUF_RAM);
- if (p != NULL) {
- LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
- /* fill dns header */
- hdr = (struct dns_hdr*)p->payload;
- memset(hdr, 0, SIZEOF_DNS_HDR);
- hdr->id = htons(id);
- hdr->flags1 = DNS_FLAG1_RD;
- hdr->numquestions = htons(1);
- query = (char*)hdr + SIZEOF_DNS_HDR;
- pHostname = name;
- --pHostname;
-
- /* convert hostname into suitable query format. */
- do {
- ++pHostname;
- nptr = query;
- ++query;
- for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
- *query = *pHostname;
- ++query;
- ++n;
- }
- *nptr = n;
- } while(*pHostname != 0);
- *query++='\0';
-
- /* fill dns query */
- qry.type = htons(DNS_RRTYPE_A);
- qry.cls = htons(DNS_RRCLASS_IN);
- SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
-
- /* resize pbuf to the exact dns query */
- pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
-
- /* connect to the server for faster receiving */
- udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
- /* send dns packet */
- err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
-
- /* free pbuf */
- pbuf_free(p);
- } else {
- err = ERR_MEM;
- }
-
- return err;
-}
-
-/**
- * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query.
- * Check an entry in the dns_table:
- * - send out query for new entries
- * - retry old pending entries on timeout (also with different servers)
- * - remove completed entries from the table if their TTL has expired
- *
- * @param i index of the dns_table entry to check
- */
-static void
-dns_check_entry(u8_t i)
-{
- struct dns_table_entry *pEntry = &dns_table[i];
-
- LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
-
- switch(pEntry->state) {
-
- case DNS_STATE_NEW: {
- /* initialize new entry */
- pEntry->state = DNS_STATE_ASKING;
- pEntry->numdns = 0;
- pEntry->tmr = 1;
- pEntry->retries = 0;
-
- /* send DNS packet for this entry */
- dns_send(pEntry->numdns, pEntry->name, i);
- break;
- }
-
- case DNS_STATE_ASKING: {
- if (--pEntry->tmr == 0) {
- if (++pEntry->retries == DNS_MAX_RETRIES) {
- if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
- /* change of server */
- pEntry->numdns++;
- pEntry->tmr = 1;
- pEntry->retries = 0;
- break;
- } else {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
- /* call specified callback function if provided */
- if (pEntry->found)
- (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
- /* flush this entry */
- pEntry->state = DNS_STATE_UNUSED;
- pEntry->found = NULL;
- break;
- }
- }
-
- /* wait longer for the next retry */
- pEntry->tmr = pEntry->retries;
-
- /* send DNS packet for this entry */
- dns_send(pEntry->numdns, pEntry->name, i);
- }
- break;
- }
-
- case DNS_STATE_DONE: {
- /* if the time to live is nul */
- if (--pEntry->ttl == 0) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
- /* flush this entry */
- pEntry->state = DNS_STATE_UNUSED;
- pEntry->found = NULL;
- }
- break;
- }
- case DNS_STATE_UNUSED:
- /* nothing to do */
- break;
- default:
- LWIP_ASSERT("unknown dns_table entry state:", 0);
- break;
- }
-}
-
-/**
- * Call dns_check_entry for each entry in dns_table - check all entries.
- */
-static void
-dns_check_entries(void)
-{
- u8_t i;
-
- for (i = 0; i < DNS_TABLE_SIZE; ++i) {
- dns_check_entry(i);
- }
-}
-
-/**
- * Receive input function for DNS response packets arriving for the dns UDP pcb.
- *
- * @params see udp.h
- */
-static void
-dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
-{
- u16_t i;
- char *pHostname;
- struct dns_hdr *hdr;
- struct dns_answer ans;
- struct dns_table_entry *pEntry;
- u16_t nquestions, nanswers;
-
- LWIP_UNUSED_ARG(arg);
- LWIP_UNUSED_ARG(pcb);
- LWIP_UNUSED_ARG(addr);
- LWIP_UNUSED_ARG(port);
-
- /* is the dns message too big ? */
- if (p->tot_len > DNS_MSG_SIZE) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
- /* free pbuf and return */
- goto memerr;
- }
-
- /* is the dns message big enough ? */
- if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
- /* free pbuf and return */
- goto memerr;
- }
-
- /* copy dns payload inside static buffer for processing */
- if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
- /* The ID in the DNS header should be our entry into the name table. */
- hdr = (struct dns_hdr*)dns_payload;
- i = htons(hdr->id);
- if (i < DNS_TABLE_SIZE) {
- pEntry = &dns_table[i];
- if(pEntry->state == DNS_STATE_ASKING) {
- /* This entry is now completed. */
- pEntry->state = DNS_STATE_DONE;
- pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
-
- /* We only care about the question(s) and the answers. The authrr
- and the extrarr are simply discarded. */
- nquestions = htons(hdr->numquestions);
- nanswers = htons(hdr->numanswers);
-
- /* Check for error. If so, call callback to inform. */
- if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
- /* call callback to indicate error, clean up memory and return */
- goto responseerr;
- }
-
-#if DNS_DOES_NAME_CHECK
- /* Check if the name in the "question" part match with the name in the entry. */
- if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
- /* call callback to indicate error, clean up memory and return */
- goto responseerr;
- }
-#endif /* DNS_DOES_NAME_CHECK */
-
- /* Skip the name in the "question" part */
- pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
-
- while (nanswers > 0) {
- /* skip answer resource record's host name */
- pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
-
- /* Check for IP address type and Internet class. Others are discarded. */
- SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
- if((ans.type == htons(DNS_RRTYPE_A)) && (ans.cls == htons(DNS_RRCLASS_IN)) &&
- (ans.len == htons(sizeof(ip_addr_t))) ) {
- /* read the answer resource record's TTL, and maximize it if needed */
- pEntry->ttl = ntohl(ans.ttl);
- if (pEntry->ttl > DNS_MAX_TTL) {
- pEntry->ttl = DNS_MAX_TTL;
- }
- /* read the IP address after answer resource record's header */
- SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
- ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
- LWIP_DEBUGF(DNS_DEBUG, ("\n"));
- /* call specified callback function if provided */
- if (pEntry->found) {
- (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
- }
- /* deallocate memory and return */
- goto memerr;
- } else {
- pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
- }
- --nanswers;
- }
- LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
- /* call callback to indicate error, clean up memory and return */
- goto responseerr;
- }
- }
- }
-
- /* deallocate memory and return */
- goto memerr;
-
-responseerr:
- /* ERROR: call specified callback function with NULL as name to indicate an error */
- if (pEntry->found) {
- (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
- }
- /* flush this entry */
- pEntry->state = DNS_STATE_UNUSED;
- pEntry->found = NULL;
-
-memerr:
- /* free pbuf */
- pbuf_free(p);
- return;
-}
-
-/**
- * Queues a new hostname to resolve and sends out a DNS query for that hostname
- *
- * @param name the hostname that is to be queried
- * @param found a callback founction to be called on success, failure or timeout
- * @param callback_arg argument to pass to the callback function
- * @return @return a err_t return code.
- */
-static err_t
-dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
-{
- u8_t i;
- u8_t lseq, lseqi;
- struct dns_table_entry *pEntry = NULL;
- size_t namelen;
-
- /* search an unused entry, or the oldest one */
- lseq = lseqi = 0;
- for (i = 0; i < DNS_TABLE_SIZE; ++i) {
- pEntry = &dns_table[i];
- /* is it an unused entry ? */
- if (pEntry->state == DNS_STATE_UNUSED)
- break;
-
- /* check if this is the oldest completed entry */
- if (pEntry->state == DNS_STATE_DONE) {
- if ((dns_seqno - pEntry->seqno) > lseq) {
- lseq = dns_seqno - pEntry->seqno;
- lseqi = i;
- }
- }
- }
-
- /* if we don't have found an unused entry, use the oldest completed one */
- if (i == DNS_TABLE_SIZE) {
- if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
- /* no entry can't be used now, table is full */
- LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
- return ERR_MEM;
- } else {
- /* use the oldest completed one */
- i = lseqi;
- pEntry = &dns_table[i];
- }
- }
-
- /* use this entry */
- LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
-
- /* fill the entry */
- pEntry->state = DNS_STATE_NEW;
- pEntry->seqno = dns_seqno++;
- pEntry->found = found;
- pEntry->arg = callback_arg;
- namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
- MEMCPY(pEntry->name, name, namelen);
- pEntry->name[namelen] = 0;
-
- /* force to send query without waiting timer */
- dns_check_entry(i);
-
- /* dns query is enqueued */
- return ERR_INPROGRESS;
-}
-
-/**
- * Resolve a hostname (string) into an IP address.
- * NON-BLOCKING callback version for use with raw API!!!
- *
- * Returns immediately with one of err_t return codes:
- * - ERR_OK if hostname is a valid IP address string or the host
- * name is already in the local names table.
- * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
- * for resolution if no errors are present.
- *
- * @param hostname the hostname that is to be queried
- * @param addr pointer to a ip_addr_t where to store the address if it is already
- * cached in the dns_table (only valid if ERR_OK is returned!)
- * @param found a callback function to be called on success, failure or timeout (only if
- * ERR_INPROGRESS is returned!)
- * @param callback_arg argument to pass to the callback function
- * @return a err_t return code.
- */
-err_t
-dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
- void *callback_arg)
-{
- u32_t ipaddr;
- /* not initialized or no valid server yet, or invalid addr pointer
- * or invalid hostname or invalid hostname length */
- if ((dns_pcb == NULL) || (addr == NULL) ||
- (!hostname) || (!hostname[0]) ||
- (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
- return ERR_VAL;
- }
-
-#if LWIP_HAVE_LOOPIF
- if (strcmp(hostname, "localhost")==0) {
- ip_addr_set_loopback(addr);
- return ERR_OK;
- }
-#endif /* LWIP_HAVE_LOOPIF */
-
- /* host name already in octet notation? set ip addr and return ERR_OK */
- ipaddr = ipaddr_addr(hostname);
- if (ipaddr == IPADDR_NONE) {
- /* already have this address cached? */
- ipaddr = dns_lookup(hostname);
- }
- if (ipaddr != IPADDR_NONE) {
- ip4_addr_set_u32(addr, ipaddr);
- return ERR_OK;
- }
-
- /* queue query with specified callback */
- return dns_enqueue(hostname, found, callback_arg);
-}
-#endif /* LWIP_DNS */
+/**
+ * @file
+ * DNS - host name to IP address resolver.
+ *
+ */
+
+/**
+
+ * This file implements a DNS host name to IP address resolver.
+
+ * Port to lwIP from uIP
+ * by Jim Pettinato April 2007
+
+ * uIP version Copyright (c) 2002-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * DNS.C
+ *
+ * The lwIP DNS resolver functions are used to lookup a host name and
+ * map it to a numerical IP address. It maintains a list of resolved
+ * hostnames that can be queried with the dns_lookup() function.
+ * New hostnames can be resolved using the dns_query() function.
+ *
+ * The lwIP version of the resolver also adds a non-blocking version of
+ * gethostbyname() that will work with a raw API application. This function
+ * checks for an IP address string first and converts it if it is valid.
+ * gethostbyname() then does a dns_lookup() to see if the name is
+ * already in the table. If so, the IP is returned. If not, a query is
+ * issued and the function returns with a ERR_INPROGRESS status. The app
+ * using the dns client must then go into a waiting state.
+ *
+ * Once a hostname has been resolved (or found to be non-existent),
+ * the resolver code calls a specified callback function (which
+ * must be implemented by the module that uses the resolver).
+ */
+
+/*-----------------------------------------------------------------------------
+ * RFC 1035 - Domain names - implementation and specification
+ * RFC 2181 - Clarifications to the DNS Specification
+ *----------------------------------------------------------------------------*/
+
+/** @todo: define good default values (rfc compliance) */
+/** @todo: improve answer parsing, more checkings... */
+/** @todo: check RFC1035 - 7.3. Processing responses */
+
+/*-----------------------------------------------------------------------------
+ * Includes
+ *----------------------------------------------------------------------------*/
+
+#include "lwip/opt.h"
+
+#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/dns.h"
+#include "lwip/debug.h"
+
+#include <string.h>
+
+/** DNS server IP address */
+#ifndef DNS_SERVER_ADDRESS
+#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
+#endif
+
+/** DNS server port address */
+#ifndef DNS_SERVER_PORT
+#define DNS_SERVER_PORT 53
+#endif
+
+/** DNS maximum number of retries when asking for a name, before "timeout". */
+#ifndef DNS_MAX_RETRIES
+#define DNS_MAX_RETRIES 4
+#endif
+
+/** DNS resource record max. TTL (one week as default) */
+#ifndef DNS_MAX_TTL
+#define DNS_MAX_TTL 604800
+#endif
+
+/* DNS protocol flags */
+#define DNS_FLAG1_RESPONSE 0x80
+#define DNS_FLAG1_OPCODE_STATUS 0x10
+#define DNS_FLAG1_OPCODE_INVERSE 0x08
+#define DNS_FLAG1_OPCODE_STANDARD 0x00
+#define DNS_FLAG1_AUTHORATIVE 0x04
+#define DNS_FLAG1_TRUNC 0x02
+#define DNS_FLAG1_RD 0x01
+#define DNS_FLAG2_RA 0x80
+#define DNS_FLAG2_ERR_MASK 0x0f
+#define DNS_FLAG2_ERR_NONE 0x00
+#define DNS_FLAG2_ERR_NAME 0x03
+
+/* DNS protocol states */
+#define DNS_STATE_UNUSED 0
+#define DNS_STATE_NEW 1
+#define DNS_STATE_ASKING 2
+#define DNS_STATE_DONE 3
+
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+/** DNS message header */
+struct dns_hdr {
+ PACK_STRUCT_FIELD(u16_t id);
+ PACK_STRUCT_FIELD(u8_t flags1);
+ PACK_STRUCT_FIELD(u8_t flags2);
+ PACK_STRUCT_FIELD(u16_t numquestions);
+ PACK_STRUCT_FIELD(u16_t numanswers);
+ PACK_STRUCT_FIELD(u16_t numauthrr);
+ PACK_STRUCT_FIELD(u16_t numextrarr);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/epstruct.h"
+#endif
+#define SIZEOF_DNS_HDR 12
+
+/** DNS query message structure.
+ No packing needed: only used locally on the stack. */
+struct dns_query {
+ /* DNS query record starts with either a domain name or a pointer
+ to a name already present somewhere in the packet. */
+ u16_t type;
+ u16_t cls;
+};
+#define SIZEOF_DNS_QUERY 4
+
+/** DNS answer message structure.
+ No packing needed: only used locally on the stack. */
+struct dns_answer {
+ /* DNS answer record starts with either a domain name or a pointer
+ to a name already present somewhere in the packet. */
+ u16_t type;
+ u16_t cls;
+ u32_t ttl;
+ u16_t len;
+};
+#define SIZEOF_DNS_ANSWER 10
+
+/** DNS table entry */
+struct dns_table_entry {
+ u8_t state;
+ u8_t numdns;
+ u8_t tmr;
+ u8_t retries;
+ u8_t seqno;
+ u8_t err;
+ u32_t ttl;
+ char name[DNS_MAX_NAME_LENGTH];
+ ip_addr_t ipaddr;
+ /* pointer to callback on DNS query done */
+ dns_found_callback found;
+ void *arg;
+};
+
+#if DNS_LOCAL_HOSTLIST
+
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+/** Local host-list. For hostnames in this list, no
+ * external name resolution is performed */
+static struct local_hostlist_entry *local_hostlist_dynamic;
+#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+
+/** Defining this allows the local_hostlist_static to be placed in a different
+ * linker section (e.g. FLASH) */
+#ifndef DNS_LOCAL_HOSTLIST_STORAGE_PRE
+#define DNS_LOCAL_HOSTLIST_STORAGE_PRE static
+#endif /* DNS_LOCAL_HOSTLIST_STORAGE_PRE */
+/** Defining this allows the local_hostlist_static to be placed in a different
+ * linker section (e.g. FLASH) */
+#ifndef DNS_LOCAL_HOSTLIST_STORAGE_POST
+#define DNS_LOCAL_HOSTLIST_STORAGE_POST
+#endif /* DNS_LOCAL_HOSTLIST_STORAGE_POST */
+DNS_LOCAL_HOSTLIST_STORAGE_PRE struct local_hostlist_entry local_hostlist_static[]
+ DNS_LOCAL_HOSTLIST_STORAGE_POST = DNS_LOCAL_HOSTLIST_INIT;
+
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+
+static void dns_init_local();
+#endif /* DNS_LOCAL_HOSTLIST */
+
+
+/* forward declarations */
+static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
+static void dns_check_entries(void);
+
+/*-----------------------------------------------------------------------------
+ * Globales
+ *----------------------------------------------------------------------------*/
+
+/* DNS variables */
+static struct udp_pcb *dns_pcb;
+static u8_t dns_seqno;
+static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
+static ip_addr_t dns_servers[DNS_MAX_SERVERS];
+/** Contiguous buffer for processing responses */
+static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
+static u8_t* dns_payload;
+
+/**
+ * Initialize the resolver: set up the UDP pcb and configure the default server
+ * (DNS_SERVER_ADDRESS).
+ */
+void
+dns_init()
+{
+ ip_addr_t dnsserver;
+
+ dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
+
+ /* initialize default DNS server address */
+ DNS_SERVER_ADDRESS(&dnsserver);
+
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
+
+ /* if dns client not yet initialized... */
+ if (dns_pcb == NULL) {
+ dns_pcb = udp_new();
+
+ if (dns_pcb != NULL) {
+ /* initialize DNS table not needed (initialized to zero since it is a
+ * global variable) */
+ LWIP_ASSERT("For implicit initialization to work, DNS_STATE_UNUSED needs to be 0",
+ DNS_STATE_UNUSED == 0);
+
+ /* initialize DNS client */
+ udp_bind(dns_pcb, IP_ADDR_ANY, 0);
+ udp_recv(dns_pcb, dns_recv, NULL);
+
+ /* initialize default DNS primary server */
+ dns_setserver(0, &dnsserver);
+ }
+ }
+#if DNS_LOCAL_HOSTLIST
+ dns_init_local();
+#endif
+}
+
+/**
+ * Initialize one of the DNS servers.
+ *
+ * @param numdns the index of the DNS server to set must be < DNS_MAX_SERVERS
+ * @param dnsserver IP address of the DNS server to set
+ */
+void
+dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
+{
+ if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
+ (dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
+ dns_servers[numdns] = (*dnsserver);
+ }
+}
+
+/**
+ * Obtain one of the currently configured DNS server.
+ *
+ * @param numdns the index of the DNS server
+ * @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
+ * server has not been configured.
+ */
+ip_addr_t
+dns_getserver(u8_t numdns)
+{
+ if (numdns < DNS_MAX_SERVERS) {
+ return dns_servers[numdns];
+ } else {
+ return *IP_ADDR_ANY;
+ }
+}
+
+/**
+ * The DNS resolver client timer - handle retries and timeouts and should
+ * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
+ */
+void
+dns_tmr(void)
+{
+ if (dns_pcb != NULL) {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_tmr: dns_check_entries\n"));
+ dns_check_entries();
+ }
+}
+
+#if DNS_LOCAL_HOSTLIST
+static void
+dns_init_local()
+{
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT)
+ int i;
+ struct local_hostlist_entry *entry;
+ /* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
+ struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
+ size_t namelen;
+ for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
+ struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
+ LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
+ namelen = strlen(init_entry->name);
+ LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
+ entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
+ LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
+ if (entry != NULL) {
+ entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
+ MEMCPY((char*)entry->name, init_entry->name, namelen);
+ ((char*)entry->name)[namelen] = 0;
+ entry->addr = init_entry->addr;
+ entry->next = local_hostlist_dynamic;
+ local_hostlist_dynamic = entry;
+ }
+ }
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC && defined(DNS_LOCAL_HOSTLIST_INIT) */
+}
+
+/**
+ * Scans the local host-list for a hostname.
+ *
+ * @param hostname Hostname to look for in the local host-list
+ * @return The first IP address for the hostname in the local host-list or
+ * IPADDR_NONE if not found.
+ */
+static u32_t
+dns_lookup_local(const char *hostname)
+{
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+ struct local_hostlist_entry *entry = local_hostlist_dynamic;
+ while(entry != NULL) {
+ if(strcmp(entry->name, hostname) == 0) {
+ return ip4_addr_get_u32(&entry->addr);
+ }
+ entry = entry->next;
+ }
+#else /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+ int i;
+ for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
+ if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
+ return ip4_addr_get_u32(&local_hostlist_static[i].addr);
+ }
+ }
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+ return IPADDR_NONE;
+}
+
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+/** Remove all entries from the local host-list for a specific hostname
+ * and/or IP addess
+ *
+ * @param hostname hostname for which entries shall be removed from the local
+ * host-list
+ * @param addr address for which entries shall be removed from the local host-list
+ * @return the number of removed entries
+ */
+int
+dns_local_removehost(const char *hostname, const ip_addr_t *addr)
+{
+ int removed = 0;
+ struct local_hostlist_entry *entry = local_hostlist_dynamic;
+ struct local_hostlist_entry *last_entry = NULL;
+ while (entry != NULL) {
+ if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
+ ((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
+ struct local_hostlist_entry *free_entry;
+ if (last_entry != NULL) {
+ last_entry->next = entry->next;
+ } else {
+ local_hostlist_dynamic = entry->next;
+ }
+ free_entry = entry;
+ entry = entry->next;
+ memp_free(MEMP_LOCALHOSTLIST, free_entry);
+ removed++;
+ } else {
+ last_entry = entry;
+ entry = entry->next;
+ }
+ }
+ return removed;
+}
+
+/**
+ * Add a hostname/IP address pair to the local host-list.
+ * Duplicates are not checked.
+ *
+ * @param hostname hostname of the new entry
+ * @param addr IP address of the new entry
+ * @return ERR_OK if succeeded or ERR_MEM on memory error
+ */
+err_t
+dns_local_addhost(const char *hostname, const ip_addr_t *addr)
+{
+ struct local_hostlist_entry *entry;
+ size_t namelen;
+ LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
+ namelen = strlen(hostname);
+ LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
+ entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
+ if (entry == NULL) {
+ return ERR_MEM;
+ }
+ entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
+ MEMCPY((char*)entry->name, hostname, namelen);
+ ((char*)entry->name)[namelen] = 0;
+ ip_addr_copy(entry->addr, *addr);
+ entry->next = local_hostlist_dynamic;
+ local_hostlist_dynamic = entry;
+ return ERR_OK;
+}
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC*/
+#endif /* DNS_LOCAL_HOSTLIST */
+
+/**
+ * Look up a hostname in the array of known hostnames.
+ *
+ * @note This function only looks in the internal array of known
+ * hostnames, it does not send out a query for the hostname if none
+ * was found. The function dns_enqueue() can be used to send a query
+ * for a hostname.
+ *
+ * @param name the hostname to look up
+ * @return the hostname's IP address, as u32_t (instead of ip_addr_t to
+ * better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
+ * was not found in the cached dns_table.
+ */
+static u32_t
+dns_lookup(const char *name)
+{
+ u8_t i;
+#if DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN)
+ u32_t addr;
+#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
+#if DNS_LOCAL_HOSTLIST
+ if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
+ return addr;
+ }
+#endif /* DNS_LOCAL_HOSTLIST */
+#ifdef DNS_LOOKUP_LOCAL_EXTERN
+ if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
+ return addr;
+ }
+#endif /* DNS_LOOKUP_LOCAL_EXTERN */
+
+ /* Walk through name list, return entry if found. If not, return NULL. */
+ for (i = 0; i < DNS_TABLE_SIZE; ++i) {
+ if ((dns_table[i].state == DNS_STATE_DONE) &&
+ (strcmp(name, dns_table[i].name) == 0)) {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
+ ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
+ LWIP_DEBUGF(DNS_DEBUG, ("\n"));
+ return ip4_addr_get_u32(&dns_table[i].ipaddr);
+ }
+ }
+
+ return IPADDR_NONE;
+}
+
+#if DNS_DOES_NAME_CHECK
+/**
+ * Compare the "dotted" name "query" with the encoded name "response"
+ * to make sure an answer from the DNS server matches the current dns_table
+ * entry (otherwise, answers might arrive late for hostname not on the list
+ * any more).
+ *
+ * @param query hostname (not encoded) from the dns_table
+ * @param response encoded hostname in the DNS response
+ * @return 0: names equal; 1: names differ
+ */
+static u8_t
+dns_compare_name(unsigned char *query, unsigned char *response)
+{
+ unsigned char n;
+
+ do {
+ n = *response++;
+ /** @see RFC 1035 - 4.1.4. Message compression */
+ if ((n & 0xc0) == 0xc0) {
+ /* Compressed name */
+ break;
+ } else {
+ /* Not compressed name */
+ while (n > 0) {
+ if ((*query) != (*response)) {
+ return 1;
+ }
+ ++response;
+ ++query;
+ --n;
+ };
+ ++query;
+ }
+ } while (*response != 0);
+
+ return 0;
+}
+#endif /* DNS_DOES_NAME_CHECK */
+
+/**
+ * Walk through a compact encoded DNS name and return the end of the name.
+ *
+ * @param query encoded DNS name in the DNS server response
+ * @return end of the name
+ */
+static unsigned char *
+dns_parse_name(unsigned char *query)
+{
+ unsigned char n;
+
+ do {
+ n = *query++;
+ /** @see RFC 1035 - 4.1.4. Message compression */
+ if ((n & 0xc0) == 0xc0) {
+ /* Compressed name */
+ break;
+ } else {
+ /* Not compressed name */
+ while (n > 0) {
+ ++query;
+ --n;
+ };
+ }
+ } while (*query != 0);
+
+ return query + 1;
+}
+
+/**
+ * Send a DNS query packet.
+ *
+ * @param numdns index of the DNS server in the dns_servers table
+ * @param name hostname to query
+ * @param id index of the hostname in dns_table, used as transaction ID in the
+ * DNS query packet
+ * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
+ */
+static err_t
+dns_send(u8_t numdns, const char* name, u8_t id)
+{
+ err_t err;
+ struct dns_hdr *hdr;
+ struct dns_query qry;
+ struct pbuf *p;
+ char *query, *nptr;
+ const char *pHostname;
+ u8_t n;
+
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
+ (u16_t)(numdns), name));
+ LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
+ LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
+
+ /* if here, we have either a new query or a retry on a previous query to process */
+ p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
+ SIZEOF_DNS_QUERY, PBUF_RAM);
+ if (p != NULL) {
+ LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
+ /* fill dns header */
+ hdr = (struct dns_hdr*)p->payload;
+ memset(hdr, 0, SIZEOF_DNS_HDR);
+ hdr->id = htons(id);
+ hdr->flags1 = DNS_FLAG1_RD;
+ hdr->numquestions = PP_HTONS(1);
+ query = (char*)hdr + SIZEOF_DNS_HDR;
+ pHostname = name;
+ --pHostname;
+
+ /* convert hostname into suitable query format. */
+ do {
+ ++pHostname;
+ nptr = query;
+ ++query;
+ for(n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
+ *query = *pHostname;
+ ++query;
+ ++n;
+ }
+ *nptr = n;
+ } while(*pHostname != 0);
+ *query++='\0';
+
+ /* fill dns query */
+ qry.type = PP_HTONS(DNS_RRTYPE_A);
+ qry.cls = PP_HTONS(DNS_RRCLASS_IN);
+ SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
+
+ /* resize pbuf to the exact dns query */
+ pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
+
+ /* connect to the server for faster receiving */
+ udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
+ /* send dns packet */
+ err = udp_sendto(dns_pcb, p, &dns_servers[numdns], DNS_SERVER_PORT);
+
+ /* free pbuf */
+ pbuf_free(p);
+ } else {
+ err = ERR_MEM;
+ }
+
+ return err;
+}
+
+/**
+ * dns_check_entry() - see if pEntry has not yet been queried and, if so, sends out a query.
+ * Check an entry in the dns_table:
+ * - send out query for new entries
+ * - retry old pending entries on timeout (also with different servers)
+ * - remove completed entries from the table if their TTL has expired
+ *
+ * @param i index of the dns_table entry to check
+ */
+static void
+dns_check_entry(u8_t i)
+{
+ err_t err;
+ struct dns_table_entry *pEntry = &dns_table[i];
+
+ LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
+
+ switch(pEntry->state) {
+
+ case DNS_STATE_NEW: {
+ /* initialize new entry */
+ pEntry->state = DNS_STATE_ASKING;
+ pEntry->numdns = 0;
+ pEntry->tmr = 1;
+ pEntry->retries = 0;
+
+ /* send DNS packet for this entry */
+ err = dns_send(pEntry->numdns, pEntry->name, i);
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("dns_send returned error: %d\n", err));
+ }
+ break;
+ }
+
+ case DNS_STATE_ASKING: {
+ if (--pEntry->tmr == 0) {
+ if (++pEntry->retries == DNS_MAX_RETRIES) {
+ if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
+ /* change of server */
+ pEntry->numdns++;
+ pEntry->tmr = 1;
+ pEntry->retries = 0;
+ break;
+ } else {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
+ /* call specified callback function if provided */
+ if (pEntry->found)
+ (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
+ /* flush this entry */
+ pEntry->state = DNS_STATE_UNUSED;
+ pEntry->found = NULL;
+ break;
+ }
+ }
+
+ /* wait longer for the next retry */
+ pEntry->tmr = pEntry->retries;
+
+ /* send DNS packet for this entry */
+ err = dns_send(pEntry->numdns, pEntry->name, i);
+ if (err != ERR_OK) {
+ LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
+ ("dns_send returned error: %d\n", err));
+ }
+ }
+ break;
+ }
+
+ case DNS_STATE_DONE: {
+ /* if the time to live is nul */
+ if (--pEntry->ttl == 0) {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
+ /* flush this entry */
+ pEntry->state = DNS_STATE_UNUSED;
+ pEntry->found = NULL;
+ }
+ break;
+ }
+ case DNS_STATE_UNUSED:
+ /* nothing to do */
+ break;
+ default:
+ LWIP_ASSERT("unknown dns_table entry state:", 0);
+ break;
+ }
+}
+
+/**
+ * Call dns_check_entry for each entry in dns_table - check all entries.
+ */
+static void
+dns_check_entries(void)
+{
+ u8_t i;
+
+ for (i = 0; i < DNS_TABLE_SIZE; ++i) {
+ dns_check_entry(i);
+ }
+}
+
+/**
+ * Receive input function for DNS response packets arriving for the dns UDP pcb.
+ *
+ * @params see udp.h
+ */
+static void
+dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
+{
+ u16_t i;
+ char *pHostname;
+ struct dns_hdr *hdr;
+ struct dns_answer ans;
+ struct dns_table_entry *pEntry;
+ u16_t nquestions, nanswers;
+
+ LWIP_UNUSED_ARG(arg);
+ LWIP_UNUSED_ARG(pcb);
+ LWIP_UNUSED_ARG(addr);
+ LWIP_UNUSED_ARG(port);
+
+ /* is the dns message too big ? */
+ if (p->tot_len > DNS_MSG_SIZE) {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
+ /* free pbuf and return */
+ goto memerr;
+ }
+
+ /* is the dns message big enough ? */
+ if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
+ /* free pbuf and return */
+ goto memerr;
+ }
+
+ /* copy dns payload inside static buffer for processing */
+ if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
+ /* The ID in the DNS header should be our entry into the name table. */
+ hdr = (struct dns_hdr*)dns_payload;
+ i = htons(hdr->id);
+ if (i < DNS_TABLE_SIZE) {
+ pEntry = &dns_table[i];
+ if(pEntry->state == DNS_STATE_ASKING) {
+ /* This entry is now completed. */
+ pEntry->state = DNS_STATE_DONE;
+ pEntry->err = hdr->flags2 & DNS_FLAG2_ERR_MASK;
+
+ /* We only care about the question(s) and the answers. The authrr
+ and the extrarr are simply discarded. */
+ nquestions = htons(hdr->numquestions);
+ nanswers = htons(hdr->numanswers);
+
+ /* Check for error. If so, call callback to inform. */
+ if (((hdr->flags1 & DNS_FLAG1_RESPONSE) == 0) || (pEntry->err != 0) || (nquestions != 1)) {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in flags\n", pEntry->name));
+ /* call callback to indicate error, clean up memory and return */
+ goto responseerr;
+ }
+
+#if DNS_DOES_NAME_CHECK
+ /* Check if the name in the "question" part match with the name in the entry. */
+ if (dns_compare_name((unsigned char *)(pEntry->name), (unsigned char *)dns_payload + SIZEOF_DNS_HDR) != 0) {
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response not match to query\n", pEntry->name));
+ /* call callback to indicate error, clean up memory and return */
+ goto responseerr;
+ }
+#endif /* DNS_DOES_NAME_CHECK */
+
+ /* Skip the name in the "question" part */
+ pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
+
+ while (nanswers > 0) {
+ /* skip answer resource record's host name */
+ pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
+
+ /* Check for IP address type and Internet class. Others are discarded. */
+ SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
+ if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
+ (ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
+ /* read the answer resource record's TTL, and maximize it if needed */
+ pEntry->ttl = ntohl(ans.ttl);
+ if (pEntry->ttl > DNS_MAX_TTL) {
+ pEntry->ttl = DNS_MAX_TTL;
+ }
+ /* read the IP address after answer resource record's header */
+ SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
+ ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
+ LWIP_DEBUGF(DNS_DEBUG, ("\n"));
+ /* call specified callback function if provided */
+ if (pEntry->found) {
+ (*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
+ }
+ /* deallocate memory and return */
+ goto memerr;
+ } else {
+ pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
+ }
+ --nanswers;
+ }
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": error in response\n", pEntry->name));
+ /* call callback to indicate error, clean up memory and return */
+ goto responseerr;
+ }
+ }
+ }
+
+ /* deallocate memory and return */
+ goto memerr;
+
+responseerr:
+ /* ERROR: call specified callback function with NULL as name to indicate an error */
+ if (pEntry->found) {
+ (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
+ }
+ /* flush this entry */
+ pEntry->state = DNS_STATE_UNUSED;
+ pEntry->found = NULL;
+
+memerr:
+ /* free pbuf */
+ pbuf_free(p);
+ return;
+}
+
+/**
+ * Queues a new hostname to resolve and sends out a DNS query for that hostname
+ *
+ * @param name the hostname that is to be queried
+ * @param found a callback founction to be called on success, failure or timeout
+ * @param callback_arg argument to pass to the callback function
+ * @return @return a err_t return code.
+ */
+static err_t
+dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
+{
+ u8_t i;
+ u8_t lseq, lseqi;
+ struct dns_table_entry *pEntry = NULL;
+ size_t namelen;
+
+ /* search an unused entry, or the oldest one */
+ lseq = lseqi = 0;
+ for (i = 0; i < DNS_TABLE_SIZE; ++i) {
+ pEntry = &dns_table[i];
+ /* is it an unused entry ? */
+ if (pEntry->state == DNS_STATE_UNUSED)
+ break;
+
+ /* check if this is the oldest completed entry */
+ if (pEntry->state == DNS_STATE_DONE) {
+ if ((dns_seqno - pEntry->seqno) > lseq) {
+ lseq = dns_seqno - pEntry->seqno;
+ lseqi = i;
+ }
+ }
+ }
+
+ /* if we don't have found an unused entry, use the oldest completed one */
+ if (i == DNS_TABLE_SIZE) {
+ if ((lseqi >= DNS_TABLE_SIZE) || (dns_table[lseqi].state != DNS_STATE_DONE)) {
+ /* no entry can't be used now, table is full */
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": DNS entries table is full\n", name));
+ return ERR_MEM;
+ } else {
+ /* use the oldest completed one */
+ i = lseqi;
+ pEntry = &dns_table[i];
+ }
+ }
+
+ /* use this entry */
+ LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
+
+ /* fill the entry */
+ pEntry->state = DNS_STATE_NEW;
+ pEntry->seqno = dns_seqno++;
+ pEntry->found = found;
+ pEntry->arg = callback_arg;
+ namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
+ MEMCPY(pEntry->name, name, namelen);
+ pEntry->name[namelen] = 0;
+
+ /* force to send query without waiting timer */
+ dns_check_entry(i);
+
+ /* dns query is enqueued */
+ return ERR_INPROGRESS;
+}
+
+/**
+ * Resolve a hostname (string) into an IP address.
+ * NON-BLOCKING callback version for use with raw API!!!
+ *
+ * Returns immediately with one of err_t return codes:
+ * - ERR_OK if hostname is a valid IP address string or the host
+ * name is already in the local names table.
+ * - ERR_INPROGRESS enqueue a request to be sent to the DNS server
+ * for resolution if no errors are present.
+ *
+ * @param hostname the hostname that is to be queried
+ * @param addr pointer to a ip_addr_t where to store the address if it is already
+ * cached in the dns_table (only valid if ERR_OK is returned!)
+ * @param found a callback function to be called on success, failure or timeout (only if
+ * ERR_INPROGRESS is returned!)
+ * @param callback_arg argument to pass to the callback function
+ * @return a err_t return code.
+ */
+err_t
+dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
+ void *callback_arg)
+{
+ u32_t ipaddr;
+ /* not initialized or no valid server yet, or invalid addr pointer
+ * or invalid hostname or invalid hostname length */
+ if ((dns_pcb == NULL) || (addr == NULL) ||
+ (!hostname) || (!hostname[0]) ||
+ (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
+ return ERR_VAL;
+ }
+
+#if LWIP_HAVE_LOOPIF
+ if (strcmp(hostname, "localhost")==0) {
+ ip_addr_set_loopback(addr);
+ return ERR_OK;
+ }
+#endif /* LWIP_HAVE_LOOPIF */
+
+ /* host name already in octet notation? set ip addr and return ERR_OK */
+ ipaddr = ipaddr_addr(hostname);
+ if (ipaddr == IPADDR_NONE) {
+ /* already have this address cached? */
+ ipaddr = dns_lookup(hostname);
+ }
+ if (ipaddr != IPADDR_NONE) {
+ ip4_addr_set_u32(addr, ipaddr);
+ return ERR_OK;
+ }
+
+ /* queue query with specified callback */
+ return dns_enqueue(hostname, found, callback_arg);
+}
+
+#endif /* LWIP_DNS */
--- a/lwip/include/lwip/def.h Fri Jun 18 09:11:35 2010 +0000 +++ b/lwip/include/lwip/def.h Fri Jun 18 15:54:21 2010 +0000 @@ -91,6 +91,8 @@ #endif /* BYTE_ORDER == BIG_ENDIAN */ +#define PP_HTONS htons + #ifdef __cplusplus } #endif
--- a/lwip/include/lwip/dns.h Fri Jun 18 09:11:35 2010 +0000
+++ b/lwip/include/lwip/dns.h Fri Jun 18 15:54:21 2010 +0000
@@ -1,99 +1,116 @@
-/**
- * lwip DNS resolver header file.
-
- * Author: Jim Pettinato
- * April 2007
-
- * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __LWIP_DNS_H__
-#define __LWIP_DNS_H__
-
-#include "lwip/opt.h"
-
-#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
-
-/** DNS timer period */
-#define DNS_TMR_INTERVAL 1000
-
-/** DNS field TYPE used for "Resource Records" */
-#define DNS_RRTYPE_A 1 /* a host address */
-#define DNS_RRTYPE_NS 2 /* an authoritative name server */
-#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */
-#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */
-#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */
-#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */
-#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */
-#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */
-#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */
-#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */
-#define DNS_RRTYPE_WKS 11 /* a well known service description */
-#define DNS_RRTYPE_PTR 12 /* a domain name pointer */
-#define DNS_RRTYPE_HINFO 13 /* host information */
-#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */
-#define DNS_RRTYPE_MX 15 /* mail exchange */
-#define DNS_RRTYPE_TXT 16 /* text strings */
-
-/** DNS field CLASS used for "Resource Records" */
-#define DNS_RRCLASS_IN 1 /* the Internet */
-#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
-#define DNS_RRCLASS_CH 3 /* the CHAOS class */
-#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
-#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
-
-/* The size used for the next line is rather a hack, but it prevents including socket.h in all files
- that include memp.h, and that would possibly break portability (since socket.h defines some types
- and constants possibly already define by the OS).
- Calculation rule:
- sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */
-#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1)
-
-/** Callback which is invoked when a hostname is found.
- * A function of this type must be implemented by the application using the DNS resolver.
- * @param name pointer to the name that was looked up.
- * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname,
- * or NULL if the name could not be found (or on any other error).
- * @param callback_arg a user-specified callback argument passed to dns_gethostbyname
-*/
-typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg);
-
-void dns_init(void);
-void dns_tmr(void);
-void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
-ip_addr_t dns_getserver(u8_t numdns);
-err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
- dns_found_callback found, void *callback_arg);
-
-#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
-int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
-err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
-#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
-
-#endif /* LWIP_DNS */
-
-#endif /* __LWIP_DNS_H__ */
+/**
+ * lwip DNS resolver header file.
+
+ * Author: Jim Pettinato
+ * April 2007
+
+ * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LWIP_DNS_H__
+#define __LWIP_DNS_H__
+
+#include "lwip/opt.h"
+
+#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
+
+/** DNS timer period */
+#define DNS_TMR_INTERVAL 1000
+
+/** DNS field TYPE used for "Resource Records" */
+#define DNS_RRTYPE_A 1 /* a host address */
+#define DNS_RRTYPE_NS 2 /* an authoritative name server */
+#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */
+#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */
+#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */
+#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */
+#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */
+#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */
+#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */
+#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */
+#define DNS_RRTYPE_WKS 11 /* a well known service description */
+#define DNS_RRTYPE_PTR 12 /* a domain name pointer */
+#define DNS_RRTYPE_HINFO 13 /* host information */
+#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */
+#define DNS_RRTYPE_MX 15 /* mail exchange */
+#define DNS_RRTYPE_TXT 16 /* text strings */
+
+/** DNS field CLASS used for "Resource Records" */
+#define DNS_RRCLASS_IN 1 /* the Internet */
+#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
+#define DNS_RRCLASS_CH 3 /* the CHAOS class */
+#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
+#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
+
+/* The size used for the next line is rather a hack, but it prevents including socket.h in all files
+ that include memp.h, and that would possibly break portability (since socket.h defines some types
+ and constants possibly already define by the OS).
+ Calculation rule:
+ sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */
+#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1)
+
+#if DNS_LOCAL_HOSTLIST
+/** struct used for local host-list */
+struct local_hostlist_entry {
+ /** static hostname */
+ const char *name;
+ /** static host address in network byteorder */
+ ip_addr_t addr;
+ struct local_hostlist_entry *next;
+};
+#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
+#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH
+#endif
+#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1))
+#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+#endif /* DNS_LOCAL_HOSTLIST */
+
+/** Callback which is invoked when a hostname is found.
+ * A function of this type must be implemented by the application using the DNS resolver.
+ * @param name pointer to the name that was looked up.
+ * @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname,
+ * or NULL if the name could not be found (or on any other error).
+ * @param callback_arg a user-specified callback argument passed to dns_gethostbyname
+*/
+typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg);
+
+void dns_init(void);
+void dns_tmr(void);
+void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
+ip_addr_t dns_getserver(u8_t numdns);
+err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
+ dns_found_callback found, void *callback_arg);
+
+#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
+int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
+err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
+#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
+
+#endif /* LWIP_DNS */
+
+#endif /* __LWIP_DNS_H__ */
--- a/lwip/lwipopts.h Fri Jun 18 09:11:35 2010 +0000
+++ b/lwip/lwipopts.h Fri Jun 18 15:54:21 2010 +0000
@@ -57,16 +57,16 @@
#define TCPDUMP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
-#define MEM_DEBUG LWIP_DBG_OFF
-#define MEMP_DEBUG LWIP_DBG_OFF
-#define PBUF_DEBUG LWIP_DBG_OFF
+#define MEM_DEBUG LWIP_DBG_ON
+#define MEMP_DEBUG LWIP_DBG_ON
+#define PBUF_DEBUG LWIP_DBG_ON
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
-#define TCPIP_DEBUG LWIP_DBG_ON
+#define TCPIP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define DEMO_DEBUG LWIP_DBG_OFF
-#define IP_DEBUG LWIP_DBG_ON
+#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
@@ -81,6 +81,7 @@
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define ETHARP_DEBUG LWIP_DBG_OFF
+#define DNS_DEBUG LWIP_DBG_OFF
#endif
@@ -108,10 +109,13 @@
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
//#define MEM_SIZE 10240
-#define MEM_SIZE 2000//5000
+
+#if TARGET_LPC1768
+
+
+#define MEM_SIZE 3000 //2000
///
-#if TARGET_LPC1768
#define MEM_POSITION __attribute((section("AHBSRAM0")))
@@ -155,7 +159,7 @@
#define PBUF_POOL_SIZE 8//16//100
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
-#define PBUF_POOL_BUFSIZE 128
+//#define PBUF_POOL_BUFSIZE 128
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
@@ -178,14 +182,14 @@
/* TCP Maximum segment size. */
//#define TCP_MSS 1024
-#define TCP_MSS 0x276//536//0x276
+#define TCP_MSS 1024//536//0x276
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF 2048
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
-#define TCP_SND_QUEUELEN (3 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS)
+#define TCP_SND_QUEUELEN (2 * TCP_SND_BUF/TCP_MSS)
/* TCP writable space (bytes). This must be less than or equal
to TCP_SND_BUF. It is the amount of space which must be
@@ -203,7 +207,7 @@
#elif TARGET_LPC2368
-#define MEM_POSITION
+#define MEM_POSITION __attribute((section("AHBSRAM1")))
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
@@ -220,7 +224,7 @@
#define MEMP_NUM_TCP_PCB 2
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
-#define MEMP_NUM_TCP_PCB_LISTEN 1//4
+#define MEMP_NUM_TCP_PCB_LISTEN 2//4
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 8
@@ -242,10 +246,10 @@
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
-#define PBUF_POOL_SIZE 4//16//100
+#define PBUF_POOL_SIZE 8//16//100
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
-#define PBUF_POOL_BUFSIZE 128
+//#define PBUF_POOL_BUFSIZE 128
/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
link level header. */
@@ -268,14 +272,14 @@
/* TCP Maximum segment size. */
//#define TCP_MSS 1024
-#define TCP_MSS 0x276//536//0x276
+#define TCP_MSS 512//0x276//536//0x276
/* TCP sender buffer space (bytes). */
-#define TCP_SND_BUF 1024
+#define TCP_SND_BUF 1024//2048
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
-#define TCP_SND_QUEUELEN (3 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS)
+#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS)//(4 * TCP_SND_BUF/TCP_MSS)
/* TCP writable space (bytes). This must be less than or equal
to TCP_SND_BUF. It is the amount of space which must be
@@ -283,7 +287,7 @@
#define TCP_SNDLOWAT (TCP_SND_BUF/2)
/* TCP receive window. */
-#define TCP_WND 1024 //8096
+#define TCP_WND 512 //8096
/* Maximum number of retransmissions of data segments. */
//#define TCP_MAXRTX 12
@@ -327,7 +331,9 @@
#define DHCP_DOES_ARP_CHECK (LWIP_DHCP)
/* ---------- AUTOIP options ------- */
-#define LWIP_AUTOIP 0
+#define LWIP_AUTOIP (LWIP_DHCP)
+#define LWIP_DHCP_AUTOIP_COOP (LWIP_AUTOIP)
+#define LWIP_DHCP_AUTOIP_COOP_TRIES 3
/* ---------- SNMP options ---------- */
/** @todo SNMP is experimental for now
--- a/main.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/main.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -18,9 +18,5 @@
printf("Entering while loop Net::poll()ing\r\n");
while (1) {
Net::poll();
- myled = 1;
- wait(0.2);
- myled = 0;
- wait(0.2);
}
}
--- a/netCfg.h Fri Jun 18 09:11:35 2010 +0000 +++ b/netCfg.h Fri Jun 18 15:54:21 2010 +0000 @@ -1,12 +1,12 @@ #ifndef NET_CFG_H #define NET_TELIT_STACK 0 -#define NET_GPRS 1 -#define NET_PPP 1 +#define NET_GPRS 0 +#define NET_PPP 0 #define NET_ZG2100 0 #define NET_ETH 1 #define NET_USB_SERIAL 0 -#define NET_TELIT 1 -#define NET_CFG_H 1 -#define NET_USB 1 +#define NET_TELIT 0 +#define NET_CFG_H 0 +#define NET_USB 0 #define NET_LWIP_STACK 1 #endif
--- a/services/http/client/HTTPClient.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/services/http/client/HTTPClient.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -144,7 +144,7 @@
void HTTPClient::setTimeout(int ms)
{
- m_timeout = 1000*ms;
+ m_timeout = ms;
//resetTimeout();
}
@@ -154,7 +154,7 @@
{
return;
}
- if(m_watchdog.read_us()>m_timeout)
+ if(m_watchdog.read_ms()>m_timeout)
{
onTimeout();
}
@@ -396,6 +396,9 @@
onResult(HTTP_CONN);
return;
}
+
+ if(len>0)
+ resetTimeout();
if(m_state == HTTP_READ_DATA_INCOMPLETE)
return;
--- a/services/http/server/HTTPRequestDispatcher.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/services/http/server/HTTPRequestDispatcher.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -41,14 +41,13 @@
void HTTPRequestDispatcher::dispatchRequest()
{
- string rootPath;
- string subPath;
+ string path;
string meth;
HTTP_METH methCode;
- DBG("\r\nDispatching req\r\n");
+ DBG("Dispatching req\r\n");
- if( !getRequest(&rootPath, &subPath, &meth ) )
+ if( !getRequest(&path, &meth ) )
{
close();
return; //Invalid request
@@ -72,23 +71,47 @@
return;
}
- DBG("\r\nLooking for a handler\r\n");
+ DBG("Looking for a handler\r\n");
map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*) >::iterator it;
- it = m_pSvr->m_lpHandlers.find(rootPath); //We are friends so we can do that
- if(it == m_pSvr->m_lpHandlers.end())
+// it = m_pSvr->m_lpHandlers.find(rootPath); //We are friends so we can do that
+// NEW CODE START:
+ int root_len = 0;
+ for (it = m_pSvr->m_lpHandlers.begin(); it != m_pSvr->m_lpHandlers.end(); it++)
{
- it = m_pSvr->m_lpHandlers.find(""); //Use default handler if it exists
+ DBG("Checking %s...\n", (*it).first.c_str());
+ root_len = (*it).first.length();
+ if ( root_len &&
+ !path.compare( 0, root_len, (*it).first ) &&
+ (path[root_len] == '/' || path[root_len] == '\0'))
+ {
+ DBG("Found (%s)\n", (*it).first.c_str());
+ // Found!
+ break; // for
+ }
+ }
+// NEW CODE END
+ if((it == m_pSvr->m_lpHandlers.end()) && !(m_pSvr->m_lpHandlers.empty()))
+ {
+ DBG("Using default handler\n");
+ it = m_pSvr->m_lpHandlers.end();
+ it--; //Get the last element
+ if( ! (((*it).first.length() == 0) || !(*it).first.compare("/")) ) //This is not the default handler
+ it = m_pSvr->m_lpHandlers.end();
+ root_len = 0;
}
if(it == m_pSvr->m_lpHandlers.end())
{
+ DBG("No handler found\n");
close(); //No handler found
return;
}
- DBG("\r\nHandler found.\r\n");
+ DBG("Handler found.\r\n");
- HTTPRequestHandler* pHdlr = (*it).second(rootPath.c_str(), subPath.c_str(), m_pTCPSocket);
+//HTTPRequestHandler* pHdlr = (*it).second(rootPath.c_str(), subPath.c_str(), m_pTCPSocket);
+//NEW CODE 1 LINE:
+ HTTPRequestHandler* pHdlr = (*it).second((*it).first.c_str(), path.c_str() + root_len, m_pTCPSocket);
m_pTCPSocket = NULL; //We don't own it anymore
switch(methCode)
@@ -104,7 +127,7 @@
break;
}
- DBG("\r\nReq handled (or being handled)\r\n");
+ DBG("Req handled (or being handled)\r\n");
close();
}
@@ -129,7 +152,7 @@
close();
}
-bool HTTPRequestDispatcher::getRequest(string* rootPath, string* subPath, string* meth)
+bool HTTPRequestDispatcher::getRequest(string* path, string* meth)
{
char req[128];
char c_path[128];
@@ -162,40 +185,18 @@
}
*p = 0;
- DBG("\r\nParsing request : %s\r\n", req);
+ DBG("Parsing request : %s\r\n", req);
ret = sscanf(req, "%s %s HTTP/%*d.%*d", c_meth, c_path);
if(ret !=2)
return false;
*meth = string(c_meth);
- *subPath = string(c_path);
-
- c_path[0]= '/';
- if(!strchr(c_path+1, '/'))
- {
- //Not found, so this is the root path
- c_path[1]=0;
- *rootPath = string(c_path);
- }
- else
- {
- ret = sscanf(req, "%*s /%[^/ ]/%*s HTTP/%*d.%*d", c_path+1);
- if(ret !=1)
- {
- //This is the root path
- DBG("Default path\n");
- }
- *rootPath = string(c_path);
- subPath->erase(0,rootPath->length());
- }
-
-
- DBG("\r\nParse OK :\r\nRoot Path: %s\r\nSub Path: %s\r\nMethod: %s\r\n", rootPath->c_str(), subPath->c_str(), meth->c_str());
-
+// NEW CODE (old code removed):
+ *path = string(c_path);
return true;
+}
-}
void HTTPRequestDispatcher::onTCPSocketEvent(TCPSocketEvent e)
--- a/services/http/server/HTTPRequestDispatcher.h Fri Jun 18 09:11:35 2010 +0000 +++ b/services/http/server/HTTPRequestDispatcher.h Fri Jun 18 15:54:21 2010 +0000 @@ -26,7 +26,6 @@ class HTTPServer; -#include "if/net/net.h" #include "api/TCPSocket.h" #include "HTTPServer.h" @@ -60,7 +59,7 @@ void onTimeout(); //Connection has timed out - bool getRequest(string* rootPath, string* subPath, string* meth); + bool getRequest(string* path, string* meth); HTTPServer* m_pSvr; TCPSocket* m_pTCPSocket;
--- a/services/http/server/HTTPRequestHandler.h Fri Jun 18 09:11:35 2010 +0000 +++ b/services/http/server/HTTPRequestHandler.h Fri Jun 18 15:54:21 2010 +0000 @@ -24,7 +24,6 @@ #ifndef HTTP_REQUEST_HANDLER_H #define HTTP_REQUEST_HANDLER_H -#include "if/net/net.h" #include "api/TCPSocket.h" //#include "HTTPServer.h"
--- a/services/http/server/HTTPServer.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/services/http/server/HTTPServer.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -49,6 +49,7 @@
void HTTPServer::addHandler(const char* path)
{
m_lpHandlers[path] = &T::inst;
+
}
#endif
--- a/services/http/server/HTTPServer.h Fri Jun 18 09:11:35 2010 +0000
+++ b/services/http/server/HTTPServer.h Fri Jun 18 15:54:21 2010 +0000
@@ -42,6 +42,20 @@
public:
HTTPServer();
~HTTPServer();
+
+ struct handlersComp //Used to order handlers in the right way
+ {
+ bool operator() (const string& handler1, const string& handler2) const
+ {
+ //The first handler is longer than the second one
+ if (handler1.length() > handler2.length())
+ return true; //Returns true if handler1 is to appear before handler2
+ else if (handler1.length() < handler2.length())
+ return false;
+ else //To avoid the == case, sort now by address
+ return ((&handler1)>(&handler2));
+ }
+ };
template<typename T>
void addHandler(const char* path) //Template decl in header
@@ -55,7 +69,7 @@
void onTCPSocketEvent(TCPSocketEvent e);
TCPSocket* m_pTCPSocket;
- map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*) > m_lpHandlers;
+ map< string, HTTPRequestHandler*(*)(const char*, const char*, TCPSocket*), handlersComp > m_lpHandlers;
};
--- a/services/http/server/impl/FSHandler.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/services/http/server/impl/FSHandler.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -26,7 +26,9 @@
//#define __DEBUG
#include "dbg/dbg.h"
-#define CHUNK_SIZE 512//128
+#define CHUNK_SIZE 128
+
+#define DEFAULT_PAGE "/index.htm"
FSHandler::FSHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : HTTPRequestHandler(rootPath, path, pTCPSocket), m_err404(false)
{}
@@ -48,9 +50,23 @@
void FSHandler::doGet()
{
- DBG("\r\nIn FSHandler::doGet()\r\n");
+ DBG("\r\nIn FSHandler::doGet() - rootPath=%s, path=%s\r\n", rootPath().c_str(), path().c_str());
//FIXME: Translate path to local/path
- string filePath = m_lFsPath[rootPath()] + path();
+ string checkedRootPath = rootPath();
+ if(checkedRootPath.empty())
+ checkedRootPath="/";
+ string filePath = m_lFsPath[checkedRootPath];
+ if (path().size() > 1)
+ {
+ filePath += path();
+ }
+ else
+ {
+ filePath += DEFAULT_PAGE;
+ }
+
+ DBG("Trying to open %s\n", filePath.c_str());
+
m_fp = fopen(filePath.c_str(), "r"); //FIXME: if null, error 404
if(!m_fp)
@@ -62,7 +78,7 @@
respHeaders()["Content-Type"] = "text/html";
respHeaders()["Connection"] = "close";
writeData(msg,strlen(msg)); //Only send header
- DBG("\r\nExit SimpleHandler::doGet() w Error 404\r\n");
+ DBG("\r\nExit FSHandler::doGet() w Error 404\r\n");
return;
}
@@ -102,14 +118,38 @@
}
static char rBuf[CHUNK_SIZE];
- int len = fread(rBuf, 1, CHUNK_SIZE, m_fp);
- if(len>0)
+ while(true)
{
- writeData(rBuf, len);
- }
- else
- {
- close(); //Data written, we can close the connection
+ int len = fread(rBuf, 1, CHUNK_SIZE, m_fp);
+ if(len>0)
+ {
+ int writtenLen = writeData(rBuf, len);
+ if(writtenLen < 0) //Socket error
+ {
+ DBG("FSHandler: Socket error %d\n", writtenLen);
+ if(writtenLen == TCPSOCKET_MEM)
+ {
+ fseek(m_fp, -len, SEEK_CUR);
+ return; //Wait for the queued TCP segments to be transmitted
+ }
+ else
+ {
+ //This is a critical error
+ close();
+ return;
+ }
+ }
+ else if(writtenLen < len) //Short write, socket's buffer is full
+ {
+ fseek(m_fp, writtenLen - len, SEEK_CUR);
+ return;
+ }
+ }
+ else
+ {
+ close(); //Data written, we can close the connection
+ return;
+ }
}
}
--- a/services/ntp/NTPClient.cpp Fri Jun 18 09:11:35 2010 +0000
+++ b/services/ntp/NTPClient.cpp Fri Jun 18 15:54:21 2010 +0000
@@ -29,7 +29,7 @@
#include "dbg/dbg.h"
#define NTP_PORT 123
-#define NTP_CLIENT_PORT 50420
+#define NTP_CLIENT_PORT 0//50420 //Random port
#define NTP_REQUEST_TIMEOUT 15000
#define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
@@ -42,7 +42,7 @@
| (( x >> 24 ) & 0x000000FF) )
#define ntohl( x ) (htonl(x))
-NTPClient::NTPClient() : m_state(NTP_PING), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL),
+NTPClient::NTPClient() : NetService(false), m_state(NTP_PING), m_pCbItem(NULL), m_pCbMeth(NULL), m_pCb(NULL),
m_watchdog(), m_timeout(0), m_closed(true), m_host(), m_pDnsReq(NULL), m_blockingResult(NTP_PROCESSING)
{
setTimeout(NTP_REQUEST_TIMEOUT);
@@ -68,7 +68,7 @@
return NTP_PROCESSING;
}
-#ifdef __LINKER_BUG_SOLVED__
+#if 0 //For doc only
template<class T>
NTPResult NTPClient::setTime(const Host& host, T* pItem, void (T::*pMethod)(NTPResult)) //Non blocking
{
@@ -81,7 +81,12 @@
void NTPClient::doSetTime(const Host& host)
{
init();
+ resetTimeout();
m_host = host;
+ if(!m_host.getPort())
+ {
+ m_host.setPort(NTP_PORT);
+ }
if(m_host.getIp().isNull())
{
//DNS query required
@@ -91,16 +96,7 @@
m_pDnsReq->resolve(&m_host);
return;
}
- if(!m_host.getPort())
- {
- m_host.setPort(NTP_PORT);
- }
-
- m_state = NTP_PING;
- Host localhost(IpAddr(127,0,0,1), NTP_CLIENT_PORT, "localhost");
- m_pUDPSocket->bind(localhost);
- set_time( 1280000000 ); //End of July 2010... just there to limit offset range
- process();
+ open();
}
void NTPClient::setOnResult( void (*pMethod)(NTPResult) )
@@ -108,22 +104,12 @@
m_pCb = pMethod;
}
-void NTPClient::init() //Create and setup socket if needed
-{
- if(!m_closed) //Already opened
- return;
- m_state = NTP_PING;
- m_pUDPSocket = new UDPSocket;
- m_pUDPSocket->setOnEvent(this, &NTPClient::onUDPSocketEvent);
- m_closed = false;
-}
-
void NTPClient::close()
{
if(m_closed)
return;
m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
- m_watchdog.detach();
+ m_watchdog.stop();
m_pUDPSocket->resetOnEvent();
m_pUDPSocket->close();
delete m_pUDPSocket;
@@ -135,45 +121,74 @@
}
}
+void NTPClient::poll() //Called by NetServices
+{
+ if( (!m_closed) && (m_watchdog.read_ms() >= m_timeout) )
+ {
+ onTimeout();
+ }
+}
+
+void NTPClient::init() //Create and setup socket if needed
+{
+ if(!m_closed) //Already opened
+ return;
+ m_state = NTP_PING;
+ m_pUDPSocket = new UDPSocket;
+ m_pUDPSocket->setOnEvent(this, &NTPClient::onUDPSocketEvent);
+ m_closed = false;
+ DBG("NTPClient: Init OK\n");
+}
+
+void NTPClient::open()
+{
+ resetTimeout();
+ DBG("Opening connection\n");
+ m_state = NTP_PING;
+ Host localhost(IpAddr(127,0,0,1), NTP_CLIENT_PORT, "localhost");
+ m_pUDPSocket->bind(localhost);
+ set_time( 1280000000 ); //End of July 2010... just there to limit offset range
+ process();
+}
+
#define MIN(a,b) ((a)<(b))?(a):(b)
void NTPClient::process() //Main state-machine
{
- NTPPacket pkt;
int len;
Host host;
-
+
switch(m_state)
{
case NTP_PING:
DBG("\r\nPing\r\n");
//Prepare NTP Packet:
- pkt.li = 0; //Leap Indicator : No warning
- pkt.vn = 4; //Version Number : 4
- pkt.mode = 3; //Client mode
- pkt.stratum = 0; //Not relevant here
- pkt.poll = 0; //Not significant as well
- pkt.precision = 0; //Neither this one is
+ m_pkt.li = 0; //Leap Indicator : No warning
+ m_pkt.vn = 4; //Version Number : 4
+ m_pkt.mode = 3; //Client mode
+ m_pkt.stratum = 0; //Not relevant here
+ m_pkt.poll = 0; //Not significant as well
+ m_pkt.precision = 0; //Neither this one is
- pkt.rootDelay = 0; //Or this one
- pkt.rootDispersion = 0; //Or that one
- pkt.refId = 0; //...
+ m_pkt.rootDelay = 0; //Or this one
+ m_pkt.rootDispersion = 0; //Or that one
+ m_pkt.refId = 0; //...
- pkt.refTm_s = 0;
- pkt.origTm_s = 0;
- pkt.rxTm_s = 0;
- pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
+ m_pkt.refTm_s = 0;
+ m_pkt.origTm_s = 0;
+ m_pkt.rxTm_s = 0;
+ m_pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
- pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
+ m_pkt.refTm_f = m_pkt.origTm_f = m_pkt.rxTm_f = m_pkt.txTm_f = 0;
//Hex Dump:
DBG("\r\nDump Tx:\r\n");
for(int i = 0; i< sizeof(NTPPacket); i++)
{
- DBG("%02x ", *((char*)&pkt + i));
+ DBG("%02x ", *((char*)&m_pkt + i));
}
DBG("\r\n\r\n");
- len = m_pUDPSocket->sendto( (char*)&pkt, sizeof(NTPPacket), &m_host );
+ len = m_pUDPSocket->sendto( (char*)&m_pkt, sizeof(NTPPacket), &m_host );
if(len < sizeof(NTPPacket))
{ onResult(NTP_PRTCL); close(); return; }
@@ -183,12 +198,11 @@
case NTP_PONG:
DBG("\r\nPong\r\n");
- while( len = m_pUDPSocket->recvfrom( (char*)&pkt, sizeof(NTPPacket), &host ) )
+ while( len = m_pUDPSocket->recvfrom( (char*)&m_pkt, sizeof(NTPPacket), &host ) )
{
if( len <= 0 )
break;
if( !host.getIp().isEq(m_host.getIp()) )
- //if( !ip_addr_cmp( &host.getIp().getStruct(), &m_host.getIp().getStruct() ) ) //Was working like that, trying nicer impl above
continue; //Not our packet
if( len > 0 )
break;
@@ -207,33 +221,33 @@
DBG("\r\nDump Rx:\r\n");
for(int i = 0; i< sizeof(NTPPacket); i++)
{
- DBG("%02x ", *((char*)&pkt + i));
+ DBG("%02x ", *((char*)&m_pkt + i));
}
DBG("\r\n\r\n");
- if( pkt.stratum == 0) //Kiss of death message : Not good !
+ if( m_pkt.stratum == 0) //Kiss of death message : Not good !
{
onResult(NTP_PRTCL); close(); return;
}
//Correct Endianness
- pkt.refTm_s = ntohl( pkt.refTm_s );
- pkt.refTm_f = ntohl( pkt.refTm_f );
- pkt.origTm_s = ntohl( pkt.origTm_s );
- pkt.origTm_f = ntohl( pkt.origTm_f );
- pkt.rxTm_s = ntohl( pkt.rxTm_s );
- pkt.rxTm_f = ntohl( pkt.rxTm_f );
- pkt.txTm_s = ntohl( pkt.txTm_s );
- pkt.txTm_f = ntohl( pkt.txTm_f );
+ m_pkt.refTm_s = ntohl( m_pkt.refTm_s );
+ m_pkt.refTm_f = ntohl( m_pkt.refTm_f );
+ m_pkt.origTm_s = ntohl( m_pkt.origTm_s );
+ m_pkt.origTm_f = ntohl( m_pkt.origTm_f );
+ m_pkt.rxTm_s = ntohl( m_pkt.rxTm_s );
+ m_pkt.rxTm_f = ntohl( m_pkt.rxTm_f );
+ m_pkt.txTm_s = ntohl( m_pkt.txTm_s );
+ m_pkt.txTm_f = ntohl( m_pkt.txTm_f );
//Compute offset, see RFC 4330 p.13
uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
- //int32_t origTm = (int32_t) ((uint64_t) pkt.origTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
- //int32_t rxTm = (int32_t) ((uint64_t) pkt.rxTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
- //int32_t txTm = (int32_t) ((uint64_t) pkt.txTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
- // int64_t offset = ( ( ( pkt.rxTm_s - pkt.origTm_s ) + ( pkt.txTm_s - destTm_s ) ) << 32 + ( ( pkt.rxTm_f - pkt.origTm_f ) + ( pkt.txTm_f - 0 ) ) ) / 2;
- int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
- DBG("\r\nSent @%d\r\n", pkt.txTm_s);
+ //int32_t origTm = (int32_t) ((uint64_t) m_pkt.origTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
+ //int32_t rxTm = (int32_t) ((uint64_t) m_pkt.rxTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
+ //int32_t txTm = (int32_t) ((uint64_t) m_pkt.txTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
+ // int64_t offset = ( ( ( m_pkt.rxTm_s - m_pkt.origTm_s ) + ( m_pkt.txTm_s - destTm_s ) ) << 32 + ( ( m_pkt.rxTm_f - m_pkt.origTm_f ) + ( m_pkt.txTm_f - 0 ) ) ) / 2;
+ int64_t offset = ( (int64_t)( m_pkt.rxTm_s - m_pkt.origTm_s ) + (int64_t) ( m_pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
+ DBG("\r\nSent @%d\r\n", m_pkt.txTm_s);
DBG("\r\nOffset: %d\r\n", offset);
//Set time accordingly
set_time( time(NULL) + (offset /*>> 32*/) );
@@ -247,14 +261,13 @@
void NTPClient::setTimeout(int ms)
{
- m_timeout = 1000*ms;
- resetTimeout();
+ m_timeout = ms;
}
void NTPClient::resetTimeout()
{
- m_watchdog.detach();
- m_watchdog.attach_us<NTPClient>(this, &NTPClient::onTimeout, m_timeout);
+ m_watchdog.reset();
+ m_watchdog.start();
}
void NTPClient::onTimeout() //Connection has timed out
@@ -278,14 +291,16 @@
close();
return;
}
+ DBG("\r\nDNS resolved.\r\n");
m_pDnsReq->close();
delete m_pDnsReq;
m_pDnsReq=NULL;
- doSetTime(m_host);
+ open();
}
void NTPClient::onUDPSocketEvent(UDPSocketEvent e)
{
+ resetTimeout();
switch(e)
{
case UDPSOCKET_READABLE: //The only event for now
--- a/services/ntp/NTPClient.h Fri Jun 18 09:11:35 2010 +0000
+++ b/services/ntp/NTPClient.h Fri Jun 18 15:54:21 2010 +0000
@@ -38,7 +38,7 @@
NTP_DNS //Could not resolve DNS Addr
};
-class NTPClient
+class NTPClient : protected NetService
{
public:
NTPClient();
@@ -66,10 +66,15 @@
m_pCbMeth = (void (CDummy::*)(NTPResult)) pMethod;
}
- void init();
void close();
+protected:
+ virtual void poll(); //Called by NetServices
+
private:
+ void init();
+ void open();
+
__packed struct NTPPacket //See RFC 4330 for Simple NTP
{
//WARN: We are in LE! Network is BE!
@@ -119,12 +124,14 @@
NTPStep m_state;
+ NTPPacket m_pkt;
+
CDummy* m_pCbItem;
void (CDummy::*m_pCbMeth)(NTPResult);
void (*m_pCb)(NTPResult);
- Timeout m_watchdog;
+ Timer m_watchdog;
int m_timeout;
bool m_closed;