Official mbed lwIP library (version 1.4.0)

Dependents:   LwIPNetworking NetServicesMin EthernetInterface EthernetInterface_RSF ... more

Legacy Networking Libraries

This is an mbed 2 networking library. For mbed OS 5, lwip has been integrated with built-in networking interfaces. The networking libraries have been revised to better support additional network stacks and thread safety here.

This library is based on the code of lwIP v1.4.0

Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
All rights reserved. 

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
mbed_official
Date:
Mon Mar 14 16:15:36 2016 +0000
Revision:
20:08f08bfc3f3d
Parent:
0:51ac1d130fd4
Synchronized with git revision fec574a5ed6db26aca1b13992ff271bf527d4a0d

Full URL: https://github.com/mbedmicro/mbed/commit/fec574a5ed6db26aca1b13992ff271bf527d4a0d/

Increased allocated netbufs to handle DTLS handshakes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbed_official 0:51ac1d130fd4 1 /**
mbed_official 0:51ac1d130fd4 2 * @file
mbed_official 0:51ac1d130fd4 3 * Sockets BSD-Like API module
mbed_official 0:51ac1d130fd4 4 *
mbed_official 0:51ac1d130fd4 5 */
mbed_official 0:51ac1d130fd4 6
mbed_official 0:51ac1d130fd4 7 /*
mbed_official 0:51ac1d130fd4 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
mbed_official 0:51ac1d130fd4 9 * All rights reserved.
mbed_official 0:51ac1d130fd4 10 *
mbed_official 0:51ac1d130fd4 11 * Redistribution and use in source and binary forms, with or without modification,
mbed_official 0:51ac1d130fd4 12 * are permitted provided that the following conditions are met:
mbed_official 0:51ac1d130fd4 13 *
mbed_official 0:51ac1d130fd4 14 * 1. Redistributions of source code must retain the above copyright notice,
mbed_official 0:51ac1d130fd4 15 * this list of conditions and the following disclaimer.
mbed_official 0:51ac1d130fd4 16 * 2. Redistributions in binary form must reproduce the above copyright notice,
mbed_official 0:51ac1d130fd4 17 * this list of conditions and the following disclaimer in the documentation
mbed_official 0:51ac1d130fd4 18 * and/or other materials provided with the distribution.
mbed_official 0:51ac1d130fd4 19 * 3. The name of the author may not be used to endorse or promote products
mbed_official 0:51ac1d130fd4 20 * derived from this software without specific prior written permission.
mbed_official 0:51ac1d130fd4 21 *
mbed_official 0:51ac1d130fd4 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
mbed_official 0:51ac1d130fd4 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
mbed_official 0:51ac1d130fd4 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
mbed_official 0:51ac1d130fd4 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
mbed_official 0:51ac1d130fd4 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
mbed_official 0:51ac1d130fd4 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
mbed_official 0:51ac1d130fd4 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
mbed_official 0:51ac1d130fd4 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
mbed_official 0:51ac1d130fd4 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
mbed_official 0:51ac1d130fd4 31 * OF SUCH DAMAGE.
mbed_official 0:51ac1d130fd4 32 *
mbed_official 0:51ac1d130fd4 33 * This file is part of the lwIP TCP/IP stack.
mbed_official 0:51ac1d130fd4 34 *
mbed_official 0:51ac1d130fd4 35 * Author: Adam Dunkels <adam@sics.se>
mbed_official 0:51ac1d130fd4 36 *
mbed_official 0:51ac1d130fd4 37 * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
mbed_official 0:51ac1d130fd4 38 *
mbed_official 0:51ac1d130fd4 39 */
mbed_official 0:51ac1d130fd4 40
mbed_official 0:51ac1d130fd4 41 #include "lwip/opt.h"
mbed_official 0:51ac1d130fd4 42
mbed_official 0:51ac1d130fd4 43 #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
mbed_official 0:51ac1d130fd4 44
mbed_official 0:51ac1d130fd4 45 #include "lwip/sockets.h"
mbed_official 0:51ac1d130fd4 46 #include "lwip/api.h"
mbed_official 0:51ac1d130fd4 47 #include "lwip/sys.h"
mbed_official 0:51ac1d130fd4 48 #include "lwip/igmp.h"
mbed_official 0:51ac1d130fd4 49 #include "lwip/inet.h"
mbed_official 0:51ac1d130fd4 50 #include "lwip/tcp.h"
mbed_official 0:51ac1d130fd4 51 #include "lwip/raw.h"
mbed_official 0:51ac1d130fd4 52 #include "lwip/udp.h"
mbed_official 0:51ac1d130fd4 53 #include "lwip/tcpip.h"
mbed_official 0:51ac1d130fd4 54 #include "lwip/pbuf.h"
mbed_official 0:51ac1d130fd4 55 #if LWIP_CHECKSUM_ON_COPY
mbed_official 0:51ac1d130fd4 56 #include "lwip/inet_chksum.h"
mbed_official 0:51ac1d130fd4 57 #endif
mbed_official 0:51ac1d130fd4 58
mbed_official 0:51ac1d130fd4 59 #include <string.h>
mbed_official 0:51ac1d130fd4 60
mbed_official 0:51ac1d130fd4 61 #define NUM_SOCKETS MEMP_NUM_NETCONN
mbed_official 0:51ac1d130fd4 62
mbed_official 0:51ac1d130fd4 63 /** Contains all internal pointers and states used for a socket */
mbed_official 0:51ac1d130fd4 64 struct lwip_sock {
mbed_official 0:51ac1d130fd4 65 /** sockets currently are built on netconns, each socket has one netconn */
mbed_official 0:51ac1d130fd4 66 struct netconn *conn;
mbed_official 0:51ac1d130fd4 67 /** data that was left from the previous read */
mbed_official 0:51ac1d130fd4 68 void *lastdata;
mbed_official 0:51ac1d130fd4 69 /** offset in the data that was left from the previous read */
mbed_official 0:51ac1d130fd4 70 u16_t lastoffset;
mbed_official 0:51ac1d130fd4 71 /** number of times data was received, set by event_callback(),
mbed_official 0:51ac1d130fd4 72 tested by the receive and select functions */
mbed_official 0:51ac1d130fd4 73 s16_t rcvevent;
mbed_official 0:51ac1d130fd4 74 /** number of times data was ACKed (free send buffer), set by event_callback(),
mbed_official 0:51ac1d130fd4 75 tested by select */
mbed_official 0:51ac1d130fd4 76 u16_t sendevent;
mbed_official 0:51ac1d130fd4 77 /** error happened for this socket, set by event_callback(), tested by select */
mbed_official 0:51ac1d130fd4 78 u16_t errevent;
mbed_official 0:51ac1d130fd4 79 /** last error that occurred on this socket */
mbed_official 0:51ac1d130fd4 80 int err;
mbed_official 0:51ac1d130fd4 81 /** counter of how many threads are waiting for this socket using select */
mbed_official 0:51ac1d130fd4 82 int select_waiting;
mbed_official 0:51ac1d130fd4 83 };
mbed_official 0:51ac1d130fd4 84
mbed_official 0:51ac1d130fd4 85 /** Description for a task waiting in select */
mbed_official 0:51ac1d130fd4 86 struct lwip_select_cb {
mbed_official 0:51ac1d130fd4 87 /** Pointer to the next waiting task */
mbed_official 0:51ac1d130fd4 88 struct lwip_select_cb *next;
mbed_official 0:51ac1d130fd4 89 /** Pointer to the previous waiting task */
mbed_official 0:51ac1d130fd4 90 struct lwip_select_cb *prev;
mbed_official 0:51ac1d130fd4 91 /** readset passed to select */
mbed_official 0:51ac1d130fd4 92 fd_set *readset;
mbed_official 0:51ac1d130fd4 93 /** writeset passed to select */
mbed_official 0:51ac1d130fd4 94 fd_set *writeset;
mbed_official 0:51ac1d130fd4 95 /** unimplemented: exceptset passed to select */
mbed_official 0:51ac1d130fd4 96 fd_set *exceptset;
mbed_official 0:51ac1d130fd4 97 /** don't signal the same semaphore twice: set to 1 when signalled */
mbed_official 0:51ac1d130fd4 98 int sem_signalled;
mbed_official 0:51ac1d130fd4 99 /** semaphore to wake up a task waiting for select */
mbed_official 0:51ac1d130fd4 100 sys_sem_t sem;
mbed_official 0:51ac1d130fd4 101 };
mbed_official 0:51ac1d130fd4 102
mbed_official 0:51ac1d130fd4 103 /** This struct is used to pass data to the set/getsockopt_internal
mbed_official 0:51ac1d130fd4 104 * functions running in tcpip_thread context (only a void* is allowed) */
mbed_official 0:51ac1d130fd4 105 struct lwip_setgetsockopt_data {
mbed_official 0:51ac1d130fd4 106 /** socket struct for which to change options */
mbed_official 0:51ac1d130fd4 107 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 108 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 109 /** socket index for which to change options */
mbed_official 0:51ac1d130fd4 110 int s;
mbed_official 0:51ac1d130fd4 111 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 112 /** level of the option to process */
mbed_official 0:51ac1d130fd4 113 int level;
mbed_official 0:51ac1d130fd4 114 /** name of the option to process */
mbed_official 0:51ac1d130fd4 115 int optname;
mbed_official 0:51ac1d130fd4 116 /** set: value to set the option to
mbed_official 0:51ac1d130fd4 117 * get: value of the option is stored here */
mbed_official 0:51ac1d130fd4 118 void *optval;
mbed_official 0:51ac1d130fd4 119 /** size of *optval */
mbed_official 0:51ac1d130fd4 120 socklen_t *optlen;
mbed_official 0:51ac1d130fd4 121 /** if an error occures, it is temporarily stored here */
mbed_official 0:51ac1d130fd4 122 err_t err;
mbed_official 0:51ac1d130fd4 123 };
mbed_official 0:51ac1d130fd4 124
mbed_official 0:51ac1d130fd4 125 /** The global array of available sockets */
mbed_official 0:51ac1d130fd4 126 static struct lwip_sock sockets[NUM_SOCKETS];
mbed_official 0:51ac1d130fd4 127 /** The global list of tasks waiting for select */
mbed_official 0:51ac1d130fd4 128 static struct lwip_select_cb *select_cb_list;
mbed_official 0:51ac1d130fd4 129 /** This counter is increased from lwip_select when the list is chagned
mbed_official 0:51ac1d130fd4 130 and checked in event_callback to see if it has changed. */
mbed_official 0:51ac1d130fd4 131 static volatile int select_cb_ctr;
mbed_official 0:51ac1d130fd4 132
mbed_official 0:51ac1d130fd4 133 /** Table to quickly map an lwIP error (err_t) to a socket error
mbed_official 0:51ac1d130fd4 134 * by using -err as an index */
mbed_official 0:51ac1d130fd4 135 static const int err_to_errno_table[] = {
mbed_official 0:51ac1d130fd4 136 0, /* ERR_OK 0 No error, everything OK. */
mbed_official 0:51ac1d130fd4 137 ENOMEM, /* ERR_MEM -1 Out of memory error. */
mbed_official 0:51ac1d130fd4 138 ENOBUFS, /* ERR_BUF -2 Buffer error. */
mbed_official 0:51ac1d130fd4 139 EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
mbed_official 0:51ac1d130fd4 140 EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
mbed_official 0:51ac1d130fd4 141 EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
mbed_official 0:51ac1d130fd4 142 EINVAL, /* ERR_VAL -6 Illegal value. */
mbed_official 0:51ac1d130fd4 143 EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
mbed_official 0:51ac1d130fd4 144 EADDRINUSE, /* ERR_USE -8 Address in use. */
mbed_official 0:51ac1d130fd4 145 EALREADY, /* ERR_ISCONN -9 Already connected. */
mbed_official 0:51ac1d130fd4 146 ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
mbed_official 0:51ac1d130fd4 147 ECONNRESET, /* ERR_RST -11 Connection reset. */
mbed_official 0:51ac1d130fd4 148 ENOTCONN, /* ERR_CLSD -12 Connection closed. */
mbed_official 0:51ac1d130fd4 149 ENOTCONN, /* ERR_CONN -13 Not connected. */
mbed_official 0:51ac1d130fd4 150 EIO, /* ERR_ARG -14 Illegal argument. */
mbed_official 0:51ac1d130fd4 151 -1, /* ERR_IF -15 Low-level netif error */
mbed_official 0:51ac1d130fd4 152 };
mbed_official 0:51ac1d130fd4 153
mbed_official 0:51ac1d130fd4 154 #define ERR_TO_ERRNO_TABLE_SIZE \
mbed_official 0:51ac1d130fd4 155 (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
mbed_official 0:51ac1d130fd4 156
mbed_official 0:51ac1d130fd4 157 #define err_to_errno(err) \
mbed_official 0:51ac1d130fd4 158 ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
mbed_official 0:51ac1d130fd4 159 err_to_errno_table[-(err)] : EIO)
mbed_official 0:51ac1d130fd4 160
mbed_official 0:51ac1d130fd4 161 #ifdef ERRNO
mbed_official 0:51ac1d130fd4 162 #ifndef set_errno
mbed_official 0:51ac1d130fd4 163 #define set_errno(err) errno = (err)
mbed_official 0:51ac1d130fd4 164 #endif
mbed_official 0:51ac1d130fd4 165 #else /* ERRNO */
mbed_official 0:51ac1d130fd4 166 #define set_errno(err)
mbed_official 0:51ac1d130fd4 167 #endif /* ERRNO */
mbed_official 0:51ac1d130fd4 168
mbed_official 0:51ac1d130fd4 169 #define sock_set_errno(sk, e) do { \
mbed_official 0:51ac1d130fd4 170 sk->err = (e); \
mbed_official 0:51ac1d130fd4 171 set_errno(sk->err); \
mbed_official 0:51ac1d130fd4 172 } while (0)
mbed_official 0:51ac1d130fd4 173
mbed_official 0:51ac1d130fd4 174 /* Forward delcaration of some functions */
mbed_official 0:51ac1d130fd4 175 static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
mbed_official 0:51ac1d130fd4 176 static void lwip_getsockopt_internal(void *arg);
mbed_official 0:51ac1d130fd4 177 static void lwip_setsockopt_internal(void *arg);
mbed_official 0:51ac1d130fd4 178
mbed_official 0:51ac1d130fd4 179 /**
mbed_official 0:51ac1d130fd4 180 * Initialize this module. This function has to be called before any other
mbed_official 0:51ac1d130fd4 181 * functions in this module!
mbed_official 0:51ac1d130fd4 182 */
mbed_official 0:51ac1d130fd4 183 void
mbed_official 0:51ac1d130fd4 184 lwip_socket_init(void)
mbed_official 0:51ac1d130fd4 185 {
mbed_official 0:51ac1d130fd4 186 }
mbed_official 0:51ac1d130fd4 187
mbed_official 0:51ac1d130fd4 188 /**
mbed_official 0:51ac1d130fd4 189 * Map a externally used socket index to the internal socket representation.
mbed_official 0:51ac1d130fd4 190 *
mbed_official 0:51ac1d130fd4 191 * @param s externally used socket index
mbed_official 0:51ac1d130fd4 192 * @return struct lwip_sock for the socket or NULL if not found
mbed_official 0:51ac1d130fd4 193 */
mbed_official 0:51ac1d130fd4 194 static struct lwip_sock *
mbed_official 0:51ac1d130fd4 195 get_socket(int s)
mbed_official 0:51ac1d130fd4 196 {
mbed_official 0:51ac1d130fd4 197 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 198
mbed_official 0:51ac1d130fd4 199 if ((s < 0) || (s >= NUM_SOCKETS)) {
mbed_official 0:51ac1d130fd4 200 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
mbed_official 0:51ac1d130fd4 201 set_errno(EBADF);
mbed_official 0:51ac1d130fd4 202 return NULL;
mbed_official 0:51ac1d130fd4 203 }
mbed_official 0:51ac1d130fd4 204
mbed_official 0:51ac1d130fd4 205 sock = &sockets[s];
mbed_official 0:51ac1d130fd4 206
mbed_official 0:51ac1d130fd4 207 if (!sock->conn) {
mbed_official 0:51ac1d130fd4 208 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
mbed_official 0:51ac1d130fd4 209 set_errno(EBADF);
mbed_official 0:51ac1d130fd4 210 return NULL;
mbed_official 0:51ac1d130fd4 211 }
mbed_official 0:51ac1d130fd4 212
mbed_official 0:51ac1d130fd4 213 return sock;
mbed_official 0:51ac1d130fd4 214 }
mbed_official 0:51ac1d130fd4 215
mbed_official 0:51ac1d130fd4 216 /**
mbed_official 0:51ac1d130fd4 217 * Same as get_socket but doesn't set errno
mbed_official 0:51ac1d130fd4 218 *
mbed_official 0:51ac1d130fd4 219 * @param s externally used socket index
mbed_official 0:51ac1d130fd4 220 * @return struct lwip_sock for the socket or NULL if not found
mbed_official 0:51ac1d130fd4 221 */
mbed_official 0:51ac1d130fd4 222 static struct lwip_sock *
mbed_official 0:51ac1d130fd4 223 tryget_socket(int s)
mbed_official 0:51ac1d130fd4 224 {
mbed_official 0:51ac1d130fd4 225 if ((s < 0) || (s >= NUM_SOCKETS)) {
mbed_official 0:51ac1d130fd4 226 return NULL;
mbed_official 0:51ac1d130fd4 227 }
mbed_official 0:51ac1d130fd4 228 if (!sockets[s].conn) {
mbed_official 0:51ac1d130fd4 229 return NULL;
mbed_official 0:51ac1d130fd4 230 }
mbed_official 0:51ac1d130fd4 231 return &sockets[s];
mbed_official 0:51ac1d130fd4 232 }
mbed_official 0:51ac1d130fd4 233
mbed_official 0:51ac1d130fd4 234 /**
mbed_official 0:51ac1d130fd4 235 * Allocate a new socket for a given netconn.
mbed_official 0:51ac1d130fd4 236 *
mbed_official 0:51ac1d130fd4 237 * @param newconn the netconn for which to allocate a socket
mbed_official 0:51ac1d130fd4 238 * @param accepted 1 if socket has been created by accept(),
mbed_official 0:51ac1d130fd4 239 * 0 if socket has been created by socket()
mbed_official 0:51ac1d130fd4 240 * @return the index of the new socket; -1 on error
mbed_official 0:51ac1d130fd4 241 */
mbed_official 0:51ac1d130fd4 242 static int
mbed_official 0:51ac1d130fd4 243 alloc_socket(struct netconn *newconn, int accepted)
mbed_official 0:51ac1d130fd4 244 {
mbed_official 0:51ac1d130fd4 245 int i;
mbed_official 0:51ac1d130fd4 246 SYS_ARCH_DECL_PROTECT(lev);
mbed_official 0:51ac1d130fd4 247
mbed_official 0:51ac1d130fd4 248 /* allocate a new socket identifier */
mbed_official 0:51ac1d130fd4 249 for (i = 0; i < NUM_SOCKETS; ++i) {
mbed_official 0:51ac1d130fd4 250 /* Protect socket array */
mbed_official 0:51ac1d130fd4 251 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 252 if (!sockets[i].conn) {
mbed_official 0:51ac1d130fd4 253 sockets[i].conn = newconn;
mbed_official 0:51ac1d130fd4 254 /* The socket is not yet known to anyone, so no need to protect
mbed_official 0:51ac1d130fd4 255 after having marked it as used. */
mbed_official 0:51ac1d130fd4 256 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 257 sockets[i].lastdata = NULL;
mbed_official 0:51ac1d130fd4 258 sockets[i].lastoffset = 0;
mbed_official 0:51ac1d130fd4 259 sockets[i].rcvevent = 0;
mbed_official 0:51ac1d130fd4 260 /* TCP sendbuf is empty, but the socket is not yet writable until connected
mbed_official 0:51ac1d130fd4 261 * (unless it has been created by accept()). */
mbed_official 0:51ac1d130fd4 262 sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
mbed_official 0:51ac1d130fd4 263 sockets[i].errevent = 0;
mbed_official 0:51ac1d130fd4 264 sockets[i].err = 0;
mbed_official 0:51ac1d130fd4 265 sockets[i].select_waiting = 0;
mbed_official 0:51ac1d130fd4 266 return i;
mbed_official 0:51ac1d130fd4 267 }
mbed_official 0:51ac1d130fd4 268 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 269 }
mbed_official 0:51ac1d130fd4 270 return -1;
mbed_official 0:51ac1d130fd4 271 }
mbed_official 0:51ac1d130fd4 272
mbed_official 0:51ac1d130fd4 273 /** Free a socket. The socket's netconn must have been
mbed_official 0:51ac1d130fd4 274 * delete before!
mbed_official 0:51ac1d130fd4 275 *
mbed_official 0:51ac1d130fd4 276 * @param sock the socket to free
mbed_official 0:51ac1d130fd4 277 * @param is_tcp != 0 for TCP sockets, used to free lastdata
mbed_official 0:51ac1d130fd4 278 */
mbed_official 0:51ac1d130fd4 279 static void
mbed_official 0:51ac1d130fd4 280 free_socket(struct lwip_sock *sock, int is_tcp)
mbed_official 0:51ac1d130fd4 281 {
mbed_official 0:51ac1d130fd4 282 void *lastdata;
mbed_official 0:51ac1d130fd4 283 SYS_ARCH_DECL_PROTECT(lev);
mbed_official 0:51ac1d130fd4 284
mbed_official 0:51ac1d130fd4 285 lastdata = sock->lastdata;
mbed_official 0:51ac1d130fd4 286 sock->lastdata = NULL;
mbed_official 0:51ac1d130fd4 287 sock->lastoffset = 0;
mbed_official 0:51ac1d130fd4 288 sock->err = 0;
mbed_official 0:51ac1d130fd4 289
mbed_official 0:51ac1d130fd4 290 /* Protect socket array */
mbed_official 0:51ac1d130fd4 291 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 292 sock->conn = NULL;
mbed_official 0:51ac1d130fd4 293 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 294 /* don't use 'sock' after this line, as another task might have allocated it */
mbed_official 0:51ac1d130fd4 295
mbed_official 0:51ac1d130fd4 296 if (lastdata != NULL) {
mbed_official 0:51ac1d130fd4 297 if (is_tcp) {
mbed_official 0:51ac1d130fd4 298 pbuf_free((struct pbuf *)lastdata);
mbed_official 0:51ac1d130fd4 299 } else {
mbed_official 0:51ac1d130fd4 300 netbuf_delete((struct netbuf *)lastdata);
mbed_official 0:51ac1d130fd4 301 }
mbed_official 0:51ac1d130fd4 302 }
mbed_official 0:51ac1d130fd4 303 }
mbed_official 0:51ac1d130fd4 304
mbed_official 0:51ac1d130fd4 305 /* Below this, the well-known socket functions are implemented.
mbed_official 0:51ac1d130fd4 306 * Use google.com or opengroup.org to get a good description :-)
mbed_official 0:51ac1d130fd4 307 *
mbed_official 0:51ac1d130fd4 308 * Exceptions are documented!
mbed_official 0:51ac1d130fd4 309 */
mbed_official 0:51ac1d130fd4 310
mbed_official 0:51ac1d130fd4 311 int
mbed_official 0:51ac1d130fd4 312 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
mbed_official 0:51ac1d130fd4 313 {
mbed_official 0:51ac1d130fd4 314 struct lwip_sock *sock, *nsock;
mbed_official 0:51ac1d130fd4 315 struct netconn *newconn;
mbed_official 0:51ac1d130fd4 316 ip_addr_t naddr;
mbed_official 0:51ac1d130fd4 317 u16_t port;
mbed_official 0:51ac1d130fd4 318 int newsock;
mbed_official 0:51ac1d130fd4 319 struct sockaddr_in sin;
mbed_official 0:51ac1d130fd4 320 err_t err;
mbed_official 0:51ac1d130fd4 321 SYS_ARCH_DECL_PROTECT(lev);
mbed_official 0:51ac1d130fd4 322
mbed_official 0:51ac1d130fd4 323 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
mbed_official 0:51ac1d130fd4 324 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 325 if (!sock) {
mbed_official 0:51ac1d130fd4 326 return -1;
mbed_official 0:51ac1d130fd4 327 }
mbed_official 0:51ac1d130fd4 328
mbed_official 0:51ac1d130fd4 329 if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
mbed_official 0:51ac1d130fd4 330 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
mbed_official 0:51ac1d130fd4 331 sock_set_errno(sock, EWOULDBLOCK);
mbed_official 0:51ac1d130fd4 332 return -1;
mbed_official 0:51ac1d130fd4 333 }
mbed_official 0:51ac1d130fd4 334
mbed_official 0:51ac1d130fd4 335 /* wait for a new connection */
mbed_official 0:51ac1d130fd4 336 err = netconn_accept(sock->conn, &newconn);
mbed_official 0:51ac1d130fd4 337 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 338 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
mbed_official 0:51ac1d130fd4 339 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 340 return -1;
mbed_official 0:51ac1d130fd4 341 }
mbed_official 0:51ac1d130fd4 342 LWIP_ASSERT("newconn != NULL", newconn != NULL);
mbed_official 0:51ac1d130fd4 343 /* Prevent automatic window updates, we do this on our own! */
mbed_official 0:51ac1d130fd4 344 netconn_set_noautorecved(newconn, 1);
mbed_official 0:51ac1d130fd4 345
mbed_official 0:51ac1d130fd4 346 /* get the IP address and port of the remote host */
mbed_official 0:51ac1d130fd4 347 err = netconn_peer(newconn, &naddr, &port);
mbed_official 0:51ac1d130fd4 348 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 349 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
mbed_official 0:51ac1d130fd4 350 netconn_delete(newconn);
mbed_official 0:51ac1d130fd4 351 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 352 return -1;
mbed_official 0:51ac1d130fd4 353 }
mbed_official 0:51ac1d130fd4 354
mbed_official 0:51ac1d130fd4 355 /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
mbed_official 0:51ac1d130fd4 356 * not be NULL if addr is valid.
mbed_official 0:51ac1d130fd4 357 */
mbed_official 0:51ac1d130fd4 358 if (NULL != addr) {
mbed_official 0:51ac1d130fd4 359 LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
mbed_official 0:51ac1d130fd4 360 memset(&sin, 0, sizeof(sin));
mbed_official 0:51ac1d130fd4 361 sin.sin_len = sizeof(sin);
mbed_official 0:51ac1d130fd4 362 sin.sin_family = AF_INET;
mbed_official 0:51ac1d130fd4 363 sin.sin_port = htons(port);
mbed_official 0:51ac1d130fd4 364 inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
mbed_official 0:51ac1d130fd4 365
mbed_official 0:51ac1d130fd4 366 if (*addrlen > sizeof(sin))
mbed_official 0:51ac1d130fd4 367 *addrlen = sizeof(sin);
mbed_official 0:51ac1d130fd4 368
mbed_official 0:51ac1d130fd4 369 MEMCPY(addr, &sin, *addrlen);
mbed_official 0:51ac1d130fd4 370 }
mbed_official 0:51ac1d130fd4 371
mbed_official 0:51ac1d130fd4 372 newsock = alloc_socket(newconn, 1);
mbed_official 0:51ac1d130fd4 373 if (newsock == -1) {
mbed_official 0:51ac1d130fd4 374 netconn_delete(newconn);
mbed_official 0:51ac1d130fd4 375 sock_set_errno(sock, ENFILE);
mbed_official 0:51ac1d130fd4 376 return -1;
mbed_official 0:51ac1d130fd4 377 }
mbed_official 0:51ac1d130fd4 378 LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
mbed_official 0:51ac1d130fd4 379 LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
mbed_official 0:51ac1d130fd4 380 nsock = &sockets[newsock];
mbed_official 0:51ac1d130fd4 381
mbed_official 0:51ac1d130fd4 382 /* See event_callback: If data comes in right away after an accept, even
mbed_official 0:51ac1d130fd4 383 * though the server task might not have created a new socket yet.
mbed_official 0:51ac1d130fd4 384 * In that case, newconn->socket is counted down (newconn->socket--),
mbed_official 0:51ac1d130fd4 385 * so nsock->rcvevent is >= 1 here!
mbed_official 0:51ac1d130fd4 386 */
mbed_official 0:51ac1d130fd4 387 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 388 nsock->rcvevent += (s16_t)(-1 - newconn->socket);
mbed_official 0:51ac1d130fd4 389 newconn->socket = newsock;
mbed_official 0:51ac1d130fd4 390 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 391
mbed_official 0:51ac1d130fd4 392 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
mbed_official 0:51ac1d130fd4 393 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
mbed_official 0:51ac1d130fd4 394 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
mbed_official 0:51ac1d130fd4 395
mbed_official 0:51ac1d130fd4 396 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 397 return newsock;
mbed_official 0:51ac1d130fd4 398 }
mbed_official 0:51ac1d130fd4 399
mbed_official 0:51ac1d130fd4 400 int
mbed_official 0:51ac1d130fd4 401 lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
mbed_official 0:51ac1d130fd4 402 {
mbed_official 0:51ac1d130fd4 403 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 404 ip_addr_t local_addr;
mbed_official 0:51ac1d130fd4 405 u16_t local_port;
mbed_official 0:51ac1d130fd4 406 err_t err;
mbed_official 0:51ac1d130fd4 407 const struct sockaddr_in *name_in;
mbed_official 0:51ac1d130fd4 408
mbed_official 0:51ac1d130fd4 409 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 410 if (!sock) {
mbed_official 0:51ac1d130fd4 411 return -1;
mbed_official 0:51ac1d130fd4 412 }
mbed_official 0:51ac1d130fd4 413
mbed_official 0:51ac1d130fd4 414 /* check size, familiy and alignment of 'name' */
mbed_official 0:51ac1d130fd4 415 LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
mbed_official 0:51ac1d130fd4 416 ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
mbed_official 0:51ac1d130fd4 417 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
mbed_official 0:51ac1d130fd4 418 name_in = (const struct sockaddr_in *)(void*)name;
mbed_official 0:51ac1d130fd4 419
mbed_official 0:51ac1d130fd4 420 inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr);
mbed_official 0:51ac1d130fd4 421 local_port = name_in->sin_port;
mbed_official 0:51ac1d130fd4 422
mbed_official 0:51ac1d130fd4 423 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
mbed_official 0:51ac1d130fd4 424 ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
mbed_official 0:51ac1d130fd4 425 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
mbed_official 0:51ac1d130fd4 426
mbed_official 0:51ac1d130fd4 427 err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
mbed_official 0:51ac1d130fd4 428
mbed_official 0:51ac1d130fd4 429 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 430 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
mbed_official 0:51ac1d130fd4 431 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 432 return -1;
mbed_official 0:51ac1d130fd4 433 }
mbed_official 0:51ac1d130fd4 434
mbed_official 0:51ac1d130fd4 435 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
mbed_official 0:51ac1d130fd4 436 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 437 return 0;
mbed_official 0:51ac1d130fd4 438 }
mbed_official 0:51ac1d130fd4 439
mbed_official 0:51ac1d130fd4 440 int
mbed_official 0:51ac1d130fd4 441 lwip_close(int s)
mbed_official 0:51ac1d130fd4 442 {
mbed_official 0:51ac1d130fd4 443 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 444 int is_tcp = 0;
mbed_official 0:51ac1d130fd4 445
mbed_official 0:51ac1d130fd4 446 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
mbed_official 0:51ac1d130fd4 447
mbed_official 0:51ac1d130fd4 448 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 449 if (!sock) {
mbed_official 0:51ac1d130fd4 450 return -1;
mbed_official 0:51ac1d130fd4 451 }
mbed_official 0:51ac1d130fd4 452
mbed_official 0:51ac1d130fd4 453 if(sock->conn != NULL) {
mbed_official 0:51ac1d130fd4 454 is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
mbed_official 0:51ac1d130fd4 455 } else {
mbed_official 0:51ac1d130fd4 456 LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
mbed_official 0:51ac1d130fd4 457 }
mbed_official 0:51ac1d130fd4 458
mbed_official 0:51ac1d130fd4 459 netconn_delete(sock->conn);
mbed_official 0:51ac1d130fd4 460
mbed_official 0:51ac1d130fd4 461 free_socket(sock, is_tcp);
mbed_official 0:51ac1d130fd4 462 set_errno(0);
mbed_official 0:51ac1d130fd4 463 return 0;
mbed_official 0:51ac1d130fd4 464 }
mbed_official 0:51ac1d130fd4 465
mbed_official 0:51ac1d130fd4 466 int
mbed_official 0:51ac1d130fd4 467 lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
mbed_official 0:51ac1d130fd4 468 {
mbed_official 0:51ac1d130fd4 469 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 470 err_t err;
mbed_official 0:51ac1d130fd4 471 const struct sockaddr_in *name_in;
mbed_official 0:51ac1d130fd4 472
mbed_official 0:51ac1d130fd4 473 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 474 if (!sock) {
mbed_official 0:51ac1d130fd4 475 return -1;
mbed_official 0:51ac1d130fd4 476 }
mbed_official 0:51ac1d130fd4 477
mbed_official 0:51ac1d130fd4 478 /* check size, familiy and alignment of 'name' */
mbed_official 0:51ac1d130fd4 479 LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
mbed_official 0:51ac1d130fd4 480 ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
mbed_official 0:51ac1d130fd4 481 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
mbed_official 0:51ac1d130fd4 482 name_in = (const struct sockaddr_in *)(void*)name;
mbed_official 0:51ac1d130fd4 483
mbed_official 0:51ac1d130fd4 484 if (name_in->sin_family == AF_UNSPEC) {
mbed_official 0:51ac1d130fd4 485 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
mbed_official 0:51ac1d130fd4 486 err = netconn_disconnect(sock->conn);
mbed_official 0:51ac1d130fd4 487 } else {
mbed_official 0:51ac1d130fd4 488 ip_addr_t remote_addr;
mbed_official 0:51ac1d130fd4 489 u16_t remote_port;
mbed_official 0:51ac1d130fd4 490
mbed_official 0:51ac1d130fd4 491 inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr);
mbed_official 0:51ac1d130fd4 492 remote_port = name_in->sin_port;
mbed_official 0:51ac1d130fd4 493
mbed_official 0:51ac1d130fd4 494 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
mbed_official 0:51ac1d130fd4 495 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
mbed_official 0:51ac1d130fd4 496 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
mbed_official 0:51ac1d130fd4 497
mbed_official 0:51ac1d130fd4 498 err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
mbed_official 0:51ac1d130fd4 499 }
mbed_official 0:51ac1d130fd4 500
mbed_official 0:51ac1d130fd4 501 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 502 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
mbed_official 0:51ac1d130fd4 503 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 504 return -1;
mbed_official 0:51ac1d130fd4 505 }
mbed_official 0:51ac1d130fd4 506
mbed_official 0:51ac1d130fd4 507 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
mbed_official 0:51ac1d130fd4 508 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 509 return 0;
mbed_official 0:51ac1d130fd4 510 }
mbed_official 0:51ac1d130fd4 511
mbed_official 0:51ac1d130fd4 512 /**
mbed_official 0:51ac1d130fd4 513 * Set a socket into listen mode.
mbed_official 0:51ac1d130fd4 514 * The socket may not have been used for another connection previously.
mbed_official 0:51ac1d130fd4 515 *
mbed_official 0:51ac1d130fd4 516 * @param s the socket to set to listening mode
mbed_official 0:51ac1d130fd4 517 * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1)
mbed_official 0:51ac1d130fd4 518 * @return 0 on success, non-zero on failure
mbed_official 0:51ac1d130fd4 519 */
mbed_official 0:51ac1d130fd4 520 int
mbed_official 0:51ac1d130fd4 521 lwip_listen(int s, int backlog)
mbed_official 0:51ac1d130fd4 522 {
mbed_official 0:51ac1d130fd4 523 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 524 err_t err;
mbed_official 0:51ac1d130fd4 525
mbed_official 0:51ac1d130fd4 526 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
mbed_official 0:51ac1d130fd4 527
mbed_official 0:51ac1d130fd4 528 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 529 if (!sock) {
mbed_official 0:51ac1d130fd4 530 return -1;
mbed_official 0:51ac1d130fd4 531 }
mbed_official 0:51ac1d130fd4 532
mbed_official 0:51ac1d130fd4 533 /* limit the "backlog" parameter to fit in an u8_t */
mbed_official 0:51ac1d130fd4 534 backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
mbed_official 0:51ac1d130fd4 535
mbed_official 0:51ac1d130fd4 536 err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
mbed_official 0:51ac1d130fd4 537
mbed_official 0:51ac1d130fd4 538 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 539 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
mbed_official 0:51ac1d130fd4 540 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 541 return -1;
mbed_official 0:51ac1d130fd4 542 }
mbed_official 0:51ac1d130fd4 543
mbed_official 0:51ac1d130fd4 544 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 545 return 0;
mbed_official 0:51ac1d130fd4 546 }
mbed_official 0:51ac1d130fd4 547
mbed_official 0:51ac1d130fd4 548 int
mbed_official 0:51ac1d130fd4 549 lwip_recvfrom(int s, void *mem, size_t len, int flags,
mbed_official 0:51ac1d130fd4 550 struct sockaddr *from, socklen_t *fromlen)
mbed_official 0:51ac1d130fd4 551 {
mbed_official 0:51ac1d130fd4 552 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 553 void *buf = NULL;
mbed_official 0:51ac1d130fd4 554 struct pbuf *p;
mbed_official 0:51ac1d130fd4 555 u16_t buflen, copylen;
mbed_official 0:51ac1d130fd4 556 int off = 0;
mbed_official 0:51ac1d130fd4 557 ip_addr_t *addr;
mbed_official 0:51ac1d130fd4 558 u16_t port;
mbed_official 0:51ac1d130fd4 559 u8_t done = 0;
mbed_official 0:51ac1d130fd4 560 err_t err;
mbed_official 0:51ac1d130fd4 561
mbed_official 0:51ac1d130fd4 562 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
mbed_official 0:51ac1d130fd4 563 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 564 if (!sock) {
mbed_official 0:51ac1d130fd4 565 return -1;
mbed_official 0:51ac1d130fd4 566 }
mbed_official 0:51ac1d130fd4 567
mbed_official 0:51ac1d130fd4 568 do {
mbed_official 0:51ac1d130fd4 569 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
mbed_official 0:51ac1d130fd4 570 /* Check if there is data left from the last recv operation. */
mbed_official 0:51ac1d130fd4 571 if (sock->lastdata) {
mbed_official 0:51ac1d130fd4 572 buf = sock->lastdata;
mbed_official 0:51ac1d130fd4 573 } else {
mbed_official 0:51ac1d130fd4 574 /* If this is non-blocking call, then check first */
mbed_official 0:51ac1d130fd4 575 if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
mbed_official 0:51ac1d130fd4 576 (sock->rcvevent <= 0)) {
mbed_official 0:51ac1d130fd4 577 if (off > 0) {
mbed_official 0:51ac1d130fd4 578 /* update receive window */
mbed_official 0:51ac1d130fd4 579 netconn_recved(sock->conn, (u32_t)off);
mbed_official 0:51ac1d130fd4 580 /* already received data, return that */
mbed_official 0:51ac1d130fd4 581 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 582 return off;
mbed_official 0:51ac1d130fd4 583 }
mbed_official 0:51ac1d130fd4 584 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
mbed_official 0:51ac1d130fd4 585 sock_set_errno(sock, EWOULDBLOCK);
mbed_official 0:51ac1d130fd4 586 return -1;
mbed_official 0:51ac1d130fd4 587 }
mbed_official 0:51ac1d130fd4 588
mbed_official 0:51ac1d130fd4 589 /* No data was left from the previous operation, so we try to get
mbed_official 0:51ac1d130fd4 590 some from the network. */
mbed_official 0:51ac1d130fd4 591 if (netconn_type(sock->conn) == NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 592 err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
mbed_official 0:51ac1d130fd4 593 } else {
mbed_official 0:51ac1d130fd4 594 err = netconn_recv(sock->conn, (struct netbuf **)&buf);
mbed_official 0:51ac1d130fd4 595 }
mbed_official 0:51ac1d130fd4 596 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
mbed_official 0:51ac1d130fd4 597 err, buf));
mbed_official 0:51ac1d130fd4 598
mbed_official 0:51ac1d130fd4 599 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 600 if (off > 0) {
mbed_official 0:51ac1d130fd4 601 /* update receive window */
mbed_official 0:51ac1d130fd4 602 netconn_recved(sock->conn, (u32_t)off);
mbed_official 0:51ac1d130fd4 603 /* already received data, return that */
mbed_official 0:51ac1d130fd4 604 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 605 return off;
mbed_official 0:51ac1d130fd4 606 }
mbed_official 0:51ac1d130fd4 607 /* We should really do some error checking here. */
mbed_official 0:51ac1d130fd4 608 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
mbed_official 0:51ac1d130fd4 609 s, lwip_strerr(err)));
mbed_official 0:51ac1d130fd4 610 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 611 if (err == ERR_CLSD) {
mbed_official 0:51ac1d130fd4 612 return 0;
mbed_official 0:51ac1d130fd4 613 } else {
mbed_official 0:51ac1d130fd4 614 return -1;
mbed_official 0:51ac1d130fd4 615 }
mbed_official 0:51ac1d130fd4 616 }
mbed_official 0:51ac1d130fd4 617 LWIP_ASSERT("buf != NULL", buf != NULL);
mbed_official 0:51ac1d130fd4 618 sock->lastdata = buf;
mbed_official 0:51ac1d130fd4 619 }
mbed_official 0:51ac1d130fd4 620
mbed_official 0:51ac1d130fd4 621 if (netconn_type(sock->conn) == NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 622 p = (struct pbuf *)buf;
mbed_official 0:51ac1d130fd4 623 } else {
mbed_official 0:51ac1d130fd4 624 p = ((struct netbuf *)buf)->p;
mbed_official 0:51ac1d130fd4 625 }
mbed_official 0:51ac1d130fd4 626 buflen = p->tot_len;
mbed_official 0:51ac1d130fd4 627 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
mbed_official 0:51ac1d130fd4 628 buflen, len, off, sock->lastoffset));
mbed_official 0:51ac1d130fd4 629
mbed_official 0:51ac1d130fd4 630 buflen -= sock->lastoffset;
mbed_official 0:51ac1d130fd4 631
mbed_official 0:51ac1d130fd4 632 if (len > buflen) {
mbed_official 0:51ac1d130fd4 633 copylen = buflen;
mbed_official 0:51ac1d130fd4 634 } else {
mbed_official 0:51ac1d130fd4 635 copylen = (u16_t)len;
mbed_official 0:51ac1d130fd4 636 }
mbed_official 0:51ac1d130fd4 637
mbed_official 0:51ac1d130fd4 638 /* copy the contents of the received buffer into
mbed_official 0:51ac1d130fd4 639 the supplied memory pointer mem */
mbed_official 0:51ac1d130fd4 640 pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
mbed_official 0:51ac1d130fd4 641
mbed_official 0:51ac1d130fd4 642 off += copylen;
mbed_official 0:51ac1d130fd4 643
mbed_official 0:51ac1d130fd4 644 if (netconn_type(sock->conn) == NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 645 LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
mbed_official 0:51ac1d130fd4 646 len -= copylen;
mbed_official 0:51ac1d130fd4 647 if ( (len <= 0) ||
mbed_official 0:51ac1d130fd4 648 (p->flags & PBUF_FLAG_PUSH) ||
mbed_official 0:51ac1d130fd4 649 (sock->rcvevent <= 0) ||
mbed_official 0:51ac1d130fd4 650 ((flags & MSG_PEEK)!=0)) {
mbed_official 0:51ac1d130fd4 651 done = 1;
mbed_official 0:51ac1d130fd4 652 }
mbed_official 0:51ac1d130fd4 653 } else {
mbed_official 0:51ac1d130fd4 654 done = 1;
mbed_official 0:51ac1d130fd4 655 }
mbed_official 0:51ac1d130fd4 656
mbed_official 0:51ac1d130fd4 657 /* Check to see from where the data was.*/
mbed_official 0:51ac1d130fd4 658 if (done) {
mbed_official 0:51ac1d130fd4 659 ip_addr_t fromaddr;
mbed_official 0:51ac1d130fd4 660 if (from && fromlen) {
mbed_official 0:51ac1d130fd4 661 struct sockaddr_in sin;
mbed_official 0:51ac1d130fd4 662
mbed_official 0:51ac1d130fd4 663 if (netconn_type(sock->conn) == NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 664 addr = &fromaddr;
mbed_official 0:51ac1d130fd4 665 netconn_getaddr(sock->conn, addr, &port, 0);
mbed_official 0:51ac1d130fd4 666 } else {
mbed_official 0:51ac1d130fd4 667 addr = netbuf_fromaddr((struct netbuf *)buf);
mbed_official 0:51ac1d130fd4 668 port = netbuf_fromport((struct netbuf *)buf);
mbed_official 0:51ac1d130fd4 669 }
mbed_official 0:51ac1d130fd4 670
mbed_official 0:51ac1d130fd4 671 memset(&sin, 0, sizeof(sin));
mbed_official 0:51ac1d130fd4 672 sin.sin_len = sizeof(sin);
mbed_official 0:51ac1d130fd4 673 sin.sin_family = AF_INET;
mbed_official 0:51ac1d130fd4 674 sin.sin_port = htons(port);
mbed_official 0:51ac1d130fd4 675 inet_addr_from_ipaddr(&sin.sin_addr, addr);
mbed_official 0:51ac1d130fd4 676
mbed_official 0:51ac1d130fd4 677 if (*fromlen > sizeof(sin)) {
mbed_official 0:51ac1d130fd4 678 *fromlen = sizeof(sin);
mbed_official 0:51ac1d130fd4 679 }
mbed_official 0:51ac1d130fd4 680
mbed_official 0:51ac1d130fd4 681 MEMCPY(from, &sin, *fromlen);
mbed_official 0:51ac1d130fd4 682
mbed_official 0:51ac1d130fd4 683 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
mbed_official 0:51ac1d130fd4 684 ip_addr_debug_print(SOCKETS_DEBUG, addr);
mbed_official 0:51ac1d130fd4 685 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
mbed_official 0:51ac1d130fd4 686 } else {
mbed_official 0:51ac1d130fd4 687 #if SOCKETS_DEBUG
mbed_official 0:51ac1d130fd4 688 if (netconn_type(sock->conn) == NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 689 addr = &fromaddr;
mbed_official 0:51ac1d130fd4 690 netconn_getaddr(sock->conn, addr, &port, 0);
mbed_official 0:51ac1d130fd4 691 } else {
mbed_official 0:51ac1d130fd4 692 addr = netbuf_fromaddr((struct netbuf *)buf);
mbed_official 0:51ac1d130fd4 693 port = netbuf_fromport((struct netbuf *)buf);
mbed_official 0:51ac1d130fd4 694 }
mbed_official 0:51ac1d130fd4 695
mbed_official 0:51ac1d130fd4 696 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
mbed_official 0:51ac1d130fd4 697 ip_addr_debug_print(SOCKETS_DEBUG, addr);
mbed_official 0:51ac1d130fd4 698 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
mbed_official 0:51ac1d130fd4 699 #endif /* SOCKETS_DEBUG */
mbed_official 0:51ac1d130fd4 700 }
mbed_official 0:51ac1d130fd4 701 }
mbed_official 0:51ac1d130fd4 702
mbed_official 0:51ac1d130fd4 703 /* If we don't peek the incoming message... */
mbed_official 0:51ac1d130fd4 704 if ((flags & MSG_PEEK) == 0) {
mbed_official 0:51ac1d130fd4 705 /* If this is a TCP socket, check if there is data left in the
mbed_official 0:51ac1d130fd4 706 buffer. If so, it should be saved in the sock structure for next
mbed_official 0:51ac1d130fd4 707 time around. */
mbed_official 0:51ac1d130fd4 708 if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
mbed_official 0:51ac1d130fd4 709 sock->lastdata = buf;
mbed_official 0:51ac1d130fd4 710 sock->lastoffset += copylen;
mbed_official 0:51ac1d130fd4 711 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
mbed_official 0:51ac1d130fd4 712 } else {
mbed_official 0:51ac1d130fd4 713 sock->lastdata = NULL;
mbed_official 0:51ac1d130fd4 714 sock->lastoffset = 0;
mbed_official 0:51ac1d130fd4 715 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
mbed_official 0:51ac1d130fd4 716 if (netconn_type(sock->conn) == NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 717 pbuf_free((struct pbuf *)buf);
mbed_official 0:51ac1d130fd4 718 } else {
mbed_official 0:51ac1d130fd4 719 netbuf_delete((struct netbuf *)buf);
mbed_official 0:51ac1d130fd4 720 }
mbed_official 0:51ac1d130fd4 721 }
mbed_official 0:51ac1d130fd4 722 }
mbed_official 0:51ac1d130fd4 723 } while (!done);
mbed_official 0:51ac1d130fd4 724
mbed_official 0:51ac1d130fd4 725 if (off > 0) {
mbed_official 0:51ac1d130fd4 726 /* update receive window */
mbed_official 0:51ac1d130fd4 727 netconn_recved(sock->conn, (u32_t)off);
mbed_official 0:51ac1d130fd4 728 }
mbed_official 0:51ac1d130fd4 729 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 730 return off;
mbed_official 0:51ac1d130fd4 731 }
mbed_official 0:51ac1d130fd4 732
mbed_official 0:51ac1d130fd4 733 int
mbed_official 0:51ac1d130fd4 734 lwip_read(int s, void *mem, size_t len)
mbed_official 0:51ac1d130fd4 735 {
mbed_official 0:51ac1d130fd4 736 return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
mbed_official 0:51ac1d130fd4 737 }
mbed_official 0:51ac1d130fd4 738
mbed_official 0:51ac1d130fd4 739 int
mbed_official 0:51ac1d130fd4 740 lwip_recv(int s, void *mem, size_t len, int flags)
mbed_official 0:51ac1d130fd4 741 {
mbed_official 0:51ac1d130fd4 742 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
mbed_official 0:51ac1d130fd4 743 }
mbed_official 0:51ac1d130fd4 744
mbed_official 0:51ac1d130fd4 745 int
mbed_official 0:51ac1d130fd4 746 lwip_send(int s, const void *data, size_t size, int flags)
mbed_official 0:51ac1d130fd4 747 {
mbed_official 0:51ac1d130fd4 748 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 749 err_t err;
mbed_official 0:51ac1d130fd4 750 u8_t write_flags;
mbed_official 0:51ac1d130fd4 751
mbed_official 0:51ac1d130fd4 752 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
mbed_official 0:51ac1d130fd4 753 s, data, size, flags));
mbed_official 0:51ac1d130fd4 754
mbed_official 0:51ac1d130fd4 755 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 756 if (!sock) {
mbed_official 0:51ac1d130fd4 757 return -1;
mbed_official 0:51ac1d130fd4 758 }
mbed_official 0:51ac1d130fd4 759
mbed_official 0:51ac1d130fd4 760 if (sock->conn->type != NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 761 #if (LWIP_UDP || LWIP_RAW)
mbed_official 0:51ac1d130fd4 762 return lwip_sendto(s, data, size, flags, NULL, 0);
mbed_official 0:51ac1d130fd4 763 #else /* (LWIP_UDP || LWIP_RAW) */
mbed_official 0:51ac1d130fd4 764 sock_set_errno(sock, err_to_errno(ERR_ARG));
mbed_official 0:51ac1d130fd4 765 return -1;
mbed_official 0:51ac1d130fd4 766 #endif /* (LWIP_UDP || LWIP_RAW) */
mbed_official 0:51ac1d130fd4 767 }
mbed_official 0:51ac1d130fd4 768
mbed_official 0:51ac1d130fd4 769 if ((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) {
mbed_official 0:51ac1d130fd4 770 if ((size > TCP_SND_BUF) || ((size / TCP_MSS) > TCP_SND_QUEUELEN)) {
mbed_official 0:51ac1d130fd4 771 /* too much data to ever send nonblocking! */
mbed_official 0:51ac1d130fd4 772 sock_set_errno(sock, EMSGSIZE);
mbed_official 0:51ac1d130fd4 773 return -1;
mbed_official 0:51ac1d130fd4 774 }
mbed_official 0:51ac1d130fd4 775 }
mbed_official 0:51ac1d130fd4 776
mbed_official 0:51ac1d130fd4 777 write_flags = NETCONN_COPY |
mbed_official 0:51ac1d130fd4 778 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
mbed_official 0:51ac1d130fd4 779 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
mbed_official 0:51ac1d130fd4 780 err = netconn_write(sock->conn, data, size, write_flags);
mbed_official 0:51ac1d130fd4 781
mbed_official 0:51ac1d130fd4 782 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
mbed_official 0:51ac1d130fd4 783 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 784 return (err == ERR_OK ? (int)size : -1);
mbed_official 0:51ac1d130fd4 785 }
mbed_official 0:51ac1d130fd4 786
mbed_official 0:51ac1d130fd4 787 int
mbed_official 0:51ac1d130fd4 788 lwip_sendto(int s, const void *data, size_t size, int flags,
mbed_official 0:51ac1d130fd4 789 const struct sockaddr *to, socklen_t tolen)
mbed_official 0:51ac1d130fd4 790 {
mbed_official 0:51ac1d130fd4 791 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 792 err_t err;
mbed_official 0:51ac1d130fd4 793 u16_t short_size;
mbed_official 0:51ac1d130fd4 794 const struct sockaddr_in *to_in;
mbed_official 0:51ac1d130fd4 795 u16_t remote_port;
mbed_official 0:51ac1d130fd4 796 #if !LWIP_TCPIP_CORE_LOCKING
mbed_official 0:51ac1d130fd4 797 struct netbuf buf;
mbed_official 0:51ac1d130fd4 798 #endif
mbed_official 0:51ac1d130fd4 799
mbed_official 0:51ac1d130fd4 800 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 801 if (!sock) {
mbed_official 0:51ac1d130fd4 802 return -1;
mbed_official 0:51ac1d130fd4 803 }
mbed_official 0:51ac1d130fd4 804
mbed_official 0:51ac1d130fd4 805 if (sock->conn->type == NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 806 #if LWIP_TCP
mbed_official 0:51ac1d130fd4 807 return lwip_send(s, data, size, flags);
mbed_official 0:51ac1d130fd4 808 #else /* LWIP_TCP */
mbed_official 0:51ac1d130fd4 809 LWIP_UNUSED_ARG(flags);
mbed_official 0:51ac1d130fd4 810 sock_set_errno(sock, err_to_errno(ERR_ARG));
mbed_official 0:51ac1d130fd4 811 return -1;
mbed_official 0:51ac1d130fd4 812 #endif /* LWIP_TCP */
mbed_official 0:51ac1d130fd4 813 }
mbed_official 0:51ac1d130fd4 814
mbed_official 0:51ac1d130fd4 815 /* @todo: split into multiple sendto's? */
mbed_official 0:51ac1d130fd4 816 LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
mbed_official 0:51ac1d130fd4 817 short_size = (u16_t)size;
mbed_official 0:51ac1d130fd4 818 LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
mbed_official 0:51ac1d130fd4 819 ((tolen == sizeof(struct sockaddr_in)) &&
mbed_official 0:51ac1d130fd4 820 ((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))),
mbed_official 0:51ac1d130fd4 821 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
mbed_official 0:51ac1d130fd4 822 to_in = (const struct sockaddr_in *)(void*)to;
mbed_official 0:51ac1d130fd4 823
mbed_official 0:51ac1d130fd4 824 #if LWIP_TCPIP_CORE_LOCKING
mbed_official 0:51ac1d130fd4 825 /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
mbed_official 0:51ac1d130fd4 826 {
mbed_official 0:51ac1d130fd4 827 struct pbuf* p;
mbed_official 0:51ac1d130fd4 828 ip_addr_t *remote_addr;
mbed_official 0:51ac1d130fd4 829
mbed_official 0:51ac1d130fd4 830 #if LWIP_NETIF_TX_SINGLE_PBUF
mbed_official 0:51ac1d130fd4 831 p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
mbed_official 0:51ac1d130fd4 832 if (p != NULL) {
mbed_official 0:51ac1d130fd4 833 #if LWIP_CHECKSUM_ON_COPY
mbed_official 0:51ac1d130fd4 834 u16_t chksum = 0;
mbed_official 0:51ac1d130fd4 835 if (sock->conn->type != NETCONN_RAW) {
mbed_official 0:51ac1d130fd4 836 chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
mbed_official 0:51ac1d130fd4 837 } else
mbed_official 0:51ac1d130fd4 838 #endif /* LWIP_CHECKSUM_ON_COPY */
mbed_official 0:51ac1d130fd4 839 MEMCPY(p->payload, data, size);
mbed_official 0:51ac1d130fd4 840 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
mbed_official 0:51ac1d130fd4 841 p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF);
mbed_official 0:51ac1d130fd4 842 if (p != NULL) {
mbed_official 0:51ac1d130fd4 843 p->payload = (void*)data;
mbed_official 0:51ac1d130fd4 844 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
mbed_official 0:51ac1d130fd4 845
mbed_official 0:51ac1d130fd4 846 if (to_in != NULL) {
mbed_official 0:51ac1d130fd4 847 inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr);
mbed_official 0:51ac1d130fd4 848 remote_port = ntohs(to_in->sin_port);
mbed_official 0:51ac1d130fd4 849 } else {
mbed_official 0:51ac1d130fd4 850 remote_addr = &sock->conn->pcb.raw->remote_ip;
mbed_official 0:51ac1d130fd4 851 if (sock->conn->type == NETCONN_RAW) {
mbed_official 0:51ac1d130fd4 852 remote_port = 0;
mbed_official 0:51ac1d130fd4 853 } else {
mbed_official 0:51ac1d130fd4 854 remote_port = sock->conn->pcb.udp->remote_port;
mbed_official 0:51ac1d130fd4 855 }
mbed_official 0:51ac1d130fd4 856 }
mbed_official 0:51ac1d130fd4 857
mbed_official 0:51ac1d130fd4 858 LOCK_TCPIP_CORE();
mbed_official 0:51ac1d130fd4 859 if (sock->conn->type == NETCONN_RAW) {
mbed_official 0:51ac1d130fd4 860 err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr);
mbed_official 0:51ac1d130fd4 861 } else {
mbed_official 0:51ac1d130fd4 862 #if LWIP_UDP
mbed_official 0:51ac1d130fd4 863 #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
mbed_official 0:51ac1d130fd4 864 err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
mbed_official 0:51ac1d130fd4 865 remote_addr, remote_port, 1, chksum);
mbed_official 0:51ac1d130fd4 866 #else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
mbed_official 0:51ac1d130fd4 867 err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
mbed_official 0:51ac1d130fd4 868 remote_addr, remote_port);
mbed_official 0:51ac1d130fd4 869 #endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
mbed_official 0:51ac1d130fd4 870 #else /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 871 err = ERR_ARG;
mbed_official 0:51ac1d130fd4 872 #endif /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 873 }
mbed_official 0:51ac1d130fd4 874 UNLOCK_TCPIP_CORE();
mbed_official 0:51ac1d130fd4 875
mbed_official 0:51ac1d130fd4 876 pbuf_free(p);
mbed_official 0:51ac1d130fd4 877 } else {
mbed_official 0:51ac1d130fd4 878 err = ERR_MEM;
mbed_official 0:51ac1d130fd4 879 }
mbed_official 0:51ac1d130fd4 880 }
mbed_official 0:51ac1d130fd4 881 #else /* LWIP_TCPIP_CORE_LOCKING */
mbed_official 0:51ac1d130fd4 882 /* initialize a buffer */
mbed_official 0:51ac1d130fd4 883 buf.p = buf.ptr = NULL;
mbed_official 0:51ac1d130fd4 884 #if LWIP_CHECKSUM_ON_COPY
mbed_official 0:51ac1d130fd4 885 buf.flags = 0;
mbed_official 0:51ac1d130fd4 886 #endif /* LWIP_CHECKSUM_ON_COPY */
mbed_official 0:51ac1d130fd4 887 if (to) {
mbed_official 0:51ac1d130fd4 888 inet_addr_to_ipaddr(&buf.addr, &to_in->sin_addr);
mbed_official 0:51ac1d130fd4 889 remote_port = ntohs(to_in->sin_port);
mbed_official 0:51ac1d130fd4 890 netbuf_fromport(&buf) = remote_port;
mbed_official 0:51ac1d130fd4 891 } else {
mbed_official 0:51ac1d130fd4 892 remote_port = 0;
mbed_official 0:51ac1d130fd4 893 ip_addr_set_any(&buf.addr);
mbed_official 0:51ac1d130fd4 894 netbuf_fromport(&buf) = 0;
mbed_official 0:51ac1d130fd4 895 }
mbed_official 0:51ac1d130fd4 896
mbed_official 0:51ac1d130fd4 897 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=",
mbed_official 0:51ac1d130fd4 898 s, data, short_size, flags));
mbed_official 0:51ac1d130fd4 899 ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr);
mbed_official 0:51ac1d130fd4 900 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
mbed_official 0:51ac1d130fd4 901
mbed_official 0:51ac1d130fd4 902 /* make the buffer point to the data that should be sent */
mbed_official 0:51ac1d130fd4 903 #if LWIP_NETIF_TX_SINGLE_PBUF
mbed_official 0:51ac1d130fd4 904 /* Allocate a new netbuf and copy the data into it. */
mbed_official 0:51ac1d130fd4 905 if (netbuf_alloc(&buf, short_size) == NULL) {
mbed_official 0:51ac1d130fd4 906 err = ERR_MEM;
mbed_official 0:51ac1d130fd4 907 } else {
mbed_official 0:51ac1d130fd4 908 #if LWIP_CHECKSUM_ON_COPY
mbed_official 0:51ac1d130fd4 909 if (sock->conn->type != NETCONN_RAW) {
mbed_official 0:51ac1d130fd4 910 u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
mbed_official 0:51ac1d130fd4 911 netbuf_set_chksum(&buf, chksum);
mbed_official 0:51ac1d130fd4 912 err = ERR_OK;
mbed_official 0:51ac1d130fd4 913 } else
mbed_official 0:51ac1d130fd4 914 #endif /* LWIP_CHECKSUM_ON_COPY */
mbed_official 0:51ac1d130fd4 915 {
mbed_official 0:51ac1d130fd4 916 err = netbuf_take(&buf, data, short_size);
mbed_official 0:51ac1d130fd4 917 }
mbed_official 0:51ac1d130fd4 918 }
mbed_official 0:51ac1d130fd4 919 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
mbed_official 0:51ac1d130fd4 920 err = netbuf_ref(&buf, data, short_size);
mbed_official 0:51ac1d130fd4 921 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
mbed_official 0:51ac1d130fd4 922 if (err == ERR_OK) {
mbed_official 0:51ac1d130fd4 923 /* send the data */
mbed_official 0:51ac1d130fd4 924 err = netconn_send(sock->conn, &buf);
mbed_official 0:51ac1d130fd4 925 }
mbed_official 0:51ac1d130fd4 926
mbed_official 0:51ac1d130fd4 927 /* deallocated the buffer */
mbed_official 0:51ac1d130fd4 928 netbuf_free(&buf);
mbed_official 0:51ac1d130fd4 929 #endif /* LWIP_TCPIP_CORE_LOCKING */
mbed_official 0:51ac1d130fd4 930 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 931 return (err == ERR_OK ? short_size : -1);
mbed_official 0:51ac1d130fd4 932 }
mbed_official 0:51ac1d130fd4 933
mbed_official 0:51ac1d130fd4 934 int
mbed_official 0:51ac1d130fd4 935 lwip_socket(int domain, int type, int protocol)
mbed_official 0:51ac1d130fd4 936 {
mbed_official 0:51ac1d130fd4 937 struct netconn *conn;
mbed_official 0:51ac1d130fd4 938 int i;
mbed_official 0:51ac1d130fd4 939
mbed_official 0:51ac1d130fd4 940 LWIP_UNUSED_ARG(domain);
mbed_official 0:51ac1d130fd4 941
mbed_official 0:51ac1d130fd4 942 /* create a netconn */
mbed_official 0:51ac1d130fd4 943 switch (type) {
mbed_official 0:51ac1d130fd4 944 case SOCK_RAW:
mbed_official 0:51ac1d130fd4 945 conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
mbed_official 0:51ac1d130fd4 946 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
mbed_official 0:51ac1d130fd4 947 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
mbed_official 0:51ac1d130fd4 948 break;
mbed_official 0:51ac1d130fd4 949 case SOCK_DGRAM:
mbed_official 0:51ac1d130fd4 950 conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
mbed_official 0:51ac1d130fd4 951 NETCONN_UDPLITE : NETCONN_UDP, event_callback);
mbed_official 0:51ac1d130fd4 952 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
mbed_official 0:51ac1d130fd4 953 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
mbed_official 0:51ac1d130fd4 954 break;
mbed_official 0:51ac1d130fd4 955 case SOCK_STREAM:
mbed_official 0:51ac1d130fd4 956 conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
mbed_official 0:51ac1d130fd4 957 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
mbed_official 0:51ac1d130fd4 958 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
mbed_official 0:51ac1d130fd4 959 if (conn != NULL) {
mbed_official 0:51ac1d130fd4 960 /* Prevent automatic window updates, we do this on our own! */
mbed_official 0:51ac1d130fd4 961 netconn_set_noautorecved(conn, 1);
mbed_official 0:51ac1d130fd4 962 }
mbed_official 0:51ac1d130fd4 963 break;
mbed_official 0:51ac1d130fd4 964 default:
mbed_official 0:51ac1d130fd4 965 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
mbed_official 0:51ac1d130fd4 966 domain, type, protocol));
mbed_official 0:51ac1d130fd4 967 set_errno(EINVAL);
mbed_official 0:51ac1d130fd4 968 return -1;
mbed_official 0:51ac1d130fd4 969 }
mbed_official 0:51ac1d130fd4 970
mbed_official 0:51ac1d130fd4 971 if (!conn) {
mbed_official 0:51ac1d130fd4 972 LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
mbed_official 0:51ac1d130fd4 973 set_errno(ENOBUFS);
mbed_official 0:51ac1d130fd4 974 return -1;
mbed_official 0:51ac1d130fd4 975 }
mbed_official 0:51ac1d130fd4 976
mbed_official 0:51ac1d130fd4 977 i = alloc_socket(conn, 0);
mbed_official 0:51ac1d130fd4 978
mbed_official 0:51ac1d130fd4 979 if (i == -1) {
mbed_official 0:51ac1d130fd4 980 netconn_delete(conn);
mbed_official 0:51ac1d130fd4 981 set_errno(ENFILE);
mbed_official 0:51ac1d130fd4 982 return -1;
mbed_official 0:51ac1d130fd4 983 }
mbed_official 0:51ac1d130fd4 984 conn->socket = i;
mbed_official 0:51ac1d130fd4 985 LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
mbed_official 0:51ac1d130fd4 986 set_errno(0);
mbed_official 0:51ac1d130fd4 987 return i;
mbed_official 0:51ac1d130fd4 988 }
mbed_official 0:51ac1d130fd4 989
mbed_official 0:51ac1d130fd4 990 int
mbed_official 0:51ac1d130fd4 991 lwip_write(int s, const void *data, size_t size)
mbed_official 0:51ac1d130fd4 992 {
mbed_official 0:51ac1d130fd4 993 return lwip_send(s, data, size, 0);
mbed_official 0:51ac1d130fd4 994 }
mbed_official 0:51ac1d130fd4 995
mbed_official 0:51ac1d130fd4 996 /**
mbed_official 0:51ac1d130fd4 997 * Go through the readset and writeset lists and see which socket of the sockets
mbed_official 0:51ac1d130fd4 998 * set in the sets has events. On return, readset, writeset and exceptset have
mbed_official 0:51ac1d130fd4 999 * the sockets enabled that had events.
mbed_official 0:51ac1d130fd4 1000 *
mbed_official 0:51ac1d130fd4 1001 * exceptset is not used for now!!!
mbed_official 0:51ac1d130fd4 1002 *
mbed_official 0:51ac1d130fd4 1003 * @param maxfdp1 the highest socket index in the sets
mbed_official 0:51ac1d130fd4 1004 * @param readset_in: set of sockets to check for read events
mbed_official 0:51ac1d130fd4 1005 * @param writeset_in: set of sockets to check for write events
mbed_official 0:51ac1d130fd4 1006 * @param exceptset_in: set of sockets to check for error events
mbed_official 0:51ac1d130fd4 1007 * @param readset_out: set of sockets that had read events
mbed_official 0:51ac1d130fd4 1008 * @param writeset_out: set of sockets that had write events
mbed_official 0:51ac1d130fd4 1009 * @param exceptset_out: set os sockets that had error events
mbed_official 0:51ac1d130fd4 1010 * @return number of sockets that had events (read/write/exception) (>= 0)
mbed_official 0:51ac1d130fd4 1011 */
mbed_official 0:51ac1d130fd4 1012 static int
mbed_official 0:51ac1d130fd4 1013 lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
mbed_official 0:51ac1d130fd4 1014 fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
mbed_official 0:51ac1d130fd4 1015 {
mbed_official 0:51ac1d130fd4 1016 int i, nready = 0;
mbed_official 0:51ac1d130fd4 1017 fd_set lreadset, lwriteset, lexceptset;
mbed_official 0:51ac1d130fd4 1018 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 1019 SYS_ARCH_DECL_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1020
mbed_official 0:51ac1d130fd4 1021 FD_ZERO(&lreadset);
mbed_official 0:51ac1d130fd4 1022 FD_ZERO(&lwriteset);
mbed_official 0:51ac1d130fd4 1023 FD_ZERO(&lexceptset);
mbed_official 0:51ac1d130fd4 1024
mbed_official 0:51ac1d130fd4 1025 /* Go through each socket in each list to count number of sockets which
mbed_official 0:51ac1d130fd4 1026 currently match */
mbed_official 0:51ac1d130fd4 1027 for(i = 0; i < maxfdp1; i++) {
mbed_official 0:51ac1d130fd4 1028 void* lastdata = NULL;
mbed_official 0:51ac1d130fd4 1029 s16_t rcvevent = 0;
mbed_official 0:51ac1d130fd4 1030 u16_t sendevent = 0;
mbed_official 0:51ac1d130fd4 1031 u16_t errevent = 0;
mbed_official 0:51ac1d130fd4 1032 /* First get the socket's status (protected)... */
mbed_official 0:51ac1d130fd4 1033 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1034 sock = tryget_socket(i);
mbed_official 0:51ac1d130fd4 1035 if (sock != NULL) {
mbed_official 0:51ac1d130fd4 1036 lastdata = sock->lastdata;
mbed_official 0:51ac1d130fd4 1037 rcvevent = sock->rcvevent;
mbed_official 0:51ac1d130fd4 1038 sendevent = sock->sendevent;
mbed_official 0:51ac1d130fd4 1039 errevent = sock->errevent;
mbed_official 0:51ac1d130fd4 1040 }
mbed_official 0:51ac1d130fd4 1041 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1042 /* ... then examine it: */
mbed_official 0:51ac1d130fd4 1043 /* See if netconn of this socket is ready for read */
mbed_official 0:51ac1d130fd4 1044 if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
mbed_official 0:51ac1d130fd4 1045 FD_SET(i, &lreadset);
mbed_official 0:51ac1d130fd4 1046 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
mbed_official 0:51ac1d130fd4 1047 nready++;
mbed_official 0:51ac1d130fd4 1048 }
mbed_official 0:51ac1d130fd4 1049 /* See if netconn of this socket is ready for write */
mbed_official 0:51ac1d130fd4 1050 if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
mbed_official 0:51ac1d130fd4 1051 FD_SET(i, &lwriteset);
mbed_official 0:51ac1d130fd4 1052 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
mbed_official 0:51ac1d130fd4 1053 nready++;
mbed_official 0:51ac1d130fd4 1054 }
mbed_official 0:51ac1d130fd4 1055 /* See if netconn of this socket had an error */
mbed_official 0:51ac1d130fd4 1056 if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
mbed_official 0:51ac1d130fd4 1057 FD_SET(i, &lexceptset);
mbed_official 0:51ac1d130fd4 1058 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
mbed_official 0:51ac1d130fd4 1059 nready++;
mbed_official 0:51ac1d130fd4 1060 }
mbed_official 0:51ac1d130fd4 1061 }
mbed_official 0:51ac1d130fd4 1062 /* copy local sets to the ones provided as arguments */
mbed_official 0:51ac1d130fd4 1063 *readset_out = lreadset;
mbed_official 0:51ac1d130fd4 1064 *writeset_out = lwriteset;
mbed_official 0:51ac1d130fd4 1065 *exceptset_out = lexceptset;
mbed_official 0:51ac1d130fd4 1066
mbed_official 0:51ac1d130fd4 1067 LWIP_ASSERT("nready >= 0", nready >= 0);
mbed_official 0:51ac1d130fd4 1068 return nready;
mbed_official 0:51ac1d130fd4 1069 }
mbed_official 0:51ac1d130fd4 1070
mbed_official 0:51ac1d130fd4 1071 /**
mbed_official 0:51ac1d130fd4 1072 * Processing exceptset is not yet implemented.
mbed_official 0:51ac1d130fd4 1073 */
mbed_official 0:51ac1d130fd4 1074 int
mbed_official 0:51ac1d130fd4 1075 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
mbed_official 0:51ac1d130fd4 1076 struct timeval *timeout)
mbed_official 0:51ac1d130fd4 1077 {
mbed_official 0:51ac1d130fd4 1078 u32_t waitres = 0;
mbed_official 0:51ac1d130fd4 1079 int nready;
mbed_official 0:51ac1d130fd4 1080 fd_set lreadset, lwriteset, lexceptset;
mbed_official 0:51ac1d130fd4 1081 u32_t msectimeout;
mbed_official 0:51ac1d130fd4 1082 struct lwip_select_cb select_cb;
mbed_official 0:51ac1d130fd4 1083 err_t err;
mbed_official 0:51ac1d130fd4 1084 int i;
mbed_official 0:51ac1d130fd4 1085 SYS_ARCH_DECL_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1086
mbed_official 0:51ac1d130fd4 1087 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
mbed_official 0:51ac1d130fd4 1088 maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
mbed_official 0:51ac1d130fd4 1089 timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
mbed_official 0:51ac1d130fd4 1090 timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
mbed_official 0:51ac1d130fd4 1091
mbed_official 0:51ac1d130fd4 1092 /* Go through each socket in each list to count number of sockets which
mbed_official 0:51ac1d130fd4 1093 currently match */
mbed_official 0:51ac1d130fd4 1094 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
mbed_official 0:51ac1d130fd4 1095
mbed_official 0:51ac1d130fd4 1096 /* If we don't have any current events, then suspend if we are supposed to */
mbed_official 0:51ac1d130fd4 1097 if (!nready) {
mbed_official 0:51ac1d130fd4 1098 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
mbed_official 0:51ac1d130fd4 1099 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
mbed_official 0:51ac1d130fd4 1100 /* This is OK as the local fdsets are empty and nready is zero,
mbed_official 0:51ac1d130fd4 1101 or we would have returned earlier. */
mbed_official 0:51ac1d130fd4 1102 goto return_copy_fdsets;
mbed_official 0:51ac1d130fd4 1103 }
mbed_official 0:51ac1d130fd4 1104
mbed_official 0:51ac1d130fd4 1105 /* None ready: add our semaphore to list:
mbed_official 0:51ac1d130fd4 1106 We don't actually need any dynamic memory. Our entry on the
mbed_official 0:51ac1d130fd4 1107 list is only valid while we are in this function, so it's ok
mbed_official 0:51ac1d130fd4 1108 to use local variables. */
mbed_official 0:51ac1d130fd4 1109
mbed_official 0:51ac1d130fd4 1110 select_cb.next = NULL;
mbed_official 0:51ac1d130fd4 1111 select_cb.prev = NULL;
mbed_official 0:51ac1d130fd4 1112 select_cb.readset = readset;
mbed_official 0:51ac1d130fd4 1113 select_cb.writeset = writeset;
mbed_official 0:51ac1d130fd4 1114 select_cb.exceptset = exceptset;
mbed_official 0:51ac1d130fd4 1115 select_cb.sem_signalled = 0;
mbed_official 0:51ac1d130fd4 1116 err = sys_sem_new(&select_cb.sem, 0);
mbed_official 0:51ac1d130fd4 1117 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 1118 /* failed to create semaphore */
mbed_official 0:51ac1d130fd4 1119 set_errno(ENOMEM);
mbed_official 0:51ac1d130fd4 1120 return -1;
mbed_official 0:51ac1d130fd4 1121 }
mbed_official 0:51ac1d130fd4 1122
mbed_official 0:51ac1d130fd4 1123 /* Protect the select_cb_list */
mbed_official 0:51ac1d130fd4 1124 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1125
mbed_official 0:51ac1d130fd4 1126 /* Put this select_cb on top of list */
mbed_official 0:51ac1d130fd4 1127 select_cb.next = select_cb_list;
mbed_official 0:51ac1d130fd4 1128 if (select_cb_list != NULL) {
mbed_official 0:51ac1d130fd4 1129 select_cb_list->prev = &select_cb;
mbed_official 0:51ac1d130fd4 1130 }
mbed_official 0:51ac1d130fd4 1131 select_cb_list = &select_cb;
mbed_official 0:51ac1d130fd4 1132 /* Increasing this counter tells even_callback that the list has changed. */
mbed_official 0:51ac1d130fd4 1133 select_cb_ctr++;
mbed_official 0:51ac1d130fd4 1134
mbed_official 0:51ac1d130fd4 1135 /* Now we can safely unprotect */
mbed_official 0:51ac1d130fd4 1136 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1137
mbed_official 0:51ac1d130fd4 1138 /* Increase select_waiting for each socket we are interested in */
mbed_official 0:51ac1d130fd4 1139 for(i = 0; i < maxfdp1; i++) {
mbed_official 0:51ac1d130fd4 1140 if ((readset && FD_ISSET(i, readset)) ||
mbed_official 0:51ac1d130fd4 1141 (writeset && FD_ISSET(i, writeset)) ||
mbed_official 0:51ac1d130fd4 1142 (exceptset && FD_ISSET(i, exceptset))) {
mbed_official 0:51ac1d130fd4 1143 struct lwip_sock *sock = tryget_socket(i);
mbed_official 0:51ac1d130fd4 1144 LWIP_ASSERT("sock != NULL", sock != NULL);
mbed_official 0:51ac1d130fd4 1145 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1146 sock->select_waiting++;
mbed_official 0:51ac1d130fd4 1147 LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
mbed_official 0:51ac1d130fd4 1148 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1149 }
mbed_official 0:51ac1d130fd4 1150 }
mbed_official 0:51ac1d130fd4 1151
mbed_official 0:51ac1d130fd4 1152 /* Call lwip_selscan again: there could have been events between
mbed_official 0:51ac1d130fd4 1153 the last scan (whithout us on the list) and putting us on the list! */
mbed_official 0:51ac1d130fd4 1154 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
mbed_official 0:51ac1d130fd4 1155 if (!nready) {
mbed_official 0:51ac1d130fd4 1156 /* Still none ready, just wait to be woken */
mbed_official 0:51ac1d130fd4 1157 if (timeout == 0) {
mbed_official 0:51ac1d130fd4 1158 /* Wait forever */
mbed_official 0:51ac1d130fd4 1159 msectimeout = 0;
mbed_official 0:51ac1d130fd4 1160 } else {
mbed_official 0:51ac1d130fd4 1161 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
mbed_official 0:51ac1d130fd4 1162 if (msectimeout == 0) {
mbed_official 0:51ac1d130fd4 1163 /* Wait 1ms at least (0 means wait forever) */
mbed_official 0:51ac1d130fd4 1164 msectimeout = 1;
mbed_official 0:51ac1d130fd4 1165 }
mbed_official 0:51ac1d130fd4 1166 }
mbed_official 0:51ac1d130fd4 1167
mbed_official 0:51ac1d130fd4 1168 waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout);
mbed_official 0:51ac1d130fd4 1169 }
mbed_official 0:51ac1d130fd4 1170 /* Increase select_waiting for each socket we are interested in */
mbed_official 0:51ac1d130fd4 1171 for(i = 0; i < maxfdp1; i++) {
mbed_official 0:51ac1d130fd4 1172 if ((readset && FD_ISSET(i, readset)) ||
mbed_official 0:51ac1d130fd4 1173 (writeset && FD_ISSET(i, writeset)) ||
mbed_official 0:51ac1d130fd4 1174 (exceptset && FD_ISSET(i, exceptset))) {
mbed_official 0:51ac1d130fd4 1175 struct lwip_sock *sock = tryget_socket(i);
mbed_official 0:51ac1d130fd4 1176 LWIP_ASSERT("sock != NULL", sock != NULL);
mbed_official 0:51ac1d130fd4 1177 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1178 sock->select_waiting--;
mbed_official 0:51ac1d130fd4 1179 LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0);
mbed_official 0:51ac1d130fd4 1180 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1181 }
mbed_official 0:51ac1d130fd4 1182 }
mbed_official 0:51ac1d130fd4 1183 /* Take us off the list */
mbed_official 0:51ac1d130fd4 1184 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1185 if (select_cb.next != NULL) {
mbed_official 0:51ac1d130fd4 1186 select_cb.next->prev = select_cb.prev;
mbed_official 0:51ac1d130fd4 1187 }
mbed_official 0:51ac1d130fd4 1188 if (select_cb_list == &select_cb) {
mbed_official 0:51ac1d130fd4 1189 LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
mbed_official 0:51ac1d130fd4 1190 select_cb_list = select_cb.next;
mbed_official 0:51ac1d130fd4 1191 } else {
mbed_official 0:51ac1d130fd4 1192 LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
mbed_official 0:51ac1d130fd4 1193 select_cb.prev->next = select_cb.next;
mbed_official 0:51ac1d130fd4 1194 }
mbed_official 0:51ac1d130fd4 1195 /* Increasing this counter tells even_callback that the list has changed. */
mbed_official 0:51ac1d130fd4 1196 select_cb_ctr++;
mbed_official 0:51ac1d130fd4 1197 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1198
mbed_official 0:51ac1d130fd4 1199 sys_sem_free(&select_cb.sem);
mbed_official 0:51ac1d130fd4 1200 if (waitres == SYS_ARCH_TIMEOUT) {
mbed_official 0:51ac1d130fd4 1201 /* Timeout */
mbed_official 0:51ac1d130fd4 1202 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
mbed_official 0:51ac1d130fd4 1203 /* This is OK as the local fdsets are empty and nready is zero,
mbed_official 0:51ac1d130fd4 1204 or we would have returned earlier. */
mbed_official 0:51ac1d130fd4 1205 goto return_copy_fdsets;
mbed_official 0:51ac1d130fd4 1206 }
mbed_official 0:51ac1d130fd4 1207
mbed_official 0:51ac1d130fd4 1208 /* See what's set */
mbed_official 0:51ac1d130fd4 1209 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
mbed_official 0:51ac1d130fd4 1210 }
mbed_official 0:51ac1d130fd4 1211
mbed_official 0:51ac1d130fd4 1212 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
mbed_official 0:51ac1d130fd4 1213 return_copy_fdsets:
mbed_official 0:51ac1d130fd4 1214 set_errno(0);
mbed_official 0:51ac1d130fd4 1215 if (readset) {
mbed_official 0:51ac1d130fd4 1216 *readset = lreadset;
mbed_official 0:51ac1d130fd4 1217 }
mbed_official 0:51ac1d130fd4 1218 if (writeset) {
mbed_official 0:51ac1d130fd4 1219 *writeset = lwriteset;
mbed_official 0:51ac1d130fd4 1220 }
mbed_official 0:51ac1d130fd4 1221 if (exceptset) {
mbed_official 0:51ac1d130fd4 1222 *exceptset = lexceptset;
mbed_official 0:51ac1d130fd4 1223 }
mbed_official 0:51ac1d130fd4 1224
mbed_official 0:51ac1d130fd4 1225
mbed_official 0:51ac1d130fd4 1226 return nready;
mbed_official 0:51ac1d130fd4 1227 }
mbed_official 0:51ac1d130fd4 1228
mbed_official 0:51ac1d130fd4 1229 /**
mbed_official 0:51ac1d130fd4 1230 * Callback registered in the netconn layer for each socket-netconn.
mbed_official 0:51ac1d130fd4 1231 * Processes recvevent (data available) and wakes up tasks waiting for select.
mbed_official 0:51ac1d130fd4 1232 */
mbed_official 0:51ac1d130fd4 1233 static void
mbed_official 0:51ac1d130fd4 1234 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
mbed_official 0:51ac1d130fd4 1235 {
mbed_official 0:51ac1d130fd4 1236 int s;
mbed_official 0:51ac1d130fd4 1237 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 1238 struct lwip_select_cb *scb;
mbed_official 0:51ac1d130fd4 1239 int last_select_cb_ctr;
mbed_official 0:51ac1d130fd4 1240 SYS_ARCH_DECL_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1241
mbed_official 0:51ac1d130fd4 1242 LWIP_UNUSED_ARG(len);
mbed_official 0:51ac1d130fd4 1243
mbed_official 0:51ac1d130fd4 1244 /* Get socket */
mbed_official 0:51ac1d130fd4 1245 if (conn) {
mbed_official 0:51ac1d130fd4 1246 s = conn->socket;
mbed_official 0:51ac1d130fd4 1247 if (s < 0) {
mbed_official 0:51ac1d130fd4 1248 /* Data comes in right away after an accept, even though
mbed_official 0:51ac1d130fd4 1249 * the server task might not have created a new socket yet.
mbed_official 0:51ac1d130fd4 1250 * Just count down (or up) if that's the case and we
mbed_official 0:51ac1d130fd4 1251 * will use the data later. Note that only receive events
mbed_official 0:51ac1d130fd4 1252 * can happen before the new socket is set up. */
mbed_official 0:51ac1d130fd4 1253 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1254 if (conn->socket < 0) {
mbed_official 0:51ac1d130fd4 1255 if (evt == NETCONN_EVT_RCVPLUS) {
mbed_official 0:51ac1d130fd4 1256 conn->socket--;
mbed_official 0:51ac1d130fd4 1257 }
mbed_official 0:51ac1d130fd4 1258 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1259 return;
mbed_official 0:51ac1d130fd4 1260 }
mbed_official 0:51ac1d130fd4 1261 s = conn->socket;
mbed_official 0:51ac1d130fd4 1262 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1263 }
mbed_official 0:51ac1d130fd4 1264
mbed_official 0:51ac1d130fd4 1265 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 1266 if (!sock) {
mbed_official 0:51ac1d130fd4 1267 return;
mbed_official 0:51ac1d130fd4 1268 }
mbed_official 0:51ac1d130fd4 1269 } else {
mbed_official 0:51ac1d130fd4 1270 return;
mbed_official 0:51ac1d130fd4 1271 }
mbed_official 0:51ac1d130fd4 1272
mbed_official 0:51ac1d130fd4 1273 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1274 /* Set event as required */
mbed_official 0:51ac1d130fd4 1275 switch (evt) {
mbed_official 0:51ac1d130fd4 1276 case NETCONN_EVT_RCVPLUS:
mbed_official 0:51ac1d130fd4 1277 sock->rcvevent++;
mbed_official 0:51ac1d130fd4 1278 break;
mbed_official 0:51ac1d130fd4 1279 case NETCONN_EVT_RCVMINUS:
mbed_official 0:51ac1d130fd4 1280 sock->rcvevent--;
mbed_official 0:51ac1d130fd4 1281 break;
mbed_official 0:51ac1d130fd4 1282 case NETCONN_EVT_SENDPLUS:
mbed_official 0:51ac1d130fd4 1283 sock->sendevent = 1;
mbed_official 0:51ac1d130fd4 1284 break;
mbed_official 0:51ac1d130fd4 1285 case NETCONN_EVT_SENDMINUS:
mbed_official 0:51ac1d130fd4 1286 sock->sendevent = 0;
mbed_official 0:51ac1d130fd4 1287 break;
mbed_official 0:51ac1d130fd4 1288 case NETCONN_EVT_ERROR:
mbed_official 0:51ac1d130fd4 1289 sock->errevent = 1;
mbed_official 0:51ac1d130fd4 1290 break;
mbed_official 0:51ac1d130fd4 1291 default:
mbed_official 0:51ac1d130fd4 1292 LWIP_ASSERT("unknown event", 0);
mbed_official 0:51ac1d130fd4 1293 break;
mbed_official 0:51ac1d130fd4 1294 }
mbed_official 0:51ac1d130fd4 1295
mbed_official 0:51ac1d130fd4 1296 if (sock->select_waiting == 0) {
mbed_official 0:51ac1d130fd4 1297 /* noone is waiting for this socket, no need to check select_cb_list */
mbed_official 0:51ac1d130fd4 1298 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1299 return;
mbed_official 0:51ac1d130fd4 1300 }
mbed_official 0:51ac1d130fd4 1301
mbed_official 0:51ac1d130fd4 1302 /* Now decide if anyone is waiting for this socket */
mbed_official 0:51ac1d130fd4 1303 /* NOTE: This code goes through the select_cb_list list multiple times
mbed_official 0:51ac1d130fd4 1304 ONLY IF a select was actually waiting. We go through the list the number
mbed_official 0:51ac1d130fd4 1305 of waiting select calls + 1. This list is expected to be small. */
mbed_official 0:51ac1d130fd4 1306
mbed_official 0:51ac1d130fd4 1307 /* At this point, SYS_ARCH is still protected! */
mbed_official 0:51ac1d130fd4 1308 again:
mbed_official 0:51ac1d130fd4 1309 for (scb = select_cb_list; scb != NULL; scb = scb->next) {
mbed_official 0:51ac1d130fd4 1310 if (scb->sem_signalled == 0) {
mbed_official 0:51ac1d130fd4 1311 /* semaphore not signalled yet */
mbed_official 0:51ac1d130fd4 1312 int do_signal = 0;
mbed_official 0:51ac1d130fd4 1313 /* Test this select call for our socket */
mbed_official 0:51ac1d130fd4 1314 if (sock->rcvevent > 0) {
mbed_official 0:51ac1d130fd4 1315 if (scb->readset && FD_ISSET(s, scb->readset)) {
mbed_official 0:51ac1d130fd4 1316 do_signal = 1;
mbed_official 0:51ac1d130fd4 1317 }
mbed_official 0:51ac1d130fd4 1318 }
mbed_official 0:51ac1d130fd4 1319 if (sock->sendevent != 0) {
mbed_official 0:51ac1d130fd4 1320 if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) {
mbed_official 0:51ac1d130fd4 1321 do_signal = 1;
mbed_official 0:51ac1d130fd4 1322 }
mbed_official 0:51ac1d130fd4 1323 }
mbed_official 0:51ac1d130fd4 1324 if (sock->errevent != 0) {
mbed_official 0:51ac1d130fd4 1325 if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) {
mbed_official 0:51ac1d130fd4 1326 do_signal = 1;
mbed_official 0:51ac1d130fd4 1327 }
mbed_official 0:51ac1d130fd4 1328 }
mbed_official 0:51ac1d130fd4 1329 if (do_signal) {
mbed_official 0:51ac1d130fd4 1330 scb->sem_signalled = 1;
mbed_official 0:51ac1d130fd4 1331 /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might
mbed_official 0:51ac1d130fd4 1332 lead to the select thread taking itself off the list, invalidagin the semaphore. */
mbed_official 0:51ac1d130fd4 1333 sys_sem_signal(&scb->sem);
mbed_official 0:51ac1d130fd4 1334 }
mbed_official 0:51ac1d130fd4 1335 }
mbed_official 0:51ac1d130fd4 1336 /* unlock interrupts with each step */
mbed_official 0:51ac1d130fd4 1337 last_select_cb_ctr = select_cb_ctr;
mbed_official 0:51ac1d130fd4 1338 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1339 /* this makes sure interrupt protection time is short */
mbed_official 0:51ac1d130fd4 1340 SYS_ARCH_PROTECT(lev);
mbed_official 0:51ac1d130fd4 1341 if (last_select_cb_ctr != select_cb_ctr) {
mbed_official 0:51ac1d130fd4 1342 /* someone has changed select_cb_list, restart at the beginning */
mbed_official 0:51ac1d130fd4 1343 goto again;
mbed_official 0:51ac1d130fd4 1344 }
mbed_official 0:51ac1d130fd4 1345 }
mbed_official 0:51ac1d130fd4 1346 SYS_ARCH_UNPROTECT(lev);
mbed_official 0:51ac1d130fd4 1347 }
mbed_official 0:51ac1d130fd4 1348
mbed_official 0:51ac1d130fd4 1349 /**
mbed_official 0:51ac1d130fd4 1350 * Unimplemented: Close one end of a full-duplex connection.
mbed_official 0:51ac1d130fd4 1351 * Currently, the full connection is closed.
mbed_official 0:51ac1d130fd4 1352 */
mbed_official 0:51ac1d130fd4 1353 int
mbed_official 0:51ac1d130fd4 1354 lwip_shutdown(int s, int how)
mbed_official 0:51ac1d130fd4 1355 {
mbed_official 0:51ac1d130fd4 1356 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 1357 err_t err;
mbed_official 0:51ac1d130fd4 1358 u8_t shut_rx = 0, shut_tx = 0;
mbed_official 0:51ac1d130fd4 1359
mbed_official 0:51ac1d130fd4 1360 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
mbed_official 0:51ac1d130fd4 1361
mbed_official 0:51ac1d130fd4 1362 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 1363 if (!sock) {
mbed_official 0:51ac1d130fd4 1364 return -1;
mbed_official 0:51ac1d130fd4 1365 }
mbed_official 0:51ac1d130fd4 1366
mbed_official 0:51ac1d130fd4 1367 if (sock->conn != NULL) {
mbed_official 0:51ac1d130fd4 1368 if (netconn_type(sock->conn) != NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 1369 sock_set_errno(sock, EOPNOTSUPP);
mbed_official 0:51ac1d130fd4 1370 return EOPNOTSUPP;
mbed_official 0:51ac1d130fd4 1371 }
mbed_official 0:51ac1d130fd4 1372 } else {
mbed_official 0:51ac1d130fd4 1373 sock_set_errno(sock, ENOTCONN);
mbed_official 0:51ac1d130fd4 1374 return ENOTCONN;
mbed_official 0:51ac1d130fd4 1375 }
mbed_official 0:51ac1d130fd4 1376
mbed_official 0:51ac1d130fd4 1377 if (how == SHUT_RD) {
mbed_official 0:51ac1d130fd4 1378 shut_rx = 1;
mbed_official 0:51ac1d130fd4 1379 } else if (how == SHUT_WR) {
mbed_official 0:51ac1d130fd4 1380 shut_tx = 1;
mbed_official 0:51ac1d130fd4 1381 } else if(how == SHUT_RDWR) {
mbed_official 0:51ac1d130fd4 1382 shut_rx = 1;
mbed_official 0:51ac1d130fd4 1383 shut_tx = 1;
mbed_official 0:51ac1d130fd4 1384 } else {
mbed_official 0:51ac1d130fd4 1385 sock_set_errno(sock, EINVAL);
mbed_official 0:51ac1d130fd4 1386 return EINVAL;
mbed_official 0:51ac1d130fd4 1387 }
mbed_official 0:51ac1d130fd4 1388 err = netconn_shutdown(sock->conn, shut_rx, shut_tx);
mbed_official 0:51ac1d130fd4 1389
mbed_official 0:51ac1d130fd4 1390 sock_set_errno(sock, err_to_errno(err));
mbed_official 0:51ac1d130fd4 1391 return (err == ERR_OK ? 0 : -1);
mbed_official 0:51ac1d130fd4 1392 }
mbed_official 0:51ac1d130fd4 1393
mbed_official 0:51ac1d130fd4 1394 static int
mbed_official 0:51ac1d130fd4 1395 lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
mbed_official 0:51ac1d130fd4 1396 {
mbed_official 0:51ac1d130fd4 1397 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 1398 struct sockaddr_in sin;
mbed_official 0:51ac1d130fd4 1399 ip_addr_t naddr;
mbed_official 0:51ac1d130fd4 1400
mbed_official 0:51ac1d130fd4 1401 sock = get_socket(s);
mbed_official 0:51ac1d130fd4 1402 if (!sock) {
mbed_official 0:51ac1d130fd4 1403 return -1;
mbed_official 0:51ac1d130fd4 1404 }
mbed_official 0:51ac1d130fd4 1405
mbed_official 0:51ac1d130fd4 1406 memset(&sin, 0, sizeof(sin));
mbed_official 0:51ac1d130fd4 1407 sin.sin_len = sizeof(sin);
mbed_official 0:51ac1d130fd4 1408 sin.sin_family = AF_INET;
mbed_official 0:51ac1d130fd4 1409
mbed_official 0:51ac1d130fd4 1410 /* get the IP address and port */
mbed_official 0:51ac1d130fd4 1411 netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
mbed_official 0:51ac1d130fd4 1412
mbed_official 0:51ac1d130fd4 1413 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
mbed_official 0:51ac1d130fd4 1414 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
mbed_official 0:51ac1d130fd4 1415 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
mbed_official 0:51ac1d130fd4 1416
mbed_official 0:51ac1d130fd4 1417 sin.sin_port = htons(sin.sin_port);
mbed_official 0:51ac1d130fd4 1418 inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
mbed_official 0:51ac1d130fd4 1419
mbed_official 0:51ac1d130fd4 1420 if (*namelen > sizeof(sin)) {
mbed_official 0:51ac1d130fd4 1421 *namelen = sizeof(sin);
mbed_official 0:51ac1d130fd4 1422 }
mbed_official 0:51ac1d130fd4 1423
mbed_official 0:51ac1d130fd4 1424 MEMCPY(name, &sin, *namelen);
mbed_official 0:51ac1d130fd4 1425 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 1426 return 0;
mbed_official 0:51ac1d130fd4 1427 }
mbed_official 0:51ac1d130fd4 1428
mbed_official 0:51ac1d130fd4 1429 int
mbed_official 0:51ac1d130fd4 1430 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
mbed_official 0:51ac1d130fd4 1431 {
mbed_official 0:51ac1d130fd4 1432 return lwip_getaddrname(s, name, namelen, 0);
mbed_official 0:51ac1d130fd4 1433 }
mbed_official 0:51ac1d130fd4 1434
mbed_official 0:51ac1d130fd4 1435 int
mbed_official 0:51ac1d130fd4 1436 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
mbed_official 0:51ac1d130fd4 1437 {
mbed_official 0:51ac1d130fd4 1438 return lwip_getaddrname(s, name, namelen, 1);
mbed_official 0:51ac1d130fd4 1439 }
mbed_official 0:51ac1d130fd4 1440
mbed_official 0:51ac1d130fd4 1441 int
mbed_official 0:51ac1d130fd4 1442 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
mbed_official 0:51ac1d130fd4 1443 {
mbed_official 0:51ac1d130fd4 1444 err_t err = ERR_OK;
mbed_official 0:51ac1d130fd4 1445 struct lwip_sock *sock = get_socket(s);
mbed_official 0:51ac1d130fd4 1446 struct lwip_setgetsockopt_data data;
mbed_official 0:51ac1d130fd4 1447
mbed_official 0:51ac1d130fd4 1448 if (!sock) {
mbed_official 0:51ac1d130fd4 1449 return -1;
mbed_official 0:51ac1d130fd4 1450 }
mbed_official 0:51ac1d130fd4 1451
mbed_official 0:51ac1d130fd4 1452 if ((NULL == optval) || (NULL == optlen)) {
mbed_official 0:51ac1d130fd4 1453 sock_set_errno(sock, EFAULT);
mbed_official 0:51ac1d130fd4 1454 return -1;
mbed_official 0:51ac1d130fd4 1455 }
mbed_official 0:51ac1d130fd4 1456
mbed_official 0:51ac1d130fd4 1457 /* Do length and type checks for the various options first, to keep it readable. */
mbed_official 0:51ac1d130fd4 1458 switch (level) {
mbed_official 0:51ac1d130fd4 1459
mbed_official 0:51ac1d130fd4 1460 /* Level: SOL_SOCKET */
mbed_official 0:51ac1d130fd4 1461 case SOL_SOCKET:
mbed_official 0:51ac1d130fd4 1462 switch (optname) {
mbed_official 0:51ac1d130fd4 1463
mbed_official 0:51ac1d130fd4 1464 case SO_ACCEPTCONN:
mbed_official 0:51ac1d130fd4 1465 case SO_BROADCAST:
mbed_official 0:51ac1d130fd4 1466 /* UNIMPL case SO_DEBUG: */
mbed_official 0:51ac1d130fd4 1467 /* UNIMPL case SO_DONTROUTE: */
mbed_official 0:51ac1d130fd4 1468 case SO_ERROR:
mbed_official 0:51ac1d130fd4 1469 case SO_KEEPALIVE:
mbed_official 0:51ac1d130fd4 1470 /* UNIMPL case SO_CONTIMEO: */
mbed_official 0:51ac1d130fd4 1471 /* UNIMPL case SO_SNDTIMEO: */
mbed_official 0:51ac1d130fd4 1472 #if LWIP_SO_RCVTIMEO
mbed_official 0:51ac1d130fd4 1473 case SO_RCVTIMEO:
mbed_official 0:51ac1d130fd4 1474 #endif /* LWIP_SO_RCVTIMEO */
mbed_official 0:51ac1d130fd4 1475 #if LWIP_SO_RCVBUF
mbed_official 0:51ac1d130fd4 1476 case SO_RCVBUF:
mbed_official 0:51ac1d130fd4 1477 #endif /* LWIP_SO_RCVBUF */
mbed_official 0:51ac1d130fd4 1478 /* UNIMPL case SO_OOBINLINE: */
mbed_official 0:51ac1d130fd4 1479 /* UNIMPL case SO_SNDBUF: */
mbed_official 0:51ac1d130fd4 1480 /* UNIMPL case SO_RCVLOWAT: */
mbed_official 0:51ac1d130fd4 1481 /* UNIMPL case SO_SNDLOWAT: */
mbed_official 0:51ac1d130fd4 1482 #if SO_REUSE
mbed_official 0:51ac1d130fd4 1483 case SO_REUSEADDR:
mbed_official 0:51ac1d130fd4 1484 case SO_REUSEPORT:
mbed_official 0:51ac1d130fd4 1485 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 1486 case SO_TYPE:
mbed_official 0:51ac1d130fd4 1487 /* UNIMPL case SO_USELOOPBACK: */
mbed_official 0:51ac1d130fd4 1488 if (*optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1489 err = EINVAL;
mbed_official 0:51ac1d130fd4 1490 }
mbed_official 0:51ac1d130fd4 1491 break;
mbed_official 0:51ac1d130fd4 1492
mbed_official 0:51ac1d130fd4 1493 case SO_NO_CHECK:
mbed_official 0:51ac1d130fd4 1494 if (*optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1495 err = EINVAL;
mbed_official 0:51ac1d130fd4 1496 }
mbed_official 0:51ac1d130fd4 1497 #if LWIP_UDP
mbed_official 0:51ac1d130fd4 1498 if ((sock->conn->type != NETCONN_UDP) ||
mbed_official 0:51ac1d130fd4 1499 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
mbed_official 0:51ac1d130fd4 1500 /* this flag is only available for UDP, not for UDP lite */
mbed_official 0:51ac1d130fd4 1501 err = EAFNOSUPPORT;
mbed_official 0:51ac1d130fd4 1502 }
mbed_official 0:51ac1d130fd4 1503 #endif /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 1504 break;
mbed_official 0:51ac1d130fd4 1505
mbed_official 0:51ac1d130fd4 1506 default:
mbed_official 0:51ac1d130fd4 1507 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1508 s, optname));
mbed_official 0:51ac1d130fd4 1509 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1510 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1511 break;
mbed_official 0:51ac1d130fd4 1512
mbed_official 0:51ac1d130fd4 1513 /* Level: IPPROTO_IP */
mbed_official 0:51ac1d130fd4 1514 case IPPROTO_IP:
mbed_official 0:51ac1d130fd4 1515 switch (optname) {
mbed_official 0:51ac1d130fd4 1516 /* UNIMPL case IP_HDRINCL: */
mbed_official 0:51ac1d130fd4 1517 /* UNIMPL case IP_RCVDSTADDR: */
mbed_official 0:51ac1d130fd4 1518 /* UNIMPL case IP_RCVIF: */
mbed_official 0:51ac1d130fd4 1519 case IP_TTL:
mbed_official 0:51ac1d130fd4 1520 case IP_TOS:
mbed_official 0:51ac1d130fd4 1521 if (*optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1522 err = EINVAL;
mbed_official 0:51ac1d130fd4 1523 }
mbed_official 0:51ac1d130fd4 1524 break;
mbed_official 0:51ac1d130fd4 1525 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 1526 case IP_MULTICAST_TTL:
mbed_official 0:51ac1d130fd4 1527 if (*optlen < sizeof(u8_t)) {
mbed_official 0:51ac1d130fd4 1528 err = EINVAL;
mbed_official 0:51ac1d130fd4 1529 }
mbed_official 0:51ac1d130fd4 1530 break;
mbed_official 0:51ac1d130fd4 1531 case IP_MULTICAST_IF:
mbed_official 0:51ac1d130fd4 1532 if (*optlen < sizeof(struct in_addr)) {
mbed_official 0:51ac1d130fd4 1533 err = EINVAL;
mbed_official 0:51ac1d130fd4 1534 }
mbed_official 0:51ac1d130fd4 1535 break;
mbed_official 0:51ac1d130fd4 1536 case IP_MULTICAST_LOOP:
mbed_official 0:51ac1d130fd4 1537 if (*optlen < sizeof(u8_t)) {
mbed_official 0:51ac1d130fd4 1538 err = EINVAL;
mbed_official 0:51ac1d130fd4 1539 }
mbed_official 0:51ac1d130fd4 1540 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
mbed_official 0:51ac1d130fd4 1541 err = EAFNOSUPPORT;
mbed_official 0:51ac1d130fd4 1542 }
mbed_official 0:51ac1d130fd4 1543 break;
mbed_official 0:51ac1d130fd4 1544 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 1545
mbed_official 0:51ac1d130fd4 1546 default:
mbed_official 0:51ac1d130fd4 1547 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1548 s, optname));
mbed_official 0:51ac1d130fd4 1549 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1550 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1551 break;
mbed_official 0:51ac1d130fd4 1552
mbed_official 0:51ac1d130fd4 1553 #if LWIP_TCP
mbed_official 0:51ac1d130fd4 1554 /* Level: IPPROTO_TCP */
mbed_official 0:51ac1d130fd4 1555 case IPPROTO_TCP:
mbed_official 0:51ac1d130fd4 1556 if (*optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1557 err = EINVAL;
mbed_official 0:51ac1d130fd4 1558 break;
mbed_official 0:51ac1d130fd4 1559 }
mbed_official 0:51ac1d130fd4 1560
mbed_official 0:51ac1d130fd4 1561 /* If this is no TCP socket, ignore any options. */
mbed_official 0:51ac1d130fd4 1562 if (sock->conn->type != NETCONN_TCP)
mbed_official 0:51ac1d130fd4 1563 return 0;
mbed_official 0:51ac1d130fd4 1564
mbed_official 0:51ac1d130fd4 1565 switch (optname) {
mbed_official 0:51ac1d130fd4 1566 case TCP_NODELAY:
mbed_official 0:51ac1d130fd4 1567 case TCP_KEEPALIVE:
mbed_official 0:51ac1d130fd4 1568 #if LWIP_TCP_KEEPALIVE
mbed_official 0:51ac1d130fd4 1569 case TCP_KEEPIDLE:
mbed_official 0:51ac1d130fd4 1570 case TCP_KEEPINTVL:
mbed_official 0:51ac1d130fd4 1571 case TCP_KEEPCNT:
mbed_official 0:51ac1d130fd4 1572 #endif /* LWIP_TCP_KEEPALIVE */
mbed_official 0:51ac1d130fd4 1573 break;
mbed_official 0:51ac1d130fd4 1574
mbed_official 0:51ac1d130fd4 1575 default:
mbed_official 0:51ac1d130fd4 1576 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1577 s, optname));
mbed_official 0:51ac1d130fd4 1578 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1579 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1580 break;
mbed_official 0:51ac1d130fd4 1581 #endif /* LWIP_TCP */
mbed_official 0:51ac1d130fd4 1582 #if LWIP_UDP && LWIP_UDPLITE
mbed_official 0:51ac1d130fd4 1583 /* Level: IPPROTO_UDPLITE */
mbed_official 0:51ac1d130fd4 1584 case IPPROTO_UDPLITE:
mbed_official 0:51ac1d130fd4 1585 if (*optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1586 err = EINVAL;
mbed_official 0:51ac1d130fd4 1587 break;
mbed_official 0:51ac1d130fd4 1588 }
mbed_official 0:51ac1d130fd4 1589
mbed_official 0:51ac1d130fd4 1590 /* If this is no UDP lite socket, ignore any options. */
mbed_official 0:51ac1d130fd4 1591 if (sock->conn->type != NETCONN_UDPLITE) {
mbed_official 0:51ac1d130fd4 1592 return 0;
mbed_official 0:51ac1d130fd4 1593 }
mbed_official 0:51ac1d130fd4 1594
mbed_official 0:51ac1d130fd4 1595 switch (optname) {
mbed_official 0:51ac1d130fd4 1596 case UDPLITE_SEND_CSCOV:
mbed_official 0:51ac1d130fd4 1597 case UDPLITE_RECV_CSCOV:
mbed_official 0:51ac1d130fd4 1598 break;
mbed_official 0:51ac1d130fd4 1599
mbed_official 0:51ac1d130fd4 1600 default:
mbed_official 0:51ac1d130fd4 1601 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1602 s, optname));
mbed_official 0:51ac1d130fd4 1603 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1604 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1605 break;
mbed_official 0:51ac1d130fd4 1606 #endif /* LWIP_UDP && LWIP_UDPLITE*/
mbed_official 0:51ac1d130fd4 1607 /* UNDEFINED LEVEL */
mbed_official 0:51ac1d130fd4 1608 default:
mbed_official 0:51ac1d130fd4 1609 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1610 s, level, optname));
mbed_official 0:51ac1d130fd4 1611 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1612 } /* switch */
mbed_official 0:51ac1d130fd4 1613
mbed_official 0:51ac1d130fd4 1614
mbed_official 0:51ac1d130fd4 1615 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 1616 sock_set_errno(sock, err);
mbed_official 0:51ac1d130fd4 1617 return -1;
mbed_official 0:51ac1d130fd4 1618 }
mbed_official 0:51ac1d130fd4 1619
mbed_official 0:51ac1d130fd4 1620 /* Now do the actual option processing */
mbed_official 0:51ac1d130fd4 1621 data.sock = sock;
mbed_official 0:51ac1d130fd4 1622 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 1623 data.s = s;
mbed_official 0:51ac1d130fd4 1624 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 1625 data.level = level;
mbed_official 0:51ac1d130fd4 1626 data.optname = optname;
mbed_official 0:51ac1d130fd4 1627 data.optval = optval;
mbed_official 0:51ac1d130fd4 1628 data.optlen = optlen;
mbed_official 0:51ac1d130fd4 1629 data.err = err;
mbed_official 0:51ac1d130fd4 1630 tcpip_callback(lwip_getsockopt_internal, &data);
mbed_official 0:51ac1d130fd4 1631 sys_arch_sem_wait(&sock->conn->op_completed, 0);
mbed_official 0:51ac1d130fd4 1632 /* maybe lwip_getsockopt_internal has changed err */
mbed_official 0:51ac1d130fd4 1633 err = data.err;
mbed_official 0:51ac1d130fd4 1634
mbed_official 0:51ac1d130fd4 1635 sock_set_errno(sock, err);
mbed_official 0:51ac1d130fd4 1636 return err ? -1 : 0;
mbed_official 0:51ac1d130fd4 1637 }
mbed_official 0:51ac1d130fd4 1638
mbed_official 0:51ac1d130fd4 1639 static void
mbed_official 0:51ac1d130fd4 1640 lwip_getsockopt_internal(void *arg)
mbed_official 0:51ac1d130fd4 1641 {
mbed_official 0:51ac1d130fd4 1642 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 1643 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 1644 int s;
mbed_official 0:51ac1d130fd4 1645 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 1646 int level, optname;
mbed_official 0:51ac1d130fd4 1647 void *optval;
mbed_official 0:51ac1d130fd4 1648 struct lwip_setgetsockopt_data *data;
mbed_official 0:51ac1d130fd4 1649
mbed_official 0:51ac1d130fd4 1650 LWIP_ASSERT("arg != NULL", arg != NULL);
mbed_official 0:51ac1d130fd4 1651
mbed_official 0:51ac1d130fd4 1652 data = (struct lwip_setgetsockopt_data*)arg;
mbed_official 0:51ac1d130fd4 1653 sock = data->sock;
mbed_official 0:51ac1d130fd4 1654 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 1655 s = data->s;
mbed_official 0:51ac1d130fd4 1656 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 1657 level = data->level;
mbed_official 0:51ac1d130fd4 1658 optname = data->optname;
mbed_official 0:51ac1d130fd4 1659 optval = data->optval;
mbed_official 0:51ac1d130fd4 1660
mbed_official 0:51ac1d130fd4 1661 switch (level) {
mbed_official 0:51ac1d130fd4 1662
mbed_official 0:51ac1d130fd4 1663 /* Level: SOL_SOCKET */
mbed_official 0:51ac1d130fd4 1664 case SOL_SOCKET:
mbed_official 0:51ac1d130fd4 1665 switch (optname) {
mbed_official 0:51ac1d130fd4 1666
mbed_official 0:51ac1d130fd4 1667 /* The option flags */
mbed_official 0:51ac1d130fd4 1668 case SO_ACCEPTCONN:
mbed_official 0:51ac1d130fd4 1669 case SO_BROADCAST:
mbed_official 0:51ac1d130fd4 1670 /* UNIMPL case SO_DEBUG: */
mbed_official 0:51ac1d130fd4 1671 /* UNIMPL case SO_DONTROUTE: */
mbed_official 0:51ac1d130fd4 1672 case SO_KEEPALIVE:
mbed_official 0:51ac1d130fd4 1673 /* UNIMPL case SO_OOBINCLUDE: */
mbed_official 0:51ac1d130fd4 1674 #if SO_REUSE
mbed_official 0:51ac1d130fd4 1675 case SO_REUSEADDR:
mbed_official 0:51ac1d130fd4 1676 case SO_REUSEPORT:
mbed_official 0:51ac1d130fd4 1677 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 1678 /*case SO_USELOOPBACK: UNIMPL */
mbed_official 0:51ac1d130fd4 1679 *(int*)optval = sock->conn->pcb.ip->so_options & optname;
mbed_official 0:51ac1d130fd4 1680 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
mbed_official 0:51ac1d130fd4 1681 s, optname, (*(int*)optval?"on":"off")));
mbed_official 0:51ac1d130fd4 1682 break;
mbed_official 0:51ac1d130fd4 1683
mbed_official 0:51ac1d130fd4 1684 case SO_TYPE:
mbed_official 0:51ac1d130fd4 1685 switch (NETCONNTYPE_GROUP(sock->conn->type)) {
mbed_official 0:51ac1d130fd4 1686 case NETCONN_RAW:
mbed_official 0:51ac1d130fd4 1687 *(int*)optval = SOCK_RAW;
mbed_official 0:51ac1d130fd4 1688 break;
mbed_official 0:51ac1d130fd4 1689 case NETCONN_TCP:
mbed_official 0:51ac1d130fd4 1690 *(int*)optval = SOCK_STREAM;
mbed_official 0:51ac1d130fd4 1691 break;
mbed_official 0:51ac1d130fd4 1692 case NETCONN_UDP:
mbed_official 0:51ac1d130fd4 1693 *(int*)optval = SOCK_DGRAM;
mbed_official 0:51ac1d130fd4 1694 break;
mbed_official 0:51ac1d130fd4 1695 default: /* unrecognized socket type */
mbed_official 0:51ac1d130fd4 1696 *(int*)optval = sock->conn->type;
mbed_official 0:51ac1d130fd4 1697 LWIP_DEBUGF(SOCKETS_DEBUG,
mbed_official 0:51ac1d130fd4 1698 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
mbed_official 0:51ac1d130fd4 1699 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1700 } /* switch (sock->conn->type) */
mbed_official 0:51ac1d130fd4 1701 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
mbed_official 0:51ac1d130fd4 1702 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1703 break;
mbed_official 0:51ac1d130fd4 1704
mbed_official 0:51ac1d130fd4 1705 case SO_ERROR:
mbed_official 0:51ac1d130fd4 1706 /* only overwrite ERR_OK or tempoary errors */
mbed_official 0:51ac1d130fd4 1707 if ((sock->err == 0) || (sock->err == EINPROGRESS)) {
mbed_official 0:51ac1d130fd4 1708 sock_set_errno(sock, err_to_errno(sock->conn->last_err));
mbed_official 0:51ac1d130fd4 1709 }
mbed_official 0:51ac1d130fd4 1710 *(int *)optval = sock->err;
mbed_official 0:51ac1d130fd4 1711 sock->err = 0;
mbed_official 0:51ac1d130fd4 1712 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
mbed_official 0:51ac1d130fd4 1713 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1714 break;
mbed_official 0:51ac1d130fd4 1715
mbed_official 0:51ac1d130fd4 1716 #if LWIP_SO_RCVTIMEO
mbed_official 0:51ac1d130fd4 1717 case SO_RCVTIMEO:
mbed_official 0:51ac1d130fd4 1718 *(int *)optval = netconn_get_recvtimeout(sock->conn);
mbed_official 0:51ac1d130fd4 1719 break;
mbed_official 0:51ac1d130fd4 1720 #endif /* LWIP_SO_RCVTIMEO */
mbed_official 0:51ac1d130fd4 1721 #if LWIP_SO_RCVBUF
mbed_official 0:51ac1d130fd4 1722 case SO_RCVBUF:
mbed_official 0:51ac1d130fd4 1723 *(int *)optval = netconn_get_recvbufsize(sock->conn);
mbed_official 0:51ac1d130fd4 1724 break;
mbed_official 0:51ac1d130fd4 1725 #endif /* LWIP_SO_RCVBUF */
mbed_official 0:51ac1d130fd4 1726 #if LWIP_UDP
mbed_official 0:51ac1d130fd4 1727 case SO_NO_CHECK:
mbed_official 0:51ac1d130fd4 1728 *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
mbed_official 0:51ac1d130fd4 1729 break;
mbed_official 0:51ac1d130fd4 1730 #endif /* LWIP_UDP*/
mbed_official 0:51ac1d130fd4 1731 default:
mbed_official 0:51ac1d130fd4 1732 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 1733 break;
mbed_official 0:51ac1d130fd4 1734 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1735 break;
mbed_official 0:51ac1d130fd4 1736
mbed_official 0:51ac1d130fd4 1737 /* Level: IPPROTO_IP */
mbed_official 0:51ac1d130fd4 1738 case IPPROTO_IP:
mbed_official 0:51ac1d130fd4 1739 switch (optname) {
mbed_official 0:51ac1d130fd4 1740 case IP_TTL:
mbed_official 0:51ac1d130fd4 1741 *(int*)optval = sock->conn->pcb.ip->ttl;
mbed_official 0:51ac1d130fd4 1742 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
mbed_official 0:51ac1d130fd4 1743 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1744 break;
mbed_official 0:51ac1d130fd4 1745 case IP_TOS:
mbed_official 0:51ac1d130fd4 1746 *(int*)optval = sock->conn->pcb.ip->tos;
mbed_official 0:51ac1d130fd4 1747 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
mbed_official 0:51ac1d130fd4 1748 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1749 break;
mbed_official 0:51ac1d130fd4 1750 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 1751 case IP_MULTICAST_TTL:
mbed_official 0:51ac1d130fd4 1752 *(u8_t*)optval = sock->conn->pcb.ip->ttl;
mbed_official 0:51ac1d130fd4 1753 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
mbed_official 0:51ac1d130fd4 1754 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1755 break;
mbed_official 0:51ac1d130fd4 1756 case IP_MULTICAST_IF:
mbed_official 0:51ac1d130fd4 1757 inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip);
mbed_official 0:51ac1d130fd4 1758 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
mbed_official 0:51ac1d130fd4 1759 s, *(u32_t *)optval));
mbed_official 0:51ac1d130fd4 1760 break;
mbed_official 0:51ac1d130fd4 1761 case IP_MULTICAST_LOOP:
mbed_official 0:51ac1d130fd4 1762 if ((sock->conn->pcb.udp->flags & UDP_FLAGS_MULTICAST_LOOP) != 0) {
mbed_official 0:51ac1d130fd4 1763 *(u8_t*)optval = 1;
mbed_official 0:51ac1d130fd4 1764 } else {
mbed_official 0:51ac1d130fd4 1765 *(u8_t*)optval = 0;
mbed_official 0:51ac1d130fd4 1766 }
mbed_official 0:51ac1d130fd4 1767 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
mbed_official 0:51ac1d130fd4 1768 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1769 break;
mbed_official 0:51ac1d130fd4 1770 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 1771 default:
mbed_official 0:51ac1d130fd4 1772 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 1773 break;
mbed_official 0:51ac1d130fd4 1774 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1775 break;
mbed_official 0:51ac1d130fd4 1776
mbed_official 0:51ac1d130fd4 1777 #if LWIP_TCP
mbed_official 0:51ac1d130fd4 1778 /* Level: IPPROTO_TCP */
mbed_official 0:51ac1d130fd4 1779 case IPPROTO_TCP:
mbed_official 0:51ac1d130fd4 1780 switch (optname) {
mbed_official 0:51ac1d130fd4 1781 case TCP_NODELAY:
mbed_official 0:51ac1d130fd4 1782 *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
mbed_official 0:51ac1d130fd4 1783 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
mbed_official 0:51ac1d130fd4 1784 s, (*(int*)optval)?"on":"off") );
mbed_official 0:51ac1d130fd4 1785 break;
mbed_official 0:51ac1d130fd4 1786 case TCP_KEEPALIVE:
mbed_official 0:51ac1d130fd4 1787 *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
mbed_official 0:51ac1d130fd4 1788 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
mbed_official 0:51ac1d130fd4 1789 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1790 break;
mbed_official 0:51ac1d130fd4 1791
mbed_official 0:51ac1d130fd4 1792 #if LWIP_TCP_KEEPALIVE
mbed_official 0:51ac1d130fd4 1793 case TCP_KEEPIDLE:
mbed_official 0:51ac1d130fd4 1794 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
mbed_official 0:51ac1d130fd4 1795 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
mbed_official 0:51ac1d130fd4 1796 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1797 break;
mbed_official 0:51ac1d130fd4 1798 case TCP_KEEPINTVL:
mbed_official 0:51ac1d130fd4 1799 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
mbed_official 0:51ac1d130fd4 1800 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
mbed_official 0:51ac1d130fd4 1801 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1802 break;
mbed_official 0:51ac1d130fd4 1803 case TCP_KEEPCNT:
mbed_official 0:51ac1d130fd4 1804 *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
mbed_official 0:51ac1d130fd4 1805 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
mbed_official 0:51ac1d130fd4 1806 s, *(int *)optval));
mbed_official 0:51ac1d130fd4 1807 break;
mbed_official 0:51ac1d130fd4 1808 #endif /* LWIP_TCP_KEEPALIVE */
mbed_official 0:51ac1d130fd4 1809 default:
mbed_official 0:51ac1d130fd4 1810 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 1811 break;
mbed_official 0:51ac1d130fd4 1812 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1813 break;
mbed_official 0:51ac1d130fd4 1814 #endif /* LWIP_TCP */
mbed_official 0:51ac1d130fd4 1815 #if LWIP_UDP && LWIP_UDPLITE
mbed_official 0:51ac1d130fd4 1816 /* Level: IPPROTO_UDPLITE */
mbed_official 0:51ac1d130fd4 1817 case IPPROTO_UDPLITE:
mbed_official 0:51ac1d130fd4 1818 switch (optname) {
mbed_official 0:51ac1d130fd4 1819 case UDPLITE_SEND_CSCOV:
mbed_official 0:51ac1d130fd4 1820 *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
mbed_official 0:51ac1d130fd4 1821 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
mbed_official 0:51ac1d130fd4 1822 s, (*(int*)optval)) );
mbed_official 0:51ac1d130fd4 1823 break;
mbed_official 0:51ac1d130fd4 1824 case UDPLITE_RECV_CSCOV:
mbed_official 0:51ac1d130fd4 1825 *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
mbed_official 0:51ac1d130fd4 1826 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
mbed_official 0:51ac1d130fd4 1827 s, (*(int*)optval)) );
mbed_official 0:51ac1d130fd4 1828 break;
mbed_official 0:51ac1d130fd4 1829 default:
mbed_official 0:51ac1d130fd4 1830 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 1831 break;
mbed_official 0:51ac1d130fd4 1832 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1833 break;
mbed_official 0:51ac1d130fd4 1834 #endif /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 1835 default:
mbed_official 0:51ac1d130fd4 1836 LWIP_ASSERT("unhandled level", 0);
mbed_official 0:51ac1d130fd4 1837 break;
mbed_official 0:51ac1d130fd4 1838 } /* switch (level) */
mbed_official 0:51ac1d130fd4 1839 sys_sem_signal(&sock->conn->op_completed);
mbed_official 0:51ac1d130fd4 1840 }
mbed_official 0:51ac1d130fd4 1841
mbed_official 0:51ac1d130fd4 1842 int
mbed_official 0:51ac1d130fd4 1843 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
mbed_official 0:51ac1d130fd4 1844 {
mbed_official 0:51ac1d130fd4 1845 struct lwip_sock *sock = get_socket(s);
mbed_official 0:51ac1d130fd4 1846 err_t err = ERR_OK;
mbed_official 0:51ac1d130fd4 1847 struct lwip_setgetsockopt_data data;
mbed_official 0:51ac1d130fd4 1848
mbed_official 0:51ac1d130fd4 1849 if (!sock) {
mbed_official 0:51ac1d130fd4 1850 return -1;
mbed_official 0:51ac1d130fd4 1851 }
mbed_official 0:51ac1d130fd4 1852
mbed_official 0:51ac1d130fd4 1853 if (NULL == optval) {
mbed_official 0:51ac1d130fd4 1854 sock_set_errno(sock, EFAULT);
mbed_official 0:51ac1d130fd4 1855 return -1;
mbed_official 0:51ac1d130fd4 1856 }
mbed_official 0:51ac1d130fd4 1857
mbed_official 0:51ac1d130fd4 1858 /* Do length and type checks for the various options first, to keep it readable. */
mbed_official 0:51ac1d130fd4 1859 switch (level) {
mbed_official 0:51ac1d130fd4 1860
mbed_official 0:51ac1d130fd4 1861 /* Level: SOL_SOCKET */
mbed_official 0:51ac1d130fd4 1862 case SOL_SOCKET:
mbed_official 0:51ac1d130fd4 1863 switch (optname) {
mbed_official 0:51ac1d130fd4 1864
mbed_official 0:51ac1d130fd4 1865 case SO_BROADCAST:
mbed_official 0:51ac1d130fd4 1866 /* UNIMPL case SO_DEBUG: */
mbed_official 0:51ac1d130fd4 1867 /* UNIMPL case SO_DONTROUTE: */
mbed_official 0:51ac1d130fd4 1868 case SO_KEEPALIVE:
mbed_official 0:51ac1d130fd4 1869 /* UNIMPL case case SO_CONTIMEO: */
mbed_official 0:51ac1d130fd4 1870 /* UNIMPL case case SO_SNDTIMEO: */
mbed_official 0:51ac1d130fd4 1871 #if LWIP_SO_RCVTIMEO
mbed_official 0:51ac1d130fd4 1872 case SO_RCVTIMEO:
mbed_official 0:51ac1d130fd4 1873 #endif /* LWIP_SO_RCVTIMEO */
mbed_official 0:51ac1d130fd4 1874 #if LWIP_SO_RCVBUF
mbed_official 0:51ac1d130fd4 1875 case SO_RCVBUF:
mbed_official 0:51ac1d130fd4 1876 #endif /* LWIP_SO_RCVBUF */
mbed_official 0:51ac1d130fd4 1877 /* UNIMPL case SO_OOBINLINE: */
mbed_official 0:51ac1d130fd4 1878 /* UNIMPL case SO_SNDBUF: */
mbed_official 0:51ac1d130fd4 1879 /* UNIMPL case SO_RCVLOWAT: */
mbed_official 0:51ac1d130fd4 1880 /* UNIMPL case SO_SNDLOWAT: */
mbed_official 0:51ac1d130fd4 1881 #if SO_REUSE
mbed_official 0:51ac1d130fd4 1882 case SO_REUSEADDR:
mbed_official 0:51ac1d130fd4 1883 case SO_REUSEPORT:
mbed_official 0:51ac1d130fd4 1884 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 1885 /* UNIMPL case SO_USELOOPBACK: */
mbed_official 0:51ac1d130fd4 1886 if (optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1887 err = EINVAL;
mbed_official 0:51ac1d130fd4 1888 }
mbed_official 0:51ac1d130fd4 1889 break;
mbed_official 0:51ac1d130fd4 1890 case SO_NO_CHECK:
mbed_official 0:51ac1d130fd4 1891 if (optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1892 err = EINVAL;
mbed_official 0:51ac1d130fd4 1893 }
mbed_official 0:51ac1d130fd4 1894 #if LWIP_UDP
mbed_official 0:51ac1d130fd4 1895 if ((sock->conn->type != NETCONN_UDP) ||
mbed_official 0:51ac1d130fd4 1896 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
mbed_official 0:51ac1d130fd4 1897 /* this flag is only available for UDP, not for UDP lite */
mbed_official 0:51ac1d130fd4 1898 err = EAFNOSUPPORT;
mbed_official 0:51ac1d130fd4 1899 }
mbed_official 0:51ac1d130fd4 1900 #endif /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 1901 break;
mbed_official 0:51ac1d130fd4 1902 default:
mbed_official 0:51ac1d130fd4 1903 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1904 s, optname));
mbed_official 0:51ac1d130fd4 1905 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1906 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1907 break;
mbed_official 0:51ac1d130fd4 1908
mbed_official 0:51ac1d130fd4 1909 /* Level: IPPROTO_IP */
mbed_official 0:51ac1d130fd4 1910 case IPPROTO_IP:
mbed_official 0:51ac1d130fd4 1911 switch (optname) {
mbed_official 0:51ac1d130fd4 1912 /* UNIMPL case IP_HDRINCL: */
mbed_official 0:51ac1d130fd4 1913 /* UNIMPL case IP_RCVDSTADDR: */
mbed_official 0:51ac1d130fd4 1914 /* UNIMPL case IP_RCVIF: */
mbed_official 0:51ac1d130fd4 1915 case IP_TTL:
mbed_official 0:51ac1d130fd4 1916 case IP_TOS:
mbed_official 0:51ac1d130fd4 1917 if (optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1918 err = EINVAL;
mbed_official 0:51ac1d130fd4 1919 }
mbed_official 0:51ac1d130fd4 1920 break;
mbed_official 0:51ac1d130fd4 1921 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 1922 case IP_MULTICAST_TTL:
mbed_official 0:51ac1d130fd4 1923 if (optlen < sizeof(u8_t)) {
mbed_official 0:51ac1d130fd4 1924 err = EINVAL;
mbed_official 0:51ac1d130fd4 1925 }
mbed_official 0:51ac1d130fd4 1926 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
mbed_official 0:51ac1d130fd4 1927 err = EAFNOSUPPORT;
mbed_official 0:51ac1d130fd4 1928 }
mbed_official 0:51ac1d130fd4 1929 break;
mbed_official 0:51ac1d130fd4 1930 case IP_MULTICAST_IF:
mbed_official 0:51ac1d130fd4 1931 if (optlen < sizeof(struct in_addr)) {
mbed_official 0:51ac1d130fd4 1932 err = EINVAL;
mbed_official 0:51ac1d130fd4 1933 }
mbed_official 0:51ac1d130fd4 1934 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
mbed_official 0:51ac1d130fd4 1935 err = EAFNOSUPPORT;
mbed_official 0:51ac1d130fd4 1936 }
mbed_official 0:51ac1d130fd4 1937 break;
mbed_official 0:51ac1d130fd4 1938 case IP_MULTICAST_LOOP:
mbed_official 0:51ac1d130fd4 1939 if (optlen < sizeof(u8_t)) {
mbed_official 0:51ac1d130fd4 1940 err = EINVAL;
mbed_official 0:51ac1d130fd4 1941 }
mbed_official 0:51ac1d130fd4 1942 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
mbed_official 0:51ac1d130fd4 1943 err = EAFNOSUPPORT;
mbed_official 0:51ac1d130fd4 1944 }
mbed_official 0:51ac1d130fd4 1945 break;
mbed_official 0:51ac1d130fd4 1946 case IP_ADD_MEMBERSHIP:
mbed_official 0:51ac1d130fd4 1947 case IP_DROP_MEMBERSHIP:
mbed_official 0:51ac1d130fd4 1948 if (optlen < sizeof(struct ip_mreq)) {
mbed_official 0:51ac1d130fd4 1949 err = EINVAL;
mbed_official 0:51ac1d130fd4 1950 }
mbed_official 0:51ac1d130fd4 1951 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
mbed_official 0:51ac1d130fd4 1952 err = EAFNOSUPPORT;
mbed_official 0:51ac1d130fd4 1953 }
mbed_official 0:51ac1d130fd4 1954 break;
mbed_official 0:51ac1d130fd4 1955 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 1956 default:
mbed_official 0:51ac1d130fd4 1957 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1958 s, optname));
mbed_official 0:51ac1d130fd4 1959 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1960 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1961 break;
mbed_official 0:51ac1d130fd4 1962
mbed_official 0:51ac1d130fd4 1963 #if LWIP_TCP
mbed_official 0:51ac1d130fd4 1964 /* Level: IPPROTO_TCP */
mbed_official 0:51ac1d130fd4 1965 case IPPROTO_TCP:
mbed_official 0:51ac1d130fd4 1966 if (optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1967 err = EINVAL;
mbed_official 0:51ac1d130fd4 1968 break;
mbed_official 0:51ac1d130fd4 1969 }
mbed_official 0:51ac1d130fd4 1970
mbed_official 0:51ac1d130fd4 1971 /* If this is no TCP socket, ignore any options. */
mbed_official 0:51ac1d130fd4 1972 if (sock->conn->type != NETCONN_TCP)
mbed_official 0:51ac1d130fd4 1973 return 0;
mbed_official 0:51ac1d130fd4 1974
mbed_official 0:51ac1d130fd4 1975 switch (optname) {
mbed_official 0:51ac1d130fd4 1976 case TCP_NODELAY:
mbed_official 0:51ac1d130fd4 1977 case TCP_KEEPALIVE:
mbed_official 0:51ac1d130fd4 1978 #if LWIP_TCP_KEEPALIVE
mbed_official 0:51ac1d130fd4 1979 case TCP_KEEPIDLE:
mbed_official 0:51ac1d130fd4 1980 case TCP_KEEPINTVL:
mbed_official 0:51ac1d130fd4 1981 case TCP_KEEPCNT:
mbed_official 0:51ac1d130fd4 1982 #endif /* LWIP_TCP_KEEPALIVE */
mbed_official 0:51ac1d130fd4 1983 break;
mbed_official 0:51ac1d130fd4 1984
mbed_official 0:51ac1d130fd4 1985 default:
mbed_official 0:51ac1d130fd4 1986 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 1987 s, optname));
mbed_official 0:51ac1d130fd4 1988 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 1989 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 1990 break;
mbed_official 0:51ac1d130fd4 1991 #endif /* LWIP_TCP */
mbed_official 0:51ac1d130fd4 1992 #if LWIP_UDP && LWIP_UDPLITE
mbed_official 0:51ac1d130fd4 1993 /* Level: IPPROTO_UDPLITE */
mbed_official 0:51ac1d130fd4 1994 case IPPROTO_UDPLITE:
mbed_official 0:51ac1d130fd4 1995 if (optlen < sizeof(int)) {
mbed_official 0:51ac1d130fd4 1996 err = EINVAL;
mbed_official 0:51ac1d130fd4 1997 break;
mbed_official 0:51ac1d130fd4 1998 }
mbed_official 0:51ac1d130fd4 1999
mbed_official 0:51ac1d130fd4 2000 /* If this is no UDP lite socket, ignore any options. */
mbed_official 0:51ac1d130fd4 2001 if (sock->conn->type != NETCONN_UDPLITE)
mbed_official 0:51ac1d130fd4 2002 return 0;
mbed_official 0:51ac1d130fd4 2003
mbed_official 0:51ac1d130fd4 2004 switch (optname) {
mbed_official 0:51ac1d130fd4 2005 case UDPLITE_SEND_CSCOV:
mbed_official 0:51ac1d130fd4 2006 case UDPLITE_RECV_CSCOV:
mbed_official 0:51ac1d130fd4 2007 break;
mbed_official 0:51ac1d130fd4 2008
mbed_official 0:51ac1d130fd4 2009 default:
mbed_official 0:51ac1d130fd4 2010 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 2011 s, optname));
mbed_official 0:51ac1d130fd4 2012 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 2013 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 2014 break;
mbed_official 0:51ac1d130fd4 2015 #endif /* LWIP_UDP && LWIP_UDPLITE */
mbed_official 0:51ac1d130fd4 2016 /* UNDEFINED LEVEL */
mbed_official 0:51ac1d130fd4 2017 default:
mbed_official 0:51ac1d130fd4 2018 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
mbed_official 0:51ac1d130fd4 2019 s, level, optname));
mbed_official 0:51ac1d130fd4 2020 err = ENOPROTOOPT;
mbed_official 0:51ac1d130fd4 2021 } /* switch (level) */
mbed_official 0:51ac1d130fd4 2022
mbed_official 0:51ac1d130fd4 2023
mbed_official 0:51ac1d130fd4 2024 if (err != ERR_OK) {
mbed_official 0:51ac1d130fd4 2025 sock_set_errno(sock, err);
mbed_official 0:51ac1d130fd4 2026 return -1;
mbed_official 0:51ac1d130fd4 2027 }
mbed_official 0:51ac1d130fd4 2028
mbed_official 0:51ac1d130fd4 2029
mbed_official 0:51ac1d130fd4 2030 /* Now do the actual option processing */
mbed_official 0:51ac1d130fd4 2031 data.sock = sock;
mbed_official 0:51ac1d130fd4 2032 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 2033 data.s = s;
mbed_official 0:51ac1d130fd4 2034 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 2035 data.level = level;
mbed_official 0:51ac1d130fd4 2036 data.optname = optname;
mbed_official 0:51ac1d130fd4 2037 data.optval = (void*)optval;
mbed_official 0:51ac1d130fd4 2038 data.optlen = &optlen;
mbed_official 0:51ac1d130fd4 2039 data.err = err;
mbed_official 0:51ac1d130fd4 2040 tcpip_callback(lwip_setsockopt_internal, &data);
mbed_official 0:51ac1d130fd4 2041 sys_arch_sem_wait(&sock->conn->op_completed, 0);
mbed_official 0:51ac1d130fd4 2042 /* maybe lwip_setsockopt_internal has changed err */
mbed_official 0:51ac1d130fd4 2043 err = data.err;
mbed_official 0:51ac1d130fd4 2044
mbed_official 0:51ac1d130fd4 2045 sock_set_errno(sock, err);
mbed_official 0:51ac1d130fd4 2046 return err ? -1 : 0;
mbed_official 0:51ac1d130fd4 2047 }
mbed_official 0:51ac1d130fd4 2048
mbed_official 0:51ac1d130fd4 2049 static void
mbed_official 0:51ac1d130fd4 2050 lwip_setsockopt_internal(void *arg)
mbed_official 0:51ac1d130fd4 2051 {
mbed_official 0:51ac1d130fd4 2052 struct lwip_sock *sock;
mbed_official 0:51ac1d130fd4 2053 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 2054 int s;
mbed_official 0:51ac1d130fd4 2055 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 2056 int level, optname;
mbed_official 0:51ac1d130fd4 2057 const void *optval;
mbed_official 0:51ac1d130fd4 2058 struct lwip_setgetsockopt_data *data;
mbed_official 0:51ac1d130fd4 2059
mbed_official 0:51ac1d130fd4 2060 LWIP_ASSERT("arg != NULL", arg != NULL);
mbed_official 0:51ac1d130fd4 2061
mbed_official 0:51ac1d130fd4 2062 data = (struct lwip_setgetsockopt_data*)arg;
mbed_official 0:51ac1d130fd4 2063 sock = data->sock;
mbed_official 0:51ac1d130fd4 2064 #ifdef LWIP_DEBUG
mbed_official 0:51ac1d130fd4 2065 s = data->s;
mbed_official 0:51ac1d130fd4 2066 #endif /* LWIP_DEBUG */
mbed_official 0:51ac1d130fd4 2067 level = data->level;
mbed_official 0:51ac1d130fd4 2068 optname = data->optname;
mbed_official 0:51ac1d130fd4 2069 optval = data->optval;
mbed_official 0:51ac1d130fd4 2070
mbed_official 0:51ac1d130fd4 2071 switch (level) {
mbed_official 0:51ac1d130fd4 2072
mbed_official 0:51ac1d130fd4 2073 /* Level: SOL_SOCKET */
mbed_official 0:51ac1d130fd4 2074 case SOL_SOCKET:
mbed_official 0:51ac1d130fd4 2075 switch (optname) {
mbed_official 0:51ac1d130fd4 2076
mbed_official 0:51ac1d130fd4 2077 /* The option flags */
mbed_official 0:51ac1d130fd4 2078 case SO_BROADCAST:
mbed_official 0:51ac1d130fd4 2079 /* UNIMPL case SO_DEBUG: */
mbed_official 0:51ac1d130fd4 2080 /* UNIMPL case SO_DONTROUTE: */
mbed_official 0:51ac1d130fd4 2081 case SO_KEEPALIVE:
mbed_official 0:51ac1d130fd4 2082 /* UNIMPL case SO_OOBINCLUDE: */
mbed_official 0:51ac1d130fd4 2083 #if SO_REUSE
mbed_official 0:51ac1d130fd4 2084 case SO_REUSEADDR:
mbed_official 0:51ac1d130fd4 2085 case SO_REUSEPORT:
mbed_official 0:51ac1d130fd4 2086 #endif /* SO_REUSE */
mbed_official 0:51ac1d130fd4 2087 /* UNIMPL case SO_USELOOPBACK: */
mbed_official 0:51ac1d130fd4 2088 if (*(int*)optval) {
mbed_official 0:51ac1d130fd4 2089 sock->conn->pcb.ip->so_options |= optname;
mbed_official 0:51ac1d130fd4 2090 } else {
mbed_official 0:51ac1d130fd4 2091 sock->conn->pcb.ip->so_options &= ~optname;
mbed_official 0:51ac1d130fd4 2092 }
mbed_official 0:51ac1d130fd4 2093 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
mbed_official 0:51ac1d130fd4 2094 s, optname, (*(int*)optval?"on":"off")));
mbed_official 0:51ac1d130fd4 2095 break;
mbed_official 0:51ac1d130fd4 2096 #if LWIP_SO_RCVTIMEO
mbed_official 0:51ac1d130fd4 2097 case SO_RCVTIMEO:
mbed_official 0:51ac1d130fd4 2098 netconn_set_recvtimeout(sock->conn, *(int*)optval);
mbed_official 0:51ac1d130fd4 2099 break;
mbed_official 0:51ac1d130fd4 2100 #endif /* LWIP_SO_RCVTIMEO */
mbed_official 0:51ac1d130fd4 2101 #if LWIP_SO_RCVBUF
mbed_official 0:51ac1d130fd4 2102 case SO_RCVBUF:
mbed_official 0:51ac1d130fd4 2103 netconn_set_recvbufsize(sock->conn, *(int*)optval);
mbed_official 0:51ac1d130fd4 2104 break;
mbed_official 0:51ac1d130fd4 2105 #endif /* LWIP_SO_RCVBUF */
mbed_official 0:51ac1d130fd4 2106 #if LWIP_UDP
mbed_official 0:51ac1d130fd4 2107 case SO_NO_CHECK:
mbed_official 0:51ac1d130fd4 2108 if (*(int*)optval) {
mbed_official 0:51ac1d130fd4 2109 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
mbed_official 0:51ac1d130fd4 2110 } else {
mbed_official 0:51ac1d130fd4 2111 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
mbed_official 0:51ac1d130fd4 2112 }
mbed_official 0:51ac1d130fd4 2113 break;
mbed_official 0:51ac1d130fd4 2114 #endif /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 2115 default:
mbed_official 0:51ac1d130fd4 2116 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 2117 break;
mbed_official 0:51ac1d130fd4 2118 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 2119 break;
mbed_official 0:51ac1d130fd4 2120
mbed_official 0:51ac1d130fd4 2121 /* Level: IPPROTO_IP */
mbed_official 0:51ac1d130fd4 2122 case IPPROTO_IP:
mbed_official 0:51ac1d130fd4 2123 switch (optname) {
mbed_official 0:51ac1d130fd4 2124 case IP_TTL:
mbed_official 0:51ac1d130fd4 2125 sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
mbed_official 0:51ac1d130fd4 2126 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
mbed_official 0:51ac1d130fd4 2127 s, sock->conn->pcb.ip->ttl));
mbed_official 0:51ac1d130fd4 2128 break;
mbed_official 0:51ac1d130fd4 2129 case IP_TOS:
mbed_official 0:51ac1d130fd4 2130 sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
mbed_official 0:51ac1d130fd4 2131 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
mbed_official 0:51ac1d130fd4 2132 s, sock->conn->pcb.ip->tos));
mbed_official 0:51ac1d130fd4 2133 break;
mbed_official 0:51ac1d130fd4 2134 #if LWIP_IGMP
mbed_official 0:51ac1d130fd4 2135 case IP_MULTICAST_TTL:
mbed_official 0:51ac1d130fd4 2136 sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
mbed_official 0:51ac1d130fd4 2137 break;
mbed_official 0:51ac1d130fd4 2138 case IP_MULTICAST_IF:
mbed_official 0:51ac1d130fd4 2139 inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval);
mbed_official 0:51ac1d130fd4 2140 break;
mbed_official 0:51ac1d130fd4 2141 case IP_MULTICAST_LOOP:
mbed_official 0:51ac1d130fd4 2142 if (*(u8_t*)optval) {
mbed_official 0:51ac1d130fd4 2143 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_MULTICAST_LOOP);
mbed_official 0:51ac1d130fd4 2144 } else {
mbed_official 0:51ac1d130fd4 2145 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_MULTICAST_LOOP);
mbed_official 0:51ac1d130fd4 2146 }
mbed_official 0:51ac1d130fd4 2147 break;
mbed_official 0:51ac1d130fd4 2148 case IP_ADD_MEMBERSHIP:
mbed_official 0:51ac1d130fd4 2149 case IP_DROP_MEMBERSHIP:
mbed_official 0:51ac1d130fd4 2150 {
mbed_official 0:51ac1d130fd4 2151 /* If this is a TCP or a RAW socket, ignore these options. */
mbed_official 0:51ac1d130fd4 2152 struct ip_mreq *imr = (struct ip_mreq *)optval;
mbed_official 0:51ac1d130fd4 2153 ip_addr_t if_addr;
mbed_official 0:51ac1d130fd4 2154 ip_addr_t multi_addr;
mbed_official 0:51ac1d130fd4 2155 inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
mbed_official 0:51ac1d130fd4 2156 inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
mbed_official 0:51ac1d130fd4 2157 if(optname == IP_ADD_MEMBERSHIP){
mbed_official 0:51ac1d130fd4 2158 data->err = igmp_joingroup(&if_addr, &multi_addr);
mbed_official 0:51ac1d130fd4 2159 } else {
mbed_official 0:51ac1d130fd4 2160 data->err = igmp_leavegroup(&if_addr, &multi_addr);
mbed_official 0:51ac1d130fd4 2161 }
mbed_official 0:51ac1d130fd4 2162 if(data->err != ERR_OK) {
mbed_official 0:51ac1d130fd4 2163 data->err = EADDRNOTAVAIL;
mbed_official 0:51ac1d130fd4 2164 }
mbed_official 0:51ac1d130fd4 2165 }
mbed_official 0:51ac1d130fd4 2166 break;
mbed_official 0:51ac1d130fd4 2167 #endif /* LWIP_IGMP */
mbed_official 0:51ac1d130fd4 2168 default:
mbed_official 0:51ac1d130fd4 2169 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 2170 break;
mbed_official 0:51ac1d130fd4 2171 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 2172 break;
mbed_official 0:51ac1d130fd4 2173
mbed_official 0:51ac1d130fd4 2174 #if LWIP_TCP
mbed_official 0:51ac1d130fd4 2175 /* Level: IPPROTO_TCP */
mbed_official 0:51ac1d130fd4 2176 case IPPROTO_TCP:
mbed_official 0:51ac1d130fd4 2177 switch (optname) {
mbed_official 0:51ac1d130fd4 2178 case TCP_NODELAY:
mbed_official 0:51ac1d130fd4 2179 if (*(int*)optval) {
mbed_official 0:51ac1d130fd4 2180 tcp_nagle_disable(sock->conn->pcb.tcp);
mbed_official 0:51ac1d130fd4 2181 } else {
mbed_official 0:51ac1d130fd4 2182 tcp_nagle_enable(sock->conn->pcb.tcp);
mbed_official 0:51ac1d130fd4 2183 }
mbed_official 0:51ac1d130fd4 2184 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
mbed_official 0:51ac1d130fd4 2185 s, (*(int *)optval)?"on":"off") );
mbed_official 0:51ac1d130fd4 2186 break;
mbed_official 0:51ac1d130fd4 2187 case TCP_KEEPALIVE:
mbed_official 0:51ac1d130fd4 2188 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
mbed_official 0:51ac1d130fd4 2189 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
mbed_official 0:51ac1d130fd4 2190 s, sock->conn->pcb.tcp->keep_idle));
mbed_official 0:51ac1d130fd4 2191 break;
mbed_official 0:51ac1d130fd4 2192
mbed_official 0:51ac1d130fd4 2193 #if LWIP_TCP_KEEPALIVE
mbed_official 0:51ac1d130fd4 2194 case TCP_KEEPIDLE:
mbed_official 0:51ac1d130fd4 2195 sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
mbed_official 0:51ac1d130fd4 2196 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
mbed_official 0:51ac1d130fd4 2197 s, sock->conn->pcb.tcp->keep_idle));
mbed_official 0:51ac1d130fd4 2198 break;
mbed_official 0:51ac1d130fd4 2199 case TCP_KEEPINTVL:
mbed_official 0:51ac1d130fd4 2200 sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
mbed_official 0:51ac1d130fd4 2201 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
mbed_official 0:51ac1d130fd4 2202 s, sock->conn->pcb.tcp->keep_intvl));
mbed_official 0:51ac1d130fd4 2203 break;
mbed_official 0:51ac1d130fd4 2204 case TCP_KEEPCNT:
mbed_official 0:51ac1d130fd4 2205 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
mbed_official 0:51ac1d130fd4 2206 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
mbed_official 0:51ac1d130fd4 2207 s, sock->conn->pcb.tcp->keep_cnt));
mbed_official 0:51ac1d130fd4 2208 break;
mbed_official 0:51ac1d130fd4 2209 #endif /* LWIP_TCP_KEEPALIVE */
mbed_official 0:51ac1d130fd4 2210 default:
mbed_official 0:51ac1d130fd4 2211 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 2212 break;
mbed_official 0:51ac1d130fd4 2213 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 2214 break;
mbed_official 0:51ac1d130fd4 2215 #endif /* LWIP_TCP*/
mbed_official 0:51ac1d130fd4 2216 #if LWIP_UDP && LWIP_UDPLITE
mbed_official 0:51ac1d130fd4 2217 /* Level: IPPROTO_UDPLITE */
mbed_official 0:51ac1d130fd4 2218 case IPPROTO_UDPLITE:
mbed_official 0:51ac1d130fd4 2219 switch (optname) {
mbed_official 0:51ac1d130fd4 2220 case UDPLITE_SEND_CSCOV:
mbed_official 0:51ac1d130fd4 2221 if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
mbed_official 0:51ac1d130fd4 2222 /* don't allow illegal values! */
mbed_official 0:51ac1d130fd4 2223 sock->conn->pcb.udp->chksum_len_tx = 8;
mbed_official 0:51ac1d130fd4 2224 } else {
mbed_official 0:51ac1d130fd4 2225 sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval;
mbed_official 0:51ac1d130fd4 2226 }
mbed_official 0:51ac1d130fd4 2227 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
mbed_official 0:51ac1d130fd4 2228 s, (*(int*)optval)) );
mbed_official 0:51ac1d130fd4 2229 break;
mbed_official 0:51ac1d130fd4 2230 case UDPLITE_RECV_CSCOV:
mbed_official 0:51ac1d130fd4 2231 if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
mbed_official 0:51ac1d130fd4 2232 /* don't allow illegal values! */
mbed_official 0:51ac1d130fd4 2233 sock->conn->pcb.udp->chksum_len_rx = 8;
mbed_official 0:51ac1d130fd4 2234 } else {
mbed_official 0:51ac1d130fd4 2235 sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval;
mbed_official 0:51ac1d130fd4 2236 }
mbed_official 0:51ac1d130fd4 2237 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
mbed_official 0:51ac1d130fd4 2238 s, (*(int*)optval)) );
mbed_official 0:51ac1d130fd4 2239 break;
mbed_official 0:51ac1d130fd4 2240 default:
mbed_official 0:51ac1d130fd4 2241 LWIP_ASSERT("unhandled optname", 0);
mbed_official 0:51ac1d130fd4 2242 break;
mbed_official 0:51ac1d130fd4 2243 } /* switch (optname) */
mbed_official 0:51ac1d130fd4 2244 break;
mbed_official 0:51ac1d130fd4 2245 #endif /* LWIP_UDP */
mbed_official 0:51ac1d130fd4 2246 default:
mbed_official 0:51ac1d130fd4 2247 LWIP_ASSERT("unhandled level", 0);
mbed_official 0:51ac1d130fd4 2248 break;
mbed_official 0:51ac1d130fd4 2249 } /* switch (level) */
mbed_official 0:51ac1d130fd4 2250 sys_sem_signal(&sock->conn->op_completed);
mbed_official 0:51ac1d130fd4 2251 }
mbed_official 0:51ac1d130fd4 2252
mbed_official 0:51ac1d130fd4 2253 int
mbed_official 0:51ac1d130fd4 2254 lwip_ioctl(int s, long cmd, void *argp)
mbed_official 0:51ac1d130fd4 2255 {
mbed_official 0:51ac1d130fd4 2256 struct lwip_sock *sock = get_socket(s);
mbed_official 0:51ac1d130fd4 2257 u8_t val;
mbed_official 0:51ac1d130fd4 2258 #if LWIP_SO_RCVBUF
mbed_official 0:51ac1d130fd4 2259 u16_t buflen = 0;
mbed_official 0:51ac1d130fd4 2260 s16_t recv_avail;
mbed_official 0:51ac1d130fd4 2261 #endif /* LWIP_SO_RCVBUF */
mbed_official 0:51ac1d130fd4 2262
mbed_official 0:51ac1d130fd4 2263 if (!sock) {
mbed_official 0:51ac1d130fd4 2264 return -1;
mbed_official 0:51ac1d130fd4 2265 }
mbed_official 0:51ac1d130fd4 2266
mbed_official 0:51ac1d130fd4 2267 switch (cmd) {
mbed_official 0:51ac1d130fd4 2268 #if LWIP_SO_RCVBUF
mbed_official 0:51ac1d130fd4 2269 case FIONREAD:
mbed_official 0:51ac1d130fd4 2270 if (!argp) {
mbed_official 0:51ac1d130fd4 2271 sock_set_errno(sock, EINVAL);
mbed_official 0:51ac1d130fd4 2272 return -1;
mbed_official 0:51ac1d130fd4 2273 }
mbed_official 0:51ac1d130fd4 2274
mbed_official 0:51ac1d130fd4 2275 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
mbed_official 0:51ac1d130fd4 2276 if (recv_avail < 0) {
mbed_official 0:51ac1d130fd4 2277 recv_avail = 0;
mbed_official 0:51ac1d130fd4 2278 }
mbed_official 0:51ac1d130fd4 2279 *((u16_t*)argp) = (u16_t)recv_avail;
mbed_official 0:51ac1d130fd4 2280
mbed_official 0:51ac1d130fd4 2281 /* Check if there is data left from the last recv operation. /maq 041215 */
mbed_official 0:51ac1d130fd4 2282 if (sock->lastdata) {
mbed_official 0:51ac1d130fd4 2283 struct pbuf *p = (struct pbuf *)sock->lastdata;
mbed_official 0:51ac1d130fd4 2284 if (netconn_type(sock->conn) != NETCONN_TCP) {
mbed_official 0:51ac1d130fd4 2285 p = ((struct netbuf *)p)->p;
mbed_official 0:51ac1d130fd4 2286 }
mbed_official 0:51ac1d130fd4 2287 buflen = p->tot_len;
mbed_official 0:51ac1d130fd4 2288 buflen -= sock->lastoffset;
mbed_official 0:51ac1d130fd4 2289
mbed_official 0:51ac1d130fd4 2290 *((u16_t*)argp) += buflen;
mbed_official 0:51ac1d130fd4 2291 }
mbed_official 0:51ac1d130fd4 2292
mbed_official 0:51ac1d130fd4 2293 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
mbed_official 0:51ac1d130fd4 2294 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 2295 return 0;
mbed_official 0:51ac1d130fd4 2296 #endif /* LWIP_SO_RCVBUF */
mbed_official 0:51ac1d130fd4 2297
mbed_official 0:51ac1d130fd4 2298 case FIONBIO:
mbed_official 0:51ac1d130fd4 2299 val = 0;
mbed_official 0:51ac1d130fd4 2300 if (argp && *(u32_t*)argp) {
mbed_official 0:51ac1d130fd4 2301 val = 1;
mbed_official 0:51ac1d130fd4 2302 }
mbed_official 0:51ac1d130fd4 2303 netconn_set_nonblocking(sock->conn, val);
mbed_official 0:51ac1d130fd4 2304 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
mbed_official 0:51ac1d130fd4 2305 sock_set_errno(sock, 0);
mbed_official 0:51ac1d130fd4 2306 return 0;
mbed_official 0:51ac1d130fd4 2307
mbed_official 0:51ac1d130fd4 2308 default:
mbed_official 0:51ac1d130fd4 2309 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
mbed_official 0:51ac1d130fd4 2310 sock_set_errno(sock, ENOSYS); /* not yet implemented */
mbed_official 0:51ac1d130fd4 2311 return -1;
mbed_official 0:51ac1d130fd4 2312 } /* switch (cmd) */
mbed_official 0:51ac1d130fd4 2313 }
mbed_official 0:51ac1d130fd4 2314
mbed_official 0:51ac1d130fd4 2315 /** A minimal implementation of fcntl.
mbed_official 0:51ac1d130fd4 2316 * Currently only the commands F_GETFL and F_SETFL are implemented.
mbed_official 0:51ac1d130fd4 2317 * Only the flag O_NONBLOCK is implemented.
mbed_official 0:51ac1d130fd4 2318 */
mbed_official 0:51ac1d130fd4 2319 int
mbed_official 0:51ac1d130fd4 2320 lwip_fcntl(int s, int cmd, int val)
mbed_official 0:51ac1d130fd4 2321 {
mbed_official 0:51ac1d130fd4 2322 struct lwip_sock *sock = get_socket(s);
mbed_official 0:51ac1d130fd4 2323 int ret = -1;
mbed_official 0:51ac1d130fd4 2324
mbed_official 0:51ac1d130fd4 2325 if (!sock || !sock->conn) {
mbed_official 0:51ac1d130fd4 2326 return -1;
mbed_official 0:51ac1d130fd4 2327 }
mbed_official 0:51ac1d130fd4 2328
mbed_official 0:51ac1d130fd4 2329 switch (cmd) {
mbed_official 0:51ac1d130fd4 2330 case F_GETFL:
mbed_official 0:51ac1d130fd4 2331 ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
mbed_official 0:51ac1d130fd4 2332 break;
mbed_official 0:51ac1d130fd4 2333 case F_SETFL:
mbed_official 0:51ac1d130fd4 2334 if ((val & ~O_NONBLOCK) == 0) {
mbed_official 0:51ac1d130fd4 2335 /* only O_NONBLOCK, all other bits are zero */
mbed_official 0:51ac1d130fd4 2336 netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
mbed_official 0:51ac1d130fd4 2337 ret = 0;
mbed_official 0:51ac1d130fd4 2338 }
mbed_official 0:51ac1d130fd4 2339 break;
mbed_official 0:51ac1d130fd4 2340 default:
mbed_official 0:51ac1d130fd4 2341 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
mbed_official 0:51ac1d130fd4 2342 break;
mbed_official 0:51ac1d130fd4 2343 }
mbed_official 0:51ac1d130fd4 2344 return ret;
mbed_official 0:51ac1d130fd4 2345 }
mbed_official 0:51ac1d130fd4 2346
mbed_official 0:51ac1d130fd4 2347 #endif /* LWIP_SOCKET */