Browse Source

Upgraded LWIP to 1.4.0 released from Espressif.

Plus directly provided patch for user_interface.h.
Johny Mattsson 8 years ago
parent
commit
5d5be35633

+ 4 - 1
app/include/lwip/app/dhcpserver.h

@@ -24,6 +24,7 @@ typedef struct dhcps_msg {
 
 #ifndef LWIP_OPEN_SRC
 struct dhcps_lease {
+	bool enable;
 	struct ip_addr start_ip;
 	struct ip_addr end_ip;
 };
@@ -46,7 +47,8 @@ typedef struct _list_node{
 	struct _list_node *pnext;
 }list_node;
 
-#define DHCPS_LEASE_TIMER 0x05A0
+extern uint32 dhcps_lease_time;
+#define DHCPS_LEASE_TIMER  dhcps_lease_time  //0x05A0
 #define DHCPS_MAX_LEASE 0x64
 #define BOOTP_BROADCAST 0x8000
 
@@ -89,6 +91,7 @@ typedef struct _list_node{
 #define DHCPS_STATE_ACK 3
 #define DHCPS_STATE_NAK 4
 #define DHCPS_STATE_IDLE 5
+#define DHCPS_STATE_RELEASE 6
 
 #define   dhcps_router_enabled(offer)	((offer & OFFER_ROUTER) != 0)
 

+ 2 - 1
app/include/lwip/app/espconn.h

@@ -30,6 +30,7 @@ typedef void (* espconn_reconnect_callback)(void *arg, sint8 err);
 #define ESPCONN_CONN       -11   /* Not connected.           */
 
 #define ESPCONN_ARG        -12   /* Illegal argument.        */
+#define ESPCONN_IF		   -14	 /* Low_level error			 */
 #define ESPCONN_ISCONN     -15   /* Already connected.       */
 
 #define ESPCONN_HANDSHAKE  -28   /* ssl handshake failed	 */
@@ -168,7 +169,7 @@ typedef struct _espconn_msg{
 	struct espconn *pespconn;
 	comon_pkt pcommon;
 	uint8 count_opt;
-	sint16_t hs_status;	//the status of the handshake
+	int16_t hs_status;	//the status of the handshake
 	void *preverse;
 	void *pssl;
 	struct _espconn_msg *pnext;

+ 13 - 0
app/include/lwip/app/espconn_udp.h

@@ -45,6 +45,19 @@ extern sint8 espconn_udp_server(struct espconn *espconn);
 
 extern err_t espconn_udp_sent(void *arg, uint8 *psent, uint16 length);
 
+/******************************************************************************
+ * FunctionName : espconn_udp_sendto
+ * Description  : sent data for UDP
+ * Parameters   : void *arg -- UDP to send
+ * 				  uint8* psent -- Data to send
+ *                uint16 length -- Length of data to send
+ * Returns      : return espconn error code.
+ * - ESPCONN_OK. Successful. No error occured.
+ * - ESPCONN_MEM. Out of memory.
+ * - ESPCONN_RTE. Could not find route to destination address.
+ * - More errors could be returned by lower protocol layers.
+*******************************************************************************/
+extern err_t espconn_udp_sendto(void *arg, uint8 *psent, uint16 length);
 
 #endif /* __ESPCONN_UDP_H__ */
 

+ 24 - 1
app/include/lwip/mem.h

@@ -33,7 +33,7 @@
 #define __LWIP_MEM_H__
 
 #include "lwip/opt.h"
-#include "mem_manager.h"
+//#include "mem_manager.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -50,6 +50,7 @@ typedef size_t mem_size_t;
 /* in case C library malloc() needs extra protection,
  * allow these defines to be overridden.
  */
+#ifndef MEMLEAK_DEBUG
 #ifndef mem_free
 #define mem_free vPortFree
 #endif
@@ -64,6 +65,28 @@ typedef size_t mem_size_t;
 #endif
 #ifndef mem_zalloc
 #define mem_zalloc pvPortZalloc
+#endif
+#else
+#ifndef mem_free
+#define mem_free(s) \
+do{\
+	const char *file = mem_debug_file;\
+    vPortFree(s, file, __LINE__);\
+}while(0)
+#endif
+#ifndef mem_malloc
+#define mem_malloc(s) ({const char *file = mem_debug_file; pvPortMalloc(s, file, __LINE__);})
+#endif
+#ifndef mem_calloc
+#define mem_calloc(s) ({const char *file = mem_debug_file; pvPortCalloc(s, file, __LINE__);})
+#endif
+#ifndef mem_realloc
+#define mem_realloc(p, s) ({const char *file = mem_debug_file; pvPortRealloc(p, s, file, __LINE__);})
+#endif
+#ifndef mem_zalloc
+#define mem_zalloc(s) ({const char *file = mem_debug_file; pvPortZalloc(s, file, __LINE__);})
+#endif
+
 #endif
 
 #ifndef os_malloc

+ 4 - 1
app/include/lwip/netif.h

@@ -130,6 +130,9 @@ typedef void (*netif_status_callback_fn)(struct netif *netif);
 typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
        ip_addr_t *group, u8_t action);
 
+/*add DHCP event processing by LiuHan*/
+typedef void (*dhcp_event_fn)(void);
+
 /** Generic data structure used for all lwIP network interfaces.
  *  The following fields should be filled in by the initialization
  *  function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
@@ -170,7 +173,7 @@ struct netif {
   /** the DHCP client state information for this netif */
   struct dhcp *dhcp;
   struct udp_pcb *dhcps_pcb;	//dhcps
-  void *pad;
+  dhcp_event_fn dhcp_event;
 #endif /* LWIP_DHCP */
 #if LWIP_AUTOIP
   /** the AutoIP client state information for this netif */

+ 2 - 2
app/include/lwip/sys.h

@@ -281,8 +281,8 @@ void sys_arch_unprotect(sys_prot_t pval)ICACHE_FLASH_ATTR;
 #else
 
 #define SYS_ARCH_DECL_PROTECT(lev)
-#define SYS_ARCH_PROTECT(lev) lev = ets_intr_lock()	//fix by ives at 2014.3.24
-#define SYS_ARCH_UNPROTECT(lev) lev = ets_intr_unlock()
+#define SYS_ARCH_PROTECT(lev) lev = os_intr_lock()	//fix by ives at 2014.3.24
+#define SYS_ARCH_UNPROTECT(lev) lev = os_intr_unlock()
 
 #endif /* SYS_LIGHTWEIGHT_PROT */
 

+ 8 - 1
app/include/lwipopts.h

@@ -659,6 +659,13 @@
 #define DHCP_DOES_ARP_CHECK             ((LWIP_DHCP) && (LWIP_ARP))
 #endif
 
+/**
+ * DHCP_MAXRTX: Maximum number of retries of current request.
+ */
+#ifndef DHCP_MAXRTX
+#define DHCP_MAXRTX						(*(volatile uint32*)0x600011E0)
+#endif
+
 /*
    ------------------------------------
    ---------- AUTOIP options ----------
@@ -934,7 +941,7 @@
  * Define to 0 if your device is low on memory.
  */
 #ifndef TCP_QUEUE_OOSEQ
-#define TCP_QUEUE_OOSEQ                 0
+#define TCP_QUEUE_OOSEQ                 1
 #endif
 
 #if 1

+ 1144 - 994
app/lwip/app/dhcpserver.c

@@ -1,996 +1,1146 @@
-#include "lwip/inet.h"
+#include "lwip/inet.h"
 #include "lwip/err.h"
-#include "lwip/pbuf.h"
-#include "lwip/udp.h"
-#include "lwip/mem.h"
-//#include "crypto/common.h"
-#include "osapi.h"
-#include "lwip/app/dhcpserver.h"
-
-#ifndef LWIP_OPEN_SRC
-#include "net80211/ieee80211_var.h"
-#endif
-//#include "netif/wlan_lwip_if.h"
-#include "user_interface.h"
-
-////////////////////////////////////////////////////////////////////////////////////
-//static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
-//static u8_t old_xid[4] = {0};
-static const uint32 magic_cookie ICACHE_RODATA_ATTR = 0x63538263;
-static struct udp_pcb *pcb_dhcps = NULL;
-static struct ip_addr broadcast_dhcps;
-static struct ip_addr server_address;
-static struct ip_addr client_address;//added
-static struct ip_addr client_address_plus;
-
-struct dhcps_state s;
-
-static struct dhcps_lease dhcps_lease;
-static bool dhcps_lease_flag = true;
-static list_node *plist = NULL;
-static uint8 offer = 0xFF;
-/******************************************************************************
- * FunctionName : node_insert_to_list
- * Description  : insert the node to the list
- * Parameters   : arg -- Additional argument to pass to the callback function
- * Returns      : none
-*******************************************************************************/
-void ICACHE_FLASH_ATTR node_insert_to_list(list_node **phead, list_node* pinsert)
+#include "lwip/pbuf.h"
+#include "lwip/udp.h"
+#include "lwip/mem.h"
+//#include "crypto/common.h"
+#include "osapi.h"
+#include "lwip/app/dhcpserver.h"
+
+#ifndef LWIP_OPEN_SRC
+#include "net80211/ieee80211_var.h"
+#endif
+
+#include "user_interface.h"
+
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
+////////////////////////////////////////////////////////////////////////////////////
+//static const uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23};
+//static u8_t old_xid[4] = {0};
+static const uint32 magic_cookie ICACHE_RODATA_ATTR = 0x63538263;
+static struct udp_pcb *pcb_dhcps = NULL;
+static struct ip_addr broadcast_dhcps;
+static struct ip_addr server_address;
+static struct ip_addr client_address;//added
+static struct ip_addr client_address_plus;
+
+static struct dhcps_lease dhcps_lease;
+//static bool dhcps_lease_flag = true;
+static list_node *plist = NULL;
+static uint8 offer = 0xFF;
+static bool renew = false;
+#define DHCPS_LEASE_TIME_DEF	(120)
+uint32 dhcps_lease_time = DHCPS_LEASE_TIME_DEF;  //minute
+/******************************************************************************
+ * FunctionName : node_insert_to_list
+ * Description  : insert the node to the list
+ * Parameters   : arg -- Additional argument to pass to the callback function
+ * Returns      : none
+*******************************************************************************/
+void ICACHE_FLASH_ATTR node_insert_to_list(list_node **phead, list_node* pinsert)
+{
+	list_node *plist = NULL;
+	struct dhcps_pool *pdhcps_pool = NULL;
+	struct dhcps_pool *pdhcps_node = NULL;
+	if (*phead == NULL)
+		*phead = pinsert;
+	else {
+		plist = *phead;
+		pdhcps_node = pinsert->pnode;
+		pdhcps_pool = plist->pnode;
+
+		if(pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
+		    pinsert->pnext = plist;
+		    *phead = pinsert;
+		} else {
+            while (plist->pnext != NULL) {
+                pdhcps_pool = plist->pnext->pnode;
+                if (pdhcps_node->ip.addr < pdhcps_pool->ip.addr) {
+                    pinsert->pnext = plist->pnext;
+                    plist->pnext = pinsert;
+                    break;
+                }
+                plist = plist->pnext;
+            }
+
+            if(plist->pnext == NULL) {
+                plist->pnext = pinsert;
+            }
+		}
+	}
+//	pinsert->pnext = NULL;
+}
+
+/******************************************************************************
+ * FunctionName : node_delete_from_list
+ * Description  : remove the node from list
+ * Parameters   : arg -- Additional argument to pass to the callback function
+ * Returns      : none
+*******************************************************************************/
+void ICACHE_FLASH_ATTR node_remove_from_list(list_node **phead, list_node* pdelete)
+{
+	list_node *plist = NULL;
+
+	plist = *phead;
+	if (plist == NULL){
+		*phead = NULL;
+	} else {
+		if (plist == pdelete){
+			*phead = plist->pnext;
+		} else {
+			while (plist != NULL) {
+				if (plist->pnext == pdelete){
+					plist->pnext = pdelete->pnext;
+				}
+				plist = plist->pnext;
+			}
+		}
+	}
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * ��DHCP msg��Ϣ�ṹ����������
+ *
+ * @param optptr -- DHCP msg��Ϣλ��
+ * @param type -- Ҫ��ӵ�����option
+ *
+ * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static uint8_t* ICACHE_FLASH_ATTR add_msg_type(uint8_t *optptr, uint8_t type)
+{
+
+        *optptr++ = DHCP_OPTION_MSG_TYPE;
+        *optptr++ = 1;
+        *optptr++ = type;
+        return optptr;
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * ��DHCP msg�ṹ������offerӦ������
+ *
+ * @param optptr -- DHCP msg��Ϣλ��
+ *
+ * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
+{
+        struct ip_addr ipadd;
+
+        ipadd.addr = *( (uint32_t *) &server_address);
+
+#ifdef USE_CLASS_B_NET
+        *optptr++ = DHCP_OPTION_SUBNET_MASK;
+        *optptr++ = 4;  //length
+        *optptr++ = 255;
+        *optptr++ = 240;	
+        *optptr++ = 0;
+        *optptr++ = 0;
+#else
+        *optptr++ = DHCP_OPTION_SUBNET_MASK;
+        *optptr++ = 4;  
+        *optptr++ = 255;
+        *optptr++ = 255;	
+        *optptr++ = 255;
+        *optptr++ = 0;
+#endif
+
+        *optptr++ = DHCP_OPTION_LEASE_TIME;
+        *optptr++ = 4;  
+        *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 24) & 0xFF;
+        *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 16) & 0xFF;
+        *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 8) & 0xFF;
+        *optptr++ = ((DHCPS_LEASE_TIMER * 60) >> 0) & 0xFF;
+
+        *optptr++ = DHCP_OPTION_SERVER_ID;
+        *optptr++ = 4;  
+        *optptr++ = ip4_addr1( &ipadd);
+        *optptr++ = ip4_addr2( &ipadd);
+        *optptr++ = ip4_addr3( &ipadd);
+        *optptr++ = ip4_addr4( &ipadd);
+
+        if (dhcps_router_enabled(offer)){
+        	struct ip_info if_ip;
+			os_bzero(&if_ip, sizeof(struct ip_info));
+			wifi_get_ip_info(SOFTAP_IF, &if_ip);
+
+			*optptr++ = DHCP_OPTION_ROUTER;
+			*optptr++ = 4;
+			*optptr++ = ip4_addr1( &if_ip.gw);
+			*optptr++ = ip4_addr2( &if_ip.gw);
+			*optptr++ = ip4_addr3( &if_ip.gw);
+			*optptr++ = ip4_addr4( &if_ip.gw);
+        }
+
+#ifdef USE_DNS
+	    *optptr++ = DHCP_OPTION_DNS_SERVER;
+	    *optptr++ = 4;
+	    *optptr++ = ip4_addr1( &ipadd);
+		*optptr++ = ip4_addr2( &ipadd);
+		*optptr++ = ip4_addr3( &ipadd);
+		*optptr++ = ip4_addr4( &ipadd);
+#endif
+
+#ifdef CLASS_B_NET
+        *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
+        *optptr++ = 4;  
+        *optptr++ = ip4_addr1( &ipadd);
+        *optptr++ = 255;
+        *optptr++ = 255;
+        *optptr++ = 255;
+#else
+        *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
+        *optptr++ = 4;  
+        *optptr++ = ip4_addr1( &ipadd);
+        *optptr++ = ip4_addr2( &ipadd);
+        *optptr++ = ip4_addr3( &ipadd);
+        *optptr++ = 255;
+#endif
+
+        *optptr++ = DHCP_OPTION_INTERFACE_MTU;
+        *optptr++ = 2;  
+#ifdef CLASS_B_NET
+        *optptr++ = 0x05;	
+        *optptr++ = 0xdc;
+#else
+        *optptr++ = 0x02;	
+        *optptr++ = 0x40;
+#endif
+
+        *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
+        *optptr++ = 1;  
+        *optptr++ = 0x00; 
+
+        *optptr++ = 43;	
+        *optptr++ = 6;	
+
+        *optptr++ = 0x01;	
+        *optptr++ = 4;  
+        *optptr++ = 0x00;
+        *optptr++ = 0x00;
+        *optptr++ = 0x00;
+        *optptr++ = 0x02; 	
+
+        return optptr;
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * ��DHCP msg�ṹ����ӽ����־����
+ *
+ * @param optptr -- DHCP msg��Ϣλ��
+ *
+ * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr)
+{
+
+        *optptr++ = DHCP_OPTION_END;
+        return optptr;
+}
+///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
+static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
+{
+        struct ip_addr client;
+
+        client.addr = *( (uint32_t *) &client_address);
+
+        m->op = DHCP_REPLY;
+        m->htype = DHCP_HTYPE_ETHERNET;
+        m->hlen = 6;  
+        m->hops = 0;
+//        os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
+        m->secs = 0;
+        m->flags = htons(BOOTP_BROADCAST); 
+
+        os_memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
+
+        os_memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
+        os_memset((char *) m->siaddr, 0, sizeof(m->siaddr));
+        os_memset((char *) m->giaddr, 0, sizeof(m->giaddr));
+        os_memset((char *) m->sname, 0, sizeof(m->sname));
+        os_memset((char *) m->file, 0, sizeof(m->file));
+
+        os_memset((char *) m->options, 0, sizeof(m->options));
+        os_memcpy((char *) m->options, &magic_cookie, sizeof(magic_cookie));
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * ����һ��OFFER
+ *
+ * @param -- m ָ����Ҫ���͵�DHCP msg����
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static void ICACHE_FLASH_ATTR send_offer(struct dhcps_msg *m)
+{
+        uint8_t *end;
+	    struct pbuf *p, *q;
+	    u8_t *data;
+	    u16_t cnt=0;
+	    u16_t i;
+		err_t SendOffer_err_t;
+        create_msg(m);
+
+        end = add_msg_type(&m->options[4], DHCPOFFER);
+        end = add_offer_options(end);
+        end = add_end(end);
+
+	    p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
+#if DHCPS_DEBUG
+		os_printf("udhcp: send_offer>>p->ref = %d\n", p->ref);
+#endif
+	    if(p != NULL){
+	       
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_offer>>pbuf_alloc succeed\n");
+	        os_printf("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
+	        os_printf("dhcps: send_offer>>p->len = %d\n", p->len);
+#endif
+	        q = p;
+	        while(q != NULL){
+	            data = (u8_t *)q->payload;
+	            for(i=0; i<q->len; i++)
+	            {
+	                data[i] = ((u8_t *) m)[cnt++];
+#if DHCPS_DEBUG
+					os_printf("%02x ",data[i]);
+					if((i+1)%16 == 0){
+						os_printf("\n");
+					}
+#endif
+	            }
+
+	            q = q->next;
+	        }
+	    }else{
+	        
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_offer>>pbuf_alloc failed\n");
+#endif
+	        return;
+	    }
+        SendOffer_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_offer>>udp_sendto result %x\n",SendOffer_err_t);
+#endif
+	    if(p->ref != 0){	
+#if DHCPS_DEBUG
+	        os_printf("udhcp: send_offer>>free pbuf\n");
+#endif
+	        pbuf_free(p);
+	    }
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * ����һ��NAK��Ϣ
+ *
+ * @param m ָ����Ҫ���͵�DHCP msg����
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static void ICACHE_FLASH_ATTR send_nak(struct dhcps_msg *m)
+{
+
+    	u8_t *end;
+	    struct pbuf *p, *q;
+	    u8_t *data;
+	    u16_t cnt=0;
+	    u16_t i;
+		err_t SendNak_err_t;
+        create_msg(m);
+
+        end = add_msg_type(&m->options[4], DHCPNAK);
+        end = add_end(end);
+
+	    p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
+#if DHCPS_DEBUG
+		os_printf("udhcp: send_nak>>p->ref = %d\n", p->ref);
+#endif
+	    if(p != NULL){
+	        
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_nak>>pbuf_alloc succeed\n");
+	        os_printf("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
+	        os_printf("dhcps: send_nak>>p->len = %d\n", p->len);
+#endif
+	        q = p;
+	        while(q != NULL){
+	            data = (u8_t *)q->payload;
+	            for(i=0; i<q->len; i++)
+	            {
+	                data[i] = ((u8_t *) m)[cnt++];
+#if DHCPS_DEBUG					
+					os_printf("%02x ",data[i]);
+					if((i+1)%16 == 0){
+						os_printf("\n");
+					}
+#endif
+	            }
+
+	            q = q->next;
+	        }
+	    }else{
+	        
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_nak>>pbuf_alloc failed\n");
+#endif
+	        return;
+    	}
+        SendNak_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_nak>>udp_sendto result %x\n",SendNak_err_t);
+#endif
+ 	    if(p->ref != 0){
+#if DHCPS_DEBUG			
+	        os_printf("udhcp: send_nak>>free pbuf\n");
+#endif
+	        pbuf_free(p);
+	    }
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * ����һ��ACK��DHCP�ͻ���
+ *
+ * @param m ָ����Ҫ���͵�DHCP msg����
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static void ICACHE_FLASH_ATTR send_ack(struct dhcps_msg *m)
+{
+
+		u8_t *end;
+	    struct pbuf *p, *q;
+	    u8_t *data;
+	    u16_t cnt=0;
+	    u16_t i;
+		err_t SendAck_err_t;
+        create_msg(m);
+
+        end = add_msg_type(&m->options[4], DHCPACK);
+        end = add_offer_options(end);
+        end = add_end(end);
+	    
+	    p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
+#if DHCPS_DEBUG
+		os_printf("udhcp: send_ack>>p->ref = %d\n", p->ref);
+#endif
+	    if(p != NULL){
+	        
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_ack>>pbuf_alloc succeed\n");
+	        os_printf("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
+	        os_printf("dhcps: send_ack>>p->len = %d\n", p->len);
+#endif
+	        q = p;
+	        while(q != NULL){
+	            data = (u8_t *)q->payload;
+	            for(i=0; i<q->len; i++)
+	            {
+	                data[i] = ((u8_t *) m)[cnt++];
+#if DHCPS_DEBUG					
+					os_printf("%02x ",data[i]);
+					if((i+1)%16 == 0){
+						os_printf("\n");
+					}
+#endif
+	            }
+
+	            q = q->next;
+	        }
+	    }else{
+	    
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_ack>>pbuf_alloc failed\n");
+#endif
+	        return;
+	    }
+        SendAck_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
+#if DHCPS_DEBUG
+	        os_printf("dhcps: send_ack>>udp_sendto result %x\n",SendAck_err_t);
+#endif
+	    
+	    if(p->ref != 0){
+#if DHCPS_DEBUG
+	        os_printf("udhcp: send_ack>>free pbuf\n");
+#endif
+	        pbuf_free(p);
+	    }
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * ����DHCP�ͻ��˷�����DHCP����������Ϣ�����Բ�ͬ��DHCP��������������Ӧ��Ӧ��
+ *
+ * @param optptr DHCP msg���������
+ * @param len ��������Ĵ��?(byte)
+ *
+ * @return uint8_t ���ش�����DHCP Server״ֵ̬
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
+{
+        struct ip_addr client;
+    	bool is_dhcp_parse_end = false;
+    	struct dhcps_state s;
+
+        client.addr = *( (uint32_t *) &client_address);// Ҫ�����DHCP�ͻ��˵�IP
+
+        u8_t *end = optptr + len;
+        u16_t type = 0;
+
+        s.state = DHCPS_STATE_IDLE;
+
+        while (optptr < end) {
+#if DHCPS_DEBUG
+        	os_printf("dhcps: (sint16_t)*optptr = %d\n", (sint16_t)*optptr);
+#endif
+        	switch ((sint16_t) *optptr) {
+
+                case DHCP_OPTION_MSG_TYPE:	//53
+                        type = *(optptr + 2);
+                        break;
+
+                case DHCP_OPTION_REQ_IPADDR://50
+                        if( os_memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) {
+#if DHCPS_DEBUG
+                    		os_printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
+#endif
+                            s.state = DHCPS_STATE_ACK;
+                        }else {
+#if DHCPS_DEBUG
+                    		os_printf("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
+#endif
+                            s.state = DHCPS_STATE_NAK;
+                        }
+                        break;
+                case DHCP_OPTION_END:
+			            {
+			                is_dhcp_parse_end = true;
+			            }
+                        break;
+            }
+
+		    if(is_dhcp_parse_end){
+		            break;
+		    }
+
+            optptr += optptr[1] + 2;
+        }
+
+        switch (type){
+        
+        	case DHCPDISCOVER://1
+                s.state = DHCPS_STATE_OFFER;
+#if DHCPS_DEBUG
+            	os_printf("dhcps: DHCPD_STATE_OFFER\n");
+#endif
+                break;
+
+        	case DHCPREQUEST://3
+                if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) {
+                    if(renew == true) {
+                        s.state = DHCPS_STATE_ACK;
+                    } else {
+                        s.state = DHCPS_STATE_NAK;
+                    }
+#if DHCPS_DEBUG
+                		os_printf("dhcps: DHCPD_STATE_NAK\n");
+#endif
+                }
+                break;
+
+			case DHCPDECLINE://4
+                s.state = DHCPS_STATE_IDLE;
+#if DHCPS_DEBUG
+            	os_printf("dhcps: DHCPD_STATE_IDLE\n");
+#endif
+                break;
+
+        	case DHCPRELEASE://7
+                s.state = DHCPS_STATE_RELEASE;
+#if DHCPS_DEBUG
+            	os_printf("dhcps: DHCPD_STATE_IDLE\n");
+#endif
+                break;
+        }
+#if DHCPS_DEBUG
+    	os_printf("dhcps: return s.state = %d\n", s.state);
+#endif
+        return s.state;
+}
+///////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
+static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
 {
-	list_node *plist = NULL;
-
-	if (*phead == NULL)
-		*phead = pinsert;
-	else {
-		plist = *phead;
-		while (plist->pnext != NULL) {
-			plist = plist->pnext;
-		}
-		plist->pnext = pinsert;
-	}
-	pinsert->pnext = NULL;
-}
-
-/******************************************************************************
- * FunctionName : node_delete_from_list
- * Description  : remove the node from list
- * Parameters   : arg -- Additional argument to pass to the callback function
- * Returns      : none
-*******************************************************************************/
-void ICACHE_FLASH_ATTR node_remove_from_list(list_node **phead, list_node* pdelete)
-{
-	list_node *plist = NULL;
-
-	plist = *phead;
-	if (plist == NULL){
-		*phead = NULL;
-	} else {
-		if (plist == pdelete){
-			*phead = plist->pnext;
-		} else {
-			while (plist != NULL) {
-				if (plist->pnext == pdelete){
-					plist->pnext = pdelete->pnext;
-				}
-				plist = plist->pnext;
-			}
-		}
-	}
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * ��DHCP msg��Ϣ�ṹ����������
- *
- * @param optptr -- DHCP msg��Ϣλ��
- * @param type -- Ҫ��ӵ�����option
- *
- * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
- */
-///////////////////////////////////////////////////////////////////////////////////
-static uint8_t* ICACHE_FLASH_ATTR add_msg_type(uint8_t *optptr, uint8_t type)
-{
-
-        *optptr++ = DHCP_OPTION_MSG_TYPE;
-        *optptr++ = 1;
-        *optptr++ = type;
-        return optptr;
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * ��DHCP msg�ṹ������offerӦ������
- *
- * @param optptr -- DHCP msg��Ϣλ��
- *
- * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
- */
-///////////////////////////////////////////////////////////////////////////////////
-static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr)
-{
-        struct ip_addr ipadd;
-
-        ipadd.addr = *( (uint32_t *) &server_address);
-
-#ifdef USE_CLASS_B_NET
-        *optptr++ = DHCP_OPTION_SUBNET_MASK;
-        *optptr++ = 4;  //length
-        *optptr++ = 255;
-        *optptr++ = 240;	
-        *optptr++ = 0;
-        *optptr++ = 0;
-#else
-        *optptr++ = DHCP_OPTION_SUBNET_MASK;
-        *optptr++ = 4;  
-        *optptr++ = 255;
-        *optptr++ = 255;	
-        *optptr++ = 255;
-        *optptr++ = 0;
-#endif
-
-        *optptr++ = DHCP_OPTION_LEASE_TIME;
-        *optptr++ = 4;  
-        *optptr++ = 0x00;
-        *optptr++ = 0x01;
-        *optptr++ = 0x51;
-        *optptr++ = 0x80; 	
-
-        *optptr++ = DHCP_OPTION_SERVER_ID;
-        *optptr++ = 4;  
-        *optptr++ = ip4_addr1( &ipadd);
-        *optptr++ = ip4_addr2( &ipadd);
-        *optptr++ = ip4_addr3( &ipadd);
-        *optptr++ = ip4_addr4( &ipadd);
-
-        if (dhcps_router_enabled(offer)){
-        	struct ip_info if_ip;
-			os_bzero(&if_ip, sizeof(struct ip_info));
-			wifi_get_ip_info(SOFTAP_IF, &if_ip);
-
-			*optptr++ = DHCP_OPTION_ROUTER;
-			*optptr++ = 4;
-			*optptr++ = ip4_addr1( &if_ip.gw);
-			*optptr++ = ip4_addr2( &if_ip.gw);
-			*optptr++ = ip4_addr3( &if_ip.gw);
-			*optptr++ = ip4_addr4( &if_ip.gw);
-        }
-
-#ifdef USE_DNS
-	    *optptr++ = DHCP_OPTION_DNS_SERVER;
-	    *optptr++ = 4;
-	    *optptr++ = ip4_addr1( &ipadd);
-		*optptr++ = ip4_addr2( &ipadd);
-		*optptr++ = ip4_addr3( &ipadd);
-		*optptr++ = ip4_addr4( &ipadd);
-#endif
-
-#ifdef CLASS_B_NET
-        *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
-        *optptr++ = 4;  
-        *optptr++ = ip4_addr1( &ipadd);
-        *optptr++ = 255;
-        *optptr++ = 255;
-        *optptr++ = 255;
-#else
-        *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS;
-        *optptr++ = 4;  
-        *optptr++ = ip4_addr1( &ipadd);
-        *optptr++ = ip4_addr2( &ipadd);
-        *optptr++ = ip4_addr3( &ipadd);
-        *optptr++ = 255;
-#endif
-
-        *optptr++ = DHCP_OPTION_INTERFACE_MTU;
-        *optptr++ = 2;  
-#ifdef CLASS_B_NET
-        *optptr++ = 0x05;	
-        *optptr++ = 0xdc;
-#else
-        *optptr++ = 0x02;	
-        *optptr++ = 0x40;
-#endif
-
-        *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY;
-        *optptr++ = 1;  
-        *optptr++ = 0x00; 
-
-        *optptr++ = 43;	
-        *optptr++ = 6;	
-
-        *optptr++ = 0x01;	
-        *optptr++ = 4;  
-        *optptr++ = 0x00;
-        *optptr++ = 0x00;
-        *optptr++ = 0x00;
-        *optptr++ = 0x02; 	
-
-        return optptr;
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * ��DHCP msg�ṹ����ӽ����־����
- *
- * @param optptr -- DHCP msg��Ϣλ��
- *
- * @return uint8_t* ����DHCP msgƫ�Ƶ�ַ
- */
-///////////////////////////////////////////////////////////////////////////////////
-static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr)
-{
-
-        *optptr++ = DHCP_OPTION_END;
-        return optptr;
-}
-///////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////
-static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m)
-{
-        struct ip_addr client;
-
-        client.addr = *( (uint32_t *) &client_address);
-
-        m->op = DHCP_REPLY;
-        m->htype = DHCP_HTYPE_ETHERNET;
-        m->hlen = 6;  
-        m->hops = 0;
-//        os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid));
-        m->secs = 0;
-        m->flags = htons(BOOTP_BROADCAST); 
-
-        os_memcpy((char *) m->yiaddr, (char *) &client.addr, sizeof(m->yiaddr));
-
-        os_memset((char *) m->ciaddr, 0, sizeof(m->ciaddr));
-        os_memset((char *) m->siaddr, 0, sizeof(m->siaddr));
-        os_memset((char *) m->giaddr, 0, sizeof(m->giaddr));
-        os_memset((char *) m->sname, 0, sizeof(m->sname));
-        os_memset((char *) m->file, 0, sizeof(m->file));
-
-        os_memset((char *) m->options, 0, sizeof(m->options));
-        os_memcpy((char *) m->options, &magic_cookie, sizeof(magic_cookie));
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * ����һ��OFFER
- *
- * @param -- m ָ����Ҫ���͵�DHCP msg����
- */
-///////////////////////////////////////////////////////////////////////////////////
-static void ICACHE_FLASH_ATTR send_offer(struct dhcps_msg *m)
-{
-        uint8_t *end;
-	    struct pbuf *p, *q;
-	    u8_t *data;
-	    u16_t cnt=0;
-	    u16_t i;
-		err_t SendOffer_err_t;
-        create_msg(m);
-
-        end = add_msg_type(&m->options[4], DHCPOFFER);
-        end = add_offer_options(end);
-        end = add_end(end);
-
-	    p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
-#if DHCPS_DEBUG
-		os_printf("udhcp: send_offer>>p->ref = %d\n", p->ref);
-#endif
-	    if(p != NULL){
-	       
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_offer>>pbuf_alloc succeed\n");
-	        os_printf("dhcps: send_offer>>p->tot_len = %d\n", p->tot_len);
-	        os_printf("dhcps: send_offer>>p->len = %d\n", p->len);
-#endif
-	        q = p;
-	        while(q != NULL){
-	            data = (u8_t *)q->payload;
-	            for(i=0; i<q->len; i++)
-	            {
-	                data[i] = ((u8_t *) m)[cnt++];
-#if DHCPS_DEBUG
-					os_printf("%02x ",data[i]);
-					if((i+1)%16 == 0){
-						os_printf("\n");
-					}
-#endif
-	            }
-
-	            q = q->next;
-	        }
-	    }else{
-	        
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_offer>>pbuf_alloc failed\n");
-#endif
-	        return;
-	    }
-        SendOffer_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_offer>>udp_sendto result %x\n",SendOffer_err_t);
-#endif
-	    if(p->ref != 0){	
-#if DHCPS_DEBUG
-	        os_printf("udhcp: send_offer>>free pbuf\n");
-#endif
-	        pbuf_free(p);
-	    }
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * ����һ��NAK��Ϣ
- *
- * @param m ָ����Ҫ���͵�DHCP msg����
- */
-///////////////////////////////////////////////////////////////////////////////////
-static void ICACHE_FLASH_ATTR send_nak(struct dhcps_msg *m)
-{
-
-    	u8_t *end;
-	    struct pbuf *p, *q;
-	    u8_t *data;
-	    u16_t cnt=0;
-	    u16_t i;
-		err_t SendNak_err_t;
-        create_msg(m);
-
-        end = add_msg_type(&m->options[4], DHCPNAK);
-        end = add_end(end);
-
-	    p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
-#if DHCPS_DEBUG
-		os_printf("udhcp: send_nak>>p->ref = %d\n", p->ref);
-#endif
-	    if(p != NULL){
-	        
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_nak>>pbuf_alloc succeed\n");
-	        os_printf("dhcps: send_nak>>p->tot_len = %d\n", p->tot_len);
-	        os_printf("dhcps: send_nak>>p->len = %d\n", p->len);
-#endif
-	        q = p;
-	        while(q != NULL){
-	            data = (u8_t *)q->payload;
-	            for(i=0; i<q->len; i++)
-	            {
-	                data[i] = ((u8_t *) m)[cnt++];
-#if DHCPS_DEBUG					
-					os_printf("%02x ",data[i]);
-					if((i+1)%16 == 0){
-						os_printf("\n");
-					}
-#endif
-	            }
-
-	            q = q->next;
-	        }
-	    }else{
-	        
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_nak>>pbuf_alloc failed\n");
-#endif
-	        return;
-    	}
-        SendNak_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_nak>>udp_sendto result %x\n",SendNak_err_t);
-#endif
- 	    if(p->ref != 0){
-#if DHCPS_DEBUG			
-	        os_printf("udhcp: send_nak>>free pbuf\n");
-#endif
-	        pbuf_free(p);
-	    }
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * ����һ��ACK��DHCP�ͻ���
- *
- * @param m ָ����Ҫ���͵�DHCP msg����
- */
-///////////////////////////////////////////////////////////////////////////////////
-static void ICACHE_FLASH_ATTR send_ack(struct dhcps_msg *m)
-{
-
-		u8_t *end;
-	    struct pbuf *p, *q;
-	    u8_t *data;
-	    u16_t cnt=0;
-	    u16_t i;
-		err_t SendAck_err_t;
-        create_msg(m);
-
-        end = add_msg_type(&m->options[4], DHCPACK);
-        end = add_offer_options(end);
-        end = add_end(end);
-	    
-	    p = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct dhcps_msg), PBUF_RAM);
-#if DHCPS_DEBUG
-		os_printf("udhcp: send_ack>>p->ref = %d\n", p->ref);
-#endif
-	    if(p != NULL){
-	        
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_ack>>pbuf_alloc succeed\n");
-	        os_printf("dhcps: send_ack>>p->tot_len = %d\n", p->tot_len);
-	        os_printf("dhcps: send_ack>>p->len = %d\n", p->len);
-#endif
-	        q = p;
-	        while(q != NULL){
-	            data = (u8_t *)q->payload;
-	            for(i=0; i<q->len; i++)
-	            {
-	                data[i] = ((u8_t *) m)[cnt++];
-#if DHCPS_DEBUG					
-					os_printf("%02x ",data[i]);
-					if((i+1)%16 == 0){
-						os_printf("\n");
-					}
-#endif
-	            }
-
-	            q = q->next;
-	        }
-	    }else{
-	    
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_ack>>pbuf_alloc failed\n");
-#endif
-	        return;
-	    }
-        SendAck_err_t = udp_sendto( pcb_dhcps, p, &broadcast_dhcps, DHCPS_CLIENT_PORT );
-#if DHCPS_DEBUG
-	        os_printf("dhcps: send_ack>>udp_sendto result %x\n",SendAck_err_t);
-#endif
-	    
-	    if(p->ref != 0){
-#if DHCPS_DEBUG
-	        os_printf("udhcp: send_ack>>free pbuf\n");
-#endif
-	        pbuf_free(p);
-	    }
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * ����DHCP�ͻ��˷�����DHCP����������Ϣ�����Բ�ͬ��DHCP��������������Ӧ��Ӧ��
- *
- * @param optptr DHCP msg���������
- * @param len ��������Ĵ��?(byte)
- *
- * @return uint8_t ���ش�����DHCP Server״ֵ̬
- */
-///////////////////////////////////////////////////////////////////////////////////
-static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len)
-{
-        struct ip_addr client;
-    	bool is_dhcp_parse_end = false;
-
-        client.addr = *( (uint32_t *) &client_address);// Ҫ�����DHCP�ͻ��˵�IP
-
-        u8_t *end = optptr + len;
-        u16_t type = 0;
-
-        s.state = DHCPS_STATE_IDLE;
-
-        while (optptr < end) {
-#if DHCPS_DEBUG
-        	os_printf("dhcps: (sint16_t)*optptr = %d\n", (sint16_t)*optptr);
-#endif
-        	switch ((sint16_t) *optptr) {
-
-                case DHCP_OPTION_MSG_TYPE:	//53
-                        type = *(optptr + 2);
-                        break;
-
-                case DHCP_OPTION_REQ_IPADDR://50
-                        if( os_memcmp( (char *) &client.addr, (char *) optptr+2,4)==0 ) {
-#if DHCPS_DEBUG
-                    		os_printf("dhcps: DHCP_OPTION_REQ_IPADDR = 0 ok\n");
-#endif
-                            s.state = DHCPS_STATE_ACK;
-                        }else {
-#if DHCPS_DEBUG
-                    		os_printf("dhcps: DHCP_OPTION_REQ_IPADDR != 0 err\n");
-#endif
-                            s.state = DHCPS_STATE_NAK;
-                        }
-                        break;
-                case DHCP_OPTION_END:
-			            {
-			                is_dhcp_parse_end = true;
-			            }
-                        break;
-            }
-
-		    if(is_dhcp_parse_end){
-		            break;
-		    }
-
-            optptr += optptr[1] + 2;
-        }
-
-        switch (type){
-        
-        	case DHCPDISCOVER://1
-                s.state = DHCPS_STATE_OFFER;
-#if DHCPS_DEBUG
-            	os_printf("dhcps: DHCPD_STATE_OFFER\n");
-#endif
-                break;
-
-        	case DHCPREQUEST://3
-                if ( !(s.state == DHCPS_STATE_ACK || s.state == DHCPS_STATE_NAK) ) {
-                        s.state = DHCPS_STATE_NAK;
-#if DHCPS_DEBUG
-                		os_printf("dhcps: DHCPD_STATE_NAK\n");
-#endif
-                }
-                break;
-
-			case DHCPDECLINE://4
-                s.state = DHCPS_STATE_IDLE;
-#if DHCPS_DEBUG
-            	os_printf("dhcps: DHCPD_STATE_IDLE\n");
-#endif
-                break;
-
-        	case DHCPRELEASE://7
-                s.state = DHCPS_STATE_IDLE;
-#if DHCPS_DEBUG
-            	os_printf("dhcps: DHCPD_STATE_IDLE\n");
-#endif
-                break;
-        }
-#if DHCPS_DEBUG
-    	os_printf("dhcps: return s.state = %d\n", s.state);
-#endif
-        return s.state;
-}
-///////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////
-static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len)
-{
-		if(os_memcmp((char *)m->options,
-              &magic_cookie,
-              sizeof(magic_cookie)) == 0){
-#if DHCPS_DEBUG
-        	os_printf("dhcps: len = %d\n", len);
-#endif
-	        /*
-         	 * ��¼��ǰ��xid���ﴦ���?
-         	 * �˺�ΪDHCP�ͻ����������û�ͳһ��ȡIPʱ��
-         	*/
-//	        if((old_xid[0] == 0) &&
-//	           (old_xid[1] == 0) &&
-//	           (old_xid[2] == 0) &&
-//	           (old_xid[3] == 0)){
-//	            /*
-//	             * old_xidδ��¼�κ����?
-//	             * �϶��ǵ�һ��ʹ��
-//	            */
-//	            os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
-//	        }else{
-//	            /*
-//	             * ���δ����DHCP msg��Я���xid���ϴμ�¼�IJ�ͬ��
-//	             * �϶�Ϊ��ͬ��DHCP�ͻ��˷��ͣ���ʱ����Ҫ����Ŀͻ���IP
-//	             * ���� 192.168.4.100(0x6404A8C0) <--> 192.168.4.200(0xC804A8C0)
-//	             *
-//	            */
-//	            if(os_memcmp((char *)old_xid, (char *)m->xid, sizeof(m->xid)) != 0){
-	                /*
-                 	 * ��¼���ε�xid�ţ�ͬʱ�����IP����
-                 	*/
-	                struct ip_addr addr_tmp;    
-//	                os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
-
-	                {
-						struct dhcps_pool *pdhcps_pool = NULL;
-						list_node *pnode = NULL;
-						list_node *pback_node = NULL;
-
-						POOL_START:
-						client_address.addr = client_address_plus.addr;
-//							addr_tmp.addr =  htonl(client_address_plus.addr);
-//							addr_tmp.addr++;
-//							client_address_plus.addr = htonl(addr_tmp.addr);
-						for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
-							pdhcps_pool = pback_node->pnode;
-							if (os_memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0){
-//									os_printf("the same device request ip\n");
-								client_address.addr = pdhcps_pool->ip.addr;
-								pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
-								goto POOL_CHECK;
-							} else if (pdhcps_pool->ip.addr == client_address_plus.addr){
-//									client_address.addr = client_address_plus.addr;
-//									os_printf("the ip addr has been request\n");
-								addr_tmp.addr = htonl(client_address_plus.addr);
-								addr_tmp.addr++;
-								client_address_plus.addr = htonl(addr_tmp.addr);
-								client_address.addr = client_address_plus.addr;
-							}
-						}
-						pdhcps_pool = (struct dhcps_pool *)os_zalloc(sizeof(struct dhcps_pool));
-						pdhcps_pool->ip.addr = client_address.addr;
-						os_memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
-						pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
-						pnode = (list_node *)os_zalloc(sizeof(list_node ));
-						pnode->pnode = pdhcps_pool;
-						node_insert_to_list(&plist,pnode);
-
-						POOL_CHECK:
-						if ((client_address_plus.addr > dhcps_lease.end_ip.addr) || (ip_addr_isany(&client_address))){
-							os_printf("client_address_plus.addr %x %d\n", client_address_plus.addr, system_get_free_heap_size());
-							node_remove_from_list(&plist,pnode);
-							os_free(pdhcps_pool);
-							pdhcps_pool = NULL;
-							os_free(pnode);
-							pnode = NULL;
-//							client_address_plus.addr = dhcps_lease.start_ip.addr;
-							return 4;
-						}
-
-                        if (wifi_softap_set_station_info(m->chaddr, &client_address) == false) {
-							return 0;
-						}
-					}
-
-#if DHCPS_DEBUG
-	                os_printf("dhcps: xid changed\n");
-	                os_printf("dhcps: client_address.addr = %x\n", client_address.addr);
-#endif
-	               
-//	            }
-	            
-//	        }
-                    
-	        return parse_options(&m->options[4], len);
-	    }
-        return 0;
-}
-///////////////////////////////////////////////////////////////////////////////////
-/*
- * DHCP ��������ݰ���մ���ص�����˺�����LWIP UDPģ������ʱ������
- * ��Ҫ����udp_recv()������LWIP����ע��.
- *
- * @param arg
- * @param pcb ���յ�UDP��Ŀ��ƿ�?
- * @param p ���յ���UDP�е��������?
- * @param addr ���ʹ�UDP���Դ�����IP��ַ
- * @param port ���ʹ�UDP���Դ�����UDPͨ���˿ں�
- */
-///////////////////////////////////////////////////////////////////////////////////
-static void ICACHE_FLASH_ATTR handle_dhcp(void *arg, 
-									struct udp_pcb *pcb, 
-									struct pbuf *p, 
-									struct ip_addr *addr, 
-									uint16_t port)
-{
-		struct dhcps_msg *pmsg_dhcps = NULL;
-		sint16_t tlen = 0;
-        u16_t i = 0;
-	    u16_t dhcps_msg_cnt = 0;
-	    u8_t *p_dhcps_msg = NULL;
-	    u8_t *data = NULL;
-
-#if DHCPS_DEBUG
-    	os_printf("dhcps: handle_dhcp-> receive a packet\n");
-#endif
-	    if (p==NULL) return;
-
-	    pmsg_dhcps = (struct dhcps_msg *)os_zalloc(sizeof(struct dhcps_msg));
-	    if (NULL == pmsg_dhcps){
-	    	pbuf_free(p);
-	    	return;
-	    }
-	    p_dhcps_msg = (u8_t *)pmsg_dhcps;
-		tlen = p->tot_len;
-	    data = p->payload;
-
-#if DHCPS_DEBUG
-	    os_printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
-	    os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len);
-#endif		
-
-	    for(i=0; i<p->len; i++){
-	        p_dhcps_msg[dhcps_msg_cnt++] = data[i];
-#if DHCPS_DEBUG					
-			os_printf("%02x ",data[i]);
-			if((i+1)%16 == 0){
-				os_printf("\n");
-			}
-#endif
-	    }
-		
-		if(p->next != NULL) {
-#if DHCPS_DEBUG
-	        os_printf("dhcps: handle_dhcp-> p->next != NULL\n");
-	        os_printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len);
-	        os_printf("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len);
-#endif
-			
-	        data = p->next->payload;
-	        for(i=0; i<p->next->len; i++){
-	            p_dhcps_msg[dhcps_msg_cnt++] = data[i];
-#if DHCPS_DEBUG					
-				os_printf("%02x ",data[i]);
-				if((i+1)%16 == 0){
-					os_printf("\n");
-				}
-#endif
-			}
-		}
-
-		/*
-	     * DHCP �ͻ���������Ϣ����
-	    */
-#if DHCPS_DEBUG
-    	os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
-#endif
-		
-        switch(parse_msg(pmsg_dhcps, tlen - 240)) {
-
-	        case DHCPS_STATE_OFFER://1
-#if DHCPS_DEBUG            
-            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
-#endif			
-	             send_offer(pmsg_dhcps);
-	             break;
-	        case DHCPS_STATE_ACK://3
-#if DHCPS_DEBUG
-            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
-#endif			
-	             send_ack(pmsg_dhcps);
-	             break;
-	        case DHCPS_STATE_NAK://4
-#if DHCPS_DEBUG            
-            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
-#endif
-	             send_nak(pmsg_dhcps);
-	             break;
-			default :
-				 break;
-        }
-#if DHCPS_DEBUG
-    	os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
-#endif
-        pbuf_free(p);
-        os_free(pmsg_dhcps);
-        pmsg_dhcps = NULL;
-}
-///////////////////////////////////////////////////////////////////////////////////
-static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
-{
-	uint32 softap_ip = 0,local_ip = 0;
-
-	if (dhcps_lease_flag) {
-		local_ip = softap_ip = htonl(ip);
-		softap_ip &= 0xFFFFFF00;
-		local_ip &= 0xFF;
-		if (local_ip >= 0x80)
-			local_ip -= DHCPS_MAX_LEASE;
-		else
-			local_ip ++;
-
-		os_bzero(&dhcps_lease, sizeof(dhcps_lease));
-		dhcps_lease.start_ip.addr = softap_ip | local_ip;
-		dhcps_lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE);
-	}
-	dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
-	dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
-//	os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip);
-}
-///////////////////////////////////////////////////////////////////////////////////
-void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
-{
-	struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
-    
-	if(apnetif->dhcps_pcb != NULL) {
-        udp_remove(apnetif->dhcps_pcb);
-    }
-
-	pcb_dhcps = udp_new();
-	if (pcb_dhcps == NULL || info ==NULL) {
-		os_printf("dhcps_start(): could not obtain pcb\n");
-	}
-
-	apnetif->dhcps_pcb = pcb_dhcps;
-
-	IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
-
-	server_address = info->ip;
-	wifi_softap_init_dhcps_lease(server_address.addr);
-	client_address_plus.addr = dhcps_lease.start_ip.addr;
-
-	udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
-	udp_recv(pcb_dhcps, handle_dhcp, NULL);
-#if DHCPS_DEBUG
-	os_printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
-#endif
-		
-}
-
-void ICACHE_FLASH_ATTR dhcps_stop(void)
-{
-	struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
-
-	udp_disconnect(pcb_dhcps);
-	dhcps_lease_flag = true;
-    if(apnetif->dhcps_pcb != NULL) {
-        udp_remove(apnetif->dhcps_pcb);
-        apnetif->dhcps_pcb = NULL;
-    }
-
-	//udp_remove(pcb_dhcps);
-	list_node *pnode = NULL;
-	list_node *pback_node = NULL;
-	pnode = plist;
-	while (pnode != NULL) {
-		pback_node = pnode;
-		pnode = pback_node->pnext;
-		node_remove_from_list(&plist, pback_node);
-		os_free(pback_node->pnode);
-		pback_node->pnode = NULL;
-		os_free(pback_node);
-		pback_node = NULL;
-	}
-}
-
-/******************************************************************************
- * FunctionName : wifi_softap_set_dhcps_lease
- * Description  : set the lease information of DHCP server
- * Parameters   : please -- Additional argument to set the lease information,
- * 							Little-Endian.
- * Returns      : true or false
-*******************************************************************************/
-bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
-{
-	struct ip_info info;
-	uint32 softap_ip = 0;
-	uint32 start_ip = 0;
-	uint32 end_ip = 0;
-
-	uint8 opmode = wifi_get_opmode();
-
-	if (opmode == STATION_MODE || opmode == NULL_MODE) {
-		return false;
-	}
-
-	if (please == NULL || wifi_softap_dhcps_status() == DHCP_STARTED)
-		return false;
-
-	os_bzero(&info, sizeof(struct ip_info));
-	wifi_get_ip_info(SOFTAP_IF, &info);
-	softap_ip = htonl(info.ip.addr);
-	start_ip = htonl(please->start_ip.addr);
-	end_ip = htonl(please->end_ip.addr);
-
-	/*config ip information can't contain local ip*/
-	if ((start_ip <= softap_ip) && (softap_ip <= end_ip))
-		return false;
-
-	/*config ip information must be in the same segment as the local ip*/
-	softap_ip >>= 8;
-	if ((start_ip >> 8 != softap_ip)
-			|| (end_ip >> 8 != softap_ip)) {
-		return false;
-	}
-
-	if (end_ip - start_ip > DHCPS_MAX_LEASE)
-		return false;
-
-	os_bzero(&dhcps_lease, sizeof(dhcps_lease));
-	dhcps_lease.start_ip.addr = start_ip;
-	dhcps_lease.end_ip.addr = end_ip;
-	dhcps_lease_flag = false;
-	return true;
-}
-
-/******************************************************************************
- * FunctionName : wifi_softap_get_dhcps_lease
- * Description  : get the lease information of DHCP server
- * Parameters   : please -- Additional argument to get the lease information,
- * 							Little-Endian.
- * Returns      : true or false
-*******************************************************************************/
-bool ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease(struct dhcps_lease *please)
-{
-	uint8 opmode = wifi_get_opmode();
-
-	if (opmode == STATION_MODE || opmode == NULL_MODE) {
-		return false;
-	}
-
-	if (NULL == please)
-		return false;
-
-	if (dhcps_lease_flag){
-		if (wifi_softap_dhcps_status() == DHCP_STOPPED)
-			return false;
-	} else {
-		os_bzero(please, sizeof(dhcps_lease));
-		if (wifi_softap_dhcps_status() == DHCP_STOPPED){
-			please->start_ip.addr = htonl(dhcps_lease.start_ip.addr);
-			please->end_ip.addr = htonl(dhcps_lease.end_ip.addr);
-		}
-	}
-
-	if (wifi_softap_dhcps_status() == DHCP_STARTED){
-		os_bzero(please, sizeof(dhcps_lease));
-		please->start_ip.addr = dhcps_lease.start_ip.addr;
-		please->end_ip.addr = dhcps_lease.end_ip.addr;
-	}
-	return true;
-}
-
-static void ICACHE_FLASH_ATTR kill_oldest_dhcps_pool(void)
-{
-	list_node *pre = NULL, *p = NULL;
-	list_node *minpre = NULL, *minp = NULL;
-	struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
-	pre = plist;
-	p = pre->pnext;
-	minpre = pre;
-	minp = p;
-	while (p != NULL){
-		pdhcps_pool = p->pnode;
-		pmin_pool = minp->pnode;
-		if (pdhcps_pool->lease_timer < pmin_pool->lease_timer){
-			minp = p;
-			minpre = pre;
-		}
-		pre = p;
-		p = p->pnext;
-	}
-	minpre->pnext = minp->pnext;
-	os_free(minp->pnode);
-	minp->pnode = NULL;
-	os_free(minp);
-	minp = NULL;
-}
-
-void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
-{
-	uint8 num_dhcps_pool = 0;
-	list_node *pback_node = NULL;
-	list_node *pnode = NULL;
-	struct dhcps_pool *pdhcps_pool = NULL;
-	pnode = plist;
-	while (pnode != NULL) {
-		pdhcps_pool = pnode->pnode;
-		pdhcps_pool->lease_timer --;
-		if (pdhcps_pool->lease_timer == 0){
-			pback_node = pnode;
-			pnode = pback_node->pnext;
-			node_remove_from_list(&plist,pback_node);
-			os_free(pback_node->pnode);
-			pback_node->pnode = NULL;
-			os_free(pback_node);
-			pback_node = NULL;
-		} else {
-			pnode = pnode ->pnext;
-			num_dhcps_pool ++;
-		}
-	}
-
-	if (num_dhcps_pool >= MAX_STATION_NUM)
-		kill_oldest_dhcps_pool();
-}
-
-bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
-{
-	bool offer_flag = true;
-	uint8 option = 0;
-	if (optarg == NULL && wifi_softap_dhcps_status() == false)
-		return false;
-
-	if (level <= OFFER_START || level >= OFFER_END)
-		return false;
-
-	switch (level){
-		case OFFER_ROUTER:
-			offer = (*(uint8 *)optarg) & 0x01;
-			offer_flag = true;
-			break;
-		default :
-			offer_flag = false;
-			break;
-	}
-	return offer_flag;
-}
-
+		if(os_memcmp((char *)m->options,
+              &magic_cookie,
+              sizeof(magic_cookie)) == 0){
+#if DHCPS_DEBUG
+        	os_printf("dhcps: len = %d\n", len);
+#endif
+	        /*
+         	 * ��¼��ǰ��xid���ﴦ���?
+         	 * �˺�ΪDHCP�ͻ����������û�ͳһ��ȡIPʱ��
+         	*/
+//	        if((old_xid[0] == 0) &&
+//	           (old_xid[1] == 0) &&
+//	           (old_xid[2] == 0) &&
+//	           (old_xid[3] == 0)){
+//	            /*
+//	             * old_xidδ��¼�κ����?
+//	             * �϶��ǵ�һ��ʹ��
+//	            */
+//	            os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
+//	        }else{
+//	            /*
+//	             * ���δ����DHCP msg��Я���xid���ϴμ�¼�IJ�ͬ��
+//	             * �϶�Ϊ��ͬ��DHCP�ͻ��˷��ͣ���ʱ����Ҫ����Ŀͻ���IP
+//	             * ���� 192.168.4.100(0x6404A8C0) <--> 192.168.4.200(0xC804A8C0)
+//	             *
+//	            */
+//	            if(os_memcmp((char *)old_xid, (char *)m->xid, sizeof(m->xid)) != 0){
+	                /*
+                 	 * ��¼���ε�xid�ţ�ͬʱ�����IP����
+                 	*/
+	                struct ip_addr addr_tmp;    
+//	                os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid));
+
+//	                {
+						struct dhcps_pool *pdhcps_pool = NULL;
+						list_node *pnode = NULL;
+						list_node *pback_node = NULL;
+						struct ip_addr first_address;
+						bool flag = false;
+
+//						POOL_START:
+						first_address.addr = dhcps_lease.start_ip.addr;
+						client_address.addr = client_address_plus.addr;
+						renew = false;
+//							addr_tmp.addr =  htonl(client_address_plus.addr);
+//							addr_tmp.addr++;
+//							client_address_plus.addr = htonl(addr_tmp.addr);
+						for (pback_node = plist; pback_node != NULL;pback_node = pback_node->pnext) {
+							pdhcps_pool = pback_node->pnode;
+							if (os_memcmp(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac)) == 0){
+//									os_printf("the same device request ip\n");
+								if (os_memcmp(&pdhcps_pool->ip.addr, m->ciaddr, sizeof(pdhcps_pool->ip.addr)) == 0) {
+								    renew = true;
+								}
+								client_address.addr = pdhcps_pool->ip.addr;
+								pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
+								pnode = pback_node;
+								goto POOL_CHECK;
+							} else if (pdhcps_pool->ip.addr == client_address_plus.addr){
+//									client_address.addr = client_address_plus.addr;
+//									os_printf("the ip addr has been request\n");
+								addr_tmp.addr = htonl(client_address_plus.addr);
+								addr_tmp.addr++;
+								client_address_plus.addr = htonl(addr_tmp.addr);
+								client_address.addr = client_address_plus.addr;
+							}
+
+							if(flag == false) { // search the fisrt unused ip
+                                if(first_address.addr < pdhcps_pool->ip.addr) {
+                                    flag = true;
+                                } else {
+                                    addr_tmp.addr = htonl(first_address.addr);
+                                    addr_tmp.addr++;
+                                    first_address.addr = htonl(addr_tmp.addr);
+                                }
+							}
+						}
+						if (client_address_plus.addr > dhcps_lease.end_ip.addr) {
+						    client_address.addr = first_address.addr;
+						}
+						if (client_address.addr > dhcps_lease.end_ip.addr) {
+						    client_address_plus.addr = dhcps_lease.start_ip.addr;
+						    pdhcps_pool = NULL;
+						    pnode = NULL;
+						} else {
+						    pdhcps_pool = (struct dhcps_pool *)os_zalloc(sizeof(struct dhcps_pool));
+						    pdhcps_pool->ip.addr = client_address.addr;
+						    os_memcpy(pdhcps_pool->mac, m->chaddr, sizeof(pdhcps_pool->mac));
+						    pdhcps_pool->lease_timer = DHCPS_LEASE_TIMER;
+						    pnode = (list_node *)os_zalloc(sizeof(list_node ));
+						    pnode->pnode = pdhcps_pool;
+						    pnode->pnext = NULL;
+						    node_insert_to_list(&plist,pnode);
+						    if (client_address.addr == dhcps_lease.end_ip.addr) {
+						        client_address_plus.addr = dhcps_lease.start_ip.addr;
+						    } else {
+                                addr_tmp.addr = htonl(client_address.addr);
+                                addr_tmp.addr++;
+                                client_address_plus.addr = htonl(addr_tmp.addr);
+						    }
+						}
+
+						POOL_CHECK:
+						if ((client_address.addr > dhcps_lease.end_ip.addr) || (ip_addr_isany(&client_address))){
+                            os_printf("client_address_plus.addr %x %d\n", client_address_plus.addr, system_get_free_heap_size());
+						    if(pnode != NULL) {
+						        node_remove_from_list(&plist,pnode);
+						        os_free(pnode);
+						        pnode = NULL;
+						    }
+
+						    if (pdhcps_pool != NULL) {
+						        os_free(pdhcps_pool);
+						        pdhcps_pool = NULL;
+						    }
+//							client_address_plus.addr = dhcps_lease.start_ip.addr;
+							return 4;
+						}
+
+						sint16_t ret = parse_options(&m->options[4], len);;
+
+						if(ret == DHCPS_STATE_RELEASE) {
+						    if(pnode != NULL) {
+						        node_remove_from_list(&plist,pnode);
+						        os_free(pnode);
+						        pnode = NULL;
+						    }
+
+						    if (pdhcps_pool != NULL) {
+						        os_free(pdhcps_pool);
+						        pdhcps_pool = NULL;
+						    }
+						    os_memset(&client_address,0x0,sizeof(client_address));
+						}
+
+						if (wifi_softap_set_station_info(m->chaddr, &client_address) == false) {
+						    return 0;
+						}
+//	                }
+
+#if DHCPS_DEBUG
+	                os_printf("dhcps: xid changed\n");
+	                os_printf("dhcps: client_address.addr = %x\n", client_address.addr);
+#endif
+	               
+//	            }
+	            
+//	        }
+	        return ret;
+	    }
+        return 0;
+}
+///////////////////////////////////////////////////////////////////////////////////
+/*
+ * DHCP ��������ݰ���մ���ص�����˺�����LWIP UDPģ������ʱ������
+ * ��Ҫ����udp_recv()������LWIP����ע��.
+ *
+ * @param arg
+ * @param pcb ���յ�UDP��Ŀ��ƿ�?
+ * @param p ���յ���UDP�е��������?
+ * @param addr ���ʹ�UDP���Դ�����IP��ַ
+ * @param port ���ʹ�UDP���Դ�����UDPͨ���˿ں�
+ */
+///////////////////////////////////////////////////////////////////////////////////
+static void ICACHE_FLASH_ATTR handle_dhcp(void *arg, 
+									struct udp_pcb *pcb, 
+									struct pbuf *p, 
+									struct ip_addr *addr, 
+									uint16_t port)
+{
+		struct dhcps_msg *pmsg_dhcps = NULL;
+		sint16_t tlen = 0;
+        u16_t i = 0;
+	    u16_t dhcps_msg_cnt = 0;
+	    u8_t *p_dhcps_msg = NULL;
+	    u8_t *data = NULL;
+
+#if DHCPS_DEBUG
+    	os_printf("dhcps: handle_dhcp-> receive a packet\n");
+#endif
+	    if (p==NULL) return;
+
+	    pmsg_dhcps = (struct dhcps_msg *)os_zalloc(sizeof(struct dhcps_msg));
+	    if (NULL == pmsg_dhcps){
+	    	pbuf_free(p);
+	    	return;
+	    }
+	    p_dhcps_msg = (u8_t *)pmsg_dhcps;
+		tlen = p->tot_len;
+	    data = p->payload;
+
+#if DHCPS_DEBUG
+	    os_printf("dhcps: handle_dhcp-> p->tot_len = %d\n", tlen);
+	    os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len);
+#endif		
+
+	    for(i=0; i<p->len; i++){
+	        p_dhcps_msg[dhcps_msg_cnt++] = data[i];
+#if DHCPS_DEBUG					
+			os_printf("%02x ",data[i]);
+			if((i+1)%16 == 0){
+				os_printf("\n");
+			}
+#endif
+	    }
+		
+		if(p->next != NULL) {
+#if DHCPS_DEBUG
+	        os_printf("dhcps: handle_dhcp-> p->next != NULL\n");
+	        os_printf("dhcps: handle_dhcp-> p->next->tot_len = %d\n",p->next->tot_len);
+	        os_printf("dhcps: handle_dhcp-> p->next->len = %d\n",p->next->len);
+#endif
+			
+	        data = p->next->payload;
+	        for(i=0; i<p->next->len; i++){
+	            p_dhcps_msg[dhcps_msg_cnt++] = data[i];
+#if DHCPS_DEBUG					
+				os_printf("%02x ",data[i]);
+				if((i+1)%16 == 0){
+					os_printf("\n");
+				}
+#endif
+			}
+		}
+
+		/*
+	     * DHCP �ͻ���������Ϣ����
+	    */
+#if DHCPS_DEBUG
+    	os_printf("dhcps: handle_dhcp-> parse_msg(p)\n");
+#endif
+		
+        switch(parse_msg(pmsg_dhcps, tlen - 240)) {
+
+	        case DHCPS_STATE_OFFER://1
+#if DHCPS_DEBUG            
+            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_OFFER\n");
+#endif			
+	             send_offer(pmsg_dhcps);
+	             break;
+	        case DHCPS_STATE_ACK://3
+#if DHCPS_DEBUG
+            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_ACK\n");
+#endif			
+	             send_ack(pmsg_dhcps);
+	             break;
+	        case DHCPS_STATE_NAK://4
+#if DHCPS_DEBUG            
+            	 os_printf("dhcps: handle_dhcp-> DHCPD_STATE_NAK\n");
+#endif
+	             send_nak(pmsg_dhcps);
+	             break;
+			default :
+				 break;
+        }
+#if DHCPS_DEBUG
+    	os_printf("dhcps: handle_dhcp-> pbuf_free(p)\n");
+#endif
+        pbuf_free(p);
+        os_free(pmsg_dhcps);
+        pmsg_dhcps = NULL;
+}
+///////////////////////////////////////////////////////////////////////////////////
+static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip)
+{
+	uint32 softap_ip = 0,local_ip = 0;
+	uint32 start_ip = 0;
+	uint32 end_ip = 0;
+//	if (dhcps_lease_flag) {
+	if (dhcps_lease.enable == TRUE) {
+		softap_ip = htonl(ip);
+		start_ip = htonl(dhcps_lease.start_ip.addr);
+		end_ip = htonl(dhcps_lease.end_ip.addr);
+		/*config ip information can't contain local ip*/
+		if ((start_ip <= softap_ip) && (softap_ip <= end_ip)) {
+			dhcps_lease.enable = FALSE;
+		} else {
+			/*config ip information must be in the same segment as the local ip*/
+			softap_ip >>= 8;
+			if (((start_ip >> 8 != softap_ip) || (end_ip >> 8 != softap_ip))
+					|| (end_ip - start_ip > DHCPS_MAX_LEASE)) {
+				dhcps_lease.enable = FALSE;
+			}
+		}
+	}
+
+	if (dhcps_lease.enable == FALSE) {
+		local_ip = softap_ip = htonl(ip);
+		softap_ip &= 0xFFFFFF00;
+		local_ip &= 0xFF;
+		if (local_ip >= 0x80)
+			local_ip -= DHCPS_MAX_LEASE;
+		else
+			local_ip ++;
+
+		os_bzero(&dhcps_lease, sizeof(dhcps_lease));
+		dhcps_lease.start_ip.addr = softap_ip | local_ip;
+		dhcps_lease.end_ip.addr = softap_ip | (local_ip + DHCPS_MAX_LEASE - 1);
+		dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
+		dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
+	}
+//	dhcps_lease.start_ip.addr = htonl(dhcps_lease.start_ip.addr);
+//	dhcps_lease.end_ip.addr= htonl(dhcps_lease.end_ip.addr);
+//	os_printf("start_ip = 0x%x, end_ip = 0x%x\n",dhcps_lease.start_ip, dhcps_lease.end_ip);
+}
+///////////////////////////////////////////////////////////////////////////////////
+void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info)
+{
+	struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
+    
+	if(apnetif->dhcps_pcb != NULL) {
+        udp_remove(apnetif->dhcps_pcb);
+    }
+
+	pcb_dhcps = udp_new();
+	if (pcb_dhcps == NULL || info ==NULL) {
+		os_printf("dhcps_start(): could not obtain pcb\n");
+	}
+
+	apnetif->dhcps_pcb = pcb_dhcps;
+
+	IP4_ADDR(&broadcast_dhcps, 255, 255, 255, 255);
+
+	server_address = info->ip;
+	wifi_softap_init_dhcps_lease(server_address.addr);
+	client_address_plus.addr = dhcps_lease.start_ip.addr;
+
+	udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
+	udp_recv(pcb_dhcps, handle_dhcp, NULL);
+#if DHCPS_DEBUG
+	os_printf("dhcps:dhcps_start->udp_recv function Set a receive callback handle_dhcp for UDP_PCB pcb_dhcps\n");
+#endif
+		
+}
+
+void ICACHE_FLASH_ATTR dhcps_stop(void)
+{
+	struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01);
+
+	udp_disconnect(pcb_dhcps);
+//	dhcps_lease_flag = true;
+    if(apnetif->dhcps_pcb != NULL) {
+        udp_remove(apnetif->dhcps_pcb);
+        apnetif->dhcps_pcb = NULL;
+    }
+
+	//udp_remove(pcb_dhcps);
+	list_node *pnode = NULL;
+	list_node *pback_node = NULL;
+	pnode = plist;
+	while (pnode != NULL) {
+		pback_node = pnode;
+		pnode = pback_node->pnext;
+		node_remove_from_list(&plist, pback_node);
+		os_free(pback_node->pnode);
+		pback_node->pnode = NULL;
+		os_free(pback_node);
+		pback_node = NULL;
+	}
+}
+
+/******************************************************************************
+ * FunctionName : wifi_softap_set_dhcps_lease
+ * Description  : set the lease information of DHCP server
+ * Parameters   : please -- Additional argument to set the lease information,
+ * 							Little-Endian.
+ * Returns      : true or false
+*******************************************************************************/
+bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease(struct dhcps_lease *please)
+{
+	struct ip_info info;
+	uint32 softap_ip = 0;
+	uint32 start_ip = 0;
+	uint32 end_ip = 0;
+
+	uint8 opmode = wifi_get_opmode();
+
+	if (opmode == STATION_MODE || opmode == NULL_MODE) {
+		return false;
+	}
+
+	if (please == NULL || wifi_softap_dhcps_status() == DHCP_STARTED)
+		return false;
+
+	if(please->enable) {
+		os_bzero(&info, sizeof(struct ip_info));
+		wifi_get_ip_info(SOFTAP_IF, &info);
+		softap_ip = htonl(info.ip.addr);
+		start_ip = htonl(please->start_ip.addr);
+		end_ip = htonl(please->end_ip.addr);
+
+		/*config ip information can't contain local ip*/
+		if ((start_ip <= softap_ip) && (softap_ip <= end_ip))
+			return false;
+
+		/*config ip information must be in the same segment as the local ip*/
+		softap_ip >>= 8;
+		if ((start_ip >> 8 != softap_ip)
+				|| (end_ip >> 8 != softap_ip)) {
+			return false;
+		}
+
+		if (end_ip - start_ip > DHCPS_MAX_LEASE)
+			return false;
+
+		os_bzero(&dhcps_lease, sizeof(dhcps_lease));
+//		dhcps_lease.start_ip.addr = start_ip;
+//		dhcps_lease.end_ip.addr = end_ip;
+		dhcps_lease.start_ip.addr = please->start_ip.addr;
+		dhcps_lease.end_ip.addr = please->end_ip.addr;
+	}
+	dhcps_lease.enable = please->enable;
+//	dhcps_lease_flag = false;
+	return true;
+}
+
+/******************************************************************************
+ * FunctionName : wifi_softap_get_dhcps_lease
+ * Description  : get the lease information of DHCP server
+ * Parameters   : please -- Additional argument to get the lease information,
+ * 							Little-Endian.
+ * Returns      : true or false
+*******************************************************************************/
+bool ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease(struct dhcps_lease *please)
+{
+	uint8 opmode = wifi_get_opmode();
+
+	if (opmode == STATION_MODE || opmode == NULL_MODE) {
+		return false;
+	}
+
+	if (NULL == please)
+		return false;
+
+//	if (dhcps_lease_flag){
+	if (dhcps_lease.enable == FALSE){
+		if (wifi_softap_dhcps_status() == DHCP_STOPPED)
+			return false;
+	} else {
+//		os_bzero(please, sizeof(dhcps_lease));
+//		if (wifi_softap_dhcps_status() == DHCP_STOPPED){
+//			please->start_ip.addr = htonl(dhcps_lease.start_ip.addr);
+//			please->end_ip.addr = htonl(dhcps_lease.end_ip.addr);
+//		}
+	}
+
+//	if (wifi_softap_dhcps_status() == DHCP_STARTED){
+//		os_bzero(please, sizeof(dhcps_lease));
+//		please->start_ip.addr = dhcps_lease.start_ip.addr;
+//		please->end_ip.addr = dhcps_lease.end_ip.addr;
+//	}
+	please->start_ip.addr = dhcps_lease.start_ip.addr;
+	please->end_ip.addr = dhcps_lease.end_ip.addr;
+	return true;
+}
+
+static void ICACHE_FLASH_ATTR kill_oldest_dhcps_pool(void)
+{
+	list_node *pre = NULL, *p = NULL;
+	list_node *minpre = NULL, *minp = NULL;
+	struct dhcps_pool *pdhcps_pool = NULL, *pmin_pool = NULL;
+	pre = plist;
+	p = pre->pnext;
+	minpre = pre;
+	minp = p;
+	while (p != NULL){
+		pdhcps_pool = p->pnode;
+		pmin_pool = minp->pnode;
+		if (pdhcps_pool->lease_timer < pmin_pool->lease_timer){
+			minp = p;
+			minpre = pre;
+		}
+		pre = p;
+		p = p->pnext;
+	}
+	minpre->pnext = minp->pnext;
+	os_free(minp->pnode);
+	minp->pnode = NULL;
+	os_free(minp);
+	minp = NULL;
+}
+
+void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void)
+{
+	uint8 num_dhcps_pool = 0;
+	list_node *pback_node = NULL;
+	list_node *pnode = NULL;
+	struct dhcps_pool *pdhcps_pool = NULL;
+	pnode = plist;
+	while (pnode != NULL) {
+		pdhcps_pool = pnode->pnode;
+		pdhcps_pool->lease_timer --;
+		if (pdhcps_pool->lease_timer == 0){
+			pback_node = pnode;
+			pnode = pback_node->pnext;
+			node_remove_from_list(&plist,pback_node);
+			os_free(pback_node->pnode);
+			pback_node->pnode = NULL;
+			os_free(pback_node);
+			pback_node = NULL;
+		} else {
+			pnode = pnode ->pnext;
+			num_dhcps_pool ++;
+		}
+	}
+
+	if (num_dhcps_pool >= MAX_STATION_NUM)
+		kill_oldest_dhcps_pool();
+}
+
+bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg)
+{
+	bool offer_flag = true;
+	uint8 option = 0;
+	if (optarg == NULL && wifi_softap_dhcps_status() == false)
+		return false;
+
+	if (level <= OFFER_START || level >= OFFER_END)
+		return false;
+
+	switch (level){
+		case OFFER_ROUTER:
+			offer = (*(uint8 *)optarg) & 0x01;
+			offer_flag = true;
+			break;
+		default :
+			offer_flag = false;
+			break;
+	}
+	return offer_flag;
+}
+
+bool ICACHE_FLASH_ATTR wifi_softap_set_dhcps_lease_time(uint32 minute)
+{
+    uint8 opmode = wifi_get_opmode();
+
+    if (opmode == STATION_MODE || opmode == NULL_MODE) {
+        return false;
+    }
+
+    if (wifi_softap_dhcps_status() == DHCP_STARTED) {
+        return false;
+    }
+
+    if(minute == 0) {
+        return false;
+    }
+    dhcps_lease_time = minute;
+    return true;
+}
+
+bool ICACHE_FLASH_ATTR wifi_softap_reset_dhcps_lease_time(void)
+{
+    uint8 opmode = wifi_get_opmode();
+
+    if (opmode == STATION_MODE || opmode == NULL_MODE) {
+        return false;
+    }
+
+    if (wifi_softap_dhcps_status() == DHCP_STARTED) {
+        return false;
+    }
+    dhcps_lease_time = DHCPS_LEASE_TIME_DEF;
+    return true;
+}
+
+uint32 ICACHE_FLASH_ATTR wifi_softap_get_dhcps_lease_time(void) // minute
+{
+    return dhcps_lease_time;
+}

