STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
api_lib.c
Go to the documentation of this file.
1 
7 /*
8  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  * this list of conditions and the following disclaimer in the documentation
18  * and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  * derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38 
39 /* This is the part of the API that is linked with
40  the application */
41 
42 #include "lwip/opt.h"
43 
44 #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
45 
46 #include "lwip/api.h"
47 #include "lwip/memp.h"
48 
49 #include "lwip/ip.h"
50 #include "lwip/raw.h"
51 #include "lwip/udp.h"
52 #include "lwip/priv/tcp_priv.h"
53 #include "lwip/priv/tcpip_priv.h"
54 
55 #include <string.h>
56 
57 #define API_MSG_VAR_REF(name) API_VAR_REF(name)
58 #define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name)
59 #define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name)
60 #define API_MSG_VAR_ALLOC_DONTFAIL(name) API_VAR_ALLOC_DONTFAIL(struct api_msg, MEMP_API_MSG, name)
61 #define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name)
62 
63 static err_t netconn_close_shutdown(struct netconn *conn, u8_t how);
64 
75 struct netconn*
76 netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
77 {
78  struct netconn *conn;
79  API_MSG_VAR_DECLARE(msg);
80 
81  conn = netconn_alloc(t, callback);
82  if (conn != NULL) {
83  err_t err;
84  API_MSG_VAR_ALLOC_DONTFAIL(msg);
85  API_MSG_VAR_REF(msg).msg.msg.n.proto = proto;
86  API_MSG_VAR_REF(msg).msg.conn = conn;
87  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_newconn, err);
88  API_MSG_VAR_FREE(msg);
89  if (err != ERR_OK) {
90  LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
91  LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
92 #if LWIP_TCP
93  LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
94 #endif /* LWIP_TCP */
95 #if !LWIP_NETCONN_SEM_PER_THREAD
96  LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
97  sys_sem_free(&conn->op_completed);
98 #endif /* !LWIP_NETCONN_SEM_PER_THREAD */
99  sys_mbox_free(&conn->recvmbox);
100  memp_free(MEMP_NETCONN, conn);
101  return NULL;
102  }
103  }
104  return conn;
105 }
106 
115 err_t
116 netconn_delete(struct netconn *conn)
117 {
118  err_t err;
119  API_MSG_VAR_DECLARE(msg);
120 
121  /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
122  if (conn == NULL) {
123  return ERR_OK;
124  }
125 
126  API_MSG_VAR_ALLOC(msg);
127  API_MSG_VAR_REF(msg).msg.conn = conn;
128 #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
129  /* get the time we started, which is later compared to
130  sys_now() + conn->send_timeout */
131  API_MSG_VAR_REF(msg).msg.msg.sd.time_started = sys_now();
132 #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
133 #if LWIP_TCP
134  API_MSG_VAR_REF(msg).msg.msg.sd.polls_left =
135  ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
136 #endif /* LWIP_TCP */
137 #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
138  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_delconn, err);
139  API_MSG_VAR_FREE(msg);
140 
141  if (err != ERR_OK) {
142  return err;
143  }
144 
145  netconn_free(conn);
146 
147  return ERR_OK;
148 }
149 
161 err_t
162 netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
163 {
164  API_MSG_VAR_DECLARE(msg);
165  err_t err;
166 
167  LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
168  LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
169  LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
170 
171  API_MSG_VAR_ALLOC(msg);
172  API_MSG_VAR_REF(msg).msg.conn = conn;
173  API_MSG_VAR_REF(msg).msg.msg.ad.local = local;
174 #if LWIP_MPU_COMPATIBLE
175  TCPIP_APIMSG(msg, lwip_netconn_do_getaddr, err);
176  *addr = msg->msg.msg.ad.ipaddr;
177  *port = msg->msg.msg.ad.port;
178 #else /* LWIP_MPU_COMPATIBLE */
179  msg.msg.msg.ad.ipaddr = addr;
180  msg.msg.msg.ad.port = port;
181  TCPIP_APIMSG(&msg, lwip_netconn_do_getaddr, err);
182 #endif /* LWIP_MPU_COMPATIBLE */
183  API_MSG_VAR_FREE(msg);
184 
185  return err;
186 }
187 
198 err_t
199 netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
200 {
201  API_MSG_VAR_DECLARE(msg);
202  err_t err;
203 
204  LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
205 
206  API_MSG_VAR_ALLOC(msg);
207 #if LWIP_MPU_COMPATIBLE
208  if (addr == NULL) {
209  addr = IP_ADDR_ANY;
210  }
211 #endif /* LWIP_MPU_COMPATIBLE */
212  API_MSG_VAR_REF(msg).msg.conn = conn;
213  API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr);
214  API_MSG_VAR_REF(msg).msg.msg.bc.port = port;
215  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_bind, err);
216  API_MSG_VAR_FREE(msg);
217 
218  return err;
219 }
220 
229 err_t
230 netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
231 {
232  API_MSG_VAR_DECLARE(msg);
233  err_t err;
234 
235  LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
236 
237  API_MSG_VAR_ALLOC(msg);
238 #if LWIP_MPU_COMPATIBLE
239  if (addr == NULL) {
240  addr = IP_ADDR_ANY;
241  }
242 #endif /* LWIP_MPU_COMPATIBLE */
243  API_MSG_VAR_REF(msg).msg.conn = conn;
244  API_MSG_VAR_REF(msg).msg.msg.bc.ipaddr = API_MSG_VAR_REF(addr);
245  API_MSG_VAR_REF(msg).msg.msg.bc.port = port;
246  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_connect, err);
247  API_MSG_VAR_FREE(msg);
248 
249  return err;
250 }
251 
258 err_t
259 netconn_disconnect(struct netconn *conn)
260 {
261  API_MSG_VAR_DECLARE(msg);
262  err_t err;
263 
264  LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
265 
266  API_MSG_VAR_ALLOC(msg);
267  API_MSG_VAR_REF(msg).msg.conn = conn;
268  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_disconnect, err);
269  API_MSG_VAR_FREE(msg);
270 
271  return err;
272 }
273 
282 err_t
283 netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
284 {
285 #if LWIP_TCP
286  API_MSG_VAR_DECLARE(msg);
287  err_t err;
288 
289  /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
290  LWIP_UNUSED_ARG(backlog);
291 
292  LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
293 
294  API_MSG_VAR_ALLOC(msg);
295  API_MSG_VAR_REF(msg).msg.conn = conn;
296 #if TCP_LISTEN_BACKLOG
297  API_MSG_VAR_REF(msg).msg.msg.lb.backlog = backlog;
298 #endif /* TCP_LISTEN_BACKLOG */
299  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_listen, err);
300  API_MSG_VAR_FREE(msg);
301 
302  return err;
303 #else /* LWIP_TCP */
304  LWIP_UNUSED_ARG(conn);
305  LWIP_UNUSED_ARG(backlog);
306  return ERR_ARG;
307 #endif /* LWIP_TCP */
308 }
309 
318 err_t
319 netconn_accept(struct netconn *conn, struct netconn **new_conn)
320 {
321 #if LWIP_TCP
322  struct netconn *newconn;
323  err_t err;
324 #if TCP_LISTEN_BACKLOG
325  API_MSG_VAR_DECLARE(msg);
326 #endif /* TCP_LISTEN_BACKLOG */
327 
328  LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
329  *new_conn = NULL;
330  LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
331  LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;);
332 
333  err = conn->last_err;
334  if (ERR_IS_FATAL(err)) {
335  /* don't recv on fatal errors: this might block the application task
336  waiting on acceptmbox forever! */
337  return err;
338  }
339 
340 #if LWIP_SO_RCVTIMEO
341  if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
342  return ERR_TIMEOUT;
343  }
344 #else
345  sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
346 #endif /* LWIP_SO_RCVTIMEO*/
347  /* Register event with callback */
348  API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
349 
350  if (newconn == NULL) {
351  /* connection has been aborted */
352  /* in this special case, we set the netconn error from application thread, as
353  on a ready-to-accept listening netconn, there should not be anything running
354  in tcpip_thread */
355  NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
356  return ERR_ABRT;
357  }
358 #if TCP_LISTEN_BACKLOG
359  /* Let the stack know that we have accepted the connection. */
360  API_MSG_VAR_ALLOC_DONTFAIL(msg);
361  API_MSG_VAR_REF(msg).msg.conn = conn;
362  /* don't care for the return value of lwip_netconn_do_recv */
363  TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv);
364  API_MSG_VAR_FREE(msg);
365 #endif /* TCP_LISTEN_BACKLOG */
366 
367  *new_conn = newconn;
368  /* don't set conn->last_err: it's only ERR_OK, anyway */
369  return ERR_OK;
370 #else /* LWIP_TCP */
371  LWIP_UNUSED_ARG(conn);
372  LWIP_UNUSED_ARG(new_conn);
373  return ERR_ARG;
374 #endif /* LWIP_TCP */
375 }
376 
386 static err_t
387 netconn_recv_data(struct netconn *conn, void **new_buf)
388 {
389  void *buf = NULL;
390  u16_t len;
391  err_t err;
392 #if LWIP_TCP
393  API_MSG_VAR_DECLARE(msg);
394 #endif /* LWIP_TCP */
395 
396  LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
397  *new_buf = NULL;
398  LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
399 #if LWIP_TCP
400 #if (LWIP_UDP || LWIP_RAW)
401  if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
402 #endif /* (LWIP_UDP || LWIP_RAW) */
403  {
404  if (!sys_mbox_valid(&conn->recvmbox)) {
405  /* This happens when calling this function after receiving FIN */
406  return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD;
407  }
408  }
409 #endif /* LWIP_TCP */
410  LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
411 
412  err = conn->last_err;
413  if (ERR_IS_FATAL(err)) {
414  /* don't recv on fatal errors: this might block the application task
415  waiting on recvmbox forever! */
416  /* @todo: this does not allow us to fetch data that has been put into recvmbox
417  before the fatal error occurred - is that a problem? */
418  return err;
419  }
420 
421 #if LWIP_SO_RCVTIMEO
422  if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
423  return ERR_TIMEOUT;
424  }
425 #else
426  sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
427 #endif /* LWIP_SO_RCVTIMEO*/
428 
429 #if LWIP_TCP
430 #if (LWIP_UDP || LWIP_RAW)
431  if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
432 #endif /* (LWIP_UDP || LWIP_RAW) */
433  {
434  if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
435  /* Let the stack know that we have taken the data. */
436  /* TODO: Speedup: Don't block and wait for the answer here
437  (to prevent multiple thread-switches). */
438  API_MSG_VAR_ALLOC_DONTFAIL(msg);
439  API_MSG_VAR_REF(msg).msg.conn = conn;
440  if (buf != NULL) {
441  API_MSG_VAR_REF(msg).msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
442  } else {
443  API_MSG_VAR_REF(msg).msg.msg.r.len = 1;
444  }
445  /* don't care for the return value of lwip_netconn_do_recv */
446  TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv);
447  API_MSG_VAR_FREE(msg);
448  }
449 
450  /* If we are closed, we indicate that we no longer wish to use the socket */
451  if (buf == NULL) {
452  API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
453  /* RX side is closed, so deallocate the recvmbox */
454  netconn_close_shutdown(conn, NETCONN_SHUT_RD);
455  /* Don' store ERR_CLSD as conn->err since we are only half-closed */
456  return ERR_CLSD;
457  }
458  len = ((struct pbuf *)buf)->tot_len;
459  }
460 #endif /* LWIP_TCP */
461 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
462  else
463 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
464 #if (LWIP_UDP || LWIP_RAW)
465  {
466  LWIP_ASSERT("buf != NULL", buf != NULL);
467  len = netbuf_len((struct netbuf *)buf);
468  }
469 #endif /* (LWIP_UDP || LWIP_RAW) */
470 
471 #if LWIP_SO_RCVBUF
472  SYS_ARCH_DEC(conn->recv_avail, len);
473 #endif /* LWIP_SO_RCVBUF */
474  /* Register event with callback */
475  API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
476 
477  LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
478 
479  *new_buf = buf;
480  /* don't set conn->last_err: it's only ERR_OK, anyway */
481  return ERR_OK;
482 }
483 
493 err_t
494 netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
495 {
496  LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
497  NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
498 
499  return netconn_recv_data(conn, (void **)new_buf);
500 }
501 
510 err_t
511 netconn_recv(struct netconn *conn, struct netbuf **new_buf)
512 {
513 #if LWIP_TCP
514  struct netbuf *buf = NULL;
515  err_t err;
516 #endif /* LWIP_TCP */
517 
518  LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
519  *new_buf = NULL;
520  LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
521  LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
522 
523 #if LWIP_TCP
524 #if (LWIP_UDP || LWIP_RAW)
525  if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
526 #endif /* (LWIP_UDP || LWIP_RAW) */
527  {
528  struct pbuf *p = NULL;
529  /* This is not a listening netconn, since recvmbox is set */
530 
531  buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
532  if (buf == NULL) {
533  return ERR_MEM;
534  }
535 
536  err = netconn_recv_data(conn, (void **)&p);
537  if (err != ERR_OK) {
538  memp_free(MEMP_NETBUF, buf);
539  return err;
540  }
541  LWIP_ASSERT("p != NULL", p != NULL);
542 
543  buf->p = p;
544  buf->ptr = p;
545  buf->port = 0;
546  ip_addr_set_zero(&buf->addr);
547  *new_buf = buf;
548  /* don't set conn->last_err: it's only ERR_OK, anyway */
549  return ERR_OK;
550  }
551 #endif /* LWIP_TCP */
552 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
553  else
554 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
555  {
556 #if (LWIP_UDP || LWIP_RAW)
557  return netconn_recv_data(conn, (void **)new_buf);
558 #endif /* (LWIP_UDP || LWIP_RAW) */
559  }
560 }
561 
572 void
573 netconn_recved(struct netconn *conn, u32_t length)
574 {
575 #if LWIP_TCP
576  if ((conn != NULL) && (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) &&
577  (netconn_get_noautorecved(conn))) {
578  API_MSG_VAR_DECLARE(msg);
579  /* Let the stack know that we have taken the data. */
580  /* TODO: Speedup: Don't block and wait for the answer here
581  (to prevent multiple thread-switches). */
582  API_MSG_VAR_ALLOC_DONTFAIL(msg);
583  API_MSG_VAR_REF(msg).msg.conn = conn;
584  API_MSG_VAR_REF(msg).msg.msg.r.len = length;
585  /* don't care for the return value of lwip_netconn_do_recv */
586  TCPIP_APIMSG_NOERR(&API_MSG_VAR_REF(msg), lwip_netconn_do_recv);
587  API_MSG_VAR_FREE(msg);
588  }
589 #else /* LWIP_TCP */
590  LWIP_UNUSED_ARG(conn);
591  LWIP_UNUSED_ARG(length);
592 #endif /* LWIP_TCP */
593 }
594 
605 err_t
606 netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port)
607 {
608  if (buf != NULL) {
609  ip_addr_set(&buf->addr, addr);
610  buf->port = port;
611  return netconn_send(conn, buf);
612  }
613  return ERR_VAL;
614 }
615 
623 err_t
624 netconn_send(struct netconn *conn, struct netbuf *buf)
625 {
626  API_MSG_VAR_DECLARE(msg);
627  err_t err;
628 
629  LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
630 
631  LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
632  API_MSG_VAR_ALLOC(msg);
633  API_MSG_VAR_REF(msg).msg.conn = conn;
634  API_MSG_VAR_REF(msg).msg.msg.b = buf;
635  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_send, err);
636  API_MSG_VAR_FREE(msg);
637 
638  return err;
639 }
640 
654 err_t
655 netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
656  u8_t apiflags, size_t *bytes_written)
657 {
658  API_MSG_VAR_DECLARE(msg);
659  err_t err;
660  u8_t dontblock;
661 
662  LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
663  LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;);
664  if (size == 0) {
665  return ERR_OK;
666  }
667  dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
668  if (dontblock && !bytes_written) {
669  /* This implies netconn_write() cannot be used for non-blocking send, since
670  it has no way to return the number of bytes written. */
671  return ERR_VAL;
672  }
673 
674  API_MSG_VAR_ALLOC(msg);
675  /* non-blocking write sends as much */
676  API_MSG_VAR_REF(msg).msg.conn = conn;
677  API_MSG_VAR_REF(msg).msg.msg.w.dataptr = dataptr;
678  API_MSG_VAR_REF(msg).msg.msg.w.apiflags = apiflags;
679  API_MSG_VAR_REF(msg).msg.msg.w.len = size;
680 #if LWIP_SO_SNDTIMEO
681  if (conn->send_timeout != 0) {
682  /* get the time we started, which is later compared to
683  sys_now() + conn->send_timeout */
684  API_MSG_VAR_REF(msg).msg.msg.w.time_started = sys_now();
685  } else {
686  API_MSG_VAR_REF(msg).msg.msg.w.time_started = 0;
687  }
688 #endif /* LWIP_SO_SNDTIMEO */
689 
690  /* For locking the core: this _can_ be delayed on low memory/low send buffer,
691  but if it is, this is done inside api_msg.c:do_write(), so we can use the
692  non-blocking version here. */
693  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_write, err);
694  if ((err == ERR_OK) && (bytes_written != NULL)) {
695  if (dontblock
697  || (conn->send_timeout != 0)
698 #endif /* LWIP_SO_SNDTIMEO */
699  ) {
700  /* nonblocking write: maybe the data has been sent partly */
701  *bytes_written = API_MSG_VAR_REF(msg).msg.msg.w.len;
702  } else {
703  /* blocking call succeeded: all data has been sent if it */
704  *bytes_written = size;
705  }
706  }
707  API_MSG_VAR_FREE(msg);
708 
709  return err;
710 }
711 
719 static err_t
720 netconn_close_shutdown(struct netconn *conn, u8_t how)
721 {
722  API_MSG_VAR_DECLARE(msg);
723  err_t err;
724  LWIP_UNUSED_ARG(how);
725 
726  LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
727 
728  API_MSG_VAR_ALLOC(msg);
729  API_MSG_VAR_REF(msg).msg.conn = conn;
730 #if LWIP_TCP
731  /* shutting down both ends is the same as closing */
732  API_MSG_VAR_REF(msg).msg.msg.sd.shut = how;
733 #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
734  /* get the time we started, which is later compared to
735  sys_now() + conn->send_timeout */
736  API_MSG_VAR_REF(msg).msg.msg.sd.time_started = sys_now();
737 #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
738  API_MSG_VAR_REF(msg).msg.msg.sd.polls_left =
739  ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
740 #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
741 #endif /* LWIP_TCP */
742  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_close, err);
743  API_MSG_VAR_FREE(msg);
744 
745  return err;
746 }
747 
754 err_t
755 netconn_close(struct netconn *conn)
756 {
757  /* shutting down both ends is the same as closing */
758  return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
759 }
760 
767 err_t
768 netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
769 {
770  return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
771 }
772 
773 #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
774 
784 err_t
785 netconn_join_leave_group(struct netconn *conn,
786  const ip_addr_t *multiaddr,
787  const ip_addr_t *netif_addr,
788  enum netconn_igmp join_or_leave)
789 {
790  API_MSG_VAR_DECLARE(msg);
791  err_t err;
792 
793  LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
794 
795  API_MSG_VAR_ALLOC(msg);
796 #if LWIP_MPU_COMPATIBLE
797  if (multiaddr == NULL) {
798  multiaddr = IP_ADDR_ANY;
799  }
800  if (netif_addr == NULL) {
801  netif_addr = IP_ADDR_ANY;
802  }
803 #endif /* LWIP_MPU_COMPATIBLE */
804  API_MSG_VAR_REF(msg).msg.conn = conn;
805  API_MSG_VAR_REF(msg).msg.msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
806  API_MSG_VAR_REF(msg).msg.msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr);
807  API_MSG_VAR_REF(msg).msg.msg.jl.join_or_leave = join_or_leave;
808  TCPIP_APIMSG(&API_MSG_VAR_REF(msg), lwip_netconn_do_join_leave_group, err);
809  API_MSG_VAR_FREE(msg);
810 
811  return err;
812 }
813 #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
814 
815 #if LWIP_DNS
816 
826 #if LWIP_IPV4 && LWIP_IPV6
827 err_t
828 netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype)
829 #else
830 err_t
831 netconn_gethostbyname(const char *name, ip_addr_t *addr)
832 #endif
833 {
834  API_VAR_DECLARE(struct dns_api_msg, msg);
835 #if !LWIP_MPU_COMPATIBLE
836  sys_sem_t sem;
837 #endif /* LWIP_MPU_COMPATIBLE */
838  err_t err;
839 
840  LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
841  LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
842 #if LWIP_MPU_COMPATIBLE
843  if (strlen(name) >= DNS_MAX_NAME_LENGTH) {
844  return ERR_ARG;
845  }
846 #endif
847 
848  API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg);
849 #if LWIP_MPU_COMPATIBLE
850  strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1);
851  API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0;
852 #else /* LWIP_MPU_COMPATIBLE */
853  msg.err = &err;
854  msg.sem = &sem;
855  API_VAR_REF(msg).addr = API_VAR_REF(addr);
856  API_VAR_REF(msg).name = name;
857 #endif /* LWIP_MPU_COMPATIBLE */
858 #if LWIP_IPV4 && LWIP_IPV6
859  API_VAR_REF(msg).dns_addrtype = dns_addrtype;
860 #endif /* LWIP_IPV4 && LWIP_IPV6 */
861 #if LWIP_NETCONN_SEM_PER_THREAD
862  API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET();
863 #else /* LWIP_NETCONN_SEM_PER_THREAD*/
864  err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0);
865  if (err != ERR_OK) {
866  API_VAR_FREE(MEMP_DNS_API_MSG, msg);
867  return err;
868  }
869 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
870 
871  err = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
872  if (err != ERR_OK) {
873 #if !LWIP_NETCONN_SEM_PER_THREAD
875 #endif /* !LWIP_NETCONN_SEM_PER_THREAD */
876  API_VAR_FREE(MEMP_DNS_API_MSG, msg);
877  return err;
878  }
880 #if !LWIP_NETCONN_SEM_PER_THREAD
882 #endif /* !LWIP_NETCONN_SEM_PER_THREAD */
883 
884 #if LWIP_MPU_COMPATIBLE
885  *addr = msg->addr;
886  err = msg->err;
887 #endif /* LWIP_MPU_COMPATIBLE */
888 
889  API_VAR_FREE(MEMP_DNS_API_MSG, msg);
890  return err;
891 }
892 #endif /* LWIP_DNS*/
893 
894 #if LWIP_NETCONN_SEM_PER_THREAD
895 void
896 netconn_thread_init(void)
897 {
898  sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
899  if ((sem == NULL) || !sys_sem_valid(sem)) {
900  /* call alloc only once */
901  LWIP_NETCONN_THREAD_SEM_ALLOC();
902  LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET()));
903  }
904 }
905 
906 void
907 netconn_thread_cleanup(void)
908 {
909  sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
910  if ((sem != NULL) && sys_sem_valid(sem)) {
911  /* call free only once */
912  LWIP_NETCONN_THREAD_SEM_FREE();
913  }
914 }
915 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
916 
917 #endif /* LWIP_NETCONN */
918 
#define DNS_MAX_NAME_LENGTH
Definition: opt.h:888
#define ERR_CONN
Definition: err.h:64
#define U16_F
Definition: cc.h:48
#define SYS_ARCH_DEC(var, val)
Definition: sys.h:327
#define TCPIP_APIMSG_NOERR(m, f)
Definition: tcpip_priv.h:93
int sys_mbox_valid(sys_mbox_t *mbox)
Definition: sys_arch.c:205
#define ERR_CLSD
Definition: err.h:69
#define ERR_VAL
Definition: err.h:58
#define SYS_ARCH_TIMEOUT
Definition: sys.h:82
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
Definition: sys_arch.c:143
#define API_EXPR_REF(expr)
Definition: tcpip_priv.h:130
#define API_VAR_ALLOC(type, pool, name)
Definition: tcpip_priv.h:127
void memp_free(memp_t type, void *mem)
Definition: memp.c:399
#define API_VAR_REF(name)
Definition: tcpip_priv.h:125
void sys_sem_free(sys_sem_t *sem)
Definition: sys_arch.c:303
#define ERR_ABRT
Definition: err.h:67
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
Definition: sys_arch.c:221
int sys_sem_valid(sys_sem_t *sem)
Definition: sys_arch.c:312
#define ERR_IS_FATAL(e)
Definition: err.h:65
#define tcpip_callback(f, ctx)
Definition: tcpip.h:60
#define sys_sem_wait(sem)
Definition: sys.h:157
#define NULL
Definition: usbd_def.h:53
unsigned long u32_t
Definition: cc.h:42
#define API_VAR_DECLARE(type, name)
Definition: tcpip_priv.h:126
#define ERR_OK
Definition: err.h:52
Definition: pbuf.h:108
#define ERR_TIMEOUT
Definition: err.h:55
s8_t err_t
Definition: err.h:47
#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT
Definition: opt.h:1632
osSemaphoreId sys_sem_t
Definition: sys_arch.h:44
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:70
#define ip_addr_set(dest, src)
Definition: ip_addr.h:205
#define API_VAR_FREE(pool, name)
Definition: tcpip_priv.h:129
u32_t sys_now(void)
#define ERR_ARG
Definition: err.h:71
#define API_LIB_DEBUG
Definition: opt.h:2795
#define TCPIP_APIMSG(m, f, e)
Definition: tcpip_priv.h:94
unsigned char u8_t
Definition: cc.h:38
ip6_addr_t ip_addr_t
Definition: ip_addr.h:194
#define ip_addr_set_zero(ipaddr)
Definition: ip_addr.h:207
#define LWIP_ERROR(message, expression, handler)
Definition: debug.h:89
void * memp_malloc(memp_t type)
Definition: memp.c:303
#define API_EXPR_REF_SEM(expr)
Definition: tcpip_priv.h:131
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:113
#define ERR_MEM
Definition: err.h:53
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:89
void sys_mbox_free(sys_mbox_t *mbox)
Definition: sys_arch.c:76
#define LWIP_SO_SNDTIMEO
Definition: opt.h:1588
unsigned short u16_t
Definition: cc.h:40