espconn_tcp.c 47 KB

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