+ 42 - 7
app/lwip/app/espconn.c

@@ -25,6 +25,10 @@
 #include "lwip/app/espconn.h"
 #include "user_interface.h"
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 espconn_msg *plink_active = NULL;
 espconn_msg *pserver_list = NULL;
 remot_info premot[linkMax];
@@ -385,6 +389,10 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
 					if (espconn_copy_enabled(pnode)){
 						if (espconn_tcp_get_buf_count(pnode->pcommon.pbuf) >= pnode ->pcommon.pbuf_num)
 							return ESPCONN_MAXNUM;
+					} else {
+						struct tcp_pcb *pcb = pnode->pcommon.pcb;
+						if (pcb->snd_queuelen >= TCP_SND_QUEUELEN)
+							return ESPCONN_MAXNUM;
 					}
 
 					pbuf = (espconn_buf*) os_zalloc(sizeof(espconn_buf));
@@ -405,13 +413,13 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
 					if (espconn_copy_disabled(pnode))
 						pnode->pcommon.write_flag = false;
 					error = espconn_tcp_write(pnode);
-					if (error != ESPCONN_OK){
-						/*send the application packet fail,
-						 * ensure that each allocated is deleted*/
-						espconn_pbuf_delete(&pnode->pcommon.pbuf, pbuf);
-						os_free(pbuf);
-						pbuf = NULL;
-					}
+//					if (error != ESPCONN_OK){
+//						/*send the application packet fail,
+//						 * ensure that each allocated is deleted*/
+//						espconn_pbuf_delete(&pnode->pcommon.pbuf, pbuf);
+//						os_free(pbuf);
+//						pbuf = NULL;
+//					}
 					return error;
 				} else
 					return ESPCONN_ARG;
