Commit c674d191 authored by Johny Mattsson's avatar Johny Mattsson
Browse files

Upgraded open-source LWIP.

From Espressif's lwip_open_src_template_proj_for_v1.3.0.zip
parent c1cd58e0
/******************************************************************************
* FunctionName : espconn_init
* Description : dummy the espconn_init
* Parameters : none
* Returns : none
*******************************************************************************/
void espconn_init()
{
// dummy function, do nothing.
}
...@@ -23,14 +23,15 @@ ...@@ -23,14 +23,15 @@
#include "lwip/app/espconn_tcp.h" #include "lwip/app/espconn_tcp.h"
#include "lwip/app/espconn_udp.h" #include "lwip/app/espconn_udp.h"
#include "lwip/app/espconn.h" #include "lwip/app/espconn.h"
#include "user_interface.h" #include "user_interface.h"
espconn_msg *plink_active = NULL; espconn_msg *plink_active = NULL;
espconn_msg *pserver_list = NULL; espconn_msg *pserver_list = NULL;
remot_info premot[5]; remot_info premot[linkMax];
uint32 link_timer = 0;
struct espconn_packet pktinfo[2];
static uint8 espconn_tcp_get_buf_count(espconn_buf *pesp_buf);
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_copy_partial * FunctionName : espconn_copy_partial
* Description : reconnect with host * Description : reconnect with host
...@@ -122,38 +123,127 @@ void ICACHE_FLASH_ATTR espconn_list_delete(espconn_msg **phead, espconn_msg* pde ...@@ -122,38 +123,127 @@ void ICACHE_FLASH_ATTR espconn_list_delete(espconn_msg **phead, espconn_msg* pde
}*/ }*/
} }
/******************************************************************************
* FunctionName : espconn_pbuf_create
* Description : insert the node to the active connection list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_pbuf_create(espconn_buf **phead, espconn_buf* pinsert)
{
espconn_buf *plist = NULL;
if (*phead == NULL)
*phead = pinsert;
else {
plist = *phead;
while (plist->pnext != NULL) {
plist = plist->pnext;
}
plist->pnext = pinsert;
}
pinsert->pnext = NULL;
}
/******************************************************************************
* FunctionName : espconn_pbuf_delete
* Description : remove the node from the active connection list
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_pbuf_delete(espconn_buf **phead, espconn_buf* pdelete)
{
espconn_buf *plist = NULL;
plist = *phead;
if (plist == NULL){
*phead = NULL;
} else {
if (plist == pdelete){
*phead = plist->pnext;
} else {
while (plist != NULL) {
if (plist->pnext == pdelete){
plist->pnext = pdelete->pnext;
}
plist = plist->pnext;
}
}
}
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_find_connection * FunctionName : espconn_find_connection
* Description : Initialize the server: set up a listening PCB and bind it to * Description : Initialize the server: set up a listening PCB and bind it to
* the defined port * the defined port
* Parameters : espconn -- the espconn used to build server * Parameters : espconn -- the espconn used to build server
* Returns : none * Returns : true or false
*******************************************************************************/ *******************************************************************************/
bool ICACHE_FLASH_ATTR espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode) bool ICACHE_FLASH_ATTR espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode)
{ {
espconn_msg *plist = NULL; espconn_msg *plist = NULL;
struct ip_addr ip_remot; struct ip_addr ip_remot;
struct ip_addr ip_list; struct ip_addr ip_list;
plist = plink_active;
while(plist != NULL){ if (pespconn == NULL)
if (pespconn == plist->pespconn){ return false;
/*find the active connection node*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (pespconn == plist->pespconn) {
*pnode = plist; *pnode = plist;
return true; return true;
} else { }
IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0], pespconn->proto.tcp->remote_ip[1], }
pespconn->proto.tcp->remote_ip[2], pespconn->proto.tcp->remote_ip[3]);
/*find the active server node*/
IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0], plist->pcommon.remote_ip[1], for (plist = pserver_list; plist != NULL; plist = plist->pnext){
plist->pcommon.remote_ip[2], plist->pcommon.remote_ip[3]); if (pespconn == plist->pespconn) {
if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)){ if (pespconn->proto.tcp == NULL)
*pnode = plist; return false;
return true;
IP4_ADDR(&ip_remot, pespconn->proto.tcp->remote_ip[0],
pespconn->proto.tcp->remote_ip[1],
pespconn->proto.tcp->remote_ip[2],
pespconn->proto.tcp->remote_ip[3]);
if ((ip_remot.addr == IPADDR_ANY) || (pespconn->proto.tcp->remote_port == 0))
return false;
/*find the active connection node*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
IP4_ADDR(&ip_list, plist->pcommon.remote_ip[0],
plist->pcommon.remote_ip[1], plist->pcommon.remote_ip[2],
plist->pcommon.remote_ip[3]);
if ((ip_list.addr == ip_remot.addr) && (pespconn->proto.tcp->remote_port == plist->pcommon.remote_port)) {
*pnode = plist;
return true;
}
} }
return false;
}
}
return false;
}
/******************************************************************************
* FunctionName : espconn_get_acticve_num
* Description : get the count of simulatenously active connections
* Parameters : type -- the type
* Returns : the count of simulatenously active connections
*******************************************************************************/
static uint8 ICACHE_FLASH_ATTR
espconn_get_acticve_num(uint8 type)
{
espconn_msg *plist = NULL;
uint8 num_tcp_active = 0;
for (plist = plink_active; plist != NULL; plist = plist->pnext) {
if (plist->pespconn != NULL && plist->pespconn->type == type) {
num_tcp_active++;
} }
plist = plist ->pnext;
} }
return false;
return num_tcp_active;
} }
/****************************************************************************** /******************************************************************************
...@@ -170,12 +260,18 @@ espconn_connect(struct espconn *espconn) ...@@ -170,12 +260,18 @@ espconn_connect(struct espconn *espconn)
uint8 connect_status = 0; uint8 connect_status = 0;
sint8 value = ESPCONN_OK; sint8 value = ESPCONN_OK;
espconn_msg *plist = NULL; espconn_msg *plist = NULL;
remot_info *pinfo = NULL;
if (espconn == NULL) { if (espconn == NULL) {
return ESPCONN_ARG; return ESPCONN_ARG;
} else if (espconn ->type != ESPCONN_TCP) } else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG; return ESPCONN_ARG;
/*Check the active node count whether is the limit or not*/
if (espconn_get_acticve_num(ESPCONN_TCP) >= espconn_tcp_get_max_con())
return ESPCONN_ISCONN;
/*Check the IP address whether is zero or not in different mode*/
if (wifi_get_opmode() == ESPCONN_STA){ if (wifi_get_opmode() == ESPCONN_STA){
wifi_get_ip_info(STA_NETIF,&ipinfo); wifi_get_ip_info(STA_NETIF,&ipinfo);
if (ipinfo.ip.addr == 0){ if (ipinfo.ip.addr == 0){
...@@ -202,14 +298,17 @@ espconn_connect(struct espconn *espconn) ...@@ -202,14 +298,17 @@ espconn_connect(struct espconn *espconn)
wifi_get_ip_info(STA_NETIF,&ipinfo); wifi_get_ip_info(STA_NETIF,&ipinfo);
if (ipinfo.ip.addr == 0) if (ipinfo.ip.addr == 0)
return ESPCONN_RTE; return ESPCONN_RTE;
} else if (connect_status == STATION_IDLE){
return ESPCONN_RTE;
} else { } else {
return connect_status; return connect_status;
} }
} }
} }
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){ for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_TCP){ if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){
if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){ if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){
return ESPCONN_ISCONN; return ESPCONN_ISCONN;
} }
...@@ -239,8 +338,9 @@ espconn_create(struct espconn *espconn) ...@@ -239,8 +338,9 @@ espconn_create(struct espconn *espconn)
return ESPCONN_ARG; return ESPCONN_ARG;
} }
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){ for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_UDP){ if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){
if (espconn->proto.udp->local_port == plist->pespconn->proto.udp->local_port){ if (espconn->proto.udp->local_port == plist->pespconn->proto.udp->local_port){
return ESPCONN_ISCONN; return ESPCONN_ISCONN;
} }
...@@ -265,32 +365,123 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length) ...@@ -265,32 +365,123 @@ espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length)
{ {
espconn_msg *pnode = NULL; espconn_msg *pnode = NULL;
bool value = false; bool value = false;
if (espconn == NULL) { err_t error = ESPCONN_OK;
if (espconn == NULL || psent == NULL || length == 0) {
return ESPCONN_ARG; return ESPCONN_ARG;
} }
espconn ->state = ESPCONN_WRITE;
value = espconn_find_connection(espconn, &pnode);
switch (espconn ->type) {
case ESPCONN_TCP:
// if (value && (pnode->pcommon.write_len == pnode->pcommon.write_total)){
if (value && (pnode->pcommon.cntr == 0)){
espconn_tcp_sent(pnode, psent, length);
}else
return ESPCONN_ARG;
break;
case ESPCONN_UDP: {
if (value)
espconn_udp_sent(pnode, psent, length);
else
return ESPCONN_ARG;
break;
}
default : /*Find the node depend on the espconn message*/
break; value = espconn_find_connection(espconn, &pnode);
if (value){
espconn ->state = ESPCONN_WRITE;
switch (espconn ->type) {
case ESPCONN_TCP:
/* calling sent function frequently,make sure last packet has been backup or sent fully*/
if (pnode->pcommon.write_flag){
espconn_buf *pbuf = NULL;
/*If total number of espconn_buf on the unsent lists exceeds the set maximum, return an error */
if (espconn_copy_enabled(pnode)){
if (espconn_tcp_get_buf_count(pnode->pcommon.pbuf) >= pnode ->pcommon.pbuf_num)
return ESPCONN_MAXNUM;
}
pbuf = (espconn_buf*) os_zalloc(sizeof(espconn_buf));
if (pbuf == NULL)
return ESPCONN_MEM;
else {
/*Backup the application packet information for send more data*/
pbuf->payload = psent;
pbuf->punsent = pbuf->payload;
pbuf->unsent = length;
pbuf->len = length;
/*insert the espconn_pbuf to the list*/
espconn_pbuf_create(&pnode->pcommon.pbuf, pbuf);
if (pnode->pcommon.ptail == NULL)
pnode->pcommon.ptail = pbuf;
}
/*when set the data copy option. change the flag for next packet*/
if (espconn_copy_disabled(pnode))
pnode->pcommon.write_flag = false;
error = espconn_tcp_write(pnode);
if (error != ESPCONN_OK){
/*send the application packet fail,
* ensure that each allocated is deleted*/
espconn_pbuf_delete(&pnode->pcommon.pbuf, pbuf);
os_free(pbuf);
pbuf = NULL;
}
return error;
} else
return ESPCONN_ARG;
break;
case ESPCONN_UDP:
return espconn_udp_sent(pnode, psent, length);
break;
default :
break;
}
} }
return ESPCONN_OK; return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_send
* Description : sent data for client or server
* Parameters : espconn -- espconn to set for client or server
* psent -- data to send
* length -- length of data to send
* Returns : none
*******************************************************************************/
sint8 espconn_send(struct espconn *espconn, uint8 *psent, uint16 length) __attribute__((alias("espconn_sent")));
/******************************************************************************
* FunctionName : espconn_tcp_get_wnd
* Description : get the window size of simulatenously active TCP connections
* Parameters : none
* Returns : the number of TCP_MSS active TCP connections
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_wnd(void)
{
uint8 tcp_num = 0;
tcp_num = (TCP_WND / TCP_MSS);
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_con
* Description : set the window size simulatenously active TCP connections
* Parameters : num -- the number of TCP_MSS
* Returns : ESPCONN_ARG -- Illegal argument
* ESPCONN_OK -- No error
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_wnd(uint8 num)
{
if (num == 0 || num > linkMax)
return ESPCONN_ARG;
TCP_WND = (num * TCP_MSS);
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_mss
* Description : get the mss size of simulatenously active TCP connections
* Parameters : none
* Returns : the size of TCP_MSS active TCP connections
*******************************************************************************/
uint16 ICACHE_FLASH_ATTR espconn_tcp_get_mss(void)
{
uint16 tcp_num = 0;
tcp_num = TCP_MSS;
return tcp_num;
} }
/****************************************************************************** /******************************************************************************
...@@ -316,13 +507,73 @@ uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_con(void) ...@@ -316,13 +507,73 @@ uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_con(void)
*******************************************************************************/ *******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con(uint8 num) sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con(uint8 num)
{ {
if (num == 0) if (num == 0 || num > linkMax)
return ESPCONN_ARG; return ESPCONN_ARG;
MEMP_NUM_TCP_PCB = num; MEMP_NUM_TCP_PCB = num;
return ESPCONN_OK; return ESPCONN_OK;
} }
/******************************************************************************
* FunctionName : espconn_tcp_get_max_retran
* Description : get the Maximum number of retransmissions of data active TCP connections
* Parameters : none
* Returns : the Maximum number of retransmissions
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_retran(void)
{
uint8 tcp_num = 0;
tcp_num = TCP_MAXRTX;
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_retran
* Description : set the Maximum number of retransmissions of data active TCP connections
* Parameters : num -- the Maximum number of retransmissions
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_retran(uint8 num)
{
if (num == 0 || num > 12)
return ESPCONN_ARG;
TCP_MAXRTX = num;
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_max_syn
* Description : get the Maximum number of retransmissions of SYN segments
* Parameters : none
* Returns : the Maximum number of retransmissions
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR espconn_tcp_get_max_syn(void)
{
uint8 tcp_num = 0;
tcp_num = TCP_SYNMAXRTX;
return tcp_num;
}
/******************************************************************************
* FunctionName : espconn_tcp_set_max_syn
* Description : set the Maximum number of retransmissions of SYN segments
* Parameters : num -- the Maximum number of retransmissions
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_syn(uint8 num)
{
if (num == 0 || num > 12)
return ESPCONN_ARG;
TCP_SYNMAXRTX = num;
return ESPCONN_OK;
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_tcp_get_max_con_allow * FunctionName : espconn_tcp_get_max_con_allow
* Description : get the count of simulatenously active connections on the server * Description : get the count of simulatenously active connections on the server
...@@ -368,6 +619,51 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con_allow(struct espconn *espconn, u ...@@ -368,6 +619,51 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_set_max_con_allow(struct espconn *espconn, u
return ESPCONN_ARG; return ESPCONN_ARG;
} }
/******************************************************************************
* FunctionName : espconn_tcp_set_buf_count
* Description : set the total number of espconn_buf on the unsent lists for one
* activate connection
* Parameters : espconn -- espconn to set the count
* num -- the total number of espconn_buf
* Returns : result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_tcp_set_buf_count(struct espconn *espconn, uint8 num)
{
espconn_msg *plist = NULL;
if (espconn == NULL || (num > TCP_SND_QUEUELEN))
return ESPCONN_ARG;
/*find the node from the active connection list*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn && plist->pespconn == espconn && espconn->type == ESPCONN_TCP){
plist->pcommon.pbuf_num = num;
return ESPCONN_OK;
}
}
if (plist == NULL)
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_tcp_get_buf_count
* Description : get the count of the current node which has espconn_buf
* Parameters : pesp_buf -- the list head of espconn_buf type
* Returns : the count of the current node which has espconn_buf
*******************************************************************************/
static uint8 ICACHE_FLASH_ATTR espconn_tcp_get_buf_count(espconn_buf *pesp_buf)
{
espconn_buf *pbuf_list = pesp_buf;
uint8 pbuf_num = 0;
/*polling the list get the count of the current node*/
while (pbuf_list != NULL){
pbuf_list = pbuf_list->pnext;
pbuf_num ++;
}
return pbuf_num;
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_regist_sentcb * FunctionName : espconn_regist_sentcb
* Description : Used to specify the function that should be called when data * Description : Used to specify the function that should be called when data
...@@ -388,6 +684,26 @@ espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb) ...@@ -388,6 +684,26 @@ espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb)
return ESPCONN_OK; return ESPCONN_OK;
} }
/******************************************************************************
* FunctionName : espconn_regist_sentcb
* Description : Used to specify the function that should be called when data
* has been successfully delivered to the remote host.
* Parameters : espconn -- espconn to set the sent callback
* sent_cb -- sent callback function to call for this espconn
* when data is successfully sent
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_regist_write_finish(struct espconn *espconn, espconn_connect_callback write_finish_fn)
{
if (espconn == NULL || espconn ->proto.tcp == NULL || espconn->type == ESPCONN_UDP) {
return ESPCONN_ARG;
}
espconn ->proto.tcp->write_finish_fn = write_finish_fn;
return ESPCONN_OK;
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_regist_connectcb * FunctionName : espconn_regist_connectcb
* Description : used to specify the function that should be called when * Description : used to specify the function that should be called when
...@@ -484,27 +800,11 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui ...@@ -484,27 +800,11 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui
switch (pespconn->type){ switch (pespconn->type){
case ESPCONN_TCP: case ESPCONN_TCP:
while(plist != NULL){ while(plist != NULL){
if ((plist->pespconn->type == ESPCONN_TCP) && (plist->preverse == pespconn)){ if (plist->preverse == pespconn){
switch (typeflags){ premot[pespconn->link_cnt].state = plist->pespconn->state;
case ESPCONN_SSL: premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
if (plist->pssl != NULL){ os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
premot[pespconn->link_cnt].state = plist->pespconn->state; pespconn->link_cnt ++;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
pespconn->link_cnt ++;
}
break;
case ESPCONN_NORM:
if (plist->pssl == NULL){
premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
pespconn->link_cnt ++;
}
break;
default:
break;
}
} }
plist = plist->pnext; plist = plist->pnext;
} }
...@@ -512,7 +812,7 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui ...@@ -512,7 +812,7 @@ espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, ui
break; break;
case ESPCONN_UDP: case ESPCONN_UDP:
while(plist != NULL){ while(plist != NULL){
if (plist->pespconn->type == ESPCONN_UDP){ if (plist->pespconn && plist->pespconn->type == ESPCONN_UDP){
premot[pespconn->link_cnt].state = plist->pespconn->state; premot[pespconn->link_cnt].state = plist->pespconn->state;
premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port; premot[pespconn->link_cnt].remote_port = plist->pcommon.remote_port;
os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4); os_memcpy(premot[pespconn->link_cnt].remote_ip, plist->pcommon.remote_ip, 4);
...@@ -545,8 +845,9 @@ espconn_accept(struct espconn *espconn) ...@@ -545,8 +845,9 @@ espconn_accept(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_TCP) } else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG; return ESPCONN_ARG;
/*check the active node information whether is the same as the entity or not*/
for (plist = plink_active; plist != NULL; plist = plist->pnext){ for (plist = plink_active; plist != NULL; plist = plist->pnext){
if (plist->pespconn->type == ESPCONN_TCP){ if (plist->pespconn && plist->pespconn->type == ESPCONN_TCP){
if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){ if (espconn->proto.tcp->local_port == plist->pespconn->proto.tcp->local_port){
return ESPCONN_ISCONN; return ESPCONN_ISCONN;
} }
...@@ -567,11 +868,13 @@ espconn_accept(struct espconn *espconn) ...@@ -567,11 +868,13 @@ espconn_accept(struct espconn *espconn)
sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 interval, uint8 type_flag) sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 interval, uint8 type_flag)
{ {
espconn_msg *pnode = NULL; espconn_msg *pnode = NULL;
espconn_msg *ptime_msg = NULL;
bool value = false; bool value = false;
if ((espconn == NULL) || (type_flag > 0x01)) if ((espconn == NULL) || (type_flag > 0x01))
return ESPCONN_ARG; return ESPCONN_ARG;
if (type_flag == 0x01){ if (type_flag == 0x01){
/*set the timeout time for one active connection of the server*/
value = espconn_find_connection(espconn, &pnode); value = espconn_find_connection(espconn, &pnode);
if (value){ if (value){
pnode->pcommon.timeout = interval; pnode->pcommon.timeout = interval;
...@@ -579,10 +882,17 @@ sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 inte ...@@ -579,10 +882,17 @@ sint8 ICACHE_FLASH_ATTR espconn_regist_time(struct espconn *espconn, uint32 inte
} else } else
return ESPCONN_ARG; return ESPCONN_ARG;
} else { } else {
link_timer = interval; /*set the timeout time for all active connection of the server*/
os_printf("espconn_regist_time %d\n", link_timer); ptime_msg = pserver_list;
return ESPCONN_OK; while (ptime_msg != NULL){
if (ptime_msg->pespconn == espconn){
ptime_msg->pcommon.timeout = interval;
return ESPCONN_OK;
}
ptime_msg = ptime_msg->pnext;
}
} }
return ESPCONN_ARG;
} }
/****************************************************************************** /******************************************************************************
...@@ -602,41 +912,233 @@ espconn_disconnect(struct espconn *espconn) ...@@ -602,41 +912,233 @@ espconn_disconnect(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_TCP) } else if (espconn ->type != ESPCONN_TCP)
return ESPCONN_ARG; return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode); value = espconn_find_connection(espconn, &pnode);
if (value){ if (value){
/*protect for redisconnection*/
if (espconn->state == ESPCONN_CLOSE)
return ESPCONN_INPROGRESS;
espconn_tcp_disconnect(pnode); espconn_tcp_disconnect(pnode);
return ESPCONN_OK; return ESPCONN_OK;
} else } else
return ESPCONN_ARG; return ESPCONN_ARG;
} }
/******************************************************************************
* FunctionName : espconn_get_packet_info
* Description : get the packet info with host
* Parameters : espconn -- the espconn used to disconnect the connection
* infoarg -- the packet info
* Returns : the errur code
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg)
{
espconn_msg *pnode = NULL;
err_t err;
bool value = false;
if (espconn == NULL || infoarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
if (pcb == NULL)
return ESPCONN_ARG;
pnode->pcommon.packet_info.packseq_nxt = pcb->rcv_nxt;
pnode->pcommon.packet_info.packseqno = pcb->snd_nxt;
pnode->pcommon.packet_info.snd_buf_size = pcb->snd_buf;
pnode->pcommon.packet_info.total_queuelen = TCP_SND_QUEUELEN;
pnode->pcommon.packet_info.snd_queuelen = pnode->pcommon.packet_info.total_queuelen - pcb->snd_queuelen;
os_memcpy(infoarg,(void*)&pnode->pcommon.packet_info, sizeof(struct espconn_packet));
return ESPCONN_OK;
} else {
switch (espconn->state){
case ESPCONN_CLOSE:
os_memcpy(infoarg,(void*)&pktinfo[0], sizeof(struct espconn_packet));
err = ESPCONN_OK;
break;
case ESPCONN_NONE:
os_memcpy(infoarg,(void*)&pktinfo[1], sizeof(struct espconn_packet));
err = ESPCONN_OK;
break;
default:
err = ESPCONN_ARG;
break;
}
return err;
}
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_set_opt * FunctionName : espconn_set_opt
* Description : access port value for client so that we don't end up bouncing * Description : set the option for connections so that we don't end up bouncing
* all connections at the same time . * all connections at the same time .
* Parameters : none * Parameters : espconn -- the espconn used to set the connection
* Returns : access port value * opt -- the option for set
* Returns : the result
*******************************************************************************/ *******************************************************************************/
sint8 ICACHE_FLASH_ATTR sint8 ICACHE_FLASH_ATTR
espconn_set_opt(struct espconn *espconn, uint8 opt) espconn_set_opt(struct espconn *espconn, uint8 opt)
{ {
espconn_msg *pnode = NULL; espconn_msg *pnode = NULL;
struct tcp_pcb *tpcb;
bool value = false;
if (espconn == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value) {
pnode->pcommon.espconn_opt |= opt;
tpcb = pnode->pcommon.pcb;
if (espconn_delay_disabled(pnode))
tcp_nagle_disable(tpcb);
if (espconn_keepalive_disabled(pnode))
espconn_keepalive_enable(tpcb);
return ESPCONN_OK;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_clear_opt
* Description : clear the option for connections so that we don't end up bouncing
* all connections at the same time .
* Parameters : espconn -- the espconn used to set the connection
* opt -- the option for clear
* Returns : the result
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_clear_opt(struct espconn *espconn, uint8 opt)
{
espconn_msg *pnode = NULL;
struct tcp_pcb *tpcb;
bool value = false; bool value = false;
if (espconn == NULL || opt > ESPCONN_END) { if (espconn == NULL) {
return ESPCONN_ARG;; return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP) } else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG; return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode); value = espconn_find_connection(espconn, &pnode);
if (value) { if (value) {
pnode->pcommon.espconn_opt = opt; pnode->pcommon.espconn_opt &= ~opt;
tpcb = pnode->pcommon.pcb;
if (espconn_keepalive_enabled(pnode))
espconn_keepalive_disable(tpcb);
if (espconn_delay_enabled(pnode))
tcp_nagle_enable(tpcb);
return ESPCONN_OK; return ESPCONN_OK;
} else } else
return ESPCONN_ARG; return ESPCONN_ARG;
} }
/******************************************************************************
* FunctionName : espconn_set_keepalive
* Description : access level value for connection so that we set the value for
* keep alive
* Parameters : espconn -- the espconn used to set the connection
* level -- the connection's level
* value -- the value of time(s)
* Returns : access port value
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg)
{
espconn_msg *pnode = NULL;
bool value = false;
sint8 ret = ESPCONN_OK;
if (espconn == NULL || optarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
switch (level){
case ESPCONN_KEEPIDLE:
pcb->keep_idle = 1000 * (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPINTVL:
pcb->keep_intvl = 1000 * (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPCNT:
pcb->keep_cnt = (u32_t)(*(int*)optarg);
ret = ESPCONN_OK;
break;
default:
ret = ESPCONN_ARG;
break;
}
return ret;
} else
return ESPCONN_ARG;
}
/******************************************************************************
* FunctionName : espconn_get_keepalive
* Description : access level value for connection so that we get the value for
* keep alive
* Parameters : espconn -- the espconn used to get the connection
* level -- the connection's level
* Returns : access keep alive value
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg)
{
espconn_msg *pnode = NULL;
bool value = false;
sint8 ret = ESPCONN_OK;
if (espconn == NULL || optarg == NULL) {
return ESPCONN_ARG;;
} else if (espconn->type != ESPCONN_TCP)
return ESPCONN_ARG;
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode);
if (value && espconn_keepalive_disabled(pnode)) {
struct tcp_pcb *pcb = pnode->pcommon.pcb;
switch (level) {
case ESPCONN_KEEPIDLE:
*(int*)optarg = (int)(pcb->keep_idle/1000);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPINTVL:
*(int*)optarg = (int)(pcb->keep_intvl/1000);
ret = ESPCONN_OK;
break;
case ESPCONN_KEEPCNT:
*(int*)optarg = (int)(pcb->keep_cnt);
ret = ESPCONN_OK;
break;
default:
ret = ESPCONN_ARG;
break;
}
return ret;
} else
return ESPCONN_ARG;
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_delete * FunctionName : espconn_delete
* Description : disconnect with host * Description : disconnect with host
...@@ -654,6 +1156,7 @@ espconn_delete(struct espconn *espconn) ...@@ -654,6 +1156,7 @@ espconn_delete(struct espconn *espconn)
} else if (espconn ->type != ESPCONN_UDP) } else if (espconn ->type != ESPCONN_UDP)
return espconn_tcp_delete(espconn); return espconn_tcp_delete(espconn);
/*Find the node depend on the espconn message*/
value = espconn_find_connection(espconn, &pnode); value = espconn_find_connection(espconn, &pnode);
if (value){ if (value){
...@@ -670,7 +1173,8 @@ espconn_delete(struct espconn *espconn) ...@@ -670,7 +1173,8 @@ espconn_delete(struct espconn *espconn)
* Parameters : none * Parameters : none
* Returns : access port value * Returns : access port value
*******************************************************************************/ *******************************************************************************/
uint32 espconn_port(void) uint32 ICACHE_FLASH_ATTR
espconn_port(void)
{ {
uint32 port = 0; uint32 port = 0;
static uint32 randnum = 0; static uint32 randnum = 0;
...@@ -718,32 +1222,17 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t ...@@ -718,32 +1222,17 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t
return dns_gethostbyname(hostname, addr, found, pespconn); return dns_gethostbyname(hostname, addr, found, pespconn);
} }
sint8 espconn_recv_hold(struct espconn *pespconn) { /******************************************************************************
espconn_msg *pnode = NULL; * FunctionName : espconn_dns_setserver
* Description : Initialize one of the DNS servers.
if (pespconn == NULL) { * Parameters : numdns -- the index of the DNS server to set must
return ESPCONN_ARG; * be < DNS_MAX_SERVERS = 2
} * dnsserver -- IP address of the DNS server to set
pespconn->state = ESPCONN_WRITE; * Returns : none
if (!espconn_find_connection(pespconn, &pnode)) { *******************************************************************************/
return ESPCONN_ARG; void ICACHE_FLASH_ATTR
} espconn_dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
{
espconn_tcp_hold(pnode); dns_setserver(numdns,dnsserver);
return ESPCONN_OK;
} }
sint8 espconn_recv_unhold(struct espconn *pespconn) {
espconn_msg *pnode = NULL;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
pespconn->state = ESPCONN_WRITE;
if (!espconn_find_connection(pespconn, &pnode)) {
return ESPCONN_ARG;
}
espconn_tcp_unhold(pnode);
return ESPCONN_OK;
}
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: espconn_mdns.c
*
* Description: udp proto interface
*
* Modification history:
* 2014/3/31, v1.0 create this file.
*******************************************************************************/
#include "ets_sys.h"
#include "os_type.h"
#include "lwip/mdns.h"
/******************************************************************************
* FunctionName : espconn_mdns_enable
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_enable(void)
{
mdns_enable();
}
/******************************************************************************
* FunctionName : espconn_mdns_disable
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_disable(void)
{
mdns_disable();
}
/******************************************************************************
* FunctionName : espconn_mdns_set_hostname
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_set_hostname(char *name)
{
mdns_set_hostname(name);
}
/******************************************************************************
* FunctionName : espconn_mdns_init
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
char* ICACHE_FLASH_ATTR
espconn_mdns_get_hostname(void)
{
return (char *)mdns_get_hostname();
}
/******************************************************************************
* FunctionName : espconn_mdns_get_servername
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_set_servername(const char *name)
{
mdns_set_servername(name);
}
/******************************************************************************
* FunctionName : espconn_mdns_get_servername
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
char* ICACHE_FLASH_ATTR
espconn_mdns_get_servername(void)
{
return (char *)mdns_get_servername();
}
/******************************************************************************
* FunctionName : mdns_server_register
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_server_register(void)
{
mdns_server_register();
}
/******************************************************************************
* FunctionName : mdns_server_register
* Description : join a multicast group
* Parameters : info -- the info of mdns
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_server_unregister(void)
{
mdns_server_unregister();
}
/******************************************************************************
* FunctionName : espconn_mdns_init
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_close(void)
{
mdns_close();
}
/******************************************************************************
* FunctionName : espconn_mdns_init
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
espconn_mdns_init(struct mdns_info *info)
{
mdns_init(info);
}
...@@ -25,8 +25,11 @@ ...@@ -25,8 +25,11 @@
#include "lwip/app/espconn_tcp.h" #include "lwip/app/espconn_tcp.h"
extern espconn_msg *plink_active; extern espconn_msg *plink_active;
extern uint32 link_timer;
extern espconn_msg *pserver_list; extern espconn_msg *pserver_list;
extern struct espconn_packet pktinfo[2];
extern struct tcp_pcb ** const tcp_pcb_lists[];
os_event_t espconn_TaskQueue[espconn_TaskQueueLen];
static err_t static err_t
espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
...@@ -39,6 +42,176 @@ static void ...@@ -39,6 +42,176 @@ static void
espconn_server_close(void *arg, struct tcp_pcb *pcb); espconn_server_close(void *arg, struct tcp_pcb *pcb);
///////////////////////////////common function///////////////////////////////// ///////////////////////////////common function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_kill_oldest
* Description : kill the oldest TCP block
* Parameters : none
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_kill_oldest(void)
{
struct tcp_pcb *pcb, *inactive;
u32_t inactivity;
inactivity = 0;
inactive = NULL;
/* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */
for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
if (inactive != NULL) {
tcp_abort(inactive);
}
/* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */
inactivity = 0;
inactive = NULL;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->state == FIN_WAIT_2){
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
}
/*Purges the PCB, removes it from a PCB list and frees the memory*/
if (inactive != NULL) {
tcp_pcb_remove(&tcp_active_pcbs, inactive);
memp_free(MEMP_TCP_PCB, inactive);
}
/* Go through the list of LAST_ACK pcbs and get the oldest pcb. */
inactivity = 0;
inactive = NULL;
for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->state == LAST_ACK) {
if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
}
}
}
/*Purges the PCB, removes it from a PCB list and frees the memory*/
if (inactive != NULL) {
tcp_pcb_remove(&tcp_active_pcbs, inactive);
memp_free(MEMP_TCP_PCB, inactive);
}
}
/******************************************************************************
* FunctionName : espconn_kill_oldest_pcb
* Description : find the oldest TCP block by state
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_kill_oldest_pcb(void)
{
struct tcp_pcb *cpcb = NULL;
uint8 i = 0;
uint8 num_tcp_fin = 0;
for(i = 2; i < 4; i ++){
for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
if (cpcb->state == TIME_WAIT){
num_tcp_fin ++;
if (num_tcp_fin == MEMP_NUM_TCP_PCB)
break;
}
if (cpcb->state == FIN_WAIT_2 || cpcb->state == LAST_ACK){
num_tcp_fin++;
if (num_tcp_fin == MEMP_NUM_TCP_PCB)
break;
}
}
if (num_tcp_fin == MEMP_NUM_TCP_PCB){
num_tcp_fin = 0;
espconn_kill_oldest();
}
}
}
/******************************************************************************
* FunctionName : espconn_kill_pcb
* Description : kill all the TCP block by port
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR espconn_kill_pcb(u16_t port)
{
struct tcp_pcb *cpcb = NULL;
uint8 i = 0;
struct tcp_pcb *inactive = NULL;
struct tcp_pcb *prev = NULL;
u8_t pcb_remove;
/* Check if the address already is in use (on all lists) */
for (i = 1; i < 4; i++) {
cpcb = *tcp_pcb_lists[i];
while(cpcb != NULL){
pcb_remove = 0;
if (cpcb->local_port == port) {
++pcb_remove;
}
/* If the PCB should be removed, do it. */
if (pcb_remove) {
/* Remove PCB from tcp_pcb_lists list. */
inactive = cpcb;
cpcb = inactive->next;
tcp_pcb_remove(tcp_pcb_lists[i], inactive);
memp_free(MEMP_TCP_PCB, inactive);
} else {
cpcb = cpcb->next;
}
}
}
}
/******************************************************************************
* FunctionName : espconn_find_current_pcb
* Description : find the TCP block which option
* Parameters : pcurrent_msg -- the node in the list which active
* Returns : TCP block point
*******************************************************************************/
struct tcp_pcb *ICACHE_FLASH_ATTR espconn_find_current_pcb(espconn_msg *pcurrent_msg)
{
uint16 local_port = pcurrent_msg->pcommon.local_port;
uint32 local_ip = pcurrent_msg->pcommon.local_ip;
uint16 remote_port = pcurrent_msg->pcommon.remote_port;
uint32 remote_ip = *((uint32*)&pcurrent_msg->pcommon.remote_ip);
struct tcp_pcb *find_pcb = NULL;
if (pcurrent_msg ->preverse == NULL){/*Find the server's TCP block*/
if (local_ip == 0|| local_port == 0) return pcurrent_msg->pcommon.pcb;
for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) &&
(find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip))
return find_pcb;
}
for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) &&
(find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip))
return find_pcb;
}
} else {/*Find the client's TCP block*/
if (remote_ip == 0|| remote_port == 0) return pcurrent_msg->pcommon.pcb;
for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip))
return find_pcb;
}
for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip))
return find_pcb;
}
}
return NULL;
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_tcp_reconnect * FunctionName : espconn_tcp_reconnect
...@@ -51,11 +224,14 @@ espconn_tcp_reconnect(void *arg) ...@@ -51,11 +224,14 @@ espconn_tcp_reconnect(void *arg)
{ {
espconn_msg *precon_cb = arg; espconn_msg *precon_cb = arg;
sint8 re_err = 0; sint8 re_err = 0;
espconn_buf *perr_buf = NULL;
espconn_buf *perr_back = NULL;
espconn_kill_oldest_pcb();
if (precon_cb != NULL) { if (precon_cb != NULL) {
struct espconn *espconn = precon_cb->preverse; struct espconn *espconn = precon_cb->preverse;
re_err = precon_cb->pcommon.err; re_err = precon_cb->pcommon.err;
if (precon_cb->pespconn != NULL){ if (precon_cb->pespconn != NULL){
if (espconn != NULL){ if (espconn != NULL){/*Process the server's message block*/
if (precon_cb->pespconn->proto.tcp != NULL){ if (precon_cb->pespconn->proto.tcp != NULL){
espconn_copy_partial(espconn, precon_cb->pespconn); espconn_copy_partial(espconn, precon_cb->pespconn);
espconn_printf("server: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->remote_ip[0], espconn_printf("server: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->remote_ip[0],
...@@ -66,17 +242,28 @@ espconn_tcp_reconnect(void *arg) ...@@ -66,17 +242,28 @@ espconn_tcp_reconnect(void *arg)
} }
os_free(precon_cb->pespconn); os_free(precon_cb->pespconn);
precon_cb->pespconn = NULL; precon_cb->pespconn = NULL;
} else { } else {/*Process the client's message block*/
espconn = precon_cb->pespconn; espconn = precon_cb->pespconn;
espconn_printf("client: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->local_ip[0], espconn_printf("client: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->local_ip[0],
espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2], espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port); espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
} }
} }
/*to prevent memory leaks, ensure that each allocated is deleted*/
perr_buf = precon_cb->pcommon.pbuf;
while (perr_buf != NULL){
perr_back = perr_buf;
perr_buf = perr_back->pnext;
espconn_pbuf_delete(&precon_cb->pcommon.pbuf,perr_back);
os_free(perr_back);
perr_back = NULL;
}
os_bzero(&pktinfo[1], sizeof(struct espconn_packet));
os_memcpy(&pktinfo[1], (void*)&precon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
os_free(precon_cb); os_free(precon_cb);
precon_cb = NULL; precon_cb = NULL;
if (espconn && espconn->proto.tcp && espconn->proto.tcp->reconnect_callback != NULL) {
if (espconn->proto.tcp->reconnect_callback != NULL) {
espconn->proto.tcp->reconnect_callback(espconn, re_err); espconn->proto.tcp->reconnect_callback(espconn, re_err);
} }
} else { } else {
...@@ -95,14 +282,17 @@ espconn_tcp_disconnect_successful(void *arg) ...@@ -95,14 +282,17 @@ espconn_tcp_disconnect_successful(void *arg)
{ {
espconn_msg *pdiscon_cb = arg; espconn_msg *pdiscon_cb = arg;
sint8 dis_err = 0; sint8 dis_err = 0;
espconn_buf *pdis_buf = NULL;
espconn_buf *pdis_back = NULL;
espconn_kill_oldest_pcb();
if (pdiscon_cb != NULL) { if (pdiscon_cb != NULL) {
struct espconn *espconn = pdiscon_cb->preverse; struct espconn *espconn = pdiscon_cb->preverse;
dis_err = pdiscon_cb->pcommon.err; dis_err = pdiscon_cb->pcommon.err;
if (pdiscon_cb->pespconn != NULL){ if (pdiscon_cb->pespconn != NULL){
struct tcp_pcb *pcb = NULL; struct tcp_pcb *pcb = NULL;
if (espconn != NULL){ if (espconn != NULL){/*Process the server's message block*/
if (pdiscon_cb->pespconn->proto.tcp != NULL){ if (pdiscon_cb->pespconn->proto.tcp != NULL && espconn->proto.tcp){
espconn_copy_partial(espconn, pdiscon_cb->pespconn); espconn_copy_partial(espconn, pdiscon_cb->pespconn);
espconn_printf("server: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->remote_ip[0], espconn_printf("server: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2], espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2],
...@@ -112,27 +302,69 @@ espconn_tcp_disconnect_successful(void *arg) ...@@ -112,27 +302,69 @@ espconn_tcp_disconnect_successful(void *arg)
} }
os_free(pdiscon_cb->pespconn); os_free(pdiscon_cb->pespconn);
pdiscon_cb->pespconn = NULL; pdiscon_cb->pespconn = NULL;
} else { } else {/*Process the client's message block*/
espconn = pdiscon_cb->pespconn; espconn = pdiscon_cb->pespconn;
espconn_printf("client: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->local_ip[0], espconn_printf("client: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->local_ip[0],
espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2], espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port); espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
} }
pcb = pdiscon_cb->pcommon.pcb; /*process the current TCP block*/
tcp_arg(pcb, NULL); pcb = espconn_find_current_pcb(pdiscon_cb);
tcp_err(pcb, NULL); if (pcb != NULL){
/*delete TIME_WAIT State pcb after 2MSL time,for not all data received by application.*/ if (espconn_reuse_disabled(pdiscon_cb)) {
if (pdiscon_cb->pcommon.espconn_opt == ESPCONN_REUSEADDR){ struct tcp_pcb *cpcb = NULL;
if (pcb->state == TIME_WAIT){ struct tcp_pcb *prev = NULL;
tcp_pcb_remove(&tcp_tw_pcbs,pcb); u8_t pcb_remove;
memp_free(MEMP_TCP_PCB,pcb); espconn_printf("espconn_tcp_disconnect_successful %d, %d\n", pcb->state, pcb->local_port);
cpcb = tcp_tw_pcbs;
while (cpcb != NULL) {
pcb_remove = 0;
if (cpcb->local_port == pcb->local_port) {
++pcb_remove;
}
/* If the PCB should be removed, do it. */
if (pcb_remove) {
struct tcp_pcb *backup_pcb = NULL;
tcp_pcb_purge(cpcb);
/* Remove PCB from tcp_tw_pcbs list. */
if (prev != NULL) {
LWIP_ASSERT("espconn_tcp_delete: middle cpcb != tcp_tw_pcbs",cpcb != tcp_tw_pcbs);
prev->next = cpcb->next;
} else {
/* This PCB was the first. */
LWIP_ASSERT("espconn_tcp_delete: first cpcb == tcp_tw_pcbs",tcp_tw_pcbs == cpcb);
tcp_tw_pcbs = cpcb->next;
}
backup_pcb = cpcb;
cpcb = cpcb->next;
memp_free(MEMP_TCP_PCB, backup_pcb);
} else {
prev = cpcb;
cpcb = cpcb->next;
}
}
} else {
tcp_arg(pcb, NULL);
tcp_err(pcb, NULL);
} }
} }
} }
/*to prevent memory leaks, ensure that each allocated is deleted*/
pdis_buf = pdiscon_cb->pcommon.pbuf;
while (pdis_buf != NULL) {
pdis_back = pdis_buf;
pdis_buf = pdis_back->pnext;
espconn_pbuf_delete(&pdiscon_cb->pcommon.pbuf, pdis_back);
os_free(pdis_back);
pdis_back = NULL;
}
os_bzero(&pktinfo[0], sizeof(struct espconn_packet));
os_memcpy(&pktinfo[0], (void*)&pdiscon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
os_free(pdiscon_cb); os_free(pdiscon_cb);
pdiscon_cb = NULL; pdiscon_cb = NULL;
if (espconn->proto.tcp && espconn->proto.tcp->disconnect_callback != NULL) {
if (espconn->proto.tcp->disconnect_callback != NULL) {
espconn->proto.tcp->disconnect_callback(espconn); espconn->proto.tcp->disconnect_callback(espconn);
} }
} else { } else {
...@@ -140,15 +372,59 @@ espconn_tcp_disconnect_successful(void *arg) ...@@ -140,15 +372,59 @@ espconn_tcp_disconnect_successful(void *arg)
} }
} }
/******************************************************************************
* FunctionName : espconn_Task
* Description : espconn processing task
* Parameters : events -- contain the espconn processing data
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_Task(os_event_t *events)
{
espconn_msg *task_msg = NULL;
struct espconn *pespconn = NULL;
task_msg = (espconn_msg *) events->par;
switch (events->sig) {
case SIG_ESPCONN_WRITE: {
pespconn = task_msg->pespconn;
if (pespconn == NULL) {
return;
}
if (pespconn->proto.tcp->write_finish_fn != NULL) {
pespconn->proto.tcp->write_finish_fn(pespconn);
}
}
break;
case SIG_ESPCONN_ERRER:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_reconnect(task_msg);
break;
case SIG_ESPCONN_CLOSE:
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, task_msg);
espconn_tcp_disconnect_successful(task_msg);
break;
default:
break;
}
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_tcp_sent * FunctionName : espconn_tcp_sent
* Description : sent data for client or server * Description : sent data for client or server
* Parameters : void *arg -- client or server to send * Parameters : void *arg -- client or server to send
* uint8* psent -- Data to send * uint8* psent -- Data to send
* uint16 length -- Length of data to send * uint16 length -- Length of data to send
* Returns : none * Returns : return espconn error code.
* - ESPCONN_OK. Successful. No error occured.
* - ESPCONN_MEM. Out of memory.
* - ESPCONN_RTE. Could not find route to destination address.
* - More errors could be returned by lower protocol layers.
*******************************************************************************/ *******************************************************************************/
void ICACHE_FLASH_ATTR err_t ICACHE_FLASH_ATTR
espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
{ {
espconn_msg *ptcp_sent = arg; espconn_msg *ptcp_sent = arg;
...@@ -159,10 +435,12 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) ...@@ -159,10 +435,12 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
espconn_printf("espconn_tcp_sent ptcp_sent %p psent %p length %d\n", ptcp_sent, psent, length); espconn_printf("espconn_tcp_sent ptcp_sent %p psent %p length %d\n", ptcp_sent, psent, length);
/*Check the parameters*/
if (ptcp_sent == NULL || psent == NULL || length == 0) { if (ptcp_sent == NULL || psent == NULL || length == 0) {
return; return ESPCONN_ARG;
} }
/*Set the packet length depend on the sender buffer space*/
pcb = ptcp_sent->pcommon.pcb; pcb = ptcp_sent->pcommon.pcb;
if (tcp_sndbuf(pcb) < length) { if (tcp_sndbuf(pcb) < length) {
len = tcp_sndbuf(pcb); len = tcp_sndbuf(pcb);
...@@ -175,28 +453,34 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) ...@@ -175,28 +453,34 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
len = 2*pcb->mss; len = 2*pcb->mss;
} }
do { /*Write data for sending, but does not send it immediately*/
espconn_printf("espconn_tcp_sent writing %d bytes %p\n", len, pcb); do {
err = tcp_write(pcb, psent, len, 0); espconn_printf("espconn_tcp_sent writing %d bytes %p\n", len, pcb);
if (espconn_copy_disabled(ptcp_sent))
err = tcp_write(pcb, psent, len, 1);
else
err = tcp_write(pcb, psent, len, 0);
if (err == ERR_MEM) { if (err == ERR_MEM) {
len /= 2; len /= 2;
} }
} while (err == ERR_MEM && len > 1); } while (err == ERR_MEM && len > 1);
/*Find out what we can send and send it, offset the buffer point for next send*/
if (err == ERR_OK) { if (err == ERR_OK) {
data_to_send = true; ptcp_sent->pcommon.ptail->punsent = psent + len;
ptcp_sent->pcommon.ptrbuf = psent + len; ptcp_sent->pcommon.ptail->unsent = length - len;
ptcp_sent->pcommon.cntr = length - len; err = tcp_output(pcb);
ptcp_sent->pcommon.write_len += len; /*If enable the copy option, change the flag for next write*/
espconn_printf("espconn_tcp_sent sending %d bytes, remain %d\n", len, ptcp_sent->pcommon.cntr); if (espconn_copy_disabled(ptcp_sent)){
} if (ptcp_sent->pcommon.ptail->unsent == 0) {
ptcp_sent->pcommon.write_flag = true;
if (data_to_send == true) { ets_post(espconn_TaskPrio, SIG_ESPCONN_WRITE, (uint32_t)ptcp_sent);
err = tcp_output(pcb); }
} else { }
ptcp_sent->pespconn ->state = ESPCONN_CLOSE; espconn_printf("espconn_tcp_sent %d\n", err);
} }
return err;
} }
/****************************************************************************** /******************************************************************************
...@@ -208,45 +492,17 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length) ...@@ -208,45 +492,17 @@ espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
void ICACHE_FLASH_ATTR espconn_tcp_disconnect(espconn_msg *pdiscon) void ICACHE_FLASH_ATTR espconn_tcp_disconnect(espconn_msg *pdiscon)
{ {
if (pdiscon != NULL){ if (pdiscon != NULL){
/*disconnect with the host by send the FIN frame*/
if (pdiscon->preverse != NULL) if (pdiscon->preverse != NULL)
espconn_server_close(pdiscon, pdiscon->pcommon.pcb); espconn_server_close(pdiscon, pdiscon->pcommon.pcb);
else else
espconn_client_close(pdiscon, pdiscon->pcommon.pcb); espconn_client_close(pdiscon, pdiscon->pcommon.pcb);
} else{ } else{
espconn_printf("espconn_server_disconnect err.\n"); espconn_printf("espconn_tcp_disconnect err.\n");
} }
} }
///////////////////////////////client function///////////////////////////////// ///////////////////////////////client function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_close
* Description : The connection has been successfully closed.
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_cclose_cb(void *arg)
{
espconn_msg *pclose_cb = arg;
if (pclose_cb == NULL) {
return;
}
struct tcp_pcb *pcb = pclose_cb->pcommon.pcb;
espconn_printf("espconn_close %d %d\n", pcb->state, pcb->nrtx);
if (pcb->state == TIME_WAIT || pcb->state == CLOSED) {
pclose_cb ->pespconn ->state = ESPCONN_CLOSE;
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, pclose_cb);
espconn_tcp_disconnect_successful((void*)pclose_cb);
} else {
os_timer_arm(&pclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
}
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_client_close * FunctionName : espconn_client_close
* Description : The connection shall be actively closed. * Description : The connection shall be actively closed.
...@@ -260,22 +516,80 @@ espconn_client_close(void *arg, struct tcp_pcb *pcb) ...@@ -260,22 +516,80 @@ espconn_client_close(void *arg, struct tcp_pcb *pcb)
err_t err; err_t err;
espconn_msg *pclose = arg; espconn_msg *pclose = arg;
os_timer_disarm(&pclose->pcommon.ptimer); pclose->pcommon.pcb = pcb;
/*avoid recalling the disconnect function*/
tcp_recv(pcb, NULL); tcp_recv(pcb, NULL);
err = tcp_close(pcb); err = tcp_close(pcb);
os_timer_setfn(&pclose->pcommon.ptimer, espconn_cclose_cb, pclose);
os_timer_arm(&pclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
if (err != ERR_OK) { if (err != ERR_OK) {
/* closing failed, try again later */ /* closing failed, try again later */
tcp_recv(pcb, espconn_client_recv); tcp_recv(pcb, espconn_client_recv);
} else { } else {
/* closing succeeded */ /* closing succeeded */
tcp_sent(pcb, NULL); tcp_sent(pcb, NULL);
tcp_err(pcb, NULL);
/*switch the state of espconn for application process*/
pclose->pespconn->state = ESPCONN_CLOSE;
ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)pclose);
}
}
//***********Code for WIFI_BLOCK from upper**************
sint8 ICACHE_FLASH_ATTR
espconn_recv_hold(struct espconn *pespconn)
{
//1st, according to espconn code, have to find out the escpconn_msg by pespconn;
espconn_msg *pnode = NULL;
bool value = false;
if (pespconn == NULL) {
return ESPCONN_ARG;
} }
value = espconn_find_connection(pespconn, &pnode);
if(value != true)
{
os_printf("RecvHold, By pespconn,find conn_msg fail\n");
return ESPCONN_ARG;
}
//2nd, the actual operation
if(pnode->recv_hold_flag == 0)
{
pnode->recv_hold_flag = 1;
pnode->recv_holded_buf_Len = 0;
}
return ESPCONN_OK;
}
sint8 ICACHE_FLASH_ATTR
espconn_recv_unhold(struct espconn *pespconn)
{
//1st, according to espconn code, have to find out the escpconn_msg by pespconn;
espconn_msg *pnode = NULL;
bool value = false;
if (pespconn == NULL) {
return ESPCONN_ARG;
}
value = espconn_find_connection(pespconn, &pnode);
if(value != true)
{
os_printf("RecvHold, By pespconn,find conn_msg fail\n");
return ESPCONN_ARG;
}
//2nd, the actual operation
if(pnode->recv_hold_flag == 1)
{
if(pespconn->type == ESPCONN_TCP) {
tcp_recved(pnode->pcommon.pcb, pnode->recv_holded_buf_Len);
}
pnode->recv_holded_buf_Len = 0;
pnode->recv_hold_flag = 0;
}
return ESPCONN_OK;
} }
//***********Code for WIFI_BLOCK from upper**************
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_client_recv * FunctionName : espconn_client_recv
* Description : Data has been received on this pcb. * Description : Data has been received on this pcb.
...@@ -293,25 +607,35 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) ...@@ -293,25 +607,35 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
tcp_arg(pcb, arg); tcp_arg(pcb, arg);
if (p != NULL) { if (p != NULL) {
tcp_recved(pcb, p ->tot_len); /*To update and advertise a larger window*/
if(precv_cb->recv_hold_flag == 0)
tcp_recved(pcb, p->tot_len);
else
precv_cb->recv_holded_buf_Len += p->tot_len;
} }
if (err == ERR_OK && p != NULL) { if (err == ERR_OK && p != NULL) {
char *pdata = NULL; char *pdata = NULL;
u16_t length = 0; u16_t length = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
pdata = (char *)os_zalloc(p ->tot_len + 1); pdata = (char *)os_zalloc(p ->tot_len + 1);
length = pbuf_copy_partial(p, pdata, p ->tot_len, 0); length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
pbuf_free(p); pbuf_free(p);
if (length != 0) { if (length != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn ->state = ESPCONN_READ; precv_cb->pespconn ->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb; precv_cb->pcommon.pcb = pcb;
if (precv_cb->pespconn->recv_callback != NULL) { if (precv_cb->pespconn->recv_callback != NULL) {
precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length); precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length);
} }
precv_cb->pespconn ->state = ESPCONN_CONNECT; /*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn ->state = ESPCONN_CONNECT;
} }
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pdata); os_free(pdata);
pdata = NULL; pdata = NULL;
} }
...@@ -324,68 +648,93 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) ...@@ -324,68 +648,93 @@ espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
} }
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_client_sent * FunctionName : espconn_tcp_write
* Description : Data has been sent and acknowledged by the remote host. * Description : write the packet which in the active connection's list.
* This means that more data can be sent. * Parameters : arg -- the node pointer which reverse the packet
* Parameters : arg -- Additional argument to pass to the callback function * Returns : ESPCONN_MEM: memory error
* pcb -- The connection pcb for which data has been acknowledged * ESPCONN_OK:have enough space for write packet
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/ *******************************************************************************/
static err_t ICACHE_FLASH_ATTR err_t ICACHE_FLASH_ATTR espconn_tcp_write(void *arg)
espconn_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{ {
espconn_msg *psent_cb = arg; espconn_msg *pwrite = arg;
err_t err = ERR_OK;
struct tcp_pcb *pcb = pwrite->pcommon.pcb;
/*for one active connection,limit the sender buffer space*/
if (tcp_nagle_disabled(pcb) && (pcb->snd_queuelen >= TCP_SND_QUEUELEN))
return ESPCONN_MEM;
psent_cb->pcommon.pcb = pcb; while (tcp_sndbuf(pcb) != 0){
psent_cb->pcommon.write_total += len; if (pwrite->pcommon.ptail != NULL) {
espconn_printf("espconn_client_sent sent %d %d\n", len, psent_cb->pcommon.write_total); /*Find the node whether in the list's tail or not*/
if (psent_cb->pcommon.write_total == psent_cb->pcommon.write_len){ if (pwrite->pcommon.ptail->unsent == 0) {
psent_cb->pcommon.write_total = 0; pwrite->pcommon.ptail = pwrite->pcommon.ptail->pnext;
psent_cb->pcommon.write_len = 0; continue;
if (psent_cb->pcommon.cntr == 0) {
psent_cb->pespconn->state = ESPCONN_CONNECT;
if (psent_cb->pespconn->sent_callback != NULL) {
psent_cb->pespconn->sent_callback(psent_cb->pespconn);
} }
/*Send the packet for the active connection*/
err = espconn_tcp_sent(pwrite, pwrite->pcommon.ptail->punsent,pwrite->pcommon.ptail->unsent);
if (err != ERR_OK)
break;
} else } else
espconn_tcp_sent(psent_cb, psent_cb->pcommon.ptrbuf, psent_cb->pcommon.cntr); break;
} else { }
return err;
}
/******************************************************************************
* FunctionName : espconn_tcp_reconnect
* Description : reconnect with host
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR espconn_tcp_finish(void *arg)
{
espconn_msg *pfinish = arg;
espconn_buf *premove = NULL;
uint16 len = 0;
espconn_tcp_write(pfinish);
while (pfinish->pcommon.pbuf != NULL){
premove = pfinish->pcommon.pbuf;
pfinish->pcommon.pbuf->tot_len += len;
/*application packet has been sent and acknowledged by the remote host,
* to prevent memory leaks, ensure that each allocated is deleted*/
if (premove->tot_len >= premove->len){
espconn_pbuf_delete(&pfinish->pcommon.pbuf,premove);
len = premove->tot_len - premove->len;
pfinish->pcommon.packet_info.sent_length = premove->len;
os_free(premove);
premove = NULL;
pfinish->pespconn->state = ESPCONN_CONNECT;
if (pfinish->pespconn->sent_callback != NULL) {
pfinish->pespconn->sent_callback(pfinish->pespconn);
}
pfinish->pcommon.packet_info.sent_length = len;
} else
break;
} }
return ERR_OK;
} }
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_client_poll * FunctionName : espconn_client_sent
* Description : The poll function is called every 2nd second. * Description : Data has been sent and acknowledged by the remote host.
* If there has been no data sent (which resets the retries) in 8 seconds, close. * This means that more data can be sent.
* If the last portion of a file has not been sent in 2 seconds, close.
*
* This could be increased, but we don't want to waste resources for bad connections.
* Parameters : arg -- Additional argument to pass to the callback function * Parameters : arg -- Additional argument to pass to the callback function
* pcb -- The connection pcb for which data has been acknowledged * pcb -- The connection pcb for which data has been acknowledged
* len -- The amount of bytes acknowledged
* Returns : ERR_OK: try to send some data by calling tcp_output * Returns : ERR_OK: try to send some data by calling tcp_output
* ERR_ABRT: if you have called tcp_abort from within the function! * ERR_ABRT: if you have called tcp_abort from within the function!
*******************************************************************************/ *******************************************************************************/
static err_t ICACHE_FLASH_ATTR static err_t ICACHE_FLASH_ATTR
espconn_client_poll(void *arg, struct tcp_pcb *pcb) espconn_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{ {
espconn_msg *ppoll_cb = arg; espconn_msg *psent_cb = arg;
espconn_printf("espconn_client_poll pcb %p %p %d\n", pcb, arg, pcb->state);
if (arg == NULL) { psent_cb->pcommon.pcb = pcb;
tcp_abandon(pcb, 0); psent_cb->pcommon.pbuf->tot_len += len;
tcp_poll(pcb, NULL, 0); psent_cb->pcommon.packet_info.sent_length = len;
return ERR_ABRT;
} /*Send more data for one active connection*/
ppoll_cb->pcommon.pcb = pcb; espconn_tcp_finish(psent_cb);
if (pcb->state == ESTABLISHED) {
} else {
tcp_poll(pcb, espconn_client_poll, 0);
espconn_client_close(ppoll_cb->pespconn, pcb);
}
return ERR_OK; return ERR_OK;
} }
...@@ -406,14 +755,14 @@ espconn_client_err(void *arg, err_t err) ...@@ -406,14 +755,14 @@ espconn_client_err(void *arg, err_t err)
LWIP_UNUSED_ARG(err); LWIP_UNUSED_ARG(err);
if (perr_cb != NULL) { if (perr_cb != NULL) {
os_timer_disarm(&perr_cb->pcommon.ptimer);
pcb = perr_cb->pcommon.pcb; pcb = perr_cb->pcommon.pcb;
perr_cb->pespconn->state = ESPCONN_CLOSE; perr_cb->pespconn->state = ESPCONN_CLOSE;
espconn_printf("espconn_client_err %d %d %d\n", pcb->state, pcb->nrtx, err); espconn_printf("espconn_client_err %d %d %d\n", pcb->state, pcb->nrtx, err);
/*remove the node from the client's active connection list*/ // /*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, perr_cb); // espconn_list_delete(&plink_active, perr_cb);
/*Set the error code depend on the error type and control block state*/
if (err == ERR_ABRT) { if (err == ERR_ABRT) {
switch (pcb->state) { switch (pcb->state) {
case SYN_SENT: case SYN_SENT:
...@@ -450,9 +799,8 @@ espconn_client_err(void *arg, err_t err) ...@@ -450,9 +799,8 @@ espconn_client_err(void *arg, err_t err)
} else { } else {
perr_cb->pcommon.err = err; perr_cb->pcommon.err = err;
} }
os_timer_setfn(&perr_cb->pcommon.ptimer, /*post the singer to the task for processing the connection*/
(os_timer_func_t *) espconn_tcp_reconnect, perr_cb); ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)perr_cb);
os_timer_arm(&perr_cb->pcommon.ptimer, 10, 0);
} }
} }
...@@ -468,19 +816,41 @@ static err_t ICACHE_FLASH_ATTR ...@@ -468,19 +816,41 @@ static err_t ICACHE_FLASH_ATTR
espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err) espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err)
{ {
espconn_msg *pcon = arg; espconn_msg *pcon = arg;
espconn_printf("espconn_client_connect pcon %p tpcb %p\n", pcon, tpcb); espconn_printf("espconn_client_connect pcon %p tpcb %p\n", pcon, tpcb);
if (err == ERR_OK){ if (err == ERR_OK){
/*Reserve the remote information for current active connection*/
pcon->pespconn->state = ESPCONN_CONNECT; pcon->pespconn->state = ESPCONN_CONNECT;
pcon->pcommon.err = err; pcon->pcommon.err = err;
pcon->pcommon.pcb = tpcb; pcon->pcommon.pcb = tpcb;
tcp_arg(tpcb, (void *)pcon); pcon->pcommon.local_port = tpcb->local_port;
pcon->pcommon.local_ip = tpcb->local_ip.addr;
pcon->pcommon.remote_port = tpcb->remote_port;
pcon->pcommon.remote_ip[0] = ip4_addr1_16(&tpcb->remote_ip);
pcon->pcommon.remote_ip[1] = ip4_addr2_16(&tpcb->remote_ip);
pcon->pcommon.remote_ip[2] = ip4_addr3_16(&tpcb->remote_ip);
pcon->pcommon.remote_ip[3] = ip4_addr4_16(&tpcb->remote_ip);
pcon->pcommon.write_flag = true;
tcp_arg(tpcb, (void *) pcon);
/*Set the specify function that should be called
* when TCP data has been successfully delivered,
* when active connection receives data*/
tcp_sent(tpcb, espconn_client_sent); tcp_sent(tpcb, espconn_client_sent);
tcp_recv(tpcb, espconn_client_recv); tcp_recv(tpcb, espconn_client_recv);
/*Disable Nagle algorithm default*/
tcp_nagle_disable(tpcb);
/*Default set the total number of espconn_buf on the unsent lists for one*/
espconn_tcp_set_buf_count(pcon->pespconn, 1);
//tcp_poll(tpcb, espconn_client_poll, 1);
if (pcon->pespconn->proto.tcp->connect_callback != NULL) { if (pcon->pespconn->proto.tcp->connect_callback != NULL) {
pcon->pespconn->proto.tcp->connect_callback(pcon->pespconn); pcon->pespconn->proto.tcp->connect_callback(pcon->pespconn);
} }
/*Enable keep alive option*/
if (espconn_keepalive_disabled(pcon))
espconn_keepalive_enable(tpcb);
} else{ } else{
os_printf("err in host connected (%s)\n",lwip_strerr(err)); os_printf("err in host connected (%s)\n",lwip_strerr(err));
} }
...@@ -501,24 +871,28 @@ espconn_tcp_client(struct espconn *espconn) ...@@ -501,24 +871,28 @@ espconn_tcp_client(struct espconn *espconn)
struct ip_addr ipaddr; struct ip_addr ipaddr;
espconn_msg *pclient = NULL; espconn_msg *pclient = NULL;
/*Creates a new client control message*/
pclient = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); pclient = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
if (pclient == NULL){ if (pclient == NULL){
return ESPCONN_MEM; return ESPCONN_MEM;
} }
/*Set an IP address given for Little-endian.*/
IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0], IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0],
espconn->proto.tcp->remote_ip[1], espconn->proto.tcp->remote_ip[1],
espconn->proto.tcp->remote_ip[2], espconn->proto.tcp->remote_ip[2],
espconn->proto.tcp->remote_ip[3]); espconn->proto.tcp->remote_ip[3]);
/*Creates a new TCP protocol control block*/
pcb = tcp_new(); pcb = tcp_new();
if (pcb == NULL) { if (pcb == NULL) {
// pclient ->pespconn ->state = ESPCONN_NONE; /*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pclient); os_free(pclient);
pclient = NULL; pclient = NULL;
return ESPCONN_MEM; return ESPCONN_MEM;
} else { } else {
/*insert the node to the active connection list*/ /*insert the node to the active connection list*/
espconn_list_creat(&plink_active, pclient); espconn_list_creat(&plink_active, pclient);
tcp_arg(pcb, (void *)pclient); tcp_arg(pcb, (void *)pclient);
...@@ -528,39 +902,22 @@ espconn_tcp_client(struct espconn *espconn) ...@@ -528,39 +902,22 @@ espconn_tcp_client(struct espconn *espconn)
pclient->pespconn->state = ESPCONN_WAIT; pclient->pespconn->state = ESPCONN_WAIT;
pclient->pcommon.pcb = pcb; pclient->pcommon.pcb = pcb;
tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port); tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
/*Establish the connection*/
pclient->pcommon.err = tcp_connect(pcb, &ipaddr, pclient->pcommon.err = tcp_connect(pcb, &ipaddr,
pclient->pespconn->proto.tcp->remote_port, espconn_client_connect); pclient->pespconn->proto.tcp->remote_port, espconn_client_connect);
if (pclient->pcommon.err == ERR_RTE){
/*remove the node from the client's active connection list*/
espconn_list_delete(&plink_active, pclient);
espconn_kill_pcb(pcb->local_port);
os_free(pclient);
pclient = NULL;
return ESPCONN_RTE;
}
return pclient->pcommon.err; return pclient->pcommon.err;
} }
} }
///////////////////////////////server function///////////////////////////////// ///////////////////////////////server function/////////////////////////////////
/******************************************************************************
* FunctionName : espconn_closed
* Description : The connection has been successfully closed.
* Parameters : arg -- Additional argument to pass to the callback function
* Returns : none
*******************************************************************************/
static void ICACHE_FLASH_ATTR
espconn_sclose_cb(void *arg)
{
espconn_msg *psclose_cb = arg;
if (psclose_cb == NULL) {
return;
}
struct tcp_pcb *pcb = psclose_cb ->pcommon.pcb;
espconn_printf("espconn_sclose_cb %d %d\n", pcb->state, pcb->nrtx);
if (pcb->state == CLOSED || pcb->state == TIME_WAIT) {
psclose_cb ->pespconn ->state = ESPCONN_CLOSE;
/*remove the node from the server's active connection list*/
espconn_list_delete(&plink_active, psclose_cb);
espconn_tcp_disconnect_successful(psclose_cb);
} else {
os_timer_arm(&psclose_cb->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
}
}
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_server_close * FunctionName : espconn_server_close
* Description : The connection shall be actively closed. * Description : The connection shall be actively closed.
...@@ -574,12 +931,10 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb) ...@@ -574,12 +931,10 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb)
err_t err; err_t err;
espconn_msg *psclose = arg; espconn_msg *psclose = arg;
os_timer_disarm(&psclose->pcommon.ptimer); psclose->pcommon.pcb = pcb;
/*avoid recalling the disconnect function*/
tcp_recv(pcb, NULL); tcp_recv(pcb, NULL);
err = tcp_close(pcb); err = tcp_close(pcb);
os_timer_setfn(&psclose->pcommon.ptimer, espconn_sclose_cb, psclose);
os_timer_arm(&psclose->pcommon.ptimer, TCP_FAST_INTERVAL, 0);
if (err != ERR_OK) { if (err != ERR_OK) {
/* closing failed, try again later */ /* closing failed, try again later */
...@@ -588,7 +943,11 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb) ...@@ -588,7 +943,11 @@ espconn_server_close(void *arg, struct tcp_pcb *pcb)
/* closing succeeded */ /* closing succeeded */
tcp_poll(pcb, NULL, 0); tcp_poll(pcb, NULL, 0);
tcp_sent(pcb, NULL); tcp_sent(pcb, NULL);
} tcp_err(pcb, NULL);
/*switch the state of espconn for application process*/
psclose->pespconn->state = ESPCONN_CLOSE;
ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)psclose);
}
} }
/****************************************************************************** /******************************************************************************
...@@ -608,26 +967,38 @@ espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) ...@@ -608,26 +967,38 @@ espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
tcp_arg(pcb, arg); tcp_arg(pcb, arg);
espconn_printf("server has application data received: %d\n", system_get_free_heap_size()); espconn_printf("server has application data received: %d\n", system_get_free_heap_size());
if (p != NULL) { if (p != NULL) {
tcp_recved(pcb, p->tot_len); /*To update and advertise a larger window*/
if(precv_cb->recv_hold_flag == 0)
tcp_recved(pcb, p->tot_len);
else
precv_cb->recv_holded_buf_Len += p->tot_len;
} }
if (err == ERR_OK && p != NULL) { if (err == ERR_OK && p != NULL) {
u8_t *data_ptr = NULL; u8_t *data_ptr = NULL;
u32_t data_cntr = 0; u32_t data_cntr = 0;
/*clear the count for connection timeout*/
precv_cb->pcommon.recv_check = 0; precv_cb->pcommon.recv_check = 0;
/*Copy the contents of a packet buffer to an application buffer.
*to prevent memory leaks, ensure that each allocated is deleted*/
data_ptr = (u8_t *)os_zalloc(p ->tot_len + 1); data_ptr = (u8_t *)os_zalloc(p ->tot_len + 1);
data_cntr = pbuf_copy_partial(p, data_ptr, p ->tot_len, 0); data_cntr = pbuf_copy_partial(p, data_ptr, p ->tot_len, 0);
pbuf_free(p); pbuf_free(p);
if (data_cntr != 0) { if (data_cntr != 0) {
/*switch the state of espconn for application process*/
precv_cb->pespconn ->state = ESPCONN_READ; precv_cb->pespconn ->state = ESPCONN_READ;
precv_cb->pcommon.pcb = pcb; precv_cb->pcommon.pcb = pcb;
if (precv_cb->pespconn->recv_callback != NULL) { if (precv_cb->pespconn->recv_callback != NULL) {
precv_cb->pespconn->recv_callback(precv_cb->pespconn, data_ptr, data_cntr); precv_cb->pespconn->recv_callback(precv_cb->pespconn, data_ptr, data_cntr);
} }
precv_cb->pespconn ->state = ESPCONN_CONNECT;
/*switch the state of espconn for next packet copy*/
if (pcb->state == ESTABLISHED)
precv_cb->pespconn ->state = ESPCONN_CONNECT;
} }
/*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(data_ptr); os_free(data_ptr);
data_ptr = NULL; data_ptr = NULL;
espconn_printf("server's application data has been processed: %d\n", system_get_free_heap_size()); espconn_printf("server's application data has been processed: %d\n", system_get_free_heap_size());
...@@ -659,22 +1030,11 @@ espconn_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len) ...@@ -659,22 +1030,11 @@ espconn_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
psent_cb->pcommon.pcb = pcb; psent_cb->pcommon.pcb = pcb;
psent_cb->pcommon.recv_check = 0; psent_cb->pcommon.recv_check = 0;
psent_cb->pcommon.write_total += len; psent_cb->pcommon.pbuf->tot_len += len;
espconn_printf("espconn_server_sent sent %d %d\n", len, psent_cb->pcommon.write_total); psent_cb->pcommon.packet_info.sent_length = len;
if (psent_cb->pcommon.write_total == psent_cb->pcommon.write_len){
psent_cb->pcommon.write_total = 0;
psent_cb->pcommon.write_len = 0;
if (psent_cb ->pcommon.cntr == 0) {
psent_cb ->pespconn ->state = ESPCONN_CONNECT;
if (psent_cb ->pespconn ->sent_callback != NULL) {
psent_cb ->pespconn ->sent_callback(psent_cb ->pespconn);
}
} else
espconn_tcp_sent(psent_cb, psent_cb ->pcommon.ptrbuf, psent_cb ->pcommon.cntr);
} else {
} /*Send more data for one active connection*/
espconn_tcp_finish(psent_cb);
return ERR_OK; return ERR_OK;
} }
...@@ -695,30 +1055,37 @@ espconn_server_poll(void *arg, struct tcp_pcb *pcb) ...@@ -695,30 +1055,37 @@ espconn_server_poll(void *arg, struct tcp_pcb *pcb)
{ {
espconn_msg *pspoll_cb = arg; espconn_msg *pspoll_cb = arg;
/*exception calling abandon the connection for send a RST frame*/
if (arg == NULL) { if (arg == NULL) {
tcp_abandon(pcb, 0); tcp_abandon(pcb, 0);
tcp_poll(pcb, NULL, 0); tcp_poll(pcb, NULL, 0);
return ERR_ABRT; return ERR_OK;
} }
espconn_printf("espconn_server_poll %d %d\n", pspoll_cb->pcommon.recv_check, pcb->state); espconn_printf("espconn_server_poll %d %d\n", pspoll_cb->pcommon.recv_check, pcb->state);
pspoll_cb->pcommon.pcb = pcb; pspoll_cb->pcommon.pcb = pcb;
if (pcb->state == ESTABLISHED) { if (pcb->state == ESTABLISHED) {
pspoll_cb->pcommon.recv_check++; pspoll_cb->pcommon.recv_check++;
if (pspoll_cb->pcommon.timeout != 0){ if (pspoll_cb->pcommon.timeout != 0){/*no data sent in one active connection's set timeout, close.*/
if (pspoll_cb->pcommon.recv_check == pspoll_cb->pcommon.timeout) { if (pspoll_cb->pcommon.recv_check >= pspoll_cb->pcommon.timeout) {
pspoll_cb->pcommon.recv_check = 0;
espconn_server_close(pspoll_cb, pcb);
}
} else if (link_timer != 0){
if (pspoll_cb->pcommon.recv_check == link_timer) {
pspoll_cb->pcommon.recv_check = 0; pspoll_cb->pcommon.recv_check = 0;
espconn_server_close(pspoll_cb, pcb); espconn_server_close(pspoll_cb, pcb);
} }
} else { } else {
if (pspoll_cb->pcommon.recv_check == 0x0a) { espconn_msg *ptime_msg = pserver_list;
pspoll_cb->pcommon.recv_check = 0; while (ptime_msg != NULL) {
espconn_server_close(pspoll_cb, pcb); if (ptime_msg->pespconn == pspoll_cb->preverse){
if (ptime_msg->pcommon.timeout != 0){/*no data sent in server's set timeout, close.*/
if (pspoll_cb->pcommon.recv_check >= ptime_msg->pcommon.timeout){
pspoll_cb->pcommon.recv_check = 0;
espconn_server_close(pspoll_cb, pcb);
}
} else {/*don't close for ever*/
pspoll_cb->pcommon.recv_check = 0;
}
break;
}
ptime_msg = ptime_msg->pnext;
} }
} }
} else { } else {
...@@ -742,13 +1109,14 @@ esponn_server_err(void *arg, err_t err) ...@@ -742,13 +1109,14 @@ esponn_server_err(void *arg, err_t err)
espconn_msg *pserr_cb = arg; espconn_msg *pserr_cb = arg;
struct tcp_pcb *pcb = NULL; struct tcp_pcb *pcb = NULL;
if (pserr_cb != NULL) { if (pserr_cb != NULL) {
os_timer_disarm(&pserr_cb->pcommon.ptimer);
pcb = pserr_cb->pcommon.pcb; pcb = pserr_cb->pcommon.pcb;
pserr_cb->pespconn->state = ESPCONN_CLOSE; pserr_cb->pespconn->state = ESPCONN_CLOSE;
/*remove the node from the server's active connection list*/ // /*remove the node from the server's active connection list*/
espconn_list_delete(&plink_active, pserr_cb); // espconn_list_delete(&plink_active, pserr_cb);
/*Set the error code depend on the error type and control block state*/
if (err == ERR_ABRT) { if (err == ERR_ABRT) {
switch (pcb->state) { switch (pcb->state) {
case SYN_RCVD: case SYN_RCVD:
...@@ -789,10 +1157,8 @@ esponn_server_err(void *arg, err_t err) ...@@ -789,10 +1157,8 @@ esponn_server_err(void *arg, err_t err)
} else { } else {
pserr_cb->pcommon.err = err; pserr_cb->pcommon.err = err;
} }
/*post the singer to the task for processing the connection*/
os_timer_setfn(&pserr_cb->pcommon.ptimer, ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)pserr_cb);
(os_timer_func_t *) espconn_tcp_reconnect, pserr_cb);
os_timer_arm(&pserr_cb->pcommon.ptimer, 10, 0);
} }
} }
...@@ -812,12 +1178,25 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) ...@@ -812,12 +1178,25 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
remot_info *pinfo = NULL; remot_info *pinfo = NULL;
LWIP_UNUSED_ARG(err); LWIP_UNUSED_ARG(err);
if (!espconn || !espconn->proto.tcp) {
return ERR_ARG;
}
tcp_arg(pcb, paccept);
tcp_err(pcb, esponn_server_err);
/*Ensure the active connection is less than the count of active connections on the server*/
espconn_get_connection_info(espconn, &pinfo , 0);
espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt);
if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn))
return ERR_ISCONN;
/*Creates a new active connect control message*/
paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
tcp_arg(pcb, paccept); tcp_arg(pcb, paccept);
tcp_err(pcb, esponn_server_err);
if (paccept == NULL) if (paccept == NULL)
return ERR_MEM; return ERR_MEM;
/*insert the node to the active connection list*/ /*Insert the node to the active connection list*/
espconn_list_creat(&plink_active, paccept); espconn_list_creat(&plink_active, paccept);
paccept->preverse = espconn; paccept->preverse = espconn;
...@@ -828,9 +1207,7 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) ...@@ -828,9 +1207,7 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
if (paccept->pespconn->proto.tcp == NULL) if (paccept->pespconn->proto.tcp == NULL)
return ERR_MEM; return ERR_MEM;
//paccept->pcommon.timeout = 0x0a; /*Reserve the remote information for current active connection*/
//link_timer = 0x0a;
paccept->pcommon.pcb = pcb; paccept->pcommon.pcb = pcb;
paccept->pcommon.remote_port = pcb->remote_port; paccept->pcommon.remote_port = pcb->remote_port;
...@@ -838,24 +1215,33 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err) ...@@ -838,24 +1215,33 @@ espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip); paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip);
paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip); paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip);
paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip); paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip);
paccept->pcommon.write_flag = true;
os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4); os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4);
espconn->proto.tcp->remote_port = pcb->remote_port; espconn->proto.tcp->remote_port = pcb->remote_port;
espconn->state = ESPCONN_CONNECT; espconn->state = ESPCONN_CONNECT;
espconn_copy_partial(paccept->pespconn, espconn); espconn_copy_partial(paccept->pespconn, espconn);
espconn_get_connection_info(espconn, &pinfo , 0);
espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt);
if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn) + 1)
return ERR_ISCONN;
/*Set the specify function that should be called
* when TCP data has been successfully delivered,
* when active connection receives data,
* or periodically from active connection*/
tcp_sent(pcb, espconn_server_sent); tcp_sent(pcb, espconn_server_sent);
tcp_recv(pcb, espconn_server_recv); tcp_recv(pcb, espconn_server_recv);
tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */ tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */
/*Disable Nagle algorithm default*/
tcp_nagle_disable(pcb);
/*Default set the total number of espconn_buf on the unsent lists for one*/
espconn_tcp_set_buf_count(paccept->pespconn, 1);
if (paccept->pespconn->proto.tcp->connect_callback != NULL) { if (paccept->pespconn->proto.tcp->connect_callback != NULL) {
paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn); paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn);
} }
/*Enable keep alive option*/
if (espconn_keepalive_disabled(paccept))
espconn_keepalive_enable(pcb);
return ERR_OK; return ERR_OK;
} }
...@@ -872,19 +1258,25 @@ espconn_tcp_server(struct espconn *espconn) ...@@ -872,19 +1258,25 @@ espconn_tcp_server(struct espconn *espconn)
struct tcp_pcb *pcb = NULL; struct tcp_pcb *pcb = NULL;
espconn_msg *pserver = NULL; espconn_msg *pserver = NULL;
/*Creates a new server control message*/
pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
if (pserver == NULL){ if (pserver == NULL){
return ESPCONN_MEM; return ESPCONN_MEM;
} }
/*Creates a new TCP protocol control block*/
pcb = tcp_new(); pcb = tcp_new();
if (pcb == NULL) { if (pcb == NULL) {
// espconn ->state = ESPCONN_NONE; /*to prevent memory leaks, ensure that each allocated is deleted*/
os_free(pserver); os_free(pserver);
pserver = NULL; pserver = NULL;
return ESPCONN_MEM; return ESPCONN_MEM;
} else { } else {
struct tcp_pcb *lpcb = NULL;
/*Binds the connection to a local port number and any IP address*/
tcp_bind(pcb, IP_ADDR_ANY, espconn->proto.tcp->local_port); tcp_bind(pcb, IP_ADDR_ANY, espconn->proto.tcp->local_port);
lpcb = pcb;
/*malloc and set the state of the connection to be LISTEN*/
pcb = tcp_listen(pcb); pcb = tcp_listen(pcb);
if (pcb != NULL) { if (pcb != NULL) {
/*insert the node to the active connection list*/ /*insert the node to the active connection list*/
...@@ -892,14 +1284,16 @@ espconn_tcp_server(struct espconn *espconn) ...@@ -892,14 +1284,16 @@ espconn_tcp_server(struct espconn *espconn)
pserver->preverse = pcb; pserver->preverse = pcb;
pserver->pespconn = espconn; pserver->pespconn = espconn;
pserver->count_opt = MEMP_NUM_TCP_PCB; pserver->count_opt = MEMP_NUM_TCP_PCB;
pserver->pcommon.timeout = 0x0a;
espconn ->state = ESPCONN_LISTEN; espconn ->state = ESPCONN_LISTEN;
/*set the specify argument that should be passed callback function*/
tcp_arg(pcb, (void *)espconn); tcp_arg(pcb, (void *)espconn);
// tcp_err(pcb, esponn_server_err); /*accept callback function to call for this control block*/
tcp_accept(pcb, espconn_tcp_accept); tcp_accept(pcb, espconn_tcp_accept);
return ESPCONN_OK; return ESPCONN_OK;
} else { } else {
// espconn ->state = ESPCONN_NONE; /*to prevent memory leaks, ensure that each allocated is deleted*/
memp_free(MEMP_TCP_PCB,lpcb);
os_free(pserver); os_free(pserver);
pserver = NULL; pserver = NULL;
return ESPCONN_MEM; return ESPCONN_MEM;
...@@ -924,17 +1318,19 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon) ...@@ -924,17 +1318,19 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon)
return ESPCONN_ARG; return ESPCONN_ARG;
espconn_get_connection_info(pdeletecon, &pinfo , 0); espconn_get_connection_info(pdeletecon, &pinfo , 0);
/*make sure all the active connection have been disconnect*/
if (pdeletecon->link_cnt != 0) if (pdeletecon->link_cnt != 0)
return ESPCONN_INPROGRESS; return ESPCONN_INPROGRESS;
else { else {
os_printf("espconn_tcp_delete %p\n",pdeletecon); espconn_printf("espconn_tcp_delete %p\n",pdeletecon);
pdelete_msg = pserver_list; pdelete_msg = pserver_list;
while (pdelete_msg != NULL){ while (pdelete_msg != NULL){
if (pdelete_msg->pespconn == pdeletecon){ if (pdelete_msg->pespconn == pdeletecon){
/*remove the node from the client's active connection list*/ /*remove the node from the client's active connection list*/
espconn_list_delete(&pserver_list, pdelete_msg); espconn_list_delete(&pserver_list, pdelete_msg);
pcb = pdelete_msg->preverse; pcb = pdelete_msg->preverse;
os_printf("espconn_tcp_delete %d\n",pcb->state); os_printf("espconn_tcp_delete %d, %d\n",pcb->state, pcb->local_port);
espconn_kill_pcb(pcb->local_port);
err = tcp_close(pcb); err = tcp_close(pcb);
os_free(pdelete_msg); os_free(pdelete_msg);
pdelete_msg = NULL; pdelete_msg = NULL;
...@@ -949,18 +1345,13 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon) ...@@ -949,18 +1345,13 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon)
} }
} }
void espconn_tcp_hold(void *arg) { /******************************************************************************
espconn_msg *ptcp_sent = arg; * FunctionName : espconn_init
struct tcp_pcb *pcb = NULL; * Description : used to init the function that should be used when
pcb = ptcp_sent->pcommon.pcb; * Parameters : none
* Returns : none
pcb->hold = 1; *******************************************************************************/
} void ICACHE_FLASH_ATTR espconn_init(void)
{
void espconn_tcp_unhold(void *arg) { ets_task(espconn_Task, espconn_TaskPrio, espconn_TaskQueue, espconn_TaskQueueLen);
espconn_msg *ptcp_sent = arg;
struct tcp_pcb *pcb = NULL;
pcb = ptcp_sent->pcommon.pcb;
pcb->hold = 0;
} }
/****************************************************************************** /******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi) * Copyright 2013-2014 Espressif Systems (Wuxi)
* *
* FileName: espconn_udp.c * FileName: espconn_udp.c
* *
* Description: udp proto interface * Description: udp proto interface
* *
* Modification history: * Modification history:
* 2014/3/31, v1.0 create this file. * 2014/3/31, v1.0 create this file.
*******************************************************************************/ *******************************************************************************/
#include "ets_sys.h" #include "ets_sys.h"
#include "os_type.h" #include "os_type.h"
//#include "os.h" //#include "os.h"
#include "lwip/inet.h" #include "lwip/inet.h"
#include "lwip/err.h" #include "lwip/err.h"
#include "lwip/pbuf.h" #include "lwip/pbuf.h"
#include "lwip/mem.h" #include "lwip/mem.h"
#include "lwip/tcp_impl.h" #include "lwip/tcp_impl.h"
#include "lwip/udp.h" #include "lwip/udp.h"
#include "lwip/app/espconn_udp.h" #include "lwip/app/espconn_udp.h"
extern espconn_msg *plink_active; //#include "net80211/ieee80211_var.h"
extern espconn_msg *plink_active;
static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn) extern uint8 default_interface;
{ static void ICACHE_FLASH_ATTR espconn_data_sentcb(struct espconn *pespconn)
if (pespconn == NULL) { {
return; if (pespconn == NULL) {
} return;
}
if (pespconn->sent_callback != NULL) {
pespconn->sent_callback(pespconn); if (pespconn->sent_callback != NULL) {
} pespconn->sent_callback(pespconn);
} }
}
static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg)
{ static void ICACHE_FLASH_ATTR espconn_data_sent(void *arg)
espconn_msg *psent = arg; {
espconn_msg *psent = arg;
if (psent == NULL) {
return; if (psent == NULL) {
} return;
}
if (psent->pcommon.cntr == 0) {
psent->pespconn->state = ESPCONN_CONNECT; if (psent->pcommon.cntr == 0) {
sys_timeout(TCP_FAST_INTERVAL, espconn_data_sentcb, psent->pespconn); psent->pespconn->state = ESPCONN_CONNECT;
} else { // sys_timeout(10, espconn_data_sentcb, psent->pespconn);
espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr); espconn_data_sentcb(psent->pespconn);
} } else {
} espconn_udp_sent(arg, psent->pcommon.ptrbuf, psent->pcommon.cntr);
}
/****************************************************************************** }
* FunctionName : espconn_udp_sent
* Description : sent data for client or server /******************************************************************************
* Parameters : void *arg -- client or server to send * FunctionName : espconn_udp_sent
* uint8* psent -- Data to send * Description : sent data for client or server
* uint16 length -- Length of data to send * Parameters : void *arg -- client or server to send
* Returns : none * uint8* psent -- Data to send
*******************************************************************************/ * uint16 length -- Length of data to send
void ICACHE_FLASH_ATTR * Returns : return espconn error code.
espconn_udp_sent(void *arg, uint8 *psent, uint16 length) * - ESPCONN_OK. Successful. No error occured.
{ * - ESPCONN_MEM. Out of memory.
espconn_msg *pudp_sent = arg; * - ESPCONN_RTE. Could not find route to destination address.
struct udp_pcb *upcb = pudp_sent->pcommon.pcb; * - More errors could be returned by lower protocol layers.
struct pbuf *p, *q; *******************************************************************************/
u8_t *data = NULL; err_t ICACHE_FLASH_ATTR
u16_t cnt = 0; espconn_udp_sent(void *arg, uint8 *psent, uint16 length)
u16_t datalen = 0; {
u16_t i = 0; espconn_msg *pudp_sent = arg;
err_t err; struct udp_pcb *upcb = pudp_sent->pcommon.pcb;
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb)); struct pbuf *p, *q ,*p_temp;
u8_t *data = NULL;
if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) { u16_t cnt = 0;
return; u16_t datalen = 0;
} u16_t i = 0;
err_t err;
if (1024 < length) { LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d %p\n", __LINE__, length, upcb));
datalen = 1024;
} else { if (pudp_sent == NULL || upcb == NULL || psent == NULL || length == 0) {
datalen = length; return ESPCONN_ARG;
} }
p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM); if (TCP_MSS < length) {
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p)); datalen = TCP_MSS;
} else {
if (p != NULL) { datalen = length;
q = p; }
while (q != NULL) { p = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
data = (u8_t *)q->payload; LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
if (p != NULL) {
for (i = 0; i < q->len; i++) { q = p;
data[i] = ((u8_t *) psent)[cnt++];
} while (q != NULL) {
data = (u8_t *)q->payload;
q = q->next; LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, data));
}
} else { for (i = 0; i < q->len; i++) {
return; data[i] = ((u8_t *) psent)[cnt++];
} }
upcb->remote_port = pudp_sent->pespconn->proto.udp->remote_port; q = q->next;
IP4_ADDR(&upcb->remote_ip, pudp_sent->pespconn->proto.udp->remote_ip[0], }
pudp_sent->pespconn->proto.udp->remote_ip[1], } else {
pudp_sent->pespconn->proto.udp->remote_ip[2], return ESPCONN_MEM;
pudp_sent->pespconn->proto.udp->remote_ip[3]); }
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port)); upcb->remote_port = pudp_sent->pespconn->proto.udp->remote_port;
err = udp_send(upcb, p); IP4_ADDR(&upcb->remote_ip, pudp_sent->pespconn->proto.udp->remote_ip[0],
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d\n", __LINE__, err)); pudp_sent->pespconn->proto.udp->remote_ip[1],
pudp_sent->pespconn->proto.udp->remote_ip[2],
if (p->ref != 0) { pudp_sent->pespconn->proto.udp->remote_ip[3]);
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
pbuf_free(p); LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %x %d\n", __LINE__, upcb->remote_ip, upcb->remote_port));
pudp_sent->pcommon.ptrbuf = psent + datalen;
pudp_sent->pcommon.cntr = length - datalen; struct netif *sta_netif = (struct netif *)eagle_lwip_getif(0x00);
espconn_data_sent(pudp_sent); struct netif *ap_netif = (struct netif *)eagle_lwip_getif(0x01);
}
} if(wifi_get_opmode() == ESPCONN_AP_STA && default_interface == ESPCONN_AP_STA && sta_netif != NULL && ap_netif != NULL)
{
/****************************************************************************** if(netif_is_up(sta_netif) && netif_is_up(ap_netif) && \
* FunctionName : espconn_udp_server_recv ip_addr_isbroadcast(&upcb->remote_ip, sta_netif) && \
* Description : This callback will be called when receiving a datagram. ip_addr_isbroadcast(&upcb->remote_ip, ap_netif)) {
* Parameters : arg -- user supplied argument
* upcb -- the udp_pcb which received data p_temp = pbuf_alloc(PBUF_TRANSPORT, datalen, PBUF_RAM);
* p -- the packet buffer that was received if (pbuf_copy (p_temp,p) != ERR_OK) {
* addr -- the remote IP address from which the packet was received LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent: copying to new pbuf failed\n"));
* port -- the remote port from which the packet was received return ESPCONN_ARG;
* Returns : none }
*******************************************************************************/ netif_set_default(sta_netif);
static void ICACHE_FLASH_ATTR err = udp_send(upcb, p_temp);
espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, pbuf_free(p_temp);
struct ip_addr *addr, u16_t port) netif_set_default(ap_netif);
{ }
espconn_msg *precv = arg; }
struct pbuf *q = NULL; err = udp_send(upcb, p);
u8_t *pdata = NULL;
u16_t length = 0; LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %d\n", __LINE__, err));
struct ip_info ipconfig;
if (p->ref != 0) {
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb)); LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_sent %d %p\n", __LINE__, p));
pbuf_free(p);
upcb->remote_port = port; pudp_sent->pcommon.ptrbuf = psent + datalen;
upcb->remote_ip = *addr; pudp_sent->pcommon.cntr = length - datalen;
espconn_data_sent(pudp_sent);
precv->pcommon.remote_ip[0] = ip4_addr1_16(&upcb->remote_ip); return err;
precv->pcommon.remote_ip[1] = ip4_addr2_16(&upcb->remote_ip); } else {
precv->pcommon.remote_ip[2] = ip4_addr3_16(&upcb->remote_ip); pbuf_free(p);
precv->pcommon.remote_ip[3] = ip4_addr4_16(&upcb->remote_ip); return ESPCONN_RTE;
os_memcpy(precv->pespconn->proto.udp->remote_ip, precv->pcommon.remote_ip, 4); }
precv->pespconn->proto.udp->remote_port = port; }
precv->pcommon.remote_port = port;
precv->pcommon.pcb = upcb; /******************************************************************************
* FunctionName : espconn_udp_server_recv
if (wifi_get_opmode() != 1) { * Description : This callback will be called when receiving a datagram.
wifi_get_ip_info(1, &ipconfig); * Parameters : arg -- user supplied argument
* upcb -- the udp_pcb which received data
if (!ip_addr_netcmp((struct ip_addr *)precv->pespconn->proto.udp->remote_ip, &ipconfig.ip, &ipconfig.netmask)) { * p -- the packet buffer that was received
wifi_get_ip_info(0, &ipconfig); * addr -- the remote IP address from which the packet was received
} * port -- the remote port from which the packet was received
} else { * Returns : none
wifi_get_ip_info(0, &ipconfig); *******************************************************************************/
} static void ICACHE_FLASH_ATTR
upcb->local_ip = ipconfig.ip; espconn_udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p,
precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&upcb->local_ip); struct ip_addr *addr, u16_t port)
precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&upcb->local_ip); {
precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&upcb->local_ip); espconn_msg *precv = arg;
precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&upcb->local_ip); struct pbuf *q = NULL;
u8_t *pdata = NULL;
if (p != NULL) { u16_t length = 0;
// q = p; struct ip_info ipconfig;
// while (q != NULL) { LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %p\n", __LINE__, upcb));
// pdata = (u8_t *)os_zalloc(q ->len + 1);
// length = pbuf_copy_partial(q, pdata, q ->len, 0); upcb->remote_port = port;
// upcb->remote_ip = *addr;
// LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %x\n", __LINE__, length));
// precv->pcommon.pcb = upcb; precv->pcommon.remote_ip[0] = ip4_addr1_16(&upcb->remote_ip);
// precv->pcommon.remote_ip[1] = ip4_addr2_16(&upcb->remote_ip);
// if (length != 0) { precv->pcommon.remote_ip[2] = ip4_addr3_16(&upcb->remote_ip);
// if (precv->pespconn->recv_callback != NULL) { precv->pcommon.remote_ip[3] = ip4_addr4_16(&upcb->remote_ip);
// precv->pespconn->recv_callback(precv->pespconn, pdata, length); os_memcpy(precv->pespconn->proto.udp->remote_ip, precv->pcommon.remote_ip, 4);
// } precv->pespconn->proto.udp->remote_port = port;
// } precv->pcommon.remote_port = port;
// precv->pcommon.pcb = upcb;
// q = q->next;
// os_free(pdata); if (wifi_get_opmode() != 1) {
// } wifi_get_ip_info(1, &ipconfig);
pdata = (u8_t *)os_zalloc(p ->tot_len + 1);
length = pbuf_copy_partial(p, pdata, p ->tot_len, 0); if (!ip_addr_netcmp((struct ip_addr *)precv->pespconn->proto.udp->remote_ip, &ipconfig.ip, &ipconfig.netmask)) {
precv->pcommon.pcb = upcb; wifi_get_ip_info(0, &ipconfig);
pbuf_free(p); }
if (length != 0) { } else {
if (precv->pespconn->recv_callback != NULL) { wifi_get_ip_info(0, &ipconfig);
precv->pespconn->recv_callback(precv->pespconn, pdata, length); }
} // upcb->local_ip = ipconfig.ip;
} precv->pespconn->proto.udp->local_ip[0] = ip4_addr1_16(&ipconfig.ip);
os_free(pdata); precv->pespconn->proto.udp->local_ip[1] = ip4_addr2_16(&ipconfig.ip);
} else { precv->pespconn->proto.udp->local_ip[2] = ip4_addr3_16(&ipconfig.ip);
return; precv->pespconn->proto.udp->local_ip[3] = ip4_addr4_16(&ipconfig.ip);
}
} if (p != NULL) {
// q = p;
/******************************************************************************
* FunctionName : espconn_udp_disconnect // while (q != NULL) {
* Description : A new incoming connection has been disconnected. // pdata = (u8_t *)os_zalloc(q ->len + 1);
* Parameters : espconn -- the espconn used to disconnect with host // length = pbuf_copy_partial(q, pdata, q ->len, 0);
* Returns : none //
*******************************************************************************/ // LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("espconn_udp_server_recv %d %x\n", __LINE__, length));
void ICACHE_FLASH_ATTR espconn_udp_disconnect(espconn_msg *pdiscon) // precv->pcommon.pcb = upcb;
{ //
if (pdiscon == NULL) { // if (length != 0) {
return; // if (precv->pespconn->recv_callback != NULL) {
} // precv->pespconn->recv_callback(precv->pespconn, pdata, length);
// }
struct udp_pcb *upcb = pdiscon->pcommon.pcb; // }
//
udp_disconnect(upcb); // q = q->next;
// os_free(pdata);
udp_remove(upcb); // }
pdata = (u8_t *)os_zalloc(p ->tot_len + 1);
espconn_list_delete(&plink_active, pdiscon); length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
precv->pcommon.pcb = upcb;
os_free(pdiscon); pbuf_free(p);
pdiscon = NULL; if (length != 0) {
} if (precv->pespconn->recv_callback != NULL) {
precv->pespconn->recv_callback(precv->pespconn, pdata, length);
/****************************************************************************** }
* FunctionName : espconn_udp_server }
* Description : Initialize the server: set up a PCB and bind it to the port os_free(pdata);
* Parameters : pespconn -- the espconn used to build server } else {
* Returns : none return;
*******************************************************************************/ }
sint8 ICACHE_FLASH_ATTR }
espconn_udp_server(struct espconn *pespconn)
{ /******************************************************************************
struct udp_pcb *upcb = NULL; * FunctionName : espconn_udp_disconnect
espconn_msg *pserver = NULL; * Description : A new incoming connection has been disconnected.
upcb = udp_new(); * Parameters : espconn -- the espconn used to disconnect with host
* Returns : none
if (upcb == NULL) { *******************************************************************************/
return ESPCONN_MEM; void ICACHE_FLASH_ATTR espconn_udp_disconnect(espconn_msg *pdiscon)
} else { {
pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg)); if (pdiscon == NULL) {
return;
if (pserver == NULL) { }
udp_remove(upcb);
return ESPCONN_MEM; struct udp_pcb *upcb = pdiscon->pcommon.pcb;
}
udp_disconnect(upcb);
pserver->pcommon.pcb = upcb;
pserver->pespconn = pespconn; udp_remove(upcb);
espconn_list_creat(&plink_active, pserver);
udp_bind(upcb, IP_ADDR_ANY, pserver->pespconn->proto.udp->local_port); espconn_list_delete(&plink_active, pdiscon);
udp_recv(upcb, espconn_udp_recv, (void *)pserver);
return ESPCONN_OK; os_free(pdiscon);
} pdiscon = NULL;
} }
/****************************************************************************** /******************************************************************************
* FunctionName : espconn_igmp_leave * FunctionName : espconn_udp_server
* Description : leave a multicast group * Description : Initialize the server: set up a PCB and bind it to the port
* Parameters : host_ip -- the ip address of udp server * Parameters : pespconn -- the espconn used to build server
* multicast_ip -- multicast ip given by user * Returns : none
* Returns : none *******************************************************************************/
*******************************************************************************/ sint8 ICACHE_FLASH_ATTR
sint8 ICACHE_FLASH_ATTR espconn_udp_server(struct espconn *pespconn)
espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip) {
{ struct udp_pcb *upcb = NULL;
if (igmp_leavegroup(host_ip, multicast_ip) != ERR_OK) { espconn_msg *pserver = NULL;
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_leave_multigrup failed!\n")); upcb = udp_new();
return -1;
}; if (upcb == NULL) {
return ESPCONN_MEM;
return ESPCONN_OK; } else {
} pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
/****************************************************************************** if (pserver == NULL) {
* FunctionName : espconn_igmp_join udp_remove(upcb);
* Description : join a multicast group return ESPCONN_MEM;
* Parameters : host_ip -- the ip address of udp server }
* multicast_ip -- multicast ip given by user
* Returns : none pserver->pcommon.pcb = upcb;
*******************************************************************************/ pserver->pespconn = pespconn;
sint8 ICACHE_FLASH_ATTR espconn_list_creat(&plink_active, pserver);
espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip) udp_bind(upcb, IP_ADDR_ANY, pserver->pespconn->proto.udp->local_port);
{ udp_recv(upcb, espconn_udp_recv, (void *)pserver);
if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) { return ESPCONN_OK;
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n")); }
return -1; }
};
/******************************************************************************
/* join to any IP address at the port */ * FunctionName : espconn_igmp_leave
return ESPCONN_OK; * Description : leave a multicast group
} * Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
{
if (igmp_leavegroup(host_ip, multicast_ip) != ERR_OK) {
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_leave_multigrup failed!\n"));
return -1;
};
return ESPCONN_OK;
}
/******************************************************************************
* FunctionName : espconn_igmp_join
* Description : join a multicast group
* Parameters : host_ip -- the ip address of udp server
* multicast_ip -- multicast ip given by user
* Returns : none
*******************************************************************************/
sint8 ICACHE_FLASH_ATTR
espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip)
{
if (igmp_joingroup(host_ip, multicast_ip) != ERR_OK) {
LWIP_DEBUGF(ESPCONN_UDP_DEBUG, ("udp_join_multigrup failed!\n"));
return -1;
};
/* join to any IP address at the port */
return ESPCONN_OK;
}
/** /**
* @file * @file
* MetIO Server * MetIO Server
* *
*/ */
/* /*
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met: * are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products * 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * 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 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE. * OF SUCH DAMAGE.
* *
* This file is part of the lwIP TCP/IP stack. * This file is part of the lwIP TCP/IP stack.
* *
*/ */
#include "lwip/opt.h" #include "lwip/opt.h"
#if LWIP_TCP #if LWIP_TCP
#include "lwip/tcp.h" #include "lwip/tcp.h"
/* /*
* This implements a netio server. * This implements a netio server.
* The client sends a command word (4 bytes) then a data length word (4 bytes). * The client sends a command word (4 bytes) then a data length word (4 bytes).
* If the command is "receive", the server is to consume "data length" bytes into * If the command is "receive", the server is to consume "data length" bytes into
* a circular buffer until the first byte is non-zero, then it is to consume * a circular buffer until the first byte is non-zero, then it is to consume
* another command/data pair. * another command/data pair.
* If the command is "send", the server is to send "data length" bytes from a circular * If the command is "send", the server is to send "data length" bytes from a circular
* buffer with the first byte being zero, until "some time" (6 seconds in the * buffer with the first byte being zero, until "some time" (6 seconds in the
* current netio126.zip download) has passed and then send one final buffer with * current netio126.zip download) has passed and then send one final buffer with
* the first byte being non-zero. Then it is to consume another command/data pair. * the first byte being non-zero. Then it is to consume another command/data pair.
*/ */
/* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */ /* See http://www.nwlab.net/art/netio/netio.html to get the netio tool */
/* implementation options */ /* implementation options */
#define NETIO_BUF_SIZE (4 * 1024) #define NETIO_BUF_SIZE (4 * 1024)
#define NETIO_USE_STATIC_BUF 0 #define NETIO_USE_STATIC_BUF 0
/* NetIO server state definition */ /* NetIO server state definition */
#define NETIO_STATE_WAIT_FOR_CMD 0 #define NETIO_STATE_WAIT_FOR_CMD 0
#define NETIO_STATE_RECV_DATA 1 #define NETIO_STATE_RECV_DATA 1
#define NETIO_STATE_SEND_DATA 2 #define NETIO_STATE_SEND_DATA 2
#define NETIO_STATE_SEND_DATA_LAST 3 #define NETIO_STATE_SEND_DATA_LAST 3
#define NETIO_STATE_DONE 4 #define NETIO_STATE_DONE 4
struct netio_state { struct netio_state {
u32_t state; u32_t state;
u32_t cmd; u32_t cmd;
u32_t data_len; u32_t data_len;
u32_t cntr; u32_t cntr;
u8_t * buf_ptr; u8_t * buf_ptr;
u32_t buf_pos; u32_t buf_pos;
u32_t first_byte; u32_t first_byte;
u32_t time_stamp; u32_t time_stamp;
}; };
/* NetIO command protocol definition */ /* NetIO command protocol definition */
#define NETIO_CMD_QUIT 0 #define NETIO_CMD_QUIT 0
#define NETIO_CMD_C2S 1 #define NETIO_CMD_C2S 1
#define NETIO_CMD_S2C 2 #define NETIO_CMD_S2C 2
#define NETIO_CMD_RES 3 #define NETIO_CMD_RES 3
static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err); static err_t netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
netio_close(void *arg, struct tcp_pcb *pcb) netio_close(void *arg, struct tcp_pcb *pcb)
{ {
err_t err; err_t err;
struct netio_state *ns = arg; struct netio_state *ns = arg;
ns->state = NETIO_STATE_DONE; ns->state = NETIO_STATE_DONE;
tcp_recv(pcb, NULL); tcp_recv(pcb, NULL);
err = tcp_close(pcb); err = tcp_close(pcb);
if (err != ERR_OK) { if (err != ERR_OK) {
/* closing failed, try again later */ /* closing failed, try again later */
tcp_recv(pcb, netio_recv); tcp_recv(pcb, netio_recv);
} else { } else {
/* closing succeeded */ /* closing succeeded */
#if NETIO_USE_STATIC_BUF != 1 #if NETIO_USE_STATIC_BUF != 1
if(ns->buf_ptr != NULL){ if(ns->buf_ptr != NULL){
mem_free(ns->buf_ptr); mem_free(ns->buf_ptr);
} }
#endif #endif
tcp_arg(pcb, NULL); tcp_arg(pcb, NULL);
tcp_poll(pcb, NULL, 0); tcp_poll(pcb, NULL, 0);
tcp_sent(pcb, NULL); tcp_sent(pcb, NULL);
if (arg != NULL) { if (arg != NULL) {
mem_free(arg); mem_free(arg);
} }
} }
} }
static err_t ICACHE_FLASH_ATTR static err_t ICACHE_FLASH_ATTR
netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) netio_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{ {
struct netio_state *ns = arg; struct netio_state *ns = arg;
u8_t * data_ptr; u8_t * data_ptr;
u32_t data_cntr; u32_t data_cntr;
struct pbuf *q = p; struct pbuf *q = p;
u16_t len; u16_t len;
if (p != NULL) { if (p != NULL) {
tcp_recved(pcb, p->tot_len); tcp_recved(pcb, p->tot_len);
} }
if (err == ERR_OK && q != NULL) { if (err == ERR_OK && q != NULL) {
while (q != NULL) { while (q != NULL) {
data_cntr = q->len; data_cntr = q->len;
data_ptr = q->payload; data_ptr = q->payload;
while (data_cntr--) { while (data_cntr--) {
if (ns->state == NETIO_STATE_DONE){ if (ns->state == NETIO_STATE_DONE){
netio_close(ns, pcb); netio_close(ns, pcb);
break; break;
} else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) { } else if (ns->state == NETIO_STATE_WAIT_FOR_CMD) {
if (ns->cntr < 4) { if (ns->cntr < 4) {
/* build up the CMD field */ /* build up the CMD field */
ns->cmd <<= 8; ns->cmd <<= 8;
ns->cmd |= *data_ptr++; ns->cmd |= *data_ptr++;
ns->cntr++; ns->cntr++;
} else if (ns->cntr < 8) { } else if (ns->cntr < 8) {
/* build up the DATA field */ /* build up the DATA field */
ns->data_len <<= 8; ns->data_len <<= 8;
ns->data_len |= *data_ptr++; ns->data_len |= *data_ptr++;
ns->cntr++; ns->cntr++;
if (ns->cntr == 8) { if (ns->cntr == 8) {
/* now we have full command and data words */ /* now we have full command and data words */
ns->cntr = 0; ns->cntr = 0;
ns->buf_pos = 0; ns->buf_pos = 0;
ns->buf_ptr[0] = 0; ns->buf_ptr[0] = 0;
if (ns->cmd == NETIO_CMD_C2S) { if (ns->cmd == NETIO_CMD_C2S) {
ns->state = NETIO_STATE_RECV_DATA; ns->state = NETIO_STATE_RECV_DATA;
} else if (ns->cmd == NETIO_CMD_S2C) { } else if (ns->cmd == NETIO_CMD_S2C) {
ns->state = NETIO_STATE_SEND_DATA; ns->state = NETIO_STATE_SEND_DATA;
/* start timer */ /* start timer */
ns->time_stamp = sys_now(); ns->time_stamp = sys_now();
/* send first round of data */ /* send first round of data */
len = tcp_sndbuf(pcb); len = tcp_sndbuf(pcb);
len = LWIP_MIN(len, ns->data_len - ns->cntr); len = LWIP_MIN(len, ns->data_len - ns->cntr);
len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos);
do { do {
err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY);
if (err == ERR_MEM) { if (err == ERR_MEM) {
len /= 2; len /= 2;
} }
} while ((err == ERR_MEM) && (len > 1)); } while ((err == ERR_MEM) && (len > 1));
ns->buf_pos += len; ns->buf_pos += len;
ns->cntr += len; ns->cntr += len;
} else { } else {
/* unrecognized command, punt */ /* unrecognized command, punt */
ns->cntr = 0; ns->cntr = 0;
ns->buf_pos = 0; ns->buf_pos = 0;
ns->buf_ptr[0] = 0; ns->buf_ptr[0] = 0;
netio_close(ns, pcb); netio_close(ns, pcb);
break; break;
} }
} }
} else { } else {
/* in trouble... shouldn't be in this state! */ /* in trouble... shouldn't be in this state! */
} }
} else if (ns->state == NETIO_STATE_RECV_DATA) { } else if (ns->state == NETIO_STATE_RECV_DATA) {
if(ns->cntr == 0){ if(ns->cntr == 0){
/* save the first byte of this new round of data /* save the first byte of this new round of data
* this will not match ns->buf_ptr[0] in the case that * this will not match ns->buf_ptr[0] in the case that
* NETIO_BUF_SIZE is less than ns->data_len. * NETIO_BUF_SIZE is less than ns->data_len.
*/ */
ns->first_byte = *data_ptr; ns->first_byte = *data_ptr;
} }
ns->buf_ptr[ns->buf_pos++] = *data_ptr++; ns->buf_ptr[ns->buf_pos++] = *data_ptr++;
ns->cntr++; ns->cntr++;
if (ns->buf_pos == NETIO_BUF_SIZE) { if (ns->buf_pos == NETIO_BUF_SIZE) {
/* circularize the buffer */ /* circularize the buffer */
ns->buf_pos = 0; ns->buf_pos = 0;
} }
if(ns->cntr == ns->data_len){ if(ns->cntr == ns->data_len){
ns->cntr = 0; ns->cntr = 0;
if (ns->first_byte != 0) { if (ns->first_byte != 0) {
/* if this last round did not start with 0, /* if this last round did not start with 0,
* go look for another command */ * go look for another command */
ns->state = NETIO_STATE_WAIT_FOR_CMD; ns->state = NETIO_STATE_WAIT_FOR_CMD;
ns->data_len = 0; ns->data_len = 0;
ns->cmd = 0; ns->cmd = 0;
/* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */
} else { } else {
/* stay here and wait on more data */ /* stay here and wait on more data */
} }
} }
} else if (ns->state == NETIO_STATE_SEND_DATA } else if (ns->state == NETIO_STATE_SEND_DATA
|| ns->state == NETIO_STATE_SEND_DATA_LAST) { || ns->state == NETIO_STATE_SEND_DATA_LAST) {
/* I don't think this should happen... */ /* I don't think this should happen... */
} else { } else {
/* done / quit */ /* done / quit */
netio_close(ns, pcb); netio_close(ns, pcb);
break; break;
} /* end of ns->state condition */ } /* end of ns->state condition */
} /* end of while data still in this pbuf */ } /* end of while data still in this pbuf */
q = q->next; q = q->next;
} }
pbuf_free(p); pbuf_free(p);
} else { } else {
/* error or closed by other side */ /* error or closed by other side */
if (p != NULL) { if (p != NULL) {
pbuf_free(p); pbuf_free(p);
} }
/* close the connection */ /* close the connection */
netio_close(ns, pcb); netio_close(ns, pcb);
} }
return ERR_OK; return ERR_OK;
} }
static err_t ICACHE_FLASH_ATTR static err_t ICACHE_FLASH_ATTR
netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len) netio_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{ {
struct netio_state *ns = arg; struct netio_state *ns = arg;
err_t err = ERR_OK; err_t err = ERR_OK;
if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) { if (ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA) {
/* done with this round of sending */ /* done with this round of sending */
ns->buf_pos = 0; ns->buf_pos = 0;
ns->cntr = 0; ns->cntr = 0;
/* check if timer expired */ /* check if timer expired */
if (sys_now() - ns->time_stamp > 600) { if (sys_now() - ns->time_stamp > 600) {
ns->buf_ptr[0] = 1; ns->buf_ptr[0] = 1;
ns->state = NETIO_STATE_SEND_DATA_LAST; ns->state = NETIO_STATE_SEND_DATA_LAST;
} else { } else {
ns->buf_ptr[0] = 0; ns->buf_ptr[0] = 0;
} }
} }
if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){ if(ns->state == NETIO_STATE_SEND_DATA_LAST || ns->state == NETIO_STATE_SEND_DATA){
len = tcp_sndbuf(pcb); len = tcp_sndbuf(pcb);
len = LWIP_MIN(len, ns->data_len - ns->cntr); len = LWIP_MIN(len, ns->data_len - ns->cntr);
len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos); len = LWIP_MIN(len, NETIO_BUF_SIZE - ns->buf_pos);
if(ns->cntr < ns->data_len){ if(ns->cntr < ns->data_len){
do { do {
err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY); err = tcp_write(pcb, ns->buf_ptr + ns->buf_pos, len, TCP_WRITE_FLAG_COPY);
if (err == ERR_MEM) { if (err == ERR_MEM) {
len /= 2; len /= 2;
} }
} while ((err == ERR_MEM) && (len > 1)); } while ((err == ERR_MEM) && (len > 1));
ns->buf_pos += len; ns->buf_pos += len;
if(ns->buf_pos >= NETIO_BUF_SIZE){ if(ns->buf_pos >= NETIO_BUF_SIZE){
ns->buf_pos = 0; ns->buf_pos = 0;
} }
ns->cntr += len; ns->cntr += len;
} }
} }
if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){ if(ns->cntr >= ns->data_len && ns->state == NETIO_STATE_SEND_DATA_LAST){
/* we have buffered up all our data to send this last round, go look for a command */ /* we have buffered up all our data to send this last round, go look for a command */
ns->state = NETIO_STATE_WAIT_FOR_CMD; ns->state = NETIO_STATE_WAIT_FOR_CMD;
ns->cntr = 0; ns->cntr = 0;
/* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */ /* TODO LWIP_DEBUGF( print out some throughput calculation results... ); */
} }
return ERR_OK; return ERR_OK;
} }
static err_t ICACHE_FLASH_ATTR static err_t ICACHE_FLASH_ATTR
netio_poll(void *arg, struct tcp_pcb *pcb) netio_poll(void *arg, struct tcp_pcb *pcb)
{ {
struct netio_state * ns = arg; struct netio_state * ns = arg;
if(ns->state == NETIO_STATE_SEND_DATA){ if(ns->state == NETIO_STATE_SEND_DATA){
} else if(ns->state == NETIO_STATE_DONE){ } else if(ns->state == NETIO_STATE_DONE){
netio_close(ns, pcb); netio_close(ns, pcb);
} }
return ERR_OK; return ERR_OK;
} }
#if NETIO_USE_STATIC_BUF == 1 #if NETIO_USE_STATIC_BUF == 1
static u8_t netio_buf[NETIO_BUF_SIZE]; static u8_t netio_buf[NETIO_BUF_SIZE];
#endif #endif
static err_t ICACHE_FLASH_ATTR static err_t ICACHE_FLASH_ATTR
netio_accept(void *arg, struct tcp_pcb *pcb, err_t err) netio_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{ {
struct netio_state * ns; struct netio_state * ns;
LWIP_UNUSED_ARG(err); LWIP_UNUSED_ARG(err);
ns = mem_malloc(sizeof(struct netio_state)); ns = mem_malloc(sizeof(struct netio_state));
if(ns == NULL){ if(ns == NULL){
return ERR_MEM; return ERR_MEM;
} }
ns->state = NETIO_STATE_WAIT_FOR_CMD; ns->state = NETIO_STATE_WAIT_FOR_CMD;
ns->data_len = 0; ns->data_len = 0;
ns->cmd = 0; ns->cmd = 0;
ns->cntr = 0; ns->cntr = 0;
ns->buf_pos = 0; ns->buf_pos = 0;
#if NETIO_USE_STATIC_BUF == 1 #if NETIO_USE_STATIC_BUF == 1
ns->buf_ptr = netio_buf; ns->buf_ptr = netio_buf;
#else #else
ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE); ns->buf_ptr = mem_malloc(NETIO_BUF_SIZE);
if(ns->buf_ptr == NULL){ if(ns->buf_ptr == NULL){
mem_free(ns); mem_free(ns);
return ERR_MEM; return ERR_MEM;
} }
#endif #endif
ns->buf_ptr[0] = 0; ns->buf_ptr[0] = 0;
tcp_arg(pcb, ns); tcp_arg(pcb, ns);
tcp_sent(pcb, netio_sent); tcp_sent(pcb, netio_sent);
tcp_recv(pcb, netio_recv); tcp_recv(pcb, netio_recv);
tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */ tcp_poll(pcb, netio_poll, 4); /* every 2 seconds */
return ERR_OK; return ERR_OK;
} }
void ICACHE_FLASH_ATTR netio_init(void) void ICACHE_FLASH_ATTR netio_init(void)
{ {
struct tcp_pcb *pcb; struct tcp_pcb *pcb;
pcb = tcp_new(); pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 18767); tcp_bind(pcb, IP_ADDR_ANY, 18767);
pcb = tcp_listen(pcb); pcb = tcp_listen(pcb);
tcp_accept(pcb, netio_accept); tcp_accept(pcb, netio_accept);
} }
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
...@@ -93,6 +93,9 @@ ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) ...@@ -93,6 +93,9 @@ ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len)
iecho->chksum = 0; iecho->chksum = 0;
iecho->id = PING_ID; iecho->id = PING_ID;
++ ping_seq_num; ++ ping_seq_num;
if (ping_seq_num == 0x7fff)
ping_seq_num = 0;
iecho->seqno = htons(ping_seq_num); iecho->seqno = htons(ping_seq_num);
/* fill the additional data buffer with some data */ /* fill the additional data buffer with some data */
...@@ -233,7 +236,7 @@ ping_coarse_tmr(void *arg) ...@@ -233,7 +236,7 @@ ping_coarse_tmr(void *arg)
} else { } else {
uint32 delay = system_relative_time(pingmsg->ping_start); uint32 delay = system_relative_time(pingmsg->ping_start);
delay /= PING_COARSE; delay /= PING_COARSE;
ping_seq_num = 0; // ping_seq_num = 0;
if (ping_opt->sent_function == NULL){ if (ping_opt->sent_function == NULL){
os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n", os_printf("ping %d, timeout %d, total payload %d bytes, %d ms\n",
pingmsg->max_count, pingmsg->timeout_count, PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count),delay); pingmsg->max_count, pingmsg->timeout_count, PING_DATA_SIZE*(pingmsg->max_count - pingmsg->timeout_count),delay);
......
############################################################# #############################################################
# 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 = liblwipcore.a GEN_LIBS = liblwipcore.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
...@@ -129,7 +129,7 @@ u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX]; ...@@ -129,7 +129,7 @@ u8_t dhcp_rx_options_given[DHCP_OPTION_IDX_MAX];
#define dhcp_option_given(dhcp, idx) (dhcp_rx_options_given[idx] != 0) #define dhcp_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 +288,24 @@ dhcp_select(struct netif *netif) ...@@ -288,16 +288,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);
...@@ -587,7 +595,7 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) ...@@ -587,7 +595,7 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp)
LWIP_ASSERT("netif already has a struct dhcp set", netif->dhcp == NULL); 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 +634,6 @@ dhcp_start(struct netif *netif) ...@@ -626,7 +634,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 +675,7 @@ dhcp_start(struct netif *netif) ...@@ -668,7 +675,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 +720,7 @@ dhcp_inform(struct netif *netif) ...@@ -713,7 +720,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 +888,32 @@ dhcp_discover(struct netif *netif) ...@@ -881,11 +888,32 @@ dhcp_discover(struct netif *netif)
dhcp_option(dhcp, DHCP_OPTION_MAX_MSG_SIZE, DHCP_OPTION_MAX_MSG_SIZE_LEN); dhcp_option(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 +1022,12 @@ dhcp_bind(struct netif *netif) ...@@ -994,6 +1022,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 +1036,14 @@ dhcp_bind(struct netif *netif) ...@@ -1002,12 +1036,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 +1071,7 @@ dhcp_renew(struct netif *netif) ...@@ -1035,7 +1071,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 +1134,7 @@ dhcp_rebind(struct netif *netif) ...@@ -1098,7 +1134,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 +1281,6 @@ dhcp_stop(struct netif *netif) ...@@ -1245,7 +1281,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) {
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
/** 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 +173,7 @@ struct dns_table_entry { ...@@ -173,7 +173,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 +221,9 @@ static u8_t dns_seqno; ...@@ -221,9 +221,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 +233,7 @@ dns_init() ...@@ -233,7 +233,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 +299,7 @@ dns_getserver(u8_t numdns) ...@@ -299,7 +299,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 +321,7 @@ dns_init_local() ...@@ -321,7 +321,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 +416,7 @@ dns_local_addhost(const char *hostname, const ip_addr_t *addr) ...@@ -416,7 +416,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 +566,7 @@ dns_send(u8_t numdns, const char* name, u8_t id) ...@@ -566,7 +566,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 +579,8 @@ dns_send(u8_t numdns, const char* name, u8_t id) ...@@ -579,8 +579,8 @@ dns_send(u8_t numdns, const char* name, u8_t id)
LWIP_ASSERT("pbuf must be in one piece", p->next == NULL); 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 +673,6 @@ dns_check_entry(u8_t i) ...@@ -673,8 +673,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 +697,6 @@ dns_check_entry(u8_t i) ...@@ -699,8 +697,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 +739,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t ...@@ -743,6 +739,9 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
struct dns_table_entry *pEntry; 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 +766,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t ...@@ -767,6 +766,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t
/* The ID in the DNS header should be our entry into the name table. */ /* 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 +843,13 @@ responseerr: ...@@ -843,14 +843,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 +903,11 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) ...@@ -904,16 +903,11 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
LWIP_DEBUGF(DNS_DEBUG, ("dns_enqueue: \"%s\": use DNS entry %"U16_F"\n", name, (u16_t)(i))); 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 +946,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun ...@@ -952,7 +946,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 = 3;
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"));
......
...@@ -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"
/** DNS server IP address */
#ifndef DNS_MULTICAST_ADDRESS
#define DNS_MULTICAST_ADDRESS ipaddr_addr("224.0.0.251") /* resolver1.opendns.com */
#endif
/** DNS server IP address */
#ifndef MDNS_LOCAL
#define MDNS_LOCAL "local" /* resolver1.opendns.com */
#endif
/** DNS server port address */
#ifndef DNS_MDNS_PORT
#define DNS_MDNS_PORT 5353
#endif
/** DNS maximum number of retries when asking for a name, before "timeout". */
#ifndef DNS_MAX_RETRIES
#define DNS_MAX_RETRIES 4
#endif
/** DNS resource record max. TTL (one week as default) */
#ifndef DNS_MAX_TTL
#define DNS_MAX_TTL 604800
#endif
/* DNS protocol flags */
#define DNS_FLAG1_RESPONSE 0x84
#define DNS_FLAG1_OPCODE_STATUS 0x10
#define DNS_FLAG1_OPCODE_INVERSE 0x08
#define DNS_FLAG1_OPCODE_STANDARD 0x00
#define DNS_FLAG1_AUTHORATIVE 0x04
#define DNS_FLAG1_TRUNC 0x02
#define DNS_FLAG1_RD 0x01
#define DNS_FLAG2_RA 0x80
#define DNS_FLAG2_ERR_MASK 0x0f
#define DNS_FLAG2_ERR_NONE 0x00
#define DNS_FLAG2_ERR_NAME 0x03
/* DNS protocol states */
#define DNS_STATE_UNUSED 0
#define DNS_STATE_NEW 1
#define DNS_STATE_ASKING 2
#define DNS_STATE_DONE 3
/* MDNS registration type */
#define MDNS_HOSTNAME_REG 0
#define MDNS_SERVICE_REG 1
/* MDNS registration type */
#define MDNS_REG_ANSWER 1
#define MDNS_SD_ANSWER 2
#define MDNS_SERVICE_REG_ANSWER 3
/* MDNS registration time */
#define MDNS_HOST_TIME 120
#define MDNS_SERVICE_TIME 3600
/** MDNS name length with "." at the beginning and end of name*/
#ifndef MDNS_LENGTH_ADD
#define MDNS_LENGTH_ADD 2
#endif
#ifdef MDNS_MAX_NAME_LENGTH
#undef MDNS_MAX_NAME_LENGTH
#endif
#define MDNS_MAX_NAME_LENGTH (256)
PACK_STRUCT_BEGIN
/** DNS message header */
struct mdns_hdr {
PACK_STRUCT_FIELD(u16_t id);
PACK_STRUCT_FIELD(u8_t flags1);
PACK_STRUCT_FIELD(u8_t flags2);
PACK_STRUCT_FIELD(u16_t numquestions);
PACK_STRUCT_FIELD(u16_t numanswers);
PACK_STRUCT_FIELD(u16_t numauthrr);
PACK_STRUCT_FIELD(u16_t numextrarr);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#define SIZEOF_DNS_HDR 12
PACK_STRUCT_BEGIN
/** MDNS query message structure */
struct mdns_query {
/* MDNS query record starts with either a domain name or a pointer
to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
PACK_STRUCT_FIELD(u16_t class);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#define SIZEOF_DNS_QUERY 4
PACK_STRUCT_BEGIN
/** MDNS answer message structure */
struct mdns_answer {
/* MDNS answer record starts with either a domain name or a pointer
to a name already present somewhere in the packet. */PACK_STRUCT_FIELD(u16_t type);
PACK_STRUCT_FIELD(u16_t class);
PACK_STRUCT_FIELD(u32_t ttl);
PACK_STRUCT_FIELD(u16_t len);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#define SIZEOF_DNS_ANSWER 10
PACK_STRUCT_BEGIN
/** MDNS answer message structure */
struct mdns_auth {
PACK_STRUCT_FIELD(u32_t src);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#define SIZEOF_MDNS_AUTH 4
PACK_STRUCT_BEGIN
/** MDNS service registration message structure */
struct mdns_service {
PACK_STRUCT_FIELD(u16_t prior);
PACK_STRUCT_FIELD(u16_t weight);
PACK_STRUCT_FIELD(u16_t port);
}PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#define SIZEOF_MDNS_SERVICE 6
uint16 PUCK_PORT ;
os_timer_t mdns_timer;
/* forward declarations */
static void mdns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p,
struct ip_addr *addr, u16_t port);
/*-----------------------------------------------------------------------------
* Globales
*----------------------------------------------------------------------------*/
/* MDNS variables */
static char host_name[MDNS_NAME_LENGTH];
static char service_name[MDNS_NAME_LENGTH];
static char server_name[MDNS_NAME_LENGTH];
//static char puck_datasheet[PUCK_DATASHEET_SIZE];
static struct udp_pcb *mdns_pcb;
static struct ip_addr multicast_addr;
static struct ip_addr host_addr;
static uint8 register_flag = 0;
static uint8 mdns_flag = 0;
//#if (DNS_USES_STATIC_BUF == 1)
static u8_t mdns_payload[DNS_MSG_SIZE];
//#endif /* (MDNS_USES_STATIC_BUF == 1) */
/*
* Function to set the UDP pcb used to send the mDNS packages
*/
void ICACHE_FLASH_ATTR
getPcb(struct udp_pcb *pcb) {
mdns_pcb = pcb;
}
#if DNS_DOES_NAME_CHECK
/**
* Compare the "dotted" name "query" with the encoded name "response"
* to make sure an answer from the DNS server matches the current mdns_table
* entry (otherwise, answers might arrive late for hostname not on the list
* any more).
*
* @param query hostname (not encoded) from the mdns_table
* @param response encoded hostname in the DNS response
* @return 0: names equal; 1: names differ
*/
static u8_t ICACHE_FLASH_ATTR
mdns_compare_name(unsigned char *query, unsigned char *response) {
unsigned char n;
do {
n = *response++;
/** @see RFC 1035 - 4.1.4. Message compression */
if ((n & 0xc0) == 0xc0) {
/* Compressed name */
break;
} else {
/* Not compressed name */
while (n > 0) {
if ((*query) != (*response)) {
return 1;
}
++response;
++query;
--n;
};
++query;
}
} while (*response != 0);
return 0;
}
#endif /* DNS_DOES_NAME_CHECK */
/**
* Send a mDNS answer packet.
*
* @param type of answer hostname and service registration or service
* @param name to query
* @param id transaction ID in the DNS query packet
* @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
*/
static err_t ICACHE_FLASH_ATTR
mdns_answer(u16_t type, const char* name, u8_t id) {
err_t err;
struct mdns_hdr *hdr;
struct mdns_answer ans;
struct mdns_auth auth;
struct mdns_service serv;
struct pbuf *p ,*p_sta;
char *query, *nptr;
const char *pHostname;
struct netif * sta_netif = NULL;
struct netif * ap_netif = NULL;
static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
u8_t n;
u16_t length = 0;
/* if here, we have either a new query or a retry on a previous query to process */
p = pbuf_alloc(PBUF_TRANSPORT,
SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
if (p != NULL) {
LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
/* fill dns header */
hdr = (struct mdns_hdr*) p->payload;
os_memset(hdr, 0, SIZEOF_DNS_HDR);
hdr->id = htons(id);
hdr->flags1 = DNS_FLAG1_RESPONSE;
if (type == MDNS_SD_ANSWER) {
pHostname = DNS_SD_SERVICE;
hdr->numanswers = htons(1);
} else if (type == MDNS_SERVICE_REG_ANSWER) {
pHostname = PUCK_SERVICE;
hdr->numanswers = htons(type);
} else {
pHostname = name;
hdr->numanswers = htons(type);
}
query = (char*) hdr + SIZEOF_DNS_HDR;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
/* fill dns query */
if (type == MDNS_REG_ANSWER) {
ans.type = htons(DNS_RRTYPE_A);
ans.class = htons(DNS_RRCLASS_IN);
ans.ttl = htonl(MDNS_SERVICE_TIME);
ans.len = htons(DNS_IP_ADDR_LEN);
length = DNS_IP_ADDR_LEN;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
/* set the local IP address */
auth.src = host_addr.addr;
MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
}
if (type == MDNS_SD_ANSWER) {
ans.type = htons(DNS_RRTYPE_PTR);
ans.class = htons(DNS_RRCLASS_IN);
ans.ttl = htonl(300);
ans.len = htons(os_strlen(PUCK_SERVICE) + 1 +1 );
length = 0;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
pHostname = PUCK_SERVICE;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
}
if (type == MDNS_SERVICE_REG_ANSWER) {
ans.type = htons(DNS_RRTYPE_PTR);
ans.class = htons(DNS_RRCLASS_IN);
ans.ttl = htonl(MDNS_SERVICE_TIME);
os_strcpy(tmpBuf, name);
os_strcat(tmpBuf, ".");
os_strcat(tmpBuf, PUCK_SERVICE);
length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
ans.len = htons(length);
length = 0;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
pHostname = tmpBuf;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
/* Service query*/
pHostname = name;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
/* Add to the service name the service local
* pointing to the beginning of the mDNS message*/
*query++ = DNS_OFFSET_FLAG;
*query++ = DNS_DEFAULT_OFFSET;
/* fill the query */
ans.type = htons(DNS_RRTYPE_SRV);
ans.class = htons(DNS_RRCLASS_FLUSH_IN);
ans.ttl = htonl(MDNS_SERVICE_TIME);
os_strcpy(tmpBuf, host_name);
os_strcat(tmpBuf, ".");
os_strcat(tmpBuf, MDNS_LOCAL);
length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
ans.len = htons(SIZEOF_MDNS_SERVICE + length);
length = 0;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
/* fill the service properties */
serv.prior = htons(0);
serv.weight = htons(0);
serv.port = htons(PUCK_PORT);
MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
/* resize the query */
query = query + SIZEOF_MDNS_SERVICE;
pHostname = tmpBuf;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
/* TXT answer */
pHostname = name;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
/* Add to the service name the service local
* pointing to the beginning of the mDNS message*/
*query++ = DNS_OFFSET_FLAG;
*query++ = DNS_DEFAULT_OFFSET;
/* fill the answer */
ans.type = htons(DNS_RRTYPE_TXT);
ans.class = htons(DNS_RRCLASS_IN);
ans.ttl = htonl(MDNS_SERVICE_TIME);
length = sizeof(SERVICE_DESCRIPTION);
ans.len = htons(length);
length = 0;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
pHostname = SERVICE_DESCRIPTION;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
}
/* resize pbuf to the exact dns query */
pbuf_realloc(p, (query + length) - ((char*) (p->payload)));
/* send dns packet */
/*add by tzx for AP + STA MDNS begin------*/
sta_netif = (struct netif *)eagle_lwip_getif(0x00);
ap_netif = (struct netif *)eagle_lwip_getif(0x01);
if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
sta_netif != NULL && ap_netif != NULL) {
if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
p_sta = pbuf_alloc(PBUF_TRANSPORT,
SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
if (pbuf_copy (p_sta,p) != ERR_OK) {
os_printf("mdns_answer copying to new pbuf failed\n");
return -1;
}
netif_set_default(sta_netif);
err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT);
pbuf_free(p_sta);
netif_set_default(ap_netif);
}
}
/*add by tzx for AP + STA MDNS end------*/
err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
/* free pbuf */
pbuf_free(p);
} else {
err = ERR_MEM;
}
return err;
}
/**
* Send a mDNS service answer packet.
*
* @param name service name to query
* @param id transaction ID in the DNS query packet
* @return ERR_OK if packet is sent; an err_t indicating the problem otherwise
*/
static err_t ICACHE_FLASH_ATTR
mdns_send_service(struct mdns_info *info, u8_t id) {
err_t err;
struct mdns_hdr *hdr;
struct mdns_answer ans;
struct mdns_service serv;
struct mdns_auth auth;
struct pbuf *p ,*p_sta;
char *query, *nptr;
const char *pHostname;
char *device_info;
const char *name = info->host_name;
u8_t n;
u8_t i = 0;
u16_t length = 0;
u8_t addr1 = 12, addr2 = 12;
struct netif * sta_netif = NULL;
struct netif * ap_netif = NULL;
static char tmpBuf[PUCK_DATASHEET_SIZE + PUCK_SERVICE_LENGTH];
/* if here, we have either a new query or a retry on a previous query to process */
p = pbuf_alloc(PBUF_TRANSPORT,
SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
if (p != NULL) {
LWIP_ASSERT("pbuf must be in one piece", p->next == NULL);
/* fill dns header */
hdr = (struct mdns_hdr*) p->payload;
os_memset(hdr, 0, SIZEOF_DNS_HDR);
hdr->id = htons(id);
hdr->flags1 = DNS_FLAG1_RESPONSE;
hdr->numanswers = htons(4);
query = (char*) hdr + SIZEOF_DNS_HDR;
os_strcpy(tmpBuf, PUCK_SERVICE);
pHostname = tmpBuf;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
++addr1;
++addr2;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++addr1;
++addr2;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
length = sizeof(MDNS_LOCAL);
addr1 -= length;
length = os_strlen(PUCK_SERVICE) + 1;
addr2 -= length;
ans.type = htons(DNS_RRTYPE_PTR);
ans.class = htons(DNS_RRCLASS_IN);
ans.ttl = htonl(300);
os_strcpy(tmpBuf, name);
length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD + 1;
ans.len = htons(length);
length = 0;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
pHostname = tmpBuf;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = DNS_OFFSET_FLAG;
*query++ = DNS_DEFAULT_OFFSET;
pHostname = name;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
//*query++ = '\0';
*query++ = DNS_OFFSET_FLAG;
*query++ = DNS_DEFAULT_OFFSET;
/* fill the answer */
ans.type = htons(DNS_RRTYPE_TXT);
ans.class = htons(DNS_RRCLASS_FLUSH_IN);
ans.ttl = htonl(300);
// length = os_strlen(TXT_DATA) + MDNS_LENGTH_ADD + 1;
device_info = (char *)os_zalloc(50);
ets_sprintf(device_info,"vendor = %s","Espressif");
for(i = 0; i < 10 &&(info->txt_data[i] != NULL);i++) {
length += os_strlen(info->txt_data[i]);
length++;
}
length += os_strlen(device_info)+ 1 ;
ans.len = htons(length);
length = 0;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
query = query + SIZEOF_DNS_ANSWER;
pHostname = device_info;
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
i = 0;
while(info->txt_data[i] != NULL && i < 10) {
pHostname = info->txt_data[i];
--pHostname;
/* convert hostname into suitable query format. */
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
i++;
}
// *query++ = '\0';
os_free(device_info);
os_strcpy(tmpBuf, name);
pHostname = tmpBuf;
--pHostname;
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = DNS_OFFSET_FLAG;
*query++ = DNS_DEFAULT_OFFSET;
ans.type = htons(DNS_RRTYPE_SRV);
ans.class = htons(DNS_RRCLASS_FLUSH_IN);
ans.ttl = htonl(300);
os_strcpy(tmpBuf,service_name);
os_strcat(tmpBuf, ".");
os_strcat(tmpBuf, MDNS_LOCAL);
length = os_strlen(tmpBuf) + MDNS_LENGTH_ADD;
ans.len = htons(SIZEOF_MDNS_SERVICE + length);
length = 0;
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
serv.prior = htons(0);
serv.weight = htons(0);
serv.port = htons(PUCK_PORT);
MEMCPY( query, &serv, SIZEOF_MDNS_SERVICE);
/* resize the query */
query = query + SIZEOF_MDNS_SERVICE;
pHostname = tmpBuf;
--pHostname;
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
/* set the name of the authority field.
* The same name as the Query using the offset address*/
os_strcpy(tmpBuf,service_name);
os_strcat(tmpBuf, ".");
os_strcat(tmpBuf, MDNS_LOCAL);
pHostname = tmpBuf;
--pHostname;
do {
++pHostname;
nptr = query;
++query;
for (n = 0; *pHostname != '.' && *pHostname != 0; ++pHostname) {
*query = *pHostname;
++query;
++n;
}
*nptr = n;
} while (*pHostname != 0);
*query++ = '\0';
/* set the name of the authority field.
* The same name as the Query using the offset address*/
//*query++ = DNS_OFFSET_FLAG;
//*query++ = DNS_DEFAULT_OFFSET;
ans.type = htons(DNS_RRTYPE_A);
ans.class = htons(DNS_RRCLASS_FLUSH_IN);
ans.ttl = htonl(300);
ans.len = htons(DNS_IP_ADDR_LEN);
MEMCPY( query, &ans, SIZEOF_DNS_ANSWER);
/* resize the query */
query = query + SIZEOF_DNS_ANSWER;
/* fill the payload of the mDNS message */
/* set the local IP address */
auth.src = host_addr.addr; //ipAddr;
MEMCPY( query, &auth, SIZEOF_MDNS_AUTH);
/* resize the query */
query = query + SIZEOF_MDNS_AUTH;
/* set the name of the authority field.
* The same name as the Query using the offset address*/
/* resize pbuf to the exact dns query */
pbuf_realloc(p, (query) - ((char*) (p->payload)));
/* send dns packet */
sta_netif = (struct netif *)eagle_lwip_getif(0x00);
ap_netif = (struct netif *)eagle_lwip_getif(0x01);
if(wifi_get_opmode() == 0x03 && wifi_get_broadcast_if() == 0x03 &&\
sta_netif != NULL && ap_netif != NULL) {
if(netif_is_up(sta_netif) && netif_is_up(ap_netif)) {
p_sta = pbuf_alloc(PBUF_TRANSPORT,
SIZEOF_DNS_HDR + MDNS_MAX_NAME_LENGTH * 2 + SIZEOF_DNS_QUERY, PBUF_RAM);
if (pbuf_copy (p_sta,p) != ERR_OK) {
os_printf("mdns_send_service copying to new pbuf failed\n");
return -1;
}
netif_set_default(sta_netif);
err = udp_sendto(mdns_pcb, p_sta, &multicast_addr, DNS_MDNS_PORT);
pbuf_free(p_sta);
netif_set_default(ap_netif);
}
}
err = udp_sendto(mdns_pcb, p, &multicast_addr, DNS_MDNS_PORT);
/* free pbuf */
pbuf_free(p);
} else {
os_printf("ERR_MEM \n");
err = ERR_MEM;
}
return err;
}
/**
* Receive input function for DNS response packets arriving for the dns UDP pcb.
*
* @params see udp.h
*/
static void ICACHE_FLASH_ATTR
mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr,
u16_t port) {
u8_t i;
struct mdns_hdr *hdr;
u8_t nquestions;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(addr);
LWIP_UNUSED_ARG(port);
struct mdns_info *info = (struct mdns_info *)arg;
/* is the dns message too big ? */
if (p->tot_len > DNS_MSG_SIZE) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
/* free pbuf and return */
goto memerr1;
}
/* is the dns message big enough ? */
if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
/* free pbuf and return */
goto memerr1;
}
/* copy dns payload inside static buffer for processing */
if (pbuf_copy_partial(p, mdns_payload, p->tot_len, 0) == p->tot_len) {
/* The ID in the DNS header should be our entry into the name table. */
hdr = (struct mdns_hdr*) mdns_payload;
i = htons(hdr->id);
if (i < DNS_TABLE_SIZE) {
nquestions = htons(hdr->numquestions);
//nanswers = htons(hdr->numanswers);
/* if we have a question send an answer if necessary */
if (nquestions > 0) {
/* MDNS_DS_DOES_NAME_CHECK */
/* Check if the name in the "question" part match with the name of the MDNS DS service. */
if (mdns_compare_name((unsigned char *) DNS_SD_SERVICE,
(unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
/* respond with the puck service*/
mdns_answer(MDNS_SD_ANSWER, PUCK_SERVICE, 0);
} else if (mdns_compare_name((unsigned char *) PUCK_SERVICE,
(unsigned char *) mdns_payload + SIZEOF_DNS_HDR) == 0) {
/* respond with the puck service*/
mdns_send_service(info, 0);
} else
goto memerr2;
}
}
}
goto memerr2;
memerr2:
mem_free(mdns_payload);
memerr1:
/* free pbuf */
pbuf_free(p);
return;
}
/**
* close the UDP pcb .
*/
void ICACHE_FLASH_ATTR
mdns_close(void)
{
if (mdns_pcb != NULL)
udp_remove(mdns_pcb);
}
void ICACHE_FLASH_ATTR
mdns_set_name(const char *name)
{
//strcpy(host_name, name);
os_strcpy(service_name, name);
}
void ICACHE_FLASH_ATTR
mdns_enable(void)
{
if(mdns_flag == 0) {
udp_recv(mdns_pcb, mdns_recv, NULL);
}
}
void ICACHE_FLASH_ATTR
mdns_disable(void)
{
if (mdns_flag == 1) {
udp_recv(mdns_pcb, NULL, NULL);
}
}
/**
* close the UDP pcb .
*/
char* ICACHE_FLASH_ATTR
mdns_get_hostname(void) {
//strcpy(host_name, name);
char *name = host_name;
if (host_name[0] != 0 ) {
return name;
} else {
return ("Espressif");
}
}
void ICACHE_FLASH_ATTR
mdns_set_hostname(char *name) {
if (name == NULL) {
os_strncpy(host_name, "Espressif", os_strlen("Espressif")+3);
return;
}
if (os_strlen(name) + 3 <= MDNS_NAME_LENGTH ){
os_strncpy(host_name, name, os_strlen(name) );
// os_memset(host_name + os_strlen(host_name) ,0x00,3);
} else {
os_strncpy(host_name, name, MDNS_NAME_LENGTH);
}
}
void ICACHE_FLASH_ATTR
mdns_set_servername(const char *name) {
if (name == NULL) {
PUCK_SERVICE = "_Espressif._tcp._local";
}else {
os_sprintf(server_name ,"_%s._tcp.local",name);
PUCK_SERVICE = server_name;
}
}
char* ICACHE_FLASH_ATTR
mdns_get_servername(void) {
char *name = PUCK_SERVICE;
if (name == NULL) {
PUCK_SERVICE = "_Espressif._tcp._local";
}
return name;
}
void ICACHE_FLASH_ATTR
mdns_server_unregister(void) {
if(register_flag == 1){
if (igmp_leavegroup(&host_addr, &multicast_addr) != ERR_OK) {
os_printf("udp_leave_multigrup failed!\n");
return;
};
register_flag = 0;
}
}
void ICACHE_FLASH_ATTR
mdns_server_register(void) {
if (register_flag == 1) {
os_printf("mdns server is already registered !\n");
return;
} else if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
os_printf("udp_join_multigrup failed!\n");
return;
};
register_flag = 1;
}
void ICACHE_FLASH_ATTR
mdns_reg(struct mdns_info *info) {
static uint8 i = 0;
if (i <= 3) {
mdns_send_service(info,0);
i++;
} else {
os_timer_disarm(&mdns_timer);
}
}
/**
* Initialize the resolver: set up the UDP pcb and configure the default server
* (NEW IP).
*/
void ICACHE_FLASH_ATTR
mdns_init(struct mdns_info *info) {
/* initialize default DNS server address */
multicast_addr.addr = DNS_MULTICAST_ADDRESS;
if (info->ipAddr == 0) {
os_printf("mdns ip error!\n ");
return;
}
host_addr.addr = info->ipAddr ;
LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
//get the datasheet from PUCK
mdns_set_hostname(info->host_name);
mdns_set_servername(info->server_name);
mdns_set_name(info->host_name);
// get the host name as instrumentName_serialNumber for MDNS
// set the name of the service, the same as host name
os_printf("host_name = %s\n", host_name);
os_printf("server_name = %s\n", PUCK_SERVICE);
if (info->server_port == 0)
{
PUCK_PORT = 80;
} else {
PUCK_PORT = info->server_port;
}
/* initialize mDNS */
mdns_pcb = udp_new();
if (mdns_pcb != NULL) {
/* join to the multicast address 224.0.0.251 */
if (igmp_joingroup(&host_addr, &multicast_addr) != ERR_OK) {
os_printf("udp_join_multigrup failed!\n");
return;
};
register_flag = 1;
/* join to any IP address at the port 5353 */
if (udp_bind(mdns_pcb, IP_ADDR_ANY, DNS_MDNS_PORT) != ERR_OK) {
os_printf("udp_bind failed!\n");
return;
};
/*loopback function for the multicast(224.0.0.251) messages received at port 5353*/
// mdns_enable();
udp_recv(mdns_pcb, mdns_recv, info);
mdns_flag = 1;
/*
* Register the name of the instrument
*/
os_timer_disarm(&mdns_timer);
os_timer_setfn(&mdns_timer, (os_timer_func_t *)mdns_reg,info);
os_timer_arm(&mdns_timer, 1000, 1);
}
}
#endif /* LWIP_MDNS */
...@@ -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 */
......
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