api_msg.c 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986
  1. /**
  2. * @file
  3. * Sequential API Internal module
  4. *
  5. */
  6. /*
  7. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without modification,
  11. * are permitted provided that the following conditions are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * 3. The name of the author may not be used to endorse or promote products
  19. * derived from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  22. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  23. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  24. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  26. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  29. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  30. * OF SUCH DAMAGE.
  31. *
  32. * This file is part of the lwIP TCP/IP stack.
  33. *
  34. * Author: Adam Dunkels <adam@sics.se>
  35. *
  36. */
  37. #include "lwip/opt.h"
  38. #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
  39. #include "lwip/priv/api_msg.h"
  40. #include "lwip/ip.h"
  41. #include "lwip/udp.h"
  42. #include "lwip/tcp.h"
  43. #include "lwip/raw.h"
  44. #include "lwip/memp.h"
  45. #include "lwip/igmp.h"
  46. #include "lwip/dns.h"
  47. #include "lwip/mld6.h"
  48. #include "lwip/priv/tcpip_priv.h"
  49. #include <string.h>
  50. /* netconns are polled once per second (e.g. continue write on memory error) */
  51. #define NETCONN_TCP_POLL_INTERVAL 2
  52. #define SET_NONBLOCKING_CONNECT(conn, val) do { if (val) { \
  53. (conn)->flags |= NETCONN_FLAG_IN_NONBLOCKING_CONNECT; \
  54. } else { \
  55. (conn)->flags &= ~ NETCONN_FLAG_IN_NONBLOCKING_CONNECT; }} while(0)
  56. #define IN_NONBLOCKING_CONNECT(conn) (((conn)->flags & NETCONN_FLAG_IN_NONBLOCKING_CONNECT) != 0)
  57. /* forward declarations */
  58. #if LWIP_TCP
  59. #if LWIP_TCPIP_CORE_LOCKING
  60. #define WRITE_DELAYED , 1
  61. #define WRITE_DELAYED_PARAM , u8_t delayed
  62. #else /* LWIP_TCPIP_CORE_LOCKING */
  63. #define WRITE_DELAYED
  64. #define WRITE_DELAYED_PARAM
  65. #endif /* LWIP_TCPIP_CORE_LOCKING */
  66. static err_t lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM);
  67. #if ESP_LWIP
  68. #define SIG_CLOSE_PARAM , bool sig_close
  69. #define SIG_CLOSE_TRUE true
  70. #define SIG_CLOSE_FALSE false
  71. #else
  72. #define SIG_CLOSE_PARAM
  73. #define SIG_CLOSE_TRUE
  74. #define SIG_CLOSE_FALSE
  75. #endif
  76. #endif
  77. static err_t lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM SIG_CLOSE_PARAM);
  78. #if LWIP_RAW
  79. /**
  80. * Receive callback function for RAW netconns.
  81. * Doesn't 'eat' the packet, only copies it and sends it to
  82. * conn->recvmbox
  83. *
  84. * @see raw.h (struct raw_pcb.recv) for parameters and return value
  85. */
  86. static u8_t
  87. recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
  88. const ip_addr_t *addr)
  89. {
  90. struct pbuf *q;
  91. struct netbuf *buf;
  92. struct netconn *conn;
  93. LWIP_UNUSED_ARG(addr);
  94. conn = (struct netconn *)arg;
  95. if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox)) {
  96. #if LWIP_SO_RCVBUF
  97. int recv_avail;
  98. SYS_ARCH_GET(conn->recv_avail, recv_avail);
  99. if ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize) {
  100. return 0;
  101. }
  102. #endif /* LWIP_SO_RCVBUF */
  103. /* copy the whole packet into new pbufs */
  104. q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
  105. if (q != NULL) {
  106. if (pbuf_copy(q, p) != ERR_OK) {
  107. pbuf_free(q);
  108. q = NULL;
  109. }
  110. }
  111. if (q != NULL) {
  112. u16_t len;
  113. buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
  114. if (buf == NULL) {
  115. pbuf_free(q);
  116. return 0;
  117. }
  118. buf->p = q;
  119. buf->ptr = q;
  120. ip_addr_copy(buf->addr, *ip_current_src_addr());
  121. buf->port = pcb->protocol;
  122. len = q->tot_len;
  123. if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
  124. ESP_STATS_DROP_INC(esp.rx_rawmbox_post_fail);
  125. netbuf_delete(buf);
  126. return 0;
  127. } else {
  128. #if LWIP_SO_RCVBUF
  129. SYS_ARCH_INC(conn->recv_avail, len);
  130. #endif /* LWIP_SO_RCVBUF */
  131. /* Register event with callback */
  132. API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
  133. }
  134. }
  135. }
  136. return 0; /* do not eat the packet */
  137. }
  138. #endif /* LWIP_RAW*/
  139. #if LWIP_UDP
  140. /**
  141. * Receive callback function for UDP netconns.
  142. * Posts the packet to conn->recvmbox or deletes it on memory error.
  143. *
  144. * @see udp.h (struct udp_pcb.recv) for parameters
  145. */
  146. static void
  147. recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
  148. const ip_addr_t *addr, u16_t port)
  149. {
  150. struct netbuf *buf;
  151. struct netconn *conn;
  152. u16_t len;
  153. #if LWIP_SO_RCVBUF
  154. int recv_avail;
  155. #endif /* LWIP_SO_RCVBUF */
  156. LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
  157. LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
  158. LWIP_ASSERT("recv_udp must have an argument", arg != NULL);
  159. conn = (struct netconn *)arg;
  160. LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
  161. #if LWIP_SO_RCVBUF
  162. SYS_ARCH_GET(conn->recv_avail, recv_avail);
  163. if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) ||
  164. ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
  165. #else /* LWIP_SO_RCVBUF */
  166. if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox)) {
  167. #endif /* LWIP_SO_RCVBUF */
  168. pbuf_free(p);
  169. return;
  170. }
  171. #if LWIP_IPV6
  172. /* This should be eventually moved to a flag on the UDP PCB, and this drop can happen
  173. more correctly in udp_input(). This will also allow icmp_dest_unreach() to be called. */
  174. if (conn->flags & NETCONN_FLAG_IPV6_V6ONLY && !ip_current_is_v6()) {
  175. LWIP_DEBUGF(API_MSG_DEBUG, ("recv_udp: Dropping IPv4 UDP packet (IPv6-only socket)"));
  176. pbuf_free(p);
  177. return;
  178. }
  179. #endif
  180. buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
  181. if (buf == NULL) {
  182. pbuf_free(p);
  183. return;
  184. } else {
  185. buf->p = p;
  186. buf->ptr = p;
  187. ip_addr_set(&buf->addr, addr);
  188. buf->port = port;
  189. #if LWIP_NETBUF_RECVINFO
  190. {
  191. /* get the UDP header - always in the first pbuf, ensured by udp_input */
  192. const struct udp_hdr* udphdr = (const struct udp_hdr*)ip_next_header_ptr();
  193. #if LWIP_CHECKSUM_ON_COPY
  194. buf->flags = NETBUF_FLAG_DESTADDR;
  195. #endif /* LWIP_CHECKSUM_ON_COPY */
  196. ip_addr_set(&buf->toaddr, ip_current_dest_addr());
  197. buf->toport_chksum = udphdr->dest;
  198. }
  199. #endif /* LWIP_NETBUF_RECVINFO */
  200. }
  201. #if ESP_PERF
  202. if (p->len > DBG_PERF_FILTER_LEN) {
  203. DBG_PERF_PATH_SET(DBG_PERF_DIR_RX, DBG_PERF_POINT_LWIP_OUT);
  204. }
  205. #endif
  206. len = p->tot_len;
  207. if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) {
  208. ESP_STATS_DROP_INC(esp.rx_udpmbox_post_fail);
  209. netbuf_delete(buf);
  210. return;
  211. } else {
  212. #if LWIP_SO_RCVBUF
  213. SYS_ARCH_INC(conn->recv_avail, len);
  214. #endif /* LWIP_SO_RCVBUF */
  215. /* Register event with callback */
  216. API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
  217. }
  218. }
  219. #endif /* LWIP_UDP */
  220. #if LWIP_TCP
  221. /**
  222. * Receive callback function for TCP netconns.
  223. * Posts the packet to conn->recvmbox, but doesn't delete it on errors.
  224. *
  225. * @see tcp.h (struct tcp_pcb.recv) for parameters and return value
  226. */
  227. static err_t
  228. recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
  229. {
  230. struct netconn *conn;
  231. u16_t len;
  232. LWIP_UNUSED_ARG(pcb);
  233. LWIP_ASSERT("recv_tcp must have a pcb argument", pcb != NULL);
  234. LWIP_ASSERT("recv_tcp must have an argument", arg != NULL);
  235. conn = (struct netconn *)arg;
  236. if (conn == NULL) {
  237. return ERR_VAL;
  238. }
  239. LWIP_ASSERT("recv_tcp: recv for wrong pcb!", conn->pcb.tcp == pcb);
  240. if (!sys_mbox_valid(&conn->recvmbox)) {
  241. /* recvmbox already deleted */
  242. if (p != NULL) {
  243. tcp_recved(pcb, p->tot_len);
  244. pbuf_free(p);
  245. }
  246. return ERR_OK;
  247. }
  248. /* Unlike for UDP or RAW pcbs, don't check for available space
  249. using recv_avail since that could break the connection
  250. (data is already ACKed) */
  251. /* don't overwrite fatal errors! */
  252. if (err != ERR_OK) {
  253. NETCONN_SET_SAFE_ERR(conn, err);
  254. }
  255. if (p != NULL) {
  256. len = p->tot_len;
  257. } else {
  258. len = 0;
  259. }
  260. if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) {
  261. ESP_STATS_DROP_INC(esp.rx_tcpmbox_post_fail);
  262. /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
  263. return ERR_MEM;
  264. } else {
  265. #if LWIP_SO_RCVBUF
  266. SYS_ARCH_INC(conn->recv_avail, len);
  267. #endif /* LWIP_SO_RCVBUF */
  268. /* Register event with callback */
  269. API_EVENT(conn, NETCONN_EVT_RCVPLUS, len);
  270. }
  271. return ERR_OK;
  272. }
  273. /**
  274. * Poll callback function for TCP netconns.
  275. * Wakes up an application thread that waits for a connection to close
  276. * or data to be sent. The application thread then takes the
  277. * appropriate action to go on.
  278. *
  279. * Signals the conn->sem.
  280. * netconn_close waits for conn->sem if closing failed.
  281. *
  282. * @see tcp.h (struct tcp_pcb.poll) for parameters and return value
  283. */
  284. static err_t
  285. poll_tcp(void *arg, struct tcp_pcb *pcb)
  286. {
  287. struct netconn *conn = (struct netconn *)arg;
  288. bool sig_close = false;
  289. LWIP_UNUSED_ARG(pcb);
  290. LWIP_ASSERT("conn != NULL", (conn != NULL));
  291. if (conn->state == NETCONN_WRITE) {
  292. lwip_netconn_do_writemore(conn WRITE_DELAYED);
  293. } else if (conn->state == NETCONN_CLOSE) {
  294. #if !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER
  295. if (conn->current_msg && conn->current_msg->msg.sd.polls_left) {
  296. conn->current_msg->msg.sd.polls_left--;
  297. }
  298. #endif /* !LWIP_SO_SNDTIMEO && !LWIP_SO_LINGER */
  299. /* Delay the netconn close until no one use 'conn' because close frees 'conn'*/
  300. if (ERR_OK == lwip_netconn_do_close_internal(conn WRITE_DELAYED, SIG_CLOSE_FALSE)) {
  301. sig_close = true;
  302. }
  303. }
  304. /* @todo: implement connect timeout here? */
  305. /* Did a nonblocking write fail before? Then check available write-space. */
  306. if (conn->flags & NETCONN_FLAG_CHECK_WRITESPACE) {
  307. /* If the queued byte- or pbuf-count drops below the configured low-water limit,
  308. let select mark this pcb as writable again. */
  309. if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT(conn->pcb.tcp)) &&
  310. (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT(conn->pcb.tcp))) {
  311. conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
  312. API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
  313. }
  314. }
  315. #if ESP_LWIP
  316. if (sig_close) {
  317. sys_sem_t *op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
  318. conn->current_msg = NULL;
  319. sys_sem_signal(op_completed_sem);
  320. return ERR_ABRT;
  321. }
  322. #endif
  323. return ERR_OK;
  324. }
  325. /**
  326. * Sent callback function for TCP netconns.
  327. * Signals the conn->sem and calls API_EVENT.
  328. * netconn_write waits for conn->sem if send buffer is low.
  329. *
  330. * @see tcp.h (struct tcp_pcb.sent) for parameters and return value
  331. */
  332. static err_t
  333. sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
  334. {
  335. struct netconn *conn = (struct netconn *)arg;
  336. bool sig_close = false;
  337. LWIP_UNUSED_ARG(pcb);
  338. LWIP_ASSERT("conn != NULL", (conn != NULL));
  339. if (conn) {
  340. if (conn->state == NETCONN_WRITE) {
  341. lwip_netconn_do_writemore(conn WRITE_DELAYED);
  342. } else if (conn->state == NETCONN_CLOSE) {
  343. /* Delay the netconn close until no one use 'conn' because close frees 'conn'*/
  344. if (ERR_OK == lwip_netconn_do_close_internal(conn WRITE_DELAYED, SIG_CLOSE_FALSE)) {
  345. sig_close = true;
  346. }
  347. }
  348. /* If the queued byte- or pbuf-count drops below the configured low-water limit,
  349. let select mark this pcb as writable again. */
  350. if ((conn->pcb.tcp != NULL) && (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT(conn->pcb.tcp) &&
  351. (tcp_sndqueuelen(conn->pcb.tcp) < TCP_SNDQUEUELOWAT(conn->pcb.tcp)))) {
  352. conn->flags &= ~NETCONN_FLAG_CHECK_WRITESPACE;
  353. API_EVENT(conn, NETCONN_EVT_SENDPLUS, len);
  354. }
  355. #if ESP_LWIP
  356. if (sig_close) {
  357. sys_sem_t *op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
  358. conn->current_msg = NULL;
  359. sys_sem_signal(op_completed_sem);
  360. return ERR_ABRT;
  361. }
  362. #endif
  363. }
  364. return ERR_OK;
  365. }
  366. /**
  367. * Error callback function for TCP netconns.
  368. * Signals conn->sem, posts to all conn mboxes and calls API_EVENT.
  369. * The application thread has then to decide what to do.
  370. *
  371. * @see tcp.h (struct tcp_pcb.err) for parameters
  372. */
  373. static void
  374. err_tcp(void *arg, err_t err)
  375. {
  376. struct netconn *conn;
  377. enum netconn_state old_state;
  378. conn = (struct netconn *)arg;
  379. LWIP_ASSERT("conn != NULL", (conn != NULL));
  380. conn->pcb.tcp = NULL;
  381. /* no check since this is always fatal! */
  382. SYS_ARCH_SET(conn->last_err, err);
  383. /* reset conn->state now before waking up other threads */
  384. old_state = conn->state;
  385. conn->state = NETCONN_NONE;
  386. /* @todo: the type of NETCONN_EVT created should depend on 'old_state' */
  387. /* Notify the user layer about a connection error. Used to signal select. */
  388. API_EVENT(conn, NETCONN_EVT_ERROR, 0);
  389. /* Try to release selects pending on 'read' or 'write', too.
  390. They will get an error if they actually try to read or write. */
  391. API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
  392. API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
  393. /* pass NULL-message to recvmbox to wake up pending recv */
  394. if (sys_mbox_valid(&conn->recvmbox)) {
  395. /* use trypost to prevent deadlock */
  396. if (sys_mbox_trypost(&conn->recvmbox, NULL) != ERR_OK){
  397. ESP_STATS_DROP_INC(esp.err_tcp_rxmbox_post_fail);
  398. }
  399. }
  400. /* pass NULL-message to acceptmbox to wake up pending accept */
  401. if (sys_mbox_valid(&conn->acceptmbox)) {
  402. /* use trypost to preven deadlock */
  403. if (sys_mbox_trypost(&conn->acceptmbox, NULL) != ERR_OK) {
  404. ESP_STATS_DROP_INC(esp.err_tcp_rxmbox_post_fail);
  405. }
  406. }
  407. if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) ||
  408. (old_state == NETCONN_CONNECT)) {
  409. /* calling lwip_netconn_do_writemore/lwip_netconn_do_close_internal is not necessary
  410. since the pcb has already been deleted! */
  411. int was_nonblocking_connect = IN_NONBLOCKING_CONNECT(conn);
  412. SET_NONBLOCKING_CONNECT(conn, 0);
  413. if (!was_nonblocking_connect) {
  414. sys_sem_t* op_completed_sem;
  415. /* set error return code */
  416. LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
  417. conn->current_msg->err = err;
  418. op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
  419. LWIP_ASSERT("inavlid op_completed_sem", sys_sem_valid(op_completed_sem));
  420. conn->current_msg = NULL;
  421. /* wake up the waiting task */
  422. NETCONN_SET_SAFE_ERR(conn, err);
  423. sys_sem_signal(op_completed_sem);
  424. }
  425. } else {
  426. LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL);
  427. }
  428. }
  429. /**
  430. * Setup a tcp_pcb with the correct callback function pointers
  431. * and their arguments.
  432. *
  433. * @param conn the TCP netconn to setup
  434. */
  435. static void
  436. setup_tcp(struct netconn *conn)
  437. {
  438. struct tcp_pcb *pcb;
  439. pcb = conn->pcb.tcp;
  440. tcp_arg(pcb, conn);
  441. tcp_recv(pcb, recv_tcp);
  442. tcp_sent(pcb, sent_tcp);
  443. tcp_poll(pcb, poll_tcp, NETCONN_TCP_POLL_INTERVAL);
  444. tcp_err(pcb, err_tcp);
  445. }
  446. /**
  447. * Accept callback function for TCP netconns.
  448. * Allocates a new netconn and posts that to conn->acceptmbox.
  449. *
  450. * @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
  451. */
  452. static err_t
  453. accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
  454. {
  455. struct netconn *newconn;
  456. struct netconn *conn = (struct netconn *)arg;
  457. LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: newpcb->tate: %s\n", tcp_debug_state_str(newpcb->state)));
  458. if (!sys_mbox_valid(&conn->acceptmbox)) {
  459. LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n"));
  460. return ERR_VAL;
  461. }
  462. /* We have to set the callback here even though
  463. * the new socket is unknown. conn->socket is marked as -1. */
  464. newconn = netconn_alloc(conn->type, conn->callback);
  465. if (newconn == NULL) {
  466. return ERR_MEM;
  467. }
  468. newconn->pcb.tcp = newpcb;
  469. setup_tcp(newconn);
  470. /* no protection: when creating the pcb, the netconn is not yet known
  471. to the application thread */
  472. newconn->last_err = err;
  473. if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) {
  474. ESP_STATS_DROP_INC(esp.acceptmbox_post_fail);
  475. /* When returning != ERR_OK, the pcb is aborted in tcp_process(),
  476. so do nothing here! */
  477. /* remove all references to this netconn from the pcb */
  478. struct tcp_pcb* pcb = newconn->pcb.tcp;
  479. tcp_arg(pcb, NULL);
  480. tcp_recv(pcb, NULL);
  481. tcp_sent(pcb, NULL);
  482. tcp_poll(pcb, NULL, 0);
  483. tcp_err(pcb, NULL);
  484. /* remove reference from to the pcb from this netconn */
  485. newconn->pcb.tcp = NULL;
  486. /* no need to drain since we know the recvmbox is empty. */
  487. sys_mbox_free(&newconn->recvmbox);
  488. sys_mbox_set_invalid(&newconn->recvmbox);
  489. netconn_free(newconn);
  490. return ERR_MEM;
  491. } else {
  492. /* Register event with callback */
  493. API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
  494. }
  495. return ERR_OK;
  496. }
  497. #endif /* LWIP_TCP */
  498. /**
  499. * Create a new pcb of a specific type.
  500. * Called from lwip_netconn_do_newconn().
  501. *
  502. * @param msg the api_msg_msg describing the connection type
  503. * @return msg->conn->err, but the return value is currently ignored
  504. */
  505. static void
  506. pcb_new(struct api_msg_msg *msg)
  507. {
  508. LWIP_ASSERT("pcb_new: pcb already allocated", msg->conn->pcb.tcp == NULL);
  509. /* Allocate a PCB for this connection */
  510. switch(NETCONNTYPE_GROUP(msg->conn->type)) {
  511. #if LWIP_RAW
  512. case NETCONN_RAW:
  513. msg->conn->pcb.raw = raw_new(msg->msg.n.proto);
  514. if (msg->conn->pcb.raw != NULL) {
  515. raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
  516. }
  517. break;
  518. #endif /* LWIP_RAW */
  519. #if LWIP_UDP
  520. case NETCONN_UDP:
  521. msg->conn->pcb.udp = udp_new();
  522. if (msg->conn->pcb.udp != NULL) {
  523. #if LWIP_UDPLITE
  524. if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) {
  525. udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
  526. }
  527. #endif /* LWIP_UDPLITE */
  528. if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) {
  529. udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
  530. }
  531. udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
  532. }
  533. break;
  534. #endif /* LWIP_UDP */
  535. #if LWIP_TCP
  536. case NETCONN_TCP:
  537. msg->conn->pcb.tcp = tcp_new();
  538. if (msg->conn->pcb.tcp != NULL) {
  539. setup_tcp(msg->conn);
  540. }
  541. break;
  542. #endif /* LWIP_TCP */
  543. default:
  544. /* Unsupported netconn type, e.g. protocol disabled */
  545. msg->err = ERR_VAL;
  546. return;
  547. }
  548. if (msg->conn->pcb.ip == NULL) {
  549. msg->err = ERR_MEM;
  550. }
  551. #if LWIP_IPV4 && LWIP_IPV6
  552. else {
  553. if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
  554. /* Convert IPv4 PCB manually to an IPv6 PCB */
  555. IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_V6);
  556. IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_V6);
  557. }
  558. }
  559. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  560. }
  561. /**
  562. * Create a new pcb of a specific type inside a netconn.
  563. * Called from netconn_new_with_proto_and_callback.
  564. *
  565. * @param msg the api_msg_msg describing the connection type
  566. */
  567. void
  568. lwip_netconn_do_newconn(void *m)
  569. {
  570. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  571. msg->err = ERR_OK;
  572. if (msg->conn->pcb.tcp == NULL) {
  573. pcb_new(msg);
  574. }
  575. /* Else? This "new" connection already has a PCB allocated. */
  576. /* Is this an error condition? Should it be deleted? */
  577. /* We currently just are happy and return. */
  578. TCPIP_APIMSG_ACK(msg);
  579. }
  580. /**
  581. * Create a new netconn (of a specific type) that has a callback function.
  582. * The corresponding pcb is NOT created!
  583. *
  584. * @param t the type of 'connection' to create (@see enum netconn_type)
  585. * @param proto the IP protocol for RAW IP pcbs
  586. * @param callback a function to call on status changes (RX available, TX'ed)
  587. * @return a newly allocated struct netconn or
  588. * NULL on memory error
  589. */
  590. struct netconn*
  591. netconn_alloc(enum netconn_type t, netconn_callback callback)
  592. {
  593. struct netconn *conn;
  594. int size;
  595. conn = (struct netconn *)memp_malloc(MEMP_NETCONN);
  596. if (conn == NULL) {
  597. return NULL;
  598. }
  599. conn->last_err = ERR_OK;
  600. conn->type = t;
  601. conn->pcb.tcp = NULL;
  602. /* If all sizes are the same, every compiler should optimize this switch to nothing */
  603. switch(NETCONNTYPE_GROUP(t)) {
  604. #if LWIP_RAW
  605. case NETCONN_RAW:
  606. size = DEFAULT_RAW_RECVMBOX_SIZE;
  607. break;
  608. #endif /* LWIP_RAW */
  609. #if LWIP_UDP
  610. case NETCONN_UDP:
  611. size = DEFAULT_UDP_RECVMBOX_SIZE;
  612. break;
  613. #endif /* LWIP_UDP */
  614. #if LWIP_TCP
  615. case NETCONN_TCP:
  616. size = DEFAULT_TCP_RECVMBOX_SIZE;
  617. break;
  618. #endif /* LWIP_TCP */
  619. default:
  620. LWIP_ASSERT("netconn_alloc: undefined netconn_type", 0);
  621. goto free_and_return;
  622. }
  623. if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) {
  624. goto free_and_return;
  625. }
  626. #if !LWIP_NETCONN_SEM_PER_THREAD
  627. if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) {
  628. sys_mbox_free(&conn->recvmbox);
  629. goto free_and_return;
  630. }
  631. #endif
  632. #if LWIP_TCP
  633. sys_mbox_set_invalid(&conn->acceptmbox);
  634. #endif
  635. conn->state = NETCONN_NONE;
  636. #if LWIP_SOCKET
  637. /* initialize socket to -1 since 0 is a valid socket */
  638. conn->socket = -1;
  639. #endif /* LWIP_SOCKET */
  640. conn->callback = callback;
  641. #if LWIP_TCP
  642. conn->current_msg = NULL;
  643. conn->write_offset = 0;
  644. #endif /* LWIP_TCP */
  645. #if LWIP_SO_SNDTIMEO
  646. conn->send_timeout = 0;
  647. #endif /* LWIP_SO_SNDTIMEO */
  648. #if LWIP_SO_RCVTIMEO
  649. conn->recv_timeout = 0;
  650. #endif /* LWIP_SO_RCVTIMEO */
  651. #if LWIP_SO_RCVBUF
  652. conn->recv_bufsize = RECV_BUFSIZE_DEFAULT;
  653. conn->recv_avail = 0;
  654. #endif /* LWIP_SO_RCVBUF */
  655. #if LWIP_SO_LINGER
  656. conn->linger = -1;
  657. #endif /* LWIP_SO_LINGER */
  658. conn->flags = 0;
  659. return conn;
  660. free_and_return:
  661. memp_free(MEMP_NETCONN, conn);
  662. return NULL;
  663. }
  664. /**
  665. * Delete a netconn and all its resources.
  666. * The pcb is NOT freed (since we might not be in the right thread context do this).
  667. *
  668. * @param conn the netconn to free
  669. */
  670. void
  671. netconn_free(struct netconn *conn)
  672. {
  673. LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
  674. LWIP_ASSERT("recvmbox must be deallocated before calling this function",
  675. !sys_mbox_valid(&conn->recvmbox));
  676. #if LWIP_TCP
  677. LWIP_ASSERT("acceptmbox must be deallocated before calling this function",
  678. !sys_mbox_valid(&conn->acceptmbox));
  679. #endif /* LWIP_TCP */
  680. #if !LWIP_NETCONN_SEM_PER_THREAD
  681. sys_sem_free(&conn->op_completed);
  682. sys_sem_set_invalid(&conn->op_completed);
  683. #endif
  684. memp_free(MEMP_NETCONN, conn);
  685. }
  686. /**
  687. * Delete rcvmbox and acceptmbox of a netconn and free the left-over data in
  688. * these mboxes
  689. *
  690. * @param conn the netconn to free
  691. * @bytes_drained bytes drained from recvmbox
  692. * @accepts_drained pending connections drained from acceptmbox
  693. */
  694. static void
  695. netconn_drain(struct netconn *conn)
  696. {
  697. void *mem;
  698. #if LWIP_TCP
  699. struct pbuf *p;
  700. #endif /* LWIP_TCP */
  701. /* This runs in tcpip_thread, so we don't need to lock against rx packets */
  702. /* Delete and drain the recvmbox. */
  703. if (sys_mbox_valid(&conn->recvmbox)) {
  704. while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
  705. #if LWIP_TCP
  706. if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) {
  707. if (mem != NULL) {
  708. p = (struct pbuf*)mem;
  709. /* pcb might be set to NULL already by err_tcp() */
  710. if (conn->pcb.tcp != NULL) {
  711. tcp_recved(conn->pcb.tcp, p->tot_len);
  712. }
  713. pbuf_free(p);
  714. }
  715. } else
  716. #endif /* LWIP_TCP */
  717. {
  718. netbuf_delete((struct netbuf *)mem);
  719. }
  720. }
  721. sys_mbox_free(&conn->recvmbox);
  722. sys_mbox_set_invalid(&conn->recvmbox);
  723. }
  724. /* Delete and drain the acceptmbox. */
  725. #if LWIP_TCP
  726. if (sys_mbox_valid(&conn->acceptmbox)) {
  727. while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
  728. struct netconn *newconn = (struct netconn *)mem;
  729. /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */
  730. /* pcb might be set to NULL already by err_tcp() */
  731. if (conn->pcb.tcp != NULL) {
  732. tcp_accepted(conn->pcb.tcp);
  733. }
  734. /* drain recvmbox */
  735. netconn_drain(newconn);
  736. if (newconn->pcb.tcp != NULL) {
  737. tcp_abort(newconn->pcb.tcp);
  738. newconn->pcb.tcp = NULL;
  739. }
  740. netconn_free(newconn);
  741. }
  742. sys_mbox_free(&conn->acceptmbox);
  743. sys_mbox_set_invalid(&conn->acceptmbox);
  744. }
  745. #endif /* LWIP_TCP */
  746. }
  747. #if LWIP_TCP
  748. /**
  749. * Internal helper function to close a TCP netconn: since this sometimes
  750. * doesn't work at the first attempt, this function is called from multiple
  751. * places.
  752. *
  753. * @param conn the TCP netconn to close
  754. * [@param delay 1 if called from sent/poll (wake up calling thread on end)]
  755. */
  756. static err_t
  757. lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM SIG_CLOSE_PARAM)
  758. {
  759. err_t err;
  760. u8_t shut, shut_rx, shut_tx, close;
  761. u8_t close_finished = 0;
  762. struct tcp_pcb* tpcb;
  763. #if LWIP_SO_LINGER
  764. u8_t linger_wait_required = 0;
  765. #endif /* LWIP_SO_LINGER */
  766. LWIP_ASSERT("invalid conn", (conn != NULL));
  767. LWIP_ASSERT("this is for tcp netconns only", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP));
  768. LWIP_ASSERT("conn must be in state NETCONN_CLOSE", (conn->state == NETCONN_CLOSE));
  769. LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL));
  770. LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
  771. tpcb = conn->pcb.tcp;
  772. shut = conn->current_msg->msg.sd.shut;
  773. shut_rx = shut & NETCONN_SHUT_RD;
  774. shut_tx = shut & NETCONN_SHUT_WR;
  775. /* shutting down both ends is the same as closing
  776. (also if RD or WR side was shut down before already) */
  777. if (shut == NETCONN_SHUT_RDWR) {
  778. close = 1;
  779. } else if (shut_rx &&
  780. ((tpcb->state == FIN_WAIT_1) ||
  781. (tpcb->state == FIN_WAIT_2) ||
  782. (tpcb->state == CLOSING))) {
  783. close = 1;
  784. } else if (shut_tx && ((tpcb->flags & TF_RXCLOSED) != 0)) {
  785. close = 1;
  786. } else {
  787. close = 0;
  788. }
  789. /* Set back some callback pointers */
  790. if (close) {
  791. tcp_arg(tpcb, NULL);
  792. }
  793. if (tpcb->state == LISTEN) {
  794. tcp_accept(tpcb, NULL);
  795. } else {
  796. /* some callbacks have to be reset if tcp_close is not successful */
  797. if (shut_rx) {
  798. tcp_recv(tpcb, NULL);
  799. tcp_accept(tpcb, NULL);
  800. }
  801. if (shut_tx) {
  802. tcp_sent(tpcb, NULL);
  803. }
  804. if (close) {
  805. tcp_poll(tpcb, NULL, 0);
  806. tcp_err(tpcb, NULL);
  807. }
  808. }
  809. /* Try to close the connection */
  810. if (close) {
  811. #if LWIP_SO_LINGER
  812. /* check linger possibilites before calling tcp_close */
  813. err = ERR_OK;
  814. /* linger enabled/required at all? (i.e. is there untransmitted data left?) */
  815. if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) {
  816. if ((conn->linger == 0)) {
  817. /* data left but linger prevents waiting */
  818. tcp_abort(tpcb);
  819. tpcb = NULL;
  820. } else if (conn->linger > 0) {
  821. /* data left and linger says we should wait */
  822. if (netconn_is_nonblocking(conn)) {
  823. /* data left on a nonblocking netconn -> cannot linger */
  824. err = ERR_WOULDBLOCK;
  825. } else if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >=
  826. (conn->linger * 1000)) {
  827. /* data left but linger timeout has expired (this happens on further
  828. calls to this function through poll_tcp */
  829. tcp_abort(tpcb);
  830. tpcb = NULL;
  831. } else {
  832. /* data left -> need to wait for ACK after successful close */
  833. linger_wait_required = 1;
  834. }
  835. }
  836. }
  837. if ((err == ERR_OK) && (tpcb != NULL))
  838. #endif /* LWIP_SO_LINGER */
  839. {
  840. err = tcp_close(tpcb);
  841. }
  842. } else {
  843. err = tcp_shutdown(tpcb, shut_rx, shut_tx);
  844. }
  845. if (err == ERR_OK) {
  846. close_finished = 1;
  847. #if LWIP_SO_LINGER
  848. if (linger_wait_required) {
  849. /* wait for ACK of all unsent/unacked data by just getting called again */
  850. close_finished = 0;
  851. err = ERR_INPROGRESS;
  852. }
  853. #endif /* LWIP_SO_LINGER */
  854. } else {
  855. if (err == ERR_MEM) {
  856. /* Closing failed because of memory shortage */
  857. if (netconn_is_nonblocking(conn)) {
  858. /* Nonblocking close failed */
  859. close_finished = 1;
  860. err = ERR_WOULDBLOCK;
  861. } else {
  862. /* Blocking close, check the timeout */
  863. #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
  864. s32_t close_timeout = LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT;
  865. /* this is kind of an lwip addition to the standard sockets: we wait
  866. for some time when failing to allocate a segment for the FIN */
  867. #if LWIP_SO_SNDTIMEO
  868. if (conn->send_timeout > 0) {
  869. close_timeout = conn->send_timeout;
  870. }
  871. #endif /* LWIP_SO_SNDTIMEO */
  872. #if LWIP_SO_LINGER
  873. if (conn->linger >= 0) {
  874. /* use linger timeout (seconds) */
  875. close_timeout = conn->linger * 1000U;
  876. }
  877. #endif
  878. if ((s32_t)(sys_now() - conn->current_msg->msg.sd.time_started) >= close_timeout) {
  879. #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
  880. if (conn->current_msg->msg.sd.polls_left == 0) {
  881. #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
  882. close_finished = 1;
  883. if (close) {
  884. /* in this case, we want to RST the connection */
  885. tcp_abort(tpcb);
  886. err = ERR_OK;
  887. }
  888. }
  889. }
  890. } else {
  891. /* Closing failed for a non-memory error: give up */
  892. close_finished = 1;
  893. }
  894. }
  895. if (close_finished) {
  896. /* Closing done (succeeded, non-memory error, nonblocking error or timeout) */
  897. sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
  898. conn->current_msg->err = err;
  899. conn->state = NETCONN_NONE;
  900. if (err == ERR_OK) {
  901. if (close) {
  902. /* Set back some callback pointers as conn is going away */
  903. conn->pcb.tcp = NULL;
  904. /* Trigger select() in socket layer. Make sure everybody notices activity
  905. on the connection, error first! */
  906. API_EVENT(conn, NETCONN_EVT_ERROR, 0);
  907. }
  908. if (shut_rx) {
  909. API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);
  910. }
  911. if (shut_tx) {
  912. API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
  913. }
  914. }
  915. NETCONN_SET_SAFE_ERR(conn, err);
  916. #if LWIP_TCPIP_CORE_LOCKING
  917. if (delayed)
  918. #endif
  919. {
  920. /* wake up the application task */
  921. #if ESP_LWIP
  922. if (sig_close) {
  923. conn->current_msg = NULL;
  924. sys_sem_signal(op_completed_sem);
  925. }
  926. #else
  927. conn->current_msg = NULL;
  928. sys_sem_signal(op_completed_sem);
  929. #endif
  930. }
  931. return ERR_OK;
  932. }
  933. if (!close_finished) {
  934. /* Closing failed and we want to wait: restore some of the callbacks */
  935. /* Closing of listen pcb will never fail! */
  936. LWIP_ASSERT("Closing a listen pcb may not fail!", (tpcb->state != LISTEN));
  937. if (shut_tx) {
  938. tcp_sent(tpcb, sent_tcp);
  939. }
  940. /* when waiting for close, set up poll interval to 500ms */
  941. tcp_poll(tpcb, poll_tcp, 1);
  942. tcp_err(tpcb, err_tcp);
  943. tcp_arg(tpcb, conn);
  944. /* don't restore recv callback: we don't want to receive any more data */
  945. }
  946. /* If closing didn't succeed, we get called again either
  947. from poll_tcp or from sent_tcp */
  948. LWIP_ASSERT("err != ERR_OK", err != ERR_OK);
  949. return err;
  950. }
  951. #endif /* LWIP_TCP */
  952. /**
  953. * Delete the pcb inside a netconn.
  954. * Called from netconn_delete.
  955. *
  956. * @param msg the api_msg_msg pointing to the connection
  957. */
  958. void
  959. lwip_netconn_do_delconn(void *m)
  960. {
  961. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  962. enum netconn_state state = msg->conn->state;
  963. LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */
  964. (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP));
  965. msg->err = ERR_OK;
  966. #if LWIP_NETCONN_FULLDUPLEX
  967. /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */
  968. if (state != NETCONN_NONE) {
  969. if ((state == NETCONN_WRITE) ||
  970. ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) {
  971. /* close requested, abort running write/connect */
  972. sys_sem_t* op_completed_sem;
  973. LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
  974. op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
  975. msg->conn->current_msg->err = ERR_CLSD;
  976. msg->conn->current_msg = NULL;
  977. msg->conn->write_offset = 0;
  978. msg->conn->state = NETCONN_NONE;
  979. NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD);
  980. msg->err = ERR_INPROGRESS;
  981. sys_sem_signal(op_completed_sem);
  982. }
  983. }
  984. #else /* LWIP_NETCONN_FULLDUPLEX */
  985. if (((state != NETCONN_NONE) &&
  986. (state != NETCONN_LISTEN) &&
  987. (state != NETCONN_CONNECT)) ||
  988. ((state == NETCONN_CONNECT) && !IN_NONBLOCKING_CONNECT(msg->conn))) {
  989. /* This means either a blocking write or blocking connect is running
  990. (nonblocking write returns and sets state to NONE) */
  991. msg->err = ERR_INPROGRESS;
  992. } else
  993. #endif /* LWIP_NETCONN_FULLDUPLEX */
  994. {
  995. /* Drain and delete mboxes */
  996. netconn_drain(msg->conn);
  997. if (msg->conn->pcb.tcp != NULL) {
  998. switch (NETCONNTYPE_GROUP(msg->conn->type)) {
  999. #if LWIP_RAW
  1000. case NETCONN_RAW:
  1001. raw_remove(msg->conn->pcb.raw);
  1002. break;
  1003. #endif /* LWIP_RAW */
  1004. #if LWIP_UDP
  1005. case NETCONN_UDP:
  1006. msg->conn->pcb.udp->recv_arg = NULL;
  1007. udp_remove(msg->conn->pcb.udp);
  1008. break;
  1009. #endif /* LWIP_UDP */
  1010. #if LWIP_TCP
  1011. case NETCONN_TCP:
  1012. LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
  1013. msg->conn->write_offset == 0);
  1014. msg->conn->state = NETCONN_CLOSE;
  1015. msg->msg.sd.shut = NETCONN_SHUT_RDWR;
  1016. msg->conn->current_msg = msg;
  1017. #if LWIP_TCPIP_CORE_LOCKING
  1018. if (lwip_netconn_do_close_internal(msg->conn, 0, SIG_CLOSE_TRUE) != ERR_OK) {
  1019. LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE);
  1020. UNLOCK_TCPIP_CORE();
  1021. sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
  1022. LOCK_TCPIP_CORE();
  1023. LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
  1024. }
  1025. #else /* LWIP_TCPIP_CORE_LOCKING */
  1026. lwip_netconn_do_close_internal(msg->conn, SIG_CLOSE_TRUE);
  1027. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1028. /* API_EVENT is called inside lwip_netconn_do_close_internal, before releasing
  1029. the application thread, so we can return at this point! */
  1030. return;
  1031. #endif /* LWIP_TCP */
  1032. default:
  1033. break;
  1034. }
  1035. msg->conn->pcb.tcp = NULL;
  1036. }
  1037. /* tcp netconns don't come here! */
  1038. /* @todo: this lets select make the socket readable and writable,
  1039. which is wrong! errfd instead? */
  1040. API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
  1041. API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
  1042. }
  1043. if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) {
  1044. TCPIP_APIMSG_ACK(msg);
  1045. }
  1046. }
  1047. /**
  1048. * Bind a pcb contained in a netconn
  1049. * Called from netconn_bind.
  1050. *
  1051. * @param msg the api_msg_msg pointing to the connection and containing
  1052. * the IP address and port to bind to
  1053. */
  1054. void
  1055. lwip_netconn_do_bind(void *m)
  1056. {
  1057. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1058. if (ERR_IS_FATAL(msg->conn->last_err)) {
  1059. msg->err = msg->conn->last_err;
  1060. } else {
  1061. msg->err = ERR_VAL;
  1062. if (msg->conn->pcb.tcp != NULL) {
  1063. const ip_addr_t *ipaddr = API_EXPR_REF(msg->msg.bc.ipaddr);
  1064. #if LWIP_IPV4 && LWIP_IPV6
  1065. /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
  1066. * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to bind
  1067. */
  1068. if (ip_addr_cmp(ipaddr, IP6_ADDR_ANY) &&
  1069. (netconn_get_ipv6only(msg->conn) == 0)) {
  1070. /* change PCB type to IPADDR_TYPE_ANY */
  1071. IP_SET_TYPE_VAL(msg->conn->pcb.ip->local_ip, IPADDR_TYPE_ANY);
  1072. IP_SET_TYPE_VAL(msg->conn->pcb.ip->remote_ip, IPADDR_TYPE_ANY);
  1073. /* bind to IPADDR_TYPE_ANY */
  1074. ipaddr = IP_ANY_TYPE;
  1075. }
  1076. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  1077. switch (NETCONNTYPE_GROUP(msg->conn->type)) {
  1078. #if LWIP_RAW
  1079. case NETCONN_RAW:
  1080. msg->err = raw_bind(msg->conn->pcb.raw, ipaddr);
  1081. break;
  1082. #endif /* LWIP_RAW */
  1083. #if LWIP_UDP
  1084. case NETCONN_UDP:
  1085. msg->err = udp_bind(msg->conn->pcb.udp, ipaddr, msg->msg.bc.port);
  1086. break;
  1087. #endif /* LWIP_UDP */
  1088. #if LWIP_TCP
  1089. case NETCONN_TCP:
  1090. msg->err = tcp_bind(msg->conn->pcb.tcp, ipaddr, msg->msg.bc.port);
  1091. break;
  1092. #endif /* LWIP_TCP */
  1093. default:
  1094. break;
  1095. }
  1096. }
  1097. }
  1098. TCPIP_APIMSG_ACK(msg);
  1099. }
  1100. #if LWIP_TCP
  1101. /**
  1102. * TCP callback function if a connection (opened by tcp_connect/lwip_netconn_do_connect) has
  1103. * been established (or reset by the remote host).
  1104. *
  1105. * @see tcp.h (struct tcp_pcb.connected) for parameters and return values
  1106. */
  1107. static err_t
  1108. lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
  1109. {
  1110. struct netconn *conn;
  1111. int was_blocking;
  1112. sys_sem_t* op_completed_sem = NULL;
  1113. LWIP_UNUSED_ARG(pcb);
  1114. conn = (struct netconn *)arg;
  1115. if (conn == NULL) {
  1116. return ERR_VAL;
  1117. }
  1118. LWIP_ASSERT("conn->state == NETCONN_CONNECT", conn->state == NETCONN_CONNECT);
  1119. LWIP_ASSERT("(conn->current_msg != NULL) || conn->in_non_blocking_connect",
  1120. (conn->current_msg != NULL) || IN_NONBLOCKING_CONNECT(conn));
  1121. if (conn->current_msg != NULL) {
  1122. conn->current_msg->err = err;
  1123. op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
  1124. }
  1125. if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) {
  1126. setup_tcp(conn);
  1127. }
  1128. was_blocking = !IN_NONBLOCKING_CONNECT(conn);
  1129. SET_NONBLOCKING_CONNECT(conn, 0);
  1130. LWIP_ASSERT("blocking connect state error",
  1131. (was_blocking && op_completed_sem != NULL) ||
  1132. (!was_blocking && op_completed_sem == NULL));
  1133. conn->current_msg = NULL;
  1134. conn->state = NETCONN_NONE;
  1135. NETCONN_SET_SAFE_ERR(conn, ERR_OK);
  1136. API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
  1137. if (was_blocking) {
  1138. sys_sem_signal(op_completed_sem);
  1139. }
  1140. return ERR_OK;
  1141. }
  1142. #endif /* LWIP_TCP */
  1143. /**
  1144. * Connect a pcb contained inside a netconn
  1145. * Called from netconn_connect.
  1146. *
  1147. * @param msg the api_msg_msg pointing to the connection and containing
  1148. * the IP address and port to connect to
  1149. */
  1150. void
  1151. lwip_netconn_do_connect(void *m)
  1152. {
  1153. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1154. if (msg->conn->pcb.tcp == NULL) {
  1155. /* This may happen when calling netconn_connect() a second time */
  1156. msg->err = ERR_CLSD;
  1157. } else {
  1158. switch (NETCONNTYPE_GROUP(msg->conn->type)) {
  1159. #if LWIP_RAW
  1160. case NETCONN_RAW:
  1161. msg->err = raw_connect(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr));
  1162. break;
  1163. #endif /* LWIP_RAW */
  1164. #if LWIP_UDP
  1165. case NETCONN_UDP:
  1166. msg->err = udp_connect(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port);
  1167. break;
  1168. #endif /* LWIP_UDP */
  1169. #if LWIP_TCP
  1170. case NETCONN_TCP:
  1171. /* Prevent connect while doing any other action. */
  1172. if (msg->conn->state == NETCONN_CONNECT) {
  1173. msg->err = ERR_ALREADY;
  1174. } else if (msg->conn->state != NETCONN_NONE) {
  1175. msg->err = ERR_ISCONN;
  1176. } else {
  1177. setup_tcp(msg->conn);
  1178. msg->err = tcp_connect(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr),
  1179. msg->msg.bc.port, lwip_netconn_do_connected);
  1180. if (msg->err == ERR_OK) {
  1181. u8_t non_blocking = netconn_is_nonblocking(msg->conn);
  1182. msg->conn->state = NETCONN_CONNECT;
  1183. SET_NONBLOCKING_CONNECT(msg->conn, non_blocking);
  1184. if (non_blocking) {
  1185. msg->err = ERR_INPROGRESS;
  1186. } else {
  1187. msg->conn->current_msg = msg;
  1188. /* sys_sem_signal() is called from lwip_netconn_do_connected (or err_tcp()),
  1189. when the connection is established! */
  1190. #if LWIP_TCPIP_CORE_LOCKING
  1191. LWIP_ASSERT("state!", msg->conn->state == NETCONN_CONNECT);
  1192. UNLOCK_TCPIP_CORE();
  1193. sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
  1194. LOCK_TCPIP_CORE();
  1195. LWIP_ASSERT("state!", msg->conn->state != NETCONN_CONNECT);
  1196. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1197. return;
  1198. }
  1199. }
  1200. }
  1201. break;
  1202. #endif /* LWIP_TCP */
  1203. default:
  1204. LWIP_ERROR("Invalid netconn type", 0, do{ msg->err = ERR_VAL; }while(0));
  1205. break;
  1206. }
  1207. }
  1208. /* For all other protocols, netconn_connect() calls TCPIP_APIMSG(),
  1209. so use TCPIP_APIMSG_ACK() here. */
  1210. TCPIP_APIMSG_ACK(msg);
  1211. }
  1212. /**
  1213. * Disconnect a pcb contained inside a netconn
  1214. * Only used for UDP netconns.
  1215. * Called from netconn_disconnect.
  1216. *
  1217. * @param msg the api_msg_msg pointing to the connection to disconnect
  1218. */
  1219. void
  1220. lwip_netconn_do_disconnect(void *m)
  1221. {
  1222. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1223. #if LWIP_UDP
  1224. if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
  1225. udp_disconnect(msg->conn->pcb.udp);
  1226. msg->err = ERR_OK;
  1227. } else
  1228. #endif /* LWIP_UDP */
  1229. {
  1230. msg->err = ERR_VAL;
  1231. }
  1232. TCPIP_APIMSG_ACK(msg);
  1233. }
  1234. #if LWIP_TCP
  1235. /**
  1236. * Set a TCP pcb contained in a netconn into listen mode
  1237. * Called from netconn_listen.
  1238. *
  1239. * @param msg the api_msg_msg pointing to the connection
  1240. */
  1241. void
  1242. lwip_netconn_do_listen(void *m)
  1243. {
  1244. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1245. if (ERR_IS_FATAL(msg->conn->last_err)) {
  1246. msg->err = msg->conn->last_err;
  1247. } else {
  1248. msg->err = ERR_CONN;
  1249. if (msg->conn->pcb.tcp != NULL) {
  1250. if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
  1251. if (msg->conn->state == NETCONN_NONE) {
  1252. struct tcp_pcb* lpcb;
  1253. if (msg->conn->pcb.tcp->state != CLOSED) {
  1254. /* connection is not closed, cannot listen */
  1255. msg->err = ERR_VAL;
  1256. } else {
  1257. #if LWIP_IPV4 && LWIP_IPV6
  1258. /* "Socket API like" dual-stack support: If IP to listen to is IP6_ADDR_ANY,
  1259. * and NETCONN_FLAG_IPV6_V6ONLY is NOT set, use IP_ANY_TYPE to listen
  1260. */
  1261. if (ip_addr_cmp(&msg->conn->pcb.ip->local_ip, IP6_ADDR_ANY) &&
  1262. (netconn_get_ipv6only(msg->conn) == 0)) {
  1263. /* change PCB type to IPADDR_TYPE_ANY */
  1264. IP_SET_TYPE_VAL(msg->conn->pcb.tcp->local_ip, IPADDR_TYPE_ANY);
  1265. IP_SET_TYPE_VAL(msg->conn->pcb.tcp->remote_ip, IPADDR_TYPE_ANY);
  1266. }
  1267. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  1268. #if TCP_LISTEN_BACKLOG
  1269. lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
  1270. #else /* TCP_LISTEN_BACKLOG */
  1271. lpcb = tcp_listen(msg->conn->pcb.tcp);
  1272. #endif /* TCP_LISTEN_BACKLOG */
  1273. if (lpcb == NULL) {
  1274. /* in this case, the old pcb is still allocated */
  1275. msg->err = ERR_MEM;
  1276. } else {
  1277. /* delete the recvmbox and allocate the acceptmbox */
  1278. if (sys_mbox_valid(&msg->conn->recvmbox)) {
  1279. /** @todo: should we drain the recvmbox here? */
  1280. sys_mbox_free(&msg->conn->recvmbox);
  1281. sys_mbox_set_invalid(&msg->conn->recvmbox);
  1282. }
  1283. msg->err = ERR_OK;
  1284. if (!sys_mbox_valid(&msg->conn->acceptmbox)) {
  1285. msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE);
  1286. }
  1287. if (msg->err == ERR_OK) {
  1288. msg->conn->state = NETCONN_LISTEN;
  1289. msg->conn->pcb.tcp = lpcb;
  1290. tcp_arg(msg->conn->pcb.tcp, msg->conn);
  1291. tcp_accept(msg->conn->pcb.tcp, accept_function);
  1292. } else {
  1293. /* since the old pcb is already deallocated, free lpcb now */
  1294. tcp_close(lpcb);
  1295. msg->conn->pcb.tcp = NULL;
  1296. }
  1297. }
  1298. }
  1299. } else if (msg->conn->state == NETCONN_LISTEN) {
  1300. /* already listening, allow updating of the backlog */
  1301. msg->err = ERR_OK;
  1302. #if TCP_LISTEN_BACKLOG
  1303. tcp_backlog_set(msg->conn->pcb.tcp, msg->msg.lb.backlog);
  1304. #endif /* TCP_LISTEN_BACKLOG */
  1305. }
  1306. } else {
  1307. msg->err = ERR_ARG;
  1308. }
  1309. }
  1310. }
  1311. TCPIP_APIMSG_ACK(msg);
  1312. }
  1313. #endif /* LWIP_TCP */
  1314. /**
  1315. * Send some data on a RAW or UDP pcb contained in a netconn
  1316. * Called from netconn_send
  1317. *
  1318. * @param msg the api_msg_msg pointing to the connection
  1319. */
  1320. void ESP_IRAM_ATTR
  1321. lwip_netconn_do_send(void *m)
  1322. {
  1323. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1324. if (ERR_IS_FATAL(msg->conn->last_err)) {
  1325. msg->err = msg->conn->last_err;
  1326. #if LWIP_IPV4 && LWIP_IPV6
  1327. } else if ((msg->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) &&
  1328. IP_IS_V4MAPPEDV6(&msg->msg.b->addr)) {
  1329. LWIP_DEBUGF(API_MSG_DEBUG, ("lwip_netconn_do_send: Dropping IPv4 packet on IPv6-only socket"));
  1330. msg->err = ERR_VAL;
  1331. #endif /* LWIP_IPV4 && LWIP_IPV6 */
  1332. } else {
  1333. msg->err = ERR_CONN;
  1334. if (msg->conn->pcb.tcp != NULL) {
  1335. switch (NETCONNTYPE_GROUP(msg->conn->type)) {
  1336. #if LWIP_RAW
  1337. case NETCONN_RAW:
  1338. if (ip_addr_isany(&msg->msg.b->addr)) {
  1339. msg->err = raw_send(msg->conn->pcb.raw, msg->msg.b->p);
  1340. } else {
  1341. msg->err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr);
  1342. }
  1343. break;
  1344. #endif
  1345. #if LWIP_UDP
  1346. case NETCONN_UDP:
  1347. #if LWIP_CHECKSUM_ON_COPY
  1348. if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
  1349. msg->err = udp_send_chksum(msg->conn->pcb.udp, msg->msg.b->p,
  1350. msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
  1351. } else {
  1352. msg->err = udp_sendto_chksum(msg->conn->pcb.udp, msg->msg.b->p,
  1353. &msg->msg.b->addr, msg->msg.b->port,
  1354. msg->msg.b->flags & NETBUF_FLAG_CHKSUM, msg->msg.b->toport_chksum);
  1355. }
  1356. #else /* LWIP_CHECKSUM_ON_COPY */
  1357. if (ip_addr_isany_val(msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) {
  1358. msg->err = udp_send(msg->conn->pcb.udp, msg->msg.b->p);
  1359. } else {
  1360. msg->err = udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, &msg->msg.b->addr, msg->msg.b->port);
  1361. }
  1362. #endif /* LWIP_CHECKSUM_ON_COPY */
  1363. break;
  1364. #endif /* LWIP_UDP */
  1365. default:
  1366. break;
  1367. }
  1368. }
  1369. }
  1370. TCPIP_APIMSG_ACK(msg);
  1371. }
  1372. #if LWIP_TCP
  1373. /**
  1374. * Indicate data has been received from a TCP pcb contained in a netconn
  1375. * Called from netconn_recv
  1376. *
  1377. * @param msg the api_msg_msg pointing to the connection
  1378. */
  1379. void
  1380. lwip_netconn_do_recv(void *m)
  1381. {
  1382. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1383. msg->err = ERR_OK;
  1384. if (msg->conn->pcb.tcp != NULL) {
  1385. if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
  1386. #if TCP_LISTEN_BACKLOG
  1387. if (msg->conn->pcb.tcp->state == LISTEN) {
  1388. tcp_accepted(msg->conn->pcb.tcp);
  1389. } else
  1390. #endif /* TCP_LISTEN_BACKLOG */
  1391. {
  1392. u32_t remaining = msg->msg.r.len;
  1393. do {
  1394. u16_t recved = (remaining > 0xffff) ? 0xffff : (u16_t)remaining;
  1395. tcp_recved(msg->conn->pcb.tcp, recved);
  1396. remaining -= recved;
  1397. } while (remaining != 0);
  1398. }
  1399. }
  1400. }
  1401. TCPIP_APIMSG_ACK(msg);
  1402. }
  1403. /**
  1404. * See if more data needs to be written from a previous call to netconn_write.
  1405. * Called initially from lwip_netconn_do_write. If the first call can't send all data
  1406. * (because of low memory or empty send-buffer), this function is called again
  1407. * from sent_tcp() or poll_tcp() to send more data. If all data is sent, the
  1408. * blocking application thread (waiting in netconn_write) is released.
  1409. *
  1410. * @param conn netconn (that is currently in state NETCONN_WRITE) to process
  1411. * [@param delay 1 if called from sent/poll (wake up calling thread on end)]
  1412. * @return ERR_OK
  1413. * ERR_MEM if LWIP_TCPIP_CORE_LOCKING=1 and sending hasn't yet finished
  1414. */
  1415. static err_t
  1416. lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM)
  1417. {
  1418. err_t err;
  1419. const void *dataptr;
  1420. u16_t len, available;
  1421. u8_t write_finished = 0;
  1422. size_t diff;
  1423. u8_t dontblock;
  1424. u8_t apiflags;
  1425. LWIP_ASSERT("conn != NULL", conn != NULL);
  1426. LWIP_ASSERT("conn->state == NETCONN_WRITE", (conn->state == NETCONN_WRITE));
  1427. LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
  1428. LWIP_ASSERT("conn->pcb.tcp != NULL", conn->pcb.tcp != NULL);
  1429. LWIP_ASSERT("conn->write_offset < conn->current_msg->msg.w.len",
  1430. conn->write_offset < conn->current_msg->msg.w.len);
  1431. dontblock = netconn_is_nonblocking(conn) ||
  1432. (conn->current_msg->msg.w.apiflags & NETCONN_DONTBLOCK);
  1433. apiflags = conn->current_msg->msg.w.apiflags;
  1434. #if LWIP_SO_SNDTIMEO
  1435. if ((conn->send_timeout != 0) &&
  1436. ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) {
  1437. write_finished = 1;
  1438. if (conn->write_offset == 0) {
  1439. /* nothing has been written */
  1440. err = ERR_WOULDBLOCK;
  1441. conn->current_msg->msg.w.len = 0;
  1442. } else {
  1443. /* partial write */
  1444. err = ERR_OK;
  1445. conn->current_msg->msg.w.len = conn->write_offset;
  1446. conn->write_offset = 0;
  1447. }
  1448. } else
  1449. #endif /* LWIP_SO_SNDTIMEO */
  1450. {
  1451. dataptr = (const u8_t*)conn->current_msg->msg.w.dataptr + conn->write_offset;
  1452. diff = conn->current_msg->msg.w.len - conn->write_offset;
  1453. if (diff > 0xffffUL) { /* max_u16_t */
  1454. len = 0xffff;
  1455. apiflags |= TCP_WRITE_FLAG_MORE;
  1456. } else {
  1457. len = (u16_t)diff;
  1458. }
  1459. available = tcp_sndbuf(conn->pcb.tcp);
  1460. if (available < len) {
  1461. /* don't try to write more than sendbuf */
  1462. len = available;
  1463. if (dontblock) {
  1464. if (!len) {
  1465. err = ERR_WOULDBLOCK;
  1466. goto err_mem;
  1467. }
  1468. } else {
  1469. apiflags |= TCP_WRITE_FLAG_MORE;
  1470. }
  1471. }
  1472. LWIP_ASSERT("lwip_netconn_do_writemore: invalid length!", ((conn->write_offset + len) <= conn->current_msg->msg.w.len));
  1473. err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags);
  1474. /* if OK or memory error, check available space */
  1475. if ((err == ERR_OK) || (err == ERR_MEM)) {
  1476. err_mem:
  1477. if (dontblock && (len < conn->current_msg->msg.w.len)) {
  1478. /* non-blocking write did not write everything: mark the pcb non-writable
  1479. and let poll_tcp check writable space to mark the pcb writable again */
  1480. API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
  1481. conn->flags |= NETCONN_FLAG_CHECK_WRITESPACE;
  1482. } else if ((tcp_sndbuf(conn->pcb.tcp) <= TCP_SNDLOWAT(conn->pcb.tcp)) ||
  1483. (tcp_sndqueuelen(conn->pcb.tcp) >= TCP_SNDQUEUELOWAT(conn->pcb.tcp))) {
  1484. /* The queued byte- or pbuf-count exceeds the configured low-water limit,
  1485. let select mark this pcb as non-writable. */
  1486. API_EVENT(conn, NETCONN_EVT_SENDMINUS, len);
  1487. }
  1488. }
  1489. if (err == ERR_OK) {
  1490. err_t out_err;
  1491. conn->write_offset += len;
  1492. if ((conn->write_offset == conn->current_msg->msg.w.len) || dontblock) {
  1493. /* return sent length */
  1494. conn->current_msg->msg.w.len = conn->write_offset;
  1495. /* everything was written */
  1496. write_finished = 1;
  1497. }
  1498. out_err = tcp_output(conn->pcb.tcp);
  1499. if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) {
  1500. /* If tcp_output fails with fatal error or no route is found,
  1501. don't try writing any more but return the error
  1502. to the application thread. */
  1503. err = out_err;
  1504. write_finished = 1;
  1505. conn->current_msg->msg.w.len = 0;
  1506. }
  1507. } else if ((err == ERR_MEM) && !dontblock) {
  1508. /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
  1509. we do NOT return to the application thread, since ERR_MEM is
  1510. only a temporary error! */
  1511. /* tcp_write returned ERR_MEM, try tcp_output anyway */
  1512. err_t out_err = tcp_output(conn->pcb.tcp);
  1513. if (ERR_IS_FATAL(out_err) || (out_err == ERR_RTE)) {
  1514. /* If tcp_output fails with fatal error or no route is found,
  1515. don't try writing any more but return the error
  1516. to the application thread. */
  1517. err = out_err;
  1518. write_finished = 1;
  1519. conn->current_msg->msg.w.len = 0;
  1520. } else {
  1521. }
  1522. } else {
  1523. /* On errors != ERR_MEM, we don't try writing any more but return
  1524. the error to the application thread. */
  1525. write_finished = 1;
  1526. conn->current_msg->msg.w.len = 0;
  1527. }
  1528. }
  1529. if (write_finished) {
  1530. /* everything was written: set back connection state
  1531. and back to application task */
  1532. sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
  1533. conn->current_msg->err = err;
  1534. conn->current_msg = NULL;
  1535. conn->write_offset = 0;
  1536. conn->state = NETCONN_NONE;
  1537. NETCONN_SET_SAFE_ERR(conn, err);
  1538. #if LWIP_TCPIP_CORE_LOCKING
  1539. if (delayed)
  1540. #endif
  1541. {
  1542. sys_sem_signal(op_completed_sem);
  1543. }
  1544. }
  1545. #if LWIP_TCPIP_CORE_LOCKING
  1546. else {
  1547. return ERR_MEM;
  1548. }
  1549. #endif
  1550. return ERR_OK;
  1551. }
  1552. #endif /* LWIP_TCP */
  1553. /**
  1554. * Send some data on a TCP pcb contained in a netconn
  1555. * Called from netconn_write
  1556. *
  1557. * @param msg the api_msg_msg pointing to the connection
  1558. */
  1559. void
  1560. lwip_netconn_do_write(void *m)
  1561. {
  1562. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1563. if (ERR_IS_FATAL(msg->conn->last_err)) {
  1564. msg->err = msg->conn->last_err;
  1565. } else {
  1566. if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
  1567. #if LWIP_TCP
  1568. if (msg->conn->state != NETCONN_NONE) {
  1569. /* netconn is connecting, closing or in blocking write */
  1570. msg->err = ERR_INPROGRESS;
  1571. } else if (msg->conn->pcb.tcp != NULL) {
  1572. msg->conn->state = NETCONN_WRITE;
  1573. /* set all the variables used by lwip_netconn_do_writemore */
  1574. LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
  1575. msg->conn->write_offset == 0);
  1576. LWIP_ASSERT("msg->msg.w.len != 0", msg->msg.w.len != 0);
  1577. msg->conn->current_msg = msg;
  1578. msg->conn->write_offset = 0;
  1579. #if LWIP_TCPIP_CORE_LOCKING
  1580. if (lwip_netconn_do_writemore(msg->conn, 0) != ERR_OK) {
  1581. LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
  1582. UNLOCK_TCPIP_CORE();
  1583. sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
  1584. LOCK_TCPIP_CORE();
  1585. LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE);
  1586. }
  1587. #else /* LWIP_TCPIP_CORE_LOCKING */
  1588. lwip_netconn_do_writemore(msg->conn);
  1589. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1590. /* for both cases: if lwip_netconn_do_writemore was called, don't ACK the APIMSG
  1591. since lwip_netconn_do_writemore ACKs it! */
  1592. return;
  1593. } else {
  1594. msg->err = ERR_CONN;
  1595. }
  1596. #else /* LWIP_TCP */
  1597. msg->err = ERR_VAL;
  1598. #endif /* LWIP_TCP */
  1599. #if (LWIP_UDP || LWIP_RAW)
  1600. } else {
  1601. msg->err = ERR_VAL;
  1602. #endif /* (LWIP_UDP || LWIP_RAW) */
  1603. }
  1604. }
  1605. TCPIP_APIMSG_ACK(msg);
  1606. }
  1607. /**
  1608. * Return a connection's local or remote address
  1609. * Called from netconn_getaddr
  1610. *
  1611. * @param msg the api_msg_msg pointing to the connection
  1612. */
  1613. void
  1614. lwip_netconn_do_getaddr(void *m)
  1615. {
  1616. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1617. if (msg->conn->pcb.ip != NULL) {
  1618. if (msg->msg.ad.local) {
  1619. ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
  1620. msg->conn->pcb.ip->local_ip);
  1621. } else {
  1622. ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr),
  1623. msg->conn->pcb.ip->remote_ip);
  1624. }
  1625. msg->err = ERR_OK;
  1626. switch (NETCONNTYPE_GROUP(msg->conn->type)) {
  1627. #if LWIP_RAW
  1628. case NETCONN_RAW:
  1629. if (msg->msg.ad.local) {
  1630. API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol;
  1631. } else {
  1632. /* return an error as connecting is only a helper for upper layers */
  1633. msg->err = ERR_CONN;
  1634. }
  1635. break;
  1636. #endif /* LWIP_RAW */
  1637. #if LWIP_UDP
  1638. case NETCONN_UDP:
  1639. if (msg->msg.ad.local) {
  1640. API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->local_port;
  1641. } else {
  1642. if ((msg->conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0) {
  1643. msg->err = ERR_CONN;
  1644. } else {
  1645. API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.udp->remote_port;
  1646. }
  1647. }
  1648. break;
  1649. #endif /* LWIP_UDP */
  1650. #if LWIP_TCP
  1651. case NETCONN_TCP:
  1652. if ((msg->msg.ad.local == 0) &&
  1653. ((msg->conn->pcb.tcp->state == CLOSED) || (msg->conn->pcb.tcp->state == LISTEN))) {
  1654. /* pcb is not connected and remote name is requested */
  1655. msg->err = ERR_CONN;
  1656. } else {
  1657. API_EXPR_DEREF(msg->msg.ad.port) = (msg->msg.ad.local ? msg->conn->pcb.tcp->local_port : msg->conn->pcb.tcp->remote_port);
  1658. }
  1659. break;
  1660. #endif /* LWIP_TCP */
  1661. default:
  1662. LWIP_ASSERT("invalid netconn_type", 0);
  1663. break;
  1664. }
  1665. } else {
  1666. msg->err = ERR_CONN;
  1667. }
  1668. TCPIP_APIMSG_ACK(msg);
  1669. }
  1670. /**
  1671. * Close or half-shutdown a TCP pcb contained in a netconn
  1672. * Called from netconn_close
  1673. * In contrast to closing sockets, the netconn is not deallocated.
  1674. *
  1675. * @param msg the api_msg_msg pointing to the connection
  1676. */
  1677. void
  1678. lwip_netconn_do_close(void *m)
  1679. {
  1680. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1681. #if LWIP_TCP
  1682. enum netconn_state state = msg->conn->state;
  1683. /* First check if this is a TCP netconn and if it is in a correct state
  1684. (LISTEN doesn't support half shutdown) */
  1685. if ((msg->conn->pcb.tcp != NULL) &&
  1686. (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) &&
  1687. ((msg->msg.sd.shut == NETCONN_SHUT_RDWR) || (state != NETCONN_LISTEN))) {
  1688. /* Check if we are in a connected state */
  1689. if (state == NETCONN_CONNECT) {
  1690. /* TCP connect in progress: cannot shutdown */
  1691. msg->err = ERR_CONN;
  1692. } else if (state == NETCONN_WRITE) {
  1693. #if LWIP_NETCONN_FULLDUPLEX
  1694. if (msg->msg.sd.shut & NETCONN_SHUT_WR) {
  1695. /* close requested, abort running write */
  1696. sys_sem_t* op_completed_sem;
  1697. LWIP_ASSERT("msg->conn->current_msg != NULL", msg->conn->current_msg != NULL);
  1698. op_completed_sem = LWIP_API_MSG_SEM(msg->conn->current_msg);
  1699. msg->conn->current_msg->err = ERR_CLSD;
  1700. msg->conn->current_msg = NULL;
  1701. msg->conn->write_offset = 0;
  1702. msg->conn->state = NETCONN_NONE;
  1703. NETCONN_SET_SAFE_ERR(msg->conn, ERR_CLSD);
  1704. sys_sem_signal(op_completed_sem);
  1705. } else {
  1706. LWIP_ASSERT("msg->msg.sd.shut == NETCONN_SHUT_RD", msg->msg.sd.shut == NETCONN_SHUT_RD);
  1707. /* In this case, let the write continue and do not interfere with
  1708. conn->current_msg or conn->state! */
  1709. msg->err = tcp_shutdown(msg->conn->pcb.tcp, 1, 0);
  1710. }
  1711. #else /* LWIP_NETCONN_FULLDUPLEX */
  1712. msg->err = ERR_INPROGRESS;
  1713. #endif /* LWIP_NETCONN_FULLDUPLEX */
  1714. } else {
  1715. if (msg->msg.sd.shut & NETCONN_SHUT_RD) {
  1716. /* Drain and delete mboxes */
  1717. netconn_drain(msg->conn);
  1718. }
  1719. LWIP_ASSERT("already writing or closing", msg->conn->current_msg == NULL &&
  1720. msg->conn->write_offset == 0);
  1721. msg->conn->state = NETCONN_CLOSE;
  1722. msg->conn->current_msg = msg;
  1723. #if LWIP_TCPIP_CORE_LOCKING
  1724. if (lwip_netconn_do_close_internal(msg->conn, 0, SIG_CLOSE_TRUE) != ERR_OK) {
  1725. LWIP_ASSERT("state!", msg->conn->state == NETCONN_CLOSE);
  1726. UNLOCK_TCPIP_CORE();
  1727. sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
  1728. LOCK_TCPIP_CORE();
  1729. LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
  1730. }
  1731. #else /* LWIP_TCPIP_CORE_LOCKING */
  1732. lwip_netconn_do_close_internal(msg->conn, SIG_CLOSE_TRUE);
  1733. #endif /* LWIP_TCPIP_CORE_LOCKING */
  1734. /* for tcp netconns, lwip_netconn_do_close_internal ACKs the message */
  1735. return;
  1736. }
  1737. } else
  1738. #endif /* LWIP_TCP */
  1739. {
  1740. msg->err = ERR_CONN;
  1741. }
  1742. TCPIP_APIMSG_ACK(msg);
  1743. }
  1744. #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
  1745. /**
  1746. * Join multicast groups for UDP netconns.
  1747. * Called from netconn_join_leave_group
  1748. *
  1749. * @param msg the api_msg_msg pointing to the connection
  1750. */
  1751. void
  1752. lwip_netconn_do_join_leave_group(void *m)
  1753. {
  1754. struct api_msg_msg *msg = (struct api_msg_msg*)m;
  1755. if (ERR_IS_FATAL(msg->conn->last_err)) {
  1756. msg->err = msg->conn->last_err;
  1757. } else {
  1758. if (msg->conn->pcb.tcp != NULL) {
  1759. if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_UDP) {
  1760. #if LWIP_UDP
  1761. #if LWIP_IPV6 && LWIP_IPV6_MLD
  1762. if (NETCONNTYPE_ISIPV6(msg->conn->type)) {
  1763. if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
  1764. msg->err = mld6_joingroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
  1765. ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
  1766. } else {
  1767. msg->err = mld6_leavegroup(ip_2_ip6(API_EXPR_REF(msg->msg.jl.netif_addr)),
  1768. ip_2_ip6(API_EXPR_REF(msg->msg.jl.multiaddr)));
  1769. }
  1770. }
  1771. else
  1772. #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
  1773. {
  1774. #if LWIP_IGMP
  1775. if (msg->msg.jl.join_or_leave == NETCONN_JOIN) {
  1776. msg->err = igmp_joingroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)),
  1777. ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
  1778. } else {
  1779. msg->err = igmp_leavegroup(ip_2_ip4(API_EXPR_REF(msg->msg.jl.netif_addr)),
  1780. ip_2_ip4(API_EXPR_REF(msg->msg.jl.multiaddr)));
  1781. }
  1782. #endif /* LWIP_IGMP */
  1783. }
  1784. #endif /* LWIP_UDP */
  1785. #if (LWIP_TCP || LWIP_RAW)
  1786. } else {
  1787. msg->err = ERR_VAL;
  1788. #endif /* (LWIP_TCP || LWIP_RAW) */
  1789. }
  1790. } else {
  1791. msg->err = ERR_CONN;
  1792. }
  1793. }
  1794. TCPIP_APIMSG_ACK(msg);
  1795. }
  1796. #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
  1797. #if LWIP_DNS
  1798. /**
  1799. * Callback function that is called when DNS name is resolved
  1800. * (or on timeout). A waiting application thread is waked up by
  1801. * signaling the semaphore.
  1802. */
  1803. static void
  1804. lwip_netconn_do_dns_found(const char *name, const ip_addr_t *ipaddr, void *arg)
  1805. {
  1806. struct dns_api_msg *msg = (struct dns_api_msg*)arg;
  1807. /* we trust the internal implementation to be correct :-) */
  1808. LWIP_UNUSED_ARG(name);
  1809. if (ipaddr == NULL) {
  1810. /* timeout or memory error */
  1811. API_EXPR_DEREF(msg->err) = ERR_VAL;
  1812. } else {
  1813. /* address was resolved */
  1814. API_EXPR_DEREF(msg->err) = ERR_OK;
  1815. API_EXPR_DEREF(msg->addr) = *ipaddr;
  1816. }
  1817. /* wake up the application task waiting in netconn_gethostbyname */
  1818. sys_sem_signal(API_EXPR_REF_SEM(msg->sem));
  1819. }
  1820. /**
  1821. * Execute a DNS query
  1822. * Called from netconn_gethostbyname
  1823. *
  1824. * @param arg the dns_api_msg pointing to the query
  1825. */
  1826. void
  1827. lwip_netconn_do_gethostbyname(void *arg)
  1828. {
  1829. struct dns_api_msg *msg = (struct dns_api_msg*)arg;
  1830. u8_t addrtype =
  1831. #if LWIP_IPV4 && LWIP_IPV6
  1832. msg->dns_addrtype;
  1833. #else
  1834. LWIP_DNS_ADDRTYPE_DEFAULT;
  1835. #endif
  1836. API_EXPR_DEREF(msg->err) = dns_gethostbyname_addrtype(msg->name,
  1837. API_EXPR_REF(msg->addr), lwip_netconn_do_dns_found, msg, addrtype);
  1838. if (API_EXPR_DEREF(msg->err) != ERR_INPROGRESS) {
  1839. /* on error or immediate success, wake up the application
  1840. * task waiting in netconn_gethostbyname */
  1841. sys_sem_signal(API_EXPR_REF_SEM(msg->sem));
  1842. }
  1843. }
  1844. #endif /* LWIP_DNS */
  1845. #endif /* LWIP_NETCONN */