MeterLogger
espconn_tcp.c
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2013-2014 Espressif Systems (Wuxi)
3  *
4  * FileName: espconn_tcp.c
5  *
6  * Description: tcp proto interface
7  *
8  * Modification history:
9  * 2014/3/31, v1.0 create this file.
10 *******************************************************************************/
11 
12 #include "lwip/netif.h"
13 #include "lwip/inet.h"
14 #include "netif/etharp.h"
15 #include "lwip/tcp.h"
16 #include "lwip/ip.h"
17 #include "lwip/init.h"
18 #include "lwip/tcp_impl.h"
19 #include "lwip/memp.h"
20 
21 #include "ets_sys.h"
22 #include "os_type.h"
23 //#include "os.h"
24 #include "lwip/mem.h"
25 #include "lwip/app/espconn_tcp.h"
26 
27 #ifdef MEMLEAK_DEBUG
28 static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
29 #endif
30 
33 extern struct espconn_packet pktinfo[2];
34 extern struct tcp_pcb ** const tcp_pcb_lists[];
35 
37 
38 static err_t
39 espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
40 static void
41 espconn_client_close(void *arg, struct tcp_pcb *pcb,u8 type);
42 
43 static err_t
44 espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
45 static void
46 espconn_server_close(void *arg, struct tcp_pcb *pcb,u8 type);
47 
48 ///////////////////////////////common function/////////////////////////////////
49 /******************************************************************************
50  * FunctionName : espconn_kill_oldest
51  * Description : kill the oldest TCP block
52  * Parameters : none
53  * Returns : none
54 *******************************************************************************/
55 static void ICACHE_FLASH_ATTR
57 {
58  struct tcp_pcb *pcb, *inactive;
59  u32_t inactivity;
60 
61  inactivity = 0;
62  inactive = NULL;
63  /* Go through the list of TIME_WAIT pcbs and get the oldest pcb. */
64  for (pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
65  if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
66  inactivity = tcp_ticks - pcb->tmr;
67  inactive = pcb;
68  }
69  }
70  if (inactive != NULL) {
71  tcp_abort(inactive);
72  }
73 
74  /* Go through the list of FIN_WAIT_2 pcbs and get the oldest pcb. */
75  inactivity = 0;
76  inactive = NULL;
77  for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
78  if (pcb->state == FIN_WAIT_1 || pcb->state == FIN_WAIT_2){
79  if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
80  inactivity = tcp_ticks - pcb->tmr;
81  inactive = pcb;
82  }
83  }
84  }
85  /*Purges the PCB, removes it from a PCB list and frees the memory*/
86  if (inactive != NULL) {
87  tcp_pcb_remove(&tcp_active_pcbs, inactive);
88  memp_free(MEMP_TCP_PCB, inactive);
89  }
90 
91  /* Go through the list of LAST_ACK pcbs and get the oldest pcb. */
92  inactivity = 0;
93  inactive = NULL;
94  for (pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
95  if (pcb->state == LAST_ACK) {
96  if ((u32_t) (tcp_ticks - pcb->tmr) >= inactivity) {
97  inactivity = tcp_ticks - pcb->tmr;
98  inactive = pcb;
99  }
100  }
101  }
102  /*Purges the PCB, removes it from a PCB list and frees the memory*/
103  if (inactive != NULL) {
104  tcp_pcb_remove(&tcp_active_pcbs, inactive);
105  memp_free(MEMP_TCP_PCB, inactive);
106  }
107 }
108 
109 /******************************************************************************
110  * FunctionName : espconn_kill_oldest_pcb
111  * Description : find the oldest TCP block by state
112  * Parameters : none
113  * Returns : none
114 *******************************************************************************/
116 {
117  struct tcp_pcb *cpcb = NULL;
118  uint8 i = 0;
119  uint8 num_tcp_fin = 0;
120  for(i = 2; i < 4; i ++){
121  for (cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) {
122  if (cpcb->state == TIME_WAIT){
123  num_tcp_fin ++;
124  if (num_tcp_fin == MEMP_NUM_TCP_PCB)
125  break;
126  }
127 
128  if (cpcb->state == FIN_WAIT_1 || cpcb->state == FIN_WAIT_2 || cpcb->state == LAST_ACK){
129  num_tcp_fin++;
130  if (num_tcp_fin == MEMP_NUM_TCP_PCB)
131  break;
132  }
133  }
134 
135  if (num_tcp_fin == MEMP_NUM_TCP_PCB){
136  num_tcp_fin = 0;
138  } else if (cpcb == NULL){
139  num_tcp_fin = 0;
140  }
141  }
142 }
143 
144 /******************************************************************************
145  * FunctionName : espconn_kill_pcb
146  * Description : kill all the TCP block by port
147  * Parameters : none
148  * Returns : none
149 *******************************************************************************/
151 {
152  struct tcp_pcb *cpcb = NULL;
153  uint8 i = 0;
154  struct tcp_pcb *inactive = NULL;
155  struct tcp_pcb *prev = NULL;
156  u8_t pcb_remove;
157  /* Check if the address already is in use (on all lists) */
158  for (i = 1; i < 4; i++) {
159  cpcb = *tcp_pcb_lists[i];
160  while(cpcb != NULL){
161  pcb_remove = 0;
162  if (cpcb->local_port == port) {
163  ++pcb_remove;
164  }
165  /* If the PCB should be removed, do it. */
166  if (pcb_remove) {
167  /* Remove PCB from tcp_pcb_lists list. */
168  inactive = cpcb;
169  cpcb = inactive->next;
170  tcp_pcb_remove(tcp_pcb_lists[i], inactive);
171  memp_free(MEMP_TCP_PCB, inactive);
172  } else {
173  cpcb = cpcb->next;
174  }
175  }
176  }
177 }
178 
179 /******************************************************************************
180  * FunctionName : espconn_find_current_pcb
181  * Description : find the TCP block which option
182  * Parameters : pcurrent_msg -- the node in the list which active
183  * Returns : TCP block point
184 *******************************************************************************/
186 {
187  uint16 local_port = pcurrent_msg->pcommon.local_port;
188  uint32 local_ip = pcurrent_msg->pcommon.local_ip;
189  uint16 remote_port = pcurrent_msg->pcommon.remote_port;
190  uint32 remote_ip = *((uint32*)&pcurrent_msg->pcommon.remote_ip);
191  struct tcp_pcb *find_pcb = NULL;
192  if (pcurrent_msg ->preverse == NULL){/*Find the server's TCP block*/
193  if (local_ip == 0|| local_port == 0) return pcurrent_msg->pcommon.pcb;
194 
195  for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
196  if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) &&
197  (find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip))
198  return find_pcb;
199  }
200 
201  for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
202  if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip) &&
203  (find_pcb->local_port == local_port) && (find_pcb->local_ip.addr == local_ip))
204  return find_pcb;
205  }
206  } else {/*Find the client's TCP block*/
207  if (remote_ip == 0|| remote_port == 0) return pcurrent_msg->pcommon.pcb;
208 
209  for (find_pcb = tcp_active_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
210  if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip))
211  return find_pcb;
212  }
213 
214  for (find_pcb = tcp_tw_pcbs; find_pcb != NULL; find_pcb = find_pcb->next){
215  if ((find_pcb->remote_port == remote_port) && (find_pcb->remote_ip.addr == remote_ip))
216  return find_pcb;
217  }
218  }
219  return NULL;
220 }
221 
222 /******************************************************************************
223  * FunctionName : espconn_tcp_reconnect
224  * Description : reconnect with host
225  * Parameters : arg -- Additional argument to pass to the callback function
226  * Returns : none
227 *******************************************************************************/
228 static void ICACHE_FLASH_ATTR
230 {
231  espconn_msg *precon_cb = arg;
232  sint8 re_err = 0;
233  espconn_buf *perr_buf = NULL;
234  espconn_buf *perr_back = NULL;
236  if (precon_cb != NULL) {
237  struct espconn *espconn = precon_cb->preverse;
238  re_err = precon_cb->pcommon.err;
239  if (precon_cb->pespconn != NULL){
240  if (espconn != NULL){/*Process the server's message block*/
241  if (precon_cb->pespconn->proto.tcp != NULL){
242  espconn_copy_partial(espconn, precon_cb->pespconn);
243  espconn_printf("server: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->remote_ip[0],
244  espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2],
245  espconn->proto.tcp->remote_ip[3],espconn->proto.tcp->remote_port);
246  os_free(precon_cb->pespconn->proto.tcp);
247  precon_cb->pespconn->proto.tcp = NULL;
248  }
249  os_free(precon_cb->pespconn);
250  precon_cb->pespconn = NULL;
251  } else {/*Process the client's message block*/
252  espconn = precon_cb->pespconn;
253  espconn_printf("client: %d.%d.%d.%d : %d reconnection\n", espconn->proto.tcp->local_ip[0],
254  espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
255  espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
256  }
257  }
258 
259  /*to prevent memory leaks, ensure that each allocated is deleted*/
260  perr_buf = precon_cb->pcommon.pbuf;
261  while (perr_buf != NULL){
262  perr_back = perr_buf;
263  perr_buf = perr_back->pnext;
264  espconn_pbuf_delete(&precon_cb->pcommon.pbuf,perr_back);
265  os_free(perr_back);
266  perr_back = NULL;
267  }
268  os_bzero(&pktinfo[1], sizeof(struct espconn_packet));
269  os_memcpy(&pktinfo[1], (void*)&precon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
270  os_free(precon_cb);
271  precon_cb = NULL;
272  if (espconn && espconn->proto.tcp && espconn->proto.tcp->reconnect_callback != NULL) {
273  espconn->proto.tcp->reconnect_callback(espconn, re_err);
274  }
275  } else {
276  espconn_printf("espconn_tcp_reconnect err\n");
277  }
278 }
279 
280 /******************************************************************************
281  * FunctionName : espconn_tcp_disconnect
282  * Description : disconnect with host
283  * Parameters : arg -- Additional argument to pass to the callback function
284  * Returns : none
285 *******************************************************************************/
286 static void ICACHE_FLASH_ATTR
288 {
289  espconn_msg *pdiscon_cb = arg;
290  sint8 dis_err = 0;
291  espconn_buf *pdis_buf = NULL;
292  espconn_buf *pdis_back = NULL;
294  if (pdiscon_cb != NULL) {
295  struct espconn *espconn = pdiscon_cb->preverse;
296 
297  dis_err = pdiscon_cb->pcommon.err;
298  if (pdiscon_cb->pespconn != NULL){
299  struct tcp_pcb *pcb = NULL;
300  if (espconn != NULL){/*Process the server's message block*/
301  if (pdiscon_cb->pespconn->proto.tcp != NULL && espconn->proto.tcp){
302  espconn_copy_partial(espconn, pdiscon_cb->pespconn);
303  espconn_printf("server: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->remote_ip[0],
304  espconn->proto.tcp->remote_ip[1],espconn->proto.tcp->remote_ip[2],
305  espconn->proto.tcp->remote_ip[3],espconn->proto.tcp->remote_port);
306  os_free(pdiscon_cb->pespconn->proto.tcp);
307  pdiscon_cb->pespconn->proto.tcp = NULL;
308  }
309  os_free(pdiscon_cb->pespconn);
310  pdiscon_cb->pespconn = NULL;
311  } else {/*Process the client's message block*/
312  espconn = pdiscon_cb->pespconn;
313  espconn_printf("client: %d.%d.%d.%d : %d disconnect\n", espconn->proto.tcp->local_ip[0],
314  espconn->proto.tcp->local_ip[1],espconn->proto.tcp->local_ip[2],
315  espconn->proto.tcp->local_ip[3],espconn->proto.tcp->local_port);
316  }
317  /*process the current TCP block*/
318  pcb = espconn_find_current_pcb(pdiscon_cb);
319  if (pcb != NULL){
320  if (espconn_reuse_disabled(pdiscon_cb)) {
321  struct tcp_pcb *cpcb = NULL;
322  struct tcp_pcb *prev = NULL;
323  u8_t pcb_remove;
324  espconn_printf("espconn_tcp_disconnect_successful %d, %d\n", pcb->state, pcb->local_port);
325  cpcb = tcp_tw_pcbs;
326  while (cpcb != NULL) {
327  pcb_remove = 0;
328  if (cpcb->local_port == pcb->local_port) {
329  ++pcb_remove;
330  }
331  /* If the PCB should be removed, do it. */
332  if (pcb_remove) {
333  struct tcp_pcb *backup_pcb = NULL;
334  tcp_pcb_purge(cpcb);
335  /* Remove PCB from tcp_tw_pcbs list. */
336  if (prev != NULL) {
337  LWIP_ASSERT("espconn_tcp_delete: middle cpcb != tcp_tw_pcbs",cpcb != tcp_tw_pcbs);
338  prev->next = cpcb->next;
339  } else {
340  /* This PCB was the first. */
341  LWIP_ASSERT("espconn_tcp_delete: first cpcb == tcp_tw_pcbs",tcp_tw_pcbs == cpcb);
342  tcp_tw_pcbs = cpcb->next;
343  }
344  backup_pcb = cpcb;
345  cpcb = cpcb->next;
346  memp_free(MEMP_TCP_PCB, backup_pcb);
347  } else {
348  prev = cpcb;
349  cpcb = cpcb->next;
350  }
351  }
352 
353  } else {
354  tcp_arg(pcb, NULL);
355  tcp_err(pcb, NULL);
356  }
357  }
358  }
359 
360  /*to prevent memory leaks, ensure that each allocated is deleted*/
361  pdis_buf = pdiscon_cb->pcommon.pbuf;
362  while (pdis_buf != NULL) {
363  pdis_back = pdis_buf;
364  pdis_buf = pdis_back->pnext;
365  espconn_pbuf_delete(&pdiscon_cb->pcommon.pbuf, pdis_back);
366  os_free(pdis_back);
367  pdis_back = NULL;
368  }
369  os_bzero(&pktinfo[0], sizeof(struct espconn_packet));
370  os_memcpy(&pktinfo[0], (void*)&pdiscon_cb->pcommon.packet_info, sizeof(struct espconn_packet));
371  os_free(pdiscon_cb);
372  pdiscon_cb = NULL;
373  if (espconn->proto.tcp && espconn->proto.tcp->disconnect_callback != NULL) {
374  espconn->proto.tcp->disconnect_callback(espconn);
375  }
376  } else {
377  espconn_printf("espconn_tcp_disconnect err\n");
378  }
379 }
380 
381 /******************************************************************************
382  * FunctionName : espconn_Task
383  * Description : espconn processing task
384  * Parameters : events -- contain the espconn processing data
385  * Returns : none
386 *******************************************************************************/
387 static void ICACHE_FLASH_ATTR
389 {
390  espconn_msg *task_msg = NULL;
391  struct espconn *pespconn = NULL;
392 
393  task_msg = (espconn_msg *) events->par;
394  switch (events->sig) {
395  case SIG_ESPCONN_WRITE: {
396  pespconn = task_msg->pespconn;
397  if (pespconn == NULL) {
398  return;
399  }
400 
401  if (pespconn->proto.tcp->write_finish_fn != NULL) {
402  pespconn->proto.tcp->write_finish_fn(pespconn);
403  }
404  }
405  break;
406  case SIG_ESPCONN_ERRER:
407  /*remove the node from the client's active connection list*/
408  espconn_list_delete(&plink_active, task_msg);
409  espconn_tcp_reconnect(task_msg);
410  break;
411  case SIG_ESPCONN_CLOSE:
412  /*remove the node from the client's active connection list*/
413  espconn_list_delete(&plink_active, task_msg);
415  break;
416  default:
417  break;
418  }
419 }
420 
421 /******************************************************************************
422  * FunctionName : espconn_tcp_sent
423  * Description : sent data for client or server
424  * Parameters : void *arg -- client or server to send
425  * uint8* psent -- Data to send
426  * uint16 length -- Length of data to send
427  * Returns : return espconn error code.
428  * - ESPCONN_OK. Successful. No error occured.
429  * - ESPCONN_MEM. Out of memory.
430  * - ESPCONN_RTE. Could not find route to destination address.
431  * - More errors could be returned by lower protocol layers.
432 *******************************************************************************/
434 espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
435 {
436  espconn_msg *ptcp_sent = arg;
437  struct tcp_pcb *pcb = NULL;
438  err_t err = 0;
439  u16_t len = 0;
440  u8_t data_to_send = false;
441 
442  espconn_printf("espconn_tcp_sent ptcp_sent %p psent %p length %d\n", ptcp_sent, psent, length);
443 
444  /*Check the parameters*/
445  if (ptcp_sent == NULL || psent == NULL || length == 0) {
446  return ESPCONN_ARG;
447  }
448 
449  /*Set the packet length depend on the sender buffer space*/
450  pcb = ptcp_sent->pcommon.pcb;
451  if (tcp_sndbuf(pcb) < length) {
452  len = tcp_sndbuf(pcb);
453  } else {
454  len = length;
455  LWIP_ASSERT("length did not fit into uint16!", (len == length));
456  }
457 
458  if (len > (2*pcb->mss)) {
459  len = 2*pcb->mss;
460  }
461 
462  /*Write data for sending, but does not send it immediately*/
463  do {
464  espconn_printf("espconn_tcp_sent writing %d bytes %p\n", len, pcb);
465  if (espconn_copy_disabled(ptcp_sent))
466  err = tcp_write(pcb, psent, len, 1);
467  else
468  err = tcp_write(pcb, psent, len, 0);
469 
470  if (err == ERR_MEM) {
471  len /= 2;
472  }
473  } while (err == ERR_MEM && len > 1);
474 
475  /*Find out what we can send and send it, offset the buffer point for next send*/
476  if (err == ERR_OK) {
477  ptcp_sent->pcommon.ptail->punsent = psent + len;
478  ptcp_sent->pcommon.ptail->unsent = length - len;
479  err = tcp_output(pcb);
480  /*If enable the copy option, change the flag for next write*/
481  if (espconn_copy_disabled(ptcp_sent)){
482  if (ptcp_sent->pcommon.ptail->unsent == 0) {
483  ptcp_sent->pcommon.write_flag = true;
484  ets_post(espconn_TaskPrio, SIG_ESPCONN_WRITE, (uint32_t)ptcp_sent);
485  }
486  }
487  espconn_printf("espconn_tcp_sent %d\n", err);
488  }
489  return err;
490 }
491 
492 /******************************************************************************
493  * FunctionName : espconn_close
494  * Description : The connection has been successfully closed.
495  * Parameters : arg -- Additional argument to pass to the callback function
496  * Returns : none
497 *******************************************************************************/
499 {
500  if (pdiscon != NULL){
501  /*disconnect with the host by send the FIN frame*/
502  if (pdiscon->preverse != NULL)
503  espconn_server_close(pdiscon, pdiscon->pcommon.pcb,type);
504  else
505  espconn_client_close(pdiscon, pdiscon->pcommon.pcb,type);
506  } else{
507  espconn_printf("espconn_tcp_disconnect err.\n");
508  }
509 }
510 
511 ///////////////////////////////client function/////////////////////////////////
512 /******************************************************************************
513  * FunctionName : espconn_client_close
514  * Description : The connection shall be actively closed.
515  * Parameters : pcb -- Additional argument to pass to the callback function
516  * pcb -- the pcb to close
517  * Returns : none
518 *******************************************************************************/
519 static void ICACHE_FLASH_ATTR
520 espconn_client_close(void *arg, struct tcp_pcb *pcb, u8 type)
521 {
522  err_t err;
523  espconn_msg *pclose = arg;
524 
525  pclose->pcommon.pcb = pcb;
526  /*avoid recalling the disconnect function*/
527  tcp_recv(pcb, NULL);
528 
529  if(type == 0)
530  err = tcp_close(pcb);
531  else
532  {tcp_abort(pcb); err = ERR_OK;}
533 
534  if (err != ERR_OK) {
535  /* closing failed, try again later */
536  tcp_recv(pcb, espconn_client_recv);
537  } else {
538  /* closing succeeded */
539  tcp_sent(pcb, NULL);
540  tcp_err(pcb, NULL);
541  /*switch the state of espconn for application process*/
542  pclose->pespconn->state = ESPCONN_CLOSE;
543  ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)pclose);
544  }
545 }
546 
547 //***********Code for WIFI_BLOCK from upper**************
549 espconn_recv_hold(struct espconn *pespconn)
550 {
551  //1st, according to espconn code, have to find out the escpconn_msg by pespconn;
552  espconn_msg *pnode = NULL;
553  bool value = false;
554  if (pespconn == NULL) {
555  return ESPCONN_ARG;
556  }
557  value = espconn_find_connection(pespconn, &pnode);
558  if(value != true)
559  {
560  os_printf("RecvHold, By pespconn,find conn_msg fail\n");
561  return ESPCONN_ARG;
562  }
563 
564  //2nd, the actual operation
565  if(pnode->recv_hold_flag == 0)
566  {
567  pnode->recv_hold_flag = 1;
568  pnode->recv_holded_buf_Len = 0;
569  }
570  return ESPCONN_OK;
571 }
572 
574 espconn_recv_unhold(struct espconn *pespconn)
575 {
576  //1st, according to espconn code, have to find out the escpconn_msg by pespconn;
577  espconn_msg *pnode = NULL;
578  bool value = false;
579  if (pespconn == NULL) {
580  return ESPCONN_ARG;
581  }
582  value = espconn_find_connection(pespconn, &pnode);
583  if(value != true)
584  {
585  os_printf("RecvHold, By pespconn,find conn_msg fail\n");
586  return ESPCONN_ARG;
587  }
588 
589  //2nd, the actual operation
590  if(pnode->recv_hold_flag == 1)
591  {
592  if(pespconn->type == ESPCONN_TCP) {
593  tcp_recved(pnode->pcommon.pcb, pnode->recv_holded_buf_Len);
594  }
595  pnode->recv_holded_buf_Len = 0;
596  pnode->recv_hold_flag = 0;
597  }
598  return ESPCONN_OK;
599 }
600 
601 //***********Code for WIFI_BLOCK from upper**************
602 
603 /******************************************************************************
604  * FunctionName : espconn_client_recv
605  * Description : Data has been received on this pcb.
606  * Parameters : arg -- Additional argument to pass to the callback function
607  * pcb -- The connection pcb which received data
608  * p -- The received data (or NULL when the connection has been closed!)
609  * err -- An error code if there has been an error receiving
610  * Returns : ERR_ABRT: if you have called tcp_abort from within the function!
611 *******************************************************************************/
613 espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
614 {
615  espconn_msg *precv_cb = arg;
616 
617  tcp_arg(pcb, arg);
618 
619  if (p != NULL) {
620  /*To update and advertise a larger window*/
621  if(precv_cb->recv_hold_flag == 0)
622  tcp_recved(pcb, p->tot_len);
623  else
624  precv_cb->recv_holded_buf_Len += p->tot_len;
625  }
626 
627  if (err == ERR_OK && p != NULL) {
628  char *pdata = NULL;
629  u16_t length = 0;
630  /*Copy the contents of a packet buffer to an application buffer.
631  *to prevent memory leaks, ensure that each allocated is deleted*/
632  pdata = (char *)os_zalloc(p ->tot_len + 1);
633  length = pbuf_copy_partial(p, pdata, p ->tot_len, 0);
634  pbuf_free(p);
635 
636  if (length != 0) {
637  /*switch the state of espconn for application process*/
638  precv_cb->pespconn ->state = ESPCONN_READ;
639  precv_cb->pcommon.pcb = pcb;
640  if (precv_cb->pespconn->recv_callback != NULL) {
641  precv_cb->pespconn->recv_callback(precv_cb->pespconn, pdata, length);
642  }
643  /*switch the state of espconn for next packet copy*/
644  if (pcb->state == ESTABLISHED)
645  precv_cb->pespconn ->state = ESPCONN_CONNECT;
646  }
647 
648  /*to prevent memory leaks, ensure that each allocated is deleted*/
649  os_free(pdata);
650  pdata = NULL;
651  }
652 
653  if (err == ERR_OK && p == NULL) {
654  espconn_client_close(precv_cb, pcb,0);
655  }
656 
657  return ERR_OK;
658 }
659 
660 /******************************************************************************
661  * FunctionName : espconn_tcp_write
662  * Description : write the packet which in the active connection's list.
663  * Parameters : arg -- the node pointer which reverse the packet
664  * Returns : ESPCONN_MEM: memory error
665  * ESPCONN_OK:have enough space for write packet
666 *******************************************************************************/
668 {
669  espconn_msg *pwrite = arg;
670  err_t err = ERR_OK;
671  struct tcp_pcb *pcb = pwrite->pcommon.pcb;
672  /*for one active connection,limit the sender buffer space*/
673  if (tcp_nagle_disabled(pcb) && (pcb->snd_queuelen >= TCP_SND_QUEUELEN))
674  return ESPCONN_MEM;
675 
676  while (tcp_sndbuf(pcb) != 0){
677  if (pwrite->pcommon.ptail != NULL) {
678  /*Find the node whether in the list's tail or not*/
679  if (pwrite->pcommon.ptail->unsent == 0) {
680  pwrite->pcommon.ptail = pwrite->pcommon.ptail->pnext;
681  continue;
682  }
683 
684  /*Send the packet for the active connection*/
685  err = espconn_tcp_sent(pwrite, pwrite->pcommon.ptail->punsent,pwrite->pcommon.ptail->unsent);
686  if (err != ERR_OK)
687  break;
688  } else
689  break;
690  }
691  return err;
692 }
693 
694 /******************************************************************************
695  * FunctionName : espconn_tcp_reconnect
696  * Description : reconnect with host
697  * Parameters : arg -- Additional argument to pass to the callback function
698  * Returns : none
699 *******************************************************************************/
700 static void ICACHE_FLASH_ATTR espconn_tcp_finish(void *arg)
701 {
702  espconn_msg *pfinish = arg;
703  espconn_buf *premove = NULL;
704  uint16 len = 0;
705  espconn_tcp_write(pfinish);
706  while (pfinish->pcommon.pbuf != NULL){
707  premove = pfinish->pcommon.pbuf;
708  pfinish->pcommon.pbuf->tot_len += len;
709  /*application packet has been sent and acknowledged by the remote host,
710  * to prevent memory leaks, ensure that each allocated is deleted*/
711  if (premove->tot_len >= premove->len){
712  espconn_pbuf_delete(&pfinish->pcommon.pbuf,premove);
713  len = premove->tot_len - premove->len;
714  pfinish->pcommon.packet_info.sent_length = premove->len;
715  os_free(premove);
716  premove = NULL;
717  pfinish->pespconn->state = ESPCONN_CONNECT;
718  if (pfinish->pespconn->sent_callback != NULL) {
719  pfinish->pespconn->sent_callback(pfinish->pespconn);
720  }
721  pfinish->pcommon.packet_info.sent_length = len;
722  } else
723  break;
724  }
725 }
726 
727 /******************************************************************************
728  * FunctionName : espconn_client_sent
729  * Description : Data has been sent and acknowledged by the remote host.
730  * This means that more data can be sent.
731  * Parameters : arg -- Additional argument to pass to the callback function
732  * pcb -- The connection pcb for which data has been acknowledged
733  * len -- The amount of bytes acknowledged
734  * Returns : ERR_OK: try to send some data by calling tcp_output
735  * ERR_ABRT: if you have called tcp_abort from within the function!
736 *******************************************************************************/
738 espconn_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
739 {
740  espconn_msg *psent_cb = arg;
741 
742  psent_cb->pcommon.pcb = pcb;
743  psent_cb->pcommon.pbuf->tot_len += len;
744  psent_cb->pcommon.packet_info.sent_length = len;
745 
746  /*Send more data for one active connection*/
747  espconn_tcp_finish(psent_cb);
748 
749  return ERR_OK;
750 }
751 
752 /******************************************************************************
753  * FunctionName : espconn_client_err
754  * Description : The pcb had an error and is already deallocated.
755  * The argument might still be valid (if != NULL).
756  * Parameters : arg -- Additional argument to pass to the callback function
757  * err -- Error code to indicate why the pcb has been closed
758  * Returns : none
759 *******************************************************************************/
760 static void ICACHE_FLASH_ATTR
761 espconn_client_err(void *arg, err_t err)
762 {
763  espconn_msg *perr_cb = arg;
764  struct tcp_pcb *pcb = NULL;
765  LWIP_UNUSED_ARG(err);
766 
767  if (perr_cb != NULL) {
768  pcb = perr_cb->pcommon.pcb;
769  perr_cb->pespconn->state = ESPCONN_CLOSE;
770  espconn_printf("espconn_client_err %d %d %d\n", pcb->state, pcb->nrtx, err);
771 
772 // /*remove the node from the client's active connection list*/
773 // espconn_list_delete(&plink_active, perr_cb);
774 
775  /*Set the error code depend on the error type and control block state*/
776  if (err == ERR_ABRT) {
777  switch (pcb->state) {
778  case SYN_SENT:
779  if (pcb->nrtx == TCP_SYNMAXRTX) {
780  perr_cb->pcommon.err = ESPCONN_CONN;
781  } else {
782  perr_cb->pcommon.err = err;
783  }
784 
785  break;
786 
787  case ESTABLISHED:
788  if (pcb->nrtx == TCP_MAXRTX) {
789  perr_cb->pcommon.err = ESPCONN_TIMEOUT;
790  } else {
791  perr_cb->pcommon.err = err;
792  }
793  break;
794 
795  case FIN_WAIT_1:
796  if (pcb->nrtx == TCP_MAXRTX) {
797  perr_cb->pcommon.err = ESPCONN_CLSD;
798  } else {
799  perr_cb->pcommon.err = err;
800  }
801  break;
802  case FIN_WAIT_2:
803  perr_cb->pcommon.err = ESPCONN_CLSD;
804  break;
805  case CLOSED:
806  perr_cb->pcommon.err = ESPCONN_CONN;
807  break;
808  }
809  } else {
810  perr_cb->pcommon.err = err;
811  }
812  /*post the singer to the task for processing the connection*/
813  ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)perr_cb);
814  }
815 }
816 
817 /******************************************************************************
818  * FunctionName : espconn_client_connect
819  * Description : A new incoming connection has been connected.
820  * Parameters : arg -- Additional argument to pass to the callback function
821  * tpcb -- The connection pcb which is connected
822  * err -- An unused error code, always ERR_OK currently
823  * Returns : connection result
824 *******************************************************************************/
826 espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err)
827 {
828  espconn_msg *pcon = arg;
829 
830  espconn_printf("espconn_client_connect pcon %p tpcb %p\n", pcon, tpcb);
831  if (err == ERR_OK){
832  /*Reserve the remote information for current active connection*/
833  pcon->pespconn->state = ESPCONN_CONNECT;
834  pcon->pcommon.err = err;
835  pcon->pcommon.pcb = tpcb;
836  pcon->pcommon.local_port = tpcb->local_port;
837  pcon->pcommon.local_ip = tpcb->local_ip.addr;
838  pcon->pcommon.remote_port = tpcb->remote_port;
839  pcon->pcommon.remote_ip[0] = ip4_addr1_16(&tpcb->remote_ip);
840  pcon->pcommon.remote_ip[1] = ip4_addr2_16(&tpcb->remote_ip);
841  pcon->pcommon.remote_ip[2] = ip4_addr3_16(&tpcb->remote_ip);
842  pcon->pcommon.remote_ip[3] = ip4_addr4_16(&tpcb->remote_ip);
843  pcon->pcommon.write_flag = true;
844  tcp_arg(tpcb, (void *) pcon);
845 
846  /*Set the specify function that should be called
847  * when TCP data has been successfully delivered,
848  * when active connection receives data*/
849  tcp_sent(tpcb, espconn_client_sent);
850  tcp_recv(tpcb, espconn_client_recv);
851  /*Disable Nagle algorithm default*/
852  tcp_nagle_disable(tpcb);
853  /*Default set the total number of espconn_buf on the unsent lists for one*/
854  espconn_tcp_set_buf_count(pcon->pespconn, 1);
855 
856  if (pcon->pespconn->proto.tcp->connect_callback != NULL) {
857  pcon->pespconn->proto.tcp->connect_callback(pcon->pespconn);
858  }
859 
860  /*Enable keep alive option*/
861  if (espconn_keepalive_disabled(pcon))
863 
864  } else{
865  os_printf("err in host connected (%s)\n",lwip_strerr(err));
866  }
867  return err;
868 }
869 
870 /******************************************************************************
871  * FunctionName : espconn_tcp_client
872  * Description : Initialize the client: set up a connect PCB and bind it to
873  * the defined port
874  * Parameters : espconn -- the espconn used to build client
875  * Returns : none
876 *******************************************************************************/
879 {
880  struct tcp_pcb *pcb = NULL;
881  struct ip_addr ipaddr;
882  espconn_msg *pclient = NULL;
883 
884  /*Creates a new client control message*/
885  pclient = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
886  if (pclient == NULL){
887  return ESPCONN_MEM;
888  }
889 
890  /*Set an IP address given for Little-endian.*/
891  IP4_ADDR(&ipaddr, espconn->proto.tcp->remote_ip[0],
892  espconn->proto.tcp->remote_ip[1],
893  espconn->proto.tcp->remote_ip[2],
894  espconn->proto.tcp->remote_ip[3]);
895 
896  /*Creates a new TCP protocol control block*/
897  pcb = tcp_new();
898 
899  if (pcb == NULL) {
900  /*to prevent memory leaks, ensure that each allocated is deleted*/
901  os_free(pclient);
902  pclient = NULL;
903  return ESPCONN_MEM;
904  } else {
905 
906  /*insert the node to the active connection list*/
907  espconn_list_creat(&plink_active, pclient);
908  tcp_arg(pcb, (void *)pclient);
909  tcp_err(pcb, espconn_client_err);
910  pclient->preverse = NULL;
911  pclient->pespconn = espconn;
912  pclient->pespconn->state = ESPCONN_WAIT;
913  pclient->pcommon.pcb = pcb;
914  tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
915 #if 0
916  pclient->pcommon.err = tcp_bind(pcb, IP_ADDR_ANY, pclient->pespconn->proto.tcp->local_port);
917  if (pclient->pcommon.err != ERR_OK){
918  /*remove the node from the client's active connection list*/
919  espconn_list_delete(&plink_active, pclient);
920  memp_free(MEMP_TCP_PCB, pcb);
921  os_free(pclient);
922  pclient = NULL;
923  return ERR_USE;
924  }
925 #endif
926  /*Establish the connection*/
927  pclient->pcommon.err = tcp_connect(pcb, &ipaddr,
928  pclient->pespconn->proto.tcp->remote_port, espconn_client_connect);
929  if (pclient->pcommon.err == ERR_RTE){
930  /*remove the node from the client's active connection list*/
931  espconn_list_delete(&plink_active, pclient);
932  espconn_kill_pcb(pcb->local_port);
933  os_free(pclient);
934  pclient = NULL;
935  return ESPCONN_RTE;
936  }
937  return pclient->pcommon.err;
938  }
939 }
940 
941 ///////////////////////////////server function/////////////////////////////////
942 /******************************************************************************
943  * FunctionName : espconn_server_close
944  * Description : The connection shall be actively closed.
945  * Parameters : arg -- Additional argument to pass to the callback function
946  * pcb -- the pcb to close
947  * Returns : none
948 *******************************************************************************/
949 static void ICACHE_FLASH_ATTR
950 espconn_server_close(void *arg, struct tcp_pcb *pcb,u8 type)
951 {
952  err_t err;
953  espconn_msg *psclose = arg;
954 
955  psclose->pcommon.pcb = pcb;
956  /*avoid recalling the disconnect function*/
957  tcp_recv(pcb, NULL);
958 
959  if(type ==0)
960  err = tcp_close(pcb);
961  else
962  {tcp_abort(pcb); err = ERR_OK;}
963 
964  if (err != ERR_OK) {
965  /* closing failed, try again later */
966  tcp_recv(pcb, espconn_server_recv);
967  } else {
968  /* closing succeeded */
969  tcp_poll(pcb, NULL, 0);
970  tcp_sent(pcb, NULL);
971  tcp_err(pcb, NULL);
972  /*switch the state of espconn for application process*/
973  psclose->pespconn->state = ESPCONN_CLOSE;
974  ets_post(espconn_TaskPrio, SIG_ESPCONN_CLOSE, (uint32_t)psclose);
975  }
976 }
977 
978 /******************************************************************************
979  * FunctionName : espconn_server_recv
980  * Description : Data has been received on this pcb.
981  * Parameters : arg -- Additional argument to pass to the callback function
982  * pcb -- The connection pcb which received data
983  * p -- The received data (or NULL when the connection has been closed!)
984  * err -- An error code if there has been an error receiving
985  * Returns : ERR_ABRT: if you have called tcp_abort from within the function!
986 *******************************************************************************/
988 espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
989 {
990  espconn_msg *precv_cb = arg;
991 
992  tcp_arg(pcb, arg);
993  espconn_printf("server has application data received: %d\n", system_get_free_heap_size());
994  if (p != NULL) {
995  /*To update and advertise a larger window*/
996  if(precv_cb->recv_hold_flag == 0)
997  tcp_recved(pcb, p->tot_len);
998  else
999  precv_cb->recv_holded_buf_Len += p->tot_len;
1000  }
1001 
1002  if (err == ERR_OK && p != NULL) {
1003  u8_t *data_ptr = NULL;
1004  u32_t data_cntr = 0;
1005  /*clear the count for connection timeout*/
1006  precv_cb->pcommon.recv_check = 0;
1007  /*Copy the contents of a packet buffer to an application buffer.
1008  *to prevent memory leaks, ensure that each allocated is deleted*/
1009  data_ptr = (u8_t *)os_zalloc(p ->tot_len + 1);
1010  data_cntr = pbuf_copy_partial(p, data_ptr, p ->tot_len, 0);
1011  pbuf_free(p);
1012 
1013  if (data_cntr != 0) {
1014  /*switch the state of espconn for application process*/
1015  precv_cb->pespconn ->state = ESPCONN_READ;
1016  precv_cb->pcommon.pcb = pcb;
1017  if (precv_cb->pespconn->recv_callback != NULL) {
1018  precv_cb->pespconn->recv_callback(precv_cb->pespconn, data_ptr, data_cntr);
1019  }
1020 
1021  /*switch the state of espconn for next packet copy*/
1022  if (pcb->state == ESTABLISHED)
1023  precv_cb->pespconn ->state = ESPCONN_CONNECT;
1024  }
1025 
1026  /*to prevent memory leaks, ensure that each allocated is deleted*/
1027  os_free(data_ptr);
1028  data_ptr = NULL;
1029  espconn_printf("server's application data has been processed: %d\n", system_get_free_heap_size());
1030  } else {
1031  if (p != NULL) {
1032  pbuf_free(p);
1033  }
1034 
1035  espconn_server_close(precv_cb, pcb,0);
1036  }
1037 
1038  return ERR_OK;
1039 }
1040 
1041 /******************************************************************************
1042  * FunctionName : espconn_server_sent
1043  * Description : Data has been sent and acknowledged by the remote host.
1044  * This means that more data can be sent.
1045  * Parameters : arg -- Additional argument to pass to the callback function
1046  * pcb -- The connection pcb for which data has been acknowledged
1047  * len -- The amount of bytes acknowledged
1048  * Returns : ERR_OK: try to send some data by calling tcp_output
1049  * ERR_ABRT: if you have called tcp_abort from within the function!
1050 *******************************************************************************/
1051 static err_t ICACHE_FLASH_ATTR
1052 espconn_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
1053 {
1054  espconn_msg *psent_cb = arg;
1055 
1056  psent_cb->pcommon.pcb = pcb;
1057  psent_cb->pcommon.recv_check = 0;
1058  psent_cb->pcommon.pbuf->tot_len += len;
1059  psent_cb->pcommon.packet_info.sent_length = len;
1060 
1061  /*Send more data for one active connection*/
1062  espconn_tcp_finish(psent_cb);
1063  return ERR_OK;
1064 }
1065 
1066 /******************************************************************************
1067  * FunctionName : espconn_server_poll
1068  * Description : The poll function is called every 3nd second.
1069  * If there has been no data sent (which resets the retries) in 3 seconds, close.
1070  * If the last portion of a file has not been sent in 3 seconds, close.
1071  *
1072  * This could be increased, but we don't want to waste resources for bad connections.
1073  * Parameters : arg -- Additional argument to pass to the callback function
1074  * pcb -- The connection pcb for which data has been acknowledged
1075  * Returns : ERR_OK: try to send some data by calling tcp_output
1076  * ERR_ABRT: if you have called tcp_abort from within the function!
1077 *******************************************************************************/
1078 static err_t ICACHE_FLASH_ATTR
1079 espconn_server_poll(void *arg, struct tcp_pcb *pcb)
1080 {
1081  espconn_msg *pspoll_cb = arg;
1082 
1083  /*exception calling abandon the connection for send a RST frame*/
1084  if (arg == NULL) {
1085  tcp_abandon(pcb, 0);
1086  tcp_poll(pcb, NULL, 0);
1087  return ERR_OK;
1088  }
1089 
1090  espconn_printf("espconn_server_poll %d %d\n", pspoll_cb->pcommon.recv_check, pcb->state);
1091  pspoll_cb->pcommon.pcb = pcb;
1092  if (pcb->state == ESTABLISHED) {
1093  pspoll_cb->pcommon.recv_check++;
1094  if (pspoll_cb->pcommon.timeout != 0){/*no data sent in one active connection's set timeout, close.*/
1095  if (pspoll_cb->pcommon.recv_check >= pspoll_cb->pcommon.timeout) {
1096  pspoll_cb->pcommon.recv_check = 0;
1097  espconn_server_close(pspoll_cb, pcb,0);
1098  }
1099  } else {
1100  espconn_msg *ptime_msg = pserver_list;
1101  while (ptime_msg != NULL) {
1102  if (ptime_msg->pespconn == pspoll_cb->preverse){
1103  if (ptime_msg->pcommon.timeout != 0){/*no data sent in server's set timeout, close.*/
1104  if (pspoll_cb->pcommon.recv_check >= ptime_msg->pcommon.timeout){
1105  pspoll_cb->pcommon.recv_check = 0;
1106  espconn_server_close(pspoll_cb, pcb,0);
1107  }
1108  } else {/*don't close for ever*/
1109  pspoll_cb->pcommon.recv_check = 0;
1110  }
1111  break;
1112  }
1113  ptime_msg = ptime_msg->pnext;
1114  }
1115  }
1116  } else {
1117  espconn_server_close(pspoll_cb, pcb,0);
1118  }
1119 
1120  return ERR_OK;
1121 }
1122 
1123 /******************************************************************************
1124  * FunctionName : esponn_server_err
1125  * Description : The pcb had an error and is already deallocated.
1126  * The argument might still be valid (if != NULL).
1127  * Parameters : arg -- Additional argument to pass to the callback function
1128  * err -- Error code to indicate why the pcb has been closed
1129  * Returns : none
1130 *******************************************************************************/
1131 static void ICACHE_FLASH_ATTR
1132 esponn_server_err(void *arg, err_t err)
1133 {
1134  espconn_msg *pserr_cb = arg;
1135  struct tcp_pcb *pcb = NULL;
1136  if (pserr_cb != NULL) {
1137 
1138  pcb = pserr_cb->pcommon.pcb;
1139  pserr_cb->pespconn->state = ESPCONN_CLOSE;
1140 
1141 // /*remove the node from the server's active connection list*/
1142 // espconn_list_delete(&plink_active, pserr_cb);
1143 
1144  /*Set the error code depend on the error type and control block state*/
1145  if (err == ERR_ABRT) {
1146  switch (pcb->state) {
1147  case SYN_RCVD:
1148  if (pcb->nrtx == TCP_SYNMAXRTX) {
1149  pserr_cb->pcommon.err = ESPCONN_CONN;
1150  } else {
1151  pserr_cb->pcommon.err = err;
1152  }
1153 
1154  break;
1155 
1156  case ESTABLISHED:
1157  if (pcb->nrtx == TCP_MAXRTX) {
1158  pserr_cb->pcommon.err = ESPCONN_TIMEOUT;
1159  } else {
1160  pserr_cb->pcommon.err = err;
1161  }
1162 
1163  break;
1164 
1165  case CLOSE_WAIT:
1166  if (pcb->nrtx == TCP_MAXRTX) {
1167  pserr_cb->pcommon.err = ESPCONN_CLSD;
1168  } else {
1169  pserr_cb->pcommon.err = err;
1170  }
1171  break;
1172  case LAST_ACK:
1173  pserr_cb->pcommon.err = ESPCONN_CLSD;
1174  break;
1175 
1176  case CLOSED:
1177  pserr_cb->pcommon.err = ESPCONN_CONN;
1178  break;
1179  default :
1180  break;
1181  }
1182  } else {
1183  pserr_cb->pcommon.err = err;
1184  }
1185  /*post the singer to the task for processing the connection*/
1186  ets_post(espconn_TaskPrio, SIG_ESPCONN_ERRER, (uint32_t)pserr_cb);
1187  }
1188 }
1189 
1190 /******************************************************************************
1191  * FunctionName : espconn_tcp_accept
1192  * Description : A new incoming connection has been accepted.
1193  * Parameters : arg -- Additional argument to pass to the callback function
1194  * pcb -- The connection pcb which is accepted
1195  * err -- An unused error code, always ERR_OK currently
1196  * Returns : acception result
1197 *******************************************************************************/
1198 static err_t ICACHE_FLASH_ATTR
1199 espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
1200 {
1201  struct espconn *espconn = arg;
1202  espconn_msg *paccept = NULL;
1203  remot_info *pinfo = NULL;
1204  LWIP_UNUSED_ARG(err);
1205 
1206  if (!espconn || !espconn->proto.tcp) {
1207  return ERR_ARG;
1208  }
1209 
1210  tcp_arg(pcb, paccept);
1211  tcp_err(pcb, esponn_server_err);
1212  /*Ensure the active connection is less than the count of active connections on the server*/
1213  espconn_get_connection_info(espconn, &pinfo , 0);
1214  espconn_printf("espconn_tcp_accept link_cnt: %d\n", espconn->link_cnt);
1215  if (espconn->link_cnt == espconn_tcp_get_max_con_allow(espconn))
1216  return ERR_ISCONN;
1217 
1218  /*Creates a new active connect control message*/
1219  paccept = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
1220  tcp_arg(pcb, paccept);
1221 
1222  if (paccept == NULL)
1223  return ERR_MEM;
1224  /*Insert the node to the active connection list*/
1225  espconn_list_creat(&plink_active, paccept);
1226 
1227  paccept->preverse = espconn;
1228  paccept->pespconn = (struct espconn *)os_zalloc(sizeof(struct espconn));
1229  if (paccept->pespconn == NULL)
1230  return ERR_MEM;
1231  paccept->pespconn->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
1232  if (paccept->pespconn->proto.tcp == NULL)
1233  return ERR_MEM;
1234 
1235  /*Reserve the remote information for current active connection*/
1236  paccept->pcommon.pcb = pcb;
1237 
1238  paccept->pcommon.remote_port = pcb->remote_port;
1239  paccept->pcommon.remote_ip[0] = ip4_addr1_16(&pcb->remote_ip);
1240  paccept->pcommon.remote_ip[1] = ip4_addr2_16(&pcb->remote_ip);
1241  paccept->pcommon.remote_ip[2] = ip4_addr3_16(&pcb->remote_ip);
1242  paccept->pcommon.remote_ip[3] = ip4_addr4_16(&pcb->remote_ip);
1243  paccept->pcommon.write_flag = true;
1244 
1245  os_memcpy(espconn->proto.tcp->remote_ip, paccept->pcommon.remote_ip, 4);
1246  espconn->proto.tcp->remote_port = pcb->remote_port;
1247  espconn->state = ESPCONN_CONNECT;
1248  espconn_copy_partial(paccept->pespconn, espconn);
1249 
1250  /*Set the specify function that should be called
1251  * when TCP data has been successfully delivered,
1252  * when active connection receives data,
1253  * or periodically from active connection*/
1254  tcp_sent(pcb, espconn_server_sent);
1255  tcp_recv(pcb, espconn_server_recv);
1256  tcp_poll(pcb, espconn_server_poll, 8); /* every 1 seconds */
1257  /*Disable Nagle algorithm default*/
1258  tcp_nagle_disable(pcb);
1259  /*Default set the total number of espconn_buf on the unsent lists for one*/
1260  espconn_tcp_set_buf_count(paccept->pespconn, 1);
1261 
1262  if (paccept->pespconn->proto.tcp->connect_callback != NULL) {
1263  paccept->pespconn->proto.tcp->connect_callback(paccept->pespconn);
1264  }
1265 
1266  /*Enable keep alive option*/
1267  if (espconn_keepalive_disabled(paccept))
1269 
1270  return ERR_OK;
1271 }
1272 
1273 /******************************************************************************
1274  * FunctionName : espconn_tcp_server
1275  * Description : Initialize the server: set up a listening PCB and bind it to
1276  * the defined port
1277  * Parameters : espconn -- the espconn used to build server
1278  * Returns : none
1279 *******************************************************************************/
1282 {
1283  struct tcp_pcb *pcb = NULL;
1284  espconn_msg *pserver = NULL;
1285 
1286  /*Creates a new server control message*/
1287  pserver = (espconn_msg *)os_zalloc(sizeof(espconn_msg));
1288  if (pserver == NULL){
1289  return ESPCONN_MEM;
1290  }
1291 
1292  /*Creates a new TCP protocol control block*/
1293  pcb = tcp_new();
1294  if (pcb == NULL) {
1295  /*to prevent memory leaks, ensure that each allocated is deleted*/
1296  os_free(pserver);
1297  pserver = NULL;
1298  return ESPCONN_MEM;
1299  } else {
1300  struct tcp_pcb *lpcb = NULL;
1301  /*Binds the connection to a local port number and any IP address*/
1302  tcp_bind(pcb, IP_ADDR_ANY, espconn->proto.tcp->local_port);
1303  lpcb = pcb;
1304  /*malloc and set the state of the connection to be LISTEN*/
1305  pcb = tcp_listen(pcb);
1306  if (pcb != NULL) {
1307  /*insert the node to the active connection list*/
1308  espconn_list_creat(&pserver_list, pserver);
1309  pserver->preverse = pcb;
1310  pserver->pespconn = espconn;
1311  pserver->count_opt = MEMP_NUM_TCP_PCB;
1312  pserver->pcommon.timeout = 0x0a;
1313  espconn ->state = ESPCONN_LISTEN;
1314  /*set the specify argument that should be passed callback function*/
1315  tcp_arg(pcb, (void *)espconn);
1316  /*accept callback function to call for this control block*/
1317  tcp_accept(pcb, espconn_tcp_accept);
1318  return ESPCONN_OK;
1319  } else {
1320  /*to prevent memory leaks, ensure that each allocated is deleted*/
1321  memp_free(MEMP_TCP_PCB,lpcb);
1322  os_free(pserver);
1323  pserver = NULL;
1324  return ESPCONN_MEM;
1325  }
1326  }
1327 }
1328 
1329 /******************************************************************************
1330  * FunctionName : espconn_tcp_delete
1331  * Description : delete the server: delete a listening PCB and free it
1332  * Parameters : pdeletecon -- the espconn used to delete a server
1333  * Returns : none
1334 *******************************************************************************/
1336 {
1337  err_t err;
1338  remot_info *pinfo = NULL;
1339  espconn_msg *pdelete_msg = NULL;
1340  struct tcp_pcb *pcb = NULL;
1341 
1342  if (pdeletecon == NULL)
1343  return ESPCONN_ARG;
1344 
1345  espconn_get_connection_info(pdeletecon, &pinfo , 0);
1346  /*make sure all the active connection have been disconnect*/
1347  if (pdeletecon->link_cnt != 0)
1348  return ESPCONN_INPROGRESS;
1349  else {
1350  espconn_printf("espconn_tcp_delete %p\n",pdeletecon);
1351  pdelete_msg = pserver_list;
1352  while (pdelete_msg != NULL){
1353  if (pdelete_msg->pespconn == pdeletecon){
1354  /*remove the node from the client's active connection list*/
1355  espconn_list_delete(&pserver_list, pdelete_msg);
1356  pcb = pdelete_msg->preverse;
1357  os_printf("espconn_tcp_delete %d, %d\n",pcb->state, pcb->local_port);
1358  espconn_kill_pcb(pcb->local_port);
1359  err = tcp_close(pcb);
1360  os_free(pdelete_msg);
1361  pdelete_msg = NULL;
1362  break;
1363  }
1364  pdelete_msg = pdelete_msg->pnext;
1365  }
1366  if (err == ERR_OK)
1367  return err;
1368  else
1369  return ESPCONN_ARG;
1370  }
1371 }
1372 
1373 /******************************************************************************
1374  * FunctionName : espconn_init
1375  * Description : used to init the function that should be used when
1376  * Parameters : none
1377  * Returns : none
1378 *******************************************************************************/
1380 {
1382 }
uint16 unsent
Definition: espconn.h:143
#define ERR_ISCONN
Definition: err.h:73
#define TCP_MAXRTX
Definition: opt.h:910
static err_t ICACHE_FLASH_ATTR espconn_server_poll(void *arg, struct tcp_pcb *pcb)
Definition: espconn_tcp.c:1079
u16_t tot_len
Definition: pbuf.h:90
static void espconn_client_close(void *arg, struct tcp_pcb *pcb, u8 type)
Definition: espconn_tcp.c:520
sint8 ICACHE_FLASH_ATTR espconn_tcp_client(struct espconn *espconn)
Definition: espconn_tcp.c:878
#define ip4_addr3_16(ipaddr)
Definition: ip_addr.h:228
#define espconn_copy_disabled(espconn)
Definition: espconn.h:198
void memp_free(memp_t type, void *mem) ICACHE_FLASH_ATTR
Definition: memp.c:438
uint32 local_ip
Definition: espconn.h:154
err_t ICACHE_FLASH_ATTR espconn_tcp_write(void *arg)
Definition: espconn_tcp.c:667
err_t ICACHE_FLASH_ATTR espconn_tcp_sent(void *arg, uint8 *psent, uint16 length)
Definition: espconn_tcp.c:434
sint8 ICACHE_FLASH_ATTR espconn_tcp_server(struct espconn *espconn)
Definition: espconn_tcp.c:1281
#define ERR_USE
Definition: err.h:70
sint8 espconn_tcp_get_max_con_allow(struct espconn *espconn)
Definition: espconn.c:618
void ICACHE_FLASH_ATTR espconn_pbuf_delete(espconn_buf **phead, espconn_buf *pdelete)
Definition: espconn.c:158
esp_tcp * tcp
Definition: espconn.h:105
int remote_port
Definition: espconn.h:151
static void ICACHE_FLASH_ATTR espconn_Task(os_event_t *events)
Definition: espconn_tcp.c:388
#define espconn_TaskQueueLen
Definition: espconn.h:204
struct _espconn_msg * pnext
Definition: espconn.h:175
espconn_buf * ptail
Definition: espconn.h:156
uint32 system_get_free_heap_size(void)
void espconn_list_delete(espconn_msg **phead, espconn_msg *pdelete)
Definition: espconn.c:104
sint8 espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, uint8 typeflags)
Definition: espconn.c:825
uint16 len
Definition: espconn.h:144
#define NULL
Definition: def.h:47
int local_port
Definition: espconn.h:72
void * pcb
Definition: espconn.h:150
uint8 link_cnt
Definition: espconn.h:111
espconn_msg * pserver_list
Definition: espconn.c:33
static err_t espconn_client_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
Definition: espconn_tcp.c:613
static err_t espconn_server_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
Definition: espconn_tcp.c:988
uint32 timeout
Definition: espconn.h:160
#define ESPCONN_OK
Definition: espconn.h:20
const ip_addr_t ip_addr_any ICACHE_RODATA_ATTR
Definition: ip_addr.c:44
unsigned short uint16
Definition: c_types.h:50
#define ICACHE_FLASH_ATTR
Definition: c_types.h:99
#define MEMP_NUM_TCP_PCB
Definition: opt.h:251
uint8 remote_ip[4]
Definition: espconn.h:74
uint8 * punsent
Definition: espconn.h:142
uint32 local_port
Definition: espconn.h:153
static void ICACHE_FLASH_ATTR espconn_tcp_finish(void *arg)
Definition: espconn_tcp.c:700
static err_t ICACHE_FLASH_ATTR espconn_client_connect(void *arg, struct tcp_pcb *tpcb, err_t err)
Definition: espconn_tcp.c:826
os_event_t espconn_TaskQueue[espconn_TaskQueueLen]
Definition: espconn_tcp.c:36
#define TCP_SYNMAXRTX
Definition: opt.h:917
void * preverse
Definition: espconn.h:173
static void ICACHE_FLASH_ATTR espconn_tcp_reconnect(void *arg)
Definition: espconn_tcp.c:229
#define ERR_ABRT
Definition: err.h:63
void ICACHE_FLASH_ATTR espconn_kill_pcb(u16_t port)
Definition: espconn_tcp.c:150
#define lwip_strerr(x)
Definition: err.h:79
#define os_printf
Definition: osapi.h:62
sint8 err
Definition: espconn.h:159
int remote_port
Definition: espconn.h:71
sint8 espconn_tcp_set_buf_count(struct espconn *espconn, uint8 num)
Definition: espconn.c:665
#define os_event_t
Definition: os_type.h:32
#define os_zalloc(s)
Definition: mem.h:44
static err_t ICACHE_FLASH_ATTR espconn_tcp_accept(void *arg, struct tcp_pcb *pcb, err_t err)
Definition: espconn_tcp.c:1199
espconn_connect_callback connect_callback
Definition: espconn.h:75
void espconn_list_creat(espconn_msg **phead, espconn_msg *pinsert)
Definition: espconn.c:76
#define os_memcpy
Definition: osapi.h:36
struct espconn_packet packet_info
Definition: espconn.h:163
#define ESPCONN_RTE
Definition: espconn.h:23
unsigned long u32_t
Definition: cc.h:56
struct tcp_pcb **const tcp_pcb_lists[]
#define ERR_RTE
Definition: err.h:56
#define ESPCONN_CLSD
Definition: espconn.h:29
static void ICACHE_FLASH_ATTR espconn_tcp_disconnect_successful(void *arg)
Definition: espconn_tcp.c:287
uint16 tot_len
Definition: espconn.h:145
#define ERR_OK
Definition: err.h:52
static void ICACHE_FLASH_ATTR esponn_server_err(void *arg, err_t err)
Definition: espconn_tcp.c:1132
comon_pkt pcommon
Definition: espconn.h:170
bool espconn_find_connection(struct espconn *pespconn, espconn_msg **pnode)
Definition: espconn.c:186
#define espconn_keepalive_enable(pcb)
Definition: espconn_tcp.h:13
Definition: pbuf.h:76
#define ESPCONN_ARG
Definition: espconn.h:32
unsigned char uint8
Definition: c_types.h:45
void ICACHE_FLASH_ATTR espconn_kill_oldest_pcb(void)
Definition: espconn_tcp.c:115
s8_t err_t
Definition: err.h:47
#define espconn_TaskPrio
Definition: espconn.h:203
static void ICACHE_FLASH_ATTR espconn_kill_oldest(void)
Definition: espconn_tcp.c:56
#define ip4_addr4_16(ipaddr)
Definition: ip_addr.h:229
espconn_connect_callback write_finish_fn
Definition: espconn.h:78
void espconn_copy_partial(struct espconn *pesp_dest, struct espconn *pesp_source)
Definition: espconn.c:46
uint8 remote_ip[4]
Definition: espconn.h:152
#define IP_ADDR_ANY
Definition: ip_addr.h:92
static void ICACHE_FLASH_ATTR espconn_client_err(void *arg, err_t err)
Definition: espconn_tcp.c:761
#define os_free(s)
Definition: mem.h:40
unsigned char u8
Definition: c_types.h:46
#define ESPCONN_TIMEOUT
Definition: espconn.h:22
bool write_flag
Definition: espconn.h:164
static void espconn_server_close(void *arg, struct tcp_pcb *pcb, u8 type)
Definition: espconn_tcp.c:950
unsigned int uint32
Definition: c_types.h:54
#define espconn_printf(fmt, args...)
Definition: espconn.h:10
#define ERR_ARG
Definition: err.h:68
u8_t pbuf_free(struct pbuf *p) ICACHE_FLASH_ATTR
Definition: pbuf.c:685
union espconn::@1 proto
uint8 local_ip[4]
Definition: espconn.h:73
sint8 ICACHE_FLASH_ATTR espconn_recv_unhold(struct espconn *pespconn)
Definition: espconn_tcp.c:574
#define espconn_reuse_disabled(espconn)
Definition: espconn.h:197
uint8 recv_hold_flag
Definition: espconn.h:178
espconn_reconnect_callback reconnect_callback
Definition: espconn.h:76
enum espconn_type type
Definition: espconn.h:101
#define ip4_addr1_16(ipaddr)
Definition: ip_addr.h:226
enum espconn_state state
Definition: espconn.h:103
unsigned char u8_t
Definition: cc.h:52
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:65
espconn_connect_callback disconnect_callback
Definition: espconn.h:77
uint16 sent_length
Definition: espconn.h:131
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset) ICACHE_FLASH_ATTR
Definition: pbuf.c:996
void ICACHE_FLASH_ATTR espconn_init(void)
Definition: espconn_tcp.c:1379
struct espconn_packet pktinfo[2]
Definition: espconn.c:36
#define ESPCONN_INPROGRESS
Definition: espconn.h:24
espconn_recv_callback recv_callback
Definition: espconn.h:109
#define TCP_SND_QUEUELEN
Definition: opt.h:964
#define ip4_addr2_16(ipaddr)
Definition: ip_addr.h:227
uint16 recv_holded_buf_Len
Definition: espconn.h:179
signed char sint8
Definition: c_types.h:47
#define os_bzero
Definition: osapi.h:31
uint32 recv_check
Definition: espconn.h:161
struct _espconn_buf * pnext
Definition: espconn.h:146
#define ESPCONN_CONN
Definition: espconn.h:30
static err_t ICACHE_FLASH_ATTR espconn_client_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
Definition: espconn_tcp.c:738
struct espconn * pespconn
Definition: espconn.h:169
static err_t ICACHE_FLASH_ATTR espconn_server_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
Definition: espconn_tcp.c:1052
#define ERR_MEM
Definition: err.h:53
void ICACHE_FLASH_ATTR espconn_tcp_disconnect(espconn_msg *pdiscon, u8 type)
Definition: espconn_tcp.c:498
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define espconn_keepalive_disabled(espconn)
Definition: espconn.h:200
espconn_msg * plink_active
Definition: espconn.c:32
espconn_sent_callback sent_callback
Definition: espconn.h:110
struct tcp_pcb *ICACHE_FLASH_ATTR espconn_find_current_pcb(espconn_msg *pcurrent_msg)
Definition: espconn_tcp.c:185
espconn_buf * pbuf
Definition: espconn.h:155
uint8 count_opt
Definition: espconn.h:171
sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon)
Definition: espconn_tcp.c:1335
unsigned short u16_t
Definition: cc.h:54
sint8 ICACHE_FLASH_ATTR espconn_recv_hold(struct espconn *pespconn)
Definition: espconn_tcp.c:549
#define IP4_ADDR(ipaddr, a, b, c, d)
Definition: ip_addr.h:139
#define ESPCONN_MEM
Definition: espconn.h:21