@@ -428,6 +436,33 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
     return ESPCONN_ARG;
 }
 
+/******************************************************************************
+ * FunctionName : espconn_sendto
+ * Description  : send data for UDP
+ * Parameters   : espconn -- espconn to set for UDP
+ *                psent -- data to send
+ *                length -- length of data to send
+ * Returns      : error
+*******************************************************************************/
+sint16 ICACHE_FLASH_ATTR
+espconn_sendto(struct espconn *espconn, uint8 *psent, uint16 length)
+{
+	espconn_msg *pnode = NULL;
+	bool value = false;
+	err_t error = ESPCONN_OK;
+
+	if (espconn == NULL || psent == NULL || length == 0) {
+		return ESPCONN_ARG;
+	}
+
+	/*Find the node depend on the espconn message*/
+	value = espconn_find_connection(espconn, &pnode);
+	if (value && espconn->type == ESPCONN_UDP)
+		return espconn_udp_sendto(pnode, psent, length);
+	else
+		return ESPCONN_ARG;
+}
+
 /******************************************************************************
  * FunctionName : espconn_send
  * Description  : sent data for client or server

+ 20 - 3
app/lwip/app/espconn_tcp.c

@@ -24,6 +24,10 @@
 #include "lwip/mem.h"
 #include "lwip/app/espconn_tcp.h"
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 extern espconn_msg *plink_active;
 extern espconn_msg *pserver_list;
 extern struct espconn_packet pktinfo[2];
@@ -71,7 +75,7 @@ espconn_kill_oldest(void)
 	inactivity = 0;
 	inactive = NULL;
 	for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
-		if (pcb->state == FIN_WAIT_2){
+		if (pcb->state == FIN_WAIT_1 || pcb->state == FIN_WAIT_2){
 			if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
 				inactivity = tcp_ticks - pcb->tmr;
 				inactive = pcb;
@@ -121,7 +125,7 @@ void ICACHE_FLASH_ATTR espconn_kill_oldest_pcb(void)
 					break;
 			}
 
-			if (cpcb->state == FIN_WAIT_2 || cpcb->state == LAST_ACK){
+			if (cpcb->state == FIN_WAIT_1 || cpcb->state == FIN_WAIT_2 || cpcb->state == LAST_ACK){
 				num_tcp_fin++;
 				if (num_tcp_fin == MEMP_NUM_TCP_PCB)
 					break;
@@ -131,6 +135,8 @@ void ICACHE_FLASH_ATTR espconn_kill_oldest_pcb(void)
 		if (num_tcp_fin == MEMP_NUM_TCP_PCB){
 			num_tcp_fin = 0;
 			espconn_kill_oldest();
+		} else if (cpcb == NULL){
+			num_tcp_fin = 0;
 		}
 	}
 }
@@ -901,7 +907,18 @@ espconn_tcp_client(struct espconn *espconn)
     	pclient->pespconn = espconn;
     	pclient->pespconn->state = ESPCONN_WAIT;
     	pclient->pcommon.pcb = pcb;
-        tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
+    	tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
+#if 0
+    	pclient->pcommon.err = tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
+    	if (pclient->pcommon.err != ERR_OK){
+    		/*remove the node from the client's active connection list*/
+    		espconn_list_delete(&plink_active, pclient);
+    		memp_free(MEMP_TCP_PCB, pcb);
+    		os_free(pclient);
+    		pclient = NULL;
+    		return ERR_USE;
+    	}
+#endif
         /*Establish the connection*/
         pclient->pcommon.err = tcp_connect(pcb, &ipaddr,
         		pclient->pespconn->proto.tcp->remote_port, espconn_client_connect);

