Commit a33e3a4a authored by Vowstar's avatar Vowstar
Browse files

Merge pull request #687 from DiUS/dev140

Major upgrade to SDK 1.4.0 & open LWIP
parents 093a8959 8fba0f47
...@@ -84,6 +84,10 @@ ...@@ -84,6 +84,10 @@
#include <string.h> #include <string.h>
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/** Default for DHCP_GLOBAL_XID is 0xABCD0000 /** Default for DHCP_GLOBAL_XID is 0xABCD0000
* This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g. * This can be changed by defining DHCP_GLOBAL_XID and DHCP_GLOBAL_XID_HEADER, e.g.
* #define DHCP_GLOBAL_XID_HEADER "stdlib.h" * #define DHCP_GLOBAL_XID_HEADER "stdlib.h"
...@@ -129,7 +133,7 @@ u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; ...@@ -129,7 +133,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_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0)
#define dhcp_got_option(dhcp, idx) (dhcp_rx_options_given[idx] = 1) #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_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_get_option_value(dhcp, idx) (dhcp_rx_options_val[idx])
#define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val)) #define dhcp_set_option_value(dhcp, idx, val) (dhcp_rx_options_val[idx] = (val))
...@@ -288,16 +292,24 @@ dhcp_select(struct netif *netif) ...@@ -288,16 +292,24 @@ dhcp_select(struct netif *netif)
dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4); dhcp_option(dhcp, DHCP_OPTION_SERVER_ID, 4);
dhcp_option_long(dhcp, ntohl(ip4_addr_get_u32(&dhcp->server_ip_addr))); 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_SUBNET_MASK);
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); 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 LWIP_NETIF_HOSTNAME
if (netif->hostname != NULL) { if (netif->hostname != NULL) {
const char *p = (const char*)netif->hostname; 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) { if (namelen > 0) {
LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
...@@ -369,6 +381,15 @@ dhcp_fine_tmr() ...@@ -369,6 +381,15 @@ dhcp_fine_tmr()
while (netif != NULL) { while (netif != NULL) {
/* only act on DHCP configured interfaces */ /* only act on DHCP configured interfaces */
if (netif->dhcp != NULL) { if (netif->dhcp != NULL) {
/*add DHCP retries processing by LiuHan*/
if (DHCP_MAXRTX != 0) {
if (netif->dhcp->tries >= DHCP_MAXRTX){
os_printf("DHCP timeout\n");
if (netif->dhcp_event != NULL)
netif->dhcp_event();
break;
}
}
/* timer is active (non zero), and is about to trigger now */ /* timer is active (non zero), and is about to trigger now */
if (netif->dhcp->request_timeout > 1) { if (netif->dhcp->request_timeout > 1) {
netif->dhcp->request_timeout--; netif->dhcp->request_timeout--;
...@@ -384,6 +405,7 @@ dhcp_fine_tmr() ...@@ -384,6 +405,7 @@ dhcp_fine_tmr()
/* proceed to next network interface */ /* proceed to next network interface */
netif = netif->next; netif = netif->next;
} }
} }
/** /**
...@@ -587,7 +609,7 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) ...@@ -587,7 +609,7 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL);
/* clear data structure */ /* clear data structure */
memset(dhcp, 0, sizeof(struct dhcp)); os_memset(dhcp, 0, sizeof(struct dhcp));
/* dhcp_set_state(&dhcp, DHCP_OFF); */ /* dhcp_set_state(&dhcp, DHCP_OFF); */
netif->dhcp = dhcp; netif->dhcp = dhcp;
} }
...@@ -626,7 +648,6 @@ dhcp_start(struct netif *netif) ...@@ -626,7 +648,6 @@ dhcp_start(struct netif *netif)
{ {
struct dhcp *dhcp; struct dhcp *dhcp;
err_t result = ERR_OK; err_t result = ERR_OK;
LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;); LWIP_ERROR("netif != NULL", (netif != NULL), return ERR_ARG;);
dhcp = netif->dhcp; 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)); 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 +689,7 @@ dhcp_start(struct netif *netif) ...@@ -668,7 +689,7 @@ dhcp_start(struct netif *netif)
} }
/* clear data structure */ /* clear data structure */
memset(dhcp, 0, sizeof(struct dhcp)); os_memset(dhcp, 0, sizeof(struct dhcp));
/* dhcp_set_state(&dhcp, DHCP_OFF); */ /* dhcp_set_state(&dhcp, DHCP_OFF); */
/* allocate UDP PCB */ /* allocate UDP PCB */
dhcp->pcb = udp_new(); dhcp->pcb = udp_new();
...@@ -713,7 +734,7 @@ dhcp_inform(struct netif *netif) ...@@ -713,7 +734,7 @@ dhcp_inform(struct netif *netif)
LWIP_ERROR("netif != NULL", (netif != NULL), return;); 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); dhcp_set_state(&dhcp, DHCP_INFORM);
if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) { if ((netif->dhcp != NULL) && (netif->dhcp->pcb != NULL)) {
...@@ -881,11 +902,32 @@ dhcp_discover(struct netif *netif) ...@@ -881,11 +902,32 @@ dhcp_discover(struct netif *netif)
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); 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_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_SUBNET_MASK);
dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER); dhcp_option_byte(dhcp, DHCP_OPTION_ROUTER);
dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST); dhcp_option_byte(dhcp, DHCP_OPTION_BROADCAST);
dhcp_option_byte(dhcp, DHCP_OPTION_DNS_SERVER); 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); dhcp_option_trailer(dhcp);
...@@ -994,6 +1036,12 @@ dhcp_bind(struct netif *netif) ...@@ -994,6 +1036,12 @@ dhcp_bind(struct netif *netif)
} }
#endif /* LWIP_DHCP_AUTOIP_COOP */ #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", LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): IP: 0x%08"X32_F"\n",
ip4_addr_get_u32(&dhcp->offered_ip_addr))); ip4_addr_get_u32(&dhcp->offered_ip_addr)));
netif_set_ipaddr(netif, &dhcp->offered_ip_addr); netif_set_ipaddr(netif, &dhcp->offered_ip_addr);
...@@ -1002,12 +1050,14 @@ dhcp_bind(struct netif *netif) ...@@ -1002,12 +1050,14 @@ dhcp_bind(struct netif *netif)
netif_set_netmask(netif, &sn_mask); netif_set_netmask(netif, &sn_mask);
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n", LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_STATE, ("dhcp_bind(): GW: 0x%08"X32_F"\n",
ip4_addr_get_u32(&gw_addr))); 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); netif_set_gw(netif, &gw_addr);
/* bring the interface up */ /* bring the interface up */
netif_set_up(netif); 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 */ /* netif is now bound to DHCP leased address */
dhcp_set_state(dhcp, DHCP_BOUND); dhcp_set_state(dhcp, DHCP_BOUND);
} }
...@@ -1035,7 +1085,7 @@ dhcp_renew(struct netif *netif) ...@@ -1035,7 +1085,7 @@ dhcp_renew(struct netif *netif)
#if LWIP_NETIF_HOSTNAME #if LWIP_NETIF_HOSTNAME
if (netif->hostname != NULL) { if (netif->hostname != NULL) {
const char *p = (const char*)netif->hostname; 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) { if (namelen > 0) {
LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
...@@ -1098,7 +1148,7 @@ dhcp_rebind(struct netif *netif) ...@@ -1098,7 +1148,7 @@ dhcp_rebind(struct netif *netif)
#if LWIP_NETIF_HOSTNAME #if LWIP_NETIF_HOSTNAME
if (netif->hostname != NULL) { if (netif->hostname != NULL) {
const char *p = (const char*)netif->hostname; 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) { if (namelen > 0) {
LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255); LWIP_ASSERT("DHCP: hostname is too long!", namelen < 255);
dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen); dhcp_option(dhcp, DHCP_OPTION_HOSTNAME, namelen);
...@@ -1245,7 +1295,6 @@ dhcp_stop(struct netif *netif) ...@@ -1245,7 +1295,6 @@ dhcp_stop(struct netif *netif)
dhcp = netif->dhcp; dhcp = netif->dhcp;
/* Remove the flag that says this netif is handled by DHCP. */ /* Remove the flag that says this netif is handled by DHCP. */
netif->flags &= ~NETIF_FLAG_DHCP; netif->flags &= ~NETIF_FLAG_DHCP;
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n")); LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_stop()\n"));
/* netif is DHCP configured? */ /* netif is DHCP configured? */
if (dhcp != NULL) { if (dhcp != NULL) {
......
...@@ -83,9 +83,13 @@ ...@@ -83,9 +83,13 @@
#include <string.h> #include <string.h>
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/** DNS server IP address */ /** DNS server IP address */
#ifndef DNS_SERVER_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 #endif
/** DNS server port address */ /** DNS server port address */
...@@ -173,7 +177,7 @@ struct dns_table_entry { ...@@ -173,7 +177,7 @@ struct dns_table_entry {
u8_t seqno; u8_t seqno;
u8_t err; u8_t err;
u32_t ttl; u32_t ttl;
char *name; char name[DNS_MAX_NAME_LENGTH];
ip_addr_t ipaddr; ip_addr_t ipaddr;
/* pointer to callback on DNS query done */ /* pointer to callback on DNS query done */
dns_found_callback found; dns_found_callback found;
...@@ -221,9 +225,9 @@ static u8_t dns_seqno; ...@@ -221,9 +225,9 @@ static u8_t dns_seqno;
static struct dns_table_entry dns_table[DNS_TABLE_SIZE]; static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
static ip_addr_t dns_servers[DNS_MAX_SERVERS]; static ip_addr_t dns_servers[DNS_MAX_SERVERS];
/** Contiguous buffer for processing responses */ /** 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_payload;
static u8_t dns_random;
/** /**
* Initialize the resolver: set up the UDP pcb and configure the default server * Initialize the resolver: set up the UDP pcb and configure the default server
* (DNS_SERVER_ADDRESS). * (DNS_SERVER_ADDRESS).
...@@ -233,7 +237,7 @@ dns_init() ...@@ -233,7 +237,7 @@ dns_init()
{ {
ip_addr_t dnsserver; 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 */ /* initialize default DNS server address */
DNS_SERVER_ADDRESS(&dnsserver); DNS_SERVER_ADDRESS(&dnsserver);
...@@ -299,7 +303,7 @@ dns_getserver(u8_t numdns) ...@@ -299,7 +303,7 @@ dns_getserver(u8_t numdns)
* The DNS resolver client timer - handle retries and timeouts and should * The DNS resolver client timer - handle retries and timeouts and should
* be called every DNS_TMR_INTERVAL milliseconds (every second by default). * be called every DNS_TMR_INTERVAL milliseconds (every second by default).
*/ */
void void ICACHE_FLASH_ATTR
dns_tmr(void) dns_tmr(void)
{ {
if (dns_pcb != NULL) { if (dns_pcb != NULL) {
...@@ -321,7 +325,7 @@ dns_init_local() ...@@ -321,7 +325,7 @@ dns_init_local()
for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) { for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
struct local_hostlist_entry *init_entry = &local_hostlist_init[i]; struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL); 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); LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
LWIP_ASSERT("mem-error in dns_init_local", entry != NULL); LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
...@@ -416,7 +420,7 @@ dns_local_addhost(const char *hostname, const ip_addr_t *addr) ...@@ -416,7 +420,7 @@ dns_local_addhost(const char *hostname, const ip_addr_t *addr)
struct local_hostlist_entry *entry; struct local_hostlist_entry *entry;
size_t namelen; size_t namelen;
LWIP_ASSERT("invalid host name (NULL)", hostname != NULL); 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); LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST); entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
if (entry == NULL) { if (entry == NULL) {
...@@ -566,7 +570,7 @@ dns_send(u8_t numdns, const char* name, u8_t id) ...@@ -566,7 +570,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
char *query, *nptr; char *query, *nptr;
const char *pHostname; const char *pHostname;
u8_t n; u8_t n;
dns_random = os_random()%250;
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n", LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
(u16_t)(numdns), name)); (u16_t)(numdns), name));
LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS); LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
...@@ -579,8 +583,8 @@ dns_send(u8_t numdns, const char* name, u8_t id) ...@@ -579,8 +583,8 @@ dns_send(u8_t numdns, const char* name, u8_t id)
LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
/* fill dns header */ /* fill dns header */
hdr = (struct dns_hdr*)p->payload; hdr = (struct dns_hdr*)p->payload;
memset(hdr, 0, SIZEOF_DNS_HDR); os_memset(hdr, 0, SIZEOF_DNS_HDR);
hdr->id = htons(id); hdr->id = htons(id + dns_random);
hdr->flags1 = DNS_FLAG1_RD; hdr->flags1 = DNS_FLAG1_RD;
hdr->numquestions = PP_HTONS(1); hdr->numquestions = PP_HTONS(1);
query = (char*)hdr + SIZEOF_DNS_HDR; query = (char*)hdr + SIZEOF_DNS_HDR;
...@@ -673,8 +677,6 @@ dns_check_entry(u8_t i) ...@@ -673,8 +677,6 @@ dns_check_entry(u8_t i)
if (pEntry->found) if (pEntry->found)
(*pEntry->found)(pEntry->name, NULL, pEntry->arg); (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
/* flush this entry */ /* flush this entry */
mem_free (pEntry->name);
pEntry->name = NULL;
pEntry->state = DNS_STATE_UNUSED; pEntry->state = DNS_STATE_UNUSED;
pEntry->found = NULL; pEntry->found = NULL;
break; break;
...@@ -699,8 +701,6 @@ dns_check_entry(u8_t i) ...@@ -699,8 +701,6 @@ dns_check_entry(u8_t i)
if (--pEntry->ttl == 0) { if (--pEntry->ttl == 0) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name)); LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": flush\n", pEntry->name));
/* flush this entry */ /* flush this entry */
mem_free (pEntry->name);
pEntry->name = NULL;
pEntry->state = DNS_STATE_UNUSED; pEntry->state = DNS_STATE_UNUSED;
pEntry->found = NULL; pEntry->found = NULL;
} }
...@@ -743,6 +743,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t ...@@ -743,6 +743,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
struct dns_table_entry *pEntry; struct dns_table_entry *pEntry;
u16_t nquestions, nanswers; 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(arg);
LWIP_UNUSED_ARG(pcb); LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(addr); LWIP_UNUSED_ARG(addr);
...@@ -767,6 +770,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t ...@@ -767,6 +770,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. */ /* The ID in the DNS header should be our entry into the name table. */
hdr = (struct dns_hdr*)dns_payload; hdr = (struct dns_hdr*)dns_payload;
i = htons(hdr->id); i = htons(hdr->id);
i = i - dns_random;
if (i < DNS_TABLE_SIZE) { if (i < DNS_TABLE_SIZE) {
pEntry = &dns_table[i]; pEntry = &dns_table[i];
if(pEntry->state == DNS_STATE_ASKING) { if(pEntry->state == DNS_STATE_ASKING) {
...@@ -843,14 +847,13 @@ responseerr: ...@@ -843,14 +847,13 @@ responseerr:
(*pEntry->found)(pEntry->name, NULL, pEntry->arg); (*pEntry->found)(pEntry->name, NULL, pEntry->arg);
} }
/* flush this entry */ /* flush this entry */
mem_free (pEntry->name);
pEntry->name = NULL;
pEntry->state = DNS_STATE_UNUSED; pEntry->state = DNS_STATE_UNUSED;
pEntry->found = NULL; pEntry->found = NULL;
memerr: memerr:
/* free pbuf */ /* free pbuf */
pbuf_free(p); pbuf_free(p);
os_free(dns_payload_buffer);
return; return;
} }
...@@ -904,16 +907,11 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) ...@@ -904,16 +907,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))); LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i)));
/* fill the entry */ /* 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->state = DNS_STATE_NEW;
pEntry->seqno = dns_seqno++; pEntry->seqno = dns_seqno++;
pEntry->found = found; pEntry->found = found;
pEntry->arg = callback_arg; pEntry->arg = callback_arg;
mem_free (pEntry->name); namelen = LWIP_MIN(os_strlen(name), DNS_MAX_NAME_LENGTH-1);
pEntry->name = namebuf;
MEMCPY(pEntry->name, name, namelen); MEMCPY(pEntry->name, name, namelen);
pEntry->name[namelen] = 0; pEntry->name[namelen] = 0;
...@@ -952,7 +950,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun ...@@ -952,7 +950,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun
* or invalid hostname or invalid hostname length */ * or invalid hostname or invalid hostname length */
if ((dns_pcb == NULL) || (addr == NULL) || if ((dns_pcb == NULL) || (addr == NULL) ||
(!hostname) || (!hostname[0]) || (!hostname) || (!hostname[0]) ||
(strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { (os_strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
return ERR_ARG; return ERR_ARG;
} }
......
...@@ -99,18 +99,18 @@ ...@@ -99,18 +99,18 @@
//#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0)) //#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" // #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
//#endif //#endif
#if (LWIP_TCP && (TCP_WND > 0xffff)) //#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" // #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 //#endif
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) #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" #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 #endif
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) #if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
#endif #endif
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) //#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" // #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 //#endif
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)) #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" #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
#endif #endif
...@@ -259,6 +259,11 @@ lwip_sanity_check(void) ...@@ -259,6 +259,11 @@ lwip_sanity_check(void)
void void
lwip_init(void) lwip_init(void)
{ {
MEMP_NUM_TCP_PCB = 5;
TCP_WND = (4 * TCP_MSS);
TCP_MAXRTX = 12;
TCP_SYNMAXRTX = 6;
/* Sanity check user-configurable values */ /* Sanity check user-configurable values */
lwip_sanity_check(); lwip_sanity_check();
...@@ -294,7 +299,6 @@ lwip_init(void) ...@@ -294,7 +299,6 @@ lwip_init(void)
#endif /* LWIP_UDP */ #endif /* LWIP_UDP */
#if LWIP_TCP #if LWIP_TCP
MEMP_NUM_TCP_PCB = 5;
tcp_init(); tcp_init();
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
......
############################################################# #############################################################
# Required variables for each makefile # Required variables for each makefile
# Discard this section from all parent makefiles # Discard this section from all parent makefiles
# Expected variables (with automatic defaults): # Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir) # CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile) # SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated () # GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated () # GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form # COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into # subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a () # a generated lib/image xxx.a ()
# #
ifndef PDIR ifndef PDIR
GEN_LIBS = liblwipipv4.a GEN_LIBS = liblwipipv4.a
endif endif
############################################################# #############################################################
# Configuration i.e. compile options etc. # Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here! # Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the # Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden # makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein # for a subtree within the makefile rooted therein
# #
#DEFINES += #DEFINES +=
############################################################# #############################################################
# Recursion Magic - Don't touch this!! # Recursion Magic - Don't touch this!!
# #
# Each subtree potentially has an include directory # Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules # corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH # rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up # of a module can only contain the include directories up
# its parent path, and not its siblings # its parent path, and not its siblings
# #
# Required for each makefile to inherit from the parent # Required for each makefile to inherit from the parent
# #
INCLUDES := $(INCLUDES) -I $(PDIR)include INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./ INCLUDES += -I ./
PDIR := ../$(PDIR) PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile sinclude $(PDIR)Makefile
...@@ -145,7 +145,7 @@ autoip_set_struct(struct netif *netif, struct autoip *autoip) ...@@ -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); LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL);
/* clear data structure */ /* clear data structure */
memset(autoip, 0, sizeof(struct autoip)); os_memset(autoip, 0, sizeof(struct autoip));
/* autoip->state = AUTOIP_STATE_OFF; */ /* autoip->state = AUTOIP_STATE_OFF; */
netif->autoip = autoip; netif->autoip = autoip;
} }
...@@ -319,7 +319,7 @@ autoip_start(struct netif *netif) ...@@ -319,7 +319,7 @@ autoip_start(struct netif *netif)
("autoip_start(): could not allocate autoip\n")); ("autoip_start(): could not allocate autoip\n"));
return ERR_MEM; return ERR_MEM;
} }
memset(autoip, 0, sizeof(struct autoip)); os_memset(autoip, 0, sizeof(struct autoip));
/* store this AutoIP client in the netif */ /* store this AutoIP client in the netif */
netif->autoip = autoip; netif->autoip = autoip;
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip")); LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
......
...@@ -95,6 +95,10 @@ Steve Reynolds ...@@ -95,6 +95,10 @@ Steve Reynolds
#include "string.h" #include "string.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/* /*
* IGMP constants * IGMP constants
*/ */
......
...@@ -133,7 +133,13 @@ ip_route(ip_addr_t *dest) ...@@ -133,7 +133,13 @@ ip_route(ip_addr_t *dest)
/* return netif on which to forward IP packet */ /* return netif on which to forward IP packet */
return netif; 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; return netif;
} }
} }
...@@ -669,7 +675,7 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, ...@@ -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); MEMCPY(p->payload, ip_options, optlen);
if (optlen < optlen_aligned) { if (optlen < optlen_aligned) {
/* zero the remaining bytes */ /* 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 #if CHECKSUM_GEN_IP_INLINE
for (i = 0; i < optlen_aligned/2; i++) { for (i = 0; i < optlen_aligned/2; i++) {
......
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
#include "lwip/netif.h" #include "lwip/netif.h"
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.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_any ICACHE_RODATA_ATTR = { IPADDR_ANY };
const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST }; const ip_addr_t ip_addr_broadcast ICACHE_RODATA_ATTR = { IPADDR_BROADCAST };
/** /**
* Determine if an address is a broadcast address on a network interface * 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) ...@@ -154,6 +154,9 @@ ipaddr_aton(const char *cp, ip_addr_t *addr)
u32_t val; u32_t val;
u8_t base; u8_t base;
char c; char c;
char ch;
unsigned long cutoff;
int cutlim;
u32_t parts[4]; u32_t parts[4];
u32_t *pp = parts; u32_t *pp = parts;
...@@ -176,12 +179,26 @@ ipaddr_aton(const char *cp, ip_addr_t *addr) ...@@ -176,12 +179,26 @@ ipaddr_aton(const char *cp, ip_addr_t *addr)
} else } else
base = 8; base = 8;
} }
cutoff =(unsigned long)0xffffffff / (unsigned long)base;
cutlim =(unsigned long)0xffffffff % (unsigned long)base;
for (;;) { for (;;) {
if (isdigit(c)) { if (isdigit(c)) {
ch = (int)(c - '0');
if (val > cutoff || (val == cutoff && ch > cutlim))
return (0);
val = (val * base) + (int)(c - '0'); val = (val * base) + (int)(c - '0');
c = *++cp; c = *++cp;
} else if (base == 16 && isxdigit(c)) { } 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; c = *++cp;
} else } else
break; break;
...@@ -220,21 +237,21 @@ ipaddr_aton(const char *cp, ip_addr_t *addr) ...@@ -220,21 +237,21 @@ ipaddr_aton(const char *cp, ip_addr_t *addr)
break; break;
case 2: /* a.b -- 8.24 bits */ case 2: /* a.b -- 8.24 bits */
if (val > 0xffffffUL) { if ((val > 0xffffffUL) || (parts[0] > 0xff)) {
return (0); return (0);
} }
val |= parts[0] << 24; val |= parts[0] << 24;
break; break;
case 3: /* a.b.c -- 8.8.16 bits */ case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff) { if ((val > 0xffff) || (parts[0] > 0xff) || (parts[1] > 0xff)) {
return (0); return (0);
} }
val |= (parts[0] << 24) | (parts[1] << 16); val |= (parts[0] << 24) | (parts[1] << 16);
break; break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */ 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); return (0);
} }
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
......
...@@ -284,7 +284,7 @@ ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen) ...@@ -284,7 +284,7 @@ ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen)
return NULL; return NULL;
} }
} }
memset(ipr, 0, sizeof(struct ip_reassdata)); os_memset(ipr, 0, sizeof(struct ip_reassdata));
ipr->timer = IP_REASS_MAXAGE; ipr->timer = IP_REASS_MAXAGE;
/* enqueue the new structure to the front of the list */ /* enqueue the new structure to the front of the list */
......
/**
* 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"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/** DNS server IP address */
#ifndef DNS_MULTICAST_ADDRESS
#define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
#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) {
struct ip_addr ap_host_addr;
struct ip_info ipconfig;
if(register_flag == 1){
if (igmp_leavegroup(&host_addr, &multicast_addr) != ERR_OK) {
os_printf("sta udp_leave_multigrup failed!\n");
return;
};
if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
wifi_get_ip_info(SOFTAP_IF, &ipconfig);
ap_host_addr.addr = ipconfig.ip.addr;
if (igmp_leavegroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
os_printf("ap udp_join_multigrup failed!\n");
return;
};
}
register_flag = 0;
}
}
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;
struct ip_addr ap_host_addr;
struct ip_info ipconfig;
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(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x01) {
if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
os_printf("sta udp_join_multigrup failed!\n");
return;
};
}
if(wifi_get_opmode() == 0x03 || wifi_get_opmode() == 0x02) {
wifi_get_ip_info(SOFTAP_IF, &ipconfig);
ap_host_addr.addr = ipconfig.ip.addr;
if (igmp_joingroup(&ap_host_addr, &multicast_addr) != ERR_OK) {
os_printf("ap udp_join_multigrup failed!\n");
return;
};
}
register_flag = 1;
/* join to any IP address at the port 5353 */
if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {
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 */
...@@ -636,7 +636,7 @@ void *mem_calloc(mem_size_t count, mem_size_t size) ...@@ -636,7 +636,7 @@ void *mem_calloc(mem_size_t count, mem_size_t size)
p = mem_malloc(count * size); p = mem_malloc(count * size);
if (p) { if (p) {
/* zero the memory */ /* zero the memory */
memset(p, 0, count * size); os_memset(p, 0, count * size);
} }
return p; return p;
} }
......
...@@ -126,7 +126,7 @@ static struct memp *memp_tab[MEMP_MAX]; ...@@ -126,7 +126,7 @@ static struct memp *memp_tab[MEMP_MAX];
#if !MEM_USE_POOLS && !MEMP_MEM_MALLOC #if !MEM_USE_POOLS && !MEMP_MEM_MALLOC
static static
#endif #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), #define LWIP_MEMPOOL(name,num,size,desc,attr) LWIP_MEM_ALIGN_SIZE(size),
#include "lwip/memp_std.h" #include "lwip/memp_std.h"
}; };
...@@ -320,11 +320,11 @@ memp_overflow_init(void) ...@@ -320,11 +320,11 @@ memp_overflow_init(void)
for (j = 0; j < memp_num[i]; ++j) { for (j = 0; j < memp_num[i]; ++j) {
#if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0 #if MEMP_SANITY_REGION_BEFORE_ALIGNED > 0
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED; 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 #endif
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0 #if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
m = (u8_t*)p + MEMP_SIZE + memp_sizes[i]; 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 #endif
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED); p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
} }
......
...@@ -149,6 +149,7 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask, ...@@ -149,6 +149,7 @@ netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
#if LWIP_DHCP #if LWIP_DHCP
/* netif not under DHCP control by default */ /* netif not under DHCP control by default */
netif->dhcp = NULL; netif->dhcp = NULL;
netif->dhcps_pcb = NULL;
#endif /* LWIP_DHCP */ #endif /* LWIP_DHCP */
#if LWIP_AUTOIP #if LWIP_AUTOIP
/* netif not under AutoIP control by default */ /* netif not under AutoIP control by default */
......
...@@ -79,8 +79,12 @@ ...@@ -79,8 +79,12 @@
#include <string.h> #include <string.h>
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
#ifdef EBUF_LWIP #ifdef EBUF_LWIP
#include "pp/esf_buf.h" #define EP_OFFSET 36
#else #else
#define EP_OFFSET 0 #define EP_OFFSET 0
#endif /* ESF_LWIP */ #endif /* ESF_LWIP */
...@@ -90,6 +94,45 @@ ...@@ -90,6 +94,45 @@
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */ aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) #define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
/**
* Attempt to reclaim some memory from queued out-of-sequence TCP segments
* if we run out of pool pbufs. It's better to give priority to new packets
* if we're running out.
*/
#if TCP_QUEUE_OOSEQ
void ICACHE_FLASH_ATTR
pbuf_free_ooseq_new(void* arg)
{
struct tcp_pcb* pcb;
struct tcp_seg *head = NULL;
struct tcp_seg *seg1 = NULL;
struct tcp_seg *seg2 = NULL;
for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
head = pcb->ooseq;
seg1 = head;
if (head != NULL) {
if (seg1->next == NULL){
head = head->next;
tcp_seg_free(seg1);
pcb->ooseq = head;
} else {
while (seg1 != NULL){
seg2 = seg1;
seg2 = seg2->next;
if (seg2 ->next == NULL){
seg1->next = seg2->next;
tcp_seg_free(seg2);
break;
}
seg1 = seg1->next;
}
pcb->ooseq = head;
}
}
}
}
#endif
#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS #if !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS
#define PBUF_POOL_IS_EMPTY() #define PBUF_POOL_IS_EMPTY()
#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */ #else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || NO_SYS */
...@@ -329,6 +372,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) ...@@ -329,6 +372,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
p->len = p->tot_len = length; p->len = p->tot_len = length;
p->next = NULL; p->next = NULL;
p->type = type; p->type = type;
p->eb = NULL;
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
...@@ -363,6 +407,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) ...@@ -363,6 +407,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
/* set flags */ /* set flags */
p->flags = 0; p->flags = 0;
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
return p; return p;
} }
...@@ -1204,7 +1249,7 @@ pbuf_strstr(struct pbuf* p, const char* substr) ...@@ -1204,7 +1249,7 @@ pbuf_strstr(struct pbuf* p, const char* substr)
if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) { if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
return 0xFFFF; return 0xFFFF;
} }
substr_len = strlen(substr); substr_len = os_strlen(substr);
if (substr_len >= 0xFFFF) { if (substr_len >= 0xFFFF) {
return 0xFFFF; return 0xFFFF;
} }
......
...@@ -52,6 +52,10 @@ ...@@ -52,6 +52,10 @@
#include <string.h> #include <string.h>
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/** The list of RAW PCBs */ /** The list of RAW PCBs */
static struct raw_pcb *raw_pcbs; static struct raw_pcb *raw_pcbs;
...@@ -342,7 +346,7 @@ raw_new(u8_t proto) ...@@ -342,7 +346,7 @@ raw_new(u8_t proto)
/* could allocate RAW PCB? */ /* could allocate RAW PCB? */
if (pcb != NULL) { if (pcb != NULL) {
/* initialize PCB to all zeroes */ /* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct raw_pcb)); os_memset(pcb, 0, sizeof(struct raw_pcb));
pcb->protocol = proto; pcb->protocol = proto;
pcb->ttl = RAW_TTL; pcb->ttl = RAW_TTL;
pcb->next = raw_pcbs; pcb->next = raw_pcbs;
......
/**
* @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 <string.h>
#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 */
/* /*
* copyright (c) 2010 - 2011 espressif system * copyright (c) 2010 - 2011 espressif system
*/ */
#include "c_types.h" #include "c_types.h"
#include "ets_sys.h" #include "ets_sys.h"
#include "osapi.h" #include "osapi.h"
#include "os_type.h" #include "os_type.h"
#include "lwip/opt.h" #include "lwip/opt.h"
#include "lwip/sys.h" #include "lwip/sys.h"
#include "eagle_soc.h" #include "eagle_soc.h"
...@@ -55,7 +55,12 @@ ...@@ -55,7 +55,12 @@
#include <string.h> #include <string.h>
const char * const tcp_state_str[] = { #ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
#if TCP_DEBUG
const char tcp_state_str_rodata[][12] ICACHE_RODATA_ATTR = {
"CLOSED", "CLOSED",
"LISTEN", "LISTEN",
"SYN_SENT", "SYN_SENT",
...@@ -69,12 +74,15 @@ const char * const tcp_state_str[] = { ...@@ -69,12 +74,15 @@ const char * const tcp_state_str[] = {
"TIME_WAIT" "TIME_WAIT"
}; };
char tcp_state_str[12];
#endif
/* Incremented every coarse grained timer shot (typically every 500 ms). */ /* Incremented every coarse grained timer shot (typically every 500 ms). */
u32_t tcp_ticks; 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}; { 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7};
/* Times per slowtmr hits */ /* 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. */ /* The TCP PCB lists. */
...@@ -91,7 +99,7 @@ struct tcp_pcb *tcp_tw_pcbs; ...@@ -91,7 +99,7 @@ struct tcp_pcb *tcp_tw_pcbs;
#define NUM_TCP_PCB_LISTS 4 #define NUM_TCP_PCB_LISTS 4
#define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3
/** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ /** 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}; &tcp_active_pcbs, &tcp_tw_pcbs};
/** Only used for temporary storage. */ /** Only used for temporary storage. */
...@@ -798,7 +806,7 @@ tcp_slowtmr(void) ...@@ -798,7 +806,7 @@ tcp_slowtmr(void)
/* If snd_wnd is zero, use persist timer to send 1 byte probes /* If snd_wnd is zero, use persist timer to send 1 byte probes
* instead of using the standard retransmission mechanism. */ * instead of using the standard retransmission mechanism. */
pcb->persist_cnt++; 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; pcb->persist_cnt = 0;
if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) { if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
pcb->persist_backoff++; pcb->persist_backoff++;
...@@ -819,7 +827,7 @@ tcp_slowtmr(void) ...@@ -819,7 +827,7 @@ tcp_slowtmr(void)
/* Double retransmission time-out unless we are trying to /* Double retransmission time-out unless we are trying to
* connect to somebody (i.e., we are in SYN_SENT). */ * connect to somebody (i.e., we are in SYN_SENT). */
if (pcb->state != 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) // if (pcb->rto >= TCP_MAXRTO)
// pcb->rto >>= 1; // pcb->rto >>= 1;
} }
...@@ -1221,7 +1229,7 @@ tcp_alloc(u8_t prio) ...@@ -1221,7 +1229,7 @@ tcp_alloc(u8_t prio)
} }
} }
if (pcb != NULL) { if (pcb != NULL) {
memset(pcb, 0, sizeof(struct tcp_pcb)); //��0 os_memset(pcb, 0, sizeof(struct tcp_pcb)); //��0
pcb->prio = prio; //�������ȼ� pcb->prio = prio; //�������ȼ�
pcb->snd_buf = TCP_SND_BUF; //��ʹ�õķ��ͻ������С pcb->snd_buf = TCP_SND_BUF; //��ʹ�õķ��ͻ������С
pcb->snd_queuelen = 0; //��������ռ�õ�pbuf���� pcb->snd_queuelen = 0; //��������ռ�õ�pbuf����
...@@ -1259,7 +1267,6 @@ tcp_alloc(u8_t prio) ...@@ -1259,7 +1267,6 @@ tcp_alloc(u8_t prio)
#endif /* LWIP_TCP_KEEPALIVE */ #endif /* LWIP_TCP_KEEPALIVE */
pcb->keep_cnt_sent = 0; //���ķ��ʹ��� pcb->keep_cnt_sent = 0; //���ķ��ʹ���
pcb->hold = 0;
} }
return pcb; return pcb;
} }
...@@ -1482,7 +1489,11 @@ tcp_next_iss(void) ...@@ -1482,7 +1489,11 @@ tcp_next_iss(void)
{ {
static u32_t iss = 6510; static u32_t iss = 6510;
iss += tcp_ticks; /* XXX */ again:
iss += tcp_ticks; /* XXX */
if (iss == 0)
goto again;
return iss; return iss;
} }
...@@ -1511,11 +1522,15 @@ tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr) ...@@ -1511,11 +1522,15 @@ tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr)
} }
#endif /* TCP_CALCULATE_EFF_SEND_MSS */ #endif /* TCP_CALCULATE_EFF_SEND_MSS */
#if TCP_DEBUG
const char* const char*
tcp_debug_state_str(enum tcp_state s) 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 #if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
/** /**
......
...@@ -56,20 +56,24 @@ ...@@ -56,20 +56,24 @@
#include "lwip/snmp.h" #include "lwip/snmp.h"
#include "arch/perf.h" #include "arch/perf.h"
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/* These variables are global to all functions involved in the input /* These variables are global to all functions involved in the input
processing of TCP segments. They are set by the tcp_input() processing of TCP segments. They are set by the tcp_input()
function. */ function. */
static struct tcp_seg inseg; //tcp_seg结构,描述输入的报文段 static struct tcp_seg inseg; //tcp_segṹ����������ı��Ķ�
static struct tcp_hdr *tcphdr; //报文段中TCP首部 static struct tcp_hdr *tcphdr; //���Ķ���TCP�ײ�
static struct ip_hdr *iphdr; //IP数据包首部 static struct ip_hdr *iphdr; //IP��ݰ��ײ�
static u32_t seqno, ackno; //TCP首部中序号字段与确认号字段 static u32_t seqno, ackno; //TCP�ײ�������ֶ���ȷ�Ϻ��ֶ�
static u8_t flags; //首部标志字段 static u8_t flags; //�ײ���־�ֶ�
static u16_t tcplen; //TCP报文长度 static u16_t tcplen; //TCP���ij���
static u8_t recv_flags; //当前报文处理结果 static u8_t recv_flags; //��ǰ���Ĵ�����
static struct pbuf *recv_data; //报文段数据pbuf static struct pbuf *recv_data; //���Ķ����pbuf
struct tcp_pcb *tcp_input_pcb; //当前报文控制块 struct tcp_pcb *tcp_input_pcb; //��ǰ���Ŀ��ƿ�
/* Forward declarations. */ /* Forward declarations. */
static err_t tcp_process(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; static err_t tcp_process(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR;
...@@ -89,10 +93,10 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR; ...@@ -89,10 +93,10 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR;
* @param inp network interface on which this segment was received * @param inp network interface on which this segment was received
*/ */
/** /**
* TCP初始化输入处理,验证了TCP头,这个函数被IP层调用 * TCP��ʼ�����봦�?��֤��TCPͷ���������IP�����
* @参数p:处理接收的TCP段(指向IP头的负载) * @����p:������յ�TCP��(ָ��IPͷ�ĸ���)
* @参数inp:接收段的网络接口 * @����inp:���նε�����ӿ�
*/ */
void void
tcp_input(struct pbuf *p, struct netif *inp) tcp_input(struct pbuf *p, struct netif *inp)
...@@ -108,15 +112,15 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -108,15 +112,15 @@ tcp_input(struct pbuf *p, struct netif *inp)
PERF_START; PERF_START;
TCP_STATS_INC(tcp.recv); //状态1 TCP_STATS_INC(tcp.recv); //״̬��1
snmp_inc_tcpinsegs(); //tcp输入段加1 snmp_inc_tcpinsegs(); //tcp����μ�1
iphdr = (struct ip_hdr *)p->payload;// pointer to the actual data in the buffer iphdr = (struct ip_hdr *)p->payload;// pointer to the actual data in the buffer
/* /*
*包头长度(IHL):4位,IP协议包头的长度,指明IPv4协议包头长度的字节数包含多少个32位。 *��ͷ����(IHL)��4λ��IPЭ���ͷ�ij��ȣ�ָ��IPv4Э���ͷ���ȵ��ֽ������ٸ�32λ��
*由于IPv4的包头可能包含可变数量的可选 项,所以这个字段可以用来确定IPv4数据报中数据部分的偏移量。 *����IPv4�İ�ͷ���ܰ�ɱ������Ŀ�ѡ ���������ֶο�������ȷ��IPv4��ݱ�����ݲ��ֵ�ƫ������
*IPv4包头的最小长度是20个字节,因此IHL这个字段的最小值用十进制表示就是5 (5x4 = 20字节)。  
*就是说,它表示的包头的总字节数是4字节的倍数 *����˵�����ʾ�İ�ͷ�����ֽ�����4�ֽڵı���
*/ */
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4); tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
...@@ -128,17 +132,17 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -128,17 +132,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))) { if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
/* drop short packets */ /* drop short packets */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); 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.lenerr);//���󳤶ȼ���
TCP_STATS_INC(tcp.drop);//终止计数 TCP_STATS_INC(tcp.drop);//��ֹ����
snmp_inc_tcpinerrs(); snmp_inc_tcpinerrs();
pbuf_free(p);//释放buffer pbuf_free(p);//�ͷ�buffer
return; return;
} }
/* Don't even process incoming broadcasts/multicasts. */ /* Don't even process incoming broadcasts/multicasts. */
if (ip_addr_isbroadcast(&current_iphdr_dest, inp) || if (ip_addr_isbroadcast(&current_iphdr_dest, inp) ||
ip_addr_ismulticast(&current_iphdr_dest)) { ip_addr_ismulticast(&current_iphdr_dest)) {
TCP_STATS_INC(tcp.proterr);//协议错误计数 TCP_STATS_INC(tcp.proterr);//Э��������
TCP_STATS_INC(tcp.drop); TCP_STATS_INC(tcp.drop);
snmp_inc_tcpinerrs(); snmp_inc_tcpinerrs();
pbuf_free(p); pbuf_free(p);
...@@ -155,7 +159,7 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -155,7 +159,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
#if TCP_DEBUG #if TCP_DEBUG
tcp_debug_print(tcphdr); tcp_debug_print(tcphdr);
#endif /* TCP_DEBUG */ #endif /* TCP_DEBUG */
TCP_STATS_INC(tcp.chkerr);//校验错误计数 TCP_STATS_INC(tcp.chkerr);//У��������
TCP_STATS_INC(tcp.drop); TCP_STATS_INC(tcp.drop);
snmp_inc_tcpinerrs(); snmp_inc_tcpinerrs();
pbuf_free(p); pbuf_free(p);
...@@ -165,11 +169,11 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -165,11 +169,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Move the payload pointer in the pbuf so that it points to the /* Move the payload pointer in the pbuf so that it points to the
TCP data instead of the TCP header. */ TCP data instead of the TCP header. */
hdrlen = TCPH_HDRLEN(tcphdr);//计算头的长度 hdrlen = TCPH_HDRLEN(tcphdr);//����ͷ�ij���
if(pbuf_header(p, -(hdrlen * 4))){//跨过TCP头,返回0为成功,否则 if(pbuf_header(p, -(hdrlen * 4))){//���TCPͷ������0Ϊ�ɹ�������
/* drop short packets */ /* drop short packets */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n")); 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); TCP_STATS_INC(tcp.drop);
snmp_inc_tcpinerrs(); snmp_inc_tcpinerrs();
pbuf_free(p); pbuf_free(p);
...@@ -177,53 +181,53 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -177,53 +181,53 @@ tcp_input(struct pbuf *p, struct netif *inp)
} }
/* Convert fields in TCP header to host byte order. */ /* Convert fields in TCP header to host byte order. */
tcphdr->src = ntohs(tcphdr->src); //转换源地 tcphdr->src = ntohs(tcphdr->src); //ת��Դ��ַ
tcphdr->dest = ntohs(tcphdr->dest); //转换目的地 tcphdr->dest = ntohs(tcphdr->dest); //ת��Ŀ�ĵ�ַ
seqno = tcphdr->seqno = ntohl(tcphdr->seqno); //转换序列号 seqno = tcphdr->seqno = ntohl(tcphdr->seqno); //ת�����к�
ackno = tcphdr->ackno = ntohl(tcphdr->ackno); //转换应答号 ackno = tcphdr->ackno = ntohl(tcphdr->ackno); //ת��Ӧ���
tcphdr->wnd = ntohs(tcphdr->wnd); //转换tcp窗口 tcphdr->wnd = ntohs(tcphdr->wnd); //ת��tcp����
flags = TCPH_FLAGS(tcphdr);//得到tcp header的标 flags = TCPH_FLAGS(tcphdr);//�õ�tcp header�ı�־
/* /*
*标志:3位控制字段,包含: *��־��3λ�����ֶΣ���
* 保留位:1位 * ����λ��1λ
* 不分段位:1位,取值:0(允许数据报分段)、1(数据报不能分段) * ���ֶ�λ��1λ��ȡֵ��0��������ݱ��ֶΣ���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 /* Demultiplex an incoming segment. First, we check if it is destined
for an active connection. 首先,检查是否一定要激活一个连接*/ for an active connection. ���ȣ�����Ƿ�һ��Ҫ����һ������*/
//////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////
prev = NULL; 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 != CLOSED", pcb->state != CLOSED);
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
if (pcb->remote_port == tcphdr->src && if (pcb->remote_port == tcphdr->src &&
pcb->local_port == tcphdr->dest && pcb->local_port == tcphdr->dest &&
ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) && ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src) &&
ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {//检查相关的地 ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest)) {//�����صĵ�ַ
/* Move this PCB to the front of the list so that subsequent /* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment lookups will be faster (we exploit locality in TCP segment
arrivals). */ arrivals). */
LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb);
if (prev != NULL) {//如果前一个节点不为空 if (prev != NULL) {//���ǰһ���ڵ㲻Ϊ��
prev->next = pcb->next; prev->next = pcb->next;
pcb->next = tcp_active_pcbs; 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); LWIP_ASSERT("tcp_input: pcb->next != pcb (after cache)", pcb->next != pcb);
break; break;
} }
prev = pcb;//prev指pcb prev = pcb;//prevָ��pcb
} }
if (pcb == NULL) { if (pcb == NULL) {
/* If it did not go to an active connection, we check the connections /* If it did not go to an active connection, we check the connections
in the TIME-WAIT state. */ 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); LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
if (pcb->remote_port == tcphdr->src && if (pcb->remote_port == tcphdr->src &&
pcb->local_port == tcphdr->dest && pcb->local_port == tcphdr->dest &&
...@@ -233,7 +237,7 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -233,7 +237,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
of the list since we are not very likely to receive that of the list since we are not very likely to receive that
many segments for connections in TIME-WAIT. */ many segments for connections in TIME-WAIT. */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for TIME_WAITing connection.\n")); 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); pbuf_free(p);
return; return;
} }
...@@ -242,7 +246,7 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -242,7 +246,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Finally, if we still did not get a match, we check all PCBs that /* Finally, if we still did not get a match, we check all PCBs that
are LISTENing for incoming connections. */ are LISTENing for incoming connections. */
prev = NULL; 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 (lpcb->local_port == tcphdr->dest) {
#if SO_REUSE #if SO_REUSE
if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) { if (ip_addr_cmp(&(lpcb->local_ip), &current_iphdr_dest)) {
...@@ -284,7 +288,7 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -284,7 +288,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
} }
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); 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); pbuf_free(p);
return; return;
} }
...@@ -318,7 +322,7 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -318,7 +322,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
if (pcb->refused_data != NULL) { if (pcb->refused_data != NULL) {
/* Notify again application with data previously received. */ /* Notify again application with data previously received. */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); 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) { if (err == ERR_OK) {
pcb->refused_data = NULL; pcb->refused_data = NULL;
} else if ((err == ERR_ABRT) || (tcplen > 0)) { } else if ((err == ERR_ABRT) || (tcplen > 0)) {
...@@ -326,14 +330,14 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -326,14 +330,14 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Drop incoming packets because pcb is "full" (only if the incoming /* Drop incoming packets because pcb is "full" (only if the incoming
segment contains data). */ segment contains data). */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); 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(); snmp_inc_tcpinerrs();
pbuf_free(p); pbuf_free(p);
return; return;
} }
} }
tcp_input_pcb = pcb;//记录当前报文处理的控制块 tcp_input_pcb = pcb;//��¼��ǰ���Ĵ���Ŀ��ƿ�
err = tcp_process(pcb);//处理报文 err = tcp_process(pcb);//���?��
/* A return value of ERR_ABRT means that tcp_abort() was called /* 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. */ and that the pcb has been freed. If so, we don't do anything. */
if (err != ERR_ABRT) { if (err != ERR_ABRT) {
...@@ -343,7 +347,7 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -343,7 +347,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
application that the connection is dead before we application that the connection is dead before we
deallocate the PCB. */ deallocate the PCB. */
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); 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); memp_free(MEMP_TCP_PCB, pcb);
} else if (recv_flags & TF_CLOSED) { } else if (recv_flags & TF_CLOSED) {
/* The connection has been closed and we will deallocate the /* The connection has been closed and we will deallocate the
...@@ -362,13 +366,13 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -362,13 +366,13 @@ tcp_input(struct pbuf *p, struct netif *inp)
called when new send buffer space is available, we call it called when new send buffer space is available, we call it
now. */ now. */
if (pcb->acked > 0) { if (pcb->acked > 0) {
TCP_EVENT_SENT(pcb, pcb->acked, err);//有数据被确认,回调用户的send函数 TCP_EVENT_SENT(pcb, pcb->acked, err);//����ݱ�ȷ�ϣ��ص��û���send����
if (err == ERR_ABRT) { if (err == ERR_ABRT) {
goto aborted; goto aborted;
} }
} }
if (recv_data != NULL) {//有数据接收到 if (recv_data != NULL) {//����ݽ��յ�
LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
if (pcb->flags & TF_RXCLOSED) { if (pcb->flags & TF_RXCLOSED) {
/* received data although already closed -> abort (send RST) to /* received data although already closed -> abort (send RST) to
...@@ -378,12 +382,12 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -378,12 +382,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
goto aborted; goto aborted;
} }
//PSH志 PSH 紧急位。 //PSH��־ PSH ����λ��
//PSH=1时,要求发送方马上发送该分段  
//而接收方尽快的将报文交给应用层,不做队列处理。 //����շ�����Ľ����Ľ���Ӧ�ò㣬�������д��?
if (flags & TCP_PSH) { 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. */ /* Notify application that data has been received. */
...@@ -414,9 +418,9 @@ tcp_input(struct pbuf *p, struct netif *inp) ...@@ -414,9 +418,9 @@ tcp_input(struct pbuf *p, struct netif *inp)
} }
} }
tcp_input_pcb = NULL;//清空全局变量 tcp_input_pcb = NULL;//���ȫ�ֱ���
/* Try to send something out. */ /* Try to send something out. */
tcp_output(pcb);//尝试输出报文 tcp_output(pcb);//�����������
#if TCP_INPUT_DEBUG #if TCP_INPUT_DEBUG
#if TCP_DEBUG #if TCP_DEBUG
tcp_debug_print_state(pcb->state); tcp_debug_print_state(pcb->state);
...@@ -433,20 +437,30 @@ aborted: ...@@ -433,20 +437,30 @@ aborted:
/* give up our reference to inseg.p */ /* give up our reference to inseg.p */
if (inseg.p != NULL) if (inseg.p != NULL)
{ {
pbuf_free(inseg.p);//释放buffer pbuf_free(inseg.p);//�ͷ�buffer
inseg.p = NULL; inseg.p = NULL;
} }
/*add processing queue segments that arrive out of order by LiuHan*/
#if TCP_QUEUE_OOSEQ
extern char RxNodeNum(void);
if (RxNodeNum() < 2){
extern void pbuf_free_ooseq_new(void* arg);
// os_printf("reclaim some memory from queued\n");
pbuf_free_ooseq_new(NULL);
}
#endif
} else { } else {
/* If no matching PCB was found, send a TCP RST (reset) to the /* If no matching PCB was found, send a TCP RST (reset) to the
sender. */ sender. */
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n")); LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) { if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
TCP_STATS_INC(tcp.proterr);//协议错误计数 TCP_STATS_INC(tcp.proterr);//Э��������
TCP_STATS_INC(tcp.drop);//tcp丢弃计数 TCP_STATS_INC(tcp.drop);//tcp�������
tcp_rst(ackno, seqno + tcplen, tcp_rst(ackno, seqno + tcplen,
ip_current_dest_addr(), ip_current_src_addr(), ip_current_dest_addr(), ip_current_src_addr(),
tcphdr->dest, tcphdr->src);//发送TCP复 tcphdr->dest, tcphdr->src);//����TCP��λ
} }
pbuf_free(p); pbuf_free(p);
} }
...@@ -468,8 +482,8 @@ aborted: ...@@ -468,8 +482,8 @@ aborted:
* involved is passed as a parameter to this function * involved is passed as a parameter to this function
*/ */
/* /*
*处于LISTEN状态的控制块调用该函数, *����LISTEN״̬�Ŀ��ƿ���øú���
*通常是服务器端主动打开一个端口并侦听客户端SYN连接请求 ���Ƿ�������������һ���˿ڲ�����ͻ���SYN��������
* *
*/ */
static err_t static err_t
...@@ -489,7 +503,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) ...@@ -489,7 +503,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
tcp_rst(ackno + 1, seqno + tcplen, tcp_rst(ackno + 1, seqno + tcplen,
ip_current_dest_addr(), ip_current_src_addr(), ip_current_dest_addr(), ip_current_src_addr(),
tcphdr->dest, tcphdr->src); 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)); LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
#if TCP_LISTEN_BACKLOG #if TCP_LISTEN_BACKLOG
if (pcb->accepts_pending >= pcb->backlog) { if (pcb->accepts_pending >= pcb->backlog) {
...@@ -504,30 +518,31 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) ...@@ -504,30 +518,31 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
TCP_STATS_INC(tcp.memerr); TCP_STATS_INC(tcp.memerr);
return ERR_MEM; 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), /* 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 we don't do anything, but rely on the sender will retransmit the
SYN at a time when we have more memory available. */ SYN at a time when we have more memory available. */
if (npcb == NULL) { if (npcb == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n")); 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; return ERR_MEM;
} }
#if TCP_LISTEN_BACKLOG #if TCP_LISTEN_BACKLOG
pcb->accepts_pending++; pcb->accepts_pending++;
#endif /* TCP_LISTEN_BACKLOG */ #endif /* TCP_LISTEN_BACKLOG */
/* Set up the new PCB. */ /* Set up the new PCB. */
//控制块与连接相关的4个字段 //���ƿ���������ص�4���ֶ�
ip_addr_copy(npcb->local_ip, current_iphdr_dest); ip_addr_copy(npcb->local_ip, current_iphdr_dest);
npcb->local_port = pcb->local_port; npcb->local_port = pcb->local_port;
ip_addr_copy(npcb->remote_ip, current_iphdr_src); ip_addr_copy(npcb->remote_ip, current_iphdr_src);
npcb->remote_port = tcphdr->src; npcb->remote_port = tcphdr->src;
//控制块中其余字段 //���ƿ��������ֶ�
npcb->state = SYN_RCVD;//设置连接状态 npcb->state = SYN_RCVD;//��������״̬
npcb->rcv_nxt = seqno + 1;//设置下一个接收数据序号 npcb->rcv_nxt = seqno + 1;//������һ������������
npcb->rcv_ann_right_edge = npcb->rcv_nxt; npcb->rcv_ann_right_edge = npcb->rcv_nxt;
npcb->snd_wnd = tcphdr->wnd;//设置发送窗口 npcb->snd_wnd = tcphdr->wnd;//���÷��ʹ���
npcb->ssthresh = npcb->snd_wnd; npcb->ssthresh = npcb->snd_wnd;
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */ npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
npcb->callback_arg = pcb->callback_arg; npcb->callback_arg = pcb->callback_arg;
...@@ -550,11 +565,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) ...@@ -550,11 +565,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
/* Send a SYN|ACK together with the MSS option. */ /* Send a SYN|ACK together with the MSS option. */
rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK); rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
if (rc != ERR_OK) {//发生错误,释放新控制块 if (rc != ERR_OK) {//��������ͷ��¿��ƿ�
tcp_abandon(npcb, 0); tcp_abandon(npcb, 0);
return rc; return rc;
} }
return tcp_output(npcb);//发送报文 return tcp_output(npcb);//���ͱ���
} }
return ERR_OK; return ERR_OK;
} }
...@@ -569,20 +584,20 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) ...@@ -569,20 +584,20 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
* involved is passed as a parameter to this function * involved is passed as a parameter to this function
*/ */
/* /*
*处于TIME_WAIT状态的控制块调用该函数处理收到的报文段, *����TIME_WAIT״̬�Ŀ��ƿ���øú������յ��ı��ĶΣ�
*该状态下,关闭连接的握手过程已经结束,正处于等待2MSL超时, *��״̬�£��ر����ӵ����ֹ���Ѿ��������ڵȴ�2MSL��ʱ��
*该状态下的报文多数是连接中的旧数据,直接删除即可。 *��״̬�µı��Ķ����������еľ���ݣ�ֱ��ɾ��ɡ�
*但需要向发送方返回ACK报文 *����Ҫ���ͷ�����ACK����
*/ */
static err_t static err_t
tcp_timewait_input(struct tcp_pcb *pcb) tcp_timewait_input(struct tcp_pcb *pcb)
{ {
if (flags & TCP_RST) { //RST置位,直接返回 if (flags & TCP_RST) { //RST��λ��ֱ�ӷ���
return ERR_OK; 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)) { if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
...@@ -590,13 +605,13 @@ tcp_timewait_input(struct tcp_pcb *pcb) ...@@ -590,13 +605,13 @@ tcp_timewait_input(struct tcp_pcb *pcb)
tcphdr->dest, tcphdr->src); tcphdr->dest, tcphdr->src);
return ERR_OK; 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报文 if ((tcplen > 0)) { //��������ݵı��Ļ����ڽ��մ������SYN����
pcb->flags |= TF_ACK_NOW;//发送一个ACK报文 pcb->flags |= TF_ACK_NOW;//����һ��ACK����
return tcp_output(pcb); return tcp_output(pcb);
} }
return ERR_OK; return ERR_OK;
...@@ -899,13 +914,13 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -899,13 +914,13 @@ tcp_receive(struct tcp_pcb *pcb)
u16_t new_tot_len; u16_t new_tot_len;
int found_dupack = 0; int found_dupack = 0;
if (flags & TCP_ACK) {//报文包含ACK if (flags & TCP_ACK) {//���İ�ACK
right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;//发送窗口 + 序列应答最后窗口更新 right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;//���ʹ��� + ����Ӧ����󴰿ڸ���
// first /* Update window. */ // first /* Update window. */
/*seqno > snd_wl1;建立握手过程采用此种更新; /*seqno > snd_wl1���������ֹ�̲��ô��ָ���;
*seqno = snd_wl1并且ackno > snd_wl2;此时,对方没有发送数据,只是收到数据的确认; *seqno = snd_wl1����ackno > snd_wl2;��ʱ���Է�û�з�����ݣ�ֻ���յ���ݵ�ȷ��;
*ackno = snd_wl2且报文首部有比snd_wnd更大的窗口.重新设置相应值 *ackno = snd_wl2�ұ����ײ��б�snd_wnd���Ĵ���.����������Ӧֵ
*/ */
if (TCP_SEQ_LT(pcb->snd_wl1, seqno) || if (TCP_SEQ_LT(pcb->snd_wl1, seqno) ||
(pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) || (pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
...@@ -914,7 +929,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -914,7 +929,7 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->snd_wl1 = seqno; pcb->snd_wl1 = seqno;
pcb->snd_wl2 = ackno; pcb->snd_wl2 = ackno;
if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) { 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)); LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
#if TCP_WND_DEBUG #if TCP_WND_DEBUG
...@@ -930,10 +945,10 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -930,10 +945,10 @@ tcp_receive(struct tcp_pcb *pcb)
/* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a /* (From Stevens TCP/IP Illustrated Vol II, p970.) Its only a
* duplicate ack if: * duplicate ack if:
* 1) It doesn't ACK new data 没有确认新数据 * 1) It doesn't ACK new data û��ȷ�������
* 2) length of received packet is zero (i.e. no payload) 报文段巫任何数据 * 2) length of received packet is zero (i.e. no payload) ���Ķ����κ����
* 3) the advertised window hasn't changed 本地窗口没有更新 * 3) the advertised window hasn't changed ���ش���û�и���
* 4) There is outstanding unacknowledged data (retransmission timer running)正有数据等待确认 * 4) There is outstanding unacknowledged data (retransmission timer running)������ݵȴ�ȷ��
* 5) The ACK is == biggest ACK sequence number so far seen (snd_una) ackno = lastack * 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: * If it passes all five, should process as a dupack:
...@@ -949,7 +964,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -949,7 +964,7 @@ tcp_receive(struct tcp_pcb *pcb)
*/ */
/* Clause 1 */ /* Clause 1 */
if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {//是重复ACK? if (TCP_SEQ_LEQ(ackno, pcb->lastack)) {//���ظ�ACK?
pcb->acked = 0; pcb->acked = 0;
/* Clause 2 */ /* Clause 2 */
if (tcplen == 0) { if (tcplen == 0) {
...@@ -968,7 +983,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -968,7 +983,7 @@ tcp_receive(struct tcp_pcb *pcb)
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss; pcb->cwnd += pcb->mss;
} }
} else if (pcb->dupacks == 3) {//是重复ACK } else if (pcb->dupacks == 3) {//���ظ�ACK
/* Do fast retransmit */ /* Do fast retransmit */
tcp_rexmit_fast(pcb); tcp_rexmit_fast(pcb);
} }
...@@ -981,7 +996,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -981,7 +996,7 @@ tcp_receive(struct tcp_pcb *pcb)
if (!found_dupack) { if (!found_dupack) {
pcb->dupacks = 0; pcb->dupacks = 0;
} }
} else if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)){//acknolastack+1snd_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. */ /* We come here when the ACK acknowledges new data. */
if (pcb->flags & TF_INFR) { if (pcb->flags & TF_INFR) {
...@@ -1006,7 +1021,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1006,7 +1021,7 @@ tcp_receive(struct tcp_pcb *pcb)
/* Update the congestion control variables (cwnd and /* Update the congestion control variables (cwnd and
ssthresh). */ ssthresh). */
if (pcb->state >= ESTABLISHED) {//状态为建立连接标 if (pcb->state >= ESTABLISHED) {//״̬Ϊ�������ӱ�־
if (pcb->cwnd < pcb->ssthresh) { if (pcb->cwnd < pcb->ssthresh) {
if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) { if ((u16_t)(pcb->cwnd + pcb->mss) > pcb->cwnd) {
pcb->cwnd += pcb->mss; pcb->cwnd += pcb->mss;
...@@ -1029,8 +1044,8 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1029,8 +1044,8 @@ tcp_receive(struct tcp_pcb *pcb)
/* Remove segment from the unacknowledged list if the incoming /* Remove segment from the unacknowledged list if the incoming
ACK acknowlegdes them. ACK acknowlegdes them.
*释放unacked队列上被确认的报文段, *�ͷ�unacked�����ϱ�ȷ�ϵı��ĶΣ�
*直unacked队列为空停止*/ ��unacked����Ϊ��ֹͣ*/
while (pcb->unacked != NULL && while (pcb->unacked != NULL &&
TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) + TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked), ackno)) { TCP_TCPLEN(pcb->unacked), ackno)) {
...@@ -1039,8 +1054,8 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1039,8 +1054,8 @@ tcp_receive(struct tcp_pcb *pcb)
ntohl(pcb->unacked->tcphdr->seqno) + ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked))); TCP_TCPLEN(pcb->unacked)));
next = pcb->unacked;//pcb unacked next = pcb->unacked;//pcb unacked��־
pcb->unacked = pcb->unacked->next;//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_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))); LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
...@@ -1049,8 +1064,8 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1049,8 +1064,8 @@ tcp_receive(struct tcp_pcb *pcb)
pcb->acked--; pcb->acked--;
} }
pcb->snd_queuelen -= pbuf_clen(next->p);//计算链表里面的pbufs数量 pcb->snd_queuelen -= pbuf_clen(next->p);//�������������pbufs����
tcp_seg_free(next);//释放tcp段 tcp_seg_free(next);//�ͷ�tcp��
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen)); LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unacked)\n", (u16_t)pcb->snd_queuelen));
if (pcb->snd_queuelen != 0) { if (pcb->snd_queuelen != 0) {
...@@ -1061,10 +1076,10 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1061,10 +1076,10 @@ tcp_receive(struct tcp_pcb *pcb)
/* If there's nothing left to acknowledge, stop the retransmit /* If there's nothing left to acknowledge, stop the retransmit
timer, otherwise reset it to start again */ timer, otherwise reset it to start again */
if(pcb->unacked == NULL) //无数据等待确认 if(pcb->unacked == NULL) //����ݵȴ�ȷ��
pcb->rtime = -1; //停止重传定时器 pcb->rtime = -1; //ֹͣ�ش���ʱ��
else else
pcb->rtime = 0; //复位重传定时器 pcb->rtime = 0; //��λ�ش���ʱ��
pcb->polltmr = 0; pcb->polltmr = 0;
} else { } else {
...@@ -1078,7 +1093,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1078,7 +1093,7 @@ tcp_receive(struct tcp_pcb *pcb)
rationale is that lwIP puts all outstanding segments on the rationale is that lwIP puts all outstanding segments on the
->unsent list after a retransmission, so these segments may ->unsent list after a retransmission, so these segments may
in fact have been sent once. */ in fact have been sent once. */
/** unsent队列上是否能被ackno确认的报文段,有则释放**/ /** unsent�������Ƿ��ܱ�acknoȷ�ϵı��ĶΣ������ͷ�**/
while (pcb->unsent != NULL && while (pcb->unsent != NULL &&
TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) + TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) { TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
...@@ -1086,18 +1101,18 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1086,18 +1101,18 @@ tcp_receive(struct tcp_pcb *pcb)
ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) + ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
TCP_TCPLEN(pcb->unsent))); TCP_TCPLEN(pcb->unsent)));
next = pcb->unsent;//pcb未发送标 next = pcb->unsent;//pcbδ���ͱ�־
pcb->unsent = pcb->unsent->next;//未发送的下一个 pcb->unsent = pcb->unsent->next;//δ���͵���һ��
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen)); 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))); 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 */ /* Prevent ACK for FIN to generate a sent event */
if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) { if ((pcb->acked != 0) && ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0)) {
pcb->acked--; pcb->acked--;
} }
pcb->snd_queuelen -= pbuf_clen(next->p);//链表中pbuf的个数 pcb->snd_queuelen -= pbuf_clen(next->p);//������pbuf�ĸ���
tcp_seg_free(next);//释放段 tcp_seg_free(next);//�ͷŶ�
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("%"U16_F" (after freeing unsent)\n", (u16_t)pcb->snd_queuelen)); 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", LWIP_ASSERT("tcp_receive: valid queue length",
pcb->unacked != NULL || pcb->unsent != NULL); pcb->unacked != NULL || pcb->unsent != NULL);
} }
...@@ -1110,15 +1125,15 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1110,15 +1125,15 @@ tcp_receive(struct tcp_pcb *pcb)
/* RTT estimation calculations. This is done by checking if the /* RTT estimation calculations. This is done by checking if the
incoming segment acknowledges the segment we use to take a incoming segment acknowledges the segment we use to take a
round-trip time measurement. */ 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 /* diff between this shouldn't exceed 32K since this are tcp timer ticks
and a round-trip shouldn't be that long... */ 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", LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_receive: experienced rtt %"U16_F" ticks (%"U16_F" msec).\n",
m, m * TCP_SLOW_INTERVAL)); 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); m = m - (pcb->sa >> 3);
pcb->sa += m; pcb->sa += m;
if (m < 0) { if (m < 0) {
...@@ -1137,7 +1152,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1137,7 +1152,7 @@ tcp_receive(struct tcp_pcb *pcb)
/* If the incoming segment contains data, we must process it /* If the incoming segment contains data, we must process it
further. */ further. */
if ((tcplen > 0) && (!pcb->hold)) { if (tcplen > 0) {
/* This code basically does three things: /* This code basically does three things:
+) If the incoming segment contains data that is the next +) If the incoming segment contains data that is the next
...@@ -1188,7 +1203,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1188,7 +1203,7 @@ tcp_receive(struct tcp_pcb *pcb)
After we are done with adjusting the pbuf pointers we must After we are done with adjusting the pbuf pointers we must
adjust the ->data pointer in the seg and the segment adjust the ->data pointer in the seg and the segment
length.*/ length.*/
//去掉报文段中数据编号低于rcv_nxt的数据 //ȥ�����Ķ�����ݱ�ŵ���rcv_nxt�����
off = pcb->rcv_nxt - seqno; off = pcb->rcv_nxt - seqno;
p = inseg.p; p = inseg.p;
LWIP_ASSERT("inseg.p != NULL", inseg.p); LWIP_ASSERT("inseg.p != NULL", inseg.p);
...@@ -1222,8 +1237,8 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1222,8 +1237,8 @@ tcp_receive(struct tcp_pcb *pcb)
if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){//seqno < rcv_nxt if (TCP_SEQ_LT(seqno, pcb->rcv_nxt)){//seqno < rcv_nxt
/* the whole segment is < rcv_nxt */ /* the whole segment is < rcv_nxt */
/* must be a duplicate of a packet that has already been correctly handled */ /* must be a duplicate of a packet that has already been correctly handled */
//报文段中所有数据编号均小于rcv_nxt,则此报文是重复报文, //���Ķ���������ݱ�ž�С��rcv_nxt����˱������ظ����ģ�
//直接向源端响应ACK报文处理 //ֱ����Դ����ӦACK���Ĵ���
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno)); LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: duplicate seqno %"U32_F"\n", seqno));
tcp_ack_now(pcb); tcp_ack_now(pcb);
...@@ -1234,14 +1249,14 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1234,14 +1249,14 @@ tcp_receive(struct tcp_pcb *pcb)
and below rcv_nxt + rcv_wnd) in order to be further and below rcv_nxt + rcv_wnd) in order to be further
processed. */ processed. */
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, 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) { if (pcb->rcv_nxt == seqno) {
/* The incoming segment is the next in sequence. We check if /* The incoming segment is the next in sequence. We check if
we have to trim the end of the segment and update rcv_nxt we have to trim the end of the segment and update rcv_nxt
and pass the data to the application. */ 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, LWIP_DEBUGF(TCP_INPUT_DEBUG,
("tcp_receive: other end overran receive window" ("tcp_receive: other end overran receive window"
"seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n", "seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
...@@ -1408,17 +1423,17 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1408,17 +1423,17 @@ tcp_receive(struct tcp_pcb *pcb)
contains less data. */ contains less data. */
prev = NULL; prev = NULL;
for(next = pcb->ooseq; next != NULL; next = next->next) {//ooseq取下第M个报文段,该报文段非空M++  
if (seqno == next->tcphdr->seqno) {//该报文段起始编号== 要插入的报文段编号 if (seqno == next->tcphdr->seqno) {//�ñ��Ķ���ʼ���== Ҫ����ı��Ķα��
/* The sequence number of the incoming segment is the /* The sequence number of the incoming segment is the
same as the sequence number of the segment on same as the sequence number of the segment on
->ooseq. We check the lengths to see which one to ->ooseq. We check the lengths to see which one to
discard. */ discard. */
if (inseg.len > next->len) {//要插入的报文段编号更长 if (inseg.len > next->len) {//Ҫ����ı��Ķα�Ÿ�
/* The incoming segment is larger than the old /* The incoming segment is larger than the old
segment. We replace some segments with the new segment. We replace some segments with the new
one. */ one. */
cseg = tcp_seg_copy(&inseg);//要插入的报文段代替第M个报文段 cseg = tcp_seg_copy(&inseg);//Ҫ����ı��Ķδ����M�����Ķ�
if (cseg != NULL) { if (cseg != NULL) {
if (prev != NULL) { if (prev != NULL) {
prev->next = cseg; prev->next = cseg;
...@@ -1524,7 +1539,7 @@ tcp_receive(struct tcp_pcb *pcb) ...@@ -1524,7 +1539,7 @@ tcp_receive(struct tcp_pcb *pcb)
/*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) || /*if (TCP_SEQ_GT(pcb->rcv_nxt, seqno) ||
TCP_SEQ_GEQ(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/ 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)){ if(!TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd-1)){
tcp_ack_now(pcb);//向源端返回一个立即确认报文 tcp_ack_now(pcb);//��Դ�˷���һ������ȷ�ϱ���
} }
} }
} }
......
...@@ -52,9 +52,14 @@ ...@@ -52,9 +52,14 @@
#include "lwip/inet_chksum.h" #include "lwip/inet_chksum.h"
#include "lwip/stats.h" #include "lwip/stats.h"
#include "lwip/snmp.h" #include "lwip/snmp.h"
#include "netif/etharp.h"
#include <string.h> #include <string.h>
#ifdef MEMLEAK_DEBUG
static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#endif
/* Define some copy-macros for checksum-on-copy so that the code looks /* Define some copy-macros for checksum-on-copy so that the code looks
nicer by preventing too many ifdef's. */ nicer by preventing too many ifdef's. */
#if TCP_CHECKSUM_ON_COPY #if TCP_CHECKSUM_ON_COPY
...@@ -333,16 +338,16 @@ tcp_write_checks(struct tcp_pcb *pcb, u16_t len) ...@@ -333,16 +338,16 @@ tcp_write_checks(struct tcp_pcb *pcb, u16_t len)
/** /**
* Write data for sending (but does not send it immediately). * Write data for sending (but does not send it immediately).
*连接向另一方发送数据,该函数构造一个报文段并放在控制块缓冲队列中 *��������һ��������ݣ��ú�����һ�����Ķβ����ڿ��ƿ黺�������
* It waits in the expectation of more data being sent soon (as * It waits in the expectation of more data being sent soon (as
* it can send them more efficiently by combining them together). * it can send them more efficiently by combining them together).
* To prompt the system to send data now, call tcp_output() after * To prompt the system to send data now, call tcp_output() after
* calling tcp_write(). * calling tcp_write().
* *
* @param pcb Protocol control block for the TCP connection to enqueue data for.相应连接控制块 * @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 arg Pointer to the data to be enqueued for sending.���������ʼ��ַ
* @param len Data length in bytes待发送数据长度 * @param len Data length in bytes������ݳ���
* @param apiflags combination of following flags :数据是否进行拷贝,以及报文段首部是否好设置PSH标 * @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_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, * - 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 * @return ERR_OK if enqueued, another err_t on error
...@@ -883,7 +888,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb) ...@@ -883,7 +888,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
/** /**
* Find out what we can send and send it * Find out what we can send and send it
*发送控制块缓冲队列的报文段 *���Ϳ��ƿ黺����еı��Ķ�
* @param pcb Protocol control block for the TCP connection to send data * @param pcb Protocol control block for the TCP connection to send data
* @return ERR_OK if data has been sent or nothing to send * @return ERR_OK if data has been sent or nothing to send
* another err_t on error * another err_t on error
...@@ -899,12 +904,12 @@ tcp_output(struct tcp_pcb *pcb) ...@@ -899,12 +904,12 @@ tcp_output(struct tcp_pcb *pcb)
/* First, check if we are invoked by the TCP input processing /* First, check if we are invoked by the TCP input processing
code. If so, we do not output anything. Instead, we rely on the code. If so, we do not output anything. Instead, we rely on the
input processing code to call us when input processing is done input processing code to call us when input processing is done
with. 如果控制块当前正有数据被处理,直接返回*/ with. �����ƿ鵱ǰ������ݱ����?ֱ�ӷ���*/
if (tcp_input_pcb == pcb) { if (tcp_input_pcb == pcb) {
return ERR_OK; return ERR_OK;
} }
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);//从发送窗口和阻塞窗口取小者得到有效发送窗口 wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);//�ӷ��ʹ��ں������ȡС�ߵõ���Ч���ʹ���
seg = pcb->unsent; seg = pcb->unsent;
...@@ -917,13 +922,13 @@ tcp_output(struct tcp_pcb *pcb) ...@@ -917,13 +922,13 @@ tcp_output(struct tcp_pcb *pcb)
if (pcb->flags & TF_ACK_NOW && if (pcb->flags & TF_ACK_NOW &&
(seg == NULL || (seg == NULL ||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) { 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 should point to last segment on unacked queue */
useg = pcb->unacked; useg = pcb->unacked;
if (useg != NULL) { if (useg != NULL) {
for (; useg->next != NULL; useg = useg->next);//得到尾部 for (; useg->next != NULL; useg = useg->next);//�õ�β��
} }
#if TCP_OUTPUT_DEBUG #if TCP_OUTPUT_DEBUG
...@@ -948,7 +953,7 @@ tcp_output(struct tcp_pcb *pcb) ...@@ -948,7 +953,7 @@ tcp_output(struct tcp_pcb *pcb)
} }
#endif /* TCP_CWND_DEBUG */ #endif /* TCP_CWND_DEBUG */
/* data available and window allows it to be sent? /* data available and window allows it to be sent?
*当前有效窗口允许报文发送,循环发送报文,直至填满窗口*/ *��ǰ��Ч�������?�ķ��ͣ�ѭ�����ͱ��ģ�ֱ�������*/
while (seg != NULL && while (seg != NULL &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) { ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
LWIP_ASSERT("RST not expected here!", LWIP_ASSERT("RST not expected here!",
...@@ -976,30 +981,30 @@ tcp_output(struct tcp_pcb *pcb) ...@@ -976,30 +981,30 @@ tcp_output(struct tcp_pcb *pcb)
pcb->unsent = seg->next; pcb->unsent = seg->next;
if (pcb->state != SYN_SENT) { if (pcb->state != SYN_SENT) {
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);//填写首部ACK标 TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);//��д�ײ�ACK��־
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);//清除标志位 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)) { 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,或者带有 /* put segment on unacknowledged list if length > 0
* 有SYN、FIN标志,则将该报文段加入到未确认队列,以便超时重传*/ */
if (TCP_TCPLEN(seg) > 0) { if (TCP_TCPLEN(seg) > 0) {
seg->next = NULL; seg->next = NULL;
/* unacked list is empty? 直接挂*/ /* unacked list is empty? ֱӹҽ�*/
if (pcb->unacked == NULL) { if (pcb->unacked == NULL) {
pcb->unacked = seg; pcb->unacked = seg;
useg = seg; useg = seg;
/* unacked list is not empty?将当前报文按顺序组织在队列中 */ /* unacked list is not empty?����ǰ���İ�˳����֯�ڶ����� */
} else { } else {
/* In the case of fast retransmit, the packet should not go to the tail /* 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 * 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))) { if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) {
/* add segment to before tail of unacked list, keeping the list sorted */ /* add segment to before tail of unacked list, keeping the list sorted */
struct tcp_seg **cur_seg = &(pcb->unacked); struct tcp_seg **cur_seg = &(pcb->unacked);
...@@ -1009,17 +1014,17 @@ tcp_output(struct tcp_pcb *pcb) ...@@ -1009,17 +1014,17 @@ tcp_output(struct tcp_pcb *pcb)
} }
seg->next = (*cur_seg); seg->next = (*cur_seg);
(*cur_seg) = seg; (*cur_seg) = seg;
} else {//报文序号最高,则放在未确认队列末尾 } else {//���������ߣ������δȷ�϶���ĩβ
/* add segment to tail of unacked list */ /* add segment to tail of unacked list */
useg->next = seg; useg->next = seg;
useg = useg->next; useg = useg->next;
} }
} }
/* do not queue empty segments on the unacked list */ /* do not queue empty segments on the unacked list */
} else {//报文段长度为0,直接删除,无需重传 } else {//���Ķγ���Ϊ0��ֱ��ɾ�������ش�
tcp_seg_free(seg); tcp_seg_free(seg);
} }
seg = pcb->unsent;//发送下一个报文段 seg = pcb->unsent;//������һ�����Ķ�
} }
#if TCP_OVERSIZE #if TCP_OVERSIZE
if (pcb->unsent == NULL) { if (pcb->unsent == NULL) {
...@@ -1028,7 +1033,7 @@ tcp_output(struct tcp_pcb *pcb) ...@@ -1028,7 +1033,7 @@ tcp_output(struct tcp_pcb *pcb)
} }
#endif /* TCP_OVERSIZE */ #endif /* TCP_OVERSIZE */
//发送窗口填满导致报文不能发送,启动清零窗口探测 //���ʹ��������±��IJ��ܷ��ͣ��������㴰��̽�⡣
if (seg != NULL && pcb->persist_backoff == 0 && if (seg != NULL && pcb->persist_backoff == 0 &&
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) { ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > pcb->snd_wnd) {
/* prepare for persist timer */ /* prepare for persist timer */
...@@ -1036,7 +1041,7 @@ tcp_output(struct tcp_pcb *pcb) ...@@ -1036,7 +1041,7 @@ tcp_output(struct tcp_pcb *pcb)
pcb->persist_backoff = 1; pcb->persist_backoff = 1;
} }
pcb->flags &= ~TF_NAGLEMEMERR;//清内存错误标 pcb->flags &= ~TF_NAGLEMEMERR;//���ڴ�����־
return ERR_OK; return ERR_OK;
} }
...@@ -1235,11 +1240,47 @@ void ...@@ -1235,11 +1240,47 @@ void
tcp_rexmit_rto(struct tcp_pcb *pcb) tcp_rexmit_rto(struct tcp_pcb *pcb)
{ {
struct tcp_seg *seg; 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) { if (pcb->unacked == NULL) {
return; 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 */ /* Move all unacked segments to the head of the unsent queue */
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next); for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
/* concatenate unsent queue after unacked queue */ /* concatenate unsent queue after unacked queue */
...@@ -1248,6 +1289,7 @@ tcp_rexmit_rto(struct tcp_pcb *pcb) ...@@ -1248,6 +1289,7 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
pcb->unsent = pcb->unacked; pcb->unsent = pcb->unacked;
/* unacked queue is now empty */ /* unacked queue is now empty */
pcb->unacked = NULL; pcb->unacked = NULL;
#endif
/* increment number of retransmissions */ /* increment number of retransmissions */
++pcb->nrtx; ++pcb->nrtx;
...@@ -1405,6 +1447,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) ...@@ -1405,6 +1447,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
struct pbuf *p; struct pbuf *p;
struct tcp_hdr *tcphdr; struct tcp_hdr *tcphdr;
struct tcp_seg *seg; struct tcp_seg *seg;
u16_t offset = 0;
u16_t len; u16_t len;
u8_t is_fin; u8_t is_fin;
...@@ -1423,6 +1466,11 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) ...@@ -1423,6 +1466,11 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
if(seg == NULL) { if(seg == NULL) {
seg = pcb->unsent; seg = pcb->unsent;
} else {
struct ip_hdr *iphdr = NULL;
iphdr = (struct ip_hdr *)((char*)seg->p->payload + SIZEOF_ETH_HDR);
offset = IPH_HL(iphdr)*4;
offset += SIZEOF_ETH_HDR;
} }
if(seg == NULL) { if(seg == NULL) {
return; return;
...@@ -1446,7 +1494,12 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) ...@@ -1446,7 +1494,12 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
/* Data segment, copy in one byte from the head of the unacked queue */ /* Data segment, copy in one byte from the head of the unacked queue */
struct tcp_hdr *thdr = (struct tcp_hdr *)seg->p->payload; struct tcp_hdr *thdr = (struct tcp_hdr *)seg->p->payload;
char *d = ((char *)p->payload + TCP_HLEN); char *d = ((char *)p->payload + TCP_HLEN);
pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4); if (pcb->unacked == NULL)
pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4);
else {
thdr = (struct tcp_hdr *)((char*)seg->p->payload + offset);
pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4 + offset);
}
} }
#if CHECKSUM_GEN_TCP #if CHECKSUM_GEN_TCP
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment