Greg Steiert / pegasus_dev

Dependents:   blinky_max32630fthr

Committer:
switches
Date:
Fri Nov 11 20:59:50 2016 +0000
Revision:
0:5c4d7b2438d3
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
switches 0:5c4d7b2438d3 1 /**
switches 0:5c4d7b2438d3 2 * @file
switches 0:5c4d7b2438d3 3 * Sequential API External module
switches 0:5c4d7b2438d3 4 */
switches 0:5c4d7b2438d3 5
switches 0:5c4d7b2438d3 6 /*
switches 0:5c4d7b2438d3 7 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
switches 0:5c4d7b2438d3 8 * All rights reserved.
switches 0:5c4d7b2438d3 9 *
switches 0:5c4d7b2438d3 10 * Redistribution and use in source and binary forms, with or without modification,
switches 0:5c4d7b2438d3 11 * are permitted provided that the following conditions are met:
switches 0:5c4d7b2438d3 12 *
switches 0:5c4d7b2438d3 13 * 1. Redistributions of source code must retain the above copyright notice,
switches 0:5c4d7b2438d3 14 * this list of conditions and the following disclaimer.
switches 0:5c4d7b2438d3 15 * 2. Redistributions in binary form must reproduce the above copyright notice,
switches 0:5c4d7b2438d3 16 * this list of conditions and the following disclaimer in the documentation
switches 0:5c4d7b2438d3 17 * and/or other materials provided with the distribution.
switches 0:5c4d7b2438d3 18 * 3. The name of the author may not be used to endorse or promote products
switches 0:5c4d7b2438d3 19 * derived from this software without specific prior written permission.
switches 0:5c4d7b2438d3 20 *
switches 0:5c4d7b2438d3 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
switches 0:5c4d7b2438d3 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
switches 0:5c4d7b2438d3 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
switches 0:5c4d7b2438d3 24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
switches 0:5c4d7b2438d3 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
switches 0:5c4d7b2438d3 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
switches 0:5c4d7b2438d3 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
switches 0:5c4d7b2438d3 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
switches 0:5c4d7b2438d3 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
switches 0:5c4d7b2438d3 30 * OF SUCH DAMAGE.
switches 0:5c4d7b2438d3 31 *
switches 0:5c4d7b2438d3 32 * This file is part of the lwIP TCP/IP stack.
switches 0:5c4d7b2438d3 33 *
switches 0:5c4d7b2438d3 34 * Author: Adam Dunkels <adam@sics.se>
switches 0:5c4d7b2438d3 35 */
switches 0:5c4d7b2438d3 36
switches 0:5c4d7b2438d3 37 /**
switches 0:5c4d7b2438d3 38 * @defgroup netconn Netconn API
switches 0:5c4d7b2438d3 39 * @ingroup threadsafe_api
switches 0:5c4d7b2438d3 40 * Thread-safe, to be called from non-TCPIP threads only.
switches 0:5c4d7b2438d3 41 * TX/RX handling based on @ref netbuf (containing @ref pbuf)
switches 0:5c4d7b2438d3 42 * to avoid copying data around.
switches 0:5c4d7b2438d3 43 *
switches 0:5c4d7b2438d3 44 * @defgroup netconn_common Common functions
switches 0:5c4d7b2438d3 45 * @ingroup netconn
switches 0:5c4d7b2438d3 46 * For use with TCP and UDP
switches 0:5c4d7b2438d3 47 *
switches 0:5c4d7b2438d3 48 * @defgroup netconn_tcp TCP only
switches 0:5c4d7b2438d3 49 * @ingroup netconn
switches 0:5c4d7b2438d3 50 * TCP only functions
switches 0:5c4d7b2438d3 51 *
switches 0:5c4d7b2438d3 52 * @defgroup netconn_udp UDP only
switches 0:5c4d7b2438d3 53 * @ingroup netconn
switches 0:5c4d7b2438d3 54 * UDP only functions
switches 0:5c4d7b2438d3 55 */
switches 0:5c4d7b2438d3 56
switches 0:5c4d7b2438d3 57 /* This is the part of the API that is linked with
switches 0:5c4d7b2438d3 58 the application */
switches 0:5c4d7b2438d3 59
switches 0:5c4d7b2438d3 60 #include "lwip/opt.h"
switches 0:5c4d7b2438d3 61
switches 0:5c4d7b2438d3 62 #if LWIP_NETCONN /* don't build if not configured for use in lwipopts.h */
switches 0:5c4d7b2438d3 63
switches 0:5c4d7b2438d3 64 #include "lwip/api.h"
switches 0:5c4d7b2438d3 65 #include "lwip/memp.h"
switches 0:5c4d7b2438d3 66
switches 0:5c4d7b2438d3 67 #include "lwip/ip.h"
switches 0:5c4d7b2438d3 68 #include "lwip/raw.h"
switches 0:5c4d7b2438d3 69 #include "lwip/udp.h"
switches 0:5c4d7b2438d3 70 #include "lwip/priv/api_msg.h"
switches 0:5c4d7b2438d3 71 #include "lwip/priv/tcp_priv.h"
switches 0:5c4d7b2438d3 72 #include "lwip/priv/tcpip_priv.h"
switches 0:5c4d7b2438d3 73
switches 0:5c4d7b2438d3 74 #include <string.h>
switches 0:5c4d7b2438d3 75
switches 0:5c4d7b2438d3 76 #define API_MSG_VAR_REF(name) API_VAR_REF(name)
switches 0:5c4d7b2438d3 77 #define API_MSG_VAR_DECLARE(name) API_VAR_DECLARE(struct api_msg, name)
switches 0:5c4d7b2438d3 78 #define API_MSG_VAR_ALLOC(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, ERR_MEM)
switches 0:5c4d7b2438d3 79 #define API_MSG_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC(struct api_msg, MEMP_API_MSG, name, NULL)
switches 0:5c4d7b2438d3 80 #define API_MSG_VAR_FREE(name) API_VAR_FREE(MEMP_API_MSG, name)
switches 0:5c4d7b2438d3 81
switches 0:5c4d7b2438d3 82 static err_t netconn_close_shutdown(struct netconn *conn, u8_t how);
switches 0:5c4d7b2438d3 83
switches 0:5c4d7b2438d3 84 /**
switches 0:5c4d7b2438d3 85 * Call the lower part of a netconn_* function
switches 0:5c4d7b2438d3 86 * This function is then running in the thread context
switches 0:5c4d7b2438d3 87 * of tcpip_thread and has exclusive access to lwIP core code.
switches 0:5c4d7b2438d3 88 *
switches 0:5c4d7b2438d3 89 * @param fn function to call
switches 0:5c4d7b2438d3 90 * @param apimsg a struct containing the function to call and its parameters
switches 0:5c4d7b2438d3 91 * @return ERR_OK if the function was called, another err_t if not
switches 0:5c4d7b2438d3 92 */
switches 0:5c4d7b2438d3 93 static err_t
switches 0:5c4d7b2438d3 94 netconn_apimsg(tcpip_callback_fn fn, struct api_msg *apimsg)
switches 0:5c4d7b2438d3 95 {
switches 0:5c4d7b2438d3 96 err_t err;
switches 0:5c4d7b2438d3 97
switches 0:5c4d7b2438d3 98 #ifdef LWIP_DEBUG
switches 0:5c4d7b2438d3 99 /* catch functions that don't set err */
switches 0:5c4d7b2438d3 100 apimsg->err = ERR_VAL;
switches 0:5c4d7b2438d3 101 #endif /* LWIP_DEBUG */
switches 0:5c4d7b2438d3 102
switches 0:5c4d7b2438d3 103 #if LWIP_NETCONN_SEM_PER_THREAD
switches 0:5c4d7b2438d3 104 apimsg->op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET();
switches 0:5c4d7b2438d3 105 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
switches 0:5c4d7b2438d3 106
switches 0:5c4d7b2438d3 107 err = tcpip_send_msg_wait_sem(fn, apimsg, LWIP_API_MSG_SEM(apimsg));
switches 0:5c4d7b2438d3 108 if (err == ERR_OK) {
switches 0:5c4d7b2438d3 109 return apimsg->err;
switches 0:5c4d7b2438d3 110 }
switches 0:5c4d7b2438d3 111 return err;
switches 0:5c4d7b2438d3 112 }
switches 0:5c4d7b2438d3 113
switches 0:5c4d7b2438d3 114 /**
switches 0:5c4d7b2438d3 115 * Create a new netconn (of a specific type) that has a callback function.
switches 0:5c4d7b2438d3 116 * The corresponding pcb is also created.
switches 0:5c4d7b2438d3 117 *
switches 0:5c4d7b2438d3 118 * @param t the type of 'connection' to create (@see enum netconn_type)
switches 0:5c4d7b2438d3 119 * @param proto the IP protocol for RAW IP pcbs
switches 0:5c4d7b2438d3 120 * @param callback a function to call on status changes (RX available, TX'ed)
switches 0:5c4d7b2438d3 121 * @return a newly allocated struct netconn or
switches 0:5c4d7b2438d3 122 * NULL on memory error
switches 0:5c4d7b2438d3 123 */
switches 0:5c4d7b2438d3 124 struct netconn*
switches 0:5c4d7b2438d3 125 netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
switches 0:5c4d7b2438d3 126 {
switches 0:5c4d7b2438d3 127 struct netconn *conn;
switches 0:5c4d7b2438d3 128 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 129 API_MSG_VAR_ALLOC_RETURN_NULL(msg);
switches 0:5c4d7b2438d3 130
switches 0:5c4d7b2438d3 131 conn = netconn_alloc(t, callback);
switches 0:5c4d7b2438d3 132 if (conn != NULL) {
switches 0:5c4d7b2438d3 133 err_t err;
switches 0:5c4d7b2438d3 134
switches 0:5c4d7b2438d3 135 API_MSG_VAR_REF(msg).msg.n.proto = proto;
switches 0:5c4d7b2438d3 136 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 137 err = netconn_apimsg(lwip_netconn_do_newconn, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 138 if (err != ERR_OK) {
switches 0:5c4d7b2438d3 139 LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
switches 0:5c4d7b2438d3 140 LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
switches 0:5c4d7b2438d3 141 #if LWIP_TCP
switches 0:5c4d7b2438d3 142 LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
switches 0:5c4d7b2438d3 143 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 144 #if !LWIP_NETCONN_SEM_PER_THREAD
switches 0:5c4d7b2438d3 145 LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
switches 0:5c4d7b2438d3 146 sys_sem_free(&conn->op_completed);
switches 0:5c4d7b2438d3 147 #endif /* !LWIP_NETCONN_SEM_PER_THREAD */
switches 0:5c4d7b2438d3 148 sys_mbox_free(&conn->recvmbox);
switches 0:5c4d7b2438d3 149 memp_free(MEMP_NETCONN, conn);
switches 0:5c4d7b2438d3 150 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 151 return NULL;
switches 0:5c4d7b2438d3 152 }
switches 0:5c4d7b2438d3 153 }
switches 0:5c4d7b2438d3 154 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 155 return conn;
switches 0:5c4d7b2438d3 156 }
switches 0:5c4d7b2438d3 157
switches 0:5c4d7b2438d3 158 /**
switches 0:5c4d7b2438d3 159 * @ingroup netconn_common
switches 0:5c4d7b2438d3 160 * Close a netconn 'connection' and free its resources.
switches 0:5c4d7b2438d3 161 * UDP and RAW connection are completely closed, TCP pcbs might still be in a waitstate
switches 0:5c4d7b2438d3 162 * after this returns.
switches 0:5c4d7b2438d3 163 *
switches 0:5c4d7b2438d3 164 * @param conn the netconn to delete
switches 0:5c4d7b2438d3 165 * @return ERR_OK if the connection was deleted
switches 0:5c4d7b2438d3 166 */
switches 0:5c4d7b2438d3 167 err_t
switches 0:5c4d7b2438d3 168 netconn_delete(struct netconn *conn)
switches 0:5c4d7b2438d3 169 {
switches 0:5c4d7b2438d3 170 err_t err;
switches 0:5c4d7b2438d3 171 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 172
switches 0:5c4d7b2438d3 173 /* No ASSERT here because possible to get a (conn == NULL) if we got an accept error */
switches 0:5c4d7b2438d3 174 if (conn == NULL) {
switches 0:5c4d7b2438d3 175 return ERR_OK;
switches 0:5c4d7b2438d3 176 }
switches 0:5c4d7b2438d3 177
switches 0:5c4d7b2438d3 178 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 179 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 180 #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
switches 0:5c4d7b2438d3 181 /* get the time we started, which is later compared to
switches 0:5c4d7b2438d3 182 sys_now() + conn->send_timeout */
switches 0:5c4d7b2438d3 183 API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
switches 0:5c4d7b2438d3 184 #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
switches 0:5c4d7b2438d3 185 #if LWIP_TCP
switches 0:5c4d7b2438d3 186 API_MSG_VAR_REF(msg).msg.sd.polls_left =
switches 0:5c4d7b2438d3 187 ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
switches 0:5c4d7b2438d3 188 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 189 #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
switches 0:5c4d7b2438d3 190 err = netconn_apimsg(lwip_netconn_do_delconn, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 191 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 192
switches 0:5c4d7b2438d3 193 if (err != ERR_OK) {
switches 0:5c4d7b2438d3 194 return err;
switches 0:5c4d7b2438d3 195 }
switches 0:5c4d7b2438d3 196
switches 0:5c4d7b2438d3 197 netconn_free(conn);
switches 0:5c4d7b2438d3 198
switches 0:5c4d7b2438d3 199 return ERR_OK;
switches 0:5c4d7b2438d3 200 }
switches 0:5c4d7b2438d3 201
switches 0:5c4d7b2438d3 202 /**
switches 0:5c4d7b2438d3 203 * Get the local or remote IP address and port of a netconn.
switches 0:5c4d7b2438d3 204 * For RAW netconns, this returns the protocol instead of a port!
switches 0:5c4d7b2438d3 205 *
switches 0:5c4d7b2438d3 206 * @param conn the netconn to query
switches 0:5c4d7b2438d3 207 * @param addr a pointer to which to save the IP address
switches 0:5c4d7b2438d3 208 * @param port a pointer to which to save the port (or protocol for RAW)
switches 0:5c4d7b2438d3 209 * @param local 1 to get the local IP address, 0 to get the remote one
switches 0:5c4d7b2438d3 210 * @return ERR_CONN for invalid connections
switches 0:5c4d7b2438d3 211 * ERR_OK if the information was retrieved
switches 0:5c4d7b2438d3 212 */
switches 0:5c4d7b2438d3 213 err_t
switches 0:5c4d7b2438d3 214 netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
switches 0:5c4d7b2438d3 215 {
switches 0:5c4d7b2438d3 216 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 217 err_t err;
switches 0:5c4d7b2438d3 218
switches 0:5c4d7b2438d3 219 LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 220 LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 221 LWIP_ERROR("netconn_getaddr: invalid port", (port != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 222
switches 0:5c4d7b2438d3 223 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 224 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 225 API_MSG_VAR_REF(msg).msg.ad.local = local;
switches 0:5c4d7b2438d3 226 #if LWIP_MPU_COMPATIBLE
switches 0:5c4d7b2438d3 227 err = netconn_apimsg(lwip_netconn_do_getaddr, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 228 *addr = msg->msg.ad.ipaddr;
switches 0:5c4d7b2438d3 229 *port = msg->msg.ad.port;
switches 0:5c4d7b2438d3 230 #else /* LWIP_MPU_COMPATIBLE */
switches 0:5c4d7b2438d3 231 msg.msg.ad.ipaddr = addr;
switches 0:5c4d7b2438d3 232 msg.msg.ad.port = port;
switches 0:5c4d7b2438d3 233 err = netconn_apimsg(lwip_netconn_do_getaddr, &msg);
switches 0:5c4d7b2438d3 234 #endif /* LWIP_MPU_COMPATIBLE */
switches 0:5c4d7b2438d3 235 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 236
switches 0:5c4d7b2438d3 237 return err;
switches 0:5c4d7b2438d3 238 }
switches 0:5c4d7b2438d3 239
switches 0:5c4d7b2438d3 240 /**
switches 0:5c4d7b2438d3 241 * @ingroup netconn_common
switches 0:5c4d7b2438d3 242 * Bind a netconn to a specific local IP address and port.
switches 0:5c4d7b2438d3 243 * Binding one netconn twice might not always be checked correctly!
switches 0:5c4d7b2438d3 244 *
switches 0:5c4d7b2438d3 245 * @param conn the netconn to bind
switches 0:5c4d7b2438d3 246 * @param addr the local IP address to bind the netconn to (use IP_ADDR_ANY
switches 0:5c4d7b2438d3 247 * to bind to all addresses)
switches 0:5c4d7b2438d3 248 * @param port the local port to bind the netconn to (not used for RAW)
switches 0:5c4d7b2438d3 249 * @return ERR_OK if bound, any other err_t on failure
switches 0:5c4d7b2438d3 250 */
switches 0:5c4d7b2438d3 251 err_t
switches 0:5c4d7b2438d3 252 netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port)
switches 0:5c4d7b2438d3 253 {
switches 0:5c4d7b2438d3 254 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 255 err_t err;
switches 0:5c4d7b2438d3 256
switches 0:5c4d7b2438d3 257 LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 258
switches 0:5c4d7b2438d3 259 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
switches 0:5c4d7b2438d3 260 if (addr == NULL) {
switches 0:5c4d7b2438d3 261 addr = IP_ADDR_ANY;
switches 0:5c4d7b2438d3 262 }
switches 0:5c4d7b2438d3 263
switches 0:5c4d7b2438d3 264 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 265 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 266 API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr);
switches 0:5c4d7b2438d3 267 API_MSG_VAR_REF(msg).msg.bc.port = port;
switches 0:5c4d7b2438d3 268 err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 269 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 270
switches 0:5c4d7b2438d3 271 return err;
switches 0:5c4d7b2438d3 272 }
switches 0:5c4d7b2438d3 273
switches 0:5c4d7b2438d3 274 /**
switches 0:5c4d7b2438d3 275 * @ingroup netconn_common
switches 0:5c4d7b2438d3 276 * Connect a netconn to a specific remote IP address and port.
switches 0:5c4d7b2438d3 277 *
switches 0:5c4d7b2438d3 278 * @param conn the netconn to connect
switches 0:5c4d7b2438d3 279 * @param addr the remote IP address to connect to
switches 0:5c4d7b2438d3 280 * @param port the remote port to connect to (no used for RAW)
switches 0:5c4d7b2438d3 281 * @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
switches 0:5c4d7b2438d3 282 */
switches 0:5c4d7b2438d3 283 err_t
switches 0:5c4d7b2438d3 284 netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port)
switches 0:5c4d7b2438d3 285 {
switches 0:5c4d7b2438d3 286 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 287 err_t err;
switches 0:5c4d7b2438d3 288
switches 0:5c4d7b2438d3 289 LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 290
switches 0:5c4d7b2438d3 291 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
switches 0:5c4d7b2438d3 292 if (addr == NULL) {
switches 0:5c4d7b2438d3 293 addr = IP_ADDR_ANY;
switches 0:5c4d7b2438d3 294 }
switches 0:5c4d7b2438d3 295
switches 0:5c4d7b2438d3 296 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 297 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 298 API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr);
switches 0:5c4d7b2438d3 299 API_MSG_VAR_REF(msg).msg.bc.port = port;
switches 0:5c4d7b2438d3 300 err = netconn_apimsg(lwip_netconn_do_connect, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 301 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 302
switches 0:5c4d7b2438d3 303 return err;
switches 0:5c4d7b2438d3 304 }
switches 0:5c4d7b2438d3 305
switches 0:5c4d7b2438d3 306 /**
switches 0:5c4d7b2438d3 307 * @ingroup netconn_udp
switches 0:5c4d7b2438d3 308 * Disconnect a netconn from its current peer (only valid for UDP netconns).
switches 0:5c4d7b2438d3 309 *
switches 0:5c4d7b2438d3 310 * @param conn the netconn to disconnect
switches 0:5c4d7b2438d3 311 * @return @todo: return value is not set here...
switches 0:5c4d7b2438d3 312 */
switches 0:5c4d7b2438d3 313 err_t
switches 0:5c4d7b2438d3 314 netconn_disconnect(struct netconn *conn)
switches 0:5c4d7b2438d3 315 {
switches 0:5c4d7b2438d3 316 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 317 err_t err;
switches 0:5c4d7b2438d3 318
switches 0:5c4d7b2438d3 319 LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 320
switches 0:5c4d7b2438d3 321 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 322 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 323 err = netconn_apimsg(lwip_netconn_do_disconnect, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 324 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 325
switches 0:5c4d7b2438d3 326 return err;
switches 0:5c4d7b2438d3 327 }
switches 0:5c4d7b2438d3 328
switches 0:5c4d7b2438d3 329 /**
switches 0:5c4d7b2438d3 330 * @ingroup netconn_tcp
switches 0:5c4d7b2438d3 331 * Set a TCP netconn into listen mode
switches 0:5c4d7b2438d3 332 *
switches 0:5c4d7b2438d3 333 * @param conn the tcp netconn to set to listen mode
switches 0:5c4d7b2438d3 334 * @param backlog the listen backlog, only used if TCP_LISTEN_BACKLOG==1
switches 0:5c4d7b2438d3 335 * @return ERR_OK if the netconn was set to listen (UDP and RAW netconns
switches 0:5c4d7b2438d3 336 * don't return any error (yet?))
switches 0:5c4d7b2438d3 337 */
switches 0:5c4d7b2438d3 338 err_t
switches 0:5c4d7b2438d3 339 netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
switches 0:5c4d7b2438d3 340 {
switches 0:5c4d7b2438d3 341 #if LWIP_TCP
switches 0:5c4d7b2438d3 342 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 343 err_t err;
switches 0:5c4d7b2438d3 344
switches 0:5c4d7b2438d3 345 /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
switches 0:5c4d7b2438d3 346 LWIP_UNUSED_ARG(backlog);
switches 0:5c4d7b2438d3 347
switches 0:5c4d7b2438d3 348 LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 349
switches 0:5c4d7b2438d3 350 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 351 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 352 #if TCP_LISTEN_BACKLOG
switches 0:5c4d7b2438d3 353 API_MSG_VAR_REF(msg).msg.lb.backlog = backlog;
switches 0:5c4d7b2438d3 354 #endif /* TCP_LISTEN_BACKLOG */
switches 0:5c4d7b2438d3 355 err = netconn_apimsg(lwip_netconn_do_listen, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 356 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 357
switches 0:5c4d7b2438d3 358 return err;
switches 0:5c4d7b2438d3 359 #else /* LWIP_TCP */
switches 0:5c4d7b2438d3 360 LWIP_UNUSED_ARG(conn);
switches 0:5c4d7b2438d3 361 LWIP_UNUSED_ARG(backlog);
switches 0:5c4d7b2438d3 362 return ERR_ARG;
switches 0:5c4d7b2438d3 363 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 364 }
switches 0:5c4d7b2438d3 365
switches 0:5c4d7b2438d3 366 /**
switches 0:5c4d7b2438d3 367 * @ingroup netconn_tcp
switches 0:5c4d7b2438d3 368 * Accept a new connection on a TCP listening netconn.
switches 0:5c4d7b2438d3 369 *
switches 0:5c4d7b2438d3 370 * @param conn the TCP listen netconn
switches 0:5c4d7b2438d3 371 * @param new_conn pointer where the new connection is stored
switches 0:5c4d7b2438d3 372 * @return ERR_OK if a new connection has been received or an error
switches 0:5c4d7b2438d3 373 * code otherwise
switches 0:5c4d7b2438d3 374 */
switches 0:5c4d7b2438d3 375 err_t
switches 0:5c4d7b2438d3 376 netconn_accept(struct netconn *conn, struct netconn **new_conn)
switches 0:5c4d7b2438d3 377 {
switches 0:5c4d7b2438d3 378 #if LWIP_TCP
switches 0:5c4d7b2438d3 379 void *accept_ptr;
switches 0:5c4d7b2438d3 380 struct netconn *newconn;
switches 0:5c4d7b2438d3 381 err_t err;
switches 0:5c4d7b2438d3 382 #if TCP_LISTEN_BACKLOG
switches 0:5c4d7b2438d3 383 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 384 #endif /* TCP_LISTEN_BACKLOG */
switches 0:5c4d7b2438d3 385
switches 0:5c4d7b2438d3 386 LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 387 *new_conn = NULL;
switches 0:5c4d7b2438d3 388 LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 389
switches 0:5c4d7b2438d3 390 err = conn->last_err;
switches 0:5c4d7b2438d3 391 if (ERR_IS_FATAL(err)) {
switches 0:5c4d7b2438d3 392 /* don't recv on fatal errors: this might block the application task
switches 0:5c4d7b2438d3 393 waiting on acceptmbox forever! */
switches 0:5c4d7b2438d3 394 return err;
switches 0:5c4d7b2438d3 395 }
switches 0:5c4d7b2438d3 396 if (!sys_mbox_valid(&conn->acceptmbox)) {
switches 0:5c4d7b2438d3 397 return ERR_CLSD;
switches 0:5c4d7b2438d3 398 }
switches 0:5c4d7b2438d3 399
switches 0:5c4d7b2438d3 400 #if TCP_LISTEN_BACKLOG
switches 0:5c4d7b2438d3 401 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 402 #endif /* TCP_LISTEN_BACKLOG */
switches 0:5c4d7b2438d3 403
switches 0:5c4d7b2438d3 404 #if LWIP_SO_RCVTIMEO
switches 0:5c4d7b2438d3 405 if (sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
switches 0:5c4d7b2438d3 406 #if TCP_LISTEN_BACKLOG
switches 0:5c4d7b2438d3 407 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 408 #endif /* TCP_LISTEN_BACKLOG */
switches 0:5c4d7b2438d3 409 return ERR_TIMEOUT;
switches 0:5c4d7b2438d3 410 }
switches 0:5c4d7b2438d3 411 #else
switches 0:5c4d7b2438d3 412 sys_arch_mbox_fetch(&conn->acceptmbox, &accept_ptr, 0);
switches 0:5c4d7b2438d3 413 #endif /* LWIP_SO_RCVTIMEO*/
switches 0:5c4d7b2438d3 414 newconn = (struct netconn *)accept_ptr;
switches 0:5c4d7b2438d3 415 /* Register event with callback */
switches 0:5c4d7b2438d3 416 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
switches 0:5c4d7b2438d3 417
switches 0:5c4d7b2438d3 418 if (accept_ptr == &netconn_aborted) {
switches 0:5c4d7b2438d3 419 /* a connection has been aborted: out of pcbs or out of netconns during accept */
switches 0:5c4d7b2438d3 420 /* @todo: set netconn error, but this would be fatal and thus block further accepts */
switches 0:5c4d7b2438d3 421 #if TCP_LISTEN_BACKLOG
switches 0:5c4d7b2438d3 422 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 423 #endif /* TCP_LISTEN_BACKLOG */
switches 0:5c4d7b2438d3 424 return ERR_ABRT;
switches 0:5c4d7b2438d3 425 }
switches 0:5c4d7b2438d3 426 if (newconn == NULL) {
switches 0:5c4d7b2438d3 427 /* connection has been aborted */
switches 0:5c4d7b2438d3 428 /* in this special case, we set the netconn error from application thread, as
switches 0:5c4d7b2438d3 429 on a ready-to-accept listening netconn, there should not be anything running
switches 0:5c4d7b2438d3 430 in tcpip_thread */
switches 0:5c4d7b2438d3 431 NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
switches 0:5c4d7b2438d3 432 #if TCP_LISTEN_BACKLOG
switches 0:5c4d7b2438d3 433 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 434 #endif /* TCP_LISTEN_BACKLOG */
switches 0:5c4d7b2438d3 435 return ERR_CLSD;
switches 0:5c4d7b2438d3 436 }
switches 0:5c4d7b2438d3 437 #if TCP_LISTEN_BACKLOG
switches 0:5c4d7b2438d3 438 /* Let the stack know that we have accepted the connection. */
switches 0:5c4d7b2438d3 439 API_MSG_VAR_REF(msg).conn = newconn;
switches 0:5c4d7b2438d3 440 /* don't care for the return value of lwip_netconn_do_recv */
switches 0:5c4d7b2438d3 441 netconn_apimsg(lwip_netconn_do_accepted, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 442 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 443 #endif /* TCP_LISTEN_BACKLOG */
switches 0:5c4d7b2438d3 444
switches 0:5c4d7b2438d3 445 *new_conn = newconn;
switches 0:5c4d7b2438d3 446 /* don't set conn->last_err: it's only ERR_OK, anyway */
switches 0:5c4d7b2438d3 447 return ERR_OK;
switches 0:5c4d7b2438d3 448 #else /* LWIP_TCP */
switches 0:5c4d7b2438d3 449 LWIP_UNUSED_ARG(conn);
switches 0:5c4d7b2438d3 450 LWIP_UNUSED_ARG(new_conn);
switches 0:5c4d7b2438d3 451 return ERR_ARG;
switches 0:5c4d7b2438d3 452 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 453 }
switches 0:5c4d7b2438d3 454
switches 0:5c4d7b2438d3 455 /**
switches 0:5c4d7b2438d3 456 * @ingroup netconn_common
switches 0:5c4d7b2438d3 457 * Receive data: actual implementation that doesn't care whether pbuf or netbuf
switches 0:5c4d7b2438d3 458 * is received
switches 0:5c4d7b2438d3 459 *
switches 0:5c4d7b2438d3 460 * @param conn the netconn from which to receive data
switches 0:5c4d7b2438d3 461 * @param new_buf pointer where a new pbuf/netbuf is stored when received data
switches 0:5c4d7b2438d3 462 * @return ERR_OK if data has been received, an error code otherwise (timeout,
switches 0:5c4d7b2438d3 463 * memory error or another error)
switches 0:5c4d7b2438d3 464 */
switches 0:5c4d7b2438d3 465 static err_t
switches 0:5c4d7b2438d3 466 netconn_recv_data(struct netconn *conn, void **new_buf)
switches 0:5c4d7b2438d3 467 {
switches 0:5c4d7b2438d3 468 void *buf = NULL;
switches 0:5c4d7b2438d3 469 u16_t len;
switches 0:5c4d7b2438d3 470 err_t err;
switches 0:5c4d7b2438d3 471 #if LWIP_TCP
switches 0:5c4d7b2438d3 472 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 473 #if LWIP_MPU_COMPATIBLE
switches 0:5c4d7b2438d3 474 msg = NULL;
switches 0:5c4d7b2438d3 475 #endif
switches 0:5c4d7b2438d3 476 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 477
switches 0:5c4d7b2438d3 478 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 479 *new_buf = NULL;
switches 0:5c4d7b2438d3 480 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 481 #if LWIP_TCP
switches 0:5c4d7b2438d3 482 #if (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 483 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
switches 0:5c4d7b2438d3 484 #endif /* (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 485 {
switches 0:5c4d7b2438d3 486 if (!sys_mbox_valid(&conn->recvmbox)) {
switches 0:5c4d7b2438d3 487 /* This happens when calling this function after receiving FIN */
switches 0:5c4d7b2438d3 488 return sys_mbox_valid(&conn->acceptmbox) ? ERR_CONN : ERR_CLSD;
switches 0:5c4d7b2438d3 489 }
switches 0:5c4d7b2438d3 490 }
switches 0:5c4d7b2438d3 491 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 492 LWIP_ERROR("netconn_recv: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
switches 0:5c4d7b2438d3 493
switches 0:5c4d7b2438d3 494 err = conn->last_err;
switches 0:5c4d7b2438d3 495 if (ERR_IS_FATAL(err)) {
switches 0:5c4d7b2438d3 496 /* don't recv on fatal errors: this might block the application task
switches 0:5c4d7b2438d3 497 waiting on recvmbox forever! */
switches 0:5c4d7b2438d3 498 /* @todo: this does not allow us to fetch data that has been put into recvmbox
switches 0:5c4d7b2438d3 499 before the fatal error occurred - is that a problem? */
switches 0:5c4d7b2438d3 500 return err;
switches 0:5c4d7b2438d3 501 }
switches 0:5c4d7b2438d3 502 #if LWIP_TCP
switches 0:5c4d7b2438d3 503 #if (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 504 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
switches 0:5c4d7b2438d3 505 #endif /* (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 506 {
switches 0:5c4d7b2438d3 507 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 508 }
switches 0:5c4d7b2438d3 509 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 510
switches 0:5c4d7b2438d3 511 #if LWIP_SO_RCVTIMEO
switches 0:5c4d7b2438d3 512 if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
switches 0:5c4d7b2438d3 513 #if LWIP_TCP
switches 0:5c4d7b2438d3 514 #if (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 515 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
switches 0:5c4d7b2438d3 516 #endif /* (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 517 {
switches 0:5c4d7b2438d3 518 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 519 }
switches 0:5c4d7b2438d3 520 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 521 return ERR_TIMEOUT;
switches 0:5c4d7b2438d3 522 }
switches 0:5c4d7b2438d3 523 #else
switches 0:5c4d7b2438d3 524 sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
switches 0:5c4d7b2438d3 525 #endif /* LWIP_SO_RCVTIMEO*/
switches 0:5c4d7b2438d3 526
switches 0:5c4d7b2438d3 527 #if LWIP_TCP
switches 0:5c4d7b2438d3 528 #if (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 529 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
switches 0:5c4d7b2438d3 530 #endif /* (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 531 {
switches 0:5c4d7b2438d3 532 /* Let the stack know that we have taken the data. */
switches 0:5c4d7b2438d3 533 /* @todo: Speedup: Don't block and wait for the answer here
switches 0:5c4d7b2438d3 534 (to prevent multiple thread-switches). */
switches 0:5c4d7b2438d3 535 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 536 if (buf != NULL) {
switches 0:5c4d7b2438d3 537 API_MSG_VAR_REF(msg).msg.r.len = ((struct pbuf *)buf)->tot_len;
switches 0:5c4d7b2438d3 538 } else {
switches 0:5c4d7b2438d3 539 API_MSG_VAR_REF(msg).msg.r.len = 1;
switches 0:5c4d7b2438d3 540 }
switches 0:5c4d7b2438d3 541
switches 0:5c4d7b2438d3 542 /* don't care for the return value of lwip_netconn_do_recv */
switches 0:5c4d7b2438d3 543 netconn_apimsg(lwip_netconn_do_recv, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 544 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 545
switches 0:5c4d7b2438d3 546 /* If we are closed, we indicate that we no longer wish to use the socket */
switches 0:5c4d7b2438d3 547 if (buf == NULL) {
switches 0:5c4d7b2438d3 548 API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
switches 0:5c4d7b2438d3 549 /* RX side is closed, so deallocate the recvmbox */
switches 0:5c4d7b2438d3 550 netconn_close_shutdown(conn, NETCONN_SHUT_RD);
switches 0:5c4d7b2438d3 551 /* Don' store ERR_CLSD as conn->err since we are only half-closed */
switches 0:5c4d7b2438d3 552 return ERR_CLSD;
switches 0:5c4d7b2438d3 553 }
switches 0:5c4d7b2438d3 554 len = ((struct pbuf *)buf)->tot_len;
switches 0:5c4d7b2438d3 555 }
switches 0:5c4d7b2438d3 556 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 557 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 558 else
switches 0:5c4d7b2438d3 559 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 560 #if (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 561 {
switches 0:5c4d7b2438d3 562 LWIP_ASSERT("buf != NULL", buf != NULL);
switches 0:5c4d7b2438d3 563 len = netbuf_len((struct netbuf *)buf);
switches 0:5c4d7b2438d3 564 }
switches 0:5c4d7b2438d3 565 #endif /* (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 566
switches 0:5c4d7b2438d3 567 #if LWIP_SO_RCVBUF
switches 0:5c4d7b2438d3 568 SYS_ARCH_DEC(conn->recv_avail, len);
switches 0:5c4d7b2438d3 569 #endif /* LWIP_SO_RCVBUF */
switches 0:5c4d7b2438d3 570 /* Register event with callback */
switches 0:5c4d7b2438d3 571 API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
switches 0:5c4d7b2438d3 572
switches 0:5c4d7b2438d3 573 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
switches 0:5c4d7b2438d3 574
switches 0:5c4d7b2438d3 575 *new_buf = buf;
switches 0:5c4d7b2438d3 576 /* don't set conn->last_err: it's only ERR_OK, anyway */
switches 0:5c4d7b2438d3 577 return ERR_OK;
switches 0:5c4d7b2438d3 578 }
switches 0:5c4d7b2438d3 579
switches 0:5c4d7b2438d3 580 /**
switches 0:5c4d7b2438d3 581 * @ingroup netconn_tcp
switches 0:5c4d7b2438d3 582 * Receive data (in form of a pbuf) from a TCP netconn
switches 0:5c4d7b2438d3 583 *
switches 0:5c4d7b2438d3 584 * @param conn the netconn from which to receive data
switches 0:5c4d7b2438d3 585 * @param new_buf pointer where a new pbuf is stored when received data
switches 0:5c4d7b2438d3 586 * @return ERR_OK if data has been received, an error code otherwise (timeout,
switches 0:5c4d7b2438d3 587 * memory error or another error)
switches 0:5c4d7b2438d3 588 * ERR_ARG if conn is not a TCP netconn
switches 0:5c4d7b2438d3 589 */
switches 0:5c4d7b2438d3 590 err_t
switches 0:5c4d7b2438d3 591 netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
switches 0:5c4d7b2438d3 592 {
switches 0:5c4d7b2438d3 593 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
switches 0:5c4d7b2438d3 594 NETCONNTYPE_GROUP(netconn_type(conn)) == NETCONN_TCP, return ERR_ARG;);
switches 0:5c4d7b2438d3 595
switches 0:5c4d7b2438d3 596 return netconn_recv_data(conn, (void **)new_buf);
switches 0:5c4d7b2438d3 597 }
switches 0:5c4d7b2438d3 598
switches 0:5c4d7b2438d3 599 /**
switches 0:5c4d7b2438d3 600 * @ingroup netconn_common
switches 0:5c4d7b2438d3 601 * Receive data (in form of a netbuf containing a packet buffer) from a netconn
switches 0:5c4d7b2438d3 602 *
switches 0:5c4d7b2438d3 603 * @param conn the netconn from which to receive data
switches 0:5c4d7b2438d3 604 * @param new_buf pointer where a new netbuf is stored when received data
switches 0:5c4d7b2438d3 605 * @return ERR_OK if data has been received, an error code otherwise (timeout,
switches 0:5c4d7b2438d3 606 * memory error or another error)
switches 0:5c4d7b2438d3 607 */
switches 0:5c4d7b2438d3 608 err_t
switches 0:5c4d7b2438d3 609 netconn_recv(struct netconn *conn, struct netbuf **new_buf)
switches 0:5c4d7b2438d3 610 {
switches 0:5c4d7b2438d3 611 #if LWIP_TCP
switches 0:5c4d7b2438d3 612 struct netbuf *buf = NULL;
switches 0:5c4d7b2438d3 613 err_t err;
switches 0:5c4d7b2438d3 614 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 615
switches 0:5c4d7b2438d3 616 LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 617 *new_buf = NULL;
switches 0:5c4d7b2438d3 618 LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 619
switches 0:5c4d7b2438d3 620 #if LWIP_TCP
switches 0:5c4d7b2438d3 621 #if (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 622 if (NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP)
switches 0:5c4d7b2438d3 623 #endif /* (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 624 {
switches 0:5c4d7b2438d3 625 struct pbuf *p = NULL;
switches 0:5c4d7b2438d3 626 /* This is not a listening netconn, since recvmbox is set */
switches 0:5c4d7b2438d3 627
switches 0:5c4d7b2438d3 628 buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
switches 0:5c4d7b2438d3 629 if (buf == NULL) {
switches 0:5c4d7b2438d3 630 return ERR_MEM;
switches 0:5c4d7b2438d3 631 }
switches 0:5c4d7b2438d3 632
switches 0:5c4d7b2438d3 633 err = netconn_recv_data(conn, (void **)&p);
switches 0:5c4d7b2438d3 634 if (err != ERR_OK) {
switches 0:5c4d7b2438d3 635 memp_free(MEMP_NETBUF, buf);
switches 0:5c4d7b2438d3 636 return err;
switches 0:5c4d7b2438d3 637 }
switches 0:5c4d7b2438d3 638 LWIP_ASSERT("p != NULL", p != NULL);
switches 0:5c4d7b2438d3 639
switches 0:5c4d7b2438d3 640 buf->p = p;
switches 0:5c4d7b2438d3 641 buf->ptr = p;
switches 0:5c4d7b2438d3 642 buf->port = 0;
switches 0:5c4d7b2438d3 643 ip_addr_set_zero(&buf->addr);
switches 0:5c4d7b2438d3 644 *new_buf = buf;
switches 0:5c4d7b2438d3 645 /* don't set conn->last_err: it's only ERR_OK, anyway */
switches 0:5c4d7b2438d3 646 return ERR_OK;
switches 0:5c4d7b2438d3 647 }
switches 0:5c4d7b2438d3 648 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 649 #if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 650 else
switches 0:5c4d7b2438d3 651 #endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 652 {
switches 0:5c4d7b2438d3 653 #if (LWIP_UDP || LWIP_RAW)
switches 0:5c4d7b2438d3 654 return netconn_recv_data(conn, (void **)new_buf);
switches 0:5c4d7b2438d3 655 #endif /* (LWIP_UDP || LWIP_RAW) */
switches 0:5c4d7b2438d3 656 }
switches 0:5c4d7b2438d3 657 }
switches 0:5c4d7b2438d3 658
switches 0:5c4d7b2438d3 659 /**
switches 0:5c4d7b2438d3 660 * @ingroup netconn_udp
switches 0:5c4d7b2438d3 661 * Send data (in form of a netbuf) to a specific remote IP address and port.
switches 0:5c4d7b2438d3 662 * Only to be used for UDP and RAW netconns (not TCP).
switches 0:5c4d7b2438d3 663 *
switches 0:5c4d7b2438d3 664 * @param conn the netconn over which to send data
switches 0:5c4d7b2438d3 665 * @param buf a netbuf containing the data to send
switches 0:5c4d7b2438d3 666 * @param addr the remote IP address to which to send the data
switches 0:5c4d7b2438d3 667 * @param port the remote port to which to send the data
switches 0:5c4d7b2438d3 668 * @return ERR_OK if data was sent, any other err_t on error
switches 0:5c4d7b2438d3 669 */
switches 0:5c4d7b2438d3 670 err_t
switches 0:5c4d7b2438d3 671 netconn_sendto(struct netconn *conn, struct netbuf *buf, const ip_addr_t *addr, u16_t port)
switches 0:5c4d7b2438d3 672 {
switches 0:5c4d7b2438d3 673 if (buf != NULL) {
switches 0:5c4d7b2438d3 674 ip_addr_set(&buf->addr, addr);
switches 0:5c4d7b2438d3 675 buf->port = port;
switches 0:5c4d7b2438d3 676 return netconn_send(conn, buf);
switches 0:5c4d7b2438d3 677 }
switches 0:5c4d7b2438d3 678 return ERR_VAL;
switches 0:5c4d7b2438d3 679 }
switches 0:5c4d7b2438d3 680
switches 0:5c4d7b2438d3 681 /**
switches 0:5c4d7b2438d3 682 * @ingroup netconn_udp
switches 0:5c4d7b2438d3 683 * Send data over a UDP or RAW netconn (that is already connected).
switches 0:5c4d7b2438d3 684 *
switches 0:5c4d7b2438d3 685 * @param conn the UDP or RAW netconn over which to send data
switches 0:5c4d7b2438d3 686 * @param buf a netbuf containing the data to send
switches 0:5c4d7b2438d3 687 * @return ERR_OK if data was sent, any other err_t on error
switches 0:5c4d7b2438d3 688 */
switches 0:5c4d7b2438d3 689 err_t
switches 0:5c4d7b2438d3 690 netconn_send(struct netconn *conn, struct netbuf *buf)
switches 0:5c4d7b2438d3 691 {
switches 0:5c4d7b2438d3 692 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 693 err_t err;
switches 0:5c4d7b2438d3 694
switches 0:5c4d7b2438d3 695 LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 696
switches 0:5c4d7b2438d3 697 LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %"U16_F" bytes\n", buf->p->tot_len));
switches 0:5c4d7b2438d3 698 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 699 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 700 API_MSG_VAR_REF(msg).msg.b = buf;
switches 0:5c4d7b2438d3 701 err = netconn_apimsg(lwip_netconn_do_send, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 702 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 703
switches 0:5c4d7b2438d3 704 return err;
switches 0:5c4d7b2438d3 705 }
switches 0:5c4d7b2438d3 706
switches 0:5c4d7b2438d3 707 /**
switches 0:5c4d7b2438d3 708 * @ingroup netconn_tcp
switches 0:5c4d7b2438d3 709 * Send data over a TCP netconn.
switches 0:5c4d7b2438d3 710 *
switches 0:5c4d7b2438d3 711 * @param conn the TCP netconn over which to send data
switches 0:5c4d7b2438d3 712 * @param dataptr pointer to the application buffer that contains the data to send
switches 0:5c4d7b2438d3 713 * @param size size of the application data to send
switches 0:5c4d7b2438d3 714 * @param apiflags combination of following flags :
switches 0:5c4d7b2438d3 715 * - NETCONN_COPY: data will be copied into memory belonging to the stack
switches 0:5c4d7b2438d3 716 * - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
switches 0:5c4d7b2438d3 717 * - NETCONN_DONTBLOCK: only write the data if all data can be written at once
switches 0:5c4d7b2438d3 718 * @param bytes_written pointer to a location that receives the number of written bytes
switches 0:5c4d7b2438d3 719 * @return ERR_OK if data was sent, any other err_t on error
switches 0:5c4d7b2438d3 720 */
switches 0:5c4d7b2438d3 721 err_t
switches 0:5c4d7b2438d3 722 netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
switches 0:5c4d7b2438d3 723 u8_t apiflags, size_t *bytes_written)
switches 0:5c4d7b2438d3 724 {
switches 0:5c4d7b2438d3 725 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 726 err_t err;
switches 0:5c4d7b2438d3 727 u8_t dontblock;
switches 0:5c4d7b2438d3 728
switches 0:5c4d7b2438d3 729 LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 730 LWIP_ERROR("netconn_write: invalid conn->type", (NETCONNTYPE_GROUP(conn->type)== NETCONN_TCP), return ERR_VAL;);
switches 0:5c4d7b2438d3 731 if (size == 0) {
switches 0:5c4d7b2438d3 732 return ERR_OK;
switches 0:5c4d7b2438d3 733 }
switches 0:5c4d7b2438d3 734 dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
switches 0:5c4d7b2438d3 735 if (dontblock && !bytes_written) {
switches 0:5c4d7b2438d3 736 /* This implies netconn_write() cannot be used for non-blocking send, since
switches 0:5c4d7b2438d3 737 it has no way to return the number of bytes written. */
switches 0:5c4d7b2438d3 738 return ERR_VAL;
switches 0:5c4d7b2438d3 739 }
switches 0:5c4d7b2438d3 740
switches 0:5c4d7b2438d3 741 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 742 /* non-blocking write sends as much */
switches 0:5c4d7b2438d3 743 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 744 API_MSG_VAR_REF(msg).msg.w.dataptr = dataptr;
switches 0:5c4d7b2438d3 745 API_MSG_VAR_REF(msg).msg.w.apiflags = apiflags;
switches 0:5c4d7b2438d3 746 API_MSG_VAR_REF(msg).msg.w.len = size;
switches 0:5c4d7b2438d3 747 #if LWIP_SO_SNDTIMEO
switches 0:5c4d7b2438d3 748 if (conn->send_timeout != 0) {
switches 0:5c4d7b2438d3 749 /* get the time we started, which is later compared to
switches 0:5c4d7b2438d3 750 sys_now() + conn->send_timeout */
switches 0:5c4d7b2438d3 751 API_MSG_VAR_REF(msg).msg.w.time_started = sys_now();
switches 0:5c4d7b2438d3 752 } else {
switches 0:5c4d7b2438d3 753 API_MSG_VAR_REF(msg).msg.w.time_started = 0;
switches 0:5c4d7b2438d3 754 }
switches 0:5c4d7b2438d3 755 #endif /* LWIP_SO_SNDTIMEO */
switches 0:5c4d7b2438d3 756
switches 0:5c4d7b2438d3 757 /* For locking the core: this _can_ be delayed on low memory/low send buffer,
switches 0:5c4d7b2438d3 758 but if it is, this is done inside api_msg.c:do_write(), so we can use the
switches 0:5c4d7b2438d3 759 non-blocking version here. */
switches 0:5c4d7b2438d3 760 err = netconn_apimsg(lwip_netconn_do_write, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 761 if ((err == ERR_OK) && (bytes_written != NULL)) {
switches 0:5c4d7b2438d3 762 if (dontblock
switches 0:5c4d7b2438d3 763 #if LWIP_SO_SNDTIMEO
switches 0:5c4d7b2438d3 764 || (conn->send_timeout != 0)
switches 0:5c4d7b2438d3 765 #endif /* LWIP_SO_SNDTIMEO */
switches 0:5c4d7b2438d3 766 ) {
switches 0:5c4d7b2438d3 767 /* nonblocking write: maybe the data has been sent partly */
switches 0:5c4d7b2438d3 768 *bytes_written = API_MSG_VAR_REF(msg).msg.w.len;
switches 0:5c4d7b2438d3 769 } else {
switches 0:5c4d7b2438d3 770 /* blocking call succeeded: all data has been sent if it */
switches 0:5c4d7b2438d3 771 *bytes_written = size;
switches 0:5c4d7b2438d3 772 }
switches 0:5c4d7b2438d3 773 }
switches 0:5c4d7b2438d3 774 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 775
switches 0:5c4d7b2438d3 776 return err;
switches 0:5c4d7b2438d3 777 }
switches 0:5c4d7b2438d3 778
switches 0:5c4d7b2438d3 779 /**
switches 0:5c4d7b2438d3 780 * @ingroup netconn_tcp
switches 0:5c4d7b2438d3 781 * Close or shutdown a TCP netconn (doesn't delete it).
switches 0:5c4d7b2438d3 782 *
switches 0:5c4d7b2438d3 783 * @param conn the TCP netconn to close or shutdown
switches 0:5c4d7b2438d3 784 * @param how fully close or only shutdown one side?
switches 0:5c4d7b2438d3 785 * @return ERR_OK if the netconn was closed, any other err_t on error
switches 0:5c4d7b2438d3 786 */
switches 0:5c4d7b2438d3 787 static err_t
switches 0:5c4d7b2438d3 788 netconn_close_shutdown(struct netconn *conn, u8_t how)
switches 0:5c4d7b2438d3 789 {
switches 0:5c4d7b2438d3 790 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 791 err_t err;
switches 0:5c4d7b2438d3 792 LWIP_UNUSED_ARG(how);
switches 0:5c4d7b2438d3 793
switches 0:5c4d7b2438d3 794 LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 795
switches 0:5c4d7b2438d3 796 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 797 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 798 #if LWIP_TCP
switches 0:5c4d7b2438d3 799 /* shutting down both ends is the same as closing */
switches 0:5c4d7b2438d3 800 API_MSG_VAR_REF(msg).msg.sd.shut = how;
switches 0:5c4d7b2438d3 801 #if LWIP_SO_SNDTIMEO || LWIP_SO_LINGER
switches 0:5c4d7b2438d3 802 /* get the time we started, which is later compared to
switches 0:5c4d7b2438d3 803 sys_now() + conn->send_timeout */
switches 0:5c4d7b2438d3 804 API_MSG_VAR_REF(msg).msg.sd.time_started = sys_now();
switches 0:5c4d7b2438d3 805 #else /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
switches 0:5c4d7b2438d3 806 API_MSG_VAR_REF(msg).msg.sd.polls_left =
switches 0:5c4d7b2438d3 807 ((LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT + TCP_SLOW_INTERVAL - 1) / TCP_SLOW_INTERVAL) + 1;
switches 0:5c4d7b2438d3 808 #endif /* LWIP_SO_SNDTIMEO || LWIP_SO_LINGER */
switches 0:5c4d7b2438d3 809 #endif /* LWIP_TCP */
switches 0:5c4d7b2438d3 810 err = netconn_apimsg(lwip_netconn_do_close, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 811 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 812
switches 0:5c4d7b2438d3 813 return err;
switches 0:5c4d7b2438d3 814 }
switches 0:5c4d7b2438d3 815
switches 0:5c4d7b2438d3 816 /**
switches 0:5c4d7b2438d3 817 * @ingroup netconn_tcp
switches 0:5c4d7b2438d3 818 * Close a TCP netconn (doesn't delete it).
switches 0:5c4d7b2438d3 819 *
switches 0:5c4d7b2438d3 820 * @param conn the TCP netconn to close
switches 0:5c4d7b2438d3 821 * @return ERR_OK if the netconn was closed, any other err_t on error
switches 0:5c4d7b2438d3 822 */
switches 0:5c4d7b2438d3 823 err_t
switches 0:5c4d7b2438d3 824 netconn_close(struct netconn *conn)
switches 0:5c4d7b2438d3 825 {
switches 0:5c4d7b2438d3 826 /* shutting down both ends is the same as closing */
switches 0:5c4d7b2438d3 827 return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
switches 0:5c4d7b2438d3 828 }
switches 0:5c4d7b2438d3 829
switches 0:5c4d7b2438d3 830 /**
switches 0:5c4d7b2438d3 831 * @ingroup netconn_tcp
switches 0:5c4d7b2438d3 832 * Shut down one or both sides of a TCP netconn (doesn't delete it).
switches 0:5c4d7b2438d3 833 *
switches 0:5c4d7b2438d3 834 * @param conn the TCP netconn to shut down
switches 0:5c4d7b2438d3 835 * @param shut_rx shut down the RX side (no more read possible after this)
switches 0:5c4d7b2438d3 836 * @param shut_tx shut down the TX side (no more write possible after this)
switches 0:5c4d7b2438d3 837 * @return ERR_OK if the netconn was closed, any other err_t on error
switches 0:5c4d7b2438d3 838 */
switches 0:5c4d7b2438d3 839 err_t
switches 0:5c4d7b2438d3 840 netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
switches 0:5c4d7b2438d3 841 {
switches 0:5c4d7b2438d3 842 return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
switches 0:5c4d7b2438d3 843 }
switches 0:5c4d7b2438d3 844
switches 0:5c4d7b2438d3 845 #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)
switches 0:5c4d7b2438d3 846 /**
switches 0:5c4d7b2438d3 847 * @ingroup netconn_udp
switches 0:5c4d7b2438d3 848 * Join multicast groups for UDP netconns.
switches 0:5c4d7b2438d3 849 *
switches 0:5c4d7b2438d3 850 * @param conn the UDP netconn for which to change multicast addresses
switches 0:5c4d7b2438d3 851 * @param multiaddr IP address of the multicast group to join or leave
switches 0:5c4d7b2438d3 852 * @param netif_addr the IP address of the network interface on which to send
switches 0:5c4d7b2438d3 853 * the igmp message
switches 0:5c4d7b2438d3 854 * @param join_or_leave flag whether to send a join- or leave-message
switches 0:5c4d7b2438d3 855 * @return ERR_OK if the action was taken, any err_t on error
switches 0:5c4d7b2438d3 856 */
switches 0:5c4d7b2438d3 857 err_t
switches 0:5c4d7b2438d3 858 netconn_join_leave_group(struct netconn *conn,
switches 0:5c4d7b2438d3 859 const ip_addr_t *multiaddr,
switches 0:5c4d7b2438d3 860 const ip_addr_t *netif_addr,
switches 0:5c4d7b2438d3 861 enum netconn_igmp join_or_leave)
switches 0:5c4d7b2438d3 862 {
switches 0:5c4d7b2438d3 863 API_MSG_VAR_DECLARE(msg);
switches 0:5c4d7b2438d3 864 err_t err;
switches 0:5c4d7b2438d3 865
switches 0:5c4d7b2438d3 866 LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 867
switches 0:5c4d7b2438d3 868 API_MSG_VAR_ALLOC(msg);
switches 0:5c4d7b2438d3 869
switches 0:5c4d7b2438d3 870 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */
switches 0:5c4d7b2438d3 871 if (multiaddr == NULL) {
switches 0:5c4d7b2438d3 872 multiaddr = IP_ADDR_ANY;
switches 0:5c4d7b2438d3 873 }
switches 0:5c4d7b2438d3 874 if (netif_addr == NULL) {
switches 0:5c4d7b2438d3 875 netif_addr = IP_ADDR_ANY;
switches 0:5c4d7b2438d3 876 }
switches 0:5c4d7b2438d3 877
switches 0:5c4d7b2438d3 878 API_MSG_VAR_REF(msg).conn = conn;
switches 0:5c4d7b2438d3 879 API_MSG_VAR_REF(msg).msg.jl.multiaddr = API_MSG_VAR_REF(multiaddr);
switches 0:5c4d7b2438d3 880 API_MSG_VAR_REF(msg).msg.jl.netif_addr = API_MSG_VAR_REF(netif_addr);
switches 0:5c4d7b2438d3 881 API_MSG_VAR_REF(msg).msg.jl.join_or_leave = join_or_leave;
switches 0:5c4d7b2438d3 882 err = netconn_apimsg(lwip_netconn_do_join_leave_group, &API_MSG_VAR_REF(msg));
switches 0:5c4d7b2438d3 883 API_MSG_VAR_FREE(msg);
switches 0:5c4d7b2438d3 884
switches 0:5c4d7b2438d3 885 return err;
switches 0:5c4d7b2438d3 886 }
switches 0:5c4d7b2438d3 887 #endif /* LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) */
switches 0:5c4d7b2438d3 888
switches 0:5c4d7b2438d3 889 #if LWIP_DNS
switches 0:5c4d7b2438d3 890 /**
switches 0:5c4d7b2438d3 891 * @ingroup netconn_common
switches 0:5c4d7b2438d3 892 * Execute a DNS query, only one IP address is returned
switches 0:5c4d7b2438d3 893 *
switches 0:5c4d7b2438d3 894 * @param name a string representation of the DNS host name to query
switches 0:5c4d7b2438d3 895 * @param addr a preallocated ip_addr_t where to store the resolved IP address
switches 0:5c4d7b2438d3 896 * @param dns_addrtype IP address type (IPv4 / IPv6)
switches 0:5c4d7b2438d3 897 * @return ERR_OK: resolving succeeded
switches 0:5c4d7b2438d3 898 * ERR_MEM: memory error, try again later
switches 0:5c4d7b2438d3 899 * ERR_ARG: dns client not initialized or invalid hostname
switches 0:5c4d7b2438d3 900 * ERR_VAL: dns server response was invalid
switches 0:5c4d7b2438d3 901 */
switches 0:5c4d7b2438d3 902 #if LWIP_IPV4 && LWIP_IPV6
switches 0:5c4d7b2438d3 903 err_t
switches 0:5c4d7b2438d3 904 netconn_gethostbyname_addrtype(const char *name, ip_addr_t *addr, u8_t dns_addrtype)
switches 0:5c4d7b2438d3 905 #else
switches 0:5c4d7b2438d3 906 err_t
switches 0:5c4d7b2438d3 907 netconn_gethostbyname(const char *name, ip_addr_t *addr)
switches 0:5c4d7b2438d3 908 #endif
switches 0:5c4d7b2438d3 909 {
switches 0:5c4d7b2438d3 910 API_VAR_DECLARE(struct dns_api_msg, msg);
switches 0:5c4d7b2438d3 911 #if !LWIP_MPU_COMPATIBLE
switches 0:5c4d7b2438d3 912 sys_sem_t sem;
switches 0:5c4d7b2438d3 913 #endif /* LWIP_MPU_COMPATIBLE */
switches 0:5c4d7b2438d3 914 err_t err;
switches 0:5c4d7b2438d3 915
switches 0:5c4d7b2438d3 916 LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 917 LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
switches 0:5c4d7b2438d3 918 #if LWIP_MPU_COMPATIBLE
switches 0:5c4d7b2438d3 919 if (strlen(name) >= DNS_MAX_NAME_LENGTH) {
switches 0:5c4d7b2438d3 920 return ERR_ARG;
switches 0:5c4d7b2438d3 921 }
switches 0:5c4d7b2438d3 922 #endif
switches 0:5c4d7b2438d3 923
switches 0:5c4d7b2438d3 924 API_VAR_ALLOC(struct dns_api_msg, MEMP_DNS_API_MSG, msg, ERR_MEM);
switches 0:5c4d7b2438d3 925 #if LWIP_MPU_COMPATIBLE
switches 0:5c4d7b2438d3 926 strncpy(API_VAR_REF(msg).name, name, DNS_MAX_NAME_LENGTH-1);
switches 0:5c4d7b2438d3 927 API_VAR_REF(msg).name[DNS_MAX_NAME_LENGTH-1] = 0;
switches 0:5c4d7b2438d3 928 #else /* LWIP_MPU_COMPATIBLE */
switches 0:5c4d7b2438d3 929 msg.err = &err;
switches 0:5c4d7b2438d3 930 msg.sem = &sem;
switches 0:5c4d7b2438d3 931 API_VAR_REF(msg).addr = API_VAR_REF(addr);
switches 0:5c4d7b2438d3 932 API_VAR_REF(msg).name = name;
switches 0:5c4d7b2438d3 933 #endif /* LWIP_MPU_COMPATIBLE */
switches 0:5c4d7b2438d3 934 #if LWIP_IPV4 && LWIP_IPV6
switches 0:5c4d7b2438d3 935 API_VAR_REF(msg).dns_addrtype = dns_addrtype;
switches 0:5c4d7b2438d3 936 #endif /* LWIP_IPV4 && LWIP_IPV6 */
switches 0:5c4d7b2438d3 937 #if LWIP_NETCONN_SEM_PER_THREAD
switches 0:5c4d7b2438d3 938 API_VAR_REF(msg).sem = LWIP_NETCONN_THREAD_SEM_GET();
switches 0:5c4d7b2438d3 939 #else /* LWIP_NETCONN_SEM_PER_THREAD*/
switches 0:5c4d7b2438d3 940 err = sys_sem_new(API_EXPR_REF(API_VAR_REF(msg).sem), 0);
switches 0:5c4d7b2438d3 941 if (err != ERR_OK) {
switches 0:5c4d7b2438d3 942 API_VAR_FREE(MEMP_DNS_API_MSG, msg);
switches 0:5c4d7b2438d3 943 return err;
switches 0:5c4d7b2438d3 944 }
switches 0:5c4d7b2438d3 945 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
switches 0:5c4d7b2438d3 946
switches 0:5c4d7b2438d3 947 err = tcpip_callback(lwip_netconn_do_gethostbyname, &API_VAR_REF(msg));
switches 0:5c4d7b2438d3 948 if (err != ERR_OK) {
switches 0:5c4d7b2438d3 949 #if !LWIP_NETCONN_SEM_PER_THREAD
switches 0:5c4d7b2438d3 950 sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
switches 0:5c4d7b2438d3 951 #endif /* !LWIP_NETCONN_SEM_PER_THREAD */
switches 0:5c4d7b2438d3 952 API_VAR_FREE(MEMP_DNS_API_MSG, msg);
switches 0:5c4d7b2438d3 953 return err;
switches 0:5c4d7b2438d3 954 }
switches 0:5c4d7b2438d3 955 sys_sem_wait(API_EXPR_REF_SEM(API_VAR_REF(msg).sem));
switches 0:5c4d7b2438d3 956 #if !LWIP_NETCONN_SEM_PER_THREAD
switches 0:5c4d7b2438d3 957 sys_sem_free(API_EXPR_REF(API_VAR_REF(msg).sem));
switches 0:5c4d7b2438d3 958 #endif /* !LWIP_NETCONN_SEM_PER_THREAD */
switches 0:5c4d7b2438d3 959
switches 0:5c4d7b2438d3 960 #if LWIP_MPU_COMPATIBLE
switches 0:5c4d7b2438d3 961 *addr = msg->addr;
switches 0:5c4d7b2438d3 962 err = msg->err;
switches 0:5c4d7b2438d3 963 #endif /* LWIP_MPU_COMPATIBLE */
switches 0:5c4d7b2438d3 964
switches 0:5c4d7b2438d3 965 API_VAR_FREE(MEMP_DNS_API_MSG, msg);
switches 0:5c4d7b2438d3 966 return err;
switches 0:5c4d7b2438d3 967 }
switches 0:5c4d7b2438d3 968 #endif /* LWIP_DNS*/
switches 0:5c4d7b2438d3 969
switches 0:5c4d7b2438d3 970 #if LWIP_NETCONN_SEM_PER_THREAD
switches 0:5c4d7b2438d3 971 void
switches 0:5c4d7b2438d3 972 netconn_thread_init(void)
switches 0:5c4d7b2438d3 973 {
switches 0:5c4d7b2438d3 974 sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
switches 0:5c4d7b2438d3 975 if ((sem == NULL) || !sys_sem_valid(sem)) {
switches 0:5c4d7b2438d3 976 /* call alloc only once */
switches 0:5c4d7b2438d3 977 LWIP_NETCONN_THREAD_SEM_ALLOC();
switches 0:5c4d7b2438d3 978 LWIP_ASSERT("LWIP_NETCONN_THREAD_SEM_ALLOC() failed", sys_sem_valid(LWIP_NETCONN_THREAD_SEM_GET()));
switches 0:5c4d7b2438d3 979 }
switches 0:5c4d7b2438d3 980 }
switches 0:5c4d7b2438d3 981
switches 0:5c4d7b2438d3 982 void
switches 0:5c4d7b2438d3 983 netconn_thread_cleanup(void)
switches 0:5c4d7b2438d3 984 {
switches 0:5c4d7b2438d3 985 sys_sem_t *sem = LWIP_NETCONN_THREAD_SEM_GET();
switches 0:5c4d7b2438d3 986 if ((sem != NULL) && sys_sem_valid(sem)) {
switches 0:5c4d7b2438d3 987 /* call free only once */
switches 0:5c4d7b2438d3 988 LWIP_NETCONN_THREAD_SEM_FREE();
switches 0:5c4d7b2438d3 989 }
switches 0:5c4d7b2438d3 990 }
switches 0:5c4d7b2438d3 991 #endif /* LWIP_NETCONN_SEM_PER_THREAD */
switches 0:5c4d7b2438d3 992
switches 0:5c4d7b2438d3 993 #endif /* LWIP_NETCONN */