+ 127 - 34
app/lwip/app/espconn_udp.c

@@ -22,9 +22,17 @@
 
 #include "lwip/app/espconn_udp.h"
 
-//#include "net80211/ieee80211_var.h"
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 extern espconn_msg *plink_active;
 extern uint8 default_interface;
+
+enum send_opt{
+	ESPCONN_SENDTO,
+	ESPCONN_SEND
+};
 static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
 {
     if (pespconn == NULL) {
@@ -36,7 +44,7 @@ static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
     }
 }
 
-static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg)
+static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg, enum send_opt opt)
 {
     espconn_msg *psent = arg;
 
@@ -49,7 +57,11 @@ static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg)
 //        sys_timeout(10, espconn_data_sentcb, psent->pespconn);
         espconn_data_sentcb(psent->pespconn);
     } else {
-        espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
+    	if (opt == ESPCONN_SEND){
+    		espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
+    	} else {
+    		espconn_udp_sendto(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
+    	}
     }
 }
 
@@ -82,8 +94,8 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
         return ESPCONN_ARG;
     }
 
-    if (TCP_MSS < length) {
-        datalen = TCP_MSS;
+    if (1470 < length) {
+        datalen = 1470;
     } else {
         datalen = length;
     }
@@ -145,7 +157,9 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
         pbuf_free(p);
         pudp_sent->pcommon.ptrbuf = psent + datalen;
         pudp_sent->pcommon.cntr = length - datalen;
-        espconn_data_sent(pudp_sent);
+        espconn_data_sent(pudp_sent, ESPCONN_SEND);
+        if (err > 0)
+        	return ESPCONN_IF;
         return err;
     } else {
     	pbuf_free(p);
@@ -153,6 +167,108 @@ espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
     }
 }
 
