sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
api_lib.c
Go to the documentation of this file.
1
23
24/*
25 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
26 * All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without modification,
29 * are permitted provided that the following conditions are met:
30 *
31 * 1. Redistributions of source code must retain the above copyright notice,
32 * this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright notice,
34 * this list of conditions and the following disclaimer in the documentation
35 * and/or other materials provided with the distribution.
36 * 3. The name of the author may not be used to endorse or promote products
37 * derived from this software without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
40 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
41 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
42 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
43 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
44 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
47 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
48 * OF SUCH DAMAGE.
49 *
50 * This file is part of the lwIP TCP/IP stack.
51 *
52 * Author: Adam Dunkels <adam@sics.se>
53 */
54
55/* This is the part of the API that is linked with
56 the application */
57
58#include "lwip/opt.h"
59
60#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
61
62#include "lwip/api.h"
63#include "lwip/memp.h"
64
65#include "lwip/ip.h"
66#include "lwip/raw.h"
67#include "lwip/udp.h"
68#include "lwip/priv/api_msg.h"
69#include "lwip/priv/tcp_priv.h"
71
72#ifdef LWIP_HOOK_FILENAME
73#include LWIP_HOOK_FILENAME
74#endif
75
76#include <string.h>
77
78#define API_MSG_VAR_REF(name) API_VAR_REF(name)
79#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name)
80#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM)
81#define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL)
82#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name)
83
84#if TCP_LISTEN_BACKLOG
85/* need to allocate API message for accept so empty message pool does not result in event loss
86 * see bug #47512: MPU_COMPATIBLE may fail on empty pool */
87#define API_MSG_VAR_ALLOC_ACCEPT(msg) API_MSG_VAR_ALLOC(msg)
88#define API_MSG_VAR_FREE_ACCEPT(msg) API_MSG_VAR_FREE(msg)
89#else /* TCP_LISTEN_BACKLOG */
90#define API_MSG_VAR_ALLOC_ACCEPT(msg)
91#define API_MSG_VAR_FREE_ACCEPT(msg)
92#endif /* TCP_LISTEN_BACKLOG */
93
94#if LWIP_NETCONN_FULLDUPLEX
95#define NETCONN_RECVMBOX_WAITABLE(conn) (sys_mbox_valid(&(conn)->recvmbox) && (((conn)->flags & NETCONN_FLAG_MBOXINVALID) == 0))
96#define NETCONN_ACCEPTMBOX_WAITABLE(conn) (sys_mbox_valid(&(conn)->acceptmbox) && (((conn)->flags & (NETCONN_FLAG_MBOXCLOSED|NETCONN_FLAG_MBOXINVALID)) == 0))
97#define NETCONN_MBOX_WAITING_INC(conn) SYS_ARCH_INC(conn->mbox_threads_waiting, 1)
98#define NETCONN_MBOX_WAITING_DEC(conn) SYS_ARCH_DEC(conn->mbox_threads_waiting, 1)
99#else /* LWIP_NETCONN_FULLDUPLEX */
100#define NETCONN_RECVMBOX_WAITABLE(conn) sys_mbox_valid(&(conn)->recvmbox)
101#define NETCONN_ACCEPTMBOX_WAITABLE(conn) (sys_mbox_valid(&(conn)->acceptmbox) && (((conn)->flags & NETCONN_FLAG_MBOXCLOSED) == 0))
102#define NETCONN_MBOX_WAITING_INC(conn)
103#define NETCONN_MBOX_WAITING_DEC(conn)
104#endif /* LWIP_NETCONN_FULLDUPLEX */
105
106static err_t netconn_close_shutdown(struct netconn *conn, u8_t how);
107
117static err_t
118netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg)
119{
120 err_t err;
121
122#ifdef LWIP_DEBUG
123 /* catch functions that don't set err */
124 apimsg->err = ERR_VAL;
125#endif /* LWIP_DEBUG */
126
127#if LWIP_NETCONN_SEM_PER_THREAD
128 apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
129#endif /* LWIP_NETCONN_SEM_PER_THREAD */
130
131 err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg));
132 if (err == ERR_OK) {
133 return apimsg->err;
134 }
135 return err;
136}
137
148struct netconn *
149netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
150{
151 struct netconn *conn;
152 API_MSG_VAR_DECLARE(msg);
153 API_MSG_VAR_ALLOC_RETURN_NULL(msg);
154
155 conn = netconn_alloc(t, callback);
156 if (conn != NULL) {
157 err_t err;
158
159 API_MSG_VAR_REF(msg).msg.n.proto = proto;
160 API_MSG_VAR_REF(msg).conn = conn;
161 err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg));
162 if (err != ERR_OK) {
163 LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
164 LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
165#if LWIP_TCP
166 LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
167#endif /* LWIP_TCP */
168#if !LWIP_NETCONN_SEM_PER_THREAD
169 LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
170 sys_sem_free(&conn->op_completed);
171#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
172 sys_mbox_free(&conn->recvmbox);
173 memp_free(MEMP_NETCONN, conn);
174 API_MSG_VAR_FREE(msg);
175 return NULL;
176 }
177 }
178 API_MSG_VAR_FREE(msg);
179 return conn;
180}
181
191err_t
192netconn_prepare_delete(struct netconn *conn)
193{
194 err_t err;
195 API_MSG_VAR_DECLARE(msg);
196
197 /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
198 if (conn == NULL) {
199 return ERR_OK;
200 }
201
202 API_MSG_VAR_ALLOC(msg);
203 API_MSG_VAR_REF(msg).conn = conn;
204#if LWIP_TCP
205#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
206 /* get the time we started, which is later compared to
207 sys_now() + conn->send_timeout */
208 API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
209#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
210 API_MSG_VAR_REF(msg).msg.sd.polls_left =
211 ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
212#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
213#endif /* LWIP_TCP */
214 err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg));
215 API_MSG_VAR_FREE(msg);
216
217 if (err != ERR_OK) {
218 return err;
219 }
220 return ERR_OK;
221}
222
232err_t
233netconn_delete(struct netconn *conn)
234{
235 err_t err;
236
237 /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
238 if (conn == NULL) {
239 return ERR_OK;
240 }
241
242#if LWIP_NETCONN_FULLDUPLEX
243 if (conn->flags & NETCONN_FLAG_MBOXINVALID) {
244 /* Already called netconn_prepare_delete() before */
245 err = ERR_OK;
246 } else
247#endif /* LWIP_NETCONN_FULLDUPLEX */
248 {
249 err = netconn_prepare_delete(conn);
250 }
251 if (err == ERR_OK) {
252 netconn_free(conn);
253 }
254 return err;
255}
256
268err_t
269netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
270{
271 API_MSG_VAR_DECLARE(msg);
272 err_t err;
273
274 LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
275 LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
276 LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
277
278 API_MSG_VAR_ALLOC(msg);
279 API_MSG_VAR_REF(msg).conn = conn;
280 API_MSG_VAR_REF(msg).msg.ad.local = local;
281#if LWIP_MPU_COMPATIBLE
282 err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg));
283 *addr = msg->msg.ad.ipaddr;
284 *port = msg->msg.ad.port;
285#else /* LWIP_MPU_COMPATIBLE */
286 msg.msg.ad.ipaddr = addr;
287 msg.msg.ad.port = port;
288 err = netconn_apimsg(lwip_netconn_do_getaddr, &msg);
289#endif /* LWIP_MPU_COMPATIBLE */
290 API_MSG_VAR_FREE(msg);
291
292 return err;
293}
294
306err_t
307netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
308{
309 API_MSG_VAR_DECLARE(msg);
310 err_t err;
311
312 LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
313
314#if LWIP_IPV4
315 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
316 if (addr == NULL) {
317 addr = IP4_ADDR_ANY;
318 }
319#endif /* LWIP_IPV4 */
320
321#if LWIP_IPV4 && LWIP_IPV6
322 /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY,
323 * and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind
324 */
325 if ((netconn_get_ipv6only(conn) == 0) &&
326 ip_addr_eq(addr, IP6_ADDR_ANY)) {
327 addr = IP_ANY_TYPE;
328 }
329#endif /* LWIP_IPV4 && LWIP_IPV6 */
330
331 API_MSG_VAR_ALLOC(msg);
332 API_MSG_VAR_REF(msg).conn = conn;
333 API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr);
334 API_MSG_VAR_REF(msg).msg.bc.port = port;
335 err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg));
336 API_MSG_VAR_FREE(msg);
337
338 return err;
339}
340
350err_t
351netconn_bind_if(struct netconn *conn, u8_t if_idx)
352{
353 API_MSG_VAR_DECLARE(msg);
354 err_t err;
355
356 LWIP_ERROR("netconn_bind_if: invalid conn", (conn != NULL), return ERR_ARG;);
357
358 API_MSG_VAR_ALLOC(msg);
359 API_MSG_VAR_REF(msg).conn = conn;
360 API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx;
361 err = netconn_apimsg(lwip_netconn_do_bind_if, &API_MSG_VAR_REF(msg));
362 API_MSG_VAR_FREE(msg);
363
364 return err;
365}
366
376err_t
377netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
378{
379 API_MSG_VAR_DECLARE(msg);
380 err_t err;
381
382 LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
383
384#if LWIP_IPV4
385 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
386 if (addr == NULL) {
387 addr = IP4_ADDR_ANY;
388 }
389#endif /* LWIP_IPV4 */
390
391 API_MSG_VAR_ALLOC(msg);
392 API_MSG_VAR_REF(msg).conn = conn;
393 API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr);
394 API_MSG_VAR_REF(msg).msg.bc.port = port;
395 err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg));
396 API_MSG_VAR_FREE(msg);
397
398 return err;
399}
400
408err_t
409netconn_disconnect(struct netconn *conn)
410{
411 API_MSG_VAR_DECLARE(msg);
412 err_t err;
413
414 LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
415
416 API_MSG_VAR_ALLOC(msg);
417 API_MSG_VAR_REF(msg).conn = conn;
418 err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg));
419 API_MSG_VAR_FREE(msg);
420
421 return err;
422}
423
433err_t
434netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
435{
436#if LWIP_TCP
437 API_MSG_VAR_DECLARE(msg);
438 err_t err;
439
440 /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
441 LWIP_UNUSED_ARG(backlog);
442
443 LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
444
445 API_MSG_VAR_ALLOC(msg);
446 API_MSG_VAR_REF(msg).conn = conn;
447#if TCP_LISTEN_BACKLOG
448 API_MSG_VAR_REF(msg).msg.lb.backlog = backlog;
449#endif /* TCP_LISTEN_BACKLOG */
450 err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg));
451 API_MSG_VAR_FREE(msg);
452
453 return err;
454#else /* LWIP_TCP */
455 LWIP_UNUSED_ARG(conn);
456 LWIP_UNUSED_ARG(backlog);
457 return ERR_ARG;
458#endif /* LWIP_TCP */
459}
460
470err_t
471netconn_accept(struct netconn *conn, struct netconn **new_conn)
472{
473#if LWIP_TCP
474 err_t err;
475 void *accept_ptr;
476 struct netconn *newconn;
477#if TCP_LISTEN_BACKLOG
478 API_MSG_VAR_DECLARE(msg);
479#endif /* TCP_LISTEN_BACKLOG */
480
481 LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
482 *new_conn = NULL;
483 LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
484
485 /* NOTE: Although the opengroup spec says a pending error shall be returned to
486 send/recv/getsockopt(SO_ERROR) only, we return it for listening
487 connections also, to handle embedded-system errors */
488 err = netconn_err(conn);
489 if (err != ERR_OK) {
490 /* return pending error */
491 return err;
492 }
493 if (!NETCONN_ACCEPTMBOX_WAITABLE(conn)) {
494 /* don't accept if closed: this might block the application task
495 waiting on acceptmbox forever! */
496 return ERR_CLSD;
497 }
498
499 API_MSG_VAR_ALLOC_ACCEPT(msg);
500
501 NETCONN_MBOX_WAITING_INC(conn);
502 if (netconn_is_nonblocking(conn)) {
503 if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_MBOX_EMPTY) {
504 API_MSG_VAR_FREE_ACCEPT(msg);
505 NETCONN_MBOX_WAITING_DEC(conn);
506 return ERR_WOULDBLOCK;
507 }
508 } else {
509#if LWIP_SO_RCVTIMEO
510 if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
511 API_MSG_VAR_FREE_ACCEPT(msg);
512 NETCONN_MBOX_WAITING_DEC(conn);
513 return ERR_TIMEOUT;
514 }
515#else
516 sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0);
517#endif /* LWIP_SO_RCVTIMEO*/
518 }
519 NETCONN_MBOX_WAITING_DEC(conn);
520#if LWIP_NETCONN_FULLDUPLEX
521 if (conn->flags & NETCONN_FLAG_MBOXINVALID) {
522 if (lwip_netconn_is_deallocated_msg(accept_ptr)) {
523 /* the netconn has been closed from another thread */
524 API_MSG_VAR_FREE_ACCEPT(msg);
525 return ERR_CONN;
526 }
527 }
528#endif
529
530 /* Register event with callback */
531 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
532
533 if (lwip_netconn_is_err_msg(accept_ptr, &err)) {
534 /* a connection has been aborted: e.g. out of pcbs or out of netconns during accept */
535 API_MSG_VAR_FREE_ACCEPT(msg);
536 return err;
537 }
538 if (accept_ptr == NULL) {
539 /* connection has been aborted */
540 API_MSG_VAR_FREE_ACCEPT(msg);
541 return ERR_CLSD;
542 }
543 newconn = (struct netconn *)accept_ptr;
544#if TCP_LISTEN_BACKLOG
545 /* Let the stack know that we have accepted the connection. */
546 API_MSG_VAR_REF(msg).conn = newconn;
547 /* don't care for the return value of lwip_netconn_do_recv */
548 netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg));
549 API_MSG_VAR_FREE(msg);
550#endif /* TCP_LISTEN_BACKLOG */
551
552 *new_conn = newconn;
553 /* don't set conn->last_err: it's only ERR_OK, anyway */
554 return ERR_OK;
555#else /* LWIP_TCP */
556 LWIP_UNUSED_ARG(conn);
557 LWIP_UNUSED_ARG(new_conn);
558 return ERR_ARG;
559#endif /* LWIP_TCP */
560}
561
578static err_t
579netconn_recv_data(struct netconn *conn, void **new_buf, u8_t apiflags)
580{
581 void *buf = NULL;
582 u16_t len;
583
584 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
585 *new_buf = NULL;
586 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
587
588 if (!NETCONN_RECVMBOX_WAITABLE(conn)) {
589 err_t err = netconn_err(conn);
590 if (err != ERR_OK) {
591 /* return pending error */
592 return err;
593 }
594 return ERR_CONN;
595 }
596
597 NETCONN_MBOX_WAITING_INC(conn);
598 if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) ||
599 (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) {
600 if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_MBOX_EMPTY) {
601 err_t err;
602 NETCONN_MBOX_WAITING_DEC(conn);
603 err = netconn_err(conn);
604 if (err != ERR_OK) {
605 /* return pending error */
606 return err;
607 }
608 if (conn->flags & NETCONN_FLAG_MBOXCLOSED) {
609 return ERR_CONN;
610 }
611 return ERR_WOULDBLOCK;
612 }
613 } else {
614#if LWIP_SO_RCVTIMEO
615 if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
616 NETCONN_MBOX_WAITING_DEC(conn);
617 return ERR_TIMEOUT;
618 }
619#else
620 sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
621#endif /* LWIP_SO_RCVTIMEO*/
622 }
623 NETCONN_MBOX_WAITING_DEC(conn);
624#if LWIP_NETCONN_FULLDUPLEX
625 if (conn->flags & NETCONN_FLAG_MBOXINVALID) {
626 if (lwip_netconn_is_deallocated_msg(buf)) {
627 /* the netconn has been closed from another thread */
628 API_MSG_VAR_FREE_ACCEPT(msg);
629 return ERR_CONN;
630 }
631 }
632#endif
633
634#if LWIP_TCP
635#if (LWIP_UDP || LWIP_RAW)
636 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
637#endif /* (LWIP_UDP || LWIP_RAW) */
638 {
639 err_t err;
640 /* Check if this is an error message or a pbuf */
641 if (lwip_netconn_is_err_msg(buf, &err)) {
642 /* new_buf has been zeroed above already */
643 if (err == ERR_CLSD) {
644 /* connection closed translates to ERR_OK with *new_buf == NULL */
645 return ERR_OK;
646 }
647 return err;
648 }
649 len = ((struct pbuf *)buf)->tot_len;
650 }
651#endif /* LWIP_TCP */
652#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
653 else
654#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
655#if (LWIP_UDP || LWIP_RAW)
656 {
657 LWIP_ASSERT("buf != NULL", buf != NULL);
658 len = netbuf_len((struct netbuf *)buf);
659 }
660#endif /* (LWIP_UDP || LWIP_RAW) */
661
662#if LWIP_SO_RCVBUF
663 SYS_ARCH_DEC(conn->recv_avail, len);
664#endif /* LWIP_SO_RCVBUF */
665 /* Register event with callback */
666 API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
667
668 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
669
670 *new_buf = buf;
671 /* don't set conn->last_err: it's only ERR_OK, anyway */
672 return ERR_OK;
673}
674
675#if LWIP_TCP
676static err_t
677netconn_tcp_recvd_msg(struct netconn *conn, size_t len, struct api_msg *msg)
678{
679 LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) &&
680 NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
681
682 msg->conn = conn;
683 msg->msg.r.len = len;
684
685 return netconn_apimsg(lwip_netconn_do_recv, msg);
686}
687
688err_t
689netconn_tcp_recvd(struct netconn *conn, size_t len)
690{
691 err_t err;
692 API_MSG_VAR_DECLARE(msg);
693 LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) &&
694 NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
695
696 API_MSG_VAR_ALLOC(msg);
697 err = netconn_tcp_recvd_msg(conn, len, &API_VAR_REF(msg));
698 API_MSG_VAR_FREE(msg);
699 return err;
700}
701
702static err_t
703netconn_recv_data_tcp(struct netconn *conn, struct pbuf **new_buf, u8_t apiflags)
704{
705 err_t err;
706 struct pbuf *buf;
707 API_MSG_VAR_DECLARE(msg);
708#if LWIP_MPU_COMPATIBLE
709 msg = NULL;
710#endif
711
712 if (!NETCONN_RECVMBOX_WAITABLE(conn)) {
713 /* This only happens when calling this function more than once *after* receiving FIN */
714 return ERR_CONN;
715 }
716 if (netconn_is_flag_set(conn, NETCONN_FIN_RX_PENDING)) {
717 netconn_clear_flags(conn, NETCONN_FIN_RX_PENDING);
718 goto handle_fin;
719 }
720
721 if (!(apiflags & NETCONN_NOAUTORCVD)) {
722 /* need to allocate API message here so empty message pool does not result in event loss
723 * see bug #47512: MPU_COMPATIBLE may fail on empty pool */
724 API_MSG_VAR_ALLOC(msg);
725 }
726
727 err = netconn_recv_data(conn, (void **)new_buf, apiflags);
728 if (err != ERR_OK) {
729 if (!(apiflags & NETCONN_NOAUTORCVD)) {
730 API_MSG_VAR_FREE(msg);
731 }
732 return err;
733 }
734 buf = *new_buf;
735 if (!(apiflags & NETCONN_NOAUTORCVD)) {
736 /* Let the stack know that we have taken the data. */
737 u16_t len = buf ? buf->tot_len : 1;
738 /* don't care for the return value of lwip_netconn_do_recv */
739 /* @todo: this should really be fixed, e.g. by retrying in poll on error */
740 netconn_tcp_recvd_msg(conn, len, &API_VAR_REF(msg));
741 API_MSG_VAR_FREE(msg);
742 }
743
744 /* If we are closed, we indicate that we no longer wish to use the socket */
745 if (buf == NULL) {
746 if (apiflags & NETCONN_NOFIN) {
747 /* received a FIN but the caller cannot handle it right now:
748 re-enqueue it and return "no data" */
749 netconn_set_flags(conn, NETCONN_FIN_RX_PENDING);
750 return ERR_WOULDBLOCK;
751 } else {
752handle_fin:
753 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
754 if (conn->pcb.ip == NULL) {
755 /* race condition: RST during recv */
756 err = netconn_err(conn);
757 if (err != ERR_OK) {
758 return err;
759 }
760 return ERR_RST;
761 }
762 /* RX side is closed, so deallocate the recvmbox */
763 netconn_close_shutdown(conn, NETCONN_SHUT_RD);
764 /* Don' store ERR_CLSD as conn->err since we are only half-closed */
765 return ERR_CLSD;
766 }
767 }
768 return err;
769}
770
781err_t
782netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
783{
784 LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) &&
785 NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
786
787 return netconn_recv_data_tcp(conn, new_buf, 0);
788}
789
802err_t
803netconn_recv_tcp_pbuf_flags(struct netconn *conn, struct pbuf **new_buf, u8_t apiflags)
804{
805 LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) &&
806 NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
807
808 return netconn_recv_data_tcp(conn, new_buf, apiflags);
809}
810#endif /* LWIP_TCP */
811
821err_t
822netconn_recv_udp_raw_netbuf(struct netconn *conn, struct netbuf **new_buf)
823{
824 LWIP_ERROR("netconn_recv_udp_raw_netbuf: invalid conn", (conn != NULL) &&
825 NETCONNTYPE_GROUP(netconn_type(conn)) != NETCONN_TCP, return ERR_ARG;);
826
827 return netconn_recv_data(conn, (void **)new_buf, 0);
828}
829
841err_t
842netconn_recv_udp_raw_netbuf_flags(struct netconn *conn, struct netbuf **new_buf, u8_t apiflags)
843{
844 LWIP_ERROR("netconn_recv_udp_raw_netbuf: invalid conn", (conn != NULL) &&
845 NETCONNTYPE_GROUP(netconn_type(conn)) != NETCONN_TCP, return ERR_ARG;);
846
847 return netconn_recv_data(conn, (void **)new_buf, apiflags);
848}
849
859err_t
860netconn_recv(struct netconn *conn, struct netbuf **new_buf)
861{
862#if LWIP_TCP
863 struct netbuf *buf = NULL;
864 err_t err;
865#endif /* LWIP_TCP */
866
867 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
868 *new_buf = NULL;
869 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
870
871#if LWIP_TCP
872#if (LWIP_UDP || LWIP_RAW)
873 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
874#endif /* (LWIP_UDP || LWIP_RAW) */
875 {
876 struct pbuf *p = NULL;
877 /* This is not a listening netconn, since recvmbox is set */
878
879 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
880 if (buf == NULL) {
881 return ERR_MEM;
882 }
883
884 err = netconn_recv_data_tcp(conn, &p, 0);
885 if (err != ERR_OK) {
886 memp_free(MEMP_NETBUF, buf);
887 return err;
888 }
889 LWIP_ASSERT("p != NULL", p != NULL);
890
891 buf->p = p;
892 buf->ptr = p;
893 buf->port = 0;
894 ip_addr_set_zero(&buf->addr);
895 *new_buf = buf;
896 /* don't set conn->last_err: it's only ERR_OK, anyway */
897 return ERR_OK;
898 }
899#endif /* LWIP_TCP */
900#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
901 else
902#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
903 {
904#if (LWIP_UDP || LWIP_RAW)
905 return netconn_recv_data(conn, (void **)new_buf, 0);
906#endif /* (LWIP_UDP || LWIP_RAW) */
907 }
908}
909
921err_t
922netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port)
923{
924 if (buf != NULL) {
925 ip_addr_set(&buf->addr, addr);
926 buf->port = port;
927 return netconn_send(conn, buf);
928 }
929 return ERR_VAL;
930}
931
940err_t
941netconn_send(struct netconn *conn, struct netbuf *buf)
942{
943 API_MSG_VAR_DECLARE(msg);
944 err_t err;
945
946 LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
947
948 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
949
950 API_MSG_VAR_ALLOC(msg);
951 API_MSG_VAR_REF(msg).conn = conn;
952 API_MSG_VAR_REF(msg).msg.b = buf;
953 err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg));
954 API_MSG_VAR_FREE(msg);
955
956 return err;
957}
958
973err_t
974netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
975 u8_t apiflags, size_t *bytes_written)
976{
977 struct netvector vector;
978 vector.ptr = dataptr;
979 vector.len = size;
980 return netconn_write_vectors_partly(conn, &vector, 1, apiflags, bytes_written);
981}
982
996err_t
997netconn_write_vectors_partly(struct netconn *conn, struct netvector *vectors, u16_t vectorcnt,
998 u8_t apiflags, size_t *bytes_written)
999{
1000 API_MSG_VAR_DECLARE(msg);
1001 err_t err;
1002 u8_t dontblock;
1003 size_t size;
1004 int i;
1005
1006 LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
1007 LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP), return ERR_VAL;);
1008 dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
1009#if LWIP_SO_SNDTIMEO
1010 if (conn->send_timeout != 0) {
1011 dontblock = 1;
1012 }
1013#endif /* LWIP_SO_SNDTIMEO */
1014 if (dontblock && !bytes_written) {
1015 /* This implies netconn_write() cannot be used for non-blocking send, since
1016 it has no way to return the number of bytes written. */
1017 return ERR_VAL;
1018 }
1019
1020 /* sum up the total size */
1021 size = 0;
1022 for (i = 0; i < vectorcnt; i++) {
1023 size += vectors[i].len;
1024 if (size < vectors[i].len) {
1025 /* overflow */
1026 return ERR_VAL;
1027 }
1028 }
1029 if (size == 0) {
1030 return ERR_OK;
1031 } else if (size > SSIZE_MAX) {
1032 ssize_t limited;
1033 /* this is required by the socket layer (cannot send full size_t range) */
1034 if (!bytes_written) {
1035 return ERR_VAL;
1036 }
1037 /* limit the amount of data to send */
1038 limited = SSIZE_MAX;
1039 size = (size_t)limited;
1040 }
1041
1042 API_MSG_VAR_ALLOC(msg);
1043 /* non-blocking write sends as much */
1044 API_MSG_VAR_REF(msg).conn = conn;
1045 API_MSG_VAR_REF(msg).msg.w.vector = vectors;
1046 API_MSG_VAR_REF(msg).msg.w.vector_cnt = vectorcnt;
1047 API_MSG_VAR_REF(msg).msg.w.vector_off = 0;
1048 API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags;
1049 API_MSG_VAR_REF(msg).msg.w.len = size;
1050 API_MSG_VAR_REF(msg).msg.w.offset = 0;
1051#if LWIP_SO_SNDTIMEO
1052 if (conn->send_timeout != 0) {
1053 /* get the time we started, which is later compared to
1054 sys_now() + conn->send_timeout */
1055 API_MSG_VAR_REF(msg).msg.w.time_started = sys_now();
1056 } else {
1057 API_MSG_VAR_REF(msg).msg.w.time_started = 0;
1058 }
1059#endif /* LWIP_SO_SNDTIMEO */
1060
1061 /* For locking the core: this _can_ be delayed on low memory/low send buffer,
1062 but if it is, this is done inside api_msg.c:do_write(), so we can use the
1063 non-blocking version here. */
1064 err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
1065 if (err == ERR_OK) {
1066 if (bytes_written != NULL) {
1067 *bytes_written = API_MSG_VAR_REF(msg).msg.w.offset;
1068 }
1069 /* for blocking, check all requested bytes were written, NOTE: send_timeout is
1070 treated as dontblock (see dontblock assignment above) */
1071 if (!dontblock) {
1072 LWIP_ASSERT("do_write failed to write all bytes", API_MSG_VAR_REF(msg).msg.w.offset == size);
1073 }
1074 }
1075 API_MSG_VAR_FREE(msg);
1076
1077 return err;
1078}
1079
1088static err_t
1089netconn_close_shutdown(struct netconn *conn, u8_t how)
1090{
1091 API_MSG_VAR_DECLARE(msg);
1092 err_t err;
1093 LWIP_UNUSED_ARG(how);
1094
1095 LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
1096
1097 API_MSG_VAR_ALLOC(msg);
1098 API_MSG_VAR_REF(msg).conn = conn;
1099#if LWIP_TCP
1100 /* shutting down both ends is the same as closing */
1101 API_MSG_VAR_REF(msg).msg.sd.shut = how;
1102#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
1103 /* get the time we started, which is later compared to
1104 sys_now() + conn->send_timeout */
1105 API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
1106#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
1107 API_MSG_VAR_REF(msg).msg.sd.polls_left =
1108 ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
1109#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
1110#endif /* LWIP_TCP */
1111 err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg));
1112 API_MSG_VAR_FREE(msg);
1113
1114 return err;
1115}
1116
1124err_t
1125netconn_close(struct netconn *conn)
1126{
1127 /* shutting down both ends is the same as closing */
1128 return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
1129}
1130
1138err_t
1139netconn_err(struct netconn *conn)
1140{
1141 err_t err;
1143 if (conn == NULL) {
1144 return ERR_OK;
1145 }
1146 SYS_ARCH_PROTECT(lev);
1147 err = conn->pending_err;
1148 conn->pending_err = ERR_OK;
1149 SYS_ARCH_UNPROTECT(lev);
1150 return err;
1151}
1152
1162err_t
1163netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
1164{
1165 return netconn_close_shutdown(conn, (u8_t)((shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0)));
1166}
1167
1168#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
1180err_t
1181netconn_join_leave_group(struct netconn *conn,
1182 const ip_addr_t *multiaddr,
1183 const ip_addr_t *netif_addr,
1184 enum netconn_igmp join_or_leave)
1185{
1186 API_MSG_VAR_DECLARE(msg);
1187 err_t err;
1188
1189 LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
1190
1191 API_MSG_VAR_ALLOC(msg);
1192
1193#if LWIP_IPV4
1194 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
1195 if (multiaddr == NULL) {
1196 multiaddr = IP4_ADDR_ANY;
1197 }
1198 if (netif_addr == NULL) {
1199 netif_addr = IP4_ADDR_ANY;
1200 }
1201#endif /* LWIP_IPV4 */
1202
1203 API_MSG_VAR_REF(msg).conn = conn;
1204 API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
1205 API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr);
1206 API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave;
1207 err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg));
1208 API_MSG_VAR_FREE(msg);
1209
1210 return err;
1211}
1222err_t
1223netconn_join_leave_group_netif(struct netconn *conn,
1224 const ip_addr_t *multiaddr,
1225 u8_t if_idx,
1226 enum netconn_igmp join_or_leave)
1227{
1228 API_MSG_VAR_DECLARE(msg);
1229 err_t err;
1230
1231 LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
1232
1233 API_MSG_VAR_ALLOC(msg);
1234
1235#if LWIP_IPV4
1236 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
1237 if (multiaddr == NULL) {
1238 multiaddr = IP4_ADDR_ANY;
1239 }
1240 if (if_idx == NETIF_NO_INDEX) {
1241 return ERR_IF;
1242 }
1243#endif /* LWIP_IPV4 */
1244
1245 API_MSG_VAR_REF(msg).conn = conn;
1246 API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
1247 API_MSG_VAR_REF(msg).msg.jl.if_idx = if_idx;
1248 API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave;
1249 err = netconn_apimsg(lwip_netconn_do_join_leave_group_netif, &API_MSG_VAR_REF(msg));
1250 API_MSG_VAR_FREE(msg);
1251
1252 return err;
1253}
1254#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
1255
1256#if LWIP_DNS
1268#if LWIP_IPV4 && LWIP_IPV6
1270err_t
1271netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype)
1272#else
1273err_t
1274netconn_gethostbyname(const char *name, ip_addr_t *addr)
1275#endif
1276{
1277 API_VAR_DECLARE(struct dns_api_msg, msg);
1278#if !LWIP_MPU_COMPATIBLE
1279 sys_sem_t sem;
1280#endif /* LWIP_MPU_COMPATIBLE */
1281 err_t err;
1282 err_t cberr;
1283
1284 LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
1285 LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
1286#if LWIP_MPU_COMPATIBLE
1287 if (strlen(name) >= DNS_MAX_NAME_LENGTH) {
1288 return ERR_ARG;
1289 }
1290#endif
1291
1292#ifdef LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE
1293#if LWIP_IPV4 && LWIP_IPV6
1294 if (LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, dns_addrtype, &err)) {
1295#else
1296 if (LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, NETCONN_DNS_DEFAULT, &err)) {
1297#endif /* LWIP_IPV4 && LWIP_IPV6 */
1298 return err;
1299 }
1300#endif /* LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE */
1301
1302 API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM);
1303#if LWIP_MPU_COMPATIBLE
1304 strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH - 1);
1305 API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH - 1] = 0;
1306#else /* LWIP_MPU_COMPATIBLE */
1307 msg.err = &err;
1308 msg.sem = &sem;
1309 API_VAR_REF(msg).addr = API_VAR_REF(addr);
1310 API_VAR_REF(msg).name = name;
1311#endif /* LWIP_MPU_COMPATIBLE */
1312#if LWIP_IPV4 && LWIP_IPV6
1313 API_VAR_REF(msg).dns_addrtype = dns_addrtype;
1314#endif /* LWIP_IPV4 && LWIP_IPV6 */
1315#if LWIP_NETCONN_SEM_PER_THREAD
1316 API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET();
1317#else /* LWIP_NETCONN_SEM_PER_THREAD*/
1318 err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0);
1319 if (err != ERR_OK) {
1320 API_VAR_FREE(MEMP_DNS_API_MSG, msg);
1321 return err;
1322 }
1323#endif /* LWIP_NETCONN_SEM_PER_THREAD */
1324
1325 cberr = tcpip_send_msg_wait_sem(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg), API_EXPR_REF(API_VAR_REF(msg).sem));
1326#if !LWIP_NETCONN_SEM_PER_THREAD
1327 sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
1328#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
1329 if (cberr != ERR_OK) {
1330 API_VAR_FREE(MEMP_DNS_API_MSG, msg);
1331 return cberr;
1332 }
1333
1334#if LWIP_MPU_COMPATIBLE
1335 *addr = msg->addr;
1336 err = msg->err;
1337#endif /* LWIP_MPU_COMPATIBLE */
1338
1339 API_VAR_FREE(MEMP_DNS_API_MSG, msg);
1340 return err;
1341}
1342#endif /* LWIP_DNS*/
1343
1344#if LWIP_NETCONN_SEM_PER_THREAD
1345void
1346netconn_thread_init(void)
1347{
1348 sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
1349 if (!sys_sem_valid(sem)) {
1350 /* call alloc only once */
1351 LWIP_NETCONN_THREAD_SEM_ALLOC();
1352 LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET()));
1353 }
1354}
1355
1356void
1357netconn_thread_cleanup(void)
1358{
1359 sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
1360 if (sys_sem_valid(sem)) {
1361 /* call free only once */
1362 LWIP_NETCONN_THREAD_SEM_FREE();
1363 }
1364}
1365#endif /* LWIP_NETCONN_SEM_PER_THREAD */
1366
1367#endif /* LWIP_NETCONN */
#define LWIP_UNUSED_ARG(x)
Definition arch.h:373
@ ERR_RST
Definition err.h:84
@ ERR_IF
Definition err.h:79
@ ERR_OK
Definition err.h:55
@ ERR_CLSD
Definition err.h:86
@ ERR_VAL
Definition err.h:67
@ ERR_MEM
Definition err.h:57
@ ERR_CONN
Definition err.h:77
@ ERR_ARG
Definition err.h:88
@ ERR_WOULDBLOCK
Definition err.h:69
@ ERR_TIMEOUT
Definition err.h:61
#define IP4_ADDR_ANY
Definition tcpip.h:1053
#define API_LIB_DEBUG
Definition opt.h:3380
#define DNS_MAX_NAME_LENGTH
Definition opt.h:1163
#define LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT
Definition opt.h:2130
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
Definition sys_arch.c:254
int sys_mbox_valid(sys_mbox_t *mbox)
Definition sys_arch.c:167
void sys_mbox_free(sys_mbox_t *mbox)
Definition sys_arch.c:162
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
Definition sys_arch.c:259
int sys_sem_valid(sys_sem_t *sem)
Definition sys_arch.c:281
void sys_sem_free(sys_sem_t *sem)
Definition sys_arch.c:334
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
Definition sys_arch.c:263
u32_t sys_now(void)
Definition sys_arch.c:411
void * memp_malloc(memp_t type)
Definition memp.c:337
void memp_free(memp_t type, void *mem)
Definition memp.c:420
void(*) tcpip_callback_fn(void *ctx)
Definition ps2ip.h:74
Definition tcpip.h:234
u16 tot_len
Definition tcpip.h:248
u16 len
Definition tcpip.h:251
#define SYS_ARCH_DECL_PROTECT(lev)
Definition sys.h:512
#define SYS_MBOX_EMPTY
Definition sys.h:92
#define SYS_ARCH_TIMEOUT
Definition sys.h:87
err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t *sem)
Definition tcpip.c:451