First step: AutoIP compiled in and working

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
darran
Date:
Fri Jun 18 15:54:21 2010 +0000
Parent:
0:55a05330f8cc
Commit message:

Changed in this revision

api/DNSRequest.cpp Show annotated file Show diff for this revision Revisions of this file
api/TCPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
api/UDPSocket.cpp Show annotated file Show diff for this revision Revisions of this file
dbg/dbg.cpp Show annotated file Show diff for this revision Revisions of this file
dbg/dbg.h Show annotated file Show diff for this revision Revisions of this file
drv/gprs/GPRSModem.cpp Show annotated file Show diff for this revision Revisions of this file
drv/serial/usb/usbserialif.cpp Show annotated file Show diff for this revision Revisions of this file
if/eth/EthernetNetIf.cpp Show annotated file Show diff for this revision Revisions of this file
if/eth/EthernetNetIf.h Show annotated file Show diff for this revision Revisions of this file
if/lwip/LwipNetIf.cpp Show annotated file Show diff for this revision Revisions of this file
if/lwip/LwipNetIf.h Show annotated file Show diff for this revision Revisions of this file
if/lwip/lwipNetDnsRequest.cpp Show annotated file Show diff for this revision Revisions of this file
if/lwip/lwipNetDnsRequest.h Show annotated file Show diff for this revision Revisions of this file
if/lwip/lwipNetTcpSocket.cpp Show annotated file Show diff for this revision Revisions of this file
if/lwip/lwipNetUdpSocket.cpp Show annotated file Show diff for this revision Revisions of this file
if/net/net.cpp Show annotated file Show diff for this revision Revisions of this file
if/net/netservice.cpp Show annotated file Show diff for this revision Revisions of this file
if/net/netudpsocket.cpp Show annotated file Show diff for this revision Revisions of this file
lwip/core/dns.c Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/def.h Show annotated file Show diff for this revision Revisions of this file
lwip/include/lwip/dns.h Show annotated file Show diff for this revision Revisions of this file
lwip/lwipopts.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
netCfg.h Show annotated file Show diff for this revision Revisions of this file
services/http/client/HTTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
services/http/server/HTTPRequestDispatcher.cpp Show annotated file Show diff for this revision Revisions of this file
services/http/server/HTTPRequestDispatcher.h Show annotated file Show diff for this revision Revisions of this file
services/http/server/HTTPRequestHandler.h Show annotated file Show diff for this revision Revisions of this file
services/http/server/HTTPServer.cpp Show annotated file Show diff for this revision Revisions of this file
services/http/server/HTTPServer.h Show annotated file Show diff for this revision Revisions of this file
services/http/server/impl/FSHandler.cpp Show annotated file Show diff for this revision Revisions of this file
services/ntp/NTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
services/ntp/NTPClient.h Show annotated file Show diff for this revision Revisions of this file
diff -r 55a05330f8cc -r 4218cacaf696 api/DNSRequest.cpp
--- 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) )
 {
diff -r 55a05330f8cc -r 4218cacaf696 api/TCPSocket.cpp
--- 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);
 }
diff -r 55a05330f8cc -r 4218cacaf696 api/UDPSocket.cpp
--- 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)
 {
 
 }
diff -r 55a05330f8cc -r 4218cacaf696 dbg/dbg.cpp
--- 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, ...)
 {
diff -r 55a05330f8cc -r 4218cacaf696 dbg/dbg.h
--- 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
diff -r 55a05330f8cc -r 4218cacaf696 drv/gprs/GPRSModem.cpp
--- 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.
diff -r 55a05330f8cc -r 4218cacaf696 drv/serial/usb/usbserialif.cpp
--- 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 {
diff -r 55a05330f8cc -r 4218cacaf696 if/eth/EthernetNetIf.cpp
--- 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(&etharp_tmr,  ARP_TMR_INTERVAL  * 1000); // = 5s in etharp.h
+  //m_ethArpTicker.attach_us(&etharp_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();
 }
diff -r 55a05330f8cc -r 4218cacaf696 if/eth/EthernetNetIf.h
--- 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;
 
diff -r 55a05330f8cc -r 4218cacaf696 if/lwip/LwipNetIf.cpp
--- 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...
 }
 
diff -r 55a05330f8cc -r 4218cacaf696 if/lwip/LwipNetIf.h
--- 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;
 
diff -r 55a05330f8cc -r 4218cacaf696 if/lwip/lwipNetDnsRequest.cpp
--- 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 );
 }
diff -r 55a05330f8cc -r 4218cacaf696 if/lwip/lwipNetDnsRequest.h
--- 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
diff -r 55a05330f8cc -r 4218cacaf696 if/lwip/lwipNetTcpSocket.cpp
--- 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)
 {
diff -r 55a05330f8cc -r 4218cacaf696 if/lwip/lwipNetUdpSocket.cpp
--- 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();
 }
 
diff -r 55a05330f8cc -r 4218cacaf696 if/net/net.cpp
--- 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;
 
diff -r 55a05330f8cc -r 4218cacaf696 if/net/netservice.cpp
--- 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;
 }
 
diff -r 55a05330f8cc -r 4218cacaf696 if/net/netudpsocket.cpp
--- 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;
diff -r 55a05330f8cc -r 4218cacaf696 lwip/core/dns.c
--- 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 */
diff -r 55a05330f8cc -r 4218cacaf696 lwip/include/lwip/def.h
--- 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
diff -r 55a05330f8cc -r 4218cacaf696 lwip/include/lwip/dns.h
--- 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__ */
diff -r 55a05330f8cc -r 4218cacaf696 lwip/lwipopts.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
diff -r 55a05330f8cc -r 4218cacaf696 main.cpp
--- 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);
     }
 }
diff -r 55a05330f8cc -r 4218cacaf696 netCfg.h
--- 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
diff -r 55a05330f8cc -r 4218cacaf696 services/http/client/HTTPClient.cpp
--- 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;
diff -r 55a05330f8cc -r 4218cacaf696 services/http/server/HTTPRequestDispatcher.cpp
--- 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)
diff -r 55a05330f8cc -r 4218cacaf696 services/http/server/HTTPRequestDispatcher.h
--- 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;
diff -r 55a05330f8cc -r 4218cacaf696 services/http/server/HTTPRequestHandler.h
--- 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"
 
diff -r 55a05330f8cc -r 4218cacaf696 services/http/server/HTTPServer.cpp
--- 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
   
diff -r 55a05330f8cc -r 4218cacaf696 services/http/server/HTTPServer.h
--- 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;
 
 };
 
diff -r 55a05330f8cc -r 4218cacaf696 services/http/server/impl/FSHandler.cpp
--- 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;
+    }
   }
 }
 
diff -r 55a05330f8cc -r 4218cacaf696 services/ntp/NTPClient.cpp
--- 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
diff -r 55a05330f8cc -r 4218cacaf696 services/ntp/NTPClient.h
--- 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;