+/******************************************************************************
+ * FunctionName : espconn_udp_sendto
+ * Description  : sent data for UDP
+ * Parameters   : void *arg -- UDP to send
+ * 				  uint8* psent -- Data to send
+ *                uint16 length -- Length of data to send
+ * Returns      : return espconn error code.
+ * - ESPCONN_OK. Successful. No error occured.
+ * - ESPCONN_MEM. Out of memory.
+ * - ESPCONN_RTE. Could not find route to destination address.
+ * - More errors could be returned by lower protocol layers.
+*******************************************************************************/
+err_t ICACHE_FLASH_ATTR
+espconn_udp_sendto(void *arg, uint8 *psent, uint16 length)
+{
+    espconn_msg *pudp_sent = arg;
+    struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
+    struct espconn *pespconn = pudp_sent->pespconn;
+    struct pbuf *p, *q ,*p_temp;
+    struct ip_addr dst_ip;
+    u16_t dst_port;
+    u8_t *data = NULL;
+    u16_t cnt = 0;
+    u16_t datalen = 0;
+    u16_t i = 0;
+    err_t err;
+    LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
+
+    if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
+        return ESPCONN_ARG;
+    }
+
+    if (1470 < length) {
+        datalen = 1470;
+    } else {
+        datalen = length;
+    }
+
+    p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
+    LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
+
+    if (p != NULL) {
+        q = p;
+
+        while (q != NULL) {
+            data = (u8_t *)q->payload;
+            LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
+
+            for (i = 0; i < q->len; i++) {
+                data[i] = ((u8_t *) psent)[cnt++];
+            }
+
+            q = q->next;
+        }
+    } else {
+        return ESPCONN_MEM;
+    }
+
+    dst_port = pespconn->proto.udp->remote_port;
+    IP4_ADDR(&dst_ip, pespconn->proto.udp->remote_ip[0],
+			pespconn->proto.udp->remote_ip[1], pespconn->proto.udp->remote_ip[2],
+			pespconn->proto.udp->remote_ip[3]);
+    LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
+
+    struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
+	struct netif *ap_netif =  (struct netif *)eagle_lwip_getif(0x01);
+
+    if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
+	{
+		if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
+			ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
+			ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
+
+		  p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
+		  if (pbuf_copy (p_temp,p) != ERR_OK) {
+			  LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sendto: copying to new pbuf failed\n"));
+			  return ESPCONN_ARG;
+		  }
+		  netif_set_default(sta_netif);
+		  err = udp_sendto(upcb, p_temp, &dst_ip, dst_port);
+		  pbuf_free(p_temp);
+		  netif_set_default(ap_netif);
+		}
+	}
+    err = udp_sendto(upcb, p, &dst_ip, dst_port);
+
+    if (p->ref != 0) {
+    	pbuf_free(p);
+    	pudp_sent->pcommon.ptrbuf = psent + datalen;
+		pudp_sent->pcommon.cntr = length - datalen;
+		if (err == ERR_OK)
+			espconn_data_sent(pudp_sent, ESPCONN_SENDTO);
+
+		if (err > 0)
+			return ESPCONN_IF;
+		return err;
+    } else {
+    	pbuf_free(p);
+    	return ESPCONN_RTE;
+    }
+}
+
 /******************************************************************************
  * FunctionName : espconn_udp_server_recv
  * Description  : This callback will be called when receiving a datagram.
@@ -175,15 +291,10 @@ espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
 
     LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb));
 
-    upcb->remote_port = port;
-    upcb->remote_ip = *addr;
-
-    precv->pcommon.remote_ip[0] = ip4_addr1_16(&upcb->remote_ip);
-    precv->pcommon.remote_ip[1] = ip4_addr2_16(&upcb->remote_ip);
-    precv->pcommon.remote_ip[2] = ip4_addr3_16(&upcb->remote_ip);
-    precv->pcommon.remote_ip[3] = ip4_addr4_16(&upcb->remote_ip);
-    os_memcpy(precv->pespconn->proto.udp->remote_ip, precv->pcommon.remote_ip, 4);
-    precv->pespconn->proto.udp->remote_port = port;
+    precv->pcommon.remote_ip[0] = ip4_addr1_16(addr);
+    precv->pcommon.remote_ip[1] = ip4_addr2_16(addr);
+    precv->pcommon.remote_ip[2] = ip4_addr3_16(addr);
+    precv->pcommon.remote_ip[3] = ip4_addr4_16(addr);
     precv->pcommon.remote_port = port;
     precv->pcommon.pcb = upcb;
 
@@ -196,31 +307,13 @@ espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
 	} else {
 		wifi_get_ip_info(0, &ipconfig);
 	}
-//	upcb->local_ip = ipconfig.ip;
+
 	precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&ipconfig.ip);
 	precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&ipconfig.ip);
 	precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&ipconfig.ip);
 	precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&ipconfig.ip);
 
     if (p != NULL) {
-//        q = p;
-
-//        while (q != NULL) {
-//            pdata = (u8_t *)os_zalloc(q ->len + 1);
-//            length = pbuf_copy_partial(q, pdata, q ->len, 0);
-//
-//            LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %x\n", __LINE__, length));
-//            precv->pcommon.pcb = upcb;
-//
-//            if (length != 0) {
-//                if (precv->pespconn->recv_callback != NULL) {
-//                    precv->pespconn->recv_callback(precv->pespconn, pdata, length);
-//                }
-//            }
-//
-//            q = q->next;
-//            os_free(pdata);
-//        }
     	pdata = (u8_t *)os_zalloc(p ->tot_len + 1);
     	length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
     	precv->pcommon.pcb = upcb;

+ 6 - 2
app/lwip/app/netio.c

@@ -35,6 +35,10 @@
 #if LWIP_TCP
 #include "lwip/tcp.h"
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /*
  * This implements a netio server.
  *  The client sends a command word (4 bytes) then a data length word (4 bytes).
@@ -321,7 +325,7 @@ netio_accept(void *arg, struct tcp_pcb *pcb, err_t err)
 
   LWIP_UNUSED_ARG(err);
 
-  ns = mem_malloc(sizeof(struct netio_state));
+  ns = (struct netio_state *)mem_malloc(sizeof(struct netio_state));
 
   if(ns == NULL){
     return ERR_MEM;
@@ -335,7 +339,7 @@ netio_accept(void *arg, struct tcp_pcb *pcb, err_t err)
 #if NETIO_USE_STATIC_BUF == 1
   ns->buf_ptr = netio_buf;
 #else
-  ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE);
+  ns->buf_ptr = (u8_t *)mem_malloc(NETIO_BUF_SIZE);
 
   if(ns->buf_ptr == NULL){
     mem_free(ns);

+ 4 - 0
app/lwip/app/ping.c

@@ -63,6 +63,10 @@
 #include "lwip/inet.h"
 #endif /* PING_USE_SOCKETS */
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /* ping variables */
 static u16_t ping_seq_num = 0;
 static u32_t ping_time;

