1195972f6Sopenharmony_ci/** 2195972f6Sopenharmony_ci * @file 3195972f6Sopenharmony_ci * Sequential API External module 4195972f6Sopenharmony_ci * 5195972f6Sopenharmony_ci * @defgroup netconn Netconn API 6195972f6Sopenharmony_ci * @ingroup sequential_api 7195972f6Sopenharmony_ci * Thread-safe, to be called from non-TCPIP threads only. 8195972f6Sopenharmony_ci * TX/RX handling based on @ref netbuf (containing @ref pbuf) 9195972f6Sopenharmony_ci * to avoid copying data around. 10195972f6Sopenharmony_ci * 11195972f6Sopenharmony_ci * @defgroup netconn_common Common functions 12195972f6Sopenharmony_ci * @ingroup netconn 13195972f6Sopenharmony_ci * For use with TCP and UDP 14195972f6Sopenharmony_ci * 15195972f6Sopenharmony_ci * @defgroup netconn_tcp TCP only 16195972f6Sopenharmony_ci * @ingroup netconn 17195972f6Sopenharmony_ci * TCP only functions 18195972f6Sopenharmony_ci * 19195972f6Sopenharmony_ci * @defgroup netconn_udp UDP only 20195972f6Sopenharmony_ci * @ingroup netconn 21195972f6Sopenharmony_ci * UDP only functions 22195972f6Sopenharmony_ci */ 23195972f6Sopenharmony_ci 24195972f6Sopenharmony_ci/* 25195972f6Sopenharmony_ci * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 26195972f6Sopenharmony_ci * All rights reserved. 27195972f6Sopenharmony_ci * 28195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification, 29195972f6Sopenharmony_ci * are permitted provided that the following conditions are met: 30195972f6Sopenharmony_ci * 31195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 32195972f6Sopenharmony_ci * this list of conditions and the following disclaimer. 33195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 34195972f6Sopenharmony_ci * this list of conditions and the following disclaimer in the documentation 35195972f6Sopenharmony_ci * and/or other materials provided with the distribution. 36195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products 37195972f6Sopenharmony_ci * derived from this software without specific prior written permission. 38195972f6Sopenharmony_ci * 39195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 40195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 41195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 42195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 43195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 44195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 45195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 46195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 47195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 48195972f6Sopenharmony_ci * OF SUCH DAMAGE. 49195972f6Sopenharmony_ci * 50195972f6Sopenharmony_ci * This file is part of the lwIP TCP/IP stack. 51195972f6Sopenharmony_ci * 52195972f6Sopenharmony_ci * Author: Adam Dunkels <adam@sics.se> 53195972f6Sopenharmony_ci */ 54195972f6Sopenharmony_ci 55195972f6Sopenharmony_ci/* This is the part of the API that is linked with 56195972f6Sopenharmony_ci the application */ 57195972f6Sopenharmony_ci 58195972f6Sopenharmony_ci#include "lwip/opt.h" 59195972f6Sopenharmony_ci 60195972f6Sopenharmony_ci#if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */ 61195972f6Sopenharmony_ci 62195972f6Sopenharmony_ci#include "lwip/api.h" 63195972f6Sopenharmony_ci#include "lwip/memp.h" 64195972f6Sopenharmony_ci 65195972f6Sopenharmony_ci#include "lwip/ip.h" 66195972f6Sopenharmony_ci#include "lwip/raw.h" 67195972f6Sopenharmony_ci#include "lwip/udp.h" 68195972f6Sopenharmony_ci#include "lwip/priv/api_msg.h" 69195972f6Sopenharmony_ci#include "lwip/priv/tcp_priv.h" 70195972f6Sopenharmony_ci#include "lwip/priv/tcpip_priv.h" 71195972f6Sopenharmony_ci 72195972f6Sopenharmony_ci#ifdef LWIP_HOOK_FILENAME 73195972f6Sopenharmony_ci#include LWIP_HOOK_FILENAME 74195972f6Sopenharmony_ci#endif 75195972f6Sopenharmony_ci 76195972f6Sopenharmony_ci#include <string.h> 77195972f6Sopenharmony_ci 78195972f6Sopenharmony_ci#define API_MSG_VAR_REF(name) API_VAR_REF(name) 79195972f6Sopenharmony_ci#define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name) 80195972f6Sopenharmony_ci#define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM) 81195972f6Sopenharmony_ci#define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL) 82195972f6Sopenharmony_ci#define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name) 83195972f6Sopenharmony_ci 84195972f6Sopenharmony_ci#if TCP_LISTEN_BACKLOG 85195972f6Sopenharmony_ci/* need to allocate API message for accept so empty message pool does not result in event loss 86195972f6Sopenharmony_ci * see bug #47512: MPU_COMPATIBLE may fail on empty pool */ 87195972f6Sopenharmony_ci#define API_MSG_VAR_ALLOC_ACCEPT(msg) API_MSG_VAR_ALLOC(msg) 88195972f6Sopenharmony_ci#define API_MSG_VAR_FREE_ACCEPT(msg) API_MSG_VAR_FREE(msg) 89195972f6Sopenharmony_ci#else /* TCP_LISTEN_BACKLOG */ 90195972f6Sopenharmony_ci#define API_MSG_VAR_ALLOC_ACCEPT(msg) 91195972f6Sopenharmony_ci#define API_MSG_VAR_FREE_ACCEPT(msg) 92195972f6Sopenharmony_ci#endif /* TCP_LISTEN_BACKLOG */ 93195972f6Sopenharmony_ci 94195972f6Sopenharmony_ci#if LWIP_NETCONN_FULLDUPLEX 95195972f6Sopenharmony_ci#define NETCONN_RECVMBOX_WAITABLE(conn) (sys_mbox_valid(&(conn)->recvmbox) && (((conn)->flags & NETCONN_FLAG_MBOXINVALID) == 0)) 96195972f6Sopenharmony_ci#define NETCONN_ACCEPTMBOX_WAITABLE(conn) (sys_mbox_valid(&(conn)->acceptmbox) && (((conn)->flags & (NETCONN_FLAG_MBOXCLOSED|NETCONN_FLAG_MBOXINVALID)) == 0)) 97195972f6Sopenharmony_ci#define NETCONN_MBOX_WAITING_INC(conn) SYS_ARCH_INC(conn->mbox_threads_waiting, 1) 98195972f6Sopenharmony_ci#define NETCONN_MBOX_WAITING_DEC(conn) SYS_ARCH_DEC(conn->mbox_threads_waiting, 1) 99195972f6Sopenharmony_ci#else /* LWIP_NETCONN_FULLDUPLEX */ 100195972f6Sopenharmony_ci#define NETCONN_RECVMBOX_WAITABLE(conn) sys_mbox_valid(&(conn)->recvmbox) 101195972f6Sopenharmony_ci#define NETCONN_ACCEPTMBOX_WAITABLE(conn) (sys_mbox_valid(&(conn)->acceptmbox) && (((conn)->flags & NETCONN_FLAG_MBOXCLOSED) == 0)) 102195972f6Sopenharmony_ci#define NETCONN_MBOX_WAITING_INC(conn) 103195972f6Sopenharmony_ci#define NETCONN_MBOX_WAITING_DEC(conn) 104195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_FULLDUPLEX */ 105195972f6Sopenharmony_ci 106195972f6Sopenharmony_cistatic err_t netconn_close_shutdown(struct netconn *conn, u8_t how); 107195972f6Sopenharmony_ci 108195972f6Sopenharmony_ci/** 109195972f6Sopenharmony_ci * Call the lower part of a netconn_* function 110195972f6Sopenharmony_ci * This function is then running in the thread context 111195972f6Sopenharmony_ci * of tcpip_thread and has exclusive access to lwIP core code. 112195972f6Sopenharmony_ci * 113195972f6Sopenharmony_ci * @param fn function to call 114195972f6Sopenharmony_ci * @param apimsg a struct containing the function to call and its parameters 115195972f6Sopenharmony_ci * @return ERR_OK if the function was called, another err_t if not 116195972f6Sopenharmony_ci */ 117195972f6Sopenharmony_cistatic err_t 118195972f6Sopenharmony_cinetconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg) 119195972f6Sopenharmony_ci{ 120195972f6Sopenharmony_ci err_t err; 121195972f6Sopenharmony_ci 122195972f6Sopenharmony_ci#ifdef LWIP_DEBUG 123195972f6Sopenharmony_ci /* catch functions that don't set err */ 124195972f6Sopenharmony_ci apimsg->err = ERR_VAL; 125195972f6Sopenharmony_ci#endif /* LWIP_DEBUG */ 126195972f6Sopenharmony_ci 127195972f6Sopenharmony_ci#if LWIP_NETCONN_SEM_PER_THREAD 128195972f6Sopenharmony_ci apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); 129195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_SEM_PER_THREAD */ 130195972f6Sopenharmony_ci 131195972f6Sopenharmony_ci err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg)); 132195972f6Sopenharmony_ci if (err == ERR_OK) { 133195972f6Sopenharmony_ci return apimsg->err; 134195972f6Sopenharmony_ci } 135195972f6Sopenharmony_ci return err; 136195972f6Sopenharmony_ci} 137195972f6Sopenharmony_ci 138195972f6Sopenharmony_ci/** 139195972f6Sopenharmony_ci * Create a new netconn (of a specific type) that has a callback function. 140195972f6Sopenharmony_ci * The corresponding pcb is also created. 141195972f6Sopenharmony_ci * 142195972f6Sopenharmony_ci * @param t the type of 'connection' to create (@see enum netconn_type) 143195972f6Sopenharmony_ci * @param proto the IP protocol for RAW IP pcbs 144195972f6Sopenharmony_ci * @param callback a function to call on status changes (RX available, TX'ed) 145195972f6Sopenharmony_ci * @return a newly allocated struct netconn or 146195972f6Sopenharmony_ci * NULL on memory error 147195972f6Sopenharmony_ci */ 148195972f6Sopenharmony_cistruct netconn * 149195972f6Sopenharmony_cinetconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) 150195972f6Sopenharmony_ci{ 151195972f6Sopenharmony_ci struct netconn *conn; 152195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 153195972f6Sopenharmony_ci API_MSG_VAR_ALLOC_RETURN_NULL(msg); 154195972f6Sopenharmony_ci 155195972f6Sopenharmony_ci conn = netconn_alloc(t, callback); 156195972f6Sopenharmony_ci if (conn != NULL) { 157195972f6Sopenharmony_ci err_t err; 158195972f6Sopenharmony_ci 159195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.n.proto = proto; 160195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 161195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg)); 162195972f6Sopenharmony_ci if (err != ERR_OK) { 163195972f6Sopenharmony_ci LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); 164195972f6Sopenharmony_ci LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); 165195972f6Sopenharmony_ci#if LWIP_TCP 166195972f6Sopenharmony_ci LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); 167195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 168195972f6Sopenharmony_ci#if !LWIP_NETCONN_SEM_PER_THREAD 169195972f6Sopenharmony_ci LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); 170195972f6Sopenharmony_ci sys_sem_free(&conn->op_completed); 171195972f6Sopenharmony_ci#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ 172195972f6Sopenharmony_ci sys_mbox_free(&conn->recvmbox); 173195972f6Sopenharmony_ci memp_free(MEMP_NETCONN, conn); 174195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 175195972f6Sopenharmony_ci return NULL; 176195972f6Sopenharmony_ci } 177195972f6Sopenharmony_ci } 178195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 179195972f6Sopenharmony_ci return conn; 180195972f6Sopenharmony_ci} 181195972f6Sopenharmony_ci 182195972f6Sopenharmony_ci/** 183195972f6Sopenharmony_ci * @ingroup netconn_common 184195972f6Sopenharmony_ci * Close a netconn 'connection' and free all its resources but not the netconn itself. 185195972f6Sopenharmony_ci * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate 186195972f6Sopenharmony_ci * after this returns. 187195972f6Sopenharmony_ci * 188195972f6Sopenharmony_ci * @param conn the netconn to delete 189195972f6Sopenharmony_ci * @return ERR_OK if the connection was deleted 190195972f6Sopenharmony_ci */ 191195972f6Sopenharmony_cierr_t 192195972f6Sopenharmony_cinetconn_prepare_delete(struct netconn *conn) 193195972f6Sopenharmony_ci{ 194195972f6Sopenharmony_ci err_t err; 195195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 196195972f6Sopenharmony_ci 197195972f6Sopenharmony_ci /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ 198195972f6Sopenharmony_ci if (conn == NULL) { 199195972f6Sopenharmony_ci return ERR_OK; 200195972f6Sopenharmony_ci } 201195972f6Sopenharmony_ci 202195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 203195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 204195972f6Sopenharmony_ci#if LWIP_TCP 205195972f6Sopenharmony_ci#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER 206195972f6Sopenharmony_ci /* get the time we started, which is later compared to 207195972f6Sopenharmony_ci sys_now() + conn->send_timeout */ 208195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); 209195972f6Sopenharmony_ci#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ 210195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.sd.polls_left = 211195972f6Sopenharmony_ci ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; 212195972f6Sopenharmony_ci#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ 213195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 214195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg)); 215195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 216195972f6Sopenharmony_ci 217195972f6Sopenharmony_ci if (err != ERR_OK) { 218195972f6Sopenharmony_ci return err; 219195972f6Sopenharmony_ci } 220195972f6Sopenharmony_ci return ERR_OK; 221195972f6Sopenharmony_ci} 222195972f6Sopenharmony_ci 223195972f6Sopenharmony_ci/** 224195972f6Sopenharmony_ci * @ingroup netconn_common 225195972f6Sopenharmony_ci * Close a netconn 'connection' and free its resources. 226195972f6Sopenharmony_ci * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate 227195972f6Sopenharmony_ci * after this returns. 228195972f6Sopenharmony_ci * 229195972f6Sopenharmony_ci * @param conn the netconn to delete 230195972f6Sopenharmony_ci * @return ERR_OK if the connection was deleted 231195972f6Sopenharmony_ci */ 232195972f6Sopenharmony_cierr_t 233195972f6Sopenharmony_cinetconn_delete(struct netconn *conn) 234195972f6Sopenharmony_ci{ 235195972f6Sopenharmony_ci err_t err; 236195972f6Sopenharmony_ci 237195972f6Sopenharmony_ci /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */ 238195972f6Sopenharmony_ci if (conn == NULL) { 239195972f6Sopenharmony_ci return ERR_OK; 240195972f6Sopenharmony_ci } 241195972f6Sopenharmony_ci 242195972f6Sopenharmony_ci#if LWIP_NETCONN_FULLDUPLEX 243195972f6Sopenharmony_ci if (conn->flags & NETCONN_FLAG_MBOXINVALID) { 244195972f6Sopenharmony_ci /* Already called netconn_prepare_delete() before */ 245195972f6Sopenharmony_ci err = ERR_OK; 246195972f6Sopenharmony_ci } else 247195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_FULLDUPLEX */ 248195972f6Sopenharmony_ci { 249195972f6Sopenharmony_ci err = netconn_prepare_delete(conn); 250195972f6Sopenharmony_ci } 251195972f6Sopenharmony_ci if (err == ERR_OK) { 252195972f6Sopenharmony_ci netconn_free(conn); 253195972f6Sopenharmony_ci } 254195972f6Sopenharmony_ci return err; 255195972f6Sopenharmony_ci} 256195972f6Sopenharmony_ci 257195972f6Sopenharmony_ci/** 258195972f6Sopenharmony_ci * Get the local or remote IP address and port of a netconn. 259195972f6Sopenharmony_ci * For RAW netconns, this returns the protocol instead of a port! 260195972f6Sopenharmony_ci * 261195972f6Sopenharmony_ci * @param conn the netconn to query 262195972f6Sopenharmony_ci * @param addr a pointer to which to save the IP address 263195972f6Sopenharmony_ci * @param port a pointer to which to save the port (or protocol for RAW) 264195972f6Sopenharmony_ci * @param local 1 to get the local IP address, 0 to get the remote one 265195972f6Sopenharmony_ci * @return ERR_CONN for invalid connections 266195972f6Sopenharmony_ci * ERR_OK if the information was retrieved 267195972f6Sopenharmony_ci */ 268195972f6Sopenharmony_cierr_t 269195972f6Sopenharmony_cinetconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local) 270195972f6Sopenharmony_ci{ 271195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 272195972f6Sopenharmony_ci err_t err; 273195972f6Sopenharmony_ci 274195972f6Sopenharmony_ci LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;); 275195972f6Sopenharmony_ci LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;); 276195972f6Sopenharmony_ci LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;); 277195972f6Sopenharmony_ci 278195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 279195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 280195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.ad.local = local; 281195972f6Sopenharmony_ci#if LWIP_MPU_COMPATIBLE 282195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg)); 283195972f6Sopenharmony_ci *addr = msg->msg.ad.ipaddr; 284195972f6Sopenharmony_ci *port = msg->msg.ad.port; 285195972f6Sopenharmony_ci#else /* LWIP_MPU_COMPATIBLE */ 286195972f6Sopenharmony_ci msg.msg.ad.ipaddr = addr; 287195972f6Sopenharmony_ci msg.msg.ad.port = port; 288195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_getaddr, &msg); 289195972f6Sopenharmony_ci#endif /* LWIP_MPU_COMPATIBLE */ 290195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 291195972f6Sopenharmony_ci 292195972f6Sopenharmony_ci return err; 293195972f6Sopenharmony_ci} 294195972f6Sopenharmony_ci 295195972f6Sopenharmony_ci/** 296195972f6Sopenharmony_ci * @ingroup netconn_common 297195972f6Sopenharmony_ci * Bind a netconn to a specific local IP address and port. 298195972f6Sopenharmony_ci * Binding one netconn twice might not always be checked correctly! 299195972f6Sopenharmony_ci * 300195972f6Sopenharmony_ci * @param conn the netconn to bind 301195972f6Sopenharmony_ci * @param addr the local IP address to bind the netconn to 302195972f6Sopenharmony_ci * (use IP4_ADDR_ANY/IP6_ADDR_ANY to bind to all addresses) 303195972f6Sopenharmony_ci * @param port the local port to bind the netconn to (not used for RAW) 304195972f6Sopenharmony_ci * @return ERR_OK if bound, any other err_t on failure 305195972f6Sopenharmony_ci */ 306195972f6Sopenharmony_cierr_t 307195972f6Sopenharmony_cinetconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) 308195972f6Sopenharmony_ci{ 309195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 310195972f6Sopenharmony_ci err_t err; 311195972f6Sopenharmony_ci 312195972f6Sopenharmony_ci LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); 313195972f6Sopenharmony_ci 314195972f6Sopenharmony_ci#if LWIP_IPV4 315195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ 316195972f6Sopenharmony_ci if (addr == NULL) { 317195972f6Sopenharmony_ci addr = IP4_ADDR_ANY; 318195972f6Sopenharmony_ci } 319195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 320195972f6Sopenharmony_ci 321195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 322195972f6Sopenharmony_ci /* "Socket API like" dual-stack support: If IP to bind to is IP6_ADDR_ANY, 323195972f6Sopenharmony_ci * and NETCONN_FLAG_IPV6_V6ONLY is 0, use IP_ANY_TYPE to bind 324195972f6Sopenharmony_ci */ 325195972f6Sopenharmony_ci if ((netconn_get_ipv6only(conn) == 0) && 326195972f6Sopenharmony_ci ip_addr_cmp(addr, IP6_ADDR_ANY)) { 327195972f6Sopenharmony_ci addr = IP_ANY_TYPE; 328195972f6Sopenharmony_ci } 329195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_IPV6 */ 330195972f6Sopenharmony_ci 331195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 332195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 333195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); 334195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.bc.port = port; 335195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); 336195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 337195972f6Sopenharmony_ci 338195972f6Sopenharmony_ci return err; 339195972f6Sopenharmony_ci} 340195972f6Sopenharmony_ci 341195972f6Sopenharmony_ci/** 342195972f6Sopenharmony_ci * @ingroup netconn_common 343195972f6Sopenharmony_ci * Bind a netconn to a specific interface and port. 344195972f6Sopenharmony_ci * Binding one netconn twice might not always be checked correctly! 345195972f6Sopenharmony_ci * 346195972f6Sopenharmony_ci * @param conn the netconn to bind 347195972f6Sopenharmony_ci * @param if_idx the local interface index to bind the netconn to 348195972f6Sopenharmony_ci * @return ERR_OK if bound, any other err_t on failure 349195972f6Sopenharmony_ci */ 350195972f6Sopenharmony_cierr_t 351195972f6Sopenharmony_cinetconn_bind_if(struct netconn *conn, u8_t if_idx) 352195972f6Sopenharmony_ci{ 353195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 354195972f6Sopenharmony_ci err_t err; 355195972f6Sopenharmony_ci 356195972f6Sopenharmony_ci LWIP_ERROR("netconn_bind_if: invalid conn", (conn != NULL), return ERR_ARG;); 357195972f6Sopenharmony_ci 358195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 359195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 360195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx; 361195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_bind_if, &API_MSG_VAR_REF(msg)); 362195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 363195972f6Sopenharmony_ci 364195972f6Sopenharmony_ci return err; 365195972f6Sopenharmony_ci} 366195972f6Sopenharmony_ci 367195972f6Sopenharmony_ci/** 368195972f6Sopenharmony_ci * @ingroup netconn_common 369195972f6Sopenharmony_ci * Connect a netconn to a specific remote IP address and port. 370195972f6Sopenharmony_ci * 371195972f6Sopenharmony_ci * @param conn the netconn to connect 372195972f6Sopenharmony_ci * @param addr the remote IP address to connect to 373195972f6Sopenharmony_ci * @param port the remote port to connect to (no used for RAW) 374195972f6Sopenharmony_ci * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise 375195972f6Sopenharmony_ci */ 376195972f6Sopenharmony_cierr_t 377195972f6Sopenharmony_cinetconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port) 378195972f6Sopenharmony_ci{ 379195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 380195972f6Sopenharmony_ci err_t err; 381195972f6Sopenharmony_ci 382195972f6Sopenharmony_ci LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;); 383195972f6Sopenharmony_ci 384195972f6Sopenharmony_ci#if LWIP_IPV4 385195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ 386195972f6Sopenharmony_ci if (addr == NULL) { 387195972f6Sopenharmony_ci addr = IP4_ADDR_ANY; 388195972f6Sopenharmony_ci } 389195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 390195972f6Sopenharmony_ci 391195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 392195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 393195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); 394195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.bc.port = port; 395195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg)); 396195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 397195972f6Sopenharmony_ci 398195972f6Sopenharmony_ci return err; 399195972f6Sopenharmony_ci} 400195972f6Sopenharmony_ci 401195972f6Sopenharmony_ci/** 402195972f6Sopenharmony_ci * @ingroup netconn_udp 403195972f6Sopenharmony_ci * Disconnect a netconn from its current peer (only valid for UDP netconns). 404195972f6Sopenharmony_ci * 405195972f6Sopenharmony_ci * @param conn the netconn to disconnect 406195972f6Sopenharmony_ci * @return See @ref err_t 407195972f6Sopenharmony_ci */ 408195972f6Sopenharmony_cierr_t 409195972f6Sopenharmony_cinetconn_disconnect(struct netconn *conn) 410195972f6Sopenharmony_ci{ 411195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 412195972f6Sopenharmony_ci err_t err; 413195972f6Sopenharmony_ci 414195972f6Sopenharmony_ci LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;); 415195972f6Sopenharmony_ci 416195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 417195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 418195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg)); 419195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 420195972f6Sopenharmony_ci 421195972f6Sopenharmony_ci return err; 422195972f6Sopenharmony_ci} 423195972f6Sopenharmony_ci 424195972f6Sopenharmony_ci/** 425195972f6Sopenharmony_ci * @ingroup netconn_tcp 426195972f6Sopenharmony_ci * Set a TCP netconn into listen mode 427195972f6Sopenharmony_ci * 428195972f6Sopenharmony_ci * @param conn the tcp netconn to set to listen mode 429195972f6Sopenharmony_ci * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1 430195972f6Sopenharmony_ci * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns 431195972f6Sopenharmony_ci * don't return any error (yet?)) 432195972f6Sopenharmony_ci */ 433195972f6Sopenharmony_cierr_t 434195972f6Sopenharmony_cinetconn_listen_with_backlog(struct netconn *conn, u8_t backlog) 435195972f6Sopenharmony_ci{ 436195972f6Sopenharmony_ci#if LWIP_TCP 437195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 438195972f6Sopenharmony_ci err_t err; 439195972f6Sopenharmony_ci 440195972f6Sopenharmony_ci /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ 441195972f6Sopenharmony_ci LWIP_UNUSED_ARG(backlog); 442195972f6Sopenharmony_ci 443195972f6Sopenharmony_ci LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); 444195972f6Sopenharmony_ci 445195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 446195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 447195972f6Sopenharmony_ci#if TCP_LISTEN_BACKLOG 448195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.lb.backlog = backlog; 449195972f6Sopenharmony_ci#endif /* TCP_LISTEN_BACKLOG */ 450195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg)); 451195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 452195972f6Sopenharmony_ci 453195972f6Sopenharmony_ci return err; 454195972f6Sopenharmony_ci#else /* LWIP_TCP */ 455195972f6Sopenharmony_ci LWIP_UNUSED_ARG(conn); 456195972f6Sopenharmony_ci LWIP_UNUSED_ARG(backlog); 457195972f6Sopenharmony_ci return ERR_ARG; 458195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 459195972f6Sopenharmony_ci} 460195972f6Sopenharmony_ci 461195972f6Sopenharmony_ci/** 462195972f6Sopenharmony_ci * @ingroup netconn_tcp 463195972f6Sopenharmony_ci * Accept a new connection on a TCP listening netconn. 464195972f6Sopenharmony_ci * 465195972f6Sopenharmony_ci * @param conn the TCP listen netconn 466195972f6Sopenharmony_ci * @param new_conn pointer where the new connection is stored 467195972f6Sopenharmony_ci * @return ERR_OK if a new connection has been received or an error 468195972f6Sopenharmony_ci * code otherwise 469195972f6Sopenharmony_ci */ 470195972f6Sopenharmony_cierr_t 471195972f6Sopenharmony_cinetconn_accept(struct netconn *conn, struct netconn **new_conn) 472195972f6Sopenharmony_ci{ 473195972f6Sopenharmony_ci#if LWIP_TCP 474195972f6Sopenharmony_ci err_t err; 475195972f6Sopenharmony_ci void *accept_ptr; 476195972f6Sopenharmony_ci struct netconn *newconn; 477195972f6Sopenharmony_ci#if TCP_LISTEN_BACKLOG 478195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 479195972f6Sopenharmony_ci#endif /* TCP_LISTEN_BACKLOG */ 480195972f6Sopenharmony_ci 481195972f6Sopenharmony_ci LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); 482195972f6Sopenharmony_ci *new_conn = NULL; 483195972f6Sopenharmony_ci LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); 484195972f6Sopenharmony_ci 485195972f6Sopenharmony_ci /* NOTE: Although the opengroup spec says a pending error shall be returned to 486195972f6Sopenharmony_ci send/recv/getsockopt(SO_ERROR) only, we return it for listening 487195972f6Sopenharmony_ci connections also, to handle embedded-system errors */ 488195972f6Sopenharmony_ci err = netconn_err(conn); 489195972f6Sopenharmony_ci if (err != ERR_OK) { 490195972f6Sopenharmony_ci /* return pending error */ 491195972f6Sopenharmony_ci return err; 492195972f6Sopenharmony_ci } 493195972f6Sopenharmony_ci if (!NETCONN_ACCEPTMBOX_WAITABLE(conn)) { 494195972f6Sopenharmony_ci /* don't accept if closed: this might block the application task 495195972f6Sopenharmony_ci waiting on acceptmbox forever! */ 496195972f6Sopenharmony_ci return ERR_CLSD; 497195972f6Sopenharmony_ci } 498195972f6Sopenharmony_ci 499195972f6Sopenharmony_ci API_MSG_VAR_ALLOC_ACCEPT(msg); 500195972f6Sopenharmony_ci 501195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_INC(conn); 502195972f6Sopenharmony_ci if (netconn_is_nonblocking(conn)) { 503195972f6Sopenharmony_ci if (sys_arch_mbox_tryfetch(&conn->acceptmbox, &accept_ptr) == SYS_MBOX_EMPTY) { 504195972f6Sopenharmony_ci API_MSG_VAR_FREE_ACCEPT(msg); 505195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_DEC(conn); 506195972f6Sopenharmony_ci return ERR_WOULDBLOCK; 507195972f6Sopenharmony_ci } 508195972f6Sopenharmony_ci } else { 509195972f6Sopenharmony_ci#if LWIP_SO_RCVTIMEO 510195972f6Sopenharmony_ci if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { 511195972f6Sopenharmony_ci API_MSG_VAR_FREE_ACCEPT(msg); 512195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_DEC(conn); 513195972f6Sopenharmony_ci return ERR_TIMEOUT; 514195972f6Sopenharmony_ci } 515195972f6Sopenharmony_ci#else 516195972f6Sopenharmony_ci sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0); 517195972f6Sopenharmony_ci#endif /* LWIP_SO_RCVTIMEO*/ 518195972f6Sopenharmony_ci } 519195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_DEC(conn); 520195972f6Sopenharmony_ci#if LWIP_NETCONN_FULLDUPLEX 521195972f6Sopenharmony_ci if (conn->flags & NETCONN_FLAG_MBOXINVALID) { 522195972f6Sopenharmony_ci if (lwip_netconn_is_deallocated_msg(accept_ptr)) { 523195972f6Sopenharmony_ci /* the netconn has been closed from another thread */ 524195972f6Sopenharmony_ci API_MSG_VAR_FREE_ACCEPT(msg); 525195972f6Sopenharmony_ci return ERR_CONN; 526195972f6Sopenharmony_ci } 527195972f6Sopenharmony_ci } 528195972f6Sopenharmony_ci#endif 529195972f6Sopenharmony_ci 530195972f6Sopenharmony_ci /* Register event with callback */ 531195972f6Sopenharmony_ci API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); 532195972f6Sopenharmony_ci 533195972f6Sopenharmony_ci if (lwip_netconn_is_err_msg(accept_ptr, &err)) { 534195972f6Sopenharmony_ci /* a connection has been aborted: e.g. out of pcbs or out of netconns during accept */ 535195972f6Sopenharmony_ci API_MSG_VAR_FREE_ACCEPT(msg); 536195972f6Sopenharmony_ci return err; 537195972f6Sopenharmony_ci } 538195972f6Sopenharmony_ci if (accept_ptr == NULL) { 539195972f6Sopenharmony_ci /* connection has been aborted */ 540195972f6Sopenharmony_ci API_MSG_VAR_FREE_ACCEPT(msg); 541195972f6Sopenharmony_ci return ERR_CLSD; 542195972f6Sopenharmony_ci } 543195972f6Sopenharmony_ci newconn = (struct netconn *)accept_ptr; 544195972f6Sopenharmony_ci#if TCP_LISTEN_BACKLOG 545195972f6Sopenharmony_ci /* Let the stack know that we have accepted the connection. */ 546195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = newconn; 547195972f6Sopenharmony_ci /* don't care for the return value of lwip_netconn_do_recv */ 548195972f6Sopenharmony_ci netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg)); 549195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 550195972f6Sopenharmony_ci#endif /* TCP_LISTEN_BACKLOG */ 551195972f6Sopenharmony_ci 552195972f6Sopenharmony_ci *new_conn = newconn; 553195972f6Sopenharmony_ci /* don't set conn->last_err: it's only ERR_OK, anyway */ 554195972f6Sopenharmony_ci return ERR_OK; 555195972f6Sopenharmony_ci#else /* LWIP_TCP */ 556195972f6Sopenharmony_ci LWIP_UNUSED_ARG(conn); 557195972f6Sopenharmony_ci LWIP_UNUSED_ARG(new_conn); 558195972f6Sopenharmony_ci return ERR_ARG; 559195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 560195972f6Sopenharmony_ci} 561195972f6Sopenharmony_ci 562195972f6Sopenharmony_ci/** 563195972f6Sopenharmony_ci * @ingroup netconn_common 564195972f6Sopenharmony_ci * Receive data: actual implementation that doesn't care whether pbuf or netbuf 565195972f6Sopenharmony_ci * is received (this is internal, it's just here for describing common errors) 566195972f6Sopenharmony_ci * 567195972f6Sopenharmony_ci * @param conn the netconn from which to receive data 568195972f6Sopenharmony_ci * @param new_buf pointer where a new pbuf/netbuf is stored when received data 569195972f6Sopenharmony_ci * @param apiflags flags that control function behaviour. For now only: 570195972f6Sopenharmony_ci * - NETCONN_DONTBLOCK: only read data that is available now, don't wait for more data 571195972f6Sopenharmony_ci * @return ERR_OK if data has been received, an error code otherwise (timeout, 572195972f6Sopenharmony_ci * memory error or another error) 573195972f6Sopenharmony_ci * ERR_CONN if not connected 574195972f6Sopenharmony_ci * ERR_CLSD if TCP connection has been closed 575195972f6Sopenharmony_ci * ERR_WOULDBLOCK if the netconn is nonblocking but would block to wait for data 576195972f6Sopenharmony_ci * ERR_TIMEOUT if the netconn has a receive timeout and no data was received 577195972f6Sopenharmony_ci */ 578195972f6Sopenharmony_cistatic err_t 579195972f6Sopenharmony_cinetconn_recv_data(struct netconn *conn, void **new_buf, u8_t apiflags) 580195972f6Sopenharmony_ci{ 581195972f6Sopenharmony_ci void *buf = NULL; 582195972f6Sopenharmony_ci u16_t len; 583195972f6Sopenharmony_ci 584195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); 585195972f6Sopenharmony_ci *new_buf = NULL; 586195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); 587195972f6Sopenharmony_ci 588195972f6Sopenharmony_ci if (!NETCONN_RECVMBOX_WAITABLE(conn)) { 589195972f6Sopenharmony_ci err_t err = netconn_err(conn); 590195972f6Sopenharmony_ci if (err != ERR_OK) { 591195972f6Sopenharmony_ci /* return pending error */ 592195972f6Sopenharmony_ci return err; 593195972f6Sopenharmony_ci } 594195972f6Sopenharmony_ci return ERR_CONN; 595195972f6Sopenharmony_ci } 596195972f6Sopenharmony_ci 597195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_INC(conn); 598195972f6Sopenharmony_ci if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || 599195972f6Sopenharmony_ci (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { 600195972f6Sopenharmony_ci if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_MBOX_EMPTY) { 601195972f6Sopenharmony_ci err_t err; 602195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_DEC(conn); 603195972f6Sopenharmony_ci err = netconn_err(conn); 604195972f6Sopenharmony_ci if (err != ERR_OK) { 605195972f6Sopenharmony_ci /* return pending error */ 606195972f6Sopenharmony_ci return err; 607195972f6Sopenharmony_ci } 608195972f6Sopenharmony_ci if (conn->flags & NETCONN_FLAG_MBOXCLOSED) { 609195972f6Sopenharmony_ci return ERR_CONN; 610195972f6Sopenharmony_ci } 611195972f6Sopenharmony_ci return ERR_WOULDBLOCK; 612195972f6Sopenharmony_ci } 613195972f6Sopenharmony_ci } else { 614195972f6Sopenharmony_ci#if LWIP_SO_RCVTIMEO 615195972f6Sopenharmony_ci if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { 616195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_DEC(conn); 617195972f6Sopenharmony_ci return ERR_TIMEOUT; 618195972f6Sopenharmony_ci } 619195972f6Sopenharmony_ci#else 620195972f6Sopenharmony_ci sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); 621195972f6Sopenharmony_ci#endif /* LWIP_SO_RCVTIMEO*/ 622195972f6Sopenharmony_ci } 623195972f6Sopenharmony_ci NETCONN_MBOX_WAITING_DEC(conn); 624195972f6Sopenharmony_ci#if LWIP_NETCONN_FULLDUPLEX 625195972f6Sopenharmony_ci if (conn->flags & NETCONN_FLAG_MBOXINVALID) { 626195972f6Sopenharmony_ci if (lwip_netconn_is_deallocated_msg(buf)) { 627195972f6Sopenharmony_ci /* the netconn has been closed from another thread */ 628195972f6Sopenharmony_ci API_MSG_VAR_FREE_ACCEPT(msg); 629195972f6Sopenharmony_ci return ERR_CONN; 630195972f6Sopenharmony_ci } 631195972f6Sopenharmony_ci } 632195972f6Sopenharmony_ci#endif 633195972f6Sopenharmony_ci 634195972f6Sopenharmony_ci#if LWIP_TCP 635195972f6Sopenharmony_ci#if (LWIP_UDP || LWIP_RAW) 636195972f6Sopenharmony_ci if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) 637195972f6Sopenharmony_ci#endif /* (LWIP_UDP || LWIP_RAW) */ 638195972f6Sopenharmony_ci { 639195972f6Sopenharmony_ci err_t err; 640195972f6Sopenharmony_ci /* Check if this is an error message or a pbuf */ 641195972f6Sopenharmony_ci if (lwip_netconn_is_err_msg(buf, &err)) { 642195972f6Sopenharmony_ci /* new_buf has been zeroed above already */ 643195972f6Sopenharmony_ci if (err == ERR_CLSD) { 644195972f6Sopenharmony_ci /* connection closed translates to ERR_OK with *new_buf == NULL */ 645195972f6Sopenharmony_ci return ERR_OK; 646195972f6Sopenharmony_ci } 647195972f6Sopenharmony_ci return err; 648195972f6Sopenharmony_ci } 649195972f6Sopenharmony_ci len = ((struct pbuf *)buf)->tot_len; 650195972f6Sopenharmony_ci } 651195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 652195972f6Sopenharmony_ci#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) 653195972f6Sopenharmony_ci else 654195972f6Sopenharmony_ci#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ 655195972f6Sopenharmony_ci#if (LWIP_UDP || LWIP_RAW) 656195972f6Sopenharmony_ci { 657195972f6Sopenharmony_ci LWIP_ASSERT("buf != NULL", buf != NULL); 658195972f6Sopenharmony_ci len = netbuf_len((struct netbuf *)buf); 659195972f6Sopenharmony_ci } 660195972f6Sopenharmony_ci#endif /* (LWIP_UDP || LWIP_RAW) */ 661195972f6Sopenharmony_ci 662195972f6Sopenharmony_ci#if LWIP_SO_RCVBUF 663195972f6Sopenharmony_ci SYS_ARCH_DEC(conn->recv_avail, len); 664195972f6Sopenharmony_ci#endif /* LWIP_SO_RCVBUF */ 665195972f6Sopenharmony_ci /* Register event with callback */ 666195972f6Sopenharmony_ci API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); 667195972f6Sopenharmony_ci 668195972f6Sopenharmony_ci LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len)); 669195972f6Sopenharmony_ci 670195972f6Sopenharmony_ci *new_buf = buf; 671195972f6Sopenharmony_ci /* don't set conn->last_err: it's only ERR_OK, anyway */ 672195972f6Sopenharmony_ci return ERR_OK; 673195972f6Sopenharmony_ci} 674195972f6Sopenharmony_ci 675195972f6Sopenharmony_ci#if LWIP_TCP 676195972f6Sopenharmony_cistatic err_t 677195972f6Sopenharmony_cinetconn_tcp_recvd_msg(struct netconn *conn, size_t len, struct api_msg *msg) 678195972f6Sopenharmony_ci{ 679195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) && 680195972f6Sopenharmony_ci NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); 681195972f6Sopenharmony_ci 682195972f6Sopenharmony_ci msg->conn = conn; 683195972f6Sopenharmony_ci msg->msg.r.len = len; 684195972f6Sopenharmony_ci 685195972f6Sopenharmony_ci return netconn_apimsg(lwip_netconn_do_recv, msg); 686195972f6Sopenharmony_ci} 687195972f6Sopenharmony_ci 688195972f6Sopenharmony_cierr_t 689195972f6Sopenharmony_cinetconn_tcp_recvd(struct netconn *conn, size_t len) 690195972f6Sopenharmony_ci{ 691195972f6Sopenharmony_ci err_t err; 692195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 693195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) && 694195972f6Sopenharmony_ci NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); 695195972f6Sopenharmony_ci 696195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 697195972f6Sopenharmony_ci err = netconn_tcp_recvd_msg(conn, len, &API_VAR_REF(msg)); 698195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 699195972f6Sopenharmony_ci return err; 700195972f6Sopenharmony_ci} 701195972f6Sopenharmony_ci 702195972f6Sopenharmony_cistatic err_t 703195972f6Sopenharmony_cinetconn_recv_data_tcp(struct netconn *conn, struct pbuf **new_buf, u8_t apiflags) 704195972f6Sopenharmony_ci{ 705195972f6Sopenharmony_ci err_t err; 706195972f6Sopenharmony_ci struct pbuf *buf; 707195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 708195972f6Sopenharmony_ci#if LWIP_MPU_COMPATIBLE 709195972f6Sopenharmony_ci msg = NULL; 710195972f6Sopenharmony_ci#endif 711195972f6Sopenharmony_ci 712195972f6Sopenharmony_ci if (!NETCONN_RECVMBOX_WAITABLE(conn)) { 713195972f6Sopenharmony_ci /* This only happens when calling this function more than once *after* receiving FIN */ 714195972f6Sopenharmony_ci return ERR_CONN; 715195972f6Sopenharmony_ci } 716195972f6Sopenharmony_ci if (netconn_is_flag_set(conn, NETCONN_FIN_RX_PENDING)) { 717195972f6Sopenharmony_ci netconn_clear_flags(conn, NETCONN_FIN_RX_PENDING); 718195972f6Sopenharmony_ci goto handle_fin; 719195972f6Sopenharmony_ci } 720195972f6Sopenharmony_ci 721195972f6Sopenharmony_ci if (!(apiflags & NETCONN_NOAUTORCVD)) { 722195972f6Sopenharmony_ci /* need to allocate API message here so empty message pool does not result in event loss 723195972f6Sopenharmony_ci * see bug #47512: MPU_COMPATIBLE may fail on empty pool */ 724195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 725195972f6Sopenharmony_ci } 726195972f6Sopenharmony_ci 727195972f6Sopenharmony_ci err = netconn_recv_data(conn, (void **)new_buf, apiflags); 728195972f6Sopenharmony_ci if (err != ERR_OK) { 729195972f6Sopenharmony_ci if (!(apiflags & NETCONN_NOAUTORCVD)) { 730195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 731195972f6Sopenharmony_ci } 732195972f6Sopenharmony_ci return err; 733195972f6Sopenharmony_ci } 734195972f6Sopenharmony_ci buf = *new_buf; 735195972f6Sopenharmony_ci if (!(apiflags & NETCONN_NOAUTORCVD)) { 736195972f6Sopenharmony_ci /* Let the stack know that we have taken the data. */ 737195972f6Sopenharmony_ci u16_t len = buf ? buf->tot_len : 1; 738195972f6Sopenharmony_ci /* don't care for the return value of lwip_netconn_do_recv */ 739195972f6Sopenharmony_ci /* @todo: this should really be fixed, e.g. by retrying in poll on error */ 740195972f6Sopenharmony_ci netconn_tcp_recvd_msg(conn, len, &API_VAR_REF(msg)); 741195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 742195972f6Sopenharmony_ci } 743195972f6Sopenharmony_ci 744195972f6Sopenharmony_ci /* If we are closed, we indicate that we no longer wish to use the socket */ 745195972f6Sopenharmony_ci if (buf == NULL) { 746195972f6Sopenharmony_ci if (apiflags & NETCONN_NOFIN) { 747195972f6Sopenharmony_ci /* received a FIN but the caller cannot handle it right now: 748195972f6Sopenharmony_ci re-enqueue it and return "no data" */ 749195972f6Sopenharmony_ci netconn_set_flags(conn, NETCONN_FIN_RX_PENDING); 750195972f6Sopenharmony_ci return ERR_WOULDBLOCK; 751195972f6Sopenharmony_ci } else { 752195972f6Sopenharmony_cihandle_fin: 753195972f6Sopenharmony_ci API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); 754195972f6Sopenharmony_ci if (conn->pcb.ip == NULL) { 755195972f6Sopenharmony_ci /* race condition: RST during recv */ 756195972f6Sopenharmony_ci err = netconn_err(conn); 757195972f6Sopenharmony_ci if (err != ERR_OK) { 758195972f6Sopenharmony_ci return err; 759195972f6Sopenharmony_ci } 760195972f6Sopenharmony_ci return ERR_RST; 761195972f6Sopenharmony_ci } 762195972f6Sopenharmony_ci /* RX side is closed, so deallocate the recvmbox */ 763195972f6Sopenharmony_ci netconn_close_shutdown(conn, NETCONN_SHUT_RD); 764195972f6Sopenharmony_ci /* Don' store ERR_CLSD as conn->err since we are only half-closed */ 765195972f6Sopenharmony_ci return ERR_CLSD; 766195972f6Sopenharmony_ci } 767195972f6Sopenharmony_ci } 768195972f6Sopenharmony_ci return err; 769195972f6Sopenharmony_ci} 770195972f6Sopenharmony_ci 771195972f6Sopenharmony_ci/** 772195972f6Sopenharmony_ci * @ingroup netconn_tcp 773195972f6Sopenharmony_ci * Receive data (in form of a pbuf) from a TCP netconn 774195972f6Sopenharmony_ci * 775195972f6Sopenharmony_ci * @param conn the netconn from which to receive data 776195972f6Sopenharmony_ci * @param new_buf pointer where a new pbuf is stored when received data 777195972f6Sopenharmony_ci * @return ERR_OK if data has been received, an error code otherwise (timeout, 778195972f6Sopenharmony_ci * memory error or another error, @see netconn_recv_data) 779195972f6Sopenharmony_ci * ERR_ARG if conn is not a TCP netconn 780195972f6Sopenharmony_ci */ 781195972f6Sopenharmony_cierr_t 782195972f6Sopenharmony_cinetconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf) 783195972f6Sopenharmony_ci{ 784195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) && 785195972f6Sopenharmony_ci NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); 786195972f6Sopenharmony_ci 787195972f6Sopenharmony_ci return netconn_recv_data_tcp(conn, new_buf, 0); 788195972f6Sopenharmony_ci} 789195972f6Sopenharmony_ci 790195972f6Sopenharmony_ci/** 791195972f6Sopenharmony_ci * @ingroup netconn_tcp 792195972f6Sopenharmony_ci * Receive data (in form of a pbuf) from a TCP netconn 793195972f6Sopenharmony_ci * 794195972f6Sopenharmony_ci * @param conn the netconn from which to receive data 795195972f6Sopenharmony_ci * @param new_buf pointer where a new pbuf is stored when received data 796195972f6Sopenharmony_ci * @param apiflags flags that control function behaviour. For now only: 797195972f6Sopenharmony_ci * - NETCONN_DONTBLOCK: only read data that is available now, don't wait for more data 798195972f6Sopenharmony_ci * @return ERR_OK if data has been received, an error code otherwise (timeout, 799195972f6Sopenharmony_ci * memory error or another error, @see netconn_recv_data) 800195972f6Sopenharmony_ci * ERR_ARG if conn is not a TCP netconn 801195972f6Sopenharmony_ci */ 802195972f6Sopenharmony_cierr_t 803195972f6Sopenharmony_cinetconn_recv_tcp_pbuf_flags(struct netconn *conn, struct pbuf **new_buf, u8_t apiflags) 804195972f6Sopenharmony_ci{ 805195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv_tcp_pbuf: invalid conn", (conn != NULL) && 806195972f6Sopenharmony_ci NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;); 807195972f6Sopenharmony_ci 808195972f6Sopenharmony_ci return netconn_recv_data_tcp(conn, new_buf, apiflags); 809195972f6Sopenharmony_ci} 810195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 811195972f6Sopenharmony_ci 812195972f6Sopenharmony_ci/** 813195972f6Sopenharmony_ci * Receive data (in form of a netbuf) from a UDP or RAW netconn 814195972f6Sopenharmony_ci * 815195972f6Sopenharmony_ci * @param conn the netconn from which to receive data 816195972f6Sopenharmony_ci * @param new_buf pointer where a new netbuf is stored when received data 817195972f6Sopenharmony_ci * @return ERR_OK if data has been received, an error code otherwise (timeout, 818195972f6Sopenharmony_ci * memory error or another error) 819195972f6Sopenharmony_ci * ERR_ARG if conn is not a UDP/RAW netconn 820195972f6Sopenharmony_ci */ 821195972f6Sopenharmony_cierr_t 822195972f6Sopenharmony_cinetconn_recv_udp_raw_netbuf(struct netconn *conn, struct netbuf **new_buf) 823195972f6Sopenharmony_ci{ 824195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv_udp_raw_netbuf: invalid conn", (conn != NULL) && 825195972f6Sopenharmony_ci NETCONNTYPE_GROUP(netconn_type(conn)) != NETCONN_TCP, return ERR_ARG;); 826195972f6Sopenharmony_ci 827195972f6Sopenharmony_ci return netconn_recv_data(conn, (void **)new_buf, 0); 828195972f6Sopenharmony_ci} 829195972f6Sopenharmony_ci 830195972f6Sopenharmony_ci/** 831195972f6Sopenharmony_ci * Receive data (in form of a netbuf) from a UDP or RAW netconn 832195972f6Sopenharmony_ci * 833195972f6Sopenharmony_ci * @param conn the netconn from which to receive data 834195972f6Sopenharmony_ci * @param new_buf pointer where a new netbuf is stored when received data 835195972f6Sopenharmony_ci * @param apiflags flags that control function behaviour. For now only: 836195972f6Sopenharmony_ci * - NETCONN_DONTBLOCK: only read data that is available now, don't wait for more data 837195972f6Sopenharmony_ci * @return ERR_OK if data has been received, an error code otherwise (timeout, 838195972f6Sopenharmony_ci * memory error or another error) 839195972f6Sopenharmony_ci * ERR_ARG if conn is not a UDP/RAW netconn 840195972f6Sopenharmony_ci */ 841195972f6Sopenharmony_cierr_t 842195972f6Sopenharmony_cinetconn_recv_udp_raw_netbuf_flags(struct netconn *conn, struct netbuf **new_buf, u8_t apiflags) 843195972f6Sopenharmony_ci{ 844195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv_udp_raw_netbuf: invalid conn", (conn != NULL) && 845195972f6Sopenharmony_ci NETCONNTYPE_GROUP(netconn_type(conn)) != NETCONN_TCP, return ERR_ARG;); 846195972f6Sopenharmony_ci 847195972f6Sopenharmony_ci return netconn_recv_data(conn, (void **)new_buf, apiflags); 848195972f6Sopenharmony_ci} 849195972f6Sopenharmony_ci 850195972f6Sopenharmony_ci/** 851195972f6Sopenharmony_ci * @ingroup netconn_common 852195972f6Sopenharmony_ci * Receive data (in form of a netbuf containing a packet buffer) from a netconn 853195972f6Sopenharmony_ci * 854195972f6Sopenharmony_ci * @param conn the netconn from which to receive data 855195972f6Sopenharmony_ci * @param new_buf pointer where a new netbuf is stored when received data 856195972f6Sopenharmony_ci * @return ERR_OK if data has been received, an error code otherwise (timeout, 857195972f6Sopenharmony_ci * memory error or another error) 858195972f6Sopenharmony_ci */ 859195972f6Sopenharmony_cierr_t 860195972f6Sopenharmony_cinetconn_recv(struct netconn *conn, struct netbuf **new_buf) 861195972f6Sopenharmony_ci{ 862195972f6Sopenharmony_ci#if LWIP_TCP 863195972f6Sopenharmony_ci struct netbuf *buf = NULL; 864195972f6Sopenharmony_ci err_t err; 865195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 866195972f6Sopenharmony_ci 867195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); 868195972f6Sopenharmony_ci *new_buf = NULL; 869195972f6Sopenharmony_ci LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); 870195972f6Sopenharmony_ci 871195972f6Sopenharmony_ci#if LWIP_TCP 872195972f6Sopenharmony_ci#if (LWIP_UDP || LWIP_RAW) 873195972f6Sopenharmony_ci if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) 874195972f6Sopenharmony_ci#endif /* (LWIP_UDP || LWIP_RAW) */ 875195972f6Sopenharmony_ci { 876195972f6Sopenharmony_ci struct pbuf *p = NULL; 877195972f6Sopenharmony_ci /* This is not a listening netconn, since recvmbox is set */ 878195972f6Sopenharmony_ci 879195972f6Sopenharmony_ci buf = (struct netbuf *)memp_malloc(MEMP_NETBUF); 880195972f6Sopenharmony_ci if (buf == NULL) { 881195972f6Sopenharmony_ci return ERR_MEM; 882195972f6Sopenharmony_ci } 883195972f6Sopenharmony_ci 884195972f6Sopenharmony_ci err = netconn_recv_data_tcp(conn, &p, 0); 885195972f6Sopenharmony_ci if (err != ERR_OK) { 886195972f6Sopenharmony_ci memp_free(MEMP_NETBUF, buf); 887195972f6Sopenharmony_ci return err; 888195972f6Sopenharmony_ci } 889195972f6Sopenharmony_ci LWIP_ASSERT("p != NULL", p != NULL); 890195972f6Sopenharmony_ci 891195972f6Sopenharmony_ci buf->p = p; 892195972f6Sopenharmony_ci buf->ptr = p; 893195972f6Sopenharmony_ci buf->port = 0; 894195972f6Sopenharmony_ci ip_addr_set_zero(&buf->addr); 895195972f6Sopenharmony_ci *new_buf = buf; 896195972f6Sopenharmony_ci /* don't set conn->last_err: it's only ERR_OK, anyway */ 897195972f6Sopenharmony_ci return ERR_OK; 898195972f6Sopenharmony_ci } 899195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 900195972f6Sopenharmony_ci#if LWIP_TCP && (LWIP_UDP || LWIP_RAW) 901195972f6Sopenharmony_ci else 902195972f6Sopenharmony_ci#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */ 903195972f6Sopenharmony_ci { 904195972f6Sopenharmony_ci#if (LWIP_UDP || LWIP_RAW) 905195972f6Sopenharmony_ci return netconn_recv_data(conn, (void **)new_buf, 0); 906195972f6Sopenharmony_ci#endif /* (LWIP_UDP || LWIP_RAW) */ 907195972f6Sopenharmony_ci } 908195972f6Sopenharmony_ci} 909195972f6Sopenharmony_ci 910195972f6Sopenharmony_ci/** 911195972f6Sopenharmony_ci * @ingroup netconn_udp 912195972f6Sopenharmony_ci * Send data (in form of a netbuf) to a specific remote IP address and port. 913195972f6Sopenharmony_ci * Only to be used for UDP and RAW netconns (not TCP). 914195972f6Sopenharmony_ci * 915195972f6Sopenharmony_ci * @param conn the netconn over which to send data 916195972f6Sopenharmony_ci * @param buf a netbuf containing the data to send 917195972f6Sopenharmony_ci * @param addr the remote IP address to which to send the data 918195972f6Sopenharmony_ci * @param port the remote port to which to send the data 919195972f6Sopenharmony_ci * @return ERR_OK if data was sent, any other err_t on error 920195972f6Sopenharmony_ci */ 921195972f6Sopenharmony_cierr_t 922195972f6Sopenharmony_cinetconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port) 923195972f6Sopenharmony_ci{ 924195972f6Sopenharmony_ci if (buf != NULL) { 925195972f6Sopenharmony_ci ip_addr_set(&buf->addr, addr); 926195972f6Sopenharmony_ci buf->port = port; 927195972f6Sopenharmony_ci return netconn_send(conn, buf); 928195972f6Sopenharmony_ci } 929195972f6Sopenharmony_ci return ERR_VAL; 930195972f6Sopenharmony_ci} 931195972f6Sopenharmony_ci 932195972f6Sopenharmony_ci/** 933195972f6Sopenharmony_ci * @ingroup netconn_udp 934195972f6Sopenharmony_ci * Send data over a UDP or RAW netconn (that is already connected). 935195972f6Sopenharmony_ci * 936195972f6Sopenharmony_ci * @param conn the UDP or RAW netconn over which to send data 937195972f6Sopenharmony_ci * @param buf a netbuf containing the data to send 938195972f6Sopenharmony_ci * @return ERR_OK if data was sent, any other err_t on error 939195972f6Sopenharmony_ci */ 940195972f6Sopenharmony_cierr_t 941195972f6Sopenharmony_cinetconn_send(struct netconn *conn, struct netbuf *buf) 942195972f6Sopenharmony_ci{ 943195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 944195972f6Sopenharmony_ci err_t err; 945195972f6Sopenharmony_ci 946195972f6Sopenharmony_ci LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;); 947195972f6Sopenharmony_ci 948195972f6Sopenharmony_ci LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len)); 949195972f6Sopenharmony_ci 950195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 951195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 952195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.b = buf; 953195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg)); 954195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 955195972f6Sopenharmony_ci 956195972f6Sopenharmony_ci return err; 957195972f6Sopenharmony_ci} 958195972f6Sopenharmony_ci 959195972f6Sopenharmony_ci/** 960195972f6Sopenharmony_ci * @ingroup netconn_tcp 961195972f6Sopenharmony_ci * Send data over a TCP netconn. 962195972f6Sopenharmony_ci * 963195972f6Sopenharmony_ci * @param conn the TCP netconn over which to send data 964195972f6Sopenharmony_ci * @param dataptr pointer to the application buffer that contains the data to send 965195972f6Sopenharmony_ci * @param size size of the application data to send 966195972f6Sopenharmony_ci * @param apiflags combination of following flags : 967195972f6Sopenharmony_ci * - NETCONN_COPY: data will be copied into memory belonging to the stack 968195972f6Sopenharmony_ci * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent 969195972f6Sopenharmony_ci * - NETCONN_DONTBLOCK: only write the data if all data can be written at once 970195972f6Sopenharmony_ci * @param bytes_written pointer to a location that receives the number of written bytes 971195972f6Sopenharmony_ci * @return ERR_OK if data was sent, any other err_t on error 972195972f6Sopenharmony_ci */ 973195972f6Sopenharmony_cierr_t 974195972f6Sopenharmony_cinetconn_write_partly(struct netconn *conn, const void *dataptr, size_t size, 975195972f6Sopenharmony_ci u8_t apiflags, size_t *bytes_written) 976195972f6Sopenharmony_ci{ 977195972f6Sopenharmony_ci struct netvector vector; 978195972f6Sopenharmony_ci vector.ptr = dataptr; 979195972f6Sopenharmony_ci vector.len = size; 980195972f6Sopenharmony_ci return netconn_write_vectors_partly(conn, &vector, 1, apiflags, bytes_written); 981195972f6Sopenharmony_ci} 982195972f6Sopenharmony_ci 983195972f6Sopenharmony_ci/** 984195972f6Sopenharmony_ci * Send vectorized data atomically over a TCP netconn. 985195972f6Sopenharmony_ci * 986195972f6Sopenharmony_ci * @param conn the TCP netconn over which to send data 987195972f6Sopenharmony_ci * @param vectors array of vectors containing data to send 988195972f6Sopenharmony_ci * @param vectorcnt number of vectors in the array 989195972f6Sopenharmony_ci * @param apiflags combination of following flags : 990195972f6Sopenharmony_ci * - NETCONN_COPY: data will be copied into memory belonging to the stack 991195972f6Sopenharmony_ci * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent 992195972f6Sopenharmony_ci * - NETCONN_DONTBLOCK: only write the data if all data can be written at once 993195972f6Sopenharmony_ci * @param bytes_written pointer to a location that receives the number of written bytes 994195972f6Sopenharmony_ci * @return ERR_OK if data was sent, any other err_t on error 995195972f6Sopenharmony_ci */ 996195972f6Sopenharmony_cierr_t 997195972f6Sopenharmony_cinetconn_write_vectors_partly(struct netconn *conn, struct netvector *vectors, u16_t vectorcnt, 998195972f6Sopenharmony_ci u8_t apiflags, size_t *bytes_written) 999195972f6Sopenharmony_ci{ 1000195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 1001195972f6Sopenharmony_ci err_t err; 1002195972f6Sopenharmony_ci u8_t dontblock; 1003195972f6Sopenharmony_ci size_t size; 1004195972f6Sopenharmony_ci int i; 1005195972f6Sopenharmony_ci 1006195972f6Sopenharmony_ci LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;); 1007195972f6Sopenharmony_ci LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP), return ERR_VAL;); 1008195972f6Sopenharmony_ci dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); 1009195972f6Sopenharmony_ci#if LWIP_SO_SNDTIMEO 1010195972f6Sopenharmony_ci if (conn->send_timeout != 0) { 1011195972f6Sopenharmony_ci dontblock = 1; 1012195972f6Sopenharmony_ci } 1013195972f6Sopenharmony_ci#endif /* LWIP_SO_SNDTIMEO */ 1014195972f6Sopenharmony_ci if (dontblock && !bytes_written) { 1015195972f6Sopenharmony_ci /* This implies netconn_write() cannot be used for non-blocking send, since 1016195972f6Sopenharmony_ci it has no way to return the number of bytes written. */ 1017195972f6Sopenharmony_ci return ERR_VAL; 1018195972f6Sopenharmony_ci } 1019195972f6Sopenharmony_ci 1020195972f6Sopenharmony_ci /* sum up the total size */ 1021195972f6Sopenharmony_ci size = 0; 1022195972f6Sopenharmony_ci for (i = 0; i < vectorcnt; i++) { 1023195972f6Sopenharmony_ci size += vectors[i].len; 1024195972f6Sopenharmony_ci if (size < vectors[i].len) { 1025195972f6Sopenharmony_ci /* overflow */ 1026195972f6Sopenharmony_ci return ERR_VAL; 1027195972f6Sopenharmony_ci } 1028195972f6Sopenharmony_ci } 1029195972f6Sopenharmony_ci if (size == 0) { 1030195972f6Sopenharmony_ci return ERR_OK; 1031195972f6Sopenharmony_ci } else if (size > SSIZE_MAX) { 1032195972f6Sopenharmony_ci ssize_t limited; 1033195972f6Sopenharmony_ci /* this is required by the socket layer (cannot send full size_t range) */ 1034195972f6Sopenharmony_ci if (!bytes_written) { 1035195972f6Sopenharmony_ci return ERR_VAL; 1036195972f6Sopenharmony_ci } 1037195972f6Sopenharmony_ci /* limit the amount of data to send */ 1038195972f6Sopenharmony_ci limited = SSIZE_MAX; 1039195972f6Sopenharmony_ci size = (size_t)limited; 1040195972f6Sopenharmony_ci } 1041195972f6Sopenharmony_ci 1042195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 1043195972f6Sopenharmony_ci /* non-blocking write sends as much */ 1044195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 1045195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.vector = vectors; 1046195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.vector_cnt = vectorcnt; 1047195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.vector_off = 0; 1048195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags; 1049195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.len = size; 1050195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.offset = 0; 1051195972f6Sopenharmony_ci#if LWIP_SO_SNDTIMEO 1052195972f6Sopenharmony_ci if (conn->send_timeout != 0) { 1053195972f6Sopenharmony_ci /* get the time we started, which is later compared to 1054195972f6Sopenharmony_ci sys_now() + conn->send_timeout */ 1055195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.time_started = sys_now(); 1056195972f6Sopenharmony_ci } else { 1057195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.w.time_started = 0; 1058195972f6Sopenharmony_ci } 1059195972f6Sopenharmony_ci#endif /* LWIP_SO_SNDTIMEO */ 1060195972f6Sopenharmony_ci 1061195972f6Sopenharmony_ci /* For locking the core: this _can_ be delayed on low memory/low send buffer, 1062195972f6Sopenharmony_ci but if it is, this is done inside api_msg.c:do_write(), so we can use the 1063195972f6Sopenharmony_ci non-blocking version here. */ 1064195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg)); 1065195972f6Sopenharmony_ci if (err == ERR_OK) { 1066195972f6Sopenharmony_ci if (bytes_written != NULL) { 1067195972f6Sopenharmony_ci *bytes_written = API_MSG_VAR_REF(msg).msg.w.offset; 1068195972f6Sopenharmony_ci } 1069195972f6Sopenharmony_ci /* for blocking, check all requested bytes were written, NOTE: send_timeout is 1070195972f6Sopenharmony_ci treated as dontblock (see dontblock assignment above) */ 1071195972f6Sopenharmony_ci if (!dontblock) { 1072195972f6Sopenharmony_ci LWIP_ASSERT("do_write failed to write all bytes", API_MSG_VAR_REF(msg).msg.w.offset == size); 1073195972f6Sopenharmony_ci } 1074195972f6Sopenharmony_ci } 1075195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 1076195972f6Sopenharmony_ci 1077195972f6Sopenharmony_ci return err; 1078195972f6Sopenharmony_ci} 1079195972f6Sopenharmony_ci 1080195972f6Sopenharmony_ci/** 1081195972f6Sopenharmony_ci * @ingroup netconn_tcp 1082195972f6Sopenharmony_ci * Close or shutdown a TCP netconn (doesn't delete it). 1083195972f6Sopenharmony_ci * 1084195972f6Sopenharmony_ci * @param conn the TCP netconn to close or shutdown 1085195972f6Sopenharmony_ci * @param how fully close or only shutdown one side? 1086195972f6Sopenharmony_ci * @return ERR_OK if the netconn was closed, any other err_t on error 1087195972f6Sopenharmony_ci */ 1088195972f6Sopenharmony_cistatic err_t 1089195972f6Sopenharmony_cinetconn_close_shutdown(struct netconn *conn, u8_t how) 1090195972f6Sopenharmony_ci{ 1091195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 1092195972f6Sopenharmony_ci err_t err; 1093195972f6Sopenharmony_ci LWIP_UNUSED_ARG(how); 1094195972f6Sopenharmony_ci 1095195972f6Sopenharmony_ci LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;); 1096195972f6Sopenharmony_ci 1097195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 1098195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 1099195972f6Sopenharmony_ci#if LWIP_TCP 1100195972f6Sopenharmony_ci /* shutting down both ends is the same as closing */ 1101195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.sd.shut = how; 1102195972f6Sopenharmony_ci#if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER 1103195972f6Sopenharmony_ci /* get the time we started, which is later compared to 1104195972f6Sopenharmony_ci sys_now() + conn->send_timeout */ 1105195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now(); 1106195972f6Sopenharmony_ci#else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ 1107195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.sd.polls_left = 1108195972f6Sopenharmony_ci ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1; 1109195972f6Sopenharmony_ci#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */ 1110195972f6Sopenharmony_ci#endif /* LWIP_TCP */ 1111195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg)); 1112195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 1113195972f6Sopenharmony_ci 1114195972f6Sopenharmony_ci return err; 1115195972f6Sopenharmony_ci} 1116195972f6Sopenharmony_ci 1117195972f6Sopenharmony_ci/** 1118195972f6Sopenharmony_ci * @ingroup netconn_tcp 1119195972f6Sopenharmony_ci * Close a TCP netconn (doesn't delete it). 1120195972f6Sopenharmony_ci * 1121195972f6Sopenharmony_ci * @param conn the TCP netconn to close 1122195972f6Sopenharmony_ci * @return ERR_OK if the netconn was closed, any other err_t on error 1123195972f6Sopenharmony_ci */ 1124195972f6Sopenharmony_cierr_t 1125195972f6Sopenharmony_cinetconn_close(struct netconn *conn) 1126195972f6Sopenharmony_ci{ 1127195972f6Sopenharmony_ci /* shutting down both ends is the same as closing */ 1128195972f6Sopenharmony_ci return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR); 1129195972f6Sopenharmony_ci} 1130195972f6Sopenharmony_ci 1131195972f6Sopenharmony_ci/** 1132195972f6Sopenharmony_ci * @ingroup netconn_common 1133195972f6Sopenharmony_ci * Get and reset pending error on a netconn 1134195972f6Sopenharmony_ci * 1135195972f6Sopenharmony_ci * @param conn the netconn to get the error from 1136195972f6Sopenharmony_ci * @return and pending error or ERR_OK if no error was pending 1137195972f6Sopenharmony_ci */ 1138195972f6Sopenharmony_cierr_t 1139195972f6Sopenharmony_cinetconn_err(struct netconn *conn) 1140195972f6Sopenharmony_ci{ 1141195972f6Sopenharmony_ci err_t err; 1142195972f6Sopenharmony_ci SYS_ARCH_DECL_PROTECT(lev); 1143195972f6Sopenharmony_ci if (conn == NULL) { 1144195972f6Sopenharmony_ci return ERR_OK; 1145195972f6Sopenharmony_ci } 1146195972f6Sopenharmony_ci SYS_ARCH_PROTECT(lev); 1147195972f6Sopenharmony_ci err = conn->pending_err; 1148195972f6Sopenharmony_ci conn->pending_err = ERR_OK; 1149195972f6Sopenharmony_ci SYS_ARCH_UNPROTECT(lev); 1150195972f6Sopenharmony_ci return err; 1151195972f6Sopenharmony_ci} 1152195972f6Sopenharmony_ci 1153195972f6Sopenharmony_ci/** 1154195972f6Sopenharmony_ci * @ingroup netconn_tcp 1155195972f6Sopenharmony_ci * Shut down one or both sides of a TCP netconn (doesn't delete it). 1156195972f6Sopenharmony_ci * 1157195972f6Sopenharmony_ci * @param conn the TCP netconn to shut down 1158195972f6Sopenharmony_ci * @param shut_rx shut down the RX side (no more read possible after this) 1159195972f6Sopenharmony_ci * @param shut_tx shut down the TX side (no more write possible after this) 1160195972f6Sopenharmony_ci * @return ERR_OK if the netconn was closed, any other err_t on error 1161195972f6Sopenharmony_ci */ 1162195972f6Sopenharmony_cierr_t 1163195972f6Sopenharmony_cinetconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx) 1164195972f6Sopenharmony_ci{ 1165195972f6Sopenharmony_ci return netconn_close_shutdown(conn, (u8_t)((shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0))); 1166195972f6Sopenharmony_ci} 1167195972f6Sopenharmony_ci 1168195972f6Sopenharmony_ci#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) 1169195972f6Sopenharmony_ci/** 1170195972f6Sopenharmony_ci * @ingroup netconn_udp 1171195972f6Sopenharmony_ci * Join multicast groups for UDP netconns. 1172195972f6Sopenharmony_ci * 1173195972f6Sopenharmony_ci * @param conn the UDP netconn for which to change multicast addresses 1174195972f6Sopenharmony_ci * @param multiaddr IP address of the multicast group to join or leave 1175195972f6Sopenharmony_ci * @param netif_addr the IP address of the network interface on which to send 1176195972f6Sopenharmony_ci * the igmp message 1177195972f6Sopenharmony_ci * @param join_or_leave flag whether to send a join- or leave-message 1178195972f6Sopenharmony_ci * @return ERR_OK if the action was taken, any err_t on error 1179195972f6Sopenharmony_ci */ 1180195972f6Sopenharmony_cierr_t 1181195972f6Sopenharmony_cinetconn_join_leave_group(struct netconn *conn, 1182195972f6Sopenharmony_ci const ip_addr_t *multiaddr, 1183195972f6Sopenharmony_ci const ip_addr_t *netif_addr, 1184195972f6Sopenharmony_ci enum netconn_igmp join_or_leave) 1185195972f6Sopenharmony_ci{ 1186195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 1187195972f6Sopenharmony_ci err_t err; 1188195972f6Sopenharmony_ci 1189195972f6Sopenharmony_ci LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); 1190195972f6Sopenharmony_ci 1191195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 1192195972f6Sopenharmony_ci 1193195972f6Sopenharmony_ci#if LWIP_IPV4 1194195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ 1195195972f6Sopenharmony_ci if (multiaddr == NULL) { 1196195972f6Sopenharmony_ci multiaddr = IP4_ADDR_ANY; 1197195972f6Sopenharmony_ci } 1198195972f6Sopenharmony_ci if (netif_addr == NULL) { 1199195972f6Sopenharmony_ci netif_addr = IP4_ADDR_ANY; 1200195972f6Sopenharmony_ci } 1201195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 1202195972f6Sopenharmony_ci 1203195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 1204195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); 1205195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr); 1206195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave; 1207195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg)); 1208195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 1209195972f6Sopenharmony_ci 1210195972f6Sopenharmony_ci return err; 1211195972f6Sopenharmony_ci} 1212195972f6Sopenharmony_ci/** 1213195972f6Sopenharmony_ci * @ingroup netconn_udp 1214195972f6Sopenharmony_ci * Join multicast groups for UDP netconns. 1215195972f6Sopenharmony_ci * 1216195972f6Sopenharmony_ci * @param conn the UDP netconn for which to change multicast addresses 1217195972f6Sopenharmony_ci * @param multiaddr IP address of the multicast group to join or leave 1218195972f6Sopenharmony_ci * @param if_idx the index of the netif 1219195972f6Sopenharmony_ci * @param join_or_leave flag whether to send a join- or leave-message 1220195972f6Sopenharmony_ci * @return ERR_OK if the action was taken, any err_t on error 1221195972f6Sopenharmony_ci */ 1222195972f6Sopenharmony_cierr_t 1223195972f6Sopenharmony_cinetconn_join_leave_group_netif(struct netconn *conn, 1224195972f6Sopenharmony_ci const ip_addr_t *multiaddr, 1225195972f6Sopenharmony_ci u8_t if_idx, 1226195972f6Sopenharmony_ci enum netconn_igmp join_or_leave) 1227195972f6Sopenharmony_ci{ 1228195972f6Sopenharmony_ci API_MSG_VAR_DECLARE(msg); 1229195972f6Sopenharmony_ci err_t err; 1230195972f6Sopenharmony_ci 1231195972f6Sopenharmony_ci LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;); 1232195972f6Sopenharmony_ci 1233195972f6Sopenharmony_ci API_MSG_VAR_ALLOC(msg); 1234195972f6Sopenharmony_ci 1235195972f6Sopenharmony_ci#if LWIP_IPV4 1236195972f6Sopenharmony_ci /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ 1237195972f6Sopenharmony_ci if (multiaddr == NULL) { 1238195972f6Sopenharmony_ci multiaddr = IP4_ADDR_ANY; 1239195972f6Sopenharmony_ci } 1240195972f6Sopenharmony_ci if (if_idx == NETIF_NO_INDEX) { 1241195972f6Sopenharmony_ci return ERR_IF; 1242195972f6Sopenharmony_ci } 1243195972f6Sopenharmony_ci#endif /* LWIP_IPV4 */ 1244195972f6Sopenharmony_ci 1245195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).conn = conn; 1246195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr); 1247195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.jl.if_idx = if_idx; 1248195972f6Sopenharmony_ci API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave; 1249195972f6Sopenharmony_ci err = netconn_apimsg(lwip_netconn_do_join_leave_group_netif, &API_MSG_VAR_REF(msg)); 1250195972f6Sopenharmony_ci API_MSG_VAR_FREE(msg); 1251195972f6Sopenharmony_ci 1252195972f6Sopenharmony_ci return err; 1253195972f6Sopenharmony_ci} 1254195972f6Sopenharmony_ci#endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */ 1255195972f6Sopenharmony_ci 1256195972f6Sopenharmony_ci#if LWIP_DNS 1257195972f6Sopenharmony_ci/** 1258195972f6Sopenharmony_ci * @ingroup netconn_common 1259195972f6Sopenharmony_ci * Execute a DNS query, only one IP address is returned 1260195972f6Sopenharmony_ci * 1261195972f6Sopenharmony_ci * @param name a string representation of the DNS host name to query 1262195972f6Sopenharmony_ci * @param addr a preallocated ip_addr_t where to store the resolved IP address 1263195972f6Sopenharmony_ci * @param dns_addrtype IP address type (IPv4 / IPv6) 1264195972f6Sopenharmony_ci * @return ERR_OK: resolving succeeded 1265195972f6Sopenharmony_ci * ERR_MEM: memory error, try again later 1266195972f6Sopenharmony_ci * ERR_ARG: dns client not initialized or invalid hostname 1267195972f6Sopenharmony_ci * ERR_VAL: dns server response was invalid 1268195972f6Sopenharmony_ci */ 1269195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 1270195972f6Sopenharmony_cierr_t 1271195972f6Sopenharmony_cinetconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype) 1272195972f6Sopenharmony_ci#else 1273195972f6Sopenharmony_cierr_t 1274195972f6Sopenharmony_cinetconn_gethostbyname(const char *name, ip_addr_t *addr) 1275195972f6Sopenharmony_ci#endif 1276195972f6Sopenharmony_ci{ 1277195972f6Sopenharmony_ci API_VAR_DECLARE(struct dns_api_msg, msg); 1278195972f6Sopenharmony_ci#if !LWIP_MPU_COMPATIBLE 1279195972f6Sopenharmony_ci sys_sem_t sem; 1280195972f6Sopenharmony_ci#endif /* LWIP_MPU_COMPATIBLE */ 1281195972f6Sopenharmony_ci err_t err; 1282195972f6Sopenharmony_ci err_t cberr; 1283195972f6Sopenharmony_ci 1284195972f6Sopenharmony_ci LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;); 1285195972f6Sopenharmony_ci LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;); 1286195972f6Sopenharmony_ci#if LWIP_MPU_COMPATIBLE 1287195972f6Sopenharmony_ci if (strlen(name) >= DNS_MAX_NAME_LENGTH) { 1288195972f6Sopenharmony_ci return ERR_ARG; 1289195972f6Sopenharmony_ci } 1290195972f6Sopenharmony_ci#endif 1291195972f6Sopenharmony_ci 1292195972f6Sopenharmony_ci#ifdef LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE 1293195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 1294195972f6Sopenharmony_ci if (LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, dns_addrtype, &err)) { 1295195972f6Sopenharmony_ci#else 1296195972f6Sopenharmony_ci if (LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, NETCONN_DNS_DEFAULT, &err)) { 1297195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_IPV6 */ 1298195972f6Sopenharmony_ci return err; 1299195972f6Sopenharmony_ci } 1300195972f6Sopenharmony_ci#endif /* LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE */ 1301195972f6Sopenharmony_ci 1302195972f6Sopenharmony_ci API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM); 1303195972f6Sopenharmony_ci#if LWIP_MPU_COMPATIBLE 1304195972f6Sopenharmony_ci strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH - 1); 1305195972f6Sopenharmony_ci API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH - 1] = 0; 1306195972f6Sopenharmony_ci#else /* LWIP_MPU_COMPATIBLE */ 1307195972f6Sopenharmony_ci msg.err = &err; 1308195972f6Sopenharmony_ci msg.sem = &sem; 1309195972f6Sopenharmony_ci API_VAR_REF(msg).addr = API_VAR_REF(addr); 1310195972f6Sopenharmony_ci API_VAR_REF(msg).name = name; 1311195972f6Sopenharmony_ci#endif /* LWIP_MPU_COMPATIBLE */ 1312195972f6Sopenharmony_ci#if LWIP_IPV4 && LWIP_IPV6 1313195972f6Sopenharmony_ci API_VAR_REF(msg).dns_addrtype = dns_addrtype; 1314195972f6Sopenharmony_ci#endif /* LWIP_IPV4 && LWIP_IPV6 */ 1315195972f6Sopenharmony_ci#if LWIP_NETCONN_SEM_PER_THREAD 1316195972f6Sopenharmony_ci API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET(); 1317195972f6Sopenharmony_ci#else /* LWIP_NETCONN_SEM_PER_THREAD*/ 1318195972f6Sopenharmony_ci err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0); 1319195972f6Sopenharmony_ci if (err != ERR_OK) { 1320195972f6Sopenharmony_ci API_VAR_FREE(MEMP_DNS_API_MSG, msg); 1321195972f6Sopenharmony_ci return err; 1322195972f6Sopenharmony_ci } 1323195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_SEM_PER_THREAD */ 1324195972f6Sopenharmony_ci 1325195972f6Sopenharmony_ci cberr = tcpip_send_msg_wait_sem(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg), API_EXPR_REF(API_VAR_REF(msg).sem)); 1326195972f6Sopenharmony_ci#if !LWIP_NETCONN_SEM_PER_THREAD 1327195972f6Sopenharmony_ci sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem)); 1328195972f6Sopenharmony_ci#endif /* !LWIP_NETCONN_SEM_PER_THREAD */ 1329195972f6Sopenharmony_ci if (cberr != ERR_OK) { 1330195972f6Sopenharmony_ci API_VAR_FREE(MEMP_DNS_API_MSG, msg); 1331195972f6Sopenharmony_ci return cberr; 1332195972f6Sopenharmony_ci } 1333195972f6Sopenharmony_ci 1334195972f6Sopenharmony_ci#if LWIP_MPU_COMPATIBLE 1335195972f6Sopenharmony_ci *addr = msg->addr; 1336195972f6Sopenharmony_ci err = msg->err; 1337195972f6Sopenharmony_ci#endif /* LWIP_MPU_COMPATIBLE */ 1338195972f6Sopenharmony_ci 1339195972f6Sopenharmony_ci API_VAR_FREE(MEMP_DNS_API_MSG, msg); 1340195972f6Sopenharmony_ci return err; 1341195972f6Sopenharmony_ci} 1342195972f6Sopenharmony_ci#endif /* LWIP_DNS*/ 1343195972f6Sopenharmony_ci 1344195972f6Sopenharmony_ci#if LWIP_NETCONN_SEM_PER_THREAD 1345195972f6Sopenharmony_civoid 1346195972f6Sopenharmony_cinetconn_thread_init(void) 1347195972f6Sopenharmony_ci{ 1348195972f6Sopenharmony_ci sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); 1349195972f6Sopenharmony_ci if (!sys_sem_valid(sem)) { 1350195972f6Sopenharmony_ci /* call alloc only once */ 1351195972f6Sopenharmony_ci LWIP_NETCONN_THREAD_SEM_ALLOC(); 1352195972f6Sopenharmony_ci LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET())); 1353195972f6Sopenharmony_ci } 1354195972f6Sopenharmony_ci} 1355195972f6Sopenharmony_ci 1356195972f6Sopenharmony_civoid 1357195972f6Sopenharmony_cinetconn_thread_cleanup(void) 1358195972f6Sopenharmony_ci{ 1359195972f6Sopenharmony_ci sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET(); 1360195972f6Sopenharmony_ci if (sys_sem_valid(sem)) { 1361195972f6Sopenharmony_ci /* call free only once */ 1362195972f6Sopenharmony_ci LWIP_NETCONN_THREAD_SEM_FREE(); 1363195972f6Sopenharmony_ci } 1364195972f6Sopenharmony_ci} 1365195972f6Sopenharmony_ci#endif /* LWIP_NETCONN_SEM_PER_THREAD */ 1366195972f6Sopenharmony_ci 1367195972f6Sopenharmony_ci#endif /* LWIP_NETCONN */ 1368