From c674d191e481495b0568cc2c4a04bd33028f4402 Mon Sep 17 00:00:00 2001 From: Johny Mattsson Date: Thu, 1 Oct 2015 15:07:16 +1000 Subject: [PATCH] Upgraded open-source LWIP. From Espressif's lwip_open_src_template_proj_for_v1.3.0.zip --- app/driver/uart.c | 4 + app/include/lwip/app/dhcpserver.h | 193 ++--- app/include/lwip/app/espconn.h | 281 ++++++- app/include/lwip/app/espconn_tcp.h | 98 +-- app/include/lwip/app/espconn_udp.h | 102 +-- app/include/lwip/dhcp.h | 9 + app/include/lwip/igmp.h | 2 +- app/include/lwip/mdns.h | 114 +++ app/include/lwip/memp.h | 2 +- app/include/lwip/netif.h | 1 + app/include/lwip/puck_def.h | 44 ++ app/include/lwip/sntp.h | 56 ++ app/include/lwip/sys.h | 4 +- app/include/lwip/tcp.h | 2 - app/include/lwip/tcp_impl.h | 6 +- app/include/mem_manager.h | 162 ++-- app/lwip/Makefile | 100 +-- app/lwip/api/Makefile | 92 +-- app/lwip/app/Makefile | 92 +-- app/lwip/app/dhcpserver.c | 290 +++++-- app/lwip/app/dummy.c | 10 - app/lwip/app/espconn.c | 693 ++++++++++++++--- app/lwip/app/espconn_mdns.c | 134 ++++ app/lwip/app/espconn_tcp.c | 851 +++++++++++++++------ app/lwip/app/espconn_udp.c | 628 ++++++++-------- app/lwip/app/netio.c | 730 +++++++++--------- app/lwip/app/ping.c | 5 +- app/lwip/core/Makefile | 92 +-- app/lwip/core/dhcp.c | 63 +- app/lwip/core/dns.c | 42 +- app/lwip/core/init.c | 18 +- app/lwip/core/ipv4/Makefile | 92 +-- app/lwip/core/ipv4/autoip.c | 4 +- app/lwip/core/ipv4/ip.c | 10 +- app/lwip/core/ipv4/ip_addr.c | 29 +- app/lwip/core/ipv4/ip_frag.c | 2 +- app/lwip/core/mdns.c | 1068 ++++++++++++++++++++++++++ app/lwip/core/mem.c | 2 +- app/lwip/core/memp.c | 6 +- app/lwip/core/netif.c | 1 + app/lwip/core/pbuf.c | 6 +- app/lwip/core/raw.c | 2 +- app/lwip/core/sntp.c | 1128 ++++++++++++++++++++++++++++ app/lwip/core/sys_arch.c | 26 +- app/lwip/core/tcp.c | 31 +- app/lwip/core/tcp_in.c | 261 +++---- app/lwip/core/tcp_out.c | 100 ++- app/lwip/core/timers.c | 4 +- app/lwip/core/udp.c | 11 +- app/lwip/netif/Makefile | 92 +-- app/lwip/netif/etharp.c | 76 +- 51 files changed, 5957 insertions(+), 1914 deletions(-) create mode 100644 app/include/lwip/mdns.h create mode 100644 app/include/lwip/puck_def.h create mode 100644 app/include/lwip/sntp.h delete mode 100644 app/lwip/app/dummy.c create mode 100644 app/lwip/app/espconn_mdns.c create mode 100644 app/lwip/core/mdns.c create mode 100644 app/lwip/core/sntp.c diff --git a/app/driver/uart.c b/app/driver/uart.c index 9e773054..3210bd01 100644 --- a/app/driver/uart.c +++ b/app/driver/uart.c @@ -17,6 +17,10 @@ #define UART0 0 #define UART1 1 +#ifndef FUNC_U0RXD +#define FUNC_U0RXD 0 +#endif + // UartDev is defined and initialized in rom code. extern UartDevice UartDev; diff --git a/app/include/lwip/app/dhcpserver.h b/app/include/lwip/app/dhcpserver.h index 0159d1de..8e68e3e0 100644 --- a/app/include/lwip/app/dhcpserver.h +++ b/app/include/lwip/app/dhcpserver.h @@ -1,94 +1,99 @@ -#ifndef __DHCPS_H__ -#define __DHCPS_H__ - -typedef struct dhcps_state{ - sint16_t state; -} dhcps_state; - -// ����dhcpclient�Զ����һ��DHCP msg�ṹ�� -typedef struct dhcps_msg { - uint8_t op, htype, hlen, hops; - uint8_t xid[4]; - uint16_t secs, flags; - uint8_t ciaddr[4]; - uint8_t yiaddr[4]; - uint8_t siaddr[4]; - uint8_t giaddr[4]; - uint8_t chaddr[16]; - uint8_t sname[64]; - uint8_t file[128]; - uint8_t options[312]; -}dhcps_msg; - -#ifndef LWIP_OPEN_SRC -struct dhcps_lease { - uint32 start_ip; - uint32 end_ip; -}; -#endif - -struct dhcps_pool{ - struct ip_addr ip; - uint8 mac[6]; - uint32 lease_timer; -}; - -typedef struct _list_node{ - void *pnode; - struct _list_node *pnext; -}list_node; - -#define DHCPS_LEASE_TIMER 0x05A0 -#define DHCPS_MAX_LEASE 0x64 -#define BOOTP_BROADCAST 0x8000 - -#define DHCP_REQUEST 1 -#define DHCP_REPLY 2 -#define DHCP_HTYPE_ETHERNET 1 -#define DHCP_HLEN_ETHERNET 6 -#define DHCP_MSG_LEN 236 - -#define DHCPS_SERVER_PORT 67 -#define DHCPS_CLIENT_PORT 68 - -/* - * Advertise DNS capability in DHCP OFFER - */ -#define USE_DNS 0 - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPDECLINE 4 -#define DHCPACK 5 -#define DHCPNAK 6 -#define DHCPRELEASE 7 - -#define DHCP_OPTION_SUBNET_MASK 1 -#define DHCP_OPTION_ROUTER 3 -#define DHCP_OPTION_DNS_SERVER 6 -#define DHCP_OPTION_REQ_IPADDR 50 -#define DHCP_OPTION_LEASE_TIME 51 -#define DHCP_OPTION_MSG_TYPE 53 -#define DHCP_OPTION_SERVER_ID 54 -#define DHCP_OPTION_INTERFACE_MTU 26 -#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 -#define DHCP_OPTION_BROADCAST_ADDRESS 28 -#define DHCP_OPTION_REQ_LIST 55 -#define DHCP_OPTION_END 255 - -//#define USE_CLASS_B_NET 1 -#define DHCPS_DEBUG 0 - - -#define DHCPS_STATE_OFFER 1 -#define DHCPS_STATE_DECLINE 2 -#define DHCPS_STATE_ACK 3 -#define DHCPS_STATE_NAK 4 -#define DHCPS_STATE_IDLE 5 - -void dhcps_start(struct ip_info *info); -void dhcps_stop(void); - -#endif - +#ifndef __DHCPS_H__ +#define __DHCPS_H__ + +#define USE_DNS + +typedef struct dhcps_state{ + sint16_t state; +} dhcps_state; + +// ����dhcpclient�Զ����һ��DHCP msg�ṹ�� +typedef struct dhcps_msg { + uint8_t op, htype, hlen, hops; + uint8_t xid[4]; + uint16_t secs, flags; + uint8_t ciaddr[4]; + uint8_t yiaddr[4]; + uint8_t siaddr[4]; + uint8_t giaddr[4]; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + uint8_t options[312]; +}dhcps_msg; + +#ifndef LWIP_OPEN_SRC +struct dhcps_lease { + struct ip_addr start_ip; + struct ip_addr end_ip; +}; + +enum dhcps_offer_option{ + OFFER_START = 0x00, + OFFER_ROUTER = 0x01, + OFFER_END +}; +#endif + +struct dhcps_pool{ + struct ip_addr ip; + uint8 mac[6]; + uint32 lease_timer; +}; + +typedef struct _list_node{ + void *pnode; + struct _list_node *pnext; +}list_node; + +#define DHCPS_LEASE_TIMER 0x05A0 +#define DHCPS_MAX_LEASE 0x64 +#define BOOTP_BROADCAST 0x8000 + +#define DHCP_REQUEST 1 +#define DHCP_REPLY 2 +#define DHCP_HTYPE_ETHERNET 1 +#define DHCP_HLEN_ETHERNET 6 +#define DHCP_MSG_LEN 236 + +#define DHCPS_SERVER_PORT 67 +#define DHCPS_CLIENT_PORT 68 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 + +#define DHCP_OPTION_SUBNET_MASK 1 +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_REQ_IPADDR 50 +#define DHCP_OPTION_LEASE_TIME 51 +#define DHCP_OPTION_MSG_TYPE 53 +#define DHCP_OPTION_SERVER_ID 54 +#define DHCP_OPTION_INTERFACE_MTU 26 +#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31 +#define DHCP_OPTION_BROADCAST_ADDRESS 28 +#define DHCP_OPTION_REQ_LIST 55 +#define DHCP_OPTION_END 255 + +//#define USE_CLASS_B_NET 1 +#define DHCPS_DEBUG 0 +#define MAX_STATION_NUM 8 + +#define DHCPS_STATE_OFFER 1 +#define DHCPS_STATE_DECLINE 2 +#define DHCPS_STATE_ACK 3 +#define DHCPS_STATE_NAK 4 +#define DHCPS_STATE_IDLE 5 + +#define dhcps_router_enabled(offer) ((offer & OFFER_ROUTER) != 0) + +void dhcps_start(struct ip_info *info); +void dhcps_stop(void); + +#endif + diff --git a/app/include/lwip/app/espconn.h b/app/include/lwip/app/espconn.h index 6eda9e3a..91304ed2 100644 --- a/app/include/lwip/app/espconn.h +++ b/app/include/lwip/app/espconn.h @@ -21,7 +21,8 @@ typedef void (* espconn_reconnect_callback)(void *arg, sint8 err); #define ESPCONN_MEM -1 /* Out of memory error. */ #define ESPCONN_TIMEOUT -3 /* Timeout. */ #define ESPCONN_RTE -4 /* Routing problem. */ -#define ESPCONN_INPROGRESS -5 /* Operation in progress */ +#define ESPCONN_INPROGRESS -5 /* Operation in progress */ +#define ESPCONN_MAXNUM -7 /* Total number exceeds the set maximum*/ #define ESPCONN_ABRT -8 /* Connection aborted. */ #define ESPCONN_RST -9 /* Connection reset. */ @@ -31,6 +32,10 @@ typedef void (* espconn_reconnect_callback)(void *arg, sint8 err); #define ESPCONN_ARG -12 /* Illegal argument. */ #define ESPCONN_ISCONN -15 /* Already connected. */ +#define ESPCONN_HANDSHAKE -28 /* ssl handshake failed */ +#define ESPCONN_RESP_TIMEOUT -29 /* ssl handshake no response*/ +#define ESPCONN_PROTO_MSG -61 /* ssl application invalid */ + #define ESPCONN_SSL 0x01 #define ESPCONN_NORM 0x00 @@ -69,6 +74,7 @@ typedef struct _esp_tcp { espconn_connect_callback connect_callback; espconn_reconnect_callback reconnect_callback; espconn_connect_callback disconnect_callback; + espconn_connect_callback write_finish_fn; } esp_tcp; typedef struct _esp_udp { @@ -106,34 +112,107 @@ struct espconn { }; enum espconn_option{ - ESPCONN_REUSEADDR = 1, + ESPCONN_START = 0x00, + ESPCONN_REUSEADDR = 0x01, + ESPCONN_NODELAY = 0x02, + ESPCONN_COPY = 0x04, + ESPCONN_KEEPALIVE = 0x08, ESPCONN_END }; +enum espconn_level{ + ESPCONN_KEEPIDLE, + ESPCONN_KEEPINTVL, + ESPCONN_KEEPCNT +}; + +struct espconn_packet{ + uint16 sent_length; /* sent length successful*/ + uint16 snd_buf_size; /* Available buffer size for sending */ + uint16 snd_queuelen; /* Available buffer space for sending */ + uint16 total_queuelen; /* total Available buffer space for sending */ + uint32 packseqno; /* seqno to be sent */ + uint32 packseq_nxt; /* seqno expected */ + uint32 packnum; +}; + +typedef struct _espconn_buf{ + uint8 *payload; + uint8 *punsent; + uint16 unsent; + uint16 len; + uint16 tot_len; + struct _espconn_buf *pnext; +} espconn_buf; + typedef struct _comon_pkt{ void *pcb; int remote_port; uint8 remote_ip[4]; - uint8 *ptrbuf; + uint32 local_port; + uint32 local_ip; + espconn_buf *pbuf; + espconn_buf *ptail; + uint8* ptrbuf; uint16 cntr; - uint16 write_len; - uint16 write_total; sint8 err; uint32 timeout; uint32 recv_check; + uint8 pbuf_num; + struct espconn_packet packet_info; + bool write_flag; enum espconn_option espconn_opt; - os_timer_t ptimer; }comon_pkt; typedef struct _espconn_msg{ struct espconn *pespconn; comon_pkt pcommon; uint8 count_opt; + sint16_t hs_status; //the status of the handshake void *preverse; void *pssl; struct _espconn_msg *pnext; + +//***********Code for WIFI_BLOCK from upper************** + uint8 recv_hold_flag; + uint16 recv_holded_buf_Len; }espconn_msg; +#ifndef _MDNS_INFO +#define _MDNS_INFO +struct mdns_info { + char *host_name; + char *server_name; + uint16 server_port; + unsigned long ipAddr; + char *txt_data[10]; +}; +#endif + +#define linkMax 15 + +#define espconn_delay_disabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_NODELAY) != 0) +#define espconn_delay_enabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_NODELAY) == 0) +#define espconn_reuse_disabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_REUSEADDR) != 0) +#define espconn_copy_disabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_COPY) != 0) +#define espconn_copy_enabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_COPY) == 0) +#define espconn_keepalive_disabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_KEEPALIVE) != 0) +#define espconn_keepalive_enabled(espconn) (((espconn)->pcommon.espconn_opt & ESPCONN_KEEPALIVE) == 0) + +#define espconn_TaskPrio 26 +#define espconn_TaskQueueLen 15 + +enum espconn_sig { + SIG_ESPCONN_NONE, + SIG_ESPCONN_ERRER, + SIG_ESPCONN_LISTEN, + SIG_ESPCONN_CONNECT, + SIG_ESPCONN_WRITE, + SIG_ESPCONN_SEND, + SIG_ESPCONN_READ, + SIG_ESPCONN_CLOSE +}; + /****************************************************************************** * FunctionName : espconn_copy_partial * Description : reconnect with host @@ -181,6 +260,16 @@ bool espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode); sint8 espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, uint8 typeflags); +/****************************************************************************** + * FunctionName : espconn_get_packet_info + * Description : get the packet info with host + * Parameters : espconn -- the espconn used to disconnect the connection + * infoarg -- the packet info + * Returns : the errur code +*******************************************************************************/ + +sint8 espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg); + /****************************************************************************** * FunctionName : espconn_connect * Description : The function given as the connect @@ -226,6 +315,23 @@ extern sint8 espconn_accept(struct espconn *espconn); extern sint8 espconn_create(struct espconn *espconn); +/****************************************************************************** + * FunctionName : espconn_tcp_get_wnd + * Description : get the window size of simulatenously active TCP connections + * Parameters : none + * Returns : the number of TCP_MSS active TCP connections +*******************************************************************************/ +extern uint8 espconn_tcp_get_wnd(void); + +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_con + * Description : set the window size simulatenously active TCP connections + * Parameters : num -- the number of TCP_MSS + * Returns : ESPCONN_ARG -- Illegal argument + * ESPCONN_OK -- No error +*******************************************************************************/ +extern sint8 espconn_tcp_set_wnd(uint8 num); + /****************************************************************************** * FunctionName : espconn_tcp_get_max_con * Description : get the number of simulatenously active TCP connections @@ -243,6 +349,42 @@ extern uint8 espconn_tcp_get_max_con(void); *******************************************************************************/ extern sint8 espconn_tcp_set_max_con(uint8 num); + +/****************************************************************************** + * FunctionName : espconn_tcp_get_max_retran + * Description : get the Maximum number of retransmissions of data active TCP connections + * Parameters : none + * Returns : the Maximum number of retransmissions +*******************************************************************************/ +extern uint8 espconn_tcp_get_max_retran(void); + +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_retran + * Description : set the Maximum number of retransmissions of data active TCP connections + * Parameters : num -- the Maximum number of retransmissions + * Returns : result +*******************************************************************************/ + +extern sint8 espconn_tcp_set_max_retran(uint8 num); + +/****************************************************************************** + * FunctionName : espconn_tcp_get_max_syn + * Description : get the Maximum number of retransmissions of SYN segments + * Parameters : none + * Returns : the Maximum number of retransmissions +*******************************************************************************/ + +extern uint8 espconn_tcp_get_max_syn(void); + +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_syn + * Description : set the Maximum number of retransmissions of SYN segments + * Parameters : num -- the Maximum number of retransmissions + * Returns : result +*******************************************************************************/ + +extern sint8 espconn_tcp_set_max_syn(uint8 num); + /****************************************************************************** * FunctionName : espconn_tcp_get_max_con_allow * Description : get the count of simulatenously active connections on the server @@ -261,6 +403,16 @@ extern sint8 espconn_tcp_get_max_con_allow(struct espconn *espconn); extern sint8 espconn_tcp_set_max_con_allow(struct espconn *espconn, uint8 num); +/****************************************************************************** + * FunctionName : espconn_tcp_set_buf_count + * Description : set the total number of espconn_buf on the unsent lists + * Parameters : espconn -- espconn to set the count + * num -- the total number of espconn_buf + * Returns : result +*******************************************************************************/ + +extern sint8 espconn_tcp_set_buf_count(struct espconn *espconn, uint8 num); + /****************************************************************************** * FunctionName : espconn_regist_time * Description : used to specify the time that should be called when don't recv data @@ -283,6 +435,17 @@ extern sint8 espconn_regist_time(struct espconn *espconn, uint32 interval, uint8 extern sint8 espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb); +/****************************************************************************** + * FunctionName : espconn_regist_sentcb + * Description : Used to specify the function that should be called when data + * has been successfully delivered to the remote host. + * Parameters : espconn -- espconn to set the sent callback + * sent_cb -- sent callback function to call for this espconn + * when data is successfully sent + * Returns : none +*******************************************************************************/ +extern sint8 espconn_regist_write_finish(struct espconn *espconn, espconn_connect_callback write_finish_fn); + /****************************************************************************** * FunctionName : espconn_sent * Description : sent data for client or server @@ -356,6 +519,27 @@ extern uint32 espconn_port(void); *******************************************************************************/ extern sint8 espconn_set_opt(struct espconn *espconn, uint8 opt); +/****************************************************************************** + * FunctionName : espconn_set_keepalive + * Description : access level value for connection so that we set the value for + * keep alive + * Parameters : espconn -- the espconn used to set the connection + * level -- the connection's level + * value -- the value of time(s) + * Returns : access port value +*******************************************************************************/ +extern sint8 espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg); + +/****************************************************************************** + * FunctionName : espconn_get_keepalive + * Description : access level value for connection so that we get the value for + * keep alive + * Parameters : espconn -- the espconn used to get the connection + * level -- the connection's level + * Returns : access keep alive value +*******************************************************************************/ +extern sint8 espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg); + /****************************************************************************** * FunctionName : espconn_gethostbyname * Description : Resolve a hostname (string) into an IP address. @@ -395,20 +579,85 @@ extern sint8 espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip); extern sint8 espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip); /****************************************************************************** - * FunctionName : espconn_recv_hold - * Description : hold tcp receive - * Parameters : espconn -- espconn to hold + * FunctionName : espconn_mdns_init + * Description : register a device with mdns + * Parameters : ipAddr -- the ip address of device + * hostname -- the hostname of device * Returns : none *******************************************************************************/ -extern sint8 espconn_recv_hold(struct espconn *pespconn); - +extern void espconn_mdns_init(struct mdns_info *info); /****************************************************************************** - * FunctionName : espconn_recv_unhold - * Description : unhold tcp receive - * Parameters : espconn -- espconn to unhold + * FunctionName : espconn_mdns_init + * Description : close mdns socket + * Parameters : void * Returns : none *******************************************************************************/ -extern sint8 espconn_recv_unhold(struct espconn *pespconn); - +extern void espconn_mdns_close(void); +/****************************************************************************** + * FunctionName : mdns_server_register + * Description : register a server and join a multicast group + * Parameters : none + * Returns : none +*******************************************************************************/ +extern void espconn_mdns_server_register(void); +/****************************************************************************** + * FunctionName : mdns_server_register + * Description : unregister server and leave multicast group + * Parameters : none + * Returns : none +*******************************************************************************/ +extern void espconn_mdns_server_unregister(void); +/****************************************************************************** + * FunctionName : espconn_mdns_get_servername + * Description : get server name + * Parameters : none + * Returns : server name +*******************************************************************************/ +extern char* espconn_mdns_get_servername(void); +/****************************************************************************** + * FunctionName : espconn_mdns_get_servername + * Description : set server name + * Parameters : server name + * Returns : none +*******************************************************************************/ +extern void espconn_mdns_set_servername(const char *name); +/****************************************************************************** + * FunctionName : espconn_mdns_set_hostname + * Description : set host name + * Parameters : host name + * Returns : none +*******************************************************************************/ +extern void espconn_mdns_set_hostname(char *name); +/****************************************************************************** + * FunctionName : espconn_mdns_init + * Description : get host name + * Parameters : void + * Returns : hostname +*******************************************************************************/ +extern char* espconn_mdns_get_hostname(void); +/****************************************************************************** + * FunctionName : espconn_mdns_disable + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +extern void espconn_mdns_disable(void); +/****************************************************************************** + * FunctionName : espconn_mdns_enable + * Description : enable mdns + * Parameters : void + * Returns : none +*******************************************************************************/ +extern void espconn_mdns_enable(void); +/****************************************************************************** + * FunctionName : espconn_dns_setserver + * Description : Initialize one of the DNS servers. + * Parameters : numdns -- the index of the DNS server to set must + * be < DNS_MAX_SERVERS = 2 + * dnsserver -- IP address of the DNS server to set + * Returns : none +*******************************************************************************/ +extern void espconn_dns_setserver(u8_t numdns, ip_addr_t *dnsserver); #endif diff --git a/app/include/lwip/app/espconn_tcp.h b/app/include/lwip/app/espconn_tcp.h index 717c0aea..70b66b33 100644 --- a/app/include/lwip/app/espconn_tcp.h +++ b/app/include/lwip/app/espconn_tcp.h @@ -1,43 +1,55 @@ -#ifndef __ESPCONN_TCP_H__ -#define __ESPCONN_TCP_H__ - -#ifndef ESPCONN_TCP_DEBUG -#define ESPCONN_TCP_DEBUG LWIP_DBG_OFF -#endif -#include "lwip/app/espconn.h" - -#ifndef ESPCONN_TCP_TIMER -#define ESPCONN_TCP_TIMER 40 -#endif - -/****************************************************************************** - * FunctionName : espconn_tcp_disconnect - * Description : A new incoming connection has been disconnected. - * Parameters : espconn -- the espconn used to disconnect with host - * Returns : none -*******************************************************************************/ - -extern void espconn_tcp_disconnect(espconn_msg *pdiscon); - -/****************************************************************************** - * FunctionName : espconn_tcp_client - * Description : Initialize the client: set up a connect PCB and bind it to - * the defined port - * Parameters : espconn -- the espconn used to build client - * Returns : none -*******************************************************************************/ - -extern sint8 espconn_tcp_client(struct espconn* espconn); - -/****************************************************************************** - * FunctionName : espconn_tcp_server - * Description : Initialize the server: set up a listening PCB and bind it to - * the defined port - * Parameters : espconn -- the espconn used to build server - * Returns : none -*******************************************************************************/ - -extern sint8 espconn_tcp_server(struct espconn *espconn); - -#endif /* __CLIENT_TCP_H__ */ - +#ifndef __ESPCONN_TCP_H__ +#define __ESPCONN_TCP_H__ + +#ifndef ESPCONN_TCP_DEBUG +#define ESPCONN_TCP_DEBUG LWIP_DBG_OFF +#endif +#include "lwip/app/espconn.h" + +#ifndef ESPCONN_TCP_TIMER +#define ESPCONN_TCP_TIMER 40 +#endif + +#define espconn_keepalive_enable(pcb) ((pcb)->so_options |= SOF_KEEPALIVE) +#define espconn_keepalive_disable(pcb) ((pcb)->so_options &= ~SOF_KEEPALIVE) + +/****************************************************************************** + * FunctionName : espconn_kill_oldest_pcb + * Description : A oldest incoming connection has been killed. + * Parameters : none + * Returns : none +*******************************************************************************/ + +extern void espconn_kill_oldest_pcb(void); + +/****************************************************************************** + * FunctionName : espconn_tcp_disconnect + * Description : A new incoming connection has been disconnected. + * Parameters : espconn -- the espconn used to disconnect with host + * Returns : none +*******************************************************************************/ + +extern void espconn_tcp_disconnect(espconn_msg *pdiscon); + +/****************************************************************************** + * FunctionName : espconn_tcp_client + * Description : Initialize the client: set up a connect PCB and bind it to + * the defined port + * Parameters : espconn -- the espconn used to build client + * Returns : none +*******************************************************************************/ + +extern sint8 espconn_tcp_client(struct espconn* espconn); + +/****************************************************************************** + * FunctionName : espconn_tcp_server + * Description : Initialize the server: set up a listening PCB and bind it to + * the defined port + * Parameters : espconn -- the espconn used to build server + * Returns : none +*******************************************************************************/ + +extern sint8 espconn_tcp_server(struct espconn *espconn); + +#endif /* __CLIENT_TCP_H__ */ + diff --git a/app/include/lwip/app/espconn_udp.h b/app/include/lwip/app/espconn_udp.h index ad34a7a1..2b724349 100644 --- a/app/include/lwip/app/espconn_udp.h +++ b/app/include/lwip/app/espconn_udp.h @@ -1,51 +1,51 @@ -#ifndef __ESPCONN_UDP_H__ -#define __ESPCONN_UDP_H__ - -#ifndef ESPCONN_UDP_DEBUG -#define ESPCONN_UDP_DEBUG LWIP_DBG_OFF -#endif - -#include "lwip/app/espconn.h" - -/****************************************************************************** - * FunctionName : espconn_udp_client - * Description : Initialize the client: set up a PCB and bind it to the port - * Parameters : pespconn -- the espconn used to build client - * Returns : none -*******************************************************************************/ - -extern sint8 espconn_udp_client(struct espconn *pespconn); - -/****************************************************************************** - * FunctionName : espconn_udp_disconnect - * Description : A new incoming connection has been disconnected. - * Parameters : espconn -- the espconn used to disconnect with host - * Returns : none -*******************************************************************************/ - -extern void espconn_udp_disconnect(espconn_msg *pdiscon); - -/****************************************************************************** - * FunctionName : espconn_udp_server - * Description : Initialize the server: set up a PCB and bind it to the port - * Parameters : pespconn -- the espconn used to build server - * Returns : none -*******************************************************************************/ - -extern sint8 espconn_udp_server(struct espconn *espconn); - -/****************************************************************************** - * FunctionName : espconn_udp_sent - * Description : sent data for client or server - * Parameters : void *arg -- client or server to send - * uint8* psent -- Data to send - * uint16 length -- Length of data to send - * Returns : none -*******************************************************************************/ - -extern void espconn_udp_sent(void *arg, uint8 *psent, uint16 length); - - -#endif /* __ESPCONN_UDP_H__ */ - - +#ifndef __ESPCONN_UDP_H__ +#define __ESPCONN_UDP_H__ + +#ifndef ESPCONN_UDP_DEBUG +#define ESPCONN_UDP_DEBUG LWIP_DBG_OFF +#endif + +#include "lwip/app/espconn.h" + +/****************************************************************************** + * FunctionName : espconn_udp_client + * Description : Initialize the client: set up a PCB and bind it to the port + * Parameters : pespconn -- the espconn used to build client + * Returns : none +*******************************************************************************/ + +extern sint8 espconn_udp_client(struct espconn *pespconn); + +/****************************************************************************** + * FunctionName : espconn_udp_disconnect + * Description : A new incoming connection has been disconnected. + * Parameters : espconn -- the espconn used to disconnect with host + * Returns : none +*******************************************************************************/ + +extern void espconn_udp_disconnect(espconn_msg *pdiscon); + +/****************************************************************************** + * FunctionName : espconn_udp_server + * Description : Initialize the server: set up a PCB and bind it to the port + * Parameters : pespconn -- the espconn used to build server + * Returns : none +*******************************************************************************/ + +extern sint8 espconn_udp_server(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_udp_sent + * Description : sent data for client or server + * Parameters : void *arg -- client or server to send + * uint8* psent -- Data to send + * uint16 length -- Length of data to send + * Returns : none +*******************************************************************************/ + +extern err_t espconn_udp_sent(void *arg, uint8 *psent, uint16 length); + + +#endif /* __ESPCONN_UDP_H__ */ + + diff --git a/app/include/lwip/dhcp.h b/app/include/lwip/dhcp.h index ba21068c..9e8fd0ec 100644 --- a/app/include/lwip/dhcp.h +++ b/app/include/lwip/dhcp.h @@ -207,6 +207,15 @@ void dhcp_fine_tmr(void); #define DHCP_OPTION_TCP_TTL 37 #define DHCP_OPTION_END 255 +/**add options for support more router by liuHan**/ +#define DHCP_OPTION_DOMAIN_NAME 15 +#define DHCP_OPTION_PRD 31 +#define DHCP_OPTION_STATIC_ROUTER 33 +#define DHCP_OPTION_VSN 43 +#define DHCP_OPTION_NB_TINS 44 +#define DHCP_OPTION_NB_TINT 46 +#define DHCP_OPTION_NB_TIS 47 +#define DHCP_OPTION_CLASSLESS_STATIC_ROUTER 121 /** DHCP options */ #define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */ #define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */ diff --git a/app/include/lwip/igmp.h b/app/include/lwip/igmp.h index 8cf9a481..c90adcdc 100644 --- a/app/include/lwip/igmp.h +++ b/app/include/lwip/igmp.h @@ -96,7 +96,7 @@ void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)ICACHE_FLAS err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)ICACHE_FLASH_ATTR; err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)ICACHE_FLASH_ATTR; void igmp_tmr(void)ICACHE_FLASH_ATTR; -#define LWIP_RAND() rand() +#define LWIP_RAND() r_rand() #ifdef __cplusplus } #endif diff --git a/app/include/lwip/mdns.h b/app/include/lwip/mdns.h new file mode 100644 index 00000000..08db68a6 --- /dev/null +++ b/app/include/lwip/mdns.h @@ -0,0 +1,114 @@ +/** + * lwip MDNS resolver header file. + * + * Created on: Jul 29, 2010 + * Author: Daniel Toma + + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LWIP_DNS_H__ +#define __LWIP_DNS_H__ + +#include "lwip/opt.h" + +#if LWIP_MDNS /* don't build if not configured for use in lwipopts.h */ + +/** DNS timer period */ +#define DNS_TMR_INTERVAL 1000 + +/** mDNS Address offset flag*/ +#define DNS_OFFSET_FLAG 0xC0 /* the offset flag in the DNS message */ +#define DNS_DEFAULT_OFFSET 0x0C /* the offset is set at the beginning of the DNS message */ + +#define DNS_IP_ADDR_LEN 4 + + +/** DNS field TYPE used for "Resource Records" */ +#define DNS_RRTYPE_A 1 /* a host address */ +#define DNS_RRTYPE_NS 2 /* an authoritative name server */ +#define DNS_RRTYPE_MD 3 /* a mail destination (Obsolete - use MX) */ +#define DNS_RRTYPE_MF 4 /* a mail forwarder (Obsolete - use MX) */ +#define DNS_RRTYPE_CNAME 5 /* the canonical name for an alias */ +#define DNS_RRTYPE_SOA 6 /* marks the start of a zone of authority */ +#define DNS_RRTYPE_MB 7 /* a mailbox domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_MG 8 /* a mail group member (EXPERIMENTAL) */ +#define DNS_RRTYPE_MR 9 /* a mail rename domain name (EXPERIMENTAL) */ +#define DNS_RRTYPE_NULL 10 /* a null RR (EXPERIMENTAL) */ +#define DNS_RRTYPE_WKS 11 /* a well known service description */ +#define DNS_RRTYPE_PTR 12 /* a domain name pointer */ +#define DNS_RRTYPE_HINFO 13 /* host information */ +#define DNS_RRTYPE_MINFO 14 /* mailbox or mail list information */ +#define DNS_RRTYPE_MX 15 /* mail exchange */ +#define DNS_RRTYPE_TXT 16 /* text strings */ +#define DNS_RRTYPE_SRV 33 /* Service record */ +#define DNS_RRTYPE_OPT 41 /* EDNS0 OPT record */ +#define DNS_RRTYPE_TSIG 250 /* Transaction Signature */ +#define DNS_RRTYPE_ANY 255 /*Not a DNS type, but a DNS query type, meaning "all types"*/ + +/* DNS field CLASS used for "Resource Records" */ +#define DNS_RRCLASS_IN 1 /* the Internet */ +#define DNS_RRCLASS_CS 2 /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */ +#define DNS_RRCLASS_CH 3 /* the CHAOS class */ +#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */ +#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */ +#define DNS_RRCLASS_FLUSH_IN 0x8001/* Flush bit and Internet*/ + +/** Callback which is invoked when a hostname is found. + * A function of this type must be implemented by the application using the DNS resolver. + * @param name pointer to the name that was looked up. + * @param ipaddr pointer to a struct ip_addr containing the IP address of the hostname, + * or NULL if the name could not be found (or on any other error). + * @param callback_arg a user-specified callback argument passed to dns_gethostbyname +*/ +#ifndef _MDNS_INFO +#define _MDNS_INFO +struct mdns_info { + char *host_name; + char *server_name; + uint16 server_port; + unsigned long ipAddr; + char *txt_data[10]; +}; +#endif +//void mdns_enable(void); +//void mdns_disable(void); +//void mdns_init(struct mdns_info *info); +//void mdns_close(void); +//char* mdns_get_hostname(void); +//void mdns_set_hostname(char *name); +//void mdns_set_servername(const char *name); +//char* mdns_get_servername(void); +//void mdns_server_unregister(void); +//void mdns_server_register(void) ; +//void mdns_tmr(void); +//void Delay(unsigned long ulSeconds); + +#endif /* LWIP_DNS */ + +#endif /* __LWIP_DNS_H__ */ diff --git a/app/include/lwip/memp.h b/app/include/lwip/memp.h index 764dedb1..6a2127db 100644 --- a/app/include/lwip/memp.h +++ b/app/include/lwip/memp.h @@ -76,7 +76,7 @@ typedef enum { #endif /* MEM_USE_POOLS */ #if MEMP_MEM_MALLOC || MEM_USE_POOLS -extern const u16_t memp_sizes[MEMP_MAX]; +extern const u32_t memp_sizes[MEMP_MAX]; #endif /* MEMP_MEM_MALLOC || MEM_USE_POOLS */ #if MEMP_MEM_MALLOC diff --git a/app/include/lwip/netif.h b/app/include/lwip/netif.h index 8bf13752..8c9cf2f2 100644 --- a/app/include/lwip/netif.h +++ b/app/include/lwip/netif.h @@ -169,6 +169,7 @@ struct netif { #if LWIP_DHCP /** the DHCP client state information for this netif */ struct dhcp *dhcp; + struct udp_pcb *dhcps_pcb; //dhcps #endif /* LWIP_DHCP */ #if LWIP_AUTOIP /** the AutoIP client state information for this netif */ diff --git a/app/include/lwip/puck_def.h b/app/include/lwip/puck_def.h new file mode 100644 index 00000000..c20027a1 --- /dev/null +++ b/app/include/lwip/puck_def.h @@ -0,0 +1,44 @@ +/* + * puck_def.h + * + * Created on: Jul 22, 2010 + * Author: dtoma + */ + +#ifndef PUCK_DEF_H_ +#define PUCK_DEF_H_ + + + +#define INSTRUMENT_PORT 8760 + +#define INSTRUMENT_LENGTH 80 + +#define MDNS_NAME_LENGTH 68 //68 + +char* PUCK_SERVICE = NULL; +//#define PUCK_SERVICE "_Escpressif._tcp.local" +#define DNS_SD_SERVICE "_services._dns-sd._udp.local" +#define SERVICE_DESCRIPTION "PUCK PROTOCOL" +#define PUCK_SERVICE_LENGTH 30 + +#define UUID_LEN 16 +#define DS_VERS_LEN 2 +#define DS_SIZE_LEN 2 +#define MAN_ID_LEN 4 +#define MAN_MODEL_LEN 2 +#define MAN_VERS_LEN 2 +#define SER_NUM_LEN 4 +#define NAME_LEN 64 +#define PUCK_DATASHEET_SIZE 96 + +#define UUID_OFFSET 0 +#define DS_VERS_OFFSET UUID_LEN + UUID_OFFSET +#define DS_SIZE_OFFSET DS_VERS_LEN + DS_VERS_OFFSET +#define MAN_ID_OFFSET DS_SIZE_LEN + DS_SIZE_OFFSET +#define MAN_MODEL_OFFSET MAN_ID_LEN + MAN_ID_OFFSET +#define MAN_VERS_OFFSET MAN_MODEL_LEN + MAN_MODEL_OFFSET +#define SER_NUM_OFFSET MAN_VERS_LEN + MAN_VERS_OFFSET +#define NAME_OFFSET SER_NUM_LEN + SER_NUM_OFFSET + +#endif /* __PUCK_DEF_H__ */ diff --git a/app/include/lwip/sntp.h b/app/include/lwip/sntp.h new file mode 100644 index 00000000..14e802e1 --- /dev/null +++ b/app/include/lwip/sntp.h @@ -0,0 +1,56 @@ +#ifndef LWIP_SNTP_H +#define LWIP_SNTP_H + +#include "lwip/opt.h" +#include "lwip/ip_addr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** The maximum number of SNTP servers that can be set */ +#ifndef SNTP_MAX_SERVERS +#define SNTP_MAX_SERVERS 3 +#endif + +/** Set this to 1 to implement the callback function called by dhcp when + * NTP servers are received. */ +#ifndef SNTP_GET_SERVERS_FROM_DHCP +#define SNTP_GET_SERVERS_FROM_DHCP 0//LWIP_DHCP_GET_NTP_SRV +#endif + +/* Set this to 1 to support DNS names (or IP address strings) to set sntp servers */ +#ifndef SNTP_SERVER_DNS +#define SNTP_SERVER_DNS 1 +#endif + +/** One server address/name can be defined as default if SNTP_SERVER_DNS == 1: + * #define SNTP_SERVER_ADDRESS "pool.ntp.org" + */ +uint32 sntp_get_current_timestamp(); +char* sntp_get_real_time(long t); + +void sntp_init(void); +void sntp_stop(void); + +sint8 sntp_get_timezone(void); +bool sntp_set_timezone(sint8 timezone); +void sntp_setserver(u8_t idx, ip_addr_t *addr); +ip_addr_t sntp_getserver(u8_t idx); + +#if SNTP_SERVER_DNS +void sntp_setservername(u8_t idx, char *server); +char *sntp_getservername(u8_t idx); +#endif /* SNTP_SERVER_DNS */ + +#if SNTP_GET_SERVERS_FROM_DHCP +void sntp_servermode_dhcp(int set_servers_from_dhcp); +#else /* SNTP_GET_SERVERS_FROM_DHCP */ +#define sntp_servermode_dhcp(x) +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_SNTP_H */ diff --git a/app/include/lwip/sys.h b/app/include/lwip/sys.h index 31a9dea7..432d2de2 100644 --- a/app/include/lwip/sys.h +++ b/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 = os_intr_lock() //fix by ives at 2014.3.24 -#define SYS_ARCH_UNPROTECT(lev) lev = os_intr_unlock() +#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() #endif /* SYS_LIGHTWEIGHT_PROT */ diff --git a/app/include/lwip/tcp.h b/app/include/lwip/tcp.h index 7856a92d..909ff9b7 100644 --- a/app/include/lwip/tcp.h +++ b/app/include/lwip/tcp.h @@ -277,8 +277,6 @@ struct tcp_pcb { /* KEEPALIVE counter */ u8_t keep_cnt_sent; - - u8_t hold; }; struct tcp_pcb_listen { diff --git a/app/include/lwip/tcp_impl.h b/app/include/lwip/tcp_impl.h index a756781a..24ca8bb9 100644 --- a/app/include/lwip/tcp_impl.h +++ b/app/include/lwip/tcp_impl.h @@ -135,15 +135,15 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */ #ifndef TCP_KEEPIDLE_DEFAULT -#define TCP_KEEPIDLE_DEFAULT 3000UL /* Default KEEPALIVE timer in milliseconds */ +#define TCP_KEEPIDLE_DEFAULT 120000UL /* Default KEEPALIVE timer in milliseconds */ #endif #ifndef TCP_KEEPINTVL_DEFAULT -#define TCP_KEEPINTVL_DEFAULT 1000UL /* Default Time between KEEPALIVE probes in milliseconds */ +#define TCP_KEEPINTVL_DEFAULT 10000UL /* Default Time between KEEPALIVE probes in milliseconds */ #endif #ifndef TCP_KEEPCNT_DEFAULT -#define TCP_KEEPCNT_DEFAULT 3U /* Default Counter for KEEPALIVE probes */ +#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */ #endif #define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */ diff --git a/app/include/mem_manager.h b/app/include/mem_manager.h index 185cc4a7..a107aaec 100644 --- a/app/include/mem_manager.h +++ b/app/include/mem_manager.h @@ -1,81 +1,81 @@ -#ifndef __MEM_MANAGER_H__ -#define __MEM_MANAGER_H__ - -#include "c_types.h" - -/*------------------------±äÁ¿¶¨Òå------------------------*/ - -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#ifndef IOT_SIP_MODE -//#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x3fffc000 - (uint32)&_heap_start ) )//fix 16000 to 24000 on 14.2.26 -#else -#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8000 ) ) -#endif -#define portBYTE_ALIGNMENT 8 -#define pdFALSE 0 -#define pdTRUE 1 - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if portBYTE_ALIGNMENT == 8 - #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) -#endif - -#if portBYTE_ALIGNMENT == 4 - #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) -#endif - -#if portBYTE_ALIGNMENT == 2 - #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) -#endif - -#if portBYTE_ALIGNMENT == 1 - #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) -#endif - -#ifndef portBYTE_ALIGNMENT_MASK - #error "Invalid portBYTE_ALIGNMENT definition" -#endif - -#define configUSE_MALLOC_FAILED_HOOK 1 -#define portPOINTER_SIZE_TYPE unsigned int - -#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) - -//#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) - -//static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; -static unsigned char *ucHeap; - -typedef struct A_BLOCK_LINK -{ - struct A_BLOCK_LINK *pxNextFreeBlock; //The next free block in the list. - size_t xBlockSize; //The size of the free block. -} xBlockLink; - -static const unsigned short heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) ); - -//static const size_t xTotalHeapSize = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); - -static xBlockLink xStart, *pxEnd = NULL; - -//static size_t xFreeBytesRemaining = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); - - -/*------------------------º¯ÊýÉùÃ÷-----------------------------------*/ - -static void prvInsertBlockIntoFreeList( xBlockLink *pxBlockToInsert ) ;//ICACHE_FLASH_ATTR; - -static void prvHeapInit( void ) ;//ICACHE_FLASH_ATTR; - -void vApplicationMallocFailedHook( void ) ;//ICACHE_FLASH_ATTR; - -void *pvPortMalloc( size_t xWantedSize ) ;//ICACHE_FLASH_ATTR; - -void vPortFree( void *pv ) ;//ICACHE_FLASH_ATTR; - -size_t xPortGetFreeHeapSize( void ) ;//ICACHE_FLASH_ATTR; - -void vPortInitialiseBlocks( void ) ;//ICACHE_FLASH_ATTR; -/*-----------------------------------------------------------*/ - -#endif +#ifndef __MEM_MANAGER_H__ +#define __MEM_MANAGER_H__ + +#include "c_types.h" + +/*------------------------��������------------------------*/ + +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#ifndef IOT_SIP_MODE +//#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 0x3fffc000 - (uint32)&_heap_start ) )//fix 16000 to 24000 on 14.2.26 +#else +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8000 ) ) +#endif +#define portBYTE_ALIGNMENT 8 +#define pdFALSE 0 +#define pdTRUE 1 + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE +#if portBYTE_ALIGNMENT == 8 + #define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 + #define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 + #define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 + #define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK + #error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#define configUSE_MALLOC_FAILED_HOOK 1 +#define portPOINTER_SIZE_TYPE unsigned int + +#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) + +//#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) + +//static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]; +static unsigned char *ucHeap; + +typedef struct A_BLOCK_LINK +{ + struct A_BLOCK_LINK *pxNextFreeBlock; //The next free block in the list. + size_t xBlockSize; //The size of the free block. +} xBlockLink; + +static const size_t heapSTRUCT_SIZE ICACHE_RODATA_ATTR = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) ); + +//static const size_t xTotalHeapSize = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); + +static xBlockLink xStart, *pxEnd = NULL; + +//static size_t xFreeBytesRemaining = ( ( size_t ) configADJUSTED_HEAP_SIZE ) & ( ( size_t ) ~portBYTE_ALIGNMENT_MASK ); + + +/*------------------------��������-----------------------------------*/ + +static void prvInsertBlockIntoFreeList( xBlockLink *pxBlockToInsert ) ;//ICACHE_FLASH_ATTR; + +static void prvHeapInit( void ) ;//ICACHE_FLASH_ATTR; + +void vApplicationMallocFailedHook( void ) ;//ICACHE_FLASH_ATTR; + +void *pvPortMalloc( size_t xWantedSize ) ;//ICACHE_FLASH_ATTR; + +void vPortFree( void *pv ) ;//ICACHE_FLASH_ATTR; + +size_t xPortGetFreeHeapSize( void ) ;//ICACHE_FLASH_ATTR; + +void vPortInitialiseBlocks( void ) ;//ICACHE_FLASH_ATTR; +/*-----------------------------------------------------------*/ + +#endif diff --git a/app/lwip/Makefile b/app/lwip/Makefile index 37d6e747..a27bbdf7 100644 --- a/app/lwip/Makefile +++ b/app/lwip/Makefile @@ -1,50 +1,50 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR -UP_EXTRACT_DIR = .. -GEN_LIBS = liblwip.a -COMPONENTS_liblwip = api/liblwipapi.a \ - app/liblwipapp.a \ - core/liblwipcore.a \ - core/ipv4/liblwipipv4.a \ - netif/liblwipnetif.a -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +UP_EXTRACT_DIR = .. +GEN_LIBS = liblwip.a +COMPONENTS_liblwip = api/liblwipapi.a \ + app/liblwipapp.a \ + core/liblwipcore.a \ + core/ipv4/liblwipipv4.a \ + netif/liblwipnetif.a +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/lwip/api/Makefile b/app/lwip/api/Makefile index 69b027d2..ef34edcf 100644 --- a/app/lwip/api/Makefile +++ b/app/lwip/api/Makefile @@ -1,46 +1,46 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipapi.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR + +GEN_LIBS = liblwipapi.a + +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/lwip/app/Makefile b/app/lwip/app/Makefile index 3c2954ef..929da663 100644 --- a/app/lwip/app/Makefile +++ b/app/lwip/app/Makefile @@ -1,46 +1,46 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipapp.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR + +GEN_LIBS = liblwipapp.a + +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/lwip/app/dhcpserver.c b/app/lwip/app/dhcpserver.c index 017f9738..0bf8eddc 100644 --- a/app/lwip/app/dhcpserver.c +++ b/app/lwip/app/dhcpserver.c @@ -10,23 +10,25 @@ #ifndef LWIP_OPEN_SRC #include "net80211/ieee80211_var.h" #endif +//#include "netif/wlan_lwip_if.h" #include "user_interface.h" //////////////////////////////////////////////////////////////////////////////////// -static uint8_t xid[4] = {0xad, 0xde, 0x12, 0x23}; -static u8_t old_xid[4] = {0}; -static const uint8_t magic_cookie[4] = {99, 130, 83, 99}; +//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_msg msg_dhcps; + 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 @@ -112,58 +114,64 @@ static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr) *optptr++ = DHCP_OPTION_SUBNET_MASK; *optptr++ = 4; //length *optptr++ = 255; - *optptr++ = 240; + *optptr++ = 240; *optptr++ = 0; *optptr++ = 0; #else *optptr++ = DHCP_OPTION_SUBNET_MASK; - *optptr++ = 4; - *optptr++ = 255; + *optptr++ = 4; *optptr++ = 255; + *optptr++ = 255; *optptr++ = 255; *optptr++ = 0; #endif *optptr++ = DHCP_OPTION_LEASE_TIME; - *optptr++ = 4; + *optptr++ = 4; *optptr++ = 0x00; *optptr++ = 0x01; *optptr++ = 0x51; - *optptr++ = 0x80; + *optptr++ = 0x80; *optptr++ = DHCP_OPTION_SERVER_ID; - *optptr++ = 4; + *optptr++ = 4; *optptr++ = ip4_addr1( &ipadd); *optptr++ = ip4_addr2( &ipadd); *optptr++ = ip4_addr3( &ipadd); *optptr++ = ip4_addr4( &ipadd); - *optptr++ = DHCP_OPTION_ROUTER; - *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); -#if 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); + *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 USE_CLASS_B_NET +#ifdef CLASS_B_NET *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS; - *optptr++ = 4; + *optptr++ = 4; *optptr++ = ip4_addr1( &ipadd); *optptr++ = 255; *optptr++ = 255; *optptr++ = 255; #else *optptr++ = DHCP_OPTION_BROADCAST_ADDRESS; - *optptr++ = 4; + *optptr++ = 4; *optptr++ = ip4_addr1( &ipadd); *optptr++ = ip4_addr2( &ipadd); *optptr++ = ip4_addr3( &ipadd); @@ -171,28 +179,28 @@ static uint8_t* ICACHE_FLASH_ATTR add_offer_options(uint8_t *optptr) #endif *optptr++ = DHCP_OPTION_INTERFACE_MTU; - *optptr++ = 2; -#ifdef USE_CLASS_B_NET - *optptr++ = 0x05; + *optptr++ = 2; +#ifdef CLASS_B_NET + *optptr++ = 0x05; *optptr++ = 0xdc; #else - *optptr++ = 0x02; + *optptr++ = 0x02; *optptr++ = 0x40; #endif *optptr++ = DHCP_OPTION_PERFORM_ROUTER_DISCOVERY; - *optptr++ = 1; - *optptr++ = 0x00; + *optptr++ = 1; + *optptr++ = 0x00; - *optptr++ = 43; - *optptr++ = 6; + *optptr++ = 43; + *optptr++ = 6; - *optptr++ = 0x01; - *optptr++ = 4; + *optptr++ = 0x01; + *optptr++ = 4; *optptr++ = 0x00; *optptr++ = 0x00; *optptr++ = 0x00; - *optptr++ = 0x02; + *optptr++ = 0x02; return optptr; } @@ -212,11 +220,6 @@ static uint8_t* ICACHE_FLASH_ATTR add_end(uint8_t *optptr) return optptr; } /////////////////////////////////////////////////////////////////////////////////// -/* - * ����һ��DHCP msg�ṹ�� - * - * @param -- m ָ�ò´´½ï¿½ï¿½ï¿½DHCP msg�ṹ�����? - */ /////////////////////////////////////////////////////////////////////////////////// static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m) { @@ -228,7 +231,7 @@ static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m) m->htype = DHCP_HTYPE_ETHERNET; m->hlen = 6; m->hops = 0; - os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid)); +// os_memcpy((char *) xid, (char *) m->xid, sizeof(m->xid)); m->secs = 0; m->flags = htons(BOOTP_BROADCAST); @@ -241,7 +244,7 @@ static void ICACHE_FLASH_ATTR create_msg(struct dhcps_msg *m) os_memset((char *) m->file, 0, sizeof(m->file)); os_memset((char *) m->options, 0, sizeof(m->options)); - os_memcpy((char *) m->options, (char *) magic_cookie, sizeof(magic_cookie)); + os_memcpy((char *) m->options, &magic_cookie, sizeof(magic_cookie)); } /////////////////////////////////////////////////////////////////////////////////// /* @@ -544,7 +547,7 @@ static uint8_t ICACHE_FLASH_ATTR parse_options(uint8_t *optptr, sint16_t len) static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len) { if(os_memcmp((char *)m->options, - (char *)magic_cookie, + &magic_cookie, sizeof(magic_cookie)) == 0){ #if DHCPS_DEBUG os_printf("dhcps: len = %d\n", len); @@ -574,7 +577,7 @@ static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len) * ��¼���ε�xid�ţ�ͬʱ�����IP���� */ struct ip_addr addr_tmp; - os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid)); +// os_memcpy((char *)old_xid, (char *)m->xid, sizeof(m->xid)); { struct dhcps_pool *pdhcps_pool = NULL; @@ -611,9 +614,15 @@ static sint16_t ICACHE_FLASH_ATTR parse_msg(struct dhcps_msg *m, u16_t len) node_insert_to_list(&plist,pnode); POOL_CHECK: - if ((client_address_plus.addr > dhcps_lease.end_ip) || (ip_addr_isany(&client_address))){ - client_address_plus.addr = dhcps_lease.start_ip; - goto POOL_START; + 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) { @@ -652,18 +661,24 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg, struct ip_addr *addr, uint16_t port) { - - sint16_t tlen; - u16_t i; - u16_t dhcps_msg_cnt=0; - u8_t *p_dhcps_msg = (u8_t *)&msg_dhcps; - u8_t *data; + 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; @@ -672,7 +687,6 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg, os_printf("dhcps: handle_dhcp-> p->len = %d\n", p->len); #endif - os_memset(&msg_dhcps, 0, sizeof(dhcps_msg)); for(i=0; ilen; i++){ p_dhcps_msg[dhcps_msg_cnt++] = data[i]; #if DHCPS_DEBUG @@ -709,25 +723,25 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg, os_printf("dhcps: handle_dhcp-> parse_msg(p)\n"); #endif - switch(parse_msg(&msg_dhcps, tlen - 240)) { + 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(&msg_dhcps); + 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(&msg_dhcps); + 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(&msg_dhcps); + send_nak(pmsg_dhcps); break; default : break; @@ -736,6 +750,8 @@ static void ICACHE_FLASH_ATTR handle_dhcp(void *arg, 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) @@ -752,27 +768,34 @@ static void ICACHE_FLASH_ATTR wifi_softap_init_dhcps_lease(uint32 ip) local_ip ++; os_bzero(&dhcps_lease, sizeof(dhcps_lease)); - dhcps_lease.start_ip = softap_ip | local_ip; - dhcps_lease.end_ip = softap_ip | (local_ip + DHCPS_MAX_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 = htonl(dhcps_lease.start_ip); - dhcps_lease.end_ip= htonl(dhcps_lease.end_ip); + 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) { - os_memset(&msg_dhcps, 0, sizeof(dhcps_msg)); + 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; + 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); @@ -784,8 +807,16 @@ void ICACHE_FLASH_ATTR dhcps_start(struct ip_info *info) void ICACHE_FLASH_ATTR dhcps_stop(void) { + struct netif * apnetif = (struct netif *)eagle_lwip_getif(0x01); + udp_disconnect(pcb_dhcps); - udp_remove(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; @@ -800,42 +831,122 @@ void ICACHE_FLASH_ATTR dhcps_stop(void) } } +/****************************************************************************** + * 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; - if (please == NULL) + 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); - please->start_ip = htonl(please->start_ip); - please->end_ip = htonl(please->end_ip); + start_ip = htonl(please->start_ip.addr); + end_ip = htonl(please->end_ip.addr); /*config ip information can't contain local ip*/ - if ((please->start_ip <= softap_ip) && (softap_ip <= please->end_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 ((please->start_ip >> 8 != softap_ip) - || (please->end_ip >> 8 != softap_ip)) { + if ((start_ip >> 8 != softap_ip) + || (end_ip >> 8 != softap_ip)) { return false; } - if (please->end_ip - please->start_ip > DHCPS_MAX_LEASE) + if (end_ip - start_ip > DHCPS_MAX_LEASE) return false; os_bzero(&dhcps_lease, sizeof(dhcps_lease)); - dhcps_lease.start_ip = please->start_ip; - dhcps_lease.end_ip = please->end_ip; + 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; @@ -853,6 +964,33 @@ void ICACHE_FLASH_ATTR dhcps_coarse_tmr(void) 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; +} + diff --git a/app/lwip/app/dummy.c b/app/lwip/app/dummy.c deleted file mode 100644 index a7a74ed9..00000000 --- a/app/lwip/app/dummy.c +++ /dev/null @@ -1,10 +0,0 @@ -/****************************************************************************** - * FunctionName : espconn_init - * Description : dummy the espconn_init - * Parameters : none - * Returns : none -*******************************************************************************/ -void espconn_init() -{ - // dummy function, do nothing. -} diff --git a/app/lwip/app/espconn.c b/app/lwip/app/espconn.c index 114f1b59..1d113f95 100644 --- a/app/lwip/app/espconn.c +++ b/app/lwip/app/espconn.c @@ -23,14 +23,15 @@ #include "lwip/app/espconn_tcp.h" #include "lwip/app/espconn_udp.h" #include "lwip/app/espconn.h" - #include "user_interface.h" espconn_msg *plink_active = NULL; espconn_msg *pserver_list = NULL; -remot_info premot[5]; -uint32 link_timer = 0; +remot_info premot[linkMax]; +struct espconn_packet pktinfo[2]; + +static uint8 espconn_tcp_get_buf_count(espconn_buf *pesp_buf); /****************************************************************************** * FunctionName : espconn_copy_partial * Description : reconnect with host @@ -122,38 +123,127 @@ void ICACHE_FLASH_ATTR espconn_list_delete(espconn_msg **phead, espconn_msg* pde }*/ } +/****************************************************************************** + * FunctionName : espconn_pbuf_create + * Description : insert the node to the active connection list + * Parameters : arg -- Additional argument to pass to the callback function + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR espconn_pbuf_create(espconn_buf **phead, espconn_buf* pinsert) +{ + espconn_buf *plist = NULL; + + if (*phead == NULL) + *phead = pinsert; + else { + plist = *phead; + while (plist->pnext != NULL) { + plist = plist->pnext; + } + plist->pnext = pinsert; + } + pinsert->pnext = NULL; +} + +/****************************************************************************** + * FunctionName : espconn_pbuf_delete + * Description : remove the node from the active connection list + * Parameters : arg -- Additional argument to pass to the callback function + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR espconn_pbuf_delete(espconn_buf **phead, espconn_buf* pdelete) +{ + espconn_buf *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; + } + } + } +} + /****************************************************************************** * FunctionName : espconn_find_connection * Description : Initialize the server: set up a listening PCB and bind it to * the defined port * Parameters : espconn -- the espconn used to build server - * Returns : none + * Returns : true or false *******************************************************************************/ bool ICACHE_FLASH_ATTR espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode) { espconn_msg *plist = NULL; struct ip_addr ip_remot; struct ip_addr ip_list; - plist = plink_active; - while(plist != NULL){ - if (pespconn == plist->pespconn){ + if (pespconn == NULL) + return false; + + /*find the active connection node*/ + for (plist = plink_active; plist != NULL; plist = plist->pnext){ + if (pespconn == plist->pespconn) { *pnode = plist; return true; - } else { - IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0], pespconn->proto.tcp->remote_ip[1], - pespconn->proto.tcp->remote_ip[2], pespconn->proto.tcp->remote_ip[3]); - - IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0], plist->pcommon.remote_ip[1], - plist->pcommon.remote_ip[2], plist->pcommon.remote_ip[3]); - if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)){ - *pnode = plist; - return true; - } } - plist = plist ->pnext; } - return false; + + /*find the active server node*/ + for (plist = pserver_list; plist != NULL; plist = plist->pnext){ + if (pespconn == plist->pespconn) { + if (pespconn->proto.tcp == NULL) + return false; + + IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0], + pespconn->proto.tcp->remote_ip[1], + pespconn->proto.tcp->remote_ip[2], + pespconn->proto.tcp->remote_ip[3]); + if ((ip_remot.addr == IPADDR_ANY) || (pespconn->proto.tcp->remote_port == 0)) + return false; + + /*find the active connection node*/ + for (plist = plink_active; plist != NULL; plist = plist->pnext){ + IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0], + plist->pcommon.remote_ip[1], plist->pcommon.remote_ip[2], + plist->pcommon.remote_ip[3]); + if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)) { + *pnode = plist; + return true; + } + } + return false; + } + } + return false; +} + +/****************************************************************************** + * FunctionName : espconn_get_acticve_num + * Description : get the count of simulatenously active connections + * Parameters : type -- the type + * Returns : the count of simulatenously active connections + *******************************************************************************/ +static uint8 ICACHE_FLASH_ATTR +espconn_get_acticve_num(uint8 type) +{ + espconn_msg *plist = NULL; + uint8 num_tcp_active = 0; + + for (plist = plink_active; plist != NULL; plist = plist->pnext) { + if (plist->pespconn != NULL && plist->pespconn->type == type) { + num_tcp_active++; + } + } + + return num_tcp_active; } /****************************************************************************** @@ -170,12 +260,18 @@ espconn_connect(struct espconn *espconn) uint8 connect_status = 0; sint8 value = ESPCONN_OK; espconn_msg *plist = NULL; + remot_info *pinfo = NULL; if (espconn == NULL) { return ESPCONN_ARG; } else if (espconn ->type != ESPCONN_TCP) return ESPCONN_ARG; + /*Check the active node count whether is the limit or not*/ + if (espconn_get_acticve_num(ESPCONN_TCP) >= espconn_tcp_get_max_con()) + return ESPCONN_ISCONN; + + /*Check the IP address whether is zero or not in different mode*/ if (wifi_get_opmode() == ESPCONN_STA){ wifi_get_ip_info(STA_NETIF,&ipinfo); if (ipinfo.ip.addr == 0){ @@ -202,14 +298,17 @@ espconn_connect(struct espconn *espconn) wifi_get_ip_info(STA_NETIF,&ipinfo); if (ipinfo.ip.addr == 0) return ESPCONN_RTE; + } else if (connect_status == STATION_IDLE){ + return ESPCONN_RTE; } else { return connect_status; } } } + /*check the active node information whether is the same as the entity or not*/ for (plist = plink_active; plist != NULL; plist = plist->pnext){ - if (plist->pespconn->type == ESPCONN_TCP){ + if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){ if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){ return ESPCONN_ISCONN; } @@ -239,8 +338,9 @@ espconn_create(struct espconn *espconn) return ESPCONN_ARG; } + /*check the active node information whether is the same as the entity or not*/ for (plist = plink_active; plist != NULL; plist = plist->pnext){ - if (plist->pespconn->type == ESPCONN_UDP){ + if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){ if (espconn->proto.udp->local_port == plist->pespconn->proto.udp->local_port){ return ESPCONN_ISCONN; } @@ -265,32 +365,123 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length) { espconn_msg *pnode = NULL; bool value = false; - if (espconn == NULL) { + err_t error = ESPCONN_OK; + + if (espconn == NULL || psent == NULL || length == 0) { return ESPCONN_ARG; } - espconn ->state = ESPCONN_WRITE; - value = espconn_find_connection(espconn, &pnode); - switch (espconn ->type) { - case ESPCONN_TCP: - // if (value && (pnode->pcommon.write_len == pnode->pcommon.write_total)){ - if (value && (pnode->pcommon.cntr == 0)){ - espconn_tcp_sent(pnode, psent, length); - }else - return ESPCONN_ARG; - break; - case ESPCONN_UDP: { - if (value) - espconn_udp_sent(pnode, psent, length); - else - return ESPCONN_ARG; - break; - } + /*Find the node depend on the espconn message*/ + value = espconn_find_connection(espconn, &pnode); - default : - break; + if (value){ + espconn ->state = ESPCONN_WRITE; + switch (espconn ->type) { + case ESPCONN_TCP: + /* calling sent function frequently,make sure last packet has been backup or sent fully*/ + if (pnode->pcommon.write_flag){ + espconn_buf *pbuf = NULL; + /*If total number of espconn_buf on the unsent lists exceeds the set maximum, return an error */ + if (espconn_copy_enabled(pnode)){ + if (espconn_tcp_get_buf_count(pnode->pcommon.pbuf) >= pnode ->pcommon.pbuf_num) + return ESPCONN_MAXNUM; + } + + pbuf = (espconn_buf*) os_zalloc(sizeof(espconn_buf)); + if (pbuf == NULL) + return ESPCONN_MEM; + else { + /*Backup the application packet information for send more data*/ + pbuf->payload = psent; + pbuf->punsent = pbuf->payload; + pbuf->unsent = length; + pbuf->len = length; + /*insert the espconn_pbuf to the list*/ + espconn_pbuf_create(&pnode->pcommon.pbuf, pbuf); + if (pnode->pcommon.ptail == NULL) + pnode->pcommon.ptail = pbuf; + } + /*when set the data copy option. change the flag for next packet*/ + 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; + } + return error; + } else + return ESPCONN_ARG; + break; + + case ESPCONN_UDP: + return espconn_udp_sent(pnode, psent, length); + break; + + default : + break; + } } - return ESPCONN_OK; + return ESPCONN_ARG; +} + +/****************************************************************************** + * FunctionName : espconn_send + * Description : sent data for client or server + * Parameters : espconn -- espconn to set for client or server + * psent -- data to send + * length -- length of data to send + * Returns : none +*******************************************************************************/ + +sint8 espconn_send(struct espconn *espconn, uint8 *psent, uint16 length) __attribute__((alias("espconn_sent"))); + +/****************************************************************************** + * FunctionName : espconn_tcp_get_wnd + * Description : get the window size of simulatenously active TCP connections + * Parameters : none + * Returns : the number of TCP_MSS active TCP connections +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR espconn_tcp_get_wnd(void) +{ + uint8 tcp_num = 0; + + tcp_num = (TCP_WND / TCP_MSS); + + return tcp_num; +} +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_con + * Description : set the window size simulatenously active TCP connections + * Parameters : num -- the number of TCP_MSS + * Returns : ESPCONN_ARG -- Illegal argument + * ESPCONN_OK -- No error +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR espconn_tcp_set_wnd(uint8 num) +{ + if (num == 0 || num > linkMax) + return ESPCONN_ARG; + + TCP_WND = (num * TCP_MSS); + return ESPCONN_OK; +} + +/****************************************************************************** + * FunctionName : espconn_tcp_get_mss + * Description : get the mss size of simulatenously active TCP connections + * Parameters : none + * Returns : the size of TCP_MSS active TCP connections +*******************************************************************************/ +uint16 ICACHE_FLASH_ATTR espconn_tcp_get_mss(void) +{ + uint16 tcp_num = 0; + + tcp_num = TCP_MSS; + + return tcp_num; } /****************************************************************************** @@ -316,13 +507,73 @@ uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_con(void) *******************************************************************************/ sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con(uint8 num) { - if (num == 0) + if (num == 0 || num > linkMax) return ESPCONN_ARG; MEMP_NUM_TCP_PCB = num; return ESPCONN_OK; } +/****************************************************************************** + * FunctionName : espconn_tcp_get_max_retran + * Description : get the Maximum number of retransmissions of data active TCP connections + * Parameters : none + * Returns : the Maximum number of retransmissions +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_retran(void) +{ + uint8 tcp_num = 0; + + tcp_num = TCP_MAXRTX; + + return tcp_num; +} + +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_retran + * Description : set the Maximum number of retransmissions of data active TCP connections + * Parameters : num -- the Maximum number of retransmissions + * Returns : result +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_retran(uint8 num) +{ + if (num == 0 || num > 12) + return ESPCONN_ARG; + + TCP_MAXRTX = num; + return ESPCONN_OK; +} + +/****************************************************************************** + * FunctionName : espconn_tcp_get_max_syn + * Description : get the Maximum number of retransmissions of SYN segments + * Parameters : none + * Returns : the Maximum number of retransmissions +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_syn(void) +{ + uint8 tcp_num = 0; + + tcp_num = TCP_SYNMAXRTX; + + return tcp_num; +} + +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_syn + * Description : set the Maximum number of retransmissions of SYN segments + * Parameters : num -- the Maximum number of retransmissions + * Returns : result +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_syn(uint8 num) +{ + if (num == 0 || num > 12) + return ESPCONN_ARG; + + TCP_SYNMAXRTX = num; + return ESPCONN_OK; +} + /****************************************************************************** * FunctionName : espconn_tcp_get_max_con_allow * Description : get the count of simulatenously active connections on the server @@ -368,6 +619,51 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con_allow(struct espconn *espconn, u return ESPCONN_ARG; } +/****************************************************************************** + * FunctionName : espconn_tcp_set_buf_count + * Description : set the total number of espconn_buf on the unsent lists for one + * activate connection + * Parameters : espconn -- espconn to set the count + * num -- the total number of espconn_buf + * Returns : result +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR espconn_tcp_set_buf_count(struct espconn *espconn, uint8 num) +{ + espconn_msg *plist = NULL; + if (espconn == NULL || (num > TCP_SND_QUEUELEN)) + return ESPCONN_ARG; + + /*find the node from the active connection list*/ + for (plist = plink_active; plist != NULL; plist = plist->pnext){ + if (plist->pespconn && plist->pespconn == espconn && espconn->type == ESPCONN_TCP){ + plist->pcommon.pbuf_num = num; + return ESPCONN_OK; + } + } + + if (plist == NULL) + return ESPCONN_ARG; +} + +/****************************************************************************** + * FunctionName : espconn_tcp_get_buf_count + * Description : get the count of the current node which has espconn_buf + * Parameters : pesp_buf -- the list head of espconn_buf type + * Returns : the count of the current node which has espconn_buf +*******************************************************************************/ +static uint8 ICACHE_FLASH_ATTR espconn_tcp_get_buf_count(espconn_buf *pesp_buf) +{ + espconn_buf *pbuf_list = pesp_buf; + uint8 pbuf_num = 0; + + /*polling the list get the count of the current node*/ + while (pbuf_list != NULL){ + pbuf_list = pbuf_list->pnext; + pbuf_num ++; + } + return pbuf_num; +} + /****************************************************************************** * FunctionName : espconn_regist_sentcb * Description : Used to specify the function that should be called when data @@ -388,6 +684,26 @@ espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb) return ESPCONN_OK; } +/****************************************************************************** + * FunctionName : espconn_regist_sentcb + * Description : Used to specify the function that should be called when data + * has been successfully delivered to the remote host. + * Parameters : espconn -- espconn to set the sent callback + * sent_cb -- sent callback function to call for this espconn + * when data is successfully sent + * Returns : none +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR +espconn_regist_write_finish(struct espconn *espconn, espconn_connect_callback write_finish_fn) +{ + if (espconn == NULL || espconn ->proto.tcp == NULL || espconn->type == ESPCONN_UDP) { + return ESPCONN_ARG; + } + + espconn ->proto.tcp->write_finish_fn = write_finish_fn; + return ESPCONN_OK; +} + /****************************************************************************** * FunctionName : espconn_regist_connectcb * Description : used to specify the function that should be called when @@ -484,27 +800,11 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui switch (pespconn->type){ case ESPCONN_TCP: while(plist != NULL){ - if ((plist->pespconn->type == ESPCONN_TCP) && (plist->preverse == pespconn)){ - switch (typeflags){ - case ESPCONN_SSL: - if (plist->pssl != NULL){ - premot[pespconn->link_cnt].state = plist->pespconn->state; - premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port; - os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4); - pespconn->link_cnt ++; - } - break; - case ESPCONN_NORM: - if (plist->pssl == NULL){ - premot[pespconn->link_cnt].state = plist->pespconn->state; - premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port; - os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4); - pespconn->link_cnt ++; - } - break; - default: - break; - } + if (plist->preverse == pespconn){ + premot[pespconn->link_cnt].state = plist->pespconn->state; + premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port; + os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4); + pespconn->link_cnt ++; } plist = plist->pnext; } @@ -512,7 +812,7 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui break; case ESPCONN_UDP: while(plist != NULL){ - if (plist->pespconn->type == ESPCONN_UDP){ + if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){ premot[pespconn->link_cnt].state = plist->pespconn->state; premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port; os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4); @@ -545,8 +845,9 @@ espconn_accept(struct espconn *espconn) } else if (espconn ->type != ESPCONN_TCP) return ESPCONN_ARG; + /*check the active node information whether is the same as the entity or not*/ for (plist = plink_active; plist != NULL; plist = plist->pnext){ - if (plist->pespconn->type == ESPCONN_TCP){ + if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){ if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){ return ESPCONN_ISCONN; } @@ -567,11 +868,13 @@ espconn_accept(struct espconn *espconn) sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 interval, uint8 type_flag) { espconn_msg *pnode = NULL; + espconn_msg *ptime_msg = NULL; bool value = false; if ((espconn == NULL) || (type_flag > 0x01)) return ESPCONN_ARG; if (type_flag == 0x01){ + /*set the timeout time for one active connection of the server*/ value = espconn_find_connection(espconn, &pnode); if (value){ pnode->pcommon.timeout = interval; @@ -579,10 +882,17 @@ sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 inte } else return ESPCONN_ARG; } else { - link_timer = interval; - os_printf("espconn_regist_time %d\n", link_timer); - return ESPCONN_OK; + /*set the timeout time for all active connection of the server*/ + ptime_msg = pserver_list; + while (ptime_msg != NULL){ + if (ptime_msg->pespconn == espconn){ + ptime_msg->pcommon.timeout = interval; + return ESPCONN_OK; + } + ptime_msg = ptime_msg->pnext; + } } + return ESPCONN_ARG; } /****************************************************************************** @@ -602,41 +912,233 @@ espconn_disconnect(struct espconn *espconn) } else if (espconn ->type != ESPCONN_TCP) return ESPCONN_ARG; + /*Find the node depend on the espconn message*/ value = espconn_find_connection(espconn, &pnode); if (value){ + /*protect for redisconnection*/ + if (espconn->state == ESPCONN_CLOSE) + return ESPCONN_INPROGRESS; espconn_tcp_disconnect(pnode); return ESPCONN_OK; } else return ESPCONN_ARG; } +/****************************************************************************** + * FunctionName : espconn_get_packet_info + * Description : get the packet info with host + * Parameters : espconn -- the espconn used to disconnect the connection + * infoarg -- the packet info + * Returns : the errur code +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR +espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg) +{ + espconn_msg *pnode = NULL; + err_t err; + bool value = false; + + if (espconn == NULL || infoarg == NULL) { + return ESPCONN_ARG;; + } else if (espconn->type != ESPCONN_TCP) + return ESPCONN_ARG; + + /*Find the node depend on the espconn message*/ + value = espconn_find_connection(espconn, &pnode); + if (value) { + struct tcp_pcb *pcb = pnode->pcommon.pcb; + if (pcb == NULL) + return ESPCONN_ARG; + + pnode->pcommon.packet_info.packseq_nxt = pcb->rcv_nxt; + pnode->pcommon.packet_info.packseqno = pcb->snd_nxt; + pnode->pcommon.packet_info.snd_buf_size = pcb->snd_buf; + pnode->pcommon.packet_info.total_queuelen = TCP_SND_QUEUELEN; + pnode->pcommon.packet_info.snd_queuelen = pnode->pcommon.packet_info.total_queuelen - pcb->snd_queuelen; + os_memcpy(infoarg,(void*)&pnode->pcommon.packet_info, sizeof(struct espconn_packet)); + return ESPCONN_OK; + } else { + switch (espconn->state){ + case ESPCONN_CLOSE: + os_memcpy(infoarg,(void*)&pktinfo[0], sizeof(struct espconn_packet)); + err = ESPCONN_OK; + break; + case ESPCONN_NONE: + os_memcpy(infoarg,(void*)&pktinfo[1], sizeof(struct espconn_packet)); + err = ESPCONN_OK; + break; + default: + err = ESPCONN_ARG; + break; + } + return err; + } +} + /****************************************************************************** * FunctionName : espconn_set_opt - * Description : access port value for client so that we don't end up bouncing + * Description : set the option for connections so that we don't end up bouncing * all connections at the same time . - * Parameters : none - * Returns : access port value + * Parameters : espconn -- the espconn used to set the connection + * opt -- the option for set + * Returns : the result *******************************************************************************/ sint8 ICACHE_FLASH_ATTR espconn_set_opt(struct espconn *espconn, uint8 opt) { espconn_msg *pnode = NULL; + struct tcp_pcb *tpcb; bool value = false; - if (espconn == NULL || opt > ESPCONN_END) { + if (espconn == NULL) { return ESPCONN_ARG;; } else if (espconn->type != ESPCONN_TCP) return ESPCONN_ARG; + /*Find the node depend on the espconn message*/ value = espconn_find_connection(espconn, &pnode); if (value) { - pnode->pcommon.espconn_opt = opt; + pnode->pcommon.espconn_opt |= opt; + tpcb = pnode->pcommon.pcb; + if (espconn_delay_disabled(pnode)) + tcp_nagle_disable(tpcb); + + if (espconn_keepalive_disabled(pnode)) + espconn_keepalive_enable(tpcb); + return ESPCONN_OK; } else return ESPCONN_ARG; } +/****************************************************************************** + * FunctionName : espconn_clear_opt + * Description : clear the option for connections so that we don't end up bouncing + * all connections at the same time . + * Parameters : espconn -- the espconn used to set the connection + * opt -- the option for clear + * Returns : the result +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR +espconn_clear_opt(struct espconn *espconn, uint8 opt) +{ + espconn_msg *pnode = NULL; + struct tcp_pcb *tpcb; + bool value = false; + + if (espconn == NULL) { + return ESPCONN_ARG;; + } else if (espconn->type != ESPCONN_TCP) + return ESPCONN_ARG; + + /*Find the node depend on the espconn message*/ + value = espconn_find_connection(espconn, &pnode); + if (value) { + pnode->pcommon.espconn_opt &= ~opt; + tpcb = pnode->pcommon.pcb; + if (espconn_keepalive_enabled(pnode)) + espconn_keepalive_disable(tpcb); + + if (espconn_delay_enabled(pnode)) + tcp_nagle_enable(tpcb); + + return ESPCONN_OK; + } else + return ESPCONN_ARG; +} + +/****************************************************************************** + * FunctionName : espconn_set_keepalive + * Description : access level value for connection so that we set the value for + * keep alive + * Parameters : espconn -- the espconn used to set the connection + * level -- the connection's level + * value -- the value of time(s) + * Returns : access port value +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg) +{ + espconn_msg *pnode = NULL; + bool value = false; + sint8 ret = ESPCONN_OK; + + if (espconn == NULL || optarg == NULL) { + return ESPCONN_ARG;; + } else if (espconn->type != ESPCONN_TCP) + return ESPCONN_ARG; + + /*Find the node depend on the espconn message*/ + value = espconn_find_connection(espconn, &pnode); + if (value && espconn_keepalive_disabled(pnode)) { + struct tcp_pcb *pcb = pnode->pcommon.pcb; + switch (level){ + case ESPCONN_KEEPIDLE: + pcb->keep_idle = 1000 * (u32_t)(*(int*)optarg); + ret = ESPCONN_OK; + break; + case ESPCONN_KEEPINTVL: + pcb->keep_intvl = 1000 * (u32_t)(*(int*)optarg); + ret = ESPCONN_OK; + break; + case ESPCONN_KEEPCNT: + pcb->keep_cnt = (u32_t)(*(int*)optarg); + ret = ESPCONN_OK; + break; + default: + ret = ESPCONN_ARG; + break; + } + return ret; + } else + return ESPCONN_ARG; +} + +/****************************************************************************** + * FunctionName : espconn_get_keepalive + * Description : access level value for connection so that we get the value for + * keep alive + * Parameters : espconn -- the espconn used to get the connection + * level -- the connection's level + * Returns : access keep alive value +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg) +{ + espconn_msg *pnode = NULL; + bool value = false; + sint8 ret = ESPCONN_OK; + + if (espconn == NULL || optarg == NULL) { + return ESPCONN_ARG;; + } else if (espconn->type != ESPCONN_TCP) + return ESPCONN_ARG; + + /*Find the node depend on the espconn message*/ + value = espconn_find_connection(espconn, &pnode); + if (value && espconn_keepalive_disabled(pnode)) { + struct tcp_pcb *pcb = pnode->pcommon.pcb; + switch (level) { + case ESPCONN_KEEPIDLE: + *(int*)optarg = (int)(pcb->keep_idle/1000); + ret = ESPCONN_OK; + break; + case ESPCONN_KEEPINTVL: + *(int*)optarg = (int)(pcb->keep_intvl/1000); + ret = ESPCONN_OK; + break; + case ESPCONN_KEEPCNT: + *(int*)optarg = (int)(pcb->keep_cnt); + ret = ESPCONN_OK; + break; + default: + ret = ESPCONN_ARG; + break; + } + return ret; + } else + return ESPCONN_ARG; +} + /****************************************************************************** * FunctionName : espconn_delete * Description : disconnect with host @@ -654,6 +1156,7 @@ espconn_delete(struct espconn *espconn) } else if (espconn ->type != ESPCONN_UDP) return espconn_tcp_delete(espconn); + /*Find the node depend on the espconn message*/ value = espconn_find_connection(espconn, &pnode); if (value){ @@ -670,7 +1173,8 @@ espconn_delete(struct espconn *espconn) * Parameters : none * Returns : access port value *******************************************************************************/ -uint32 espconn_port(void) +uint32 ICACHE_FLASH_ATTR +espconn_port(void) { uint32 port = 0; static uint32 randnum = 0; @@ -718,32 +1222,17 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t return dns_gethostbyname(hostname, addr, found, pespconn); } -sint8 espconn_recv_hold(struct espconn *pespconn) { - espconn_msg *pnode = NULL; - - if (pespconn == NULL) { - return ESPCONN_ARG; - } - pespconn->state = ESPCONN_WRITE; - if (!espconn_find_connection(pespconn, &pnode)) { - return ESPCONN_ARG; - } - - espconn_tcp_hold(pnode); - return ESPCONN_OK; +/****************************************************************************** + * FunctionName : espconn_dns_setserver + * Description : Initialize one of the DNS servers. + * Parameters : numdns -- the index of the DNS server to set must + * be < DNS_MAX_SERVERS = 2 + * dnsserver -- IP address of the DNS server to set + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_dns_setserver(u8_t numdns, ip_addr_t *dnsserver) +{ + dns_setserver(numdns,dnsserver); } -sint8 espconn_recv_unhold(struct espconn *pespconn) { - espconn_msg *pnode = NULL; - - if (pespconn == NULL) { - return ESPCONN_ARG; - } - pespconn->state = ESPCONN_WRITE; - if (!espconn_find_connection(pespconn, &pnode)) { - return ESPCONN_ARG; - } - - espconn_tcp_unhold(pnode); - return ESPCONN_OK; -} diff --git a/app/lwip/app/espconn_mdns.c b/app/lwip/app/espconn_mdns.c new file mode 100644 index 00000000..a29c64a5 --- /dev/null +++ b/app/lwip/app/espconn_mdns.c @@ -0,0 +1,134 @@ +/****************************************************************************** + * Copyright 2013-2014 Espressif Systems (Wuxi) + * + * FileName: espconn_mdns.c + * + * Description: udp proto interface + * + * Modification history: + * 2014/3/31, v1.0 create this file. +*******************************************************************************/ + +#include "ets_sys.h" +#include "os_type.h" + +#include "lwip/mdns.h" + +/****************************************************************************** + * FunctionName : espconn_mdns_enable + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_enable(void) +{ + mdns_enable(); +} +/****************************************************************************** + * FunctionName : espconn_mdns_disable + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_disable(void) +{ + mdns_disable(); +} + +/****************************************************************************** + * FunctionName : espconn_mdns_set_hostname + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_set_hostname(char *name) +{ + mdns_set_hostname(name); +} + +/****************************************************************************** + * FunctionName : espconn_mdns_init + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +char* ICACHE_FLASH_ATTR +espconn_mdns_get_hostname(void) +{ + return (char *)mdns_get_hostname(); +} +/****************************************************************************** + * FunctionName : espconn_mdns_get_servername + * Description : join a multicast group + * Parameters : info -- the info of mdns + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_set_servername(const char *name) +{ + mdns_set_servername(name); +} +/****************************************************************************** + * FunctionName : espconn_mdns_get_servername + * Description : join a multicast group + * Parameters : info -- the info of mdns + * Returns : none +*******************************************************************************/ +char* ICACHE_FLASH_ATTR +espconn_mdns_get_servername(void) +{ + return (char *)mdns_get_servername(); +} +/****************************************************************************** + * FunctionName : mdns_server_register + * Description : join a multicast group + * Parameters : info -- the info of mdns + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_server_register(void) +{ + mdns_server_register(); +} +/****************************************************************************** + * FunctionName : mdns_server_register + * Description : join a multicast group + * Parameters : info -- the info of mdns + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_server_unregister(void) +{ + mdns_server_unregister(); +} +/****************************************************************************** + * FunctionName : espconn_mdns_init + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_close(void) +{ + mdns_close(); +} +/****************************************************************************** + * FunctionName : espconn_mdns_init + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR +espconn_mdns_init(struct mdns_info *info) +{ + mdns_init(info); +} diff --git a/app/lwip/app/espconn_tcp.c b/app/lwip/app/espconn_tcp.c index da5c441a..96975173 100644 --- a/app/lwip/app/espconn_tcp.c +++ b/app/lwip/app/espconn_tcp.c @@ -25,8 +25,11 @@ #include "lwip/app/espconn_tcp.h" extern espconn_msg *plink_active; -extern uint32 link_timer; extern espconn_msg *pserver_list; +extern struct espconn_packet pktinfo[2]; +extern struct tcp_pcb ** const tcp_pcb_lists[]; + +os_event_t espconn_TaskQueue[espconn_TaskQueueLen]; static err_t espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); @@ -39,6 +42,176 @@ static void espconn_server_close(void *arg, struct tcp_pcb *pcb); ///////////////////////////////common function///////////////////////////////// +/****************************************************************************** + * FunctionName : espconn_kill_oldest + * Description : kill the oldest TCP block + * Parameters : none + * Returns : none +*******************************************************************************/ +static void ICACHE_FLASH_ATTR +espconn_kill_oldest(void) +{ + struct tcp_pcb *pcb, *inactive; + u32_t inactivity; + + inactivity = 0; + inactive = NULL; + /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */ + for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { + if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + if (inactive != NULL) { + tcp_abort(inactive); + } + + /* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */ + inactivity = 0; + inactive = NULL; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == FIN_WAIT_2){ + if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + /*Purges the PCB, removes it from a PCB list and frees the memory*/ + if (inactive != NULL) { + tcp_pcb_remove(&tcp_active_pcbs, inactive); + memp_free(MEMP_TCP_PCB, inactive); + } + + /* Go through the list of LAST_ACK pcbs and get the oldest pcb. */ + inactivity = 0; + inactive = NULL; + for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { + if (pcb->state == LAST_ACK) { + if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) { + inactivity = tcp_ticks - pcb->tmr; + inactive = pcb; + } + } + } + /*Purges the PCB, removes it from a PCB list and frees the memory*/ + if (inactive != NULL) { + tcp_pcb_remove(&tcp_active_pcbs, inactive); + memp_free(MEMP_TCP_PCB, inactive); + } +} + +/****************************************************************************** + * FunctionName : espconn_kill_oldest_pcb + * Description : find the oldest TCP block by state + * Parameters : none + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR espconn_kill_oldest_pcb(void) +{ + struct tcp_pcb *cpcb = NULL; + uint8 i = 0; + uint8 num_tcp_fin = 0; + for(i = 2; i < 4; i ++){ + for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { + if (cpcb->state == TIME_WAIT){ + num_tcp_fin ++; + if (num_tcp_fin == MEMP_NUM_TCP_PCB) + break; + } + + if (cpcb->state == FIN_WAIT_2 || cpcb->state == LAST_ACK){ + num_tcp_fin++; + if (num_tcp_fin == MEMP_NUM_TCP_PCB) + break; + } + } + + if (num_tcp_fin == MEMP_NUM_TCP_PCB){ + num_tcp_fin = 0; + espconn_kill_oldest(); + } + } +} + +/****************************************************************************** + * FunctionName : espconn_kill_pcb + * Description : kill all the TCP block by port + * Parameters : none + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR espconn_kill_pcb(u16_t port) +{ + struct tcp_pcb *cpcb = NULL; + uint8 i = 0; + struct tcp_pcb *inactive = NULL; + struct tcp_pcb *prev = NULL; + u8_t pcb_remove; + /* Check if the address already is in use (on all lists) */ + for (i = 1; i < 4; i++) { + cpcb = *tcp_pcb_lists[i]; + while(cpcb != NULL){ + pcb_remove = 0; + if (cpcb->local_port == port) { + ++pcb_remove; + } + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + /* Remove PCB from tcp_pcb_lists list. */ + inactive = cpcb; + cpcb = inactive->next; + tcp_pcb_remove(tcp_pcb_lists[i], inactive); + memp_free(MEMP_TCP_PCB, inactive); + } else { + cpcb = cpcb->next; + } + } + } +} + +/****************************************************************************** + * FunctionName : espconn_find_current_pcb + * Description : find the TCP block which option + * Parameters : pcurrent_msg -- the node in the list which active + * Returns : TCP block point +*******************************************************************************/ +struct tcp_pcb *ICACHE_FLASH_ATTR espconn_find_current_pcb(espconn_msg *pcurrent_msg) +{ + uint16 local_port = pcurrent_msg->pcommon.local_port; + uint32 local_ip = pcurrent_msg->pcommon.local_ip; + uint16 remote_port = pcurrent_msg->pcommon.remote_port; + uint32 remote_ip = *((uint32*)&pcurrent_msg->pcommon.remote_ip); + struct tcp_pcb *find_pcb = NULL; + if (pcurrent_msg ->preverse == NULL){/*Find the server's TCP block*/ + if (local_ip == 0|| local_port == 0) return pcurrent_msg->pcommon.pcb; + + for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){ + if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) && + (find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip)) + return find_pcb; + } + + for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){ + if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) && + (find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip)) + return find_pcb; + } + } else {/*Find the client's TCP block*/ + if (remote_ip == 0|| remote_port == 0) return pcurrent_msg->pcommon.pcb; + + for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){ + if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip)) + return find_pcb; + } + + for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){ + if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip)) + return find_pcb; + } + } + return NULL; +} /****************************************************************************** * FunctionName : espconn_tcp_reconnect @@ -51,11 +224,14 @@ espconn_tcp_reconnect(void *arg) { espconn_msg *precon_cb = arg; sint8 re_err = 0; + espconn_buf *perr_buf = NULL; + espconn_buf *perr_back = NULL; + espconn_kill_oldest_pcb(); if (precon_cb != NULL) { struct espconn *espconn = precon_cb->preverse; re_err = precon_cb->pcommon.err; if (precon_cb->pespconn != NULL){ - if (espconn != NULL){ + if (espconn != NULL){/*Process the server's message block*/ if (precon_cb->pespconn->proto.tcp != NULL){ espconn_copy_partial(espconn, precon_cb->pespconn); espconn_printf("server: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->remote_ip[0], @@ -66,17 +242,28 @@ espconn_tcp_reconnect(void *arg) } os_free(precon_cb->pespconn); precon_cb->pespconn = NULL; - } else { + } else {/*Process the client's message block*/ espconn = precon_cb->pespconn; espconn_printf("client: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->local_ip[0], espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2], espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port); } } + + /*to prevent memory leaks, ensure that each allocated is deleted*/ + perr_buf = precon_cb->pcommon.pbuf; + while (perr_buf != NULL){ + perr_back = perr_buf; + perr_buf = perr_back->pnext; + espconn_pbuf_delete(&precon_cb->pcommon.pbuf,perr_back); + os_free(perr_back); + perr_back = NULL; + } + os_bzero(&pktinfo[1], sizeof(struct espconn_packet)); + os_memcpy(&pktinfo[1], (void*)&precon_cb->pcommon.packet_info, sizeof(struct espconn_packet)); os_free(precon_cb); precon_cb = NULL; - - if (espconn->proto.tcp->reconnect_callback != NULL) { + if (espconn && espconn->proto.tcp && espconn->proto.tcp->reconnect_callback != NULL) { espconn->proto.tcp->reconnect_callback(espconn, re_err); } } else { @@ -95,14 +282,17 @@ espconn_tcp_disconnect_successful(void *arg) { espconn_msg *pdiscon_cb = arg; sint8 dis_err = 0; + espconn_buf *pdis_buf = NULL; + espconn_buf *pdis_back = NULL; + espconn_kill_oldest_pcb(); if (pdiscon_cb != NULL) { struct espconn *espconn = pdiscon_cb->preverse; dis_err = pdiscon_cb->pcommon.err; if (pdiscon_cb->pespconn != NULL){ struct tcp_pcb *pcb = NULL; - if (espconn != NULL){ - if (pdiscon_cb->pespconn->proto.tcp != NULL){ + if (espconn != NULL){/*Process the server's message block*/ + if (pdiscon_cb->pespconn->proto.tcp != NULL && espconn->proto.tcp){ espconn_copy_partial(espconn, pdiscon_cb->pespconn); espconn_printf("server: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->remote_ip[0], espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2], @@ -112,27 +302,69 @@ espconn_tcp_disconnect_successful(void *arg) } os_free(pdiscon_cb->pespconn); pdiscon_cb->pespconn = NULL; - } else { + } else {/*Process the client's message block*/ espconn = pdiscon_cb->pespconn; espconn_printf("client: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->local_ip[0], espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2], espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port); } - pcb = pdiscon_cb->pcommon.pcb; - tcp_arg(pcb, NULL); - tcp_err(pcb, NULL); - /*delete TIME_WAIT State pcb after 2MSL time,for not all data received by application.*/ - if (pdiscon_cb->pcommon.espconn_opt == ESPCONN_REUSEADDR){ - if (pcb->state == TIME_WAIT){ - tcp_pcb_remove(&tcp_tw_pcbs,pcb); - memp_free(MEMP_TCP_PCB,pcb); + /*process the current TCP block*/ + pcb = espconn_find_current_pcb(pdiscon_cb); + if (pcb != NULL){ + if (espconn_reuse_disabled(pdiscon_cb)) { + struct tcp_pcb *cpcb = NULL; + struct tcp_pcb *prev = NULL; + u8_t pcb_remove; + espconn_printf("espconn_tcp_disconnect_successful %d, %d\n", pcb->state, pcb->local_port); + cpcb = tcp_tw_pcbs; + while (cpcb != NULL) { + pcb_remove = 0; + if (cpcb->local_port == pcb->local_port) { + ++pcb_remove; + } + /* If the PCB should be removed, do it. */ + if (pcb_remove) { + struct tcp_pcb *backup_pcb = NULL; + tcp_pcb_purge(cpcb); + /* Remove PCB from tcp_tw_pcbs list. */ + if (prev != NULL) { + LWIP_ASSERT("espconn_tcp_delete: middle cpcb != tcp_tw_pcbs",cpcb != tcp_tw_pcbs); + prev->next = cpcb->next; + } else { + /* This PCB was the first. */ + LWIP_ASSERT("espconn_tcp_delete: first cpcb == tcp_tw_pcbs",tcp_tw_pcbs == cpcb); + tcp_tw_pcbs = cpcb->next; + } + backup_pcb = cpcb; + cpcb = cpcb->next; + memp_free(MEMP_TCP_PCB, backup_pcb); + } else { + prev = cpcb; + cpcb = cpcb->next; + } + } + + } else { + tcp_arg(pcb, NULL); + tcp_err(pcb, NULL); } } } + + /*to prevent memory leaks, ensure that each allocated is deleted*/ + pdis_buf = pdiscon_cb->pcommon.pbuf; + while (pdis_buf != NULL) { + pdis_back = pdis_buf; + pdis_buf = pdis_back->pnext; + espconn_pbuf_delete(&pdiscon_cb->pcommon.pbuf, pdis_back); + os_free(pdis_back); + pdis_back = NULL; + } + os_bzero(&pktinfo[0], sizeof(struct espconn_packet)); + os_memcpy(&pktinfo[0], (void*)&pdiscon_cb->pcommon.packet_info, sizeof(struct espconn_packet)); os_free(pdiscon_cb); pdiscon_cb = NULL; - - if (espconn->proto.tcp->disconnect_callback != NULL) { + if (espconn->proto.tcp && espconn->proto.tcp->disconnect_callback != NULL) { espconn->proto.tcp->disconnect_callback(espconn); } } else { @@ -140,15 +372,59 @@ espconn_tcp_disconnect_successful(void *arg) } } +/****************************************************************************** + * FunctionName : espconn_Task + * Description : espconn processing task + * Parameters : events -- contain the espconn processing data + * Returns : none +*******************************************************************************/ +static void ICACHE_FLASH_ATTR +espconn_Task(os_event_t *events) +{ + espconn_msg *task_msg = NULL; + struct espconn *pespconn = NULL; + + task_msg = (espconn_msg *) events->par; + switch (events->sig) { + case SIG_ESPCONN_WRITE: { + pespconn = task_msg->pespconn; + if (pespconn == NULL) { + return; + } + + if (pespconn->proto.tcp->write_finish_fn != NULL) { + pespconn->proto.tcp->write_finish_fn(pespconn); + } + } + break; + case SIG_ESPCONN_ERRER: + /*remove the node from the client's active connection list*/ + espconn_list_delete(&plink_active, task_msg); + espconn_tcp_reconnect(task_msg); + break; + case SIG_ESPCONN_CLOSE: + /*remove the node from the client's active connection list*/ + espconn_list_delete(&plink_active, task_msg); + espconn_tcp_disconnect_successful(task_msg); + break; + default: + break; + } +} + /****************************************************************************** * FunctionName : espconn_tcp_sent * Description : sent data for client or server * Parameters : void *arg -- client or server to send * uint8* psent -- Data to send * uint16 length -- Length of data to send - * Returns : none + * 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. *******************************************************************************/ -void ICACHE_FLASH_ATTR +err_t ICACHE_FLASH_ATTR espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) { espconn_msg *ptcp_sent = arg; @@ -159,10 +435,12 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) espconn_printf("espconn_tcp_sent ptcp_sent %p psent %p length %d\n", ptcp_sent, psent, length); + /*Check the parameters*/ if (ptcp_sent == NULL || psent == NULL || length == 0) { - return; + return ESPCONN_ARG; } + /*Set the packet length depend on the sender buffer space*/ pcb = ptcp_sent->pcommon.pcb; if (tcp_sndbuf(pcb) < length) { len = tcp_sndbuf(pcb); @@ -175,28 +453,34 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) len = 2*pcb->mss; } - do { - espconn_printf("espconn_tcp_sent writing %d bytes %p\n", len, pcb); - err = tcp_write(pcb, psent, len, 0); + /*Write data for sending, but does not send it immediately*/ + do { + espconn_printf("espconn_tcp_sent writing %d bytes %p\n", len, pcb); + if (espconn_copy_disabled(ptcp_sent)) + err = tcp_write(pcb, psent, len, 1); + else + err = tcp_write(pcb, psent, len, 0); if (err == ERR_MEM) { len /= 2; } } while (err == ERR_MEM && len > 1); + /*Find out what we can send and send it, offset the buffer point for next send*/ if (err == ERR_OK) { - data_to_send = true; - ptcp_sent->pcommon.ptrbuf = psent + len; - ptcp_sent->pcommon.cntr = length - len; - ptcp_sent->pcommon.write_len += len; - espconn_printf("espconn_tcp_sent sending %d bytes, remain %d\n", len, ptcp_sent->pcommon.cntr); - } - - if (data_to_send == true) { - err = tcp_output(pcb); - } else { - ptcp_sent->pespconn ->state = ESPCONN_CLOSE; + ptcp_sent->pcommon.ptail->punsent = psent + len; + ptcp_sent->pcommon.ptail->unsent = length - len; + err = tcp_output(pcb); + /*If enable the copy option, change the flag for next write*/ + if (espconn_copy_disabled(ptcp_sent)){ + if (ptcp_sent->pcommon.ptail->unsent == 0) { + ptcp_sent->pcommon.write_flag = true; + ets_post(espconn_TaskPrio, SIG_ESPCONN_WRITE, (uint32_t)ptcp_sent); + } + } + espconn_printf("espconn_tcp_sent %d\n", err); } + return err; } /****************************************************************************** @@ -208,45 +492,17 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) void ICACHE_FLASH_ATTR espconn_tcp_disconnect(espconn_msg *pdiscon) { if (pdiscon != NULL){ + /*disconnect with the host by send the FIN frame*/ if (pdiscon->preverse != NULL) espconn_server_close(pdiscon, pdiscon->pcommon.pcb); else espconn_client_close(pdiscon, pdiscon->pcommon.pcb); } else{ - espconn_printf("espconn_server_disconnect err.\n"); + espconn_printf("espconn_tcp_disconnect err.\n"); } } ///////////////////////////////client function///////////////////////////////// -/****************************************************************************** - * FunctionName : espconn_close - * Description : The connection has been successfully closed. - * Parameters : arg -- Additional argument to pass to the callback function - * Returns : none -*******************************************************************************/ -static void ICACHE_FLASH_ATTR -espconn_cclose_cb(void *arg) -{ - espconn_msg *pclose_cb = arg; - - if (pclose_cb == NULL) { - return; - } - - struct tcp_pcb *pcb = pclose_cb->pcommon.pcb; - - espconn_printf("espconn_close %d %d\n", pcb->state, pcb->nrtx); - - if (pcb->state == TIME_WAIT || pcb->state == CLOSED) { - pclose_cb ->pespconn ->state = ESPCONN_CLOSE; - /*remove the node from the client's active connection list*/ - espconn_list_delete(&plink_active, pclose_cb); - espconn_tcp_disconnect_successful((void*)pclose_cb); - } else { - os_timer_arm(&pclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0); - } -} - /****************************************************************************** * FunctionName : espconn_client_close * Description : The connection shall be actively closed. @@ -260,22 +516,80 @@ espconn_client_close(void *arg, struct tcp_pcb *pcb) err_t err; espconn_msg *pclose = arg; - os_timer_disarm(&pclose->pcommon.ptimer); - + pclose->pcommon.pcb = pcb; + /*avoid recalling the disconnect function*/ tcp_recv(pcb, NULL); err = tcp_close(pcb); - os_timer_setfn(&pclose->pcommon.ptimer, espconn_cclose_cb, pclose); - os_timer_arm(&pclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0); - if (err != ERR_OK) { - /* closing failed, try again later */ - tcp_recv(pcb, espconn_client_recv); - } else { - /* closing succeeded */ - tcp_sent(pcb, NULL); - } + if (err != ERR_OK) { + /* closing failed, try again later */ + tcp_recv(pcb, espconn_client_recv); + } else { + /* closing succeeded */ + tcp_sent(pcb, NULL); + tcp_err(pcb, NULL); + /*switch the state of espconn for application process*/ + pclose->pespconn->state = ESPCONN_CLOSE; + ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)pclose); + } } +//***********Code for WIFI_BLOCK from upper************** +sint8 ICACHE_FLASH_ATTR +espconn_recv_hold(struct espconn *pespconn) +{ + //1st, according to espconn code, have to find out the escpconn_msg by pespconn; + espconn_msg *pnode = NULL; + bool value = false; + if (pespconn == NULL) { + return ESPCONN_ARG; + } + value = espconn_find_connection(pespconn, &pnode); + if(value != true) + { + os_printf("RecvHold, By pespconn,find conn_msg fail\n"); + return ESPCONN_ARG; + } + + //2nd, the actual operation + if(pnode->recv_hold_flag == 0) + { + pnode->recv_hold_flag = 1; + pnode->recv_holded_buf_Len = 0; + } + return ESPCONN_OK; +} + +sint8 ICACHE_FLASH_ATTR +espconn_recv_unhold(struct espconn *pespconn) +{ + //1st, according to espconn code, have to find out the escpconn_msg by pespconn; + espconn_msg *pnode = NULL; + bool value = false; + if (pespconn == NULL) { + return ESPCONN_ARG; + } + value = espconn_find_connection(pespconn, &pnode); + if(value != true) + { + os_printf("RecvHold, By pespconn,find conn_msg fail\n"); + return ESPCONN_ARG; + } + + //2nd, the actual operation + if(pnode->recv_hold_flag == 1) + { + if(pespconn->type == ESPCONN_TCP) { + tcp_recved(pnode->pcommon.pcb, pnode->recv_holded_buf_Len); + } + pnode->recv_holded_buf_Len = 0; + pnode->recv_hold_flag = 0; + } + return ESPCONN_OK; +} + +//***********Code for WIFI_BLOCK from upper************** + /****************************************************************************** * FunctionName : espconn_client_recv * Description : Data has been received on this pcb. @@ -293,25 +607,35 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) tcp_arg(pcb, arg); if (p != NULL) { - tcp_recved(pcb, p ->tot_len); + /*To update and advertise a larger window*/ + if(precv_cb->recv_hold_flag == 0) + tcp_recved(pcb, p->tot_len); + else + precv_cb->recv_holded_buf_Len += p->tot_len; } if (err == ERR_OK && p != NULL) { char *pdata = NULL; u16_t length = 0; + /*Copy the contents of a packet buffer to an application buffer. + *to prevent memory leaks, ensure that each allocated is deleted*/ pdata = (char *)os_zalloc(p ->tot_len + 1); length = pbuf_copy_partial(p, pdata, p ->tot_len, 0); pbuf_free(p); if (length != 0) { + /*switch the state of espconn for application process*/ precv_cb->pespconn ->state = ESPCONN_READ; precv_cb->pcommon.pcb = pcb; if (precv_cb->pespconn->recv_callback != NULL) { precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length); } - precv_cb->pespconn ->state = ESPCONN_CONNECT; + /*switch the state of espconn for next packet copy*/ + if (pcb->state == ESTABLISHED) + precv_cb->pespconn ->state = ESPCONN_CONNECT; } + /*to prevent memory leaks, ensure that each allocated is deleted*/ os_free(pdata); pdata = NULL; } @@ -323,6 +647,73 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) return ERR_OK; } +/****************************************************************************** + * FunctionName : espconn_tcp_write + * Description : write the packet which in the active connection's list. + * Parameters : arg -- the node pointer which reverse the packet + * Returns : ESPCONN_MEM: memory error + * ESPCONN_OK:have enough space for write packet +*******************************************************************************/ +err_t ICACHE_FLASH_ATTR espconn_tcp_write(void *arg) +{ + espconn_msg *pwrite = arg; + err_t err = ERR_OK; + struct tcp_pcb *pcb = pwrite->pcommon.pcb; + /*for one active connection,limit the sender buffer space*/ + if (tcp_nagle_disabled(pcb) && (pcb->snd_queuelen >= TCP_SND_QUEUELEN)) + return ESPCONN_MEM; + + while (tcp_sndbuf(pcb) != 0){ + if (pwrite->pcommon.ptail != NULL) { + /*Find the node whether in the list's tail or not*/ + if (pwrite->pcommon.ptail->unsent == 0) { + pwrite->pcommon.ptail = pwrite->pcommon.ptail->pnext; + continue; + } + + /*Send the packet for the active connection*/ + err = espconn_tcp_sent(pwrite, pwrite->pcommon.ptail->punsent,pwrite->pcommon.ptail->unsent); + if (err != ERR_OK) + break; + } else + break; + } + return err; +} + +/****************************************************************************** + * FunctionName : espconn_tcp_reconnect + * Description : reconnect with host + * Parameters : arg -- Additional argument to pass to the callback function + * Returns : none +*******************************************************************************/ +static void ICACHE_FLASH_ATTR espconn_tcp_finish(void *arg) +{ + espconn_msg *pfinish = arg; + espconn_buf *premove = NULL; + uint16 len = 0; + espconn_tcp_write(pfinish); + while (pfinish->pcommon.pbuf != NULL){ + premove = pfinish->pcommon.pbuf; + pfinish->pcommon.pbuf->tot_len += len; + /*application packet has been sent and acknowledged by the remote host, + * to prevent memory leaks, ensure that each allocated is deleted*/ + if (premove->tot_len >= premove->len){ + espconn_pbuf_delete(&pfinish->pcommon.pbuf,premove); + len = premove->tot_len - premove->len; + pfinish->pcommon.packet_info.sent_length = premove->len; + os_free(premove); + premove = NULL; + pfinish->pespconn->state = ESPCONN_CONNECT; + if (pfinish->pespconn->sent_callback != NULL) { + pfinish->pespconn->sent_callback(pfinish->pespconn); + } + pfinish->pcommon.packet_info.sent_length = len; + } else + break; + } +} + /****************************************************************************** * FunctionName : espconn_client_sent * Description : Data has been sent and acknowledged by the remote host. @@ -339,53 +730,11 @@ espconn_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len) espconn_msg *psent_cb = arg; psent_cb->pcommon.pcb = pcb; - psent_cb->pcommon.write_total += len; - espconn_printf("espconn_client_sent sent %d %d\n", len, psent_cb->pcommon.write_total); - if (psent_cb->pcommon.write_total == psent_cb->pcommon.write_len){ - psent_cb->pcommon.write_total = 0; - psent_cb->pcommon.write_len = 0; - if (psent_cb->pcommon.cntr == 0) { - psent_cb->pespconn->state = ESPCONN_CONNECT; + psent_cb->pcommon.pbuf->tot_len += len; + psent_cb->pcommon.packet_info.sent_length = len; - if (psent_cb->pespconn->sent_callback != NULL) { - psent_cb->pespconn->sent_callback(psent_cb->pespconn); - } - } else - espconn_tcp_sent(psent_cb, psent_cb->pcommon.ptrbuf, psent_cb->pcommon.cntr); - } else { - - } - return ERR_OK; -} - -/****************************************************************************** - * FunctionName : espconn_client_poll - * Description : The poll function is called every 2nd second. - * If there has been no data sent (which resets the retries) in 8 seconds, close. - * If the last portion of a file has not been sent in 2 seconds, close. - * - * This could be increased, but we don't want to waste resources for bad connections. - * Parameters : arg -- Additional argument to pass to the callback function - * pcb -- The connection pcb for which data has been acknowledged - * Returns : ERR_OK: try to send some data by calling tcp_output - * ERR_ABRT: if you have called tcp_abort from within the function! -*******************************************************************************/ -static err_t ICACHE_FLASH_ATTR -espconn_client_poll(void *arg, struct tcp_pcb *pcb) -{ - espconn_msg *ppoll_cb = arg; - espconn_printf("espconn_client_poll pcb %p %p %d\n", pcb, arg, pcb->state); - if (arg == NULL) { - tcp_abandon(pcb, 0); - tcp_poll(pcb, NULL, 0); - return ERR_ABRT; - } - ppoll_cb->pcommon.pcb = pcb; - if (pcb->state == ESTABLISHED) { - } else { - tcp_poll(pcb, espconn_client_poll, 0); - espconn_client_close(ppoll_cb->pespconn, pcb); - } + /*Send more data for one active connection*/ + espconn_tcp_finish(psent_cb); return ERR_OK; } @@ -406,14 +755,14 @@ espconn_client_err(void *arg, err_t err) LWIP_UNUSED_ARG(err); if (perr_cb != NULL) { - os_timer_disarm(&perr_cb->pcommon.ptimer); pcb = perr_cb->pcommon.pcb; perr_cb->pespconn->state = ESPCONN_CLOSE; espconn_printf("espconn_client_err %d %d %d\n", pcb->state, pcb->nrtx, err); - /*remove the node from the client's active connection list*/ - espconn_list_delete(&plink_active, perr_cb); +// /*remove the node from the client's active connection list*/ +// espconn_list_delete(&plink_active, perr_cb); + /*Set the error code depend on the error type and control block state*/ if (err == ERR_ABRT) { switch (pcb->state) { case SYN_SENT: @@ -450,9 +799,8 @@ espconn_client_err(void *arg, err_t err) } else { perr_cb->pcommon.err = err; } - os_timer_setfn(&perr_cb->pcommon.ptimer, - (os_timer_func_t *) espconn_tcp_reconnect, perr_cb); - os_timer_arm(&perr_cb->pcommon.ptimer, 10, 0); + /*post the singer to the task for processing the connection*/ + ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)perr_cb); } } @@ -468,19 +816,41 @@ static err_t ICACHE_FLASH_ATTR espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err) { espconn_msg *pcon = arg; + espconn_printf("espconn_client_connect pcon %p tpcb %p\n", pcon, tpcb); if (err == ERR_OK){ + /*Reserve the remote information for current active connection*/ pcon->pespconn->state = ESPCONN_CONNECT; pcon->pcommon.err = err; pcon->pcommon.pcb = tpcb; - tcp_arg(tpcb, (void *)pcon); + pcon->pcommon.local_port = tpcb->local_port; + pcon->pcommon.local_ip = tpcb->local_ip.addr; + pcon->pcommon.remote_port = tpcb->remote_port; + pcon->pcommon.remote_ip[0] = ip4_addr1_16(&tpcb->remote_ip); + pcon->pcommon.remote_ip[1] = ip4_addr2_16(&tpcb->remote_ip); + pcon->pcommon.remote_ip[2] = ip4_addr3_16(&tpcb->remote_ip); + pcon->pcommon.remote_ip[3] = ip4_addr4_16(&tpcb->remote_ip); + pcon->pcommon.write_flag = true; + tcp_arg(tpcb, (void *) pcon); + + /*Set the specify function that should be called + * when TCP data has been successfully delivered, + * when active connection receives data*/ tcp_sent(tpcb, espconn_client_sent); tcp_recv(tpcb, espconn_client_recv); + /*Disable Nagle algorithm default*/ + tcp_nagle_disable(tpcb); + /*Default set the total number of espconn_buf on the unsent lists for one*/ + espconn_tcp_set_buf_count(pcon->pespconn, 1); - //tcp_poll(tpcb, espconn_client_poll, 1); if (pcon->pespconn->proto.tcp->connect_callback != NULL) { pcon->pespconn->proto.tcp->connect_callback(pcon->pespconn); } + + /*Enable keep alive option*/ + if (espconn_keepalive_disabled(pcon)) + espconn_keepalive_enable(tpcb); + } else{ os_printf("err in host connected (%s)\n",lwip_strerr(err)); } @@ -501,24 +871,28 @@ espconn_tcp_client(struct espconn *espconn) struct ip_addr ipaddr; espconn_msg *pclient = NULL; + /*Creates a new client control message*/ pclient = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); if (pclient == NULL){ return ESPCONN_MEM; } + /*Set an IP address given for Little-endian.*/ IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0], espconn->proto.tcp->remote_ip[1], espconn->proto.tcp->remote_ip[2], espconn->proto.tcp->remote_ip[3]); + /*Creates a new TCP protocol control block*/ pcb = tcp_new(); if (pcb == NULL) { -// pclient ->pespconn ->state = ESPCONN_NONE; + /*to prevent memory leaks, ensure that each allocated is deleted*/ os_free(pclient); pclient = NULL; return ESPCONN_MEM; } else { + /*insert the node to the active connection list*/ espconn_list_creat(&plink_active, pclient); tcp_arg(pcb, (void *)pclient); @@ -528,39 +902,22 @@ espconn_tcp_client(struct espconn *espconn) pclient->pespconn->state = ESPCONN_WAIT; pclient->pcommon.pcb = pcb; tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port); + /*Establish the connection*/ pclient->pcommon.err = tcp_connect(pcb, &ipaddr, pclient->pespconn->proto.tcp->remote_port, espconn_client_connect); + if (pclient->pcommon.err == ERR_RTE){ + /*remove the node from the client's active connection list*/ + espconn_list_delete(&plink_active, pclient); + espconn_kill_pcb(pcb->local_port); + os_free(pclient); + pclient = NULL; + return ESPCONN_RTE; + } return pclient->pcommon.err; } } ///////////////////////////////server function///////////////////////////////// -/****************************************************************************** - * FunctionName : espconn_closed - * Description : The connection has been successfully closed. - * Parameters : arg -- Additional argument to pass to the callback function - * Returns : none -*******************************************************************************/ -static void ICACHE_FLASH_ATTR -espconn_sclose_cb(void *arg) -{ - espconn_msg *psclose_cb = arg; - if (psclose_cb == NULL) { - return; - } - - struct tcp_pcb *pcb = psclose_cb ->pcommon.pcb; - espconn_printf("espconn_sclose_cb %d %d\n", pcb->state, pcb->nrtx); - if (pcb->state == CLOSED || pcb->state == TIME_WAIT) { - psclose_cb ->pespconn ->state = ESPCONN_CLOSE; - /*remove the node from the server's active connection list*/ - espconn_list_delete(&plink_active, psclose_cb); - espconn_tcp_disconnect_successful(psclose_cb); - } else { - os_timer_arm(&psclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0); - } -} - /****************************************************************************** * FunctionName : espconn_server_close * Description : The connection shall be actively closed. @@ -574,12 +931,10 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb) err_t err; espconn_msg *psclose = arg; - os_timer_disarm(&psclose->pcommon.ptimer); - - tcp_recv(pcb, NULL); - err = tcp_close(pcb); - os_timer_setfn(&psclose->pcommon.ptimer, espconn_sclose_cb, psclose); - os_timer_arm(&psclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0); + psclose->pcommon.pcb = pcb; + /*avoid recalling the disconnect function*/ + tcp_recv(pcb, NULL); + err = tcp_close(pcb); if (err != ERR_OK) { /* closing failed, try again later */ @@ -588,7 +943,11 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb) /* closing succeeded */ tcp_poll(pcb, NULL, 0); tcp_sent(pcb, NULL); - } + tcp_err(pcb, NULL); + /*switch the state of espconn for application process*/ + psclose->pespconn->state = ESPCONN_CLOSE; + ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)psclose); + } } /****************************************************************************** @@ -608,26 +967,38 @@ espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) tcp_arg(pcb, arg); espconn_printf("server has application data received: %d\n", system_get_free_heap_size()); if (p != NULL) { - tcp_recved(pcb, p->tot_len); + /*To update and advertise a larger window*/ + if(precv_cb->recv_hold_flag == 0) + tcp_recved(pcb, p->tot_len); + else + precv_cb->recv_holded_buf_Len += p->tot_len; } if (err == ERR_OK && p != NULL) { u8_t *data_ptr = NULL; u32_t data_cntr = 0; + /*clear the count for connection timeout*/ precv_cb->pcommon.recv_check = 0; + /*Copy the contents of a packet buffer to an application buffer. + *to prevent memory leaks, ensure that each allocated is deleted*/ data_ptr = (u8_t *)os_zalloc(p ->tot_len + 1); data_cntr = pbuf_copy_partial(p, data_ptr, p ->tot_len, 0); pbuf_free(p); if (data_cntr != 0) { + /*switch the state of espconn for application process*/ precv_cb->pespconn ->state = ESPCONN_READ; precv_cb->pcommon.pcb = pcb; if (precv_cb->pespconn->recv_callback != NULL) { precv_cb->pespconn->recv_callback(precv_cb->pespconn, data_ptr, data_cntr); } - precv_cb->pespconn ->state = ESPCONN_CONNECT; + + /*switch the state of espconn for next packet copy*/ + if (pcb->state == ESTABLISHED) + precv_cb->pespconn ->state = ESPCONN_CONNECT; } + /*to prevent memory leaks, ensure that each allocated is deleted*/ os_free(data_ptr); data_ptr = NULL; espconn_printf("server's application data has been processed: %d\n", system_get_free_heap_size()); @@ -659,22 +1030,11 @@ espconn_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len) psent_cb->pcommon.pcb = pcb; psent_cb->pcommon.recv_check = 0; - psent_cb->pcommon.write_total += len; - espconn_printf("espconn_server_sent sent %d %d\n", len, psent_cb->pcommon.write_total); - if (psent_cb->pcommon.write_total == psent_cb->pcommon.write_len){ - psent_cb->pcommon.write_total = 0; - psent_cb->pcommon.write_len = 0; - if (psent_cb ->pcommon.cntr == 0) { - psent_cb ->pespconn ->state = ESPCONN_CONNECT; + psent_cb->pcommon.pbuf->tot_len += len; + psent_cb->pcommon.packet_info.sent_length = len; - if (psent_cb ->pespconn ->sent_callback != NULL) { - psent_cb ->pespconn ->sent_callback(psent_cb ->pespconn); - } - } else - espconn_tcp_sent(psent_cb, psent_cb ->pcommon.ptrbuf, psent_cb ->pcommon.cntr); - } else { - - } + /*Send more data for one active connection*/ + espconn_tcp_finish(psent_cb); return ERR_OK; } @@ -695,30 +1055,37 @@ espconn_server_poll(void *arg, struct tcp_pcb *pcb) { espconn_msg *pspoll_cb = arg; + /*exception calling abandon the connection for send a RST frame*/ if (arg == NULL) { tcp_abandon(pcb, 0); tcp_poll(pcb, NULL, 0); - return ERR_ABRT; + return ERR_OK; } espconn_printf("espconn_server_poll %d %d\n", pspoll_cb->pcommon.recv_check, pcb->state); pspoll_cb->pcommon.pcb = pcb; if (pcb->state == ESTABLISHED) { pspoll_cb->pcommon.recv_check++; - if (pspoll_cb->pcommon.timeout != 0){ - if (pspoll_cb->pcommon.recv_check == pspoll_cb->pcommon.timeout) { - pspoll_cb->pcommon.recv_check = 0; - espconn_server_close(pspoll_cb, pcb); - } - } else if (link_timer != 0){ - if (pspoll_cb->pcommon.recv_check == link_timer) { + if (pspoll_cb->pcommon.timeout != 0){/*no data sent in one active connection's set timeout, close.*/ + if (pspoll_cb->pcommon.recv_check >= pspoll_cb->pcommon.timeout) { pspoll_cb->pcommon.recv_check = 0; espconn_server_close(pspoll_cb, pcb); } } else { - if (pspoll_cb->pcommon.recv_check == 0x0a) { - pspoll_cb->pcommon.recv_check = 0; - espconn_server_close(pspoll_cb, pcb); + espconn_msg *ptime_msg = pserver_list; + while (ptime_msg != NULL) { + if (ptime_msg->pespconn == pspoll_cb->preverse){ + if (ptime_msg->pcommon.timeout != 0){/*no data sent in server's set timeout, close.*/ + if (pspoll_cb->pcommon.recv_check >= ptime_msg->pcommon.timeout){ + pspoll_cb->pcommon.recv_check = 0; + espconn_server_close(pspoll_cb, pcb); + } + } else {/*don't close for ever*/ + pspoll_cb->pcommon.recv_check = 0; + } + break; + } + ptime_msg = ptime_msg->pnext; } } } else { @@ -742,13 +1109,14 @@ esponn_server_err(void *arg, err_t err) espconn_msg *pserr_cb = arg; struct tcp_pcb *pcb = NULL; if (pserr_cb != NULL) { - os_timer_disarm(&pserr_cb->pcommon.ptimer); + pcb = pserr_cb->pcommon.pcb; pserr_cb->pespconn->state = ESPCONN_CLOSE; - /*remove the node from the server's active connection list*/ - espconn_list_delete(&plink_active, pserr_cb); +// /*remove the node from the server's active connection list*/ +// espconn_list_delete(&plink_active, pserr_cb); + /*Set the error code depend on the error type and control block state*/ if (err == ERR_ABRT) { switch (pcb->state) { case SYN_RCVD: @@ -789,10 +1157,8 @@ esponn_server_err(void *arg, err_t err) } else { pserr_cb->pcommon.err = err; } - - os_timer_setfn(&pserr_cb->pcommon.ptimer, - (os_timer_func_t *) espconn_tcp_reconnect, pserr_cb); - os_timer_arm(&pserr_cb->pcommon.ptimer, 10, 0); + /*post the singer to the task for processing the connection*/ + ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)pserr_cb); } } @@ -812,12 +1178,25 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) remot_info *pinfo = NULL; LWIP_UNUSED_ARG(err); + if (!espconn || !espconn->proto.tcp) { + return ERR_ARG; + } + + tcp_arg(pcb, paccept); + tcp_err(pcb, esponn_server_err); + /*Ensure the active connection is less than the count of active connections on the server*/ + espconn_get_connection_info(espconn, &pinfo , 0); + espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt); + if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn)) + return ERR_ISCONN; + + /*Creates a new active connect control message*/ paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); tcp_arg(pcb, paccept); - tcp_err(pcb, esponn_server_err); + if (paccept == NULL) return ERR_MEM; - /*insert the node to the active connection list*/ + /*Insert the node to the active connection list*/ espconn_list_creat(&plink_active, paccept); paccept->preverse = espconn; @@ -828,9 +1207,7 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) if (paccept->pespconn->proto.tcp == NULL) return ERR_MEM; - //paccept->pcommon.timeout = 0x0a; - //link_timer = 0x0a; - + /*Reserve the remote information for current active connection*/ paccept->pcommon.pcb = pcb; paccept->pcommon.remote_port = pcb->remote_port; @@ -838,24 +1215,33 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip); paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip); paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip); + paccept->pcommon.write_flag = true; os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4); espconn->proto.tcp->remote_port = pcb->remote_port; espconn->state = ESPCONN_CONNECT; espconn_copy_partial(paccept->pespconn, espconn); - espconn_get_connection_info(espconn, &pinfo , 0); - espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt); - if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn) + 1) - return ERR_ISCONN; + /*Set the specify function that should be called + * when TCP data has been successfully delivered, + * when active connection receives data, + * or periodically from active connection*/ tcp_sent(pcb, espconn_server_sent); tcp_recv(pcb, espconn_server_recv); tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */ + /*Disable Nagle algorithm default*/ + tcp_nagle_disable(pcb); + /*Default set the total number of espconn_buf on the unsent lists for one*/ + espconn_tcp_set_buf_count(paccept->pespconn, 1); if (paccept->pespconn->proto.tcp->connect_callback != NULL) { paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn); } + /*Enable keep alive option*/ + if (espconn_keepalive_disabled(paccept)) + espconn_keepalive_enable(pcb); + return ERR_OK; } @@ -872,19 +1258,25 @@ espconn_tcp_server(struct espconn *espconn) struct tcp_pcb *pcb = NULL; espconn_msg *pserver = NULL; + /*Creates a new server control message*/ pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); if (pserver == NULL){ return ESPCONN_MEM; } + /*Creates a new TCP protocol control block*/ pcb = tcp_new(); if (pcb == NULL) { -// espconn ->state = ESPCONN_NONE; + /*to prevent memory leaks, ensure that each allocated is deleted*/ os_free(pserver); pserver = NULL; return ESPCONN_MEM; } else { + struct tcp_pcb *lpcb = NULL; + /*Binds the connection to a local port number and any IP address*/ tcp_bind(pcb, IP_ADDR_ANY, espconn->proto.tcp->local_port); + lpcb = pcb; + /*malloc and set the state of the connection to be LISTEN*/ pcb = tcp_listen(pcb); if (pcb != NULL) { /*insert the node to the active connection list*/ @@ -892,14 +1284,16 @@ espconn_tcp_server(struct espconn *espconn) pserver->preverse = pcb; pserver->pespconn = espconn; pserver->count_opt = MEMP_NUM_TCP_PCB; - + pserver->pcommon.timeout = 0x0a; espconn ->state = ESPCONN_LISTEN; + /*set the specify argument that should be passed callback function*/ tcp_arg(pcb, (void *)espconn); -// tcp_err(pcb, esponn_server_err); + /*accept callback function to call for this control block*/ tcp_accept(pcb, espconn_tcp_accept); return ESPCONN_OK; } else { -// espconn ->state = ESPCONN_NONE; + /*to prevent memory leaks, ensure that each allocated is deleted*/ + memp_free(MEMP_TCP_PCB,lpcb); os_free(pserver); pserver = NULL; return ESPCONN_MEM; @@ -924,17 +1318,19 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon) return ESPCONN_ARG; espconn_get_connection_info(pdeletecon, &pinfo , 0); + /*make sure all the active connection have been disconnect*/ if (pdeletecon->link_cnt != 0) return ESPCONN_INPROGRESS; else { - os_printf("espconn_tcp_delete %p\n",pdeletecon); + espconn_printf("espconn_tcp_delete %p\n",pdeletecon); pdelete_msg = pserver_list; while (pdelete_msg != NULL){ if (pdelete_msg->pespconn == pdeletecon){ /*remove the node from the client's active connection list*/ espconn_list_delete(&pserver_list, pdelete_msg); pcb = pdelete_msg->preverse; - os_printf("espconn_tcp_delete %d\n",pcb->state); + os_printf("espconn_tcp_delete %d, %d\n",pcb->state, pcb->local_port); + espconn_kill_pcb(pcb->local_port); err = tcp_close(pcb); os_free(pdelete_msg); pdelete_msg = NULL; @@ -949,18 +1345,13 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon) } } -void espconn_tcp_hold(void *arg) { - espconn_msg *ptcp_sent = arg; - struct tcp_pcb *pcb = NULL; - pcb = ptcp_sent->pcommon.pcb; - - pcb->hold = 1; -} - -void espconn_tcp_unhold(void *arg) { - espconn_msg *ptcp_sent = arg; - struct tcp_pcb *pcb = NULL; - pcb = ptcp_sent->pcommon.pcb; - - pcb->hold = 0; +/****************************************************************************** + * FunctionName : espconn_init + * Description : used to init the function that should be used when + * Parameters : none + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR espconn_init(void) +{ + ets_task(espconn_Task, espconn_TaskPrio, espconn_TaskQueue, espconn_TaskQueueLen); } diff --git a/app/lwip/app/espconn_udp.c b/app/lwip/app/espconn_udp.c index a9dd7f0c..8a8395cc 100644 --- a/app/lwip/app/espconn_udp.c +++ b/app/lwip/app/espconn_udp.c @@ -1,298 +1,330 @@ -/****************************************************************************** - * Copyright 2013-2014 Espressif Systems (Wuxi) - * - * FileName: espconn_udp.c - * - * Description: udp proto interface - * - * Modification history: - * 2014/3/31, v1.0 create this file. -*******************************************************************************/ - -#include "ets_sys.h" -#include "os_type.h" -//#include "os.h" - -#include "lwip/inet.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/mem.h" -#include "lwip/tcp_impl.h" -#include "lwip/udp.h" - -#include "lwip/app/espconn_udp.h" - -extern espconn_msg *plink_active; - -static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn) -{ - if (pespconn == NULL) { - return; - } - - if (pespconn->sent_callback != NULL) { - pespconn->sent_callback(pespconn); - } -} - -static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg) -{ - espconn_msg *psent = arg; - - if (psent == NULL) { - return; - } - - if (psent->pcommon.cntr == 0) { - psent->pespconn->state = ESPCONN_CONNECT; - sys_timeout(TCP_FAST_INTERVAL, espconn_data_sentcb, psent->pespconn); - } else { - espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr); - } -} - -/****************************************************************************** - * FunctionName : espconn_udp_sent - * Description : sent data for client or server - * Parameters : void *arg -- client or server to send - * uint8* psent -- Data to send - * uint16 length -- Length of data to send - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR -espconn_udp_sent(void *arg, uint8 *psent, uint16 length) -{ - espconn_msg *pudp_sent = arg; - struct udp_pcb *upcb = pudp_sent->pcommon.pcb; - struct pbuf *p, *q; - 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; - } - - if (1024 < length) { - datalen = 1024; - } 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; - } - - upcb->remote_port = pudp_sent->pespconn->proto.udp->remote_port; - IP4_ADDR(&upcb->remote_ip, pudp_sent->pespconn->proto.udp->remote_ip[0], - pudp_sent->pespconn->proto.udp->remote_ip[1], - pudp_sent->pespconn->proto.udp->remote_ip[2], - pudp_sent->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)); - err = udp_send(upcb, p); - LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d\n", __LINE__, err)); - - if (p->ref != 0) { - LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p)); - pbuf_free(p); - pudp_sent->pcommon.ptrbuf = psent + datalen; - pudp_sent->pcommon.cntr = length - datalen; - espconn_data_sent(pudp_sent); - } -} - -/****************************************************************************** - * FunctionName : espconn_udp_server_recv - * Description : This callback will be called when receiving a datagram. - * Parameters : arg -- user supplied argument - * upcb -- the udp_pcb which received data - * p -- the packet buffer that was received - * addr -- the remote IP address from which the packet was received - * port -- the remote port from which the packet was received - * Returns : none -*******************************************************************************/ -static void ICACHE_FLASH_ATTR -espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, - struct ip_addr *addr, u16_t port) -{ - espconn_msg *precv = arg; - struct pbuf *q = NULL; - u8_t *pdata = NULL; - u16_t length = 0; - struct ip_info ipconfig; - - 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_port = port; - precv->pcommon.pcb = upcb; - - if (wifi_get_opmode() != 1) { - wifi_get_ip_info(1, &ipconfig); - - if (!ip_addr_netcmp((struct ip_addr *)precv->pespconn->proto.udp->remote_ip, &ipconfig.ip, &ipconfig.netmask)) { - wifi_get_ip_info(0, &ipconfig); - } - } else { - wifi_get_ip_info(0, &ipconfig); - } - upcb->local_ip = ipconfig.ip; - precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&upcb->local_ip); - precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&upcb->local_ip); - precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&upcb->local_ip); - precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&upcb->local_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; - pbuf_free(p); - if (length != 0) { - if (precv->pespconn->recv_callback != NULL) { - precv->pespconn->recv_callback(precv->pespconn, pdata, length); - } - } - os_free(pdata); - } else { - return; - } -} - -/****************************************************************************** - * FunctionName : espconn_udp_disconnect - * Description : A new incoming connection has been disconnected. - * Parameters : espconn -- the espconn used to disconnect with host - * Returns : none -*******************************************************************************/ -void ICACHE_FLASH_ATTR espconn_udp_disconnect(espconn_msg *pdiscon) -{ - if (pdiscon == NULL) { - return; - } - - struct udp_pcb *upcb = pdiscon->pcommon.pcb; - - udp_disconnect(upcb); - - udp_remove(upcb); - - espconn_list_delete(&plink_active, pdiscon); - - os_free(pdiscon); - pdiscon = NULL; -} - -/****************************************************************************** - * FunctionName : espconn_udp_server - * Description : Initialize the server: set up a PCB and bind it to the port - * Parameters : pespconn -- the espconn used to build server - * Returns : none -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_udp_server(struct espconn *pespconn) -{ - struct udp_pcb *upcb = NULL; - espconn_msg *pserver = NULL; - upcb = udp_new(); - - if (upcb == NULL) { - return ESPCONN_MEM; - } else { - pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); - - if (pserver == NULL) { - udp_remove(upcb); - return ESPCONN_MEM; - } - - pserver->pcommon.pcb = upcb; - pserver->pespconn = pespconn; - espconn_list_creat(&plink_active, pserver); - udp_bind(upcb, IP_ADDR_ANY, pserver->pespconn->proto.udp->local_port); - udp_recv(upcb, espconn_udp_recv, (void *)pserver); - return ESPCONN_OK; - } -} - -/****************************************************************************** - * FunctionName : espconn_igmp_leave - * Description : leave a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip) -{ - if (igmp_leavegroup(host_ip, multicast_ip) != ERR_OK) { - LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_leave_multigrup failed!\n")); - return -1; - }; - - return ESPCONN_OK; -} - -/****************************************************************************** - * FunctionName : espconn_igmp_join - * Description : join a multicast group - * Parameters : host_ip -- the ip address of udp server - * multicast_ip -- multicast ip given by user - * Returns : none -*******************************************************************************/ -sint8 ICACHE_FLASH_ATTR -espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip) -{ - if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) { - LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n")); - return -1; - }; - - /* join to any IP address at the port */ - return ESPCONN_OK; -} +/****************************************************************************** + * Copyright 2013-2014 Espressif Systems (Wuxi) + * + * FileName: espconn_udp.c + * + * Description: udp proto interface + * + * Modification history: + * 2014/3/31, v1.0 create this file. +*******************************************************************************/ + +#include "ets_sys.h" +#include "os_type.h" +//#include "os.h" + +#include "lwip/inet.h" +#include "lwip/err.h" +#include "lwip/pbuf.h" +#include "lwip/mem.h" +#include "lwip/tcp_impl.h" +#include "lwip/udp.h" + +#include "lwip/app/espconn_udp.h" + +//#include "net80211/ieee80211_var.h" +extern espconn_msg *plink_active; +extern uint8 default_interface; +static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn) +{ + if (pespconn == NULL) { + return; + } + + if (pespconn->sent_callback != NULL) { + pespconn->sent_callback(pespconn); + } +} + +static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg) +{ + espconn_msg *psent = arg; + + if (psent == NULL) { + return; + } + + if (psent->pcommon.cntr == 0) { + psent->pespconn->state = ESPCONN_CONNECT; +// sys_timeout(10, espconn_data_sentcb, psent->pespconn); + espconn_data_sentcb(psent->pespconn); + } else { + espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr); + } +} + +/****************************************************************************** + * FunctionName : espconn_udp_sent + * Description : sent data for client or server + * Parameters : void *arg -- client or server 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_sent(void *arg, uint8 *psent, uint16 length) +{ + espconn_msg *pudp_sent = arg; + struct udp_pcb *upcb = pudp_sent->pcommon.pcb; + struct pbuf *p, *q ,*p_temp; + 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 (TCP_MSS < length) { + datalen = TCP_MSS; + } 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; + } + + upcb->remote_port = pudp_sent->pespconn->proto.udp->remote_port; + IP4_ADDR(&upcb->remote_ip, pudp_sent->pespconn->proto.udp->remote_ip[0], + pudp_sent->pespconn->proto.udp->remote_ip[1], + pudp_sent->pespconn->proto.udp->remote_ip[2], + pudp_sent->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_sent: copying to new pbuf failed\n")); + return ESPCONN_ARG; + } + netif_set_default(sta_netif); + err = udp_send(upcb, p_temp); + pbuf_free(p_temp); + netif_set_default(ap_netif); + } + } + err = udp_send(upcb, p); + + LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d\n", __LINE__, err)); + + if (p->ref != 0) { + LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p)); + pbuf_free(p); + pudp_sent->pcommon.ptrbuf = psent + datalen; + pudp_sent->pcommon.cntr = length - datalen; + espconn_data_sent(pudp_sent); + return err; + } else { + pbuf_free(p); + return ESPCONN_RTE; + } +} + +/****************************************************************************** + * FunctionName : espconn_udp_server_recv + * Description : This callback will be called when receiving a datagram. + * Parameters : arg -- user supplied argument + * upcb -- the udp_pcb which received data + * p -- the packet buffer that was received + * addr -- the remote IP address from which the packet was received + * port -- the remote port from which the packet was received + * Returns : none +*******************************************************************************/ +static void ICACHE_FLASH_ATTR +espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, + struct ip_addr *addr, u16_t port) +{ + espconn_msg *precv = arg; + struct pbuf *q = NULL; + u8_t *pdata = NULL; + u16_t length = 0; + struct ip_info ipconfig; + + 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_port = port; + precv->pcommon.pcb = upcb; + + if (wifi_get_opmode() != 1) { + wifi_get_ip_info(1, &ipconfig); + + if (!ip_addr_netcmp((struct ip_addr *)precv->pespconn->proto.udp->remote_ip, &ipconfig.ip, &ipconfig.netmask)) { + wifi_get_ip_info(0, &ipconfig); + } + } 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; + pbuf_free(p); + if (length != 0) { + if (precv->pespconn->recv_callback != NULL) { + precv->pespconn->recv_callback(precv->pespconn, pdata, length); + } + } + os_free(pdata); + } else { + return; + } +} + +/****************************************************************************** + * FunctionName : espconn_udp_disconnect + * Description : A new incoming connection has been disconnected. + * Parameters : espconn -- the espconn used to disconnect with host + * Returns : none +*******************************************************************************/ +void ICACHE_FLASH_ATTR espconn_udp_disconnect(espconn_msg *pdiscon) +{ + if (pdiscon == NULL) { + return; + } + + struct udp_pcb *upcb = pdiscon->pcommon.pcb; + + udp_disconnect(upcb); + + udp_remove(upcb); + + espconn_list_delete(&plink_active, pdiscon); + + os_free(pdiscon); + pdiscon = NULL; +} + +/****************************************************************************** + * FunctionName : espconn_udp_server + * Description : Initialize the server: set up a PCB and bind it to the port + * Parameters : pespconn -- the espconn used to build server + * Returns : none +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR +espconn_udp_server(struct espconn *pespconn) +{ + struct udp_pcb *upcb = NULL; + espconn_msg *pserver = NULL; + upcb = udp_new(); + + if (upcb == NULL) { + return ESPCONN_MEM; + } else { + pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); + + if (pserver == NULL) { + udp_remove(upcb); + return ESPCONN_MEM; + } + + pserver->pcommon.pcb = upcb; + pserver->pespconn = pespconn; + espconn_list_creat(&plink_active, pserver); + udp_bind(upcb, IP_ADDR_ANY, pserver->pespconn->proto.udp->local_port); + udp_recv(upcb, espconn_udp_recv, (void *)pserver); + return ESPCONN_OK; + } +} + +/****************************************************************************** + * FunctionName : espconn_igmp_leave + * Description : leave a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR +espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip) +{ + if (igmp_leavegroup(host_ip, multicast_ip) != ERR_OK) { + LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_leave_multigrup failed!\n")); + return -1; + }; + + return ESPCONN_OK; +} + +/****************************************************************************** + * FunctionName : espconn_igmp_join + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +sint8 ICACHE_FLASH_ATTR +espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip) +{ + if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) { + LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n")); + return -1; + }; + + /* join to any IP address at the port */ + return ESPCONN_OK; +} diff --git a/app/lwip/app/netio.c b/app/lwip/app/netio.c index 4124b912..3aac7c59 100644 --- a/app/lwip/app/netio.c +++ b/app/lwip/app/netio.c @@ -1,365 +1,365 @@ -/** - * @file - * MetIO Server - * - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - */ -#include "lwip/opt.h" - -#if LWIP_TCP -#include "lwip/tcp.h" - -/* - * This implements a netio server. - * The client sends a command word (4 bytes) then a data length word (4 bytes). - * If the command is "receive", the server is to consume "data length" bytes into - * a circular buffer until the first byte is non-zero, then it is to consume - * another command/data pair. - * If the command is "send", the server is to send "data length" bytes from a circular - * buffer with the first byte being zero, until "some time" (6 seconds in the - * current netio126.zip download) has passed and then send one final buffer with - * the first byte being non-zero. Then it is to consume another command/data pair. - */ - -/* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */ - -/* implementation options */ -#define NETIO_BUF_SIZE (4 * 1024) -#define NETIO_USE_STATIC_BUF 0 - -/* NetIO server state definition */ -#define NETIO_STATE_WAIT_FOR_CMD 0 -#define NETIO_STATE_RECV_DATA 1 -#define NETIO_STATE_SEND_DATA 2 -#define NETIO_STATE_SEND_DATA_LAST 3 -#define NETIO_STATE_DONE 4 - -struct netio_state { - u32_t state; - u32_t cmd; - u32_t data_len; - u32_t cntr; - u8_t * buf_ptr; - u32_t buf_pos; - u32_t first_byte; - u32_t time_stamp; -}; - -/* NetIO command protocol definition */ -#define NETIO_CMD_QUIT 0 -#define NETIO_CMD_C2S 1 -#define NETIO_CMD_S2C 2 -#define NETIO_CMD_RES 3 - -static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); - -static void ICACHE_FLASH_ATTR -netio_close(void *arg, struct tcp_pcb *pcb) -{ - err_t err; - - struct netio_state *ns = arg; - ns->state = NETIO_STATE_DONE; - tcp_recv(pcb, NULL); - err = tcp_close(pcb); - - if (err != ERR_OK) { - /* closing failed, try again later */ - tcp_recv(pcb, netio_recv); - } else { - /* closing succeeded */ -#if NETIO_USE_STATIC_BUF != 1 - if(ns->buf_ptr != NULL){ - mem_free(ns->buf_ptr); - } -#endif - tcp_arg(pcb, NULL); - tcp_poll(pcb, NULL, 0); - tcp_sent(pcb, NULL); - if (arg != NULL) { - mem_free(arg); - } - } -} - -static err_t ICACHE_FLASH_ATTR -netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct netio_state *ns = arg; - u8_t * data_ptr; - u32_t data_cntr; - struct pbuf *q = p; - u16_t len; - - if (p != NULL) { - tcp_recved(pcb, p->tot_len); - } - - if (err == ERR_OK && q != NULL) { - - while (q != NULL) { - data_cntr = q->len; - data_ptr = q->payload; - while (data_cntr--) { - if (ns->state == NETIO_STATE_DONE){ - netio_close(ns, pcb); - break; - } else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) { - if (ns->cntr < 4) { - /* build up the CMD field */ - ns->cmd <<= 8; - ns->cmd |= *data_ptr++; - ns->cntr++; - } else if (ns->cntr < 8) { - /* build up the DATA field */ - ns->data_len <<= 8; - ns->data_len |= *data_ptr++; - ns->cntr++; - - if (ns->cntr == 8) { - /* now we have full command and data words */ - ns->cntr = 0; - ns->buf_pos = 0; - ns->buf_ptr[0] = 0; - if (ns->cmd == NETIO_CMD_C2S) { - ns->state = NETIO_STATE_RECV_DATA; - } else if (ns->cmd == NETIO_CMD_S2C) { - ns->state = NETIO_STATE_SEND_DATA; - /* start timer */ - ns->time_stamp = sys_now(); - /* send first round of data */ - - len = tcp_sndbuf(pcb); - len = LWIP_MIN(len, ns->data_len - ns->cntr); - len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); - - do { - err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); - if (err == ERR_MEM) { - len /= 2; - } - } while ((err == ERR_MEM) && (len > 1)); - - ns->buf_pos += len; - ns->cntr += len; - - } else { - /* unrecognized command, punt */ - ns->cntr = 0; - ns->buf_pos = 0; - ns->buf_ptr[0] = 0; - netio_close(ns, pcb); - break; - } - } - } else { - /* in trouble... shouldn't be in this state! */ - } - - } else if (ns->state == NETIO_STATE_RECV_DATA) { - - if(ns->cntr == 0){ - /* save the first byte of this new round of data - * this will not match ns->buf_ptr[0] in the case that - * NETIO_BUF_SIZE is less than ns->data_len. - */ - ns->first_byte = *data_ptr; - } - - ns->buf_ptr[ns->buf_pos++] = *data_ptr++; - ns->cntr++; - - if (ns->buf_pos == NETIO_BUF_SIZE) { - /* circularize the buffer */ - ns->buf_pos = 0; - } - - if(ns->cntr == ns->data_len){ - ns->cntr = 0; - if (ns->first_byte != 0) { - /* if this last round did not start with 0, - * go look for another command */ - ns->state = NETIO_STATE_WAIT_FOR_CMD; - ns->data_len = 0; - ns->cmd = 0; - /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ - } else { - /* stay here and wait on more data */ - } - } - - } else if (ns->state == NETIO_STATE_SEND_DATA - || ns->state == NETIO_STATE_SEND_DATA_LAST) { - /* I don't think this should happen... */ - } else { - /* done / quit */ - netio_close(ns, pcb); - break; - } /* end of ns->state condition */ - } /* end of while data still in this pbuf */ - - q = q->next; - } - - pbuf_free(p); - - } else { - - /* error or closed by other side */ - if (p != NULL) { - pbuf_free(p); - } - - /* close the connection */ - netio_close(ns, pcb); - - } - return ERR_OK; - -} - -static err_t ICACHE_FLASH_ATTR -netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) -{ - struct netio_state *ns = arg; - err_t err = ERR_OK; - - if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) { - /* done with this round of sending */ - ns->buf_pos = 0; - ns->cntr = 0; - - /* check if timer expired */ - if (sys_now() - ns->time_stamp > 600) { - ns->buf_ptr[0] = 1; - ns->state = NETIO_STATE_SEND_DATA_LAST; - } else { - ns->buf_ptr[0] = 0; - } - } - - if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ - len = tcp_sndbuf(pcb); - len = LWIP_MIN(len, ns->data_len - ns->cntr); - len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); - - if(ns->cntr < ns->data_len){ - do { - err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); - if (err == ERR_MEM) { - len /= 2; - } - } while ((err == ERR_MEM) && (len > 1)); - - ns->buf_pos += len; - if(ns->buf_pos >= NETIO_BUF_SIZE){ - ns->buf_pos = 0; - } - - ns->cntr += len; - } - } - - if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){ - /* we have buffered up all our data to send this last round, go look for a command */ - ns->state = NETIO_STATE_WAIT_FOR_CMD; - ns->cntr = 0; - /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ - } - - return ERR_OK; -} - -static err_t ICACHE_FLASH_ATTR -netio_poll(void *arg, struct tcp_pcb *pcb) -{ - struct netio_state * ns = arg; - if(ns->state == NETIO_STATE_SEND_DATA){ - - } else if(ns->state == NETIO_STATE_DONE){ - netio_close(ns, pcb); - } - - return ERR_OK; - -} - -#if NETIO_USE_STATIC_BUF == 1 -static u8_t netio_buf[NETIO_BUF_SIZE]; -#endif - -static err_t ICACHE_FLASH_ATTR -netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) -{ - struct netio_state * ns; - - LWIP_UNUSED_ARG(err); - - ns = mem_malloc(sizeof(struct netio_state)); - - if(ns == NULL){ - return ERR_MEM; - } - - ns->state = NETIO_STATE_WAIT_FOR_CMD; - ns->data_len = 0; - ns->cmd = 0; - ns->cntr = 0; - ns->buf_pos = 0; -#if NETIO_USE_STATIC_BUF == 1 - ns->buf_ptr = netio_buf; -#else - ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE); - - if(ns->buf_ptr == NULL){ - mem_free(ns); - return ERR_MEM; - } -#endif - - ns->buf_ptr[0] = 0; - - tcp_arg(pcb, ns); - tcp_sent(pcb, netio_sent); - tcp_recv(pcb, netio_recv); - tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */ - return ERR_OK; -} - -void ICACHE_FLASH_ATTR netio_init(void) -{ - struct tcp_pcb *pcb; - - pcb = tcp_new(); - tcp_bind(pcb, IP_ADDR_ANY, 18767); - pcb = tcp_listen(pcb); - tcp_accept(pcb, netio_accept); -} - -#endif /* LWIP_TCP */ +/** + * @file + * MetIO Server + * + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + */ +#include "lwip/opt.h" + +#if LWIP_TCP +#include "lwip/tcp.h" + +/* + * This implements a netio server. + * The client sends a command word (4 bytes) then a data length word (4 bytes). + * If the command is "receive", the server is to consume "data length" bytes into + * a circular buffer until the first byte is non-zero, then it is to consume + * another command/data pair. + * If the command is "send", the server is to send "data length" bytes from a circular + * buffer with the first byte being zero, until "some time" (6 seconds in the + * current netio126.zip download) has passed and then send one final buffer with + * the first byte being non-zero. Then it is to consume another command/data pair. + */ + +/* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */ + +/* implementation options */ +#define NETIO_BUF_SIZE (4 * 1024) +#define NETIO_USE_STATIC_BUF 0 + +/* NetIO server state definition */ +#define NETIO_STATE_WAIT_FOR_CMD 0 +#define NETIO_STATE_RECV_DATA 1 +#define NETIO_STATE_SEND_DATA 2 +#define NETIO_STATE_SEND_DATA_LAST 3 +#define NETIO_STATE_DONE 4 + +struct netio_state { + u32_t state; + u32_t cmd; + u32_t data_len; + u32_t cntr; + u8_t * buf_ptr; + u32_t buf_pos; + u32_t first_byte; + u32_t time_stamp; +}; + +/* NetIO command protocol definition */ +#define NETIO_CMD_QUIT 0 +#define NETIO_CMD_C2S 1 +#define NETIO_CMD_S2C 2 +#define NETIO_CMD_RES 3 + +static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); + +static void ICACHE_FLASH_ATTR +netio_close(void *arg, struct tcp_pcb *pcb) +{ + err_t err; + + struct netio_state *ns = arg; + ns->state = NETIO_STATE_DONE; + tcp_recv(pcb, NULL); + err = tcp_close(pcb); + + if (err != ERR_OK) { + /* closing failed, try again later */ + tcp_recv(pcb, netio_recv); + } else { + /* closing succeeded */ +#if NETIO_USE_STATIC_BUF != 1 + if(ns->buf_ptr != NULL){ + mem_free(ns->buf_ptr); + } +#endif + tcp_arg(pcb, NULL); + tcp_poll(pcb, NULL, 0); + tcp_sent(pcb, NULL); + if (arg != NULL) { + mem_free(arg); + } + } +} + +static err_t ICACHE_FLASH_ATTR +netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct netio_state *ns = arg; + u8_t * data_ptr; + u32_t data_cntr; + struct pbuf *q = p; + u16_t len; + + if (p != NULL) { + tcp_recved(pcb, p->tot_len); + } + + if (err == ERR_OK && q != NULL) { + + while (q != NULL) { + data_cntr = q->len; + data_ptr = q->payload; + while (data_cntr--) { + if (ns->state == NETIO_STATE_DONE){ + netio_close(ns, pcb); + break; + } else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) { + if (ns->cntr < 4) { + /* build up the CMD field */ + ns->cmd <<= 8; + ns->cmd |= *data_ptr++; + ns->cntr++; + } else if (ns->cntr < 8) { + /* build up the DATA field */ + ns->data_len <<= 8; + ns->data_len |= *data_ptr++; + ns->cntr++; + + if (ns->cntr == 8) { + /* now we have full command and data words */ + ns->cntr = 0; + ns->buf_pos = 0; + ns->buf_ptr[0] = 0; + if (ns->cmd == NETIO_CMD_C2S) { + ns->state = NETIO_STATE_RECV_DATA; + } else if (ns->cmd == NETIO_CMD_S2C) { + ns->state = NETIO_STATE_SEND_DATA; + /* start timer */ + ns->time_stamp = sys_now(); + /* send first round of data */ + + len = tcp_sndbuf(pcb); + len = LWIP_MIN(len, ns->data_len - ns->cntr); + len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); + + do { + err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + len /= 2; + } + } while ((err == ERR_MEM) && (len > 1)); + + ns->buf_pos += len; + ns->cntr += len; + + } else { + /* unrecognized command, punt */ + ns->cntr = 0; + ns->buf_pos = 0; + ns->buf_ptr[0] = 0; + netio_close(ns, pcb); + break; + } + } + } else { + /* in trouble... shouldn't be in this state! */ + } + + } else if (ns->state == NETIO_STATE_RECV_DATA) { + + if(ns->cntr == 0){ + /* save the first byte of this new round of data + * this will not match ns->buf_ptr[0] in the case that + * NETIO_BUF_SIZE is less than ns->data_len. + */ + ns->first_byte = *data_ptr; + } + + ns->buf_ptr[ns->buf_pos++] = *data_ptr++; + ns->cntr++; + + if (ns->buf_pos == NETIO_BUF_SIZE) { + /* circularize the buffer */ + ns->buf_pos = 0; + } + + if(ns->cntr == ns->data_len){ + ns->cntr = 0; + if (ns->first_byte != 0) { + /* if this last round did not start with 0, + * go look for another command */ + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->data_len = 0; + ns->cmd = 0; + /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ + } else { + /* stay here and wait on more data */ + } + } + + } else if (ns->state == NETIO_STATE_SEND_DATA + || ns->state == NETIO_STATE_SEND_DATA_LAST) { + /* I don't think this should happen... */ + } else { + /* done / quit */ + netio_close(ns, pcb); + break; + } /* end of ns->state condition */ + } /* end of while data still in this pbuf */ + + q = q->next; + } + + pbuf_free(p); + + } else { + + /* error or closed by other side */ + if (p != NULL) { + pbuf_free(p); + } + + /* close the connection */ + netio_close(ns, pcb); + + } + return ERR_OK; + +} + +static err_t ICACHE_FLASH_ATTR +netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct netio_state *ns = arg; + err_t err = ERR_OK; + + if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) { + /* done with this round of sending */ + ns->buf_pos = 0; + ns->cntr = 0; + + /* check if timer expired */ + if (sys_now() - ns->time_stamp > 600) { + ns->buf_ptr[0] = 1; + ns->state = NETIO_STATE_SEND_DATA_LAST; + } else { + ns->buf_ptr[0] = 0; + } + } + + if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ + len = tcp_sndbuf(pcb); + len = LWIP_MIN(len, ns->data_len - ns->cntr); + len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); + + if(ns->cntr < ns->data_len){ + do { + err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + len /= 2; + } + } while ((err == ERR_MEM) && (len > 1)); + + ns->buf_pos += len; + if(ns->buf_pos >= NETIO_BUF_SIZE){ + ns->buf_pos = 0; + } + + ns->cntr += len; + } + } + + if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){ + /* we have buffered up all our data to send this last round, go look for a command */ + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->cntr = 0; + /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ + } + + return ERR_OK; +} + +static err_t ICACHE_FLASH_ATTR +netio_poll(void *arg, struct tcp_pcb *pcb) +{ + struct netio_state * ns = arg; + if(ns->state == NETIO_STATE_SEND_DATA){ + + } else if(ns->state == NETIO_STATE_DONE){ + netio_close(ns, pcb); + } + + return ERR_OK; + +} + +#if NETIO_USE_STATIC_BUF == 1 +static u8_t netio_buf[NETIO_BUF_SIZE]; +#endif + +static err_t ICACHE_FLASH_ATTR +netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct netio_state * ns; + + LWIP_UNUSED_ARG(err); + + ns = mem_malloc(sizeof(struct netio_state)); + + if(ns == NULL){ + return ERR_MEM; + } + + ns->state = NETIO_STATE_WAIT_FOR_CMD; + ns->data_len = 0; + ns->cmd = 0; + ns->cntr = 0; + ns->buf_pos = 0; +#if NETIO_USE_STATIC_BUF == 1 + ns->buf_ptr = netio_buf; +#else + ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE); + + if(ns->buf_ptr == NULL){ + mem_free(ns); + return ERR_MEM; + } +#endif + + ns->buf_ptr[0] = 0; + + tcp_arg(pcb, ns); + tcp_sent(pcb, netio_sent); + tcp_recv(pcb, netio_recv); + tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */ + return ERR_OK; +} + +void ICACHE_FLASH_ATTR netio_init(void) +{ + struct tcp_pcb *pcb; + + pcb = tcp_new(); + tcp_bind(pcb, IP_ADDR_ANY, 18767); + pcb = tcp_listen(pcb); + tcp_accept(pcb, netio_accept); +} + +#endif /* LWIP_TCP */ diff --git a/app/lwip/app/ping.c b/app/lwip/app/ping.c index d353fa27..38a85fa4 100644 --- a/app/lwip/app/ping.c +++ b/app/lwip/app/ping.c @@ -93,6 +93,9 @@ ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) iecho->chksum = 0; iecho->id = PING_ID; ++ ping_seq_num; + if (ping_seq_num == 0x7fff) + ping_seq_num = 0; + iecho->seqno = htons(ping_seq_num); /* fill the additional data buffer with some data */ @@ -233,7 +236,7 @@ ping_coarse_tmr(void *arg) } else { uint32 delay = system_relative_time(pingmsg->ping_start); delay /= PING_COARSE; - ping_seq_num = 0; +// ping_seq_num = 0; if (ping_opt->sent_function == NULL){ os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n", pingmsg->max_count, pingmsg->timeout_count, PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count),delay); diff --git a/app/lwip/core/Makefile b/app/lwip/core/Makefile index 7cbb57b6..99159101 100644 --- a/app/lwip/core/Makefile +++ b/app/lwip/core/Makefile @@ -1,46 +1,46 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipcore.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR + +GEN_LIBS = liblwipcore.a + +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/lwip/core/dhcp.c b/app/lwip/core/dhcp.c index 3b189f28..73457eb2 100644 --- a/app/lwip/core/dhcp.c +++ b/app/lwip/core/dhcp.c @@ -129,7 +129,7 @@ u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; #define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) #define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) #define dhcp_clear_option(dhcp, idx) (dhcp_rx_options_given[idx] = 0) -#define dhcp_clear_all_options(dhcp) (memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) +#define dhcp_clear_all_options(dhcp) (os_memset(dhcp_rx_options_given, 0, sizeof(dhcp_rx_options_given))) #define dhcp_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx]) #define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) @@ -288,16 +288,24 @@ dhcp_select(struct netif *netif) dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr))); - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 12/*num options*/); dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + dhcp_option_byte(dhcp, DHCP_OPTION_DOMAIN_NAME); + dhcp_option_byte(dhcp, DHCP_OPTION_NB_TINS); + dhcp_option_byte(dhcp, DHCP_OPTION_NB_TINT); + dhcp_option_byte(dhcp, DHCP_OPTION_NB_TIS); + dhcp_option_byte(dhcp, DHCP_OPTION_PRD); + dhcp_option_byte(dhcp, DHCP_OPTION_STATIC_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_CLASSLESS_STATIC_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_VSN); #if LWIP_NETIF_HOSTNAME if (netif->hostname != NULL) { const char *p = (const char*)netif->hostname; - u8_t namelen = (u8_t)strlen(p); + u8_t namelen = (u8_t)os_strlen(p); if (namelen > 0) { LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); @@ -587,7 +595,7 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); + os_memset(dhcp, 0, sizeof(struct dhcp)); /* dhcp_set_state(&dhcp, DHCP_OFF); */ netif->dhcp = dhcp; } @@ -626,7 +634,6 @@ dhcp_start(struct netif *netif) { struct dhcp *dhcp; err_t result = ERR_OK; - LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); dhcp = netif->dhcp; LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("dhcp_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num)); @@ -668,7 +675,7 @@ dhcp_start(struct netif *netif) } /* clear data structure */ - memset(dhcp, 0, sizeof(struct dhcp)); + os_memset(dhcp, 0, sizeof(struct dhcp)); /* dhcp_set_state(&dhcp, DHCP_OFF); */ /* allocate UDP PCB */ dhcp->pcb = udp_new(); @@ -713,7 +720,7 @@ dhcp_inform(struct netif *netif) LWIP_ERROR("netif != NULL", (netif != NULL), return;); - memset(&dhcp, 0, sizeof(struct dhcp)); + os_memset(&dhcp, 0, sizeof(struct dhcp)); dhcp_set_state(&dhcp, DHCP_INFORM); if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) { @@ -881,11 +888,32 @@ dhcp_discover(struct netif *netif) dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option_short(dhcp, DHCP_MAX_MSG_LEN(netif)); - dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 4/*num options*/); +#if LWIP_NETIF_HOSTNAME + if (netif->hostname != NULL) { + const char *p = (const char*)netif->hostname; + u8_t namelen = (u8_t)os_strlen(p); + if (namelen > 0) { + LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); + dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); + while (*p) { + dhcp_option_byte(dhcp, *p++); + } + } + } +#endif /* LWIP_NETIF_HOSTNAME */ + dhcp_option(dhcp, DHCP_OPTION_PARAMETER_REQUEST_LIST, 12/*num options*/); dhcp_option_byte(dhcp, DHCP_OPTION_SUBNET_MASK); dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); + dhcp_option_byte(dhcp, DHCP_OPTION_DOMAIN_NAME); + dhcp_option_byte(dhcp, DHCP_OPTION_NB_TINS); + dhcp_option_byte(dhcp, DHCP_OPTION_NB_TINT); + dhcp_option_byte(dhcp, DHCP_OPTION_NB_TIS); + dhcp_option_byte(dhcp, DHCP_OPTION_PRD); + dhcp_option_byte(dhcp, DHCP_OPTION_STATIC_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_CLASSLESS_STATIC_ROUTER); + dhcp_option_byte(dhcp, DHCP_OPTION_VSN); dhcp_option_trailer(dhcp); @@ -994,6 +1022,12 @@ dhcp_bind(struct netif *netif) } #endif /* LWIP_DHCP_AUTOIP_COOP */ + // wjg:back up old ip/netmask/gw + ip_addr_t ip, mask, gw; + ip = netif->ip_addr; + mask = netif->netmask; + gw = netif->gw; + LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n", ip4_addr_get_u32(&dhcp->offered_ip_addr))); netif_set_ipaddr(netif, &dhcp->offered_ip_addr); @@ -1002,12 +1036,14 @@ dhcp_bind(struct netif *netif) netif_set_netmask(netif, &sn_mask); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", ip4_addr_get_u32(&gw_addr))); - - system_station_got_ip_set(&dhcp->offered_ip_addr, &sn_mask, &gw_addr); - netif_set_gw(netif, &gw_addr); + /* bring the interface up */ netif_set_up(netif); + + // wjg: use old ip/mask/gw to check whether ip/mask/gw changed + system_station_got_ip_set(&ip, &mask, &gw); + /* netif is now bound to DHCP leased address */ dhcp_set_state(dhcp, DHCP_BOUND); } @@ -1035,7 +1071,7 @@ dhcp_renew(struct netif *netif) #if LWIP_NETIF_HOSTNAME if (netif->hostname != NULL) { const char *p = (const char*)netif->hostname; - u8_t namelen = (u8_t)strlen(p); + u8_t namelen = (u8_t)os_strlen(p); if (namelen > 0) { LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); @@ -1098,7 +1134,7 @@ dhcp_rebind(struct netif *netif) #if LWIP_NETIF_HOSTNAME if (netif->hostname != NULL) { const char *p = (const char*)netif->hostname; - u8_t namelen = (u8_t)strlen(p); + u8_t namelen = (u8_t)os_strlen(p); if (namelen > 0) { LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); @@ -1245,7 +1281,6 @@ dhcp_stop(struct netif *netif) dhcp = netif->dhcp; /* Remove the flag that says this netif is handled by DHCP. */ netif->flags &= ~NETIF_FLAG_DHCP; - LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); /* netif is DHCP configured? */ if (dhcp != NULL) { diff --git a/app/lwip/core/dns.c b/app/lwip/core/dns.c index 1fe7aaa4..e471646b 100644 --- a/app/lwip/core/dns.c +++ b/app/lwip/core/dns.c @@ -85,7 +85,7 @@ /** DNS server IP address */ #ifndef DNS_SERVER_ADDRESS -#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */ +#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, 0xDEDE43D0)) /* resolver1.opendns.com(208.67.222.222) */ #endif /** DNS server port address */ @@ -173,7 +173,7 @@ struct dns_table_entry { u8_t seqno; u8_t err; u32_t ttl; - char *name; + char name[DNS_MAX_NAME_LENGTH]; ip_addr_t ipaddr; /* pointer to callback on DNS query done */ dns_found_callback found; @@ -221,9 +221,9 @@ static u8_t dns_seqno; static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; static ip_addr_t dns_servers[DNS_MAX_SERVERS]; /** Contiguous buffer for processing responses */ -static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)]; +//static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)]; static u8_t* dns_payload; - +static u8_t dns_random; /** * Initialize the resolver: set up the UDP pcb and configure the default server * (DNS_SERVER_ADDRESS). @@ -233,7 +233,7 @@ dns_init() { ip_addr_t dnsserver; - dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer); +// dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer); /* initialize default DNS server address */ DNS_SERVER_ADDRESS(&dnsserver); @@ -299,7 +299,7 @@ dns_getserver(u8_t numdns) * The DNS resolver client timer - handle retries and timeouts and should * be called every DNS_TMR_INTERVAL milliseconds (every second by default). */ -void +void ICACHE_FLASH_ATTR dns_tmr(void) { if (dns_pcb != NULL) { @@ -321,7 +321,7 @@ dns_init_local() for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); - namelen = strlen(init_entry->name); + namelen = os_strlen(init_entry->name); LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); @@ -416,7 +416,7 @@ dns_local_addhost(const char *hostname, const ip_addr_t *addr) struct local_hostlist_entry *entry; size_t namelen; LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); - namelen = strlen(hostname); + namelen = os_strlen(hostname); LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN); entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); if (entry == NULL) { @@ -566,7 +566,7 @@ dns_send(u8_t numdns, const char* name, u8_t id) char *query, *nptr; const char *pHostname; u8_t n; - + dns_random = os_random()%250; LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", (u16_t)(numdns), name)); LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS); @@ -579,8 +579,8 @@ dns_send(u8_t numdns, const char* name, u8_t id) LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); /* fill dns header */ hdr = (struct dns_hdr*)p->payload; - memset(hdr, 0, SIZEOF_DNS_HDR); - hdr->id = htons(id); + os_memset(hdr, 0, SIZEOF_DNS_HDR); + hdr->id = htons(id + dns_random); hdr->flags1 = DNS_FLAG1_RD; hdr->numquestions = PP_HTONS(1); query = (char*)hdr + SIZEOF_DNS_HDR; @@ -673,8 +673,6 @@ dns_check_entry(u8_t i) if (pEntry->found) (*pEntry->found)(pEntry->name, NULL, pEntry->arg); /* flush this entry */ - mem_free (pEntry->name); - pEntry->name = NULL; pEntry->state = DNS_STATE_UNUSED; pEntry->found = NULL; break; @@ -699,8 +697,6 @@ dns_check_entry(u8_t i) if (--pEntry->ttl == 0) { LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name)); /* flush this entry */ - mem_free (pEntry->name); - pEntry->name = NULL; pEntry->state = DNS_STATE_UNUSED; pEntry->found = NULL; } @@ -743,6 +739,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t struct dns_table_entry *pEntry; u16_t nquestions, nanswers; + u8_t* dns_payload_buffer = (u8_t* )os_zalloc(LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)); + dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer); + LWIP_UNUSED_ARG(arg); LWIP_UNUSED_ARG(pcb); LWIP_UNUSED_ARG(addr); @@ -767,6 +766,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t /* The ID in the DNS header should be our entry into the name table. */ hdr = (struct dns_hdr*)dns_payload; i = htons(hdr->id); + i = i - dns_random; if (i < DNS_TABLE_SIZE) { pEntry = &dns_table[i]; if(pEntry->state == DNS_STATE_ASKING) { @@ -843,14 +843,13 @@ responseerr: (*pEntry->found)(pEntry->name, NULL, pEntry->arg); } /* flush this entry */ - mem_free (pEntry->name); - pEntry->name = NULL; pEntry->state = DNS_STATE_UNUSED; pEntry->found = NULL; memerr: /* free pbuf */ pbuf_free(p); + os_free(dns_payload_buffer); return; } @@ -904,16 +903,11 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); /* fill the entry */ - namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1); - char *namebuf = (char *)mem_zalloc (namelen); - if (!namebuf) - return ERR_MEM; pEntry->state = DNS_STATE_NEW; pEntry->seqno = dns_seqno++; pEntry->found = found; pEntry->arg = callback_arg; - mem_free (pEntry->name); - pEntry->name = namebuf; + namelen = LWIP_MIN(os_strlen(name), DNS_MAX_NAME_LENGTH-1); MEMCPY(pEntry->name, name, namelen); pEntry->name[namelen] = 0; @@ -952,7 +946,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun * or invalid hostname or invalid hostname length */ if ((dns_pcb == NULL) || (addr == NULL) || (!hostname) || (!hostname[0]) || - (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { + (os_strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { return ERR_ARG; } diff --git a/app/lwip/core/init.c b/app/lwip/core/init.c index 3bd91755..a0361b17 100644 --- a/app/lwip/core/init.c +++ b/app/lwip/core/init.c @@ -99,18 +99,18 @@ //#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) // #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h" //#endif -#if (LWIP_TCP && (TCP_WND > 0xffff)) - #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" -#endif +//#if (LWIP_TCP && (TCP_WND > 0xffff)) +// #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h" +//#endif #if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" #endif #if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" #endif -#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) - #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" -#endif +//#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) +// #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" +//#endif #if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t" #endif @@ -259,6 +259,11 @@ lwip_sanity_check(void) void lwip_init(void) { + MEMP_NUM_TCP_PCB = 5; + TCP_WND = (4 * TCP_MSS); + TCP_MAXRTX = 3; + TCP_SYNMAXRTX = 6; + /* Sanity check user-configurable values */ lwip_sanity_check(); @@ -294,7 +299,6 @@ lwip_init(void) #endif /* LWIP_UDP */ #if LWIP_TCP - MEMP_NUM_TCP_PCB = 5; tcp_init(); #endif /* LWIP_TCP */ diff --git a/app/lwip/core/ipv4/Makefile b/app/lwip/core/ipv4/Makefile index 660968be..2d818fe8 100644 --- a/app/lwip/core/ipv4/Makefile +++ b/app/lwip/core/ipv4/Makefile @@ -1,46 +1,46 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipipv4.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR + +GEN_LIBS = liblwipipv4.a + +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/lwip/core/ipv4/autoip.c b/app/lwip/core/ipv4/autoip.c index 92bb4591..cdba69d6 100644 --- a/app/lwip/core/ipv4/autoip.c +++ b/app/lwip/core/ipv4/autoip.c @@ -145,7 +145,7 @@ autoip_set_struct(struct netif *netif, struct autoip *autoip) LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL); /* clear data structure */ - memset(autoip, 0, sizeof(struct autoip)); + os_memset(autoip, 0, sizeof(struct autoip)); /* autoip->state = AUTOIP_STATE_OFF; */ netif->autoip = autoip; } @@ -319,7 +319,7 @@ autoip_start(struct netif *netif) ("autoip_start(): could not allocate autoip\n")); return ERR_MEM; } - memset(autoip, 0, sizeof(struct autoip)); + os_memset(autoip, 0, sizeof(struct autoip)); /* store this AutoIP client in the netif */ netif->autoip = autoip; LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); diff --git a/app/lwip/core/ipv4/ip.c b/app/lwip/core/ipv4/ip.c index 6046e342..89d3f11c 100644 --- a/app/lwip/core/ipv4/ip.c +++ b/app/lwip/core/ipv4/ip.c @@ -133,7 +133,13 @@ ip_route(ip_addr_t *dest) /* return netif on which to forward IP packet */ return netif; } - if (!ip_addr_isbroadcast(dest, netif) && netif != netif_default) { + } + } + /* iterate through netifs */ + for(netif = netif_list; netif != NULL; netif = netif->next) { + /* network mask matches? */ + if (netif_is_up(netif)) { + if (!ip_addr_isbroadcast(dest, netif) && netif == (struct netif *)eagle_lwip_getif(0)) { return netif; } } @@ -669,7 +675,7 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, MEMCPY(p->payload, ip_options, optlen); if (optlen < optlen_aligned) { /* zero the remaining bytes */ - memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); + os_memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); } #if CHECKSUM_GEN_IP_INLINE for (i = 0; i < optlen_aligned/2; i++) { diff --git a/app/lwip/core/ipv4/ip_addr.c b/app/lwip/core/ipv4/ip_addr.c index b39ed7c8..e2df58d3 100644 --- a/app/lwip/core/ipv4/ip_addr.c +++ b/app/lwip/core/ipv4/ip_addr.c @@ -41,8 +41,8 @@ #include "lwip/netif.h" /* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ -const ip_addr_t ip_addr_any = { IPADDR_ANY }; -const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; +const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR = { IPADDR_ANY }; +const ip_addr_t ip_addr_broadcast ICACHE_RODATA_ATTR = { IPADDR_BROADCAST }; /** * Determine if an address is a broadcast address on a network interface @@ -154,6 +154,9 @@ ipaddr_aton(const char *cp, ip_addr_t *addr) u32_t val; u8_t base; char c; + char ch; + unsigned long cutoff; + int cutlim; u32_t parts[4]; u32_t *pp = parts; @@ -176,12 +179,26 @@ ipaddr_aton(const char *cp, ip_addr_t *addr) } else base = 8; } + + cutoff =(unsigned long)0xffffffff / (unsigned long)base; + cutlim =(unsigned long)0xffffffff % (unsigned long)base; + for (;;) { if (isdigit(c)) { + ch = (int)(c - '0'); + + if (val > cutoff || (val == cutoff && ch > cutlim)) + return (0); + val = (val * base) + (int)(c - '0'); c = *++cp; } else if (base == 16 && isxdigit(c)) { - val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + ch = (int)(c + 10 - (islower(c) ? 'a' : 'A')); + + if (val > cutoff || (val == cutoff && ch > cutlim)) + return (0); + + val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); c = *++cp; } else break; @@ -220,21 +237,21 @@ ipaddr_aton(const char *cp, ip_addr_t *addr) break; case 2: /* a.b -- 8.24 bits */ - if (val > 0xffffffUL) { + if ((val > 0xffffffUL) || (parts[0] > 0xff)) { return (0); } val |= parts[0] << 24; break; case 3: /* a.b.c -- 8.8.16 bits */ - if (val > 0xffff) { + if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) { return (0); } val |= (parts[0] << 24) | (parts[1] << 16); break; case 4: /* a.b.c.d -- 8.8.8.8 bits */ - if (val > 0xff) { + if ((val > 0xff) || (parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff)) { return (0); } val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); diff --git a/app/lwip/core/ipv4/ip_frag.c b/app/lwip/core/ipv4/ip_frag.c index 5eff96f2..b89eeb58 100644 --- a/app/lwip/core/ipv4/ip_frag.c +++ b/app/lwip/core/ipv4/ip_frag.c @@ -284,7 +284,7 @@ ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) return NULL; } } - memset(ipr, 0, sizeof(struct ip_reassdata)); + os_memset(ipr, 0, sizeof(struct ip_reassdata)); ipr->timer = IP_REASS_MAXAGE; /* enqueue the new structure to the front of the list */ diff --git a/app/lwip/core/mdns.c b/app/lwip/core/mdns.c new file mode 100644 index 00000000..108a0885 --- /dev/null +++ b/app/lwip/core/mdns.c @@ -0,0 +1,1068 @@ +/** + * lwip MDNS resolver file. + * + * Created on: Jul 29, 2010 + * Author: Daniel Toma + * + + * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + + * This file implements a MDNS host name and PUCK service registration. + + *----------------------------------------------------------------------------- + * Includes + *----------------------------------------------------------------------------*/ +#include "lwip/opt.h" +#if LWIP_MDNS /* don't build if not configured for use in lwipopts.h */ +#include "lwip/mdns.h" +#include "lwip/puck_def.h" +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/igmp.h" +#include "osapi.h" +#include "os_type.h" +#include "user_interface.h" +/** DNS server IP address */ +#ifndef DNS_MULTICAST_ADDRESS +#define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */ +#endif + +/** DNS server IP address */ +#ifndef MDNS_LOCAL +#define MDNS_LOCAL "local" /* resolver1.opendns.com */ +#endif + +/** DNS server port address */ +#ifndef DNS_MDNS_PORT +#define DNS_MDNS_PORT 5353 +#endif + +/** DNS maximum number of retries when asking for a name, before "timeout". */ +#ifndef DNS_MAX_RETRIES +#define DNS_MAX_RETRIES 4 +#endif + +/** DNS resource record max. TTL (one week as default) */ +#ifndef DNS_MAX_TTL +#define DNS_MAX_TTL 604800 +#endif + +/* DNS protocol flags */ +#define DNS_FLAG1_RESPONSE 0x84 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + +/* DNS protocol states */ +#define DNS_STATE_UNUSED 0 +#define DNS_STATE_NEW 1 +#define DNS_STATE_ASKING 2 +#define DNS_STATE_DONE 3 + +/* MDNS registration type */ +#define MDNS_HOSTNAME_REG 0 +#define MDNS_SERVICE_REG 1 + +/* MDNS registration type */ +#define MDNS_REG_ANSWER 1 +#define MDNS_SD_ANSWER 2 +#define MDNS_SERVICE_REG_ANSWER 3 + +/* MDNS registration time */ +#define MDNS_HOST_TIME 120 +#define MDNS_SERVICE_TIME 3600 + +/** MDNS name length with "." at the beginning and end of name*/ +#ifndef MDNS_LENGTH_ADD +#define MDNS_LENGTH_ADD 2 +#endif + +#ifdef MDNS_MAX_NAME_LENGTH +#undef MDNS_MAX_NAME_LENGTH +#endif +#define MDNS_MAX_NAME_LENGTH (256) + +PACK_STRUCT_BEGIN +/** DNS message header */ +struct mdns_hdr { + PACK_STRUCT_FIELD(u16_t id); + PACK_STRUCT_FIELD(u8_t flags1); + PACK_STRUCT_FIELD(u8_t flags2); + PACK_STRUCT_FIELD(u16_t numquestions); + PACK_STRUCT_FIELD(u16_t numanswers); + PACK_STRUCT_FIELD(u16_t numauthrr); + PACK_STRUCT_FIELD(u16_t numextrarr); +}PACK_STRUCT_STRUCT; +PACK_STRUCT_END + +#define SIZEOF_DNS_HDR 12 + +PACK_STRUCT_BEGIN +/** MDNS query message structure */ +struct mdns_query { + /* MDNS query record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type); + PACK_STRUCT_FIELD(u16_t class); +}PACK_STRUCT_STRUCT; +PACK_STRUCT_END + +#define SIZEOF_DNS_QUERY 4 + +PACK_STRUCT_BEGIN +/** MDNS answer message structure */ +struct mdns_answer { + /* MDNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type); + PACK_STRUCT_FIELD(u16_t class); + PACK_STRUCT_FIELD(u32_t ttl); + PACK_STRUCT_FIELD(u16_t len); +}PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#define SIZEOF_DNS_ANSWER 10 + +PACK_STRUCT_BEGIN +/** MDNS answer message structure */ +struct mdns_auth { + PACK_STRUCT_FIELD(u32_t src); +}PACK_STRUCT_STRUCT; +PACK_STRUCT_END + +#define SIZEOF_MDNS_AUTH 4 +PACK_STRUCT_BEGIN +/** MDNS service registration message structure */ +struct mdns_service { + PACK_STRUCT_FIELD(u16_t prior); + PACK_STRUCT_FIELD(u16_t weight); + PACK_STRUCT_FIELD(u16_t port); +}PACK_STRUCT_STRUCT; +PACK_STRUCT_END + +#define SIZEOF_MDNS_SERVICE 6 + +uint16 PUCK_PORT ; +os_timer_t mdns_timer; +/* forward declarations */ +static void mdns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, + struct ip_addr *addr, u16_t port); + +/*----------------------------------------------------------------------------- + * Globales + *----------------------------------------------------------------------------*/ + +/* MDNS variables */ +static char host_name[MDNS_NAME_LENGTH]; +static char service_name[MDNS_NAME_LENGTH]; +static char server_name[MDNS_NAME_LENGTH]; +//static char puck_datasheet[PUCK_DATASHEET_SIZE]; +static struct udp_pcb *mdns_pcb; + +static struct ip_addr multicast_addr; +static struct ip_addr host_addr; +static uint8 register_flag = 0; +static uint8 mdns_flag = 0; +//#if (DNS_USES_STATIC_BUF == 1) +static u8_t mdns_payload[DNS_MSG_SIZE]; +//#endif /* (MDNS_USES_STATIC_BUF == 1) */ +/* + * Function to set the UDP pcb used to send the mDNS packages + */ +void ICACHE_FLASH_ATTR +getPcb(struct udp_pcb *pcb) { + mdns_pcb = pcb; +} + +#if DNS_DOES_NAME_CHECK +/** + * Compare the "dotted" name "query" with the encoded name "response" + * to make sure an answer from the DNS server matches the current mdns_table + * entry (otherwise, answers might arrive late for hostname not on the list + * any more). + * + * @param query hostname (not encoded) from the mdns_table + * @param response encoded hostname in the DNS response + * @return 0: names equal; 1: names differ + */ +static u8_t ICACHE_FLASH_ATTR +mdns_compare_name(unsigned char *query, unsigned char *response) { + unsigned char n; + + do { + n = *response++; + /** @see RFC 1035 - 4.1.4. Message compression */ + if ((n & 0xc0) == 0xc0) { + /* Compressed name */ + break; + } else { + /* Not compressed name */ + while (n > 0) { + if ((*query) != (*response)) { + return 1; + } + ++response; + ++query; + --n; + }; + ++query; + } + } while (*response != 0); + + return 0; +} +#endif /* DNS_DOES_NAME_CHECK */ +/** + * Send a mDNS answer packet. + * + * @param type of answer hostname and service registration or service + * @param name to query + * @param id transaction ID in the DNS query packet + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t ICACHE_FLASH_ATTR +mdns_answer(u16_t type, const char* name, u8_t id) { + err_t err; + struct mdns_hdr *hdr; + struct mdns_answer ans; + struct mdns_auth auth; + struct mdns_service serv; + struct pbuf *p ,*p_sta; + char *query, *nptr; + const char *pHostname; + struct netif * sta_netif = NULL; + struct netif * ap_netif = NULL; + static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH]; + u8_t n; + u16_t length = 0; + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, + SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); + /* fill dns header */ + hdr = (struct mdns_hdr*) p->payload; + os_memset(hdr, 0, SIZEOF_DNS_HDR); + hdr->id = htons(id); + hdr->flags1 = DNS_FLAG1_RESPONSE; + + if (type == MDNS_SD_ANSWER) { + pHostname = DNS_SD_SERVICE; + hdr->numanswers = htons(1); + } else if (type == MDNS_SERVICE_REG_ANSWER) { + pHostname = PUCK_SERVICE; + hdr->numanswers = htons(type); + } else { + pHostname = name; + hdr->numanswers = htons(type); + } + query = (char*) hdr + SIZEOF_DNS_HDR; + --pHostname; + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + /* fill dns query */ + + if (type == MDNS_REG_ANSWER) { + + ans.type = htons(DNS_RRTYPE_A); + ans.class = htons(DNS_RRCLASS_IN); + ans.ttl = htonl(MDNS_SERVICE_TIME); + ans.len = htons(DNS_IP_ADDR_LEN); + length = DNS_IP_ADDR_LEN; + + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + + /* set the local IP address */ + auth.src = host_addr.addr; + MEMCPY( query, &auth, SIZEOF_MDNS_AUTH); + } + if (type == MDNS_SD_ANSWER) { + + ans.type = htons(DNS_RRTYPE_PTR); + ans.class = htons(DNS_RRCLASS_IN); + ans.ttl = htonl(300); + ans.len = htons(os_strlen(PUCK_SERVICE) + 1 +1 ); + length = 0; + + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + pHostname = PUCK_SERVICE; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + } + + if (type == MDNS_SERVICE_REG_ANSWER) { + + ans.type = htons(DNS_RRTYPE_PTR); + ans.class = htons(DNS_RRCLASS_IN); + ans.ttl = htonl(MDNS_SERVICE_TIME); + os_strcpy(tmpBuf, name); + os_strcat(tmpBuf, "."); + os_strcat(tmpBuf, PUCK_SERVICE); + + length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD; + ans.len = htons(length); + length = 0; + + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + + pHostname = tmpBuf; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + + /* Service query*/ + pHostname = name; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + + /* Add to the service name the service local + * pointing to the beginning of the mDNS message*/ + *query++ = DNS_OFFSET_FLAG; + *query++ = DNS_DEFAULT_OFFSET; + + /* fill the query */ + + ans.type = htons(DNS_RRTYPE_SRV); + ans.class = htons(DNS_RRCLASS_FLUSH_IN); + ans.ttl = htonl(MDNS_SERVICE_TIME); + os_strcpy(tmpBuf, host_name); + os_strcat(tmpBuf, "."); + os_strcat(tmpBuf, MDNS_LOCAL); + length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD; + ans.len = htons(SIZEOF_MDNS_SERVICE + length); + length = 0; + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + /* fill the service properties */ + + serv.prior = htons(0); + serv.weight = htons(0); + serv.port = htons(PUCK_PORT); + MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE); + /* resize the query */ + query = query + SIZEOF_MDNS_SERVICE; + + pHostname = tmpBuf; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + + /* TXT answer */ + pHostname = name; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + + /* Add to the service name the service local + * pointing to the beginning of the mDNS message*/ + *query++ = DNS_OFFSET_FLAG; + *query++ = DNS_DEFAULT_OFFSET; + + /* fill the answer */ + ans.type = htons(DNS_RRTYPE_TXT); + ans.class = htons(DNS_RRCLASS_IN); + ans.ttl = htonl(MDNS_SERVICE_TIME); + length = sizeof(SERVICE_DESCRIPTION); + ans.len = htons(length); + length = 0; + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + + pHostname = SERVICE_DESCRIPTION; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + } + /* resize pbuf to the exact dns query */ + pbuf_realloc(p, (query + length) - ((char*) (p->payload))); + + /* send dns packet */ + /*add by tzx for AP + STA MDNS begin------*/ + sta_netif = (struct netif *)eagle_lwip_getif(0x00); + ap_netif = (struct netif *)eagle_lwip_getif(0x01); + if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\ + sta_netif != NULL && ap_netif != NULL) { + if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) { + + p_sta = pbuf_alloc(PBUF_TRANSPORT, + SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM); + if (pbuf_copy (p_sta,p) != ERR_OK) { + os_printf("mdns_answer copying to new pbuf failed\n"); + return -1; + } + netif_set_default(sta_netif); + err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT); + pbuf_free(p_sta); + netif_set_default(ap_netif); + } + } + /*add by tzx for AP + STA MDNS end------*/ + err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT); + /* free pbuf */ + pbuf_free(p); + } else { + err = ERR_MEM; + } + + return err; +} + +/** + * Send a mDNS service answer packet. + * + * @param name service name to query + * @param id transaction ID in the DNS query packet + * @return ERR_OK if packet is sent; an err_t indicating the problem otherwise + */ +static err_t ICACHE_FLASH_ATTR +mdns_send_service(struct mdns_info *info, u8_t id) { + err_t err; + struct mdns_hdr *hdr; + struct mdns_answer ans; + struct mdns_service serv; + struct mdns_auth auth; + struct pbuf *p ,*p_sta; + char *query, *nptr; + const char *pHostname; + char *device_info; + const char *name = info->host_name; + u8_t n; + u8_t i = 0; + u16_t length = 0; + u8_t addr1 = 12, addr2 = 12; + struct netif * sta_netif = NULL; + struct netif * ap_netif = NULL; + static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH]; + /* if here, we have either a new query or a retry on a previous query to process */ + p = pbuf_alloc(PBUF_TRANSPORT, + SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM); + if (p != NULL) { + LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); + /* fill dns header */ + hdr = (struct mdns_hdr*) p->payload; + os_memset(hdr, 0, SIZEOF_DNS_HDR); + hdr->id = htons(id); + hdr->flags1 = DNS_FLAG1_RESPONSE; + hdr->numanswers = htons(4); + query = (char*) hdr + SIZEOF_DNS_HDR; + os_strcpy(tmpBuf, PUCK_SERVICE); + + pHostname = tmpBuf; + --pHostname; + + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + ++addr1; + ++addr2; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++addr1; + ++addr2; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + length = sizeof(MDNS_LOCAL); + addr1 -= length; + length = os_strlen(PUCK_SERVICE) + 1; + addr2 -= length; + + ans.type = htons(DNS_RRTYPE_PTR); + ans.class = htons(DNS_RRCLASS_IN); + ans.ttl = htonl(300); + os_strcpy(tmpBuf, name); + length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD + 1; + ans.len = htons(length); + length = 0; + + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + + pHostname = tmpBuf; + --pHostname; + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = DNS_OFFSET_FLAG; + *query++ = DNS_DEFAULT_OFFSET; + pHostname = name; + --pHostname; + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + //*query++ = '\0'; + *query++ = DNS_OFFSET_FLAG; + *query++ = DNS_DEFAULT_OFFSET; + + /* fill the answer */ + ans.type = htons(DNS_RRTYPE_TXT); + ans.class = htons(DNS_RRCLASS_FLUSH_IN); + ans.ttl = htonl(300); +// length = os_strlen(TXT_DATA) + MDNS_LENGTH_ADD + 1; + device_info = (char *)os_zalloc(50); + ets_sprintf(device_info,"vendor = %s","Espressif"); + for(i = 0; i < 10 &&(info->txt_data[i] != NULL);i++) { + length += os_strlen(info->txt_data[i]); + length++; + } + length += os_strlen(device_info)+ 1 ; + ans.len = htons(length); + length = 0; + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + query = query + SIZEOF_DNS_ANSWER; + pHostname = device_info; + --pHostname; + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + i = 0; + while(info->txt_data[i] != NULL && i < 10) { + pHostname = info->txt_data[i]; + --pHostname; + /* convert hostname into suitable query format. */ + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + i++; + } +// *query++ = '\0'; + os_free(device_info); + os_strcpy(tmpBuf, name); + pHostname = tmpBuf; + --pHostname; + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + + *query++ = DNS_OFFSET_FLAG; + *query++ = DNS_DEFAULT_OFFSET; + + ans.type = htons(DNS_RRTYPE_SRV); + ans.class = htons(DNS_RRCLASS_FLUSH_IN); + ans.ttl = htonl(300); + os_strcpy(tmpBuf,service_name); + os_strcat(tmpBuf, "."); + os_strcat(tmpBuf, MDNS_LOCAL); + length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD; + ans.len = htons(SIZEOF_MDNS_SERVICE + length); + length = 0; + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + + serv.prior = htons(0); + serv.weight = htons(0); + serv.port = htons(PUCK_PORT); + MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE); + /* resize the query */ + query = query + SIZEOF_MDNS_SERVICE; + + pHostname = tmpBuf; + --pHostname; + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + /* set the name of the authority field. + * The same name as the Query using the offset address*/ + os_strcpy(tmpBuf,service_name); + os_strcat(tmpBuf, "."); + os_strcat(tmpBuf, MDNS_LOCAL); + pHostname = tmpBuf; + --pHostname; + do { + ++pHostname; + nptr = query; + ++query; + for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) { + *query = *pHostname; + ++query; + ++n; + } + *nptr = n; + } while (*pHostname != 0); + *query++ = '\0'; + /* set the name of the authority field. + * The same name as the Query using the offset address*/ + //*query++ = DNS_OFFSET_FLAG; + //*query++ = DNS_DEFAULT_OFFSET; + ans.type = htons(DNS_RRTYPE_A); + ans.class = htons(DNS_RRCLASS_FLUSH_IN); + ans.ttl = htonl(300); + ans.len = htons(DNS_IP_ADDR_LEN); + + MEMCPY( query, &ans, SIZEOF_DNS_ANSWER); + + /* resize the query */ + query = query + SIZEOF_DNS_ANSWER; + + /* fill the payload of the mDNS message */ + /* set the local IP address */ + auth.src = host_addr.addr; //ipAddr; + MEMCPY( query, &auth, SIZEOF_MDNS_AUTH); + /* resize the query */ + query = query + SIZEOF_MDNS_AUTH; + + /* set the name of the authority field. + * The same name as the Query using the offset address*/ + + /* resize pbuf to the exact dns query */ + pbuf_realloc(p, (query) - ((char*) (p->payload))); + /* send dns packet */ + sta_netif = (struct netif *)eagle_lwip_getif(0x00); + ap_netif = (struct netif *)eagle_lwip_getif(0x01); + if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\ + sta_netif != NULL && ap_netif != NULL) { + if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) { + + p_sta = pbuf_alloc(PBUF_TRANSPORT, + SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM); + if (pbuf_copy (p_sta,p) != ERR_OK) { + os_printf("mdns_send_service copying to new pbuf failed\n"); + return -1; + } + netif_set_default(sta_netif); + err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT); + pbuf_free(p_sta); + netif_set_default(ap_netif); + } + } + err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT); + + /* free pbuf */ + pbuf_free(p); + } else { + os_printf("ERR_MEM \n"); + err = ERR_MEM; + } + + return err; +} + +/** + * Receive input function for DNS response packets arriving for the dns UDP pcb. + * + * @params see udp.h + */ +static void ICACHE_FLASH_ATTR +mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, + u16_t port) { + u8_t i; + struct mdns_hdr *hdr; + u8_t nquestions; + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); + struct mdns_info *info = (struct mdns_info *)arg; + /* is the dns message too big ? */ + if (p->tot_len > DNS_MSG_SIZE) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n")); + /* free pbuf and return */ + goto memerr1; + } + + /* is the dns message big enough ? */ + if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) { + LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n")); + /* free pbuf and return */ + goto memerr1; + } + /* copy dns payload inside static buffer for processing */ + if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) == p->tot_len) { + /* The ID in the DNS header should be our entry into the name table. */ + hdr = (struct mdns_hdr*) mdns_payload; + + i = htons(hdr->id); + if (i < DNS_TABLE_SIZE) { + + nquestions = htons(hdr->numquestions); + //nanswers = htons(hdr->numanswers); + /* if we have a question send an answer if necessary */ + if (nquestions > 0) { + /* MDNS_DS_DOES_NAME_CHECK */ + /* Check if the name in the "question" part match with the name of the MDNS DS service. */ + if (mdns_compare_name((unsigned char *) DNS_SD_SERVICE, + (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) { + /* respond with the puck service*/ + mdns_answer(MDNS_SD_ANSWER, PUCK_SERVICE, 0); + } else if (mdns_compare_name((unsigned char *) PUCK_SERVICE, + (unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) { + /* respond with the puck service*/ + mdns_send_service(info, 0); + } else + goto memerr2; + } + } + } + goto memerr2; + memerr2: + mem_free(mdns_payload); + memerr1: + /* free pbuf */ + pbuf_free(p); + return; +} + +/** + * close the UDP pcb . + */ +void ICACHE_FLASH_ATTR +mdns_close(void) +{ + if (mdns_pcb != NULL) + udp_remove(mdns_pcb); +} + +void ICACHE_FLASH_ATTR +mdns_set_name(const char *name) +{ + //strcpy(host_name, name); + os_strcpy(service_name, name); +} + +void ICACHE_FLASH_ATTR +mdns_enable(void) +{ + if(mdns_flag == 0) { + udp_recv(mdns_pcb, mdns_recv, NULL); + } +} + +void ICACHE_FLASH_ATTR +mdns_disable(void) +{ + if (mdns_flag == 1) { + udp_recv(mdns_pcb, NULL, NULL); + } +} + +/** + * close the UDP pcb . + */ +char* ICACHE_FLASH_ATTR +mdns_get_hostname(void) { + //strcpy(host_name, name); + char *name = host_name; + if (host_name[0] != 0 ) { + return name; + } else { + return ("Espressif"); + } +} + +void ICACHE_FLASH_ATTR +mdns_set_hostname(char *name) { + if (name == NULL) { + os_strncpy(host_name, "Espressif", os_strlen("Espressif")+3); + return; + } + if (os_strlen(name) + 3 <= MDNS_NAME_LENGTH ){ + os_strncpy(host_name, name, os_strlen(name) ); +// os_memset(host_name + os_strlen(host_name) ,0x00,3); + } else { + os_strncpy(host_name, name, MDNS_NAME_LENGTH); + } +} + +void ICACHE_FLASH_ATTR +mdns_set_servername(const char *name) { + if (name == NULL) { + PUCK_SERVICE = "_Espressif._tcp._local"; + }else { + os_sprintf(server_name ,"_%s._tcp.local",name); + PUCK_SERVICE = server_name; + } +} + +char* ICACHE_FLASH_ATTR +mdns_get_servername(void) { + char *name = PUCK_SERVICE; + if (name == NULL) { + PUCK_SERVICE = "_Espressif._tcp._local"; + } + return name; +} + +void ICACHE_FLASH_ATTR +mdns_server_unregister(void) { + if(register_flag == 1){ + if (igmp_leavegroup(&host_addr, &multicast_addr) != ERR_OK) { + os_printf("udp_leave_multigrup failed!\n"); + return; + }; + register_flag = 0; + } +} + +void ICACHE_FLASH_ATTR +mdns_server_register(void) { + + if (register_flag == 1) { + os_printf("mdns server is already registered !\n"); + return; + } else if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) { + os_printf("udp_join_multigrup failed!\n"); + return; + }; + register_flag = 1; +} + +void ICACHE_FLASH_ATTR +mdns_reg(struct mdns_info *info) { + + static uint8 i = 0; + if (i <= 3) { + mdns_send_service(info,0); + i++; + } else { + os_timer_disarm(&mdns_timer); + } +} + +/** + * Initialize the resolver: set up the UDP pcb and configure the default server + * (NEW IP). + */ +void ICACHE_FLASH_ATTR +mdns_init(struct mdns_info *info) { + /* initialize default DNS server address */ + multicast_addr.addr = DNS_MULTICAST_ADDRESS; + if (info->ipAddr == 0) { + os_printf("mdns ip error!\n "); + return; + } + host_addr.addr = info->ipAddr ; + LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n")); + //get the datasheet from PUCK + mdns_set_hostname(info->host_name); + mdns_set_servername(info->server_name); + mdns_set_name(info->host_name); + + // get the host name as instrumentName_serialNumber for MDNS + // set the name of the service, the same as host name + os_printf("host_name = %s\n", host_name); + os_printf("server_name = %s\n", PUCK_SERVICE); + if (info->server_port == 0) + { + PUCK_PORT = 80; + } else { + PUCK_PORT = info->server_port; + } + + /* initialize mDNS */ + mdns_pcb = udp_new(); + + 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; + }; + 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) { + os_printf("udp_bind failed!\n"); + return; + }; + + /*loopback function for the multicast(224.0.0.251) messages received at port 5353*/ +// mdns_enable(); + udp_recv(mdns_pcb, mdns_recv, info); + mdns_flag = 1; + /* + * Register the name of the instrument + */ + + os_timer_disarm(&mdns_timer); + os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,info); + os_timer_arm(&mdns_timer, 1000, 1); + } +} + +#endif /* LWIP_MDNS */ diff --git a/app/lwip/core/mem.c b/app/lwip/core/mem.c index 9a66f295..bf6263d9 100644 --- a/app/lwip/core/mem.c +++ b/app/lwip/core/mem.c @@ -636,7 +636,7 @@ void *mem_calloc(mem_size_t count, mem_size_t size) p = mem_malloc(count * size); if (p) { /* zero the memory */ - memset(p, 0, count * size); + os_memset(p, 0, count * size); } return p; } diff --git a/app/lwip/core/memp.c b/app/lwip/core/memp.c index 16caf20b..38bdd1be 100644 --- a/app/lwip/core/memp.c +++ b/app/lwip/core/memp.c @@ -126,7 +126,7 @@ static struct memp *memp_tab[MEMP_MAX]; #if !MEM_USE_POOLS && !MEMP_MEM_MALLOC static #endif -const u16_t memp_sizes[MEMP_MAX] = { //LWIP_MEM_ALIGN_SIZE +const u32_t memp_sizes[MEMP_MAX] ICACHE_RODATA_ATTR = { //LWIP_MEM_ALIGN_SIZE #define LWIP_MEMPOOL(name,num,size,desc,attr) LWIP_MEM_ALIGN_SIZE(size), #include "lwip/memp_std.h" }; @@ -320,11 +320,11 @@ memp_overflow_init(void) for (j = 0; j < memp_num[i]; ++j) { #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; - memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); + os_memset(m, 0xcd, MEMP_SANITY_REGION_BEFORE_ALIGNED); #endif #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; - memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); + os_memset(m, 0xcd, MEMP_SANITY_REGION_AFTER_ALIGNED); #endif p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); } diff --git a/app/lwip/core/netif.c b/app/lwip/core/netif.c index 6a11dcac..6913b408 100644 --- a/app/lwip/core/netif.c +++ b/app/lwip/core/netif.c @@ -149,6 +149,7 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, #if LWIP_DHCP /* netif not under DHCP control by default */ netif->dhcp = NULL; + netif->dhcps_pcb = NULL; #endif /* LWIP_DHCP */ #if LWIP_AUTOIP /* netif not under AutoIP control by default */ diff --git a/app/lwip/core/pbuf.c b/app/lwip/core/pbuf.c index e30c0c17..97f1baa6 100644 --- a/app/lwip/core/pbuf.c +++ b/app/lwip/core/pbuf.c @@ -80,7 +80,7 @@ #include #ifdef EBUF_LWIP -#include "pp/esf_buf.h" +#define EP_OFFSET 36 #else #define EP_OFFSET 0 #endif /* ESF_LWIP */ @@ -329,6 +329,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) p->len = p->tot_len = length; p->next = NULL; p->type = type; + p->eb = NULL; LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); @@ -363,6 +364,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) /* set flags */ p->flags = 0; LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); + return p; } @@ -1204,7 +1206,7 @@ pbuf_strstr(struct pbuf* p, const char* substr) if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { return 0xFFFF; } - substr_len = strlen(substr); + substr_len = os_strlen(substr); if (substr_len >= 0xFFFF) { return 0xFFFF; } diff --git a/app/lwip/core/raw.c b/app/lwip/core/raw.c index d0e65579..09540069 100644 --- a/app/lwip/core/raw.c +++ b/app/lwip/core/raw.c @@ -342,7 +342,7 @@ raw_new(u8_t proto) /* could allocate RAW PCB? */ if (pcb != NULL) { /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct raw_pcb)); + os_memset(pcb, 0, sizeof(struct raw_pcb)); pcb->protocol = proto; pcb->ttl = RAW_TTL; pcb->next = raw_pcbs; diff --git a/app/lwip/core/sntp.c b/app/lwip/core/sntp.c new file mode 100644 index 00000000..677de93b --- /dev/null +++ b/app/lwip/core/sntp.c @@ -0,0 +1,1128 @@ +/** + * @file + * SNTP client module + * + * This is simple "SNTP" client for the lwIP raw API. + * It is a minimal implementation of SNTPv4 as specified in RFC 4330. + * + * For a list of some public NTP servers, see this link : + * http://support.ntp.org/bin/view/Servers/NTPPoolServers + * + * @todo: + * - set/change servers at runtime + * - complete SNTP_CHECK_RESPONSE checks 3 and 4 + * - support broadcast/multicast mode? + */ + +/* + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Simon Goldschmidt (lwIP raw API part) + */ + +#include "lwip/sntp.h" +#include "osapi.h" +#include "os_type.h" +#include "lwip/opt.h" +#include "lwip/timers.h" +#include "lwip/udp.h" +#include "lwip/dns.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" + +//#include +#if LWIP_UDP + +/** + * SNTP_DEBUG: Enable debugging for SNTP. + */ +#ifndef SNTP_DEBUG +#define SNTP_DEBUG LWIP_DBG_ON +#endif + +/** SNTP server port */ +#ifndef SNTP_PORT +#define SNTP_PORT 123 +#endif + +/** Set this to 1 to allow config of SNTP server(s) by DNS name */ +#ifndef SNTP_SERVER_DNS +#define SNTP_SERVER_DNS 0 +#endif + +/** Handle support for more than one server via NTP_MAX_SERVERS, + * but catch legacy style of setting SNTP_SUPPORT_MULTIPLE_SERVERS, probably outside of this file + */ +#ifndef SNTP_SUPPORT_MULTIPLE_SERVERS +#if SNTP_MAX_SERVERS > 1 +#define SNTP_SUPPORT_MULTIPLE_SERVERS 1 +#else /* NTP_MAX_SERVERS > 1 */ +#define SNTP_SUPPORT_MULTIPLE_SERVERS 0 +#endif /* NTP_MAX_SERVERS > 1 */ +#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ +/* The developer has defined SNTP_SUPPORT_MULTIPLE_SERVERS, probably from old code */ +#if SNTP_MAX_SERVERS <= 1 +#error "SNTP_MAX_SERVERS needs to be defined to the max amount of servers if SNTP_SUPPORT_MULTIPLE_SERVERS is defined" +#endif /* SNTP_MAX_SERVERS <= 1 */ +#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ + + +/** Sanity check: + * Define this to + * - 0 to turn off sanity checks (default; smaller code) + * - >= 1 to check address and port of the response packet to ensure the + * response comes from the server we sent the request to. + * - >= 2 to check returned Originate Timestamp against Transmit Timestamp + * sent to the server (to ensure response to older request). + * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp + * fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast). + * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each + * greater than or equal to 0 and less than infinity, where infinity is + * currently a cozy number like one second. This check avoids using a + * server whose synchronization source has expired for a very long time. + */ +#ifndef SNTP_CHECK_RESPONSE +#define SNTP_CHECK_RESPONSE 0 +#endif + +/** According to the RFC, this shall be a random delay + * between 1 and 5 minutes (in milliseconds) to prevent load peaks. + * This can be defined to a random generation function, + * which must return the delay in milliseconds as u32_t. + * Turned off by default. + */ +#ifndef SNTP_STARTUP_DELAY +#define SNTP_STARTUP_DELAY 0 +#endif + +/** If you want the startup delay to be a function, define this + * to a function (including the brackets) and define SNTP_STARTUP_DELAY to 1. + */ +#ifndef SNTP_STARTUP_DELAY_FUNC +#define SNTP_STARTUP_DELAY_FUNC SNTP_STARTUP_DELAY +#endif + +/** SNTP receive timeout - in milliseconds + * Also used as retry timeout - this shouldn't be too low. + * Default is 3 seconds. + */ +#ifndef SNTP_RECV_TIMEOUT +#define SNTP_RECV_TIMEOUT 3000 +#endif + +/** SNTP update delay - in milliseconds + * Default is 1 hour. + */ +#ifndef SNTP_UPDATE_DELAY +#define SNTP_UPDATE_DELAY 3600000 +#endif +#if (SNTP_UPDATE_DELAY < 15000) && !SNTP_SUPPRESS_DELAY_CHECK +#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds!" +#endif + +/** SNTP macro to change system time and/or the update the RTC clock */ +#ifndef SNTP_SET_SYSTEM_TIME +#define SNTP_SET_SYSTEM_TIME(sec) ((void)sec) +#endif + +/** SNTP macro to change system time including microseconds */ +#ifdef SNTP_SET_SYSTEM_TIME_US +#define SNTP_CALC_TIME_US 1 +#define SNTP_RECEIVE_TIME_SIZE 2 +#else +#define SNTP_SET_SYSTEM_TIME_US(sec, us) +#define SNTP_CALC_TIME_US 0 +#define SNTP_RECEIVE_TIME_SIZE 1 +#endif + +/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2 + * to send in request and compare in response. + */ +#ifndef SNTP_GET_SYSTEM_TIME +#define SNTP_GET_SYSTEM_TIME(sec, us) do { (sec) = 0; (us) = 0; } while(0) +#endif + +/** Default retry timeout (in milliseconds) if the response + * received is invalid. + * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached. + */ +#ifndef SNTP_RETRY_TIMEOUT +#define SNTP_RETRY_TIMEOUT SNTP_RECV_TIMEOUT +#endif + +/** Maximum retry timeout (in milliseconds). */ +#ifndef SNTP_RETRY_TIMEOUT_MAX +#define SNTP_RETRY_TIMEOUT_MAX (SNTP_RETRY_TIMEOUT * 10) +#endif + +/** Increase retry timeout with every retry sent + * Default is on to conform to RFC. + */ +#ifndef SNTP_RETRY_TIMEOUT_EXP +#define SNTP_RETRY_TIMEOUT_EXP 1 +#endif + +/* the various debug levels for this file */ +#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE) +#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE) +#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) +#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) + +#define SNTP_ERR_KOD 1 + +/* SNTP protocol defines */ +#define SNTP_MSG_LEN 48 + +#define SNTP_OFFSET_LI_VN_MODE 0 +#define SNTP_LI_MASK 0xC0 +#define SNTP_LI_NO_WARNING 0x00 +#define SNTP_LI_LAST_MINUTE_61_SEC 0x01 +#define SNTP_LI_LAST_MINUTE_59_SEC 0x02 +#define SNTP_LI_ALARM_CONDITION 0x03 /* (clock not synchronized) */ + +#define SNTP_VERSION_MASK 0x38 +#define SNTP_VERSION (4/* NTP Version 4*/<<3) + +#define SNTP_MODE_MASK 0x07 +#define SNTP_MODE_CLIENT 0x03 +#define SNTP_MODE_SERVER 0x04 +#define SNTP_MODE_BROADCAST 0x05 + +#define SNTP_OFFSET_STRATUM 1 +#define SNTP_STRATUM_KOD 0x00 + +#define SNTP_OFFSET_ORIGINATE_TIME 24 +#define SNTP_OFFSET_RECEIVE_TIME 32 +#define SNTP_OFFSET_TRANSMIT_TIME 40 + +/* number of seconds between 1900 and 1970 */ +#define DIFF_SEC_1900_1970 (2208988800UL) + +/** + * SNTP packet format (without optional fields) + * Timestamps are coded as 64 bits: + * - 32 bits seconds since Jan 01, 1970, 00:00 + * - 32 bits seconds fraction (0-padded) + * For future use, if the MSB in the seconds part is set, seconds are based + * on Feb 07, 2036, 06:28:16. + */ +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/bpstruct.h" +#endif +PACK_STRUCT_BEGIN +#define PACK_STRUCT_FLD_8 PACK_STRUCT_FIELD +struct sntp_msg { + PACK_STRUCT_FLD_8(u8_t li_vn_mode); + PACK_STRUCT_FLD_8(u8_t stratum); + PACK_STRUCT_FLD_8(u8_t poll); + PACK_STRUCT_FLD_8(u8_t precision); + PACK_STRUCT_FIELD(u32_t root_delay); + PACK_STRUCT_FIELD(u32_t root_dispersion); + PACK_STRUCT_FIELD(u32_t reference_identifier); + PACK_STRUCT_FIELD(u32_t reference_timestamp[2]); + PACK_STRUCT_FIELD(u32_t originate_timestamp[2]); + PACK_STRUCT_FIELD(u32_t receive_timestamp[2]); + PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]); +} PACK_STRUCT_STRUCT; +PACK_STRUCT_END +#ifdef PACK_STRUCT_USE_INCLUDES +# include "arch/epstruct.h" +#endif + +/* function prototypes */ +static void sntp_request(void *arg); + +/** The UDP pcb used by the SNTP client */ +static struct udp_pcb* sntp_pcb; + +sint8 time_zone = 8; +/** Names/Addresses of servers */ +struct sntp_server { +#if SNTP_SERVER_DNS + char* name; +#endif /* SNTP_SERVER_DNS */ + ip_addr_t addr; +}; +static struct sntp_server sntp_servers[SNTP_MAX_SERVERS]; + +static u8_t sntp_set_servers_from_dhcp; +#if SNTP_SUPPORT_MULTIPLE_SERVERS +/** The currently used server (initialized to 0) */ +static u8_t sntp_current_server; +#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ +#define sntp_current_server 0 +#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ + +#if SNTP_RETRY_TIMEOUT_EXP +#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT +/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */ +static u32_t sntp_retry_timeout; +#else /* SNTP_RETRY_TIMEOUT_EXP */ +#define SNTP_RESET_RETRY_TIMEOUT() +#define sntp_retry_timeout SNTP_RETRY_TIMEOUT +#endif /* SNTP_RETRY_TIMEOUT_EXP */ + +#if SNTP_CHECK_RESPONSE >= 1 +/** Saves the last server address to compare with response */ +static ip_addr_t sntp_last_server_address; +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + +#if SNTP_CHECK_RESPONSE >= 2 +/** Saves the last timestamp sent (which is sent back by the server) + * to compare against in response */ +static u32_t sntp_last_timestamp_sent[2]; +#endif /* SNTP_CHECK_RESPONSE >= 2 */ +typedef long time_t; +//uint32 current_stamp_1 = 0; +//uint32 current_stamp_2 = 0; +uint32 realtime_stamp = 0; +LOCAL os_timer_t sntp_timer; +/*****************************************/ +#define SECSPERMIN 60L +#define MINSPERHOUR 60L +#define HOURSPERDAY 24L +#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR) +#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY) +#define DAYSPERWEEK 7 +#define MONSPERYEAR 12 + +#define YEAR_BASE 1900 +#define EPOCH_YEAR 1970 +#define EPOCH_WDAY 4 +#define EPOCH_YEARS_SINCE_LEAP 2 +#define EPOCH_YEARS_SINCE_CENTURY 70 +#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370 + +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + +int __tznorth; +int __tzyear; +char reult[100]; +static const int mon_lengths[2][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +} ; + +static const int year_lengths[2] = { + 365, + 366 +} ; +struct tm +{ + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +struct tm res_buf; +typedef struct __tzrule_struct +{ + char ch; + int m; + int n; + int d; + int s; + time_t change; + int offset; +} __tzrule_type; + +__tzrule_type sntp__tzrule[2]; +struct tm * ICACHE_FLASH_ATTR +sntp_mktm_r(const time_t * tim_p ,struct tm *res ,int is_gmtime) +{ + long days, rem; + time_t lcltime; + int i; + int y; + int yleap; + const int *ip; + + /* base decision about std/dst time on current time */ + lcltime = *tim_p; + + days = ((long)lcltime) / SECSPERDAY; + rem = ((long)lcltime) % SECSPERDAY; + while (rem < 0) + { + rem += SECSPERDAY; + --days; + } + while (rem >= SECSPERDAY) + { + rem -= SECSPERDAY; + ++days; + } + + /* compute hour, min, and sec */ + res->tm_hour = (int) (rem / SECSPERHOUR); + rem %= SECSPERHOUR; + res->tm_min = (int) (rem / SECSPERMIN); + res->tm_sec = (int) (rem % SECSPERMIN); + + /* compute day of week */ + if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0) + res->tm_wday += DAYSPERWEEK; + + /* compute year & day of year */ + y = EPOCH_YEAR; + if (days >= 0) + { + for (;;) + { + yleap = isleap(y); + if (days < year_lengths[yleap]) + break; + y++; + days -= year_lengths[yleap]; + } + } + else + { + do + { + --y; + yleap = isleap(y); + days += year_lengths[yleap]; + } while (days < 0); + } + + res->tm_year = y - YEAR_BASE; + res->tm_yday = days; + ip = mon_lengths[yleap]; + for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon) + days -= ip[res->tm_mon]; + res->tm_mday = days + 1; + + if (!is_gmtime) + { + int offset; + int hours, mins, secs; + +// TZ_LOCK; +// if (_daylight) +// { +// if (y == __tzyear || __tzcalc_limits (y)) +// res->tm_isdst = (__tznorth +// ? (*tim_p >= __tzrule[0].change && *tim_p < __tzrule[1].change) +// : (*tim_p >= __tzrule[0].change || *tim_p < __tzrule[1].change)); +// else +// res->tm_isdst = -1; +// } +// else + res->tm_isdst = 0; + + offset = (res->tm_isdst == 1 ? sntp__tzrule[1].offset : sntp__tzrule[0].offset); + + hours = offset / SECSPERHOUR; + offset = offset % SECSPERHOUR; + + mins = offset / SECSPERMIN; + secs = offset % SECSPERMIN; + + res->tm_sec -= secs; + res->tm_min -= mins; + res->tm_hour -= hours; + + if (res->tm_sec >= SECSPERMIN) + { + res->tm_min += 1; + res->tm_sec -= SECSPERMIN; + } + else if (res->tm_sec < 0) + { + res->tm_min -= 1; + res->tm_sec += SECSPERMIN; + } + if (res->tm_min >= MINSPERHOUR) + { + res->tm_hour += 1; + res->tm_min -= MINSPERHOUR; + } + else if (res->tm_min < 0) + { + res->tm_hour -= 1; + res->tm_min += MINSPERHOUR; + } + if (res->tm_hour >= HOURSPERDAY) + { + ++res->tm_yday; + ++res->tm_wday; + if (res->tm_wday > 6) + res->tm_wday = 0; + ++res->tm_mday; + res->tm_hour -= HOURSPERDAY; + if (res->tm_mday > ip[res->tm_mon]) + { + res->tm_mday -= ip[res->tm_mon]; + res->tm_mon += 1; + if (res->tm_mon == 12) + { + res->tm_mon = 0; + res->tm_year += 1; + res->tm_yday = 0; + } + } + } + else if (res->tm_hour < 0) + { + res->tm_yday -= 1; + res->tm_wday -= 1; + if (res->tm_wday < 0) + res->tm_wday = 6; + res->tm_mday -= 1; + res->tm_hour += 24; + if (res->tm_mday == 0) + { + res->tm_mon -= 1; + if (res->tm_mon < 0) + { + res->tm_mon = 11; + res->tm_year -= 1; + res->tm_yday = 365 + isleap(res->tm_year); + } + res->tm_mday = ip[res->tm_mon]; + } + } +// TZ_UNLOCK; + } + else + res->tm_isdst = 0; +// os_printf("res %d %d %d %d %d\n",res->tm_year,res->tm_mon,res->tm_mday,res->tm_yday,res->tm_hour); + return (res); +} +struct tm * ICACHE_FLASH_ATTR +sntp_localtime_r(const time_t * tim_p , + struct tm *res) +{ + return sntp_mktm_r (tim_p, res, 0); +} + +struct tm * ICACHE_FLASH_ATTR +sntp_localtime(const time_t * tim_p) +{ + return sntp_localtime_r (tim_p, &res_buf); +} + + +int ICACHE_FLASH_ATTR +sntp__tzcalc_limits(int year) +{ + int days, year_days, years; + int i, j; + + if (year < EPOCH_YEAR) + return 0; + + __tzyear = year; + + years = (year - EPOCH_YEAR); + + year_days = years * 365 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP) / 4 - (years - 1 + EPOCH_YEARS_SINCE_CENTURY) / 100 + + (years - 1 + EPOCH_YEARS_SINCE_LEAP_CENTURY) / 400; + + for (i = 0; i < 2; ++i) + { + if (sntp__tzrule[i].ch == 'J') + days = year_days + sntp__tzrule[i].d + (isleap(year) && sntp__tzrule[i].d >= 60); + else if (sntp__tzrule[i].ch == 'D') + days = year_days + sntp__tzrule[i].d; + else + { + int yleap = isleap(year); + int m_day, m_wday, wday_diff; + const int *ip = mon_lengths[yleap]; + + days = year_days; + + for (j = 1; j < sntp__tzrule[i].m; ++j) + days += ip[j-1]; + + m_wday = (EPOCH_WDAY + days) % DAYSPERWEEK; + + wday_diff = sntp__tzrule[i].d - m_wday; + if (wday_diff < 0) + wday_diff += DAYSPERWEEK; + m_day = (sntp__tzrule[i].n - 1) * DAYSPERWEEK + wday_diff; + + while (m_day >= ip[j-1]) + m_day -= DAYSPERWEEK; + + days += m_day; + } + + /* store the change-over time in GMT form by adding offset */ + sntp__tzrule[i].change = days * SECSPERDAY + sntp__tzrule[i].s + sntp__tzrule[i].offset; + } + + __tznorth = (sntp__tzrule[0].change < sntp__tzrule[1].change); + + return 1; +} + +char * ICACHE_FLASH_ATTR +sntp_asctime_r(struct tm *tim_p ,char *result) +{ + static const char day_name[7][4] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + static const char mon_name[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + os_sprintf (result, "%s %s %02d %02d:%02d:%02d %02d\n", + day_name[tim_p->tm_wday], + mon_name[tim_p->tm_mon], + tim_p->tm_mday, tim_p->tm_hour, tim_p->tm_min, + tim_p->tm_sec, 1900 + tim_p->tm_year); + return result; +} +char *ICACHE_FLASH_ATTR +sntp_asctime(struct tm *tim_p) +{ + + return sntp_asctime_r (tim_p, reult); +} + +uint32 sntp_get_current_timestamp() +{ + if(realtime_stamp == 0){ + os_printf("please start sntp first !\n"); + return 0; + } else { + return realtime_stamp; + } +} + +char* sntp_get_real_time(time_t t) +{ + return sntp_asctime(sntp_localtime (&t)); +} +/** + * SNTP get time_zone default GMT + 8 + */ +sint8 ICACHE_FLASH_ATTR +sntp_get_timezone(void) +{ + return time_zone; +} +/** + * SNTP set time_zone default GMT + 8 + */ + +bool ICACHE_FLASH_ATTR +sntp_set_timezone(sint8 timezone) +{ + if(timezone >= -11 || timezone <= 13) { + time_zone = timezone; + return true; + } else { + return false; + } + +} +void ICACHE_FLASH_ATTR +sntp_time_inc(void) +{ + realtime_stamp++; +} +/** + * SNTP processing of received timestamp + */ +static void ICACHE_FLASH_ATTR +sntp_process(u32_t *receive_timestamp) +{ + /* convert SNTP time (1900-based) to unix GMT time (1970-based) + * @todo: if MSB is 1, SNTP time is 2036-based! + */ + time_t t = (ntohl(receive_timestamp[0]) - DIFF_SEC_1900_1970); + +#if SNTP_CALC_TIME_US + u32_t us = ntohl(receive_timestamp[1]) / 4295; + SNTP_SET_SYSTEM_TIME_US(t, us); + /* display local time from GMT time */ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&t), us)); + +#else /* SNTP_CALC_TIME_US */ + + /* change system time and/or the update the RTC clock */ + SNTP_SET_SYSTEM_TIME(t); + /* display local time from GMT time */ + t += time_zone * 60 * 60;// format GMT + time_zone TIME ZONE + realtime_stamp = t; + os_timer_disarm(&sntp_timer); + os_timer_setfn(&sntp_timer, (os_timer_func_t *)sntp_time_inc, NULL); + os_timer_arm(&sntp_timer, 1000, 1); + os_printf("%s\n",sntp_asctime(sntp_localtime (&t))); +// os_printf("%s\n",ctime(&t)); +// LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&t))); +#endif /* SNTP_CALC_TIME_US */ +} + +/** + * Initialize request struct to be sent to server. + */ +static void ICACHE_FLASH_ATTR +sntp_initialize_request(struct sntp_msg *req) +{ + os_memset(req, 0, SNTP_MSG_LEN); + req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; + +#if SNTP_CHECK_RESPONSE >= 2 + { + u32_t sntp_time_sec, sntp_time_us; + /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */ + SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us); + sntp_last_timestamp_sent[0] = htonl(sntp_time_sec + DIFF_SEC_1900_1970); + req->transmit_timestamp[0] = sntp_last_timestamp_sent[0]; + /* we send/save us instead of fraction to be faster... */ + sntp_last_timestamp_sent[1] = htonl(sntp_time_us); + req->transmit_timestamp[1] = sntp_last_timestamp_sent[1]; + } +#endif /* SNTP_CHECK_RESPONSE >= 2 */ +} + +/** + * Retry: send a new request (and increase retry timeout). + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void ICACHE_FLASH_ATTR +sntp_retry(void* arg) +{ + LWIP_UNUSED_ARG(arg); + + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n", + sntp_retry_timeout)); + + /* set up a timer to send a retry and increase the retry delay */ + sys_timeout(sntp_retry_timeout, sntp_request, NULL); + +#if SNTP_RETRY_TIMEOUT_EXP + { + u32_t new_retry_timeout; + /* increase the timeout for next retry */ + new_retry_timeout = sntp_retry_timeout << 1; + /* limit to maximum timeout and prevent overflow */ + if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) && + (new_retry_timeout > sntp_retry_timeout)) { + sntp_retry_timeout = new_retry_timeout; + } + } +#endif /* SNTP_RETRY_TIMEOUT_EXP */ +} + +#if SNTP_SUPPORT_MULTIPLE_SERVERS +/** + * If Kiss-of-Death is received (or another packet parsing error), + * try the next server or retry the current server and increase the retry + * timeout if only one server is available. + * (implicitly, SNTP_MAX_SERVERS > 1) + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void +sntp_try_next_server(void* arg) +{ + u8_t old_server, i; + LWIP_UNUSED_ARG(arg); + + old_server = sntp_current_server; + for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) { + sntp_current_server++; + if (sntp_current_server >= SNTP_MAX_SERVERS) { + sntp_current_server = 0; + } + if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr) +#if SNTP_SERVER_DNS + || (sntp_servers[sntp_current_server].name != NULL) +#endif + ) { + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n", + (u16_t)sntp_current_server)); + /* new server: reset retry timeout */ + SNTP_RESET_RETRY_TIMEOUT(); + /* instantly send a request to the next server */ + sntp_request(NULL); + return; + } + } + /* no other valid server found */ + sntp_current_server = old_server; + sntp_retry(NULL); +} +#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ +/* Always retry on error if only one server is supported */ +#define sntp_try_next_server sntp_retry +#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ + +/** UDP recv callback for the sntp pcb */ +static void ICACHE_FLASH_ATTR +sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, ip_addr_t *addr, u16_t port) +{ + u8_t mode; + u8_t stratum; + u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE]; + err_t err; +//os_printf("sntp_recv\n"); + LWIP_UNUSED_ARG(arg); + LWIP_UNUSED_ARG(pcb); + + /* packet received: stop retry timeout */ + sys_untimeout(sntp_try_next_server, NULL); + sys_untimeout(sntp_request, NULL); + + err = ERR_ARG; +#if SNTP_CHECK_RESPONSE >= 1 + /* check server address and port */ + if (ip_addr_cmp(addr, &sntp_last_server_address) && + (port == SNTP_PORT)) +#else /* SNTP_CHECK_RESPONSE >= 1 */ + LWIP_UNUSED_ARG(addr); + LWIP_UNUSED_ARG(port); +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + { + /* process the response */ + if (p->tot_len == SNTP_MSG_LEN) { + pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE); + mode &= SNTP_MODE_MASK; + /* if this is a SNTP response... */ + if ((mode == SNTP_MODE_SERVER) || + (mode == SNTP_MODE_BROADCAST)) { + pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM); + if (stratum == SNTP_STRATUM_KOD) { + /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ + err = SNTP_ERR_KOD; + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n")); + } else { +#if SNTP_CHECK_RESPONSE >= 2 + /* check originate_timetamp against sntp_last_timestamp_sent */ + u32_t originate_timestamp[2]; + pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME); + if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) || + (originate_timestamp[1] != sntp_last_timestamp_sent[1])) + { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n")); + } else +#endif /* SNTP_CHECK_RESPONSE >= 2 */ + /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */ + { + /* correct answer */ + err = ERR_OK; + pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_RECEIVE_TIME); + } + } + } else { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode)); + } + } else { + LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len)); + } + } + pbuf_free(p); + if (err == ERR_OK) { + /* Correct response, reset retry timeout */ + SNTP_RESET_RETRY_TIMEOUT(); + + sntp_process(receive_timestamp); + + /* Set up timeout for next request */ + sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL); + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", + (u32_t)SNTP_UPDATE_DELAY)); + } else if (err == SNTP_ERR_KOD) { + /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ + sntp_try_next_server(NULL); + } else { + /* another error, try the same server again */ + sntp_retry(NULL); + } +} + +/** Actually send an sntp request to a server. + * + * @param server_addr resolved IP address of the SNTP server + */ +static void ICACHE_FLASH_ATTR +sntp_send_request(ip_addr_t *server_addr) +{ + struct pbuf* p; +// os_printf("sntp_send_request\n"); + p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM); + if (p != NULL) { + struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload; + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n")); + /* initialize request message */ + sntp_initialize_request(sntpmsg); + /* send request */ + udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT); + /* free the pbuf after sending it */ + pbuf_free(p); + /* set up receive timeout: try next server or retry on timeout */ + sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL); +#if SNTP_CHECK_RESPONSE >= 1 + /* save server address to verify it in sntp_recv */ + ip_addr_set(&sntp_last_server_address, server_addr); +#endif /* SNTP_CHECK_RESPONSE >= 1 */ + } else { + LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n", + (u32_t)SNTP_RETRY_TIMEOUT)); + /* out of memory: set up a timer to send a retry */ + sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL); + } +} + +#if SNTP_SERVER_DNS +/** + * DNS found callback when using DNS names as server address. + */ +static void +sntp_dns_found(const char* hostname, ip_addr_t *ipaddr, void *arg) +{ + LWIP_UNUSED_ARG(hostname); + LWIP_UNUSED_ARG(arg); + + if (ipaddr != NULL) { + /* Address resolved, send request */ + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n")); + sntp_send_request(ipaddr); + } else { + /* DNS resolving failed -> try another server */ + LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n")); + sntp_try_next_server(NULL); + } +} +#endif /* SNTP_SERVER_DNS */ + +/** + * Send out an sntp request. + * + * @param arg is unused (only necessary to conform to sys_timeout) + */ +static void ICACHE_FLASH_ATTR +sntp_request(void *arg) +{ + ip_addr_t sntp_server_address; + err_t err; + + LWIP_UNUSED_ARG(arg); + + /* initialize SNTP server address */ +#if SNTP_SERVER_DNS + + if (sntp_servers[sntp_current_server].name) { + /* always resolve the name and rely on dns-internal caching & timeout */ + ip_addr_set_any(&sntp_servers[sntp_current_server].addr); + err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address, + sntp_dns_found, NULL); + if (err == ERR_INPROGRESS) { + /* DNS request sent, wait for sntp_dns_found being called */ + LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n")); + return; + } else if (err == ERR_OK) { + sntp_servers[sntp_current_server].addr = sntp_server_address; + } + } else +#endif /* SNTP_SERVER_DNS */ + { + sntp_server_address = sntp_servers[sntp_current_server].addr; +// os_printf("sntp_server_address ip %d\n",sntp_server_address.addr); + err = (ip_addr_isany(&sntp_server_address)) ? ERR_ARG : ERR_OK; + } + + if (err == ERR_OK) { + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %u.%u.%u.%u\n", + ip4_addr1(&sntp_server_address), ip4_addr2(&sntp_server_address), ip4_addr3(&sntp_server_address), ip4_addr4(&sntp_server_address))); + sntp_send_request(&sntp_server_address); + } else { + /* address conversion failed, try another server */ + LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n")); + sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL); + } +} + +/** + * Initialize this module. + * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC). + */ +void ICACHE_FLASH_ATTR +sntp_init(void) +{ +#ifdef SNTP_SERVER_ADDRESS +#if SNTP_SERVER_DNS + sntp_setservername(0, SNTP_SERVER_ADDRESS); +#else +#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0 +#endif +#endif /* SNTP_SERVER_ADDRESS */ + + if (sntp_pcb == NULL) { + SNTP_RESET_RETRY_TIMEOUT(); + sntp_pcb = udp_new(); + LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); + if (sntp_pcb != NULL) { + udp_recv(sntp_pcb, sntp_recv, NULL); +#if SNTP_STARTUP_DELAY + sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL); +#else + sntp_request(NULL); +#endif + } + } +} + +/** + * Stop this module. + */ +void ICACHE_FLASH_ATTR +sntp_stop(void) +{ + if (sntp_pcb != NULL) { + sys_untimeout(sntp_request, NULL); + udp_remove(sntp_pcb); + sntp_pcb = NULL; + } + os_timer_disarm(&sntp_timer); + realtime_stamp = 0; +} + +#if SNTP_GET_SERVERS_FROM_DHCP +/** + * Config SNTP server handling by IP address, name, or DHCP; clear table + * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp + */ +void +sntp_servermode_dhcp(int set_servers_from_dhcp) +{ + u8_t new_mode = set_servers_from_dhcp ? 1 : 0; + if (sntp_set_servers_from_dhcp != new_mode) { + sntp_set_servers_from_dhcp = new_mode; + } +} +#endif /* SNTP_GET_SERVERS_FROM_DHCP */ + +/** + * Initialize one of the NTP servers by IP address + * + * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param dnsserver IP address of the NTP server to set + */ +void ICACHE_FLASH_ATTR +sntp_setserver(u8_t idx, ip_addr_t *server) +{ + if (idx < SNTP_MAX_SERVERS) { + if (server != NULL) { + sntp_servers[idx].addr = (*server); +// os_printf("server ip %d\n",server->addr); + } else { + ip_addr_set_any(&sntp_servers[idx].addr); + } +#if SNTP_SERVER_DNS + sntp_servers[idx].name = NULL; +#endif + } +} + +#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP +/** + * Initialize one of the NTP servers by IP address, required by DHCP + * + * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param dnsserver IP address of the NTP server to set + */ +void +dhcp_set_ntp_servers(u8_t num, ip_addr_t *server) +{ + LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n", + (sntp_set_servers_from_dhcp ? "Got" : "Rejected"), + ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num)); + if (sntp_set_servers_from_dhcp && num) { + u8_t i; + for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { + sntp_setserver(i, &server[i]); + } + for (i = num; i < SNTP_MAX_SERVERS; i++) { + sntp_setserver(i, NULL); + } + } +} +#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ + +/** + * Obtain one of the currently configured by IP address (or DHCP) NTP servers + * + * @param numdns the index of the NTP server + * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP + * server has not been configured by address (or at all). + */ +ip_addr_t ICACHE_FLASH_ATTR +sntp_getserver(u8_t idx) +{ + if (idx < SNTP_MAX_SERVERS) { + return sntp_servers[idx].addr; + } + return *IP_ADDR_ANY; +} + +#if SNTP_SERVER_DNS +/** + * Initialize one of the NTP servers by name + * + * @param numdns the index of the NTP server to set must be < SNTP_MAX_SERVERS + * @param dnsserver DNS name of the NTP server to set, to be resolved at contact time + */ +void ICACHE_FLASH_ATTR +sntp_setservername(u8_t idx, char *server) +{ + if (idx < SNTP_MAX_SERVERS) { + sntp_servers[idx].name = server; + } +} + +/** + * Obtain one of the currently configured by name NTP servers. + * + * @param numdns the index of the NTP server + * @return IP address of the indexed NTP server or NULL if the NTP + * server has not been configured by name (or at all) + */ +char * ICACHE_FLASH_ATTR +sntp_getservername(u8_t idx) +{ + if (idx < SNTP_MAX_SERVERS) { + return sntp_servers[idx].name; + } + return NULL; +} +#endif /* SNTP_SERVER_DNS */ + +#endif /* LWIP_UDP */ diff --git a/app/lwip/core/sys_arch.c b/app/lwip/core/sys_arch.c index 81bb2208..e79042f2 100644 --- a/app/lwip/core/sys_arch.c +++ b/app/lwip/core/sys_arch.c @@ -1,13 +1,13 @@ -/* - * copyright (c) 2010 - 2011 espressif system - */ - -#include "c_types.h" -#include "ets_sys.h" -#include "osapi.h" -#include "os_type.h" - -#include "lwip/opt.h" -#include "lwip/sys.h" - -#include "eagle_soc.h" +/* + * copyright (c) 2010 - 2011 espressif system + */ + +#include "c_types.h" +#include "ets_sys.h" +#include "osapi.h" +#include "os_type.h" + +#include "lwip/opt.h" +#include "lwip/sys.h" + +#include "eagle_soc.h" diff --git a/app/lwip/core/tcp.c b/app/lwip/core/tcp.c index fe0bb913..6713679e 100644 --- a/app/lwip/core/tcp.c +++ b/app/lwip/core/tcp.c @@ -55,7 +55,8 @@ #include -const char * const tcp_state_str[] = { +#if TCP_DEBUG +const char tcp_state_str_rodata[][12] ICACHE_RODATA_ATTR = { "CLOSED", "LISTEN", "SYN_SENT", @@ -69,12 +70,15 @@ const char * const tcp_state_str[] = { "TIME_WAIT" }; +char tcp_state_str[12]; +#endif + /* Incremented every coarse grained timer shot (typically every 500 ms). */ u32_t tcp_ticks; -const u8_t tcp_backoff[13] = +const u8_t tcp_backoff[13] ICACHE_RODATA_ATTR = { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7}; /* Times per slowtmr hits */ -const u8_t tcp_persist_backoff[7] = { 3, 6, 12, 24, 48, 96, 120 }; +const u8_t tcp_persist_backoff[7] ICACHE_RODATA_ATTR = { 3, 6, 12, 24, 48, 96, 120 }; /* The TCP PCB lists. */ @@ -91,7 +95,7 @@ struct tcp_pcb *tcp_tw_pcbs; #define NUM_TCP_PCB_LISTS 4 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 /** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ -struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, +struct tcp_pcb ** const tcp_pcb_lists[] ICACHE_RODATA_ATTR = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; /** Only used for temporary storage. */ @@ -798,7 +802,7 @@ tcp_slowtmr(void) /* If snd_wnd is zero, use persist timer to send 1 byte probes * instead of using the standard retransmission mechanism. */ pcb->persist_cnt++; - if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) { + if (pcb->persist_cnt >= system_get_data_of_array_8(tcp_persist_backoff, pcb->persist_backoff-1)) { pcb->persist_cnt = 0; if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { pcb->persist_backoff++; @@ -819,7 +823,7 @@ tcp_slowtmr(void) /* Double retransmission time-out unless we are trying to * connect to somebody (i.e., we are in SYN_SENT). */ if (pcb->state != SYN_SENT) { - pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx]; + pcb->rto = ((pcb->sa >> 3) + pcb->sv) << system_get_data_of_array_8(tcp_backoff, pcb->nrtx); // if (pcb->rto >= TCP_MAXRTO) // pcb->rto >>= 1; } @@ -1221,7 +1225,7 @@ tcp_alloc(u8_t prio) } } if (pcb != NULL) { - memset(pcb, 0, sizeof(struct tcp_pcb)); //��0 + os_memset(pcb, 0, sizeof(struct tcp_pcb)); //��0 pcb->prio = prio; //�������ȼ� pcb->snd_buf = TCP_SND_BUF; //��ʹ�õķ��ͻ������С pcb->snd_queuelen = 0; //��������ռ�õ�pbuf���� @@ -1259,7 +1263,6 @@ tcp_alloc(u8_t prio) #endif /* LWIP_TCP_KEEPALIVE */ pcb->keep_cnt_sent = 0; //���ķ��ʹ��� - pcb->hold = 0; } return pcb; } @@ -1482,7 +1485,11 @@ tcp_next_iss(void) { static u32_t iss = 6510; - iss += tcp_ticks; /* XXX */ + again: + iss += tcp_ticks; /* XXX */ + if (iss == 0) + goto again; + return iss; } @@ -1511,11 +1518,15 @@ tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr) } #endif /* TCP_CALCULATE_EFF_SEND_MSS */ +#if TCP_DEBUG const char* tcp_debug_state_str(enum tcp_state s) { - return tcp_state_str[s]; + system_get_string_from_flash(tcp_state_str_rodata[s], tcp_state_str, 12); + + return tcp_state_str; } +#endif #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG /** diff --git a/app/lwip/core/tcp_in.c b/app/lwip/core/tcp_in.c index 2aca07d4..80b02177 100644 --- a/app/lwip/core/tcp_in.c +++ b/app/lwip/core/tcp_in.c @@ -59,17 +59,17 @@ /* These variables are global to all functions involved in the input processing of TCP segments. They are set by the tcp_input() function. */ -static struct tcp_seg inseg; //tcp_seg½á¹¹£¬ÃèÊöÊäÈëµÄ±¨ÎĶΠ-static struct tcp_hdr *tcphdr; //±¨ÎĶÎÖÐTCPÊײ¿ -static struct ip_hdr *iphdr; //IPÊý¾Ý°üÊײ¿ -static u32_t seqno, ackno; //TCPÊײ¿ÖÐÐòºÅ×Ö¶ÎÓëÈ·ÈϺÅ×ֶΠ-static u8_t flags; //Êײ¿±êÖ¾×ֶΠ-static u16_t tcplen; //TCP±¨Îij¤¶È +static struct tcp_seg inseg; //tcp_seg�ṹ����������ı��Ķ� +static struct tcp_hdr *tcphdr; //���Ķ���TCP�ײ� +static struct ip_hdr *iphdr; //IP��ݰ��ײ� +static u32_t seqno, ackno; //TCP�ײ�������ֶ���ȷ�Ϻ��ֶ� +static u8_t flags; //�ײ���־�ֶ� +static u16_t tcplen; //TCP���ij��� -static u8_t recv_flags; //µ±Ç°±¨ÎÄ´¦Àí½á¹û -static struct pbuf *recv_data; //±¨ÎĶÎÊý¾Ýpbuf +static u8_t recv_flags; //��ǰ���Ĵ����� +static struct pbuf *recv_data; //���Ķ����pbuf -struct tcp_pcb *tcp_input_pcb; //µ±Ç°±¨ÎÄ¿ØÖÆ¿é +struct tcp_pcb *tcp_input_pcb; //��ǰ���Ŀ��ƿ� /* Forward declarations. */ static err_t tcp_process(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; @@ -89,10 +89,10 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; * @param inp network interface on which this segment was received */ /** - * TCP³õʼ»¯ÊäÈë´¦Àí£¬ÑéÖ¤ÁËTCPÍ·£¬Õâ¸öº¯Êý±»IP²ãµ÷Óà + * TCP��ʼ�����봦�?��֤��TCPͷ���������IP����� - * @²ÎÊýp:´¦Àí½ÓÊÕµÄTCP¶Î(Ö¸ÏòIPÍ·µÄ¸ºÔØ) - * @²ÎÊýinp:½ÓÊնεÄÍøÂç½Ó¿Ú + * @����p:������յ�TCP��(ָ��IPͷ�ĸ���) + * @����inp:���նε�����ӿ� */ void tcp_input(struct pbuf *p, struct netif *inp) @@ -108,15 +108,15 @@ tcp_input(struct pbuf *p, struct netif *inp) PERF_START; - TCP_STATS_INC(tcp.recv); //״̬¼Ó1 - snmp_inc_tcpinsegs(); //tcpÊäÈë¶Î¼Ó1 + TCP_STATS_INC(tcp.recv); //״̬��1 + snmp_inc_tcpinsegs(); //tcp����μ�1 iphdr = (struct ip_hdr *)p->payload;// pointer to the actual data in the buffer /* - *°üÍ·³¤¶È(IHL)£º4룬IPЭÒé°üÍ·µÄ³¤¶È£¬Ö¸Ã÷IPv4ЭÒé°üÍ·³¤¶ÈµÄ×Ö½ÚÊý°üº¬¶àÉÙ¸ö32λ¡£ - *ÓÉÓÚIPv4µÄ°üÍ·¿ÉÄÜ°üº¬¿É±äÊýÁ¿µÄ¿ÉÑ¡ ÏËùÒÔÕâ¸ö×ֶοÉÒÔÓÃÀ´È·¶¨IPv4Êý¾Ý±¨ÖÐÊý¾Ý²¿·ÖµÄÆ«ÒÆÁ¿¡£ - *IPv4°üÍ·µÄ×îС³¤¶ÈÊÇ20¸ö×Ö½Ú£¬Òò´ËIHLÕâ¸ö×ֶεÄ×îСֵÓÃÊ®½øÖƱíʾ¾ÍÊÇ5 (5x4 = 20×Ö½Ú)¡£ - *¾ÍÊÇ˵£¬Ëü±íʾµÄ°üÍ·µÄ×Ü×Ö½ÚÊýÊÇ4×ֽڵı¶Êý + *��ͷ����(IHL)��4�IPЭ���ͷ�ij��ȣ�ָ��IPv4Э���ͷ���ȵ��ֽ������ٸ�32� + *����IPv4�İ�ͷ���ܰ�ɱ������Ŀ�ѡ ���������ֶο�������ȷ��IPv4��ݱ�����ݲ��ֵ�ƫ������ + *IPv4��ͷ����С������20���ֽڣ����IHL����ֶε���Сֵ��ʮ���Ʊ�ʾ����5 (5x4 = 20�ֽ�)�� + *����˵�����ʾ�İ�ͷ�����ֽ�����4�ֽڵı��� */ tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); @@ -128,17 +128,17 @@ tcp_input(struct pbuf *p, struct netif *inp) if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { /* drop short packets */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); - TCP_STATS_INC(tcp.lenerr);//´íÎ󳤶ȼÆÊý - TCP_STATS_INC(tcp.drop);//ÖÕÖ¹¼ÆÊý + TCP_STATS_INC(tcp.lenerr);//���󳤶ȼ��� + TCP_STATS_INC(tcp.drop);//��ֹ���� snmp_inc_tcpinerrs(); - pbuf_free(p);//ÊÍ·Åbuffer + pbuf_free(p);//�ͷ�buffer return; } /* Don't even process incoming broadcasts/multicasts. */ if (ip_addr_isbroadcast(¤t_iphdr_dest, inp) || ip_addr_ismulticast(¤t_iphdr_dest)) { - TCP_STATS_INC(tcp.proterr);//ЭÒé´íÎó¼ÆÊý + TCP_STATS_INC(tcp.proterr);//�������� TCP_STATS_INC(tcp.drop); snmp_inc_tcpinerrs(); pbuf_free(p); @@ -155,7 +155,7 @@ tcp_input(struct pbuf *p, struct netif *inp) #if TCP_DEBUG tcp_debug_print(tcphdr); #endif /* TCP_DEBUG */ - TCP_STATS_INC(tcp.chkerr);//УÑé´íÎó¼ÆÊý + TCP_STATS_INC(tcp.chkerr);//�������� TCP_STATS_INC(tcp.drop); snmp_inc_tcpinerrs(); pbuf_free(p); @@ -165,11 +165,11 @@ tcp_input(struct pbuf *p, struct netif *inp) /* Move the payload pointer in the pbuf so that it points to the TCP data instead of the TCP header. */ - hdrlen = TCPH_HDRLEN(tcphdr);//¼ÆËãÍ·µÄ³¤¶È - if(pbuf_header(p, -(hdrlen * 4))){//¿ç¹ýTCPÍ·£¬·µ»Ø0Ϊ³É¹¦£¬·ñÔò + hdrlen = TCPH_HDRLEN(tcphdr);//����ͷ�ij��� + if(pbuf_header(p, -(hdrlen * 4))){//���TCPͷ������0Ϊ�ɹ������� /* drop short packets */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); - TCP_STATS_INC(tcp.lenerr);//tcp³¤¶È´íÎó¼ÆÊý + TCP_STATS_INC(tcp.lenerr);//tcp���ȴ������ TCP_STATS_INC(tcp.drop); snmp_inc_tcpinerrs(); pbuf_free(p); @@ -177,53 +177,53 @@ tcp_input(struct pbuf *p, struct netif *inp) } /* Convert fields in TCP header to host byte order. */ - tcphdr->src = ntohs(tcphdr->src); //ת»»Ô´µØÖ· - tcphdr->dest = ntohs(tcphdr->dest); //ת»»Ä¿µÄµØÖ· - seqno = tcphdr->seqno = ntohl(tcphdr->seqno); //ת»»ÐòÁкŠ- ackno = tcphdr->ackno = ntohl(tcphdr->ackno); //ת»»Ó¦´ðºÅ - tcphdr->wnd = ntohs(tcphdr->wnd); //ת»»tcp´°¿Ú + tcphdr->src = ntohs(tcphdr->src); //ת��Դ��ַ + tcphdr->dest = ntohs(tcphdr->dest); //ת��Ŀ�ĵ�ַ + seqno = tcphdr->seqno = ntohl(tcphdr->seqno); //ת�����к� + ackno = tcphdr->ackno = ntohl(tcphdr->ackno); //ת��Ӧ��� + tcphdr->wnd = ntohs(tcphdr->wnd); //ת��tcp���� - flags = TCPH_FLAGS(tcphdr);//µÃµ½tcp headerµÄ±êÖ¾ + flags = TCPH_FLAGS(tcphdr);//�õ�tcp header�ı�־ /* - *±êÖ¾£º3λ¿ØÖÆ×ֶΣ¬°üº¬£º - * ±£Áôλ£º1λ - * ²»·Ö¶Îλ£º1λ£¬È¡Öµ£º0£¨ÔÊÐíÊý¾Ý±¨·Ö¶Î£©¡¢1£¨Êý¾Ý±¨²»ÄֶܷΣ© - * ¸ü¶à¶Îλ£º1λ£¬È¡Öµ£º0£¨Êý¾Ý°üºóÃæûÓаü£©¡¢1£¨Êý¾Ý°üºóÃæÓиü¶àµÄ°ü£© + *��־��3λ�����ֶΣ��� + * �����1λ + * ���ֶ�λ��1λ��ȡֵ��0��������ݱ��ֶΣ���1����ݱ����ֶܷΣ� + * �����1λ��ȡֵ��0����ݰ����û�а�1����ݰ�����и��İ� */ - tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);//TCP_FIN ºÍ TCP_SYN ÖÃλ¼Ó1£»·ñÔò¼Ó0 + tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);//TCP_FIN �� TCP_SYN ���1�������0 /* Demultiplex an incoming segment. First, we check if it is destined - for an active connection. Ê×ÏÈ£¬¼ì²éÊÇ·ñÒ»¶¨Òª¼¤»îÒ»¸öÁ¬½Ó*/ + for an active connection. ���ȣ�����Ƿ�һ��Ҫ����һ������*/ //////////////////////////////////////////////////////////////////////////////////////// prev = NULL; - for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {//±éÀú¼¤»îÁбí + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {//������б� LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); if (pcb->remote_port == tcphdr->src && pcb->local_port == tcphdr->dest && ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) && - ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {//¼ì²éÏà¹ØµÄµØÖ· + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {//�����صĵ�ַ /* Move this PCB to the front of the list so that subsequent lookups will be faster (we exploit locality in TCP segment arrivals). */ LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); - if (prev != NULL) {//Èç¹ûÇ°Ò»¸ö½Úµã²»Îª¿Õ + if (prev != NULL) {//���ǰһ���ڵ㲻Ϊ�� prev->next = pcb->next; pcb->next = tcp_active_pcbs; - tcp_active_pcbs = pcb;//pcb²åÈë×îÇ°Ãæ + tcp_active_pcbs = pcb;//pcb������ǰ�� } LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb); break; } - prev = pcb;//prevÖ¸Ïòpcb + prev = pcb;//prevָ��pcb } if (pcb == NULL) { /* If it did not go to an active connection, we check the connections in the TIME-WAIT state. */ - for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {//±éÀúµÈ´ý״̬ϵÄpcb + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {//����ȴ�״̬�µ�pcb LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); if (pcb->remote_port == tcphdr->src && pcb->local_port == tcphdr->dest && @@ -233,7 +233,7 @@ tcp_input(struct pbuf *p, struct netif *inp) of the list since we are not very likely to receive that many segments for connections in TIME-WAIT. */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); - tcp_timewait_input(pcb);//·¢ËÍtcp timewait µÄ°ü + tcp_timewait_input(pcb);//����tcp timewait �� pbuf_free(p); return; } @@ -242,7 +242,7 @@ tcp_input(struct pbuf *p, struct netif *inp) /* Finally, if we still did not get a match, we check all PCBs that are LISTENing for incoming connections. */ prev = NULL; - for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {//±éÀú¼àÌý״̬ÏÂËùÓеÄpcb + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {//�������״̬�����е�pcb if (lpcb->local_port == tcphdr->dest) { #if SO_REUSE if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest)) { @@ -284,7 +284,7 @@ tcp_input(struct pbuf *p, struct netif *inp) } LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); - tcp_listen_input(lpcb);//·¢³ötcp¼àÌýÊý¾Ý°ü + tcp_listen_input(lpcb);//����tcp������ݰ� pbuf_free(p); return; } @@ -318,7 +318,7 @@ tcp_input(struct pbuf *p, struct netif *inp) if (pcb->refused_data != NULL) { /* Notify again application with data previously received. */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); - TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);//pcb½ÓÊÕÊý¾Ý + TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);//pcb������� if (err == ERR_OK) { pcb->refused_data = NULL; } else if ((err == ERR_ABRT) || (tcplen > 0)) { @@ -326,14 +326,14 @@ tcp_input(struct pbuf *p, struct netif *inp) /* Drop incoming packets because pcb is "full" (only if the incoming segment contains data). */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); - TCP_STATS_INC(tcp.drop);//tcp¶ªÆú¼ÆÊý + TCP_STATS_INC(tcp.drop);//tcp������� snmp_inc_tcpinerrs(); pbuf_free(p); return; } } - tcp_input_pcb = pcb;//¼Ç¼µ±Ç°±¨ÎÄ´¦ÀíµÄ¿ØÖÆ¿é - err = tcp_process(pcb);//´¦Àí±¨ÎÄ + tcp_input_pcb = pcb;//��¼��ǰ���Ĵ���Ŀ��ƿ� + err = tcp_process(pcb);//���?�� /* A return value of ERR_ABRT means that tcp_abort() was called and that the pcb has been freed. If so, we don't do anything. */ if (err != ERR_ABRT) { @@ -343,7 +343,7 @@ tcp_input(struct pbuf *p, struct netif *inp) application that the connection is dead before we deallocate the PCB. */ TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); - tcp_pcb_remove(&tcp_active_pcbs, pcb);//ɾ³ý¼¤»îpcbÁбíÖеÄpcb + tcp_pcb_remove(&tcp_active_pcbs, pcb);//ɾ���pcb�б��е�pcb memp_free(MEMP_TCP_PCB, pcb); } else if (recv_flags & TF_CLOSED) { /* The connection has been closed and we will deallocate the @@ -362,13 +362,13 @@ tcp_input(struct pbuf *p, struct netif *inp) called when new send buffer space is available, we call it now. */ if (pcb->acked > 0) { - TCP_EVENT_SENT(pcb, pcb->acked, err);//ÓÐÊý¾Ý±»È·ÈÏ£¬»Øµ÷Óû§µÄsendº¯Êý + TCP_EVENT_SENT(pcb, pcb->acked, err);//����ݱ�ȷ�ϣ��ص��û���send���� if (err == ERR_ABRT) { goto aborted; } } - if (recv_data != NULL) {//ÓÐÊý¾Ý½ÓÊÕµ½ + if (recv_data != NULL) {//����ݽ��յ� LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); if (pcb->flags & TF_RXCLOSED) { /* received data although already closed -> abort (send RST) to @@ -378,12 +378,12 @@ tcp_input(struct pbuf *p, struct netif *inp) goto aborted; } - //PSH±êÖ¾ PSH ½ô¼±Î»¡£ - //µ±PSH=1ʱ£¬ÒªÇó·¢ËÍ·½ÂíÉÏ·¢Ë͸÷ֶΣ¬ - //¶ø½ÓÊÕ·½¾¡¿ìµÄ½«±¨ÎĽ»¸øÓ¦Óò㣬²»×ö¶ÓÁд¦Àí¡£ + //PSH��־ PSH ����� + //��PSH=1ʱ��Ҫ���ͷ����Ϸ��͸÷ֶΣ� + //����շ�����Ľ����Ľ���Ӧ�ò㣬�������д��? if (flags & TCP_PSH) { - recv_data->flags |= PBUF_FLAG_PUSH;//Õâ¶ÎbufferÓ¦¸ÃÁ¢¼´´æÆðÀ´ + recv_data->flags |= PBUF_FLAG_PUSH;//���bufferӦ������������ } /* Notify application that data has been received. */ @@ -414,9 +414,9 @@ tcp_input(struct pbuf *p, struct netif *inp) } } - tcp_input_pcb = NULL;//Çå¿ÕÈ«¾Ö±äÁ¿ + tcp_input_pcb = NULL;//���ȫ�ֱ��� /* Try to send something out. */ - tcp_output(pcb);//³¢ÊÔÊä³ö±¨ÎÄ + tcp_output(pcb);//����������� #if TCP_INPUT_DEBUG #if TCP_DEBUG tcp_debug_print_state(pcb->state); @@ -433,7 +433,7 @@ aborted: /* give up our reference to inseg.p */ if (inseg.p != NULL) { - pbuf_free(inseg.p);//ÊÍ·Åbuffer + pbuf_free(inseg.p);//�ͷ�buffer inseg.p = NULL; } } else { @@ -442,11 +442,11 @@ aborted: sender. */ LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { - TCP_STATS_INC(tcp.proterr);//ЭÒé´íÎó¼ÆÊý - TCP_STATS_INC(tcp.drop);//tcp¶ªÆú¼ÆÊý + TCP_STATS_INC(tcp.proterr);//�������� + TCP_STATS_INC(tcp.drop);//tcp������� tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), - tcphdr->dest, tcphdr->src);//·¢ËÍTCP¸´Î» + tcphdr->dest, tcphdr->src);//����TCP��λ } pbuf_free(p); } @@ -468,8 +468,8 @@ aborted: * involved is passed as a parameter to this function */ /* -*´¦ÓÚLISTEN״̬µÄ¿ØÖÆ¿éµ÷Óøú¯Êý£¬ -*ͨ³£ÊÇ·þÎñÆ÷¶ËÖ÷¶¯´ò¿ªÒ»¸ö¶Ë¿Ú²¢ÕìÌý¿Í»§¶ËSYNÁ¬½ÓÇëÇó +*����LISTEN״̬�Ŀ��ƿ���øú��� +*ͨ���Ƿ�������������һ���˿ڲ�����ͻ���SYN�������� * */ static err_t @@ -489,7 +489,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) tcp_rst(ackno + 1, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(), tcphdr->dest, tcphdr->src); - } else if (flags & TCP_SYN) {//ÊÕµ½SYN±¨ÎÄ + } else if (flags & TCP_SYN) {//�յ�SYN���� LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest)); #if TCP_LISTEN_BACKLOG if (pcb->accepts_pending >= pcb->backlog) { @@ -504,30 +504,31 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) TCP_STATS_INC(tcp.memerr); return ERR_MEM; } - npcb = tcp_alloc(pcb->prio);//´´½¨¿ØÖÆ¿é + npcb = tcp_alloc(pcb->prio);//�������ƿ� /* If a new PCB could not be created (probably due to lack of memory), we don't do anything, but rely on the sender will retransmit the SYN at a time when we have more memory available. */ if (npcb == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); - TCP_STATS_INC(tcp.memerr);//TCPÄÚ´æ´íÎó¼ÆÊý + TCP_STATS_INC(tcp.memerr);//TCP�ڴ������� return ERR_MEM; } + #if TCP_LISTEN_BACKLOG pcb->accepts_pending++; #endif /* TCP_LISTEN_BACKLOG */ /* Set up the new PCB. */ - //¿ØÖÆ¿éÓëÁ¬½ÓÏà¹ØµÄ4¸ö×ֶΠ+ //���ƿ���������ص�4���ֶ� ip_addr_copy(npcb->local_ip, current_iphdr_dest); npcb->local_port = pcb->local_port; ip_addr_copy(npcb->remote_ip, current_iphdr_src); npcb->remote_port = tcphdr->src; - //¿ØÖÆ¿éÖÐÆäÓà×ֶΠ- npcb->state = SYN_RCVD;//ÉèÖÃÁ¬½Ó״̬ - npcb->rcv_nxt = seqno + 1;//ÉèÖÃÏÂÒ»¸ö½ÓÊÕÊý¾ÝÐòºÅ + //���ƿ��������ֶ� + npcb->state = SYN_RCVD;//��������״̬ + npcb->rcv_nxt = seqno + 1;//������һ������������ npcb->rcv_ann_right_edge = npcb->rcv_nxt; - npcb->snd_wnd = tcphdr->wnd;//ÉèÖ÷¢ËÍ´°¿Ú + npcb->snd_wnd = tcphdr->wnd;//���÷��ʹ��� npcb->ssthresh = npcb->snd_wnd; npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ npcb->callback_arg = pcb->callback_arg; @@ -550,11 +551,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) /* Send a SYN|ACK together with the MSS option. */ rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); - if (rc != ERR_OK) {//·¢Éú´íÎó£¬ÊÍ·ÅпØÖÆ¿é + if (rc != ERR_OK) {//��������ͷ��¿��ƿ� tcp_abandon(npcb, 0); return rc; } - return tcp_output(npcb);//·¢Ëͱ¨ÎÄ + return tcp_output(npcb);//���ͱ��� } return ERR_OK; } @@ -569,20 +570,20 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) * involved is passed as a parameter to this function */ /* -*´¦ÓÚTIME_WAIT״̬µÄ¿ØÖÆ¿éµ÷Óøú¯Êý´¦ÀíÊÕµ½µÄ±¨ÎĶΣ¬ -*¸Ã״̬Ï£¬¹Ø±ÕÁ¬½ÓµÄÎÕÊÖ¹ý³ÌÒѾ­½áÊø£¬Õý´¦Óڵȴý2MSL³¬Ê±£¬ -*¸Ã״̬ϵı¨ÎĶàÊýÊÇÁ¬½ÓÖеľÉÊý¾Ý£¬Ö±½Óɾ³ý¼´¿É¡£ -*µ«ÐèÒªÏò·¢ËÍ·½·µ»ØACK±¨ÎÄ +*����TIME_WAIT״̬�Ŀ��ƿ���øú������յ��ı��ĶΣ� +*��״̬�£��ر����ӵ����ֹ���Ѿ��������ڵȴ�2MSL��ʱ�� +*��״̬�µı��Ķ����������еľ���ݣ�ֱ��ɾ��ɡ� +*����Ҫ���ͷ�����ACK���� */ static err_t tcp_timewait_input(struct tcp_pcb *pcb) { - if (flags & TCP_RST) { //RSTÖÃλ£¬Ö±½Ó·µ»Ø + if (flags & TCP_RST) { //RST��λ��ֱ�ӷ��� return ERR_OK; } - if (flags & TCP_SYN) { //°üº¬SYNÎÕÊÖÐÅÏ¢£¬ÇÒÎÕÊÖÊý¾Ý±àºÅÔÚ½ÓÊÕ´°¿ÚÄÚ£¬Ïò·¢ËÍ·½·¢ËÍRST±¨ÎÄ + if (flags & TCP_SYN) { //��SYN������Ϣ����������ݱ���ڽ��մ����ڣ����ͷ�����RST���� if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) { @@ -590,13 +591,13 @@ tcp_timewait_input(struct tcp_pcb *pcb) tcphdr->dest, tcphdr->src); return ERR_OK; } - } else if (flags & TCP_FIN) { //±¨ÎÄ°üº¬FINÎÕÊÖÐÅÏ¢ + } else if (flags & TCP_FIN) { //����FIN������Ϣ - pcb->tmr = tcp_ticks; //¸´Î»µÈ´ý2MSLʱ¼ä£¬¿ØÖÆ¿éÖØеȴý2MSL + pcb->tmr = tcp_ticks; //��λ�ȴ�2MSLʱ�䣬���ƿ����µȴ�2MSL } - if ((tcplen > 0)) { //¶ÔÓÚÓÐÊý¾ÝµÄ±¨ÎÄ»òÕßÔÚ½ÓÊÕ´°¿ÚÍâµÄSYN±¨ÎÄ - pcb->flags |= TF_ACK_NOW;//·¢ËÍÒ»¸öACK±¨ÎÄ + if ((tcplen > 0)) { //��������ݵı��Ļ����ڽ��մ������SYN���� + pcb->flags |= TF_ACK_NOW;//����һ��ACK���� return tcp_output(pcb); } return ERR_OK; @@ -899,13 +900,13 @@ tcp_receive(struct tcp_pcb *pcb) u16_t new_tot_len; int found_dupack = 0; - if (flags & TCP_ACK) {//±¨ÎÄ°üº¬ACK - right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;//·¢ËÍ´°¿Ú + ÐòÁÐÓ¦´ð×îºó´°¿Ú¸üР+ if (flags & TCP_ACK) {//����ACK + right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;//���ʹ��� + ����Ӧ����󴰿ڸ��� // first /* Update window. */ - /*seqno > snd_wl1£»½¨Á¢ÎÕÊÖ¹ý³Ì²ÉÓôËÖÖ¸üÐÂ; - *seqno = snd_wl1²¢ÇÒackno > snd_wl2;´Ëʱ£¬¶Ô·½Ã»Óз¢ËÍÊý¾Ý£¬Ö»ÊÇÊÕµ½Êý¾ÝµÄÈ·ÈÏ; - *ackno = snd_wl2ÇÒ±¨ÎÄÊײ¿ÓбÈsnd_wnd¸ü´óµÄ´°¿Ú.ÖØÐÂÉèÖÃÏàÓ¦Öµ + /*seqno > snd_wl1���������ֹ�̲��ô��ָ���; + *seqno = snd_wl1����ackno > snd_wl2;��ʱ���Է�û�з�����ݣ�ֻ���յ���ݵ�ȷ��; + *ackno = snd_wl2�ұ����ײ��б�snd_wnd���Ĵ���.����������Ӧֵ */ if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || @@ -914,7 +915,7 @@ tcp_receive(struct tcp_pcb *pcb) pcb->snd_wl1 = seqno; pcb->snd_wl2 = ackno; if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) { - pcb->persist_backoff = 0;//³ÖÐø¼ÆʱÆ÷Í˳ö + pcb->persist_backoff = 0;//�����ʱ���˳� } LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd)); #if TCP_WND_DEBUG @@ -930,10 +931,10 @@ tcp_receive(struct tcp_pcb *pcb) /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a * duplicate ack if: - * 1) It doesn't ACK new data ûÓÐÈ·ÈÏÐÂÊý¾Ý - * 2) length of received packet is zero (i.e. no payload) ±¨ÎĶÎÎ×ÈκÎÊý¾Ý - * 3) the advertised window hasn't changed ±¾µØ´°¿ÚûÓиüР- * 4) There is outstanding unacknowledged data (retransmission timer running)ÕýÓÐÊý¾ÝµÈ´ýÈ·ÈÏ + * 1) It doesn't ACK new data û��ȷ������� + * 2) length of received packet is zero (i.e. no payload) ���Ķ����κ���� + * 3) the advertised window hasn't changed ���ش���û�и��� + * 4) There is outstanding unacknowledged data (retransmission timer running)������ݵȴ�ȷ�� * 5) The ACK is == biggest ACK sequence number so far seen (snd_una) ackno = lastack * * If it passes all five, should process as a dupack: @@ -949,7 +950,7 @@ tcp_receive(struct tcp_pcb *pcb) */ /* Clause 1 */ - if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {//ÊÇÖظ´ACK? + if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {//���ظ�ACK? pcb->acked = 0; /* Clause 2 */ if (tcplen == 0) { @@ -968,7 +969,7 @@ tcp_receive(struct tcp_pcb *pcb) if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { pcb->cwnd += pcb->mss; } - } else if (pcb->dupacks == 3) {//ÊÇÖظ´ACK + } else if (pcb->dupacks == 3) {//���ظ�ACK /* Do fast retransmit */ tcp_rexmit_fast(pcb); } @@ -981,7 +982,7 @@ tcp_receive(struct tcp_pcb *pcb) if (!found_dupack) { pcb->dupacks = 0; } - } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){//acknoÔÚlastack+1ºÍsnd_nxtÖ®¼ä£¬ÅжϷ¢ËÍ´°¿ÚÄÚÊý¾Ý + } else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){//ackno��lastack+1��snd_nxt֮�䣬�жϷ��ʹ�������� /* We come here when the ACK acknowledges new data. */ if (pcb->flags & TF_INFR) { @@ -1006,7 +1007,7 @@ tcp_receive(struct tcp_pcb *pcb) /* Update the congestion control variables (cwnd and ssthresh). */ - if (pcb->state >= ESTABLISHED) {//״̬Ϊ½¨Á¢Á¬½Ó±êÖ¾ + if (pcb->state >= ESTABLISHED) {//״̬Ϊ�������ӱ�־ if (pcb->cwnd < pcb->ssthresh) { if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { pcb->cwnd += pcb->mss; @@ -1029,8 +1030,8 @@ tcp_receive(struct tcp_pcb *pcb) /* Remove segment from the unacknowledged list if the incoming ACK acknowlegdes them. - *ÊÍ·Åunacked¶ÓÁÐÉϱ»È·Èϵı¨ÎĶΣ¬ - *Ö±µ½unacked¶ÓÁÐΪ¿ÕÍ£Ö¹*/ + *�ͷ�unacked�����ϱ�ȷ�ϵı��ĶΣ� + *ֱ��unacked����Ϊ��ֹͣ*/ while (pcb->unacked != NULL && TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked), ackno)) { @@ -1039,8 +1040,8 @@ tcp_receive(struct tcp_pcb *pcb) ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked))); - next = pcb->unacked;//pcb unacked±êÖ¾ - pcb->unacked = pcb->unacked->next;//pcb unacked ÏÂÒ»¸ö±êÖ¾ + next = pcb->unacked;//pcb unacked��־ + pcb->unacked = pcb->unacked->next;//pcb unacked ��һ����־ LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); @@ -1049,8 +1050,8 @@ tcp_receive(struct tcp_pcb *pcb) pcb->acked--; } - pcb->snd_queuelen -= pbuf_clen(next->p);//¼ÆËãÁ´±íÀïÃæµÄpbufsÊýÁ¿ - tcp_seg_free(next);//ÊÍ·Åtcp¶Î + pcb->snd_queuelen -= pbuf_clen(next->p);//�������������pbufs���� + tcp_seg_free(next);//�ͷ�tcp�� LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); if (pcb->snd_queuelen != 0) { @@ -1061,10 +1062,10 @@ tcp_receive(struct tcp_pcb *pcb) /* If there's nothing left to acknowledge, stop the retransmit timer, otherwise reset it to start again */ - if(pcb->unacked == NULL) //ÎÞÊý¾ÝµÈ´ýÈ·ÈÏ - pcb->rtime = -1; //Í£Ö¹ÖØ´«¶¨Ê±Æ÷ + if(pcb->unacked == NULL) //����ݵȴ�ȷ�� + pcb->rtime = -1; //ֹͣ�ش���ʱ�� else - pcb->rtime = 0; //¸´Î»ÖØ´«¶¨Ê±Æ÷ + pcb->rtime = 0; //��λ�ش���ʱ�� pcb->polltmr = 0; } else { @@ -1078,7 +1079,7 @@ tcp_receive(struct tcp_pcb *pcb) rationale is that lwIP puts all outstanding segments on the ->unsent list after a retransmission, so these segments may in fact have been sent once. */ - /** unsent¶ÓÁÐÉÏÊÇ·ñÄܱ»acknoÈ·Èϵı¨ÎĶΣ¬ÓÐÔòÊÍ·Å**/ + /** unsent�������Ƿ��ܱ�acknoȷ�ϵı��ĶΣ������ͷ�**/ while (pcb->unsent != NULL && TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { @@ -1086,18 +1087,18 @@ tcp_receive(struct tcp_pcb *pcb) ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + TCP_TCPLEN(pcb->unsent))); - next = pcb->unsent;//pcbδ·¢ËͱêÖ¾ - pcb->unsent = pcb->unsent->next;//δ·¢Ë͵ÄÏÂÒ»¸ö + next = pcb->unsent;//pcbδ���ͱ�־ + pcb->unsent = pcb->unsent->next;//δ���͵���һ�� LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p))); /* Prevent ACK for FIN to generate a sent event */ if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { pcb->acked--; } - pcb->snd_queuelen -= pbuf_clen(next->p);//Á´±íÖÐpbufµÄ¸öÊý - tcp_seg_free(next);//ÊͷŶΠ+ pcb->snd_queuelen -= pbuf_clen(next->p);//������pbuf�ĸ��� + tcp_seg_free(next);//�ͷŶ� LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); - if (pcb->snd_queuelen != 0) {//·¢ËÍÐòÁг¤¶È + if (pcb->snd_queuelen != 0) {//��������� LWIP_ASSERT("tcp_receive: valid queue length", pcb->unacked != NULL || pcb->unsent != NULL); } @@ -1110,15 +1111,15 @@ tcp_receive(struct tcp_pcb *pcb) /* RTT estimation calculations. This is done by checking if the incoming segment acknowledges the segment we use to take a round-trip time measurement. */ - if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {//RTTÕýÔÚ½øÐÐÇҸñ¨ÎĶα»È·ÈÏ + if (pcb->rttest && TCP_SEQ_LT(pcb->rtseq, ackno)) {//RTT���ڽ����Ҹñ��Ķα�ȷ�� /* diff between this shouldn't exceed 32K since this are tcp timer ticks and a round-trip shouldn't be that long... */ - m = (s16_t)(tcp_ticks - pcb->rttest);//¼ÆËãMÖµ + m = (s16_t)(tcp_ticks - pcb->rttest);//����MÖµ LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n", m, m * TCP_SLOW_INTERVAL)); - /* This is taken directly from VJs original code in his paper ¾ßÌå¼ûRTT¼ÆË㹫ʽ*/ + /* This is taken directly from VJs original code in his paper �����RTT���㹫ʽ*/ m = m - (pcb->sa >> 3); pcb->sa += m; if (m < 0) { @@ -1137,7 +1138,7 @@ tcp_receive(struct tcp_pcb *pcb) /* If the incoming segment contains data, we must process it further. */ - if ((tcplen > 0) && (!pcb->hold)) { + if (tcplen > 0) { /* This code basically does three things: +) If the incoming segment contains data that is the next @@ -1188,7 +1189,7 @@ tcp_receive(struct tcp_pcb *pcb) After we are done with adjusting the pbuf pointers we must adjust the ->data pointer in the seg and the segment length.*/ - //È¥µô±¨ÎĶÎÖÐÊý¾Ý±àºÅµÍÓÚrcv_nxtµÄÊý¾Ý + //ȥ�����Ķ�����ݱ�ŵ���rcv_nxt����� off = pcb->rcv_nxt - seqno; p = inseg.p; LWIP_ASSERT("inseg.p != NULL", inseg.p); @@ -1222,8 +1223,8 @@ tcp_receive(struct tcp_pcb *pcb) if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){//seqno < rcv_nxt /* the whole segment is < rcv_nxt */ /* must be a duplicate of a packet that has already been correctly handled */ - //±¨ÎĶÎÖÐËùÓÐÊý¾Ý±àºÅ¾ùСÓÚrcv_nxt£¬Ôò´Ë±¨ÎÄÊÇÖظ´±¨ÎÄ£¬ - //Ö±½ÓÏòÔ´¶ËÏìÓ¦ACK±¨ÎÄ´¦Àí + //���Ķ���������ݱ�ž�С��rcv_nxt����˱������ظ����ģ� + //ֱ����Դ����ӦACK���Ĵ��� LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); tcp_ack_now(pcb); @@ -1234,14 +1235,14 @@ tcp_receive(struct tcp_pcb *pcb) and below rcv_nxt + rcv_wnd) in order to be further processed. */ if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, - pcb->rcv_nxt + pcb->rcv_wnd - 1)){//rcv_nxt < seqno < rcv_nxt + rcv_wnd - 1,¼´Êý¾ÝÔÚ½ÓÊÕ·¶Î§ÄÚ + pcb->rcv_nxt + pcb->rcv_wnd - 1)){//rcv_nxt < seqno < rcv_nxt + rcv_wnd - 1,������ڽ��շ�Χ�� if (pcb->rcv_nxt == seqno) { /* The incoming segment is the next in sequence. We check if we have to trim the end of the segment and update rcv_nxt and pass the data to the application. */ - tcplen = TCP_TCPLEN(&inseg);//¼ÆË㱨ÎĶγ¤¶È + tcplen = TCP_TCPLEN(&inseg);//���㱨�Ķγ��� - if (tcplen > pcb->rcv_wnd) {//³¬¹ý½ÓÊÕ´°¿Ú´óС£¬½«±¨ÎÄβ²¿½Ø¶Ï + if (tcplen > pcb->rcv_wnd) {//������մ��ڴ�С��������β���ض� LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: other end overran receive window" "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", @@ -1408,17 +1409,17 @@ tcp_receive(struct tcp_pcb *pcb) contains less data. */ prev = NULL; - for(next = pcb->ooseq; next != NULL; next = next->next) {//´ÓooseqȡϵÚM¸ö±¨ÎĶΣ¬¸Ã±¨ÎĶηǿգ¬M++ - if (seqno == next->tcphdr->seqno) {//¸Ã±¨ÎĶÎÆðʼ±àºÅ== Òª²åÈëµÄ±¨ÎĶαàºÅ + for(next = pcb->ooseq; next != NULL; next = next->next) {//��ooseqȡ�µ�M�����ĶΣ��ñ��Ķηǿգ�M++ + if (seqno == next->tcphdr->seqno) {//�ñ��Ķ���ʼ���== Ҫ����ı��Ķα�� /* The sequence number of the incoming segment is the same as the sequence number of the segment on ->ooseq. We check the lengths to see which one to discard. */ - if (inseg.len > next->len) {//Òª²åÈëµÄ±¨ÎĶαàºÅ¸ü³¤ + if (inseg.len > next->len) {//Ҫ����ı��Ķα�Ÿ� /* The incoming segment is larger than the old segment. We replace some segments with the new one. */ - cseg = tcp_seg_copy(&inseg);//Òª²åÈëµÄ±¨ÎĶδúÌæµÚM¸ö±¨ÎĶΠ+ cseg = tcp_seg_copy(&inseg);//Ҫ����ı��Ķδ����M�����Ķ� if (cseg != NULL) { if (prev != NULL) { prev->next = cseg; @@ -1524,7 +1525,7 @@ tcp_receive(struct tcp_pcb *pcb) /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){ - tcp_ack_now(pcb);//ÏòÔ´¶Ë·µ»ØÒ»¸öÁ¢¼´È·Èϱ¨ÎÄ + tcp_ack_now(pcb);//��Դ�˷���һ������ȷ�ϱ��� } } } diff --git a/app/lwip/core/tcp_out.c b/app/lwip/core/tcp_out.c index 9227fec5..15867b77 100644 --- a/app/lwip/core/tcp_out.c +++ b/app/lwip/core/tcp_out.c @@ -226,7 +226,16 @@ 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 @@ -333,16 +342,16 @@ tcp_write_checks(struct tcp_pcb *pcb, u16_t len) /** * Write data for sending (but does not send it immediately). - *Á¬½ÓÏòÁíÒ»·½·¢ËÍÊý¾Ý£¬¸Ãº¯Êý¹¹ÔìÒ»¸ö±¨ÎĶβ¢·ÅÔÚ¿ØÖƿ黺³å¶ÓÁÐÖÐ + *��������һ��������ݣ��ú�����һ�����Ķβ����ڿ��ƿ黺������� * It waits in the expectation of more data being sent soon (as * it can send them more efficiently by combining them together). * To prompt the system to send data now, call tcp_output() after * calling tcp_write(). * - * @param pcb Protocol control block for the TCP connection to enqueue data for.ÏàÓ¦Á¬½Ó¿ØÖÆ¿é - * @param arg Pointer to the data to be enqueued for sending.´ý·¢ËÍÊý¾ÝÆðʼµØÖ· - * @param len Data length in bytes´ý·¢ËÍÊý¾Ý³¤¶È - * @param apiflags combination of following flags :Êý¾ÝÊÇ·ñ½øÐп½±´£¬ÒÔ¼°±¨ÎĶÎÊײ¿ÊÇ·ñºÃÉèÖÃPSH±êÖ¾ + * @param pcb Protocol control block for the TCP connection to enqueue data for.��Ӧ���ӿ��ƿ� + * @param arg Pointer to the data to be enqueued for sending.���������ʼ��ַ + * @param len Data length in bytes������ݳ��� + * @param apiflags combination of following flags :����Ƿ���п������Լ����Ķ��ײ��Ƿ������PSH��־ * - TCP_WRITE_FLAG_COPY (0x01) data will be copied into memory belonging to the stack * - TCP_WRITE_FLAG_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent, * @return ERR_OK if enqueued, another err_t on error @@ -883,7 +892,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb) /** * Find out what we can send and send it - *·¢ËÍ¿ØÖƿ黺³å¶ÓÁеı¨ÎĶΠ+ *���Ϳ��ƿ黺����еı��Ķ� * @param pcb Protocol control block for the TCP connection to send data * @return ERR_OK if data has been sent or nothing to send * another err_t on error @@ -899,12 +908,12 @@ tcp_output(struct tcp_pcb *pcb) /* First, check if we are invoked by the TCP input processing code. If so, we do not output anything. Instead, we rely on the input processing code to call us when input processing is done - with. Èç¹û¿ØÖƿ鵱ǰÕýÓÐÊý¾Ý±»´¦Àí£¬Ö±½Ó·µ»Ø*/ + with. �����ƿ鵱ǰ������ݱ����?ֱ�ӷ���*/ if (tcp_input_pcb == pcb) { return ERR_OK; } - wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);//´Ó·¢ËÍ´°¿ÚºÍ×èÈû´°¿ÚȡСÕߵõ½ÓÐЧ·¢ËÍ´°¿Ú + wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);//�ӷ��ʹ��ں������ȡС�ߵõ���Ч���ʹ��� seg = pcb->unsent; @@ -917,13 +926,13 @@ tcp_output(struct tcp_pcb *pcb) if (pcb->flags & TF_ACK_NOW && (seg == NULL || ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { - return tcp_send_empty_ack(pcb);//·¢ËÍÖ»´øACKµÄ±¨ÎĶΠ+ return tcp_send_empty_ack(pcb);//����ֻ��ACK�ı��Ķ� } /* useg should point to last segment on unacked queue */ useg = pcb->unacked; if (useg != NULL) { - for (; useg->next != NULL; useg = useg->next);//µÃµ½Î²²¿ + for (; useg->next != NULL; useg = useg->next);//�õ�β�� } #if TCP_OUTPUT_DEBUG @@ -948,7 +957,7 @@ tcp_output(struct tcp_pcb *pcb) } #endif /* TCP_CWND_DEBUG */ /* data available and window allows it to be sent? - *µ±Ç°ÓÐЧ´°¿ÚÔÊÐí±¨ÎÄ·¢ËÍ£¬Ñ­»··¢Ëͱ¨ÎÄ£¬Ö±ÖÁÌîÂú´°¿Ú*/ + *��ǰ��Ч�������?�ķ��ͣ�ѭ�����ͱ��ģ�ֱ�������*/ while (seg != NULL && ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { LWIP_ASSERT("RST not expected here!", @@ -976,30 +985,30 @@ tcp_output(struct tcp_pcb *pcb) pcb->unsent = seg->next; if (pcb->state != SYN_SENT) { - TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);//ÌîдÊײ¿ACK±êÖ¾ - pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);//Çå³ý±ê־λ + TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);//��д�ײ�ACK��־ + pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);//����־λ } - tcp_output_segment(seg, pcb);//µ÷Óú¯Êý·¢Ëͱ¨ÎĶΠ+ tcp_output_segment(seg, pcb);//���ú����ͱ��Ķ� - snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);//¼ÆËãsnd_nxt + snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);//����snd_nxt if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) { - pcb->snd_nxt = snd_nxt;//¸üÐÂÒª·¢Ë͵ÄÊý¾Ý±àºÅ + pcb->snd_nxt = snd_nxt;//����Ҫ���͵���ݱ�� } - /* put segment on unacknowledged list if length > 0 ·¢³öÈ¥µÄ±¨ÎĶÎÊý¾Ý³¤¶È²»Îª0£¬»òÕß´øÓÐ - * ÓÐSYN¡¢FIN±êÖ¾£¬Ôò½«¸Ã±¨ÎĶμÓÈ뵽δȷÈ϶ÓÁУ¬ÒԱ㳬ʱÖØ´«*/ + /* put segment on unacknowledged list if length > 0 + */ if (TCP_TCPLEN(seg) > 0) { seg->next = NULL; - /* unacked list is empty? Ö±½Ó¹Ò½Ó*/ + /* unacked list is empty? ֱ�ӹҽ�*/ if (pcb->unacked == NULL) { pcb->unacked = seg; useg = seg; - /* unacked list is not empty?½«µ±Ç°±¨ÎÄ°´Ë³Ðò×éÖ¯ÔÚ¶ÓÁÐÖÐ */ + /* unacked list is not empty?����ǰ���İ�˳����֯�ڶ����� */ } else { /* In the case of fast retransmit, the packet should not go to the tail * of the unacked queue, but rather somewhere before it. We need to check for - * this case. -STJ Jul 27, 2004 */ //Èç¹ûµ±Ç°±¨ÎĵÄÐòÁкŵÍÓÚ¶ÓÁÐβ²¿±¨ÎÄÐòÁкţ¬ - //´Ó¶ÓÁÐÊײ¿¿ªÊ¼ + * this case. -STJ Jul 27, 2004 */ //���ǰ���ĵ����кŵ��ڶ���β���������кţ� + //�Ӷ����ײ���ʼ if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) { /* add segment to before tail of unacked list, keeping the list sorted */ struct tcp_seg **cur_seg = &(pcb->unacked); @@ -1009,17 +1018,17 @@ tcp_output(struct tcp_pcb *pcb) } seg->next = (*cur_seg); (*cur_seg) = seg; - } else {//±¨ÎÄÐòºÅ×î¸ß£¬Ôò·ÅÔÚδȷÈ϶ÓÁÐĩβ + } else {//���������ߣ������δȷ�϶���ĩβ /* add segment to tail of unacked list */ useg->next = seg; useg = useg->next; } } /* do not queue empty segments on the unacked list */ - } else {//±¨ÎĶ㤶ÈΪ0£¬Ö±½Óɾ³ý£¬ÎÞÐèÖØ´« + } else {//���Ķγ���Ϊ0��ֱ��ɾ�������ش� tcp_seg_free(seg); } - seg = pcb->unsent;//·¢ËÍÏÂÒ»¸ö±¨ÎĶΠ+ seg = pcb->unsent;//������һ�����Ķ� } #if TCP_OVERSIZE if (pcb->unsent == NULL) { @@ -1028,7 +1037,7 @@ tcp_output(struct tcp_pcb *pcb) } #endif /* TCP_OVERSIZE */ -//·¢ËÍ´°¿ÚÌîÂúµ¼Ö±¨ÎIJ»ÄÜ·¢ËÍ£¬Æô¶¯ÇåÁã´°¿Ú̽²â¡£ +//���ʹ��������±��IJ��ܷ��ͣ��������㴰��̽�⡣ if (seg != NULL && pcb->persist_backoff == 0 && ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) { /* prepare for persist timer */ @@ -1036,7 +1045,7 @@ tcp_output(struct tcp_pcb *pcb) pcb->persist_backoff = 1; } - pcb->flags &= ~TF_NAGLEMEMERR;//ÇåÄÚ´æ´íÎó±êÖ¾ + pcb->flags &= ~TF_NAGLEMEMERR;//���ڴ�����־ return ERR_OK; } @@ -1235,11 +1244,47 @@ void tcp_rexmit_rto(struct tcp_pcb *pcb) { struct tcp_seg *seg; + struct tcp_seg *t0_head = NULL, *t0_tail = NULL; /* keep in unacked */ + struct tcp_seg *t1_head = NULL, *t1_tail = NULL; /* link to unsent */ + bool t0_1st = true, t1_1st = true; if (pcb->unacked == NULL) { return; } +#if 1 /* by Snake: resolve the bug of pbuf reuse */ + seg = pcb->unacked; + while (seg != NULL) { + if (seg->p->eb) { + if (t0_1st) { + t0_head = t0_tail = seg; + t0_1st = false; + } else { + t0_tail->next = seg; + t0_tail = seg; + } + seg = seg->next; + t0_tail->next = NULL; + } else { + if (t1_1st) { + t1_head = t1_tail = seg; + t1_1st = false; + } else { + t1_tail->next = seg; + t1_tail = seg; + } + seg = seg->next; + t1_tail->next = NULL; + } + } + if (t1_head && t1_tail) { + t1_tail->next = pcb->unsent; + pcb->unsent = t1_head; + } + pcb->unacked = t0_head; + +#else + /* Move all unacked segments to the head of the unsent queue */ for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); /* concatenate unsent queue after unacked queue */ @@ -1248,6 +1293,7 @@ tcp_rexmit_rto(struct tcp_pcb *pcb) pcb->unsent = pcb->unacked; /* unacked queue is now empty */ pcb->unacked = NULL; +#endif /* increment number of retransmissions */ ++pcb->nrtx; diff --git a/app/lwip/core/timers.c b/app/lwip/core/timers.c index b240024a..84ba657d 100644 --- a/app/lwip/core/timers.c +++ b/app/lwip/core/timers.c @@ -389,9 +389,9 @@ sys_check_timeouts(void) if (next_timeout) { /* this cares for wraparounds */ if (timer2_ms_flag == 0) { - diff = LWIP_U32_DIFF(now, timeouts_last_time)/((CPU_CLK_FREQ>>4)/1000); + diff = LWIP_U32_DIFF(now, timeouts_last_time)/((APB_CLK_FREQ>>4)/1000); } else { - diff = LWIP_U32_DIFF(now, timeouts_last_time)/((CPU_CLK_FREQ>>8)/1000); + diff = LWIP_U32_DIFF(now, timeouts_last_time)/((APB_CLK_FREQ>>8)/1000); } do { diff --git a/app/lwip/core/udp.c b/app/lwip/core/udp.c index 83386cc0..b43e0db8 100644 --- a/app/lwip/core/udp.c +++ b/app/lwip/core/udp.c @@ -148,6 +148,15 @@ udp_input(struct pbuf *p, struct netif *inp) pcb = inp->dhcp->pcb; } } + } else if (dest == DHCP_SERVER_PORT) { + if (src == DHCP_CLIENT_PORT) { + if ( inp->dhcps_pcb != NULL ) { + if ((ip_addr_isany(&inp->dhcps_pcb->local_ip) || + ip_addr_cmp(&(inp->dhcps_pcb->local_ip), ¤t_iphdr_dest))) { + pcb = inp->dhcps_pcb; + } + } + } } } else #endif /* LWIP_DHCP */ @@ -935,7 +944,7 @@ udp_new(void) * which means checksum is generated over the whole datagram per default * (recommended as default by RFC 3828). */ /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct udp_pcb)); + os_memset(pcb, 0, sizeof(struct udp_pcb)); pcb->ttl = UDP_TTL; } return pcb; diff --git a/app/lwip/netif/Makefile b/app/lwip/netif/Makefile index 9e5e810a..f03613f6 100644 --- a/app/lwip/netif/Makefile +++ b/app/lwip/netif/Makefile @@ -1,46 +1,46 @@ - -############################################################# -# Required variables for each makefile -# Discard this section from all parent makefiles -# Expected variables (with automatic defaults): -# CSRCS (all "C" files in the dir) -# SUBDIRS (all subdirs with a Makefile) -# GEN_LIBS - list of libs to be generated () -# GEN_IMAGES - list of images to be generated () -# COMPONENTS_xxx - a list of libs/objs in the form -# subdir/lib to be extracted and rolled up into -# a generated lib/image xxx.a () -# -ifndef PDIR - -GEN_LIBS = liblwipnetif.a - -endif - - -############################################################# -# Configuration i.e. compile options etc. -# Target specific stuff (defines etc.) goes in here! -# Generally values applying to a tree are captured in the -# makefile at its root level - these are then overridden -# for a subtree within the makefile rooted therein -# -#DEFINES += - -############################################################# -# Recursion Magic - Don't touch this!! -# -# Each subtree potentially has an include directory -# corresponding to the common APIs applicable to modules -# rooted at that subtree. Accordingly, the INCLUDE PATH -# of a module can only contain the include directories up -# its parent path, and not its siblings -# -# Required for each makefile to inherit from the parent -# - -INCLUDES := $(INCLUDES) -I $(PDIR)include -INCLUDES += -I ./ -PDIR := ../$(PDIR) -sinclude $(PDIR)Makefile - + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR + +GEN_LIBS = liblwipnetif.a + +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/lwip/netif/etharp.c b/app/lwip/netif/etharp.c index efc0979d..264c1b39 100644 --- a/app/lwip/netif/etharp.c +++ b/app/lwip/netif/etharp.c @@ -72,6 +72,9 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}}; * (240 * 5) seconds = 20 minutes. */ #define ARP_MAXAGE 240 +/** Re-request a used ARP entry 1 minute before it would expire to prevent + * breaking a steadily used connection because the ARP entry timed out. */ +#define ARP_AGE_REREQUEST_USED (ARP_MAXAGE - 12) /** the time an ARP entry stays pending after first request, * for ARP_TMR_INTERVAL = 5000, this is * (2 * 5) seconds = 10 seconds. @@ -86,7 +89,8 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}}; enum etharp_state { ETHARP_STATE_EMPTY = 0, ETHARP_STATE_PENDING, - ETHARP_STATE_STABLE + ETHARP_STATE_STABLE, + ETHARP_STATE_STABLE_REREQUESTING }; struct etharp_entry { @@ -219,10 +223,15 @@ etharp_tmr(void) (arp_table[i].ctime >= ARP_MAXPENDING))) { /* pending or stable entry has become old! */ LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", - arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + arp_table[i].state >= ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); /* clean up entries that have just been expired */ free_entry(i); } + else if (arp_table[i].state == ETHARP_STATE_STABLE_REREQUESTING) { + /* Reset state to stable, so that the next transmitted packet will + re-send an ARP request. */ + arp_table[i].state = ETHARP_STATE_STABLE; + } #if ARP_QUEUEING /* still pending entry? (not expired) */ if (arp_table[i].state == ETHARP_STATE_PENDING) { @@ -288,8 +297,8 @@ find_entry(ip_addr_t *ipaddr, u8_t flags) /* remember first empty entry */ empty = i; } else if (state != ETHARP_STATE_EMPTY) { - LWIP_ASSERT("state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE", - state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE); + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state >= ETHARP_STATE_STABLE); /* if given, does IP address match IP address in ARP entry? */ if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching entry %"U16_F"\n", (u16_t)i)); @@ -313,7 +322,7 @@ find_entry(ip_addr_t *ipaddr, u8_t flags) } } /* stable entry? */ - } else if (state == ETHARP_STATE_STABLE) { + } else if (state >= ETHARP_STATE_STABLE) { #if ETHARP_SUPPORT_STATIC_ENTRIES /* don't record old_stable for static entries since they never expire */ if (arp_table[i].static_entry == 0) @@ -608,7 +617,7 @@ etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, LWIP_UNUSED_ARG(netif); i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); - if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) { + if((i >= 0) && (arp_table[i].state >= ETHARP_STATE_STABLE)) { *eth_ret = &arp_table[i].ethaddr; *ip_ret = &arp_table[i].ipaddr; return i; @@ -854,6 +863,28 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) pbuf_free(p); } +/** Just a small helper function that sends a pbuf to an ethernet address + * in the arp_table specified by the index 'arp_idx'. + */ +static err_t ICACHE_FLASH_ATTR +etharp_output_to_arp_index(struct netif *netif, struct pbuf *q, u8_t arp_idx) +{ + LWIP_ASSERT("arp_table[arp_idx].state >= ETHARP_STATE_STABLE", + arp_table[arp_idx].state >= ETHARP_STATE_STABLE); + /* if arp table entry is about to expire: re-request it, + but only if its state is ETHARP_STATE_STABLE to prevent flooding the + network with ARP requests if this address is used frequently. */ + if ((arp_table[arp_idx].state == ETHARP_STATE_STABLE) && + (arp_table[arp_idx].ctime >= ARP_AGE_REREQUEST_USED)) { + if (etharp_request(netif, &arp_table[arp_idx].ipaddr) == ERR_OK) { + arp_table[arp_idx].state = ETHARP_STATE_STABLE_REREQUESTING; + } + } + + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), + &arp_table[arp_idx].ethaddr); +} + /** * Resolve and fill-in Ethernet address header for outgoing IP packet. * @@ -908,7 +939,9 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) dest = &mcastaddr; /* unicast destination IP address? */ } else { - /* outside local network? */ + s8_t i; + /* outside local network? if so, this can neither be a global broadcast nor + a subnet broadcast. */ if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) && !ip_addr_islinklocal(ipaddr)) { #if LWIP_AUTOIP @@ -938,17 +971,26 @@ etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) u8_t etharp_cached_entry = *(netif->addr_hint); if (etharp_cached_entry < ARP_TABLE_SIZE) { #endif /* LWIP_NETIF_HWADDRHINT */ - if ((arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) && + if ((arp_table[etharp_cached_entry].state >= ETHARP_STATE_STABLE) && (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr))) { /* the per-pcb-cached entry is stable and the right one! */ ETHARP_STATS_INC(etharp.cachehit); - return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), - &arp_table[etharp_cached_entry].ethaddr); + return etharp_output_to_arp_index(netif, q, etharp_cached_entry); } #if LWIP_NETIF_HWADDRHINT } } #endif /* LWIP_NETIF_HWADDRHINT */ + /* find stable entry: do this here since this is a critical path for + throughput and etharp_find_entry() is kind of slow */ + for (i = 0; i < ARP_TABLE_SIZE; i++) { + if ((arp_table[i].state >= ETHARP_STATE_STABLE) && + (ip_addr_cmp(ipaddr, &arp_table[i].ipaddr))) { + /* found an existing, stable entry */ + ETHARP_SET_HINT(netif, i); + return etharp_output_to_arp_index(netif, q, i); + } + } /* queue on destination Ethernet address belonging to ipaddr */ return etharp_query(netif, ipaddr, q); } @@ -1028,7 +1070,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) /* { i is either a STABLE or (new or existing) PENDING entry } */ LWIP_ASSERT("arp_table[i].state == PENDING or STABLE", ((arp_table[i].state == ETHARP_STATE_PENDING) || - (arp_table[i].state == ETHARP_STATE_STABLE))); + (arp_table[i].state >= ETHARP_STATE_STABLE))); /* do we have a pending entry? or an implicit query request? */ if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) { @@ -1048,7 +1090,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) /* packet given? */ LWIP_ASSERT("q != NULL", q != NULL); /* stable entry? */ - if (arp_table[i].state == ETHARP_STATE_STABLE) { + if (arp_table[i].state >= ETHARP_STATE_STABLE) { /* we have a valid IP->Ethernet address mapping */ ETHARP_SET_HINT(netif, i); /* send the packet */ @@ -1092,20 +1134,30 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) /* allocate a new arp queue entry */ new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); if (new_entry != NULL) { + unsigned int qlen = 0; new_entry->next = 0; new_entry->p = p; if(arp_table[i].q != NULL) { /* queue was already existent, append the new entry to the end */ struct etharp_q_entry *r; r = arp_table[i].q; + qlen++; while (r->next != NULL) { r = r->next; + qlen++; } r->next = new_entry; } else { /* queue did not exist, first item in queue */ arp_table[i].q = new_entry; } + if(qlen >= 3) { + struct etharp_q_entry *old; + old = arp_table[i].q; + arp_table[i].q = arp_table[i].q->next; + pbuf_free(old->p); + memp_free(MEM_ARP_QUEUE, old); + } LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); result = ERR_OK; } else {