+ 14 - 0
app/lwip/core/dhcp.c

@@ -84,6 +84,10 @@
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /** Default for DHCP_GLOBAL_XID is 0xABCD0000
  * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
  *  #define DHCP_GLOBAL_XID_HEADER "stdlib.h"
@@ -377,6 +381,15 @@ dhcp_fine_tmr()
   while (netif != NULL) {
     /* only act on DHCP configured interfaces */
     if (netif->dhcp != NULL) {
+      /*add DHCP retries processing by LiuHan*/
+      if (DHCP_MAXRTX != 0) {
+    	  if (netif->dhcp->tries >= DHCP_MAXRTX){
+			  os_printf("DHCP timeout\n");
+			  if (netif->dhcp_event != NULL)
+				  netif->dhcp_event();
+			  break;
+		  }
+      }
       /* timer is active (non zero), and is about to trigger now */      
       if (netif->dhcp->request_timeout > 1) {
         netif->dhcp->request_timeout--;
@@ -392,6 +405,7 @@ dhcp_fine_tmr()
     /* proceed to next network interface */
     netif = netif->next;
   }
+
 }
 
 /**

+ 4 - 0
app/lwip/core/dns.c

@@ -83,6 +83,10 @@
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /** DNS server IP address */
 #ifndef DNS_SERVER_ADDRESS
 #define DNS_SERVER_ADDRESS(ipaddr)        (ip4_addr_set_u32(ipaddr, 0xDEDE43D0)) /* resolver1.opendns.com(208.67.222.222) */

