api_lib.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /**
  2. * @file
  3. * Sequential API External 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. /* This is the part of the API that is linked with
  38. the application */
  39. #include "lwip/opt.h"
  40. #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
  41. #include "lwip/api.h"
  42. #include "lwip/tcpip.h"
  43. #include "lwip/memp.h"
  44. #include "lwip/ip.h"
  45. #include "lwip/raw.h"
  46. #include "lwip/udp.h"
  47. #include "lwip/tcp.h"
  48. #include <string.h>
  49. /**
  50. * Create a new netconn (of a specific type) that has a callback function.
  51. * The corresponding pcb is also created.
  52. *
  53. * @param t the type of 'connection' to create (@see enum netconn_type)
  54. * @param proto the IP protocol for RAW IP pcbs
  55. * @param callback a function to call on status changes (RX available, TX'ed)
  56. * @return a newly allocated struct netconn or
  57. * NULL on memory error
  58. */
  59. struct netconn*
  60. netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
  61. {
  62. struct netconn *conn;
  63. struct api_msg msg;
  64. conn = netconn_alloc(t, callback);
  65. if (conn != NULL) {
  66. msg.function = do_newconn;
  67. msg.msg.msg.n.proto = proto;
  68. msg.msg.conn = conn;
  69. if (TCPIP_APIMSG(&msg) != ERR_OK) {
  70. LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
  71. LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
  72. LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
  73. #if LWIP_TCP
  74. LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
  75. #endif /* LWIP_TCP */
  76. sys_sem_free(&conn->op_completed);
  77. sys_mbox_free(&conn->recvmbox);
  78. memp_free(MEMP_NETCONN, conn);
  79. return NULL;
  80. }
  81. }
  82. return conn;
  83. }
  84. /**
  85. * Close a netconn 'connection' and free its resources.
  86. * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
  87. * after this returns.
  88. *
  89. * @param conn the netconn to delete
  90. * @return ERR_OK if the connection was deleted
  91. */
  92. err_t
  93. netconn_delete(struct netconn *conn)
  94. {
  95. struct api_msg msg;
  96. /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
  97. if (conn == NULL) {
  98. return ERR_OK;
  99. }
  100. msg.function = do_delconn;
  101. msg.msg.conn = conn;
  102. tcpip_apimsg(&msg);
  103. netconn_free(conn);
  104. /* don't care for return value of do_delconn since it only calls void functions */
  105. return ERR_OK;
  106. }
  107. /**
  108. * Get the local or remote IP address and port of a netconn.
  109. * For RAW netconns, this returns the protocol instead of a port!
  110. *
  111. * @param conn the netconn to query
  112. * @param addr a pointer to which to save the IP address
  113. * @param port a pointer to which to save the port (or protocol for RAW)
  114. * @param local 1 to get the local IP address, 0 to get the remote one
  115. * @return ERR_CONN for invalid connections
  116. * ERR_OK if the information was retrieved
  117. */
  118. err_t
  119. netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
  120. {
  121. struct api_msg msg;
  122. err_t err;
  123. LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
  124. LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
  125. LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
  126. msg.function = do_getaddr;
  127. msg.msg.conn = conn;
  128. msg.msg.msg.ad.ipaddr = addr;
  129. msg.msg.msg.ad.port = port;
  130. msg.msg.msg.ad.local = local;
  131. err = TCPIP_APIMSG(&msg);
  132. NETCONN_SET_SAFE_ERR(conn, err);
  133. return err;
  134. }
  135. /**
  136. * Bind a netconn to a specific local IP address and port.
  137. * Binding one netconn twice might not always be checked correctly!
  138. *
  139. * @param conn the netconn to bind
  140. * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY
  141. * to bind to all addresses)
  142. * @param port the local port to bind the netconn to (not used for RAW)
  143. * @return ERR_OK if bound, any other err_t on failure
  144. */
  145. err_t
  146. netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
  147. {
  148. struct api_msg msg;
  149. err_t err;
  150. LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
  151. msg.function = do_bind;
  152. msg.msg.conn = conn;
  153. msg.msg.msg.bc.ipaddr = addr;
  154. msg.msg.msg.bc.port = port;
  155. err = TCPIP_APIMSG(&msg);
  156. NETCONN_SET_SAFE_ERR(conn, err);
  157. return err;
  158. }
  159. /**
  160. * Connect a netconn to a specific remote IP address and port.
  161. *
  162. * @param conn the netconn to connect
  163. * @param addr the remote IP address to connect to
  164. * @param port the remote port to connect to (no used for RAW)
  165. * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
  166. */
  167. err_t
  168. netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
  169. {
  170. struct api_msg msg;
  171. err_t err;
  172. LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
  173. msg.function = do_connect;
  174. msg.msg.conn = conn;
  175. msg.msg.msg.bc.ipaddr = addr;
  176. msg.msg.msg.bc.port = port;
  177. /* This is the only function which need to not block tcpip_thread */
  178. err = tcpip_apimsg(&msg);
  179. NETCONN_SET_SAFE_ERR(conn, err);
  180. return err;
  181. }
  182. /**
  183. * Disconnect a netconn from its current peer (only valid for UDP netconns).
  184. *
  185. * @param conn the netconn to disconnect
  186. * @return TODO: return value is not set here...
  187. */
  188. err_t
  189. netconn_disconnect(struct netconn *conn)
  190. {
  191. struct api_msg msg;
  192. err_t err;
  193. LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
  194. msg.function = do_disconnect;
  195. msg.msg.conn = conn;
  196. err = TCPIP_APIMSG(&msg);
  197. NETCONN_SET_SAFE_ERR(conn, err);
  198. return err;
  199. }
  200. /**
  201. * Set a TCP netconn into listen mode
  202. *
  203. * @param conn the tcp netconn to set to listen mode
  204. * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1
  205. * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns
  206. * don't return any error (yet?))
  207. */
  208. err_t
  209. netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
  210. {
  211. #if LWIP_TCP
  212. struct api_msg msg;
  213. err_t err;
  214. /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
  215. LWIP_UNUSED_ARG(backlog);
  216. LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
  217. msg.function = do_listen;
  218. msg.msg.conn = conn;
  219. #if TCP_LISTEN_BACKLOG
  220. msg.msg.msg.lb.backlog = backlog;
  221. #endif /* TCP_LISTEN_BACKLOG */
  222. err = TCPIP_APIMSG(&msg);
  223. NETCONN_SET_SAFE_ERR(conn, err);
  224. return err;
  225. #else /* LWIP_TCP */
  226. LWIP_UNUSED_ARG(conn);
  227. LWIP_UNUSED_ARG(backlog);
  228. return ERR_ARG;
  229. #endif /* LWIP_TCP */
  230. }
  231. /**
  232. * Accept a new connection on a TCP listening netconn.
  233. *
  234. * @param conn the TCP listen netconn
  235. * @param new_conn pointer where the new connection is stored
  236. * @return ERR_OK if a new connection has been received or an error
  237. * code otherwise
  238. */
  239. err_t
  240. netconn_accept(struct netconn *conn, struct netconn **new_conn)
  241. {
  242. #if LWIP_TCP
  243. struct netconn *newconn;
  244. err_t err;
  245. #if TCP_LISTEN_BACKLOG
  246. struct api_msg msg;
  247. #endif /* TCP_LISTEN_BACKLOG */
  248. LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
  249. *new_conn = NULL;
  250. LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
  251. LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;);
  252. err = conn->last_err;
  253. if (ERR_IS_FATAL(err)) {
  254. /* don't recv on fatal errors: this might block the application task
  255. waiting on acceptmbox forever! */
  256. return err;
  257. }
  258. #if LWIP_SO_RCVTIMEO
  259. if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
  260. NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
  261. return ERR_TIMEOUT;
  262. }
  263. #else
  264. sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
  265. #endif /* LWIP_SO_RCVTIMEO*/
  266. /* Register event with callback */
  267. API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
  268. if (newconn == NULL) {
  269. /* connection has been aborted */
  270. NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
  271. return ERR_ABRT;
  272. }
  273. #if TCP_LISTEN_BACKLOG
  274. /* Let the stack know that we have accepted the connection. */
  275. msg.function = do_recv;
  276. msg.msg.conn = conn;
  277. /* don't care for the return value of do_recv */
  278. TCPIP_APIMSG(&msg);
  279. #endif /* TCP_LISTEN_BACKLOG */
  280. *new_conn = newconn;
  281. /* don't set conn->last_err: it's only ERR_OK, anyway */
  282. return ERR_OK;
  283. #else /* LWIP_TCP */
  284. LWIP_UNUSED_ARG(conn);
  285. LWIP_UNUSED_ARG(new_conn);
  286. return ERR_ARG;
  287. #endif /* LWIP_TCP */
  288. }
  289. /**
  290. * Receive data: actual implementation that doesn't care whether pbuf or netbuf
  291. * is received
  292. *
  293. * @param conn the netconn from which to receive data
  294. * @param new_buf pointer where a new pbuf/netbuf is stored when received data
  295. * @return ERR_OK if data has been received, an error code otherwise (timeout,
  296. * memory error or another error)
  297. */
  298. static err_t
  299. netconn_recv_data(struct netconn *conn, void **new_buf)
  300. {
  301. void *buf = NULL;
  302. u16_t len;
  303. err_t err;
  304. #if LWIP_TCP
  305. struct api_msg msg;
  306. #endif /* LWIP_TCP */
  307. LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
  308. *new_buf = NULL;
  309. LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
  310. LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
  311. err = conn->last_err;
  312. if (ERR_IS_FATAL(err)) {
  313. /* don't recv on fatal errors: this might block the application task
  314. waiting on recvmbox forever! */
  315. /* @todo: this does not allow us to fetch data that has been put into recvmbox
  316. before the fatal error occurred - is that a problem? */
  317. return err;
  318. }
  319. #if LWIP_SO_RCVTIMEO
  320. if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
  321. NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
  322. return ERR_TIMEOUT;
  323. }
  324. #else
  325. sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
  326. #endif /* LWIP_SO_RCVTIMEO*/
  327. #if LWIP_TCP
  328. if (conn->type == NETCONN_TCP) {
  329. if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
  330. /* Let the stack know that we have taken the data. */
  331. /* TODO: Speedup: Don't block and wait for the answer here
  332. (to prevent multiple thread-switches). */
  333. msg.function = do_recv;
  334. msg.msg.conn = conn;
  335. if (buf != NULL) {
  336. msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
  337. } else {
  338. msg.msg.msg.r.len = 1;
  339. }
  340. /* don't care for the return value of do_recv */
  341. TCPIP_APIMSG(&msg);
  342. }
  343. /* If we are closed, we indicate that we no longer wish to use the socket */
  344. if (buf == NULL) {
  345. API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
  346. /* Avoid to lose any previous error code */
  347. NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
  348. return ERR_CLSD;
  349. }
  350. len = ((struct pbuf *)buf)->tot_len;
  351. }
  352. #endif /* LWIP_TCP */
  353. #if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
  354. else
  355. #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
  356. #if (LWIP_UDP || LWIP_RAW)
  357. {
  358. LWIP_ASSERT("buf != NULL", buf != NULL);
  359. len = netbuf_len((struct netbuf *)buf);
  360. }
  361. #endif /* (LWIP_UDP || LWIP_RAW) */
  362. #if LWIP_SO_RCVBUF
  363. SYS_ARCH_DEC(conn->recv_avail, len);
  364. #endif /* LWIP_SO_RCVBUF */
  365. /* Register event with callback */
  366. API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
  367. LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
  368. *new_buf = buf;
  369. /* don't set conn->last_err: it's only ERR_OK, anyway */
  370. return ERR_OK;
  371. }
  372. /**
  373. * Receive data (in form of a pbuf) from a TCP netconn
  374. *
  375. * @param conn the netconn from which to receive data
  376. * @param new_buf pointer where a new pbuf is stored when received data
  377. * @return ERR_OK if data has been received, an error code otherwise (timeout,
  378. * memory error or another error)
  379. * ERR_ARG if conn is not a TCP netconn
  380. */
  381. err_t
  382. netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
  383. {
  384. LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
  385. netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
  386. return netconn_recv_data(conn, (void **)new_buf);
  387. }
  388. /**
  389. * Receive data (in form of a netbuf containing a packet buffer) from a netconn
  390. *
  391. * @param conn the netconn from which to receive data
  392. * @param new_buf pointer where a new netbuf is stored when received data
  393. * @return ERR_OK if data has been received, an error code otherwise (timeout,
  394. * memory error or another error)
  395. */
  396. err_t
  397. netconn_recv(struct netconn *conn, struct netbuf **new_buf)
  398. {
  399. #if LWIP_TCP
  400. struct netbuf *buf = NULL;
  401. err_t err;
  402. #endif /* LWIP_TCP */
  403. LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
  404. *new_buf = NULL;
  405. LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
  406. LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
  407. #if LWIP_TCP
  408. if (conn->type == NETCONN_TCP) {
  409. struct pbuf *p = NULL;
  410. /* This is not a listening netconn, since recvmbox is set */
  411. buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
  412. if (buf == NULL) {
  413. NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
  414. return ERR_MEM;
  415. }
  416. err = netconn_recv_data(conn, (void **)&p);
  417. if (err != ERR_OK) {
  418. memp_free(MEMP_NETBUF, buf);
  419. return err;
  420. }
  421. LWIP_ASSERT("p != NULL", p != NULL);
  422. buf->p = p;
  423. buf->ptr = p;
  424. buf->port = 0;
  425. ip_addr_set_any(&buf->addr);
  426. *new_buf = buf;
  427. /* don't set conn->last_err: it's only ERR_OK, anyway */
  428. return ERR_OK;
  429. } else
  430. #endif /* LWIP_TCP */
  431. {
  432. #if (LWIP_UDP || LWIP_RAW)
  433. return netconn_recv_data(conn, (void **)new_buf);
  434. #endif /* (LWIP_UDP || LWIP_RAW) */
  435. }
  436. }
  437. /**
  438. * TCP: update the receive window: by calling this, the application
  439. * tells the stack that it has processed data and is able to accept
  440. * new data.
  441. * ATTENTION: use with care, this is mainly used for sockets!
  442. * Can only be used when calling netconn_set_noautorecved(conn, 1) before.
  443. *
  444. * @param conn the netconn for which to update the receive window
  445. * @param length amount of data processed (ATTENTION: this must be accurate!)
  446. */
  447. void
  448. netconn_recved(struct netconn *conn, u32_t length)
  449. {
  450. #if LWIP_TCP
  451. if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
  452. (netconn_get_noautorecved(conn))) {
  453. struct api_msg msg;
  454. /* Let the stack know that we have taken the data. */
  455. /* TODO: Speedup: Don't block and wait for the answer here
  456. (to prevent multiple thread-switches). */
  457. msg.function = do_recv;
  458. msg.msg.conn = conn;
  459. msg.msg.msg.r.len = length;
  460. /* don't care for the return value of do_recv */
  461. TCPIP_APIMSG(&msg);
  462. }
  463. #else /* LWIP_TCP */
  464. LWIP_UNUSED_ARG(conn);
  465. LWIP_UNUSED_ARG(length);
  466. #endif /* LWIP_TCP */
  467. }
  468. /**
  469. * Send data (in form of a netbuf) to a specific remote IP address and port.
  470. * Only to be used for UDP and RAW netconns (not TCP).
  471. *
  472. * @param conn the netconn over which to send data
  473. * @param buf a netbuf containing the data to send
  474. * @param addr the remote IP address to which to send the data
  475. * @param port the remote port to which to send the data
  476. * @return ERR_OK if data was sent, any other err_t on error
  477. */
  478. err_t
  479. netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
  480. {
  481. if (buf != NULL) {
  482. ip_addr_set(&buf->addr, addr);
  483. buf->port = port;
  484. return netconn_send(conn, buf);
  485. }
  486. return ERR_VAL;
  487. }
  488. /**
  489. * Send data over a UDP or RAW netconn (that is already connected).
  490. *
  491. * @param conn the UDP or RAW netconn over which to send data
  492. * @param buf a netbuf containing the data to send
  493. * @return ERR_OK if data was sent, any other err_t on error
  494. */
  495. err_t
  496. netconn_send(struct netconn *conn, struct netbuf *buf)
  497. {
  498. struct api_msg msg;
  499. err_t err;
  500. LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
  501. LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
  502. msg.function = do_send;
  503. msg.msg.conn = conn;
  504. msg.msg.msg.b = buf;
  505. err = TCPIP_APIMSG(&msg);
  506. NETCONN_SET_SAFE_ERR(conn, err);
  507. return err;
  508. }
  509. /**
  510. * Send data over a TCP netconn.
  511. *
  512. * @param conn the TCP netconn over which to send data
  513. * @param dataptr pointer to the application buffer that contains the data to send
  514. * @param size size of the application data to send
  515. * @param apiflags combination of following flags :
  516. * - NETCONN_COPY: data will be copied into memory belonging to the stack
  517. * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
  518. * - NETCONN_DONTBLOCK: only write the data if all dat can be written at once
  519. * @return ERR_OK if data was sent, any other err_t on error
  520. */
  521. err_t
  522. netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags)
  523. {
  524. struct api_msg msg;
  525. err_t err;
  526. LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
  527. LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;);
  528. if (size == 0) {
  529. return ERR_OK;
  530. }
  531. /* @todo: for non-blocking write, check if 'size' would ever fit into
  532. snd_queue or snd_buf */
  533. msg.function = do_write;
  534. msg.msg.conn = conn;
  535. msg.msg.msg.w.dataptr = dataptr;
  536. msg.msg.msg.w.apiflags = apiflags;
  537. msg.msg.msg.w.len = size;
  538. /* For locking the core: this _can_ be delayed on low memory/low send buffer,
  539. but if it is, this is done inside api_msg.c:do_write(), so we can use the
  540. non-blocking version here. */
  541. err = TCPIP_APIMSG(&msg);
  542. NETCONN_SET_SAFE_ERR(conn, err);
  543. return err;
  544. }
  545. /**
  546. * Close ot shutdown a TCP netconn (doesn't delete it).
  547. *
  548. * @param conn the TCP netconn to close or shutdown
  549. * @param how fully close or only shutdown one side?
  550. * @return ERR_OK if the netconn was closed, any other err_t on error
  551. */
  552. static err_t
  553. netconn_close_shutdown(struct netconn *conn, u8_t how)
  554. {
  555. struct api_msg msg;
  556. err_t err;
  557. LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
  558. msg.function = do_close;
  559. msg.msg.conn = conn;
  560. /* shutting down both ends is the same as closing */
  561. msg.msg.msg.sd.shut = how;
  562. /* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close,
  563. don't use TCPIP_APIMSG here */
  564. err = tcpip_apimsg(&msg);
  565. NETCONN_SET_SAFE_ERR(conn, err);
  566. return err;
  567. }
  568. /**
  569. * Close a TCP netconn (doesn't delete it).
  570. *
  571. * @param conn the TCP netconn to close
  572. * @return ERR_OK if the netconn was closed, any other err_t on error
  573. */
  574. err_t
  575. netconn_close(struct netconn *conn)
  576. {
  577. /* shutting down both ends is the same as closing */
  578. return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
  579. }
  580. /**
  581. * Shut down one or both sides of a TCP netconn (doesn't delete it).
  582. *
  583. * @param conn the TCP netconn to shut down
  584. * @return ERR_OK if the netconn was closed, any other err_t on error
  585. */
  586. err_t
  587. netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
  588. {
  589. return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
  590. }
  591. #if LWIP_IGMP
  592. /**
  593. * Join multicast groups for UDP netconns.
  594. *
  595. * @param conn the UDP netconn for which to change multicast addresses
  596. * @param multiaddr IP address of the multicast group to join or leave
  597. * @param netif_addr the IP address of the network interface on which to send
  598. * the igmp message
  599. * @param join_or_leave flag whether to send a join- or leave-message
  600. * @return ERR_OK if the action was taken, any err_t on error
  601. */
  602. err_t
  603. netconn_join_leave_group(struct netconn *conn,
  604. ip_addr_t *multiaddr,
  605. ip_addr_t *netif_addr,
  606. enum netconn_igmp join_or_leave)
  607. {
  608. struct api_msg msg;
  609. err_t err;
  610. LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
  611. msg.function = do_join_leave_group;
  612. msg.msg.conn = conn;
  613. msg.msg.msg.jl.multiaddr = multiaddr;
  614. msg.msg.msg.jl.netif_addr = netif_addr;
  615. msg.msg.msg.jl.join_or_leave = join_or_leave;
  616. err = TCPIP_APIMSG(&msg);
  617. NETCONN_SET_SAFE_ERR(conn, err);
  618. return err;
  619. }
  620. #endif /* LWIP_IGMP */
  621. #if LWIP_DNS
  622. /**
  623. * Execute a DNS query, only one IP address is returned
  624. *
  625. * @param name a string representation of the DNS host name to query
  626. * @param addr a preallocated ip_addr_t where to store the resolved IP address
  627. * @return ERR_OK: resolving succeeded
  628. * ERR_MEM: memory error, try again later
  629. * ERR_ARG: dns client not initialized or invalid hostname
  630. * ERR_VAL: dns server response was invalid
  631. */
  632. err_t
  633. netconn_gethostbyname(const char *name, ip_addr_t *addr)
  634. {
  635. struct dns_api_msg msg;
  636. err_t err;
  637. sys_sem_t sem;
  638. LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
  639. LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
  640. err = sys_sem_new(&sem, 0);
  641. if (err != ERR_OK) {
  642. return err;
  643. }
  644. msg.name = name;
  645. msg.addr = addr;
  646. msg.err = &err;
  647. msg.sem = &sem;
  648. tcpip_callback(do_gethostbyname, &msg);
  649. sys_sem_wait(&sem);
  650. sys_sem_free(&sem);
  651. return err;
  652. }
  653. #endif /* LWIP_DNS*/
  654. #endif /* LWIP_NETCONN */