+ 1 - 1
app/lwip/core/init.c

@@ -261,7 +261,7 @@ lwip_init(void)
 {
   MEMP_NUM_TCP_PCB = 5;
   TCP_WND = (4 * TCP_MSS);
-  TCP_MAXRTX = 3;
+  TCP_MAXRTX = 12;
   TCP_SYNMAXRTX = 6;
 
   /* Sanity check user-configurable values */

+ 4 - 0
app/lwip/core/ipv4/igmp.c

@@ -95,6 +95,10 @@ Steve Reynolds
 
 #include "string.h"
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /* 
  * IGMP constants
  */

+ 32 - 5
app/lwip/core/mdns.c

@@ -49,6 +49,11 @@
 #include "osapi.h"
 #include "os_type.h"
 #include "user_interface.h"
+
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /** DNS server IP address */
 #ifndef DNS_MULTICAST_ADDRESS
 #define DNS_MULTICAST_ADDRESS        ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
@@ -971,11 +976,21 @@ mdns_get_servername(void) {
 
 void ICACHE_FLASH_ATTR
 mdns_server_unregister(void) {
+	struct ip_addr ap_host_addr;
+	struct ip_info ipconfig;
 	if(register_flag == 1){
 		if (igmp_leavegroup(&host_addr, &multicast_addr) != ERR_OK) {
-			os_printf("udp_leave_multigrup failed!\n");
+			os_printf("sta udp_leave_multigrup failed!\n");
 			return;
 		};
+		if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
+		   wifi_get_ip_info(SOFTAP_IF, &ipconfig);
+		   ap_host_addr.addr = ipconfig.ip.addr;
+		   if (igmp_leavegroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
+				os_printf("ap udp_join_multigrup failed!\n");
+				return;
+			};
+		}
 		register_flag = 0;
 	}
 }
@@ -1013,6 +1028,8 @@ void ICACHE_FLASH_ATTR
 mdns_init(struct mdns_info *info) {
 	/* initialize default DNS server address */
 	multicast_addr.addr = DNS_MULTICAST_ADDRESS;
+	struct ip_addr ap_host_addr;
+	struct ip_info ipconfig;
 	if (info->ipAddr == 0) {
 		os_printf("mdns ip error!\n ");
 		return;
@@ -1040,10 +1057,20 @@ mdns_init(struct mdns_info *info) {
 
 	if (mdns_pcb != NULL) {
 		/* join to the multicast address 224.0.0.251 */
-		if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
-			os_printf("udp_join_multigrup failed!\n");
-			return;
-		};
+		if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x01) {
+			if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
+				os_printf("sta udp_join_multigrup failed!\n");
+				return;
+			};
+		}
+		if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
+		   wifi_get_ip_info(SOFTAP_IF, &ipconfig);
+		   ap_host_addr.addr = ipconfig.ip.addr;
+		   if (igmp_joingroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
+				os_printf("ap udp_join_multigrup failed!\n");
+				return;
+			};
+		}
 		register_flag = 1;
 		/* join to any IP address at the port 5353 */
 		if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {

+ 43 - 0
app/lwip/core/pbuf.c

@@ -79,6 +79,10 @@
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 #ifdef EBUF_LWIP
 #define EP_OFFSET 36
 #else
@@ -90,6 +94,45 @@
    aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
 #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
 
+/**
+ * Attempt to reclaim some memory from queued out-of-sequence TCP segments
+ * if we run out of pool pbufs. It's better to give priority to new packets
+ * if we're running out.
+ */
+#if TCP_QUEUE_OOSEQ
+void ICACHE_FLASH_ATTR
+pbuf_free_ooseq_new(void* arg)
+{
+  struct tcp_pcb* pcb;
+  struct tcp_seg *head = NULL;
+  struct tcp_seg *seg1 = NULL;
+  struct tcp_seg *seg2 = NULL;
+  for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
+	  head = pcb->ooseq;
+	  seg1 = head;
+	  if (head != NULL) {
+		  if (seg1->next == NULL){
+			  head = head->next;
+			  tcp_seg_free(seg1);
+			  pcb->ooseq = head;
+		  } else {
+			  while (seg1 != NULL){
+				  seg2 = seg1;
+				  seg2 = seg2->next;
+				  if (seg2 ->next == NULL){
+					  seg1->next = seg2->next;
+					  tcp_seg_free(seg2);
+					  break;
+				  }
+				  seg1 = seg1->next;
+			  }
+			  pcb->ooseq = head;
+		  }
+	  }
+  }
+}
+#endif
+
 #if !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS
 #define PBUF_POOL_IS_EMPTY()
 #else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */

+ 4 - 0
app/lwip/core/raw.c

@@ -52,6 +52,10 @@
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /** The list of RAW PCBs */
 static struct raw_pcb *raw_pcbs;
 

+ 4 - 0
app/lwip/core/tcp.c

@@ -55,6 +55,10 @@
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 #if TCP_DEBUG
 const char tcp_state_str_rodata[][12] ICACHE_RODATA_ATTR = {
   "CLOSED",      

+ 14 - 0
app/lwip/core/tcp_in.c

@@ -56,6 +56,10 @@
 #include "lwip/snmp.h"
 #include "arch/perf.h"
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /* These variables are global to all functions involved in the input
    processing of TCP segments. They are set by the tcp_input()
    function. */
@@ -436,6 +440,16 @@ aborted:
       pbuf_free(inseg.p);//�ͷ�buffer
       inseg.p = NULL;
     }
+
+    /*add processing queue segments that arrive out of order by LiuHan*/
+#if TCP_QUEUE_OOSEQ
+    extern char RxNodeNum(void);
+    if (RxNodeNum() < 2){
+    	extern void pbuf_free_ooseq_new(void* arg);
+//    	os_printf("reclaim some memory from queued\n");
+    	pbuf_free_ooseq_new(NULL);
+    }
+#endif
   } else {
 
     /* If no matching PCB was found, send a TCP RST (reset) to the

+ 17 - 10
app/lwip/core/tcp_out.c

@@ -52,9 +52,14 @@
 #include "lwip/inet_chksum.h"
 #include "lwip/stats.h"
 #include "lwip/snmp.h"
+#include "netif/etharp.h"
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /* Define some copy-macros for checksum-on-copy so that the code looks
    nicer by preventing too many ifdef's. */
 #if TCP_CHECKSUM_ON_COPY
@@ -226,16 +231,7 @@ tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
   LWIP_UNUSED_ARG(apiflags);
   LWIP_UNUSED_ARG(first_seg);
   /* always create MSS-sized pbufs */
-#ifdef ESP_MESH_SUPPORT
-  if (espconn_mesh_is_on()) {
-	  if (alloc > TCP_MSS)
-	    alloc = TCP_MSS;
-  } else {
-	  alloc = TCP_MSS;
-  }
-#else
   alloc = TCP_MSS;
-#endif
 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
   if (length < max_length) {
     /* Should we allocate an oversized pbuf, or just the minimum
@@ -1451,6 +1447,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
   struct pbuf *p;
   struct tcp_hdr *tcphdr;
   struct tcp_seg *seg;
+  u16_t  offset = 0;
   u16_t len;
   u8_t is_fin;
 
@@ -1469,6 +1466,11 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
 
   if(seg == NULL) {
     seg = pcb->unsent;
+  } else {
+	  struct ip_hdr *iphdr = NULL;
+	  iphdr = (struct ip_hdr *)((char*)seg->p->payload + SIZEOF_ETH_HDR);
+	  offset = IPH_HL(iphdr)*4;
+	  offset += SIZEOF_ETH_HDR;
   }
   if(seg == NULL) {
     return;
@@ -1492,7 +1494,12 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
     /* Data segment, copy in one byte from the head of the unacked queue */
     struct tcp_hdr *thdr = (struct tcp_hdr *)seg->p->payload;
     char *d = ((char *)p->payload + TCP_HLEN);
-    pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4);
+    if (pcb->unacked == NULL)
+    	pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4);
+    else {
+    	thdr = (struct tcp_hdr *)((char*)seg->p->payload + offset);
+    	pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4 + offset);
+    }
   }
 
 #if CHECKSUM_GEN_TCP

+ 6 - 2
app/lwip/core/timers.c

@@ -57,6 +57,9 @@
 #include "lwip/igmp.h"
 #include "lwip/dns.h"
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
 
 /** The one and only timeout list */
 static struct sys_timeo *next_timeout = NULL;
@@ -245,6 +248,7 @@ void sys_timeouts_init(void)
   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
 #endif /* LWIP_ARP */
 #if LWIP_DHCP
+  DHCP_MAXRTX = 0;
   sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
   sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
 #endif /* LWIP_DHCP */
@@ -259,8 +263,8 @@ void sys_timeouts_init(void)
 #endif /* LWIP_DNS */
 
 #if LWIP_TCP
-  //sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
-  sys_timeout(TCP_TMR_INTERVAL, tcp_timer_coarse, NULL);
+  sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
+//  sys_timeout(TCP_TMR_INTERVAL, tcp_timer_coarse, NULL);
 #endif
 
 #if NO_SYS

+ 4 - 0
app/lwip/core/udp.c

@@ -64,6 +64,10 @@
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 /* The list of UDP PCBs */
 /* exported in udp.h (was static) */
 struct udp_pcb *udp_pcbs;

+ 4 - 0
app/lwip/netif/etharp.c

@@ -62,6 +62,10 @@
 
 #include <string.h>
 
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
 const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
 const struct eth_addr ethzero = {{0,0,0,0,0,0}};
 

+ 1 - 0
sdk/esp_iot_sdk_v1.4.0/include/user_interface.h

@@ -275,6 +275,7 @@ struct station_info {
 };
 
 struct dhcps_lease {
+	bool enable;
 	struct ip_addr start_ip;
 	struct ip_addr end_ip;
 };