3 * Sockets BSD-Like API module
8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11 * Redistribution and use in source and binary forms, with or without modification,
12 * are permitted provided that the following conditions are met:
14 * 1. Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 * This file is part of the lwIP TCP/IP stack.
35 * Author: Adam Dunkels <adam@sics.se>
37 * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
43 #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */
45 #include "lwip/sockets.h"
48 #include "lwip/igmp.h"
49 #include "lwip/inet.h"
53 #include "lwip/tcpip.h"
54 #include "lwip/pbuf.h"
55 #if LWIP_CHECKSUM_ON_COPY
56 #include "lwip/inet_chksum.h"
61 #define NUM_SOCKETS MEMP_NUM_NETCONN
63 /** Contains all internal pointers and states used for a socket */
65 /** sockets currently are built on netconns, each socket has one netconn */
67 /** data that was left from the previous read */
69 /** offset in the data that was left from the previous read */
71 /** number of times data was received, set by event_callback(),
72 tested by the receive and select functions */
74 /** number of times data was ACKed (free send buffer), set by event_callback(),
77 /** error happened for this socket, set by event_callback(), tested by select */
79 /** last error that occurred on this socket */
81 /** counter of how many threads are waiting for this socket using select */
85 /** Description for a task waiting in select */
86 struct lwip_select_cb {
87 /** Pointer to the next waiting task */
88 struct lwip_select_cb *next;
89 /** Pointer to the previous waiting task */
90 struct lwip_select_cb *prev;
91 /** readset passed to select */
93 /** writeset passed to select */
95 /** unimplemented: exceptset passed to select */
97 /** don't signal the same semaphore twice: set to 1 when signalled */
99 /** semaphore to wake up a task waiting for select */
103 /** This struct is used to pass data to the set/getsockopt_internal
104 * functions running in tcpip_thread context (only a void* is allowed) */
105 struct lwip_setgetsockopt_data {
106 /** socket struct for which to change options */
107 struct lwip_sock *sock;
108 /** socket index for which to change options */
110 /** level of the option to process */
112 /** name of the option to process */
114 /** set: value to set the option to
115 * get: value of the option is stored here */
117 /** size of *optval */
119 /** if an error occures, it is temporarily stored here */
123 /** The global array of available sockets */
124 static struct lwip_sock sockets[NUM_SOCKETS];
125 /** The global list of tasks waiting for select */
126 static struct lwip_select_cb *select_cb_list;
127 /** This counter is increased from lwip_select when the list is chagned
128 and checked in event_callback to see if it has changed. */
129 static volatile int select_cb_ctr;
131 /** Table to quickly map an lwIP error (err_t) to a socket error
132 * by using -err as an index */
133 static const int err_to_errno_table[] = {
134 0, /* ERR_OK 0 No error, everything OK. */
135 ENOMEM, /* ERR_MEM -1 Out of memory error. */
136 ENOBUFS, /* ERR_BUF -2 Buffer error. */
137 EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
138 EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
139 EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
140 EINVAL, /* ERR_VAL -6 Illegal value. */
141 EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
142 ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
143 ECONNRESET, /* ERR_RST -9 Connection reset. */
144 ESHUTDOWN, /* ERR_CLSD -10 Connection closed. */
145 ENOTCONN, /* ERR_CONN -11 Not connected. */
146 EIO, /* ERR_ARG -12 Illegal argument. */
147 EADDRINUSE, /* ERR_USE -13 Address in use. */
148 -1, /* ERR_IF -14 Low-level netif error */
149 -1, /* ERR_ISCONN -15 Already connected. */
152 #define ERR_TO_ERRNO_TABLE_SIZE \
153 (sizeof(err_to_errno_table)/sizeof(err_to_errno_table[0]))
155 #define err_to_errno(err) \
156 ((unsigned)(-(err)) < ERR_TO_ERRNO_TABLE_SIZE ? \
157 err_to_errno_table[-(err)] : EIO)
161 #define set_errno(err) errno = (err)
164 #define set_errno(err)
167 #define sock_set_errno(sk, e) do { \
169 set_errno(sk->err); \
172 /* Forward delcaration of some functions */
173 static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
174 static void lwip_getsockopt_internal(void *arg);
175 static void lwip_setsockopt_internal(void *arg);
178 * Initialize this module. This function has to be called before any other
179 * functions in this module!
182 lwip_socket_init(void)
187 * Map a externally used socket index to the internal socket representation.
189 * @param s externally used socket index
190 * @return struct lwip_sock for the socket or NULL if not found
192 static struct lwip_sock *
195 struct lwip_sock *sock;
197 if ((s < 0) || (s >= NUM_SOCKETS)) {
198 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", s));
206 LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s));
215 * Same as get_socket but doesn't set errno
217 * @param s externally used socket index
218 * @return struct lwip_sock for the socket or NULL if not found
220 static struct lwip_sock *
223 if ((s < 0) || (s >= NUM_SOCKETS)) {
226 if (!sockets[s].conn) {
233 * Allocate a new socket for a given netconn.
235 * @param newconn the netconn for which to allocate a socket
236 * @param accepted 1 if socket has been created by accept(),
237 * 0 if socket has been created by socket()
238 * @return the index of the new socket; -1 on error
241 alloc_socket(struct netconn *newconn, int accepted)
244 SYS_ARCH_DECL_PROTECT(lev);
246 /* allocate a new socket identifier */
247 for (i = 0; i < NUM_SOCKETS; ++i) {
248 /* Protect socket array */
249 SYS_ARCH_PROTECT(lev);
250 if (!sockets[i].conn) {
251 sockets[i].conn = newconn;
252 /* The socket is not yet known to anyone, so no need to protect
253 after having marked it as used. */
254 SYS_ARCH_UNPROTECT(lev);
255 sockets[i].lastdata = NULL;
256 sockets[i].lastoffset = 0;
257 sockets[i].rcvevent = 0;
258 /* TCP sendbuf is empty, but the socket is not yet writable until connected
259 * (unless it has been created by accept()). */
260 sockets[i].sendevent = (newconn->type == NETCONN_TCP ? (accepted != 0) : 1);
261 sockets[i].errevent = 0;
263 sockets[i].select_waiting = 0;
266 SYS_ARCH_UNPROTECT(lev);
271 /** Free a socket. The socket's netconn must have been
274 * @param sock the socket to free
275 * @param is_tcp != 0 for TCP sockets, used to free lastdata
278 free_socket(struct lwip_sock *sock, int is_tcp)
281 SYS_ARCH_DECL_PROTECT(lev);
283 lastdata = sock->lastdata;
284 sock->lastdata = NULL;
285 sock->lastoffset = 0;
288 /* Protect socket array */
289 SYS_ARCH_PROTECT(lev);
291 SYS_ARCH_UNPROTECT(lev);
292 /* don't use 'sock' after this line, as another task might have allocated it */
294 if (lastdata != NULL) {
296 pbuf_free((struct pbuf *)lastdata);
298 netbuf_delete((struct netbuf *)lastdata);
303 /* Below this, the well-known socket functions are implemented.
304 * Use google.com or opengroup.org to get a good description :-)
306 * Exceptions are documented!
310 lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
312 struct lwip_sock *sock, *nsock;
313 struct netconn *newconn;
317 struct sockaddr_in sin;
319 SYS_ARCH_DECL_PROTECT(lev);
321 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
322 sock = get_socket(s);
327 if (netconn_is_nonblocking(sock->conn) && (sock->rcvevent <= 0)) {
328 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): returning EWOULDBLOCK\n", s));
329 sock_set_errno(sock, EWOULDBLOCK);
333 /* wait for a new connection */
334 err = netconn_accept(sock->conn, &newconn);
336 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_acept failed, err=%d\n", s, err));
337 sock_set_errno(sock, err_to_errno(err));
340 LWIP_ASSERT("newconn != NULL", newconn != NULL);
341 /* Prevent automatic window updates, we do this on our own! */
342 netconn_set_noautorecved(newconn, 1);
344 /* get the IP address and port of the remote host */
345 err = netconn_peer(newconn, &naddr, &port);
347 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d): netconn_peer failed, err=%d\n", s, err));
348 netconn_delete(newconn);
349 sock_set_errno(sock, err_to_errno(err));
353 /* Note that POSIX only requires us to check addr is non-NULL. addrlen must
354 * not be NULL if addr is valid.
357 LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL);
358 memset(&sin, 0, sizeof(sin));
359 sin.sin_len = sizeof(sin);
360 sin.sin_family = AF_INET;
361 sin.sin_port = htons(port);
362 inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
364 if (*addrlen > sizeof(sin))
365 *addrlen = sizeof(sin);
367 MEMCPY(addr, &sin, *addrlen);
370 newsock = alloc_socket(newconn, 1);
372 netconn_delete(newconn);
373 sock_set_errno(sock, ENFILE);
376 LWIP_ASSERT("invalid socket index", (newsock >= 0) && (newsock < NUM_SOCKETS));
377 LWIP_ASSERT("newconn->callback == event_callback", newconn->callback == event_callback);
378 nsock = &sockets[newsock];
380 /* See event_callback: If data comes in right away after an accept, even
381 * though the server task might not have created a new socket yet.
382 * In that case, newconn->socket is counted down (newconn->socket--),
383 * so nsock->rcvevent is >= 1 here!
385 SYS_ARCH_PROTECT(lev);
386 nsock->rcvevent += (s16_t)(-1 - newconn->socket);
387 newconn->socket = newsock;
388 SYS_ARCH_UNPROTECT(lev);
390 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
391 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
392 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", port));
394 sock_set_errno(sock, 0);
399 lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
401 struct lwip_sock *sock;
402 ip_addr_t local_addr;
405 const struct sockaddr_in *name_in;
407 sock = get_socket(s);
412 /* check size, familiy and alignment of 'name' */
413 LWIP_ERROR("lwip_bind: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
414 ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
415 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
416 name_in = (const struct sockaddr_in *)(void*)name;
418 inet_addr_to_ipaddr(&local_addr, &name_in->sin_addr);
419 local_port = name_in->sin_port;
421 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
422 ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
423 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(local_port)));
425 err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
428 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err));
429 sock_set_errno(sock, err_to_errno(err));
433 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) succeeded\n", s));
434 sock_set_errno(sock, 0);
441 struct lwip_sock *sock;
444 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_close(%d)\n", s));
446 sock = get_socket(s);
451 if(sock->conn != NULL) {
452 is_tcp = netconn_type(sock->conn) == NETCONN_TCP;
454 LWIP_ASSERT("sock->lastdata == NULL", sock->lastdata == NULL);
457 netconn_delete(sock->conn);
459 free_socket(sock, is_tcp);
465 lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
467 struct lwip_sock *sock;
469 const struct sockaddr_in *name_in;
471 sock = get_socket(s);
476 /* check size, familiy and alignment of 'name' */
477 LWIP_ERROR("lwip_connect: invalid address", ((namelen == sizeof(struct sockaddr_in)) &&
478 ((name->sa_family) == AF_INET) && ((((mem_ptr_t)name) % 4) == 0)),
479 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
480 name_in = (const struct sockaddr_in *)(void*)name;
482 if (name_in->sin_family == AF_UNSPEC) {
483 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, AF_UNSPEC)\n", s));
484 err = netconn_disconnect(sock->conn);
486 ip_addr_t remote_addr;
489 inet_addr_to_ipaddr(&remote_addr, &name_in->sin_addr);
490 remote_port = name_in->sin_port;
492 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
493 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
494 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", ntohs(remote_port)));
496 err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
500 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) failed, err=%d\n", s, err));
501 sock_set_errno(sock, err_to_errno(err));
505 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d) succeeded\n", s));
506 sock_set_errno(sock, 0);
511 * Set a socket into listen mode.
512 * The socket may not have been used for another connection previously.
514 * @param s the socket to set to listening mode
515 * @param backlog (ATTENTION: needs TCP_LISTEN_BACKLOG=1)
516 * @return 0 on success, non-zero on failure
519 lwip_listen(int s, int backlog)
521 struct lwip_sock *sock;
524 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
526 sock = get_socket(s);
531 /* limit the "backlog" parameter to fit in an u8_t */
532 backlog = LWIP_MIN(LWIP_MAX(backlog, 0), 0xff);
534 err = netconn_listen_with_backlog(sock->conn, (u8_t)backlog);
537 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d) failed, err=%d\n", s, err));
538 sock_set_errno(sock, err_to_errno(err));
542 sock_set_errno(sock, 0);
547 lwip_recvfrom(int s, void *mem, size_t len, int flags,
548 struct sockaddr *from, socklen_t *fromlen)
550 struct lwip_sock *sock;
553 u16_t buflen, copylen;
560 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
561 sock = get_socket(s);
567 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata));
568 /* Check if there is data left from the last recv operation. */
569 if (sock->lastdata) {
570 buf = sock->lastdata;
572 /* If this is non-blocking call, then check first */
573 if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&
574 (sock->rcvevent <= 0)) {
576 /* update receive window */
577 netconn_recved(sock->conn, (u32_t)off);
578 /* already received data, return that */
579 sock_set_errno(sock, 0);
582 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s));
583 sock_set_errno(sock, EWOULDBLOCK);
587 /* No data was left from the previous operation, so we try to get
588 some from the network. */
589 if (netconn_type(sock->conn) == NETCONN_TCP) {
590 err = netconn_recv_tcp_pbuf(sock->conn, (struct pbuf **)&buf);
592 err = netconn_recv(sock->conn, (struct netbuf **)&buf);
594 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv err=%d, netbuf=%p\n",
599 /* update receive window */
600 netconn_recved(sock->conn, (u32_t)off);
601 /* already received data, return that */
602 sock_set_errno(sock, 0);
605 /* We should really do some error checking here. */
606 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): buf == NULL, error is \"%s\"!\n",
607 s, lwip_strerr(err)));
608 sock_set_errno(sock, err_to_errno(err));
609 if (err == ERR_CLSD) {
615 LWIP_ASSERT("buf != NULL", buf != NULL);
616 sock->lastdata = buf;
619 if (netconn_type(sock->conn) == NETCONN_TCP) {
620 p = (struct pbuf *)buf;
622 p = ((struct netbuf *)buf)->p;
625 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%"U16_F" len=%"SZT_F" off=%d sock->lastoffset=%"U16_F"\n",
626 buflen, len, off, sock->lastoffset));
628 buflen -= sock->lastoffset;
633 copylen = (u16_t)len;
636 /* copy the contents of the received buffer into
637 the supplied memory pointer mem */
638 pbuf_copy_partial(p, (u8_t*)mem + off, copylen, sock->lastoffset);
642 if (netconn_type(sock->conn) == NETCONN_TCP) {
643 LWIP_ASSERT("invalid copylen, len would underflow", len >= copylen);
646 (p->flags & PBUF_FLAG_PUSH) ||
647 (sock->rcvevent <= 0) ||
648 ((flags & MSG_PEEK)!=0)) {
655 /* Check to see from where the data was.*/
658 if (from && fromlen) {
659 struct sockaddr_in sin;
661 if (netconn_type(sock->conn) == NETCONN_TCP) {
663 netconn_getaddr(sock->conn, addr, &port, 0);
665 addr = netbuf_fromaddr((struct netbuf *)buf);
666 port = netbuf_fromport((struct netbuf *)buf);
669 memset(&sin, 0, sizeof(sin));
670 sin.sin_len = sizeof(sin);
671 sin.sin_family = AF_INET;
672 sin.sin_port = htons(port);
673 inet_addr_from_ipaddr(&sin.sin_addr, addr);
675 if (*fromlen > sizeof(sin)) {
676 *fromlen = sizeof(sin);
679 MEMCPY(from, &sin, *fromlen);
681 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
682 ip_addr_debug_print(SOCKETS_DEBUG, addr);
683 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
686 if (netconn_type(sock->conn) == NETCONN_TCP) {
688 netconn_getaddr(sock->conn, addr, &port, 0);
690 addr = netbuf_fromaddr((struct netbuf *)buf);
691 port = netbuf_fromport((struct netbuf *)buf);
694 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
695 ip_addr_debug_print(SOCKETS_DEBUG, addr);
696 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, off));
697 #endif /* SOCKETS_DEBUG */
701 /* If we don't peek the incoming message... */
702 if ((flags & MSG_PEEK) == 0) {
703 /* If this is a TCP socket, check if there is data left in the
704 buffer. If so, it should be saved in the sock structure for next
706 if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) {
707 sock->lastdata = buf;
708 sock->lastoffset += copylen;
709 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf));
711 sock->lastdata = NULL;
712 sock->lastoffset = 0;
713 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf));
714 if (netconn_type(sock->conn) == NETCONN_TCP) {
715 pbuf_free((struct pbuf *)buf);
717 netbuf_delete((struct netbuf *)buf);
724 /* update receive window */
725 netconn_recved(sock->conn, (u32_t)off);
727 sock_set_errno(sock, 0);
732 lwip_read(int s, void *mem, size_t len)
734 return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
738 lwip_recv(int s, void *mem, size_t len, int flags)
740 return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
744 lwip_send(int s, const void *data, size_t size, int flags)
746 struct lwip_sock *sock;
750 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%"SZT_F", flags=0x%x)\n",
751 s, data, size, flags));
753 sock = get_socket(s);
758 if (sock->conn->type != NETCONN_TCP) {
759 #if (LWIP_UDP || LWIP_RAW)
760 return lwip_sendto(s, data, size, flags, NULL, 0);
762 sock_set_errno(sock, err_to_errno(ERR_ARG));
764 #endif /* (LWIP_UDP || LWIP_RAW) */
767 if ((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) {
768 if ((size > TCP_SND_BUF) || ((size / TCP_MSS) > TCP_SND_QUEUELEN)) {
769 /* too much data to ever send nonblocking! */
770 sock_set_errno(sock, EMSGSIZE);
775 write_flags = NETCONN_COPY |
776 ((flags & MSG_MORE) ? NETCONN_MORE : 0) |
777 ((flags & MSG_DONTWAIT) ? NETCONN_DONTBLOCK : 0);
778 err = netconn_write(sock->conn, data, size, write_flags);
780 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%"SZT_F"\n", s, err, size));
781 sock_set_errno(sock, err_to_errno(err));
782 return (err == ERR_OK ? (int)size : -1);
786 lwip_sendto(int s, const void *data, size_t size, int flags,
787 const struct sockaddr *to, socklen_t tolen)
789 struct lwip_sock *sock;
790 ip_addr_t remote_addr;
793 const struct sockaddr_in *to_in;
794 #if !LWIP_TCPIP_CORE_LOCKING
799 sock = get_socket(s);
804 if (sock->conn->type == NETCONN_TCP) {
806 return lwip_send(s, data, size, flags);
808 sock_set_errno(sock, err_to_errno(ERR_ARG));
810 #endif /* LWIP_TCP */
813 /* @todo: split into multiple sendto's? */
814 LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size <= 0xffff);
815 short_size = (u16_t)size;
816 LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) ||
817 ((tolen == sizeof(struct sockaddr_in)) &&
818 ((to->sa_family) == AF_INET) && ((((mem_ptr_t)to) % 4) == 0))),
819 sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1;);
820 to_in = (const struct sockaddr_in *)(void*)to;
822 #if LWIP_TCPIP_CORE_LOCKING
823 /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
826 #if LWIP_NETIF_TX_SINGLE_PBUF
827 p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_RAM);
829 #if LWIP_CHECKSUM_ON_COPY
831 if (sock->conn->type != NETCONN_RAW) {
832 chksum = LWIP_CHKSUM_COPY(p->payload, data, short_size);
834 #endif /* LWIP_CHECKSUM_ON_COPY */
835 MEMCPY(p->payload, data, size);
836 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
837 p = pbuf_alloc(PBUF_TRANSPORT, short_size, PBUF_REF);
839 p->payload = (void*)data;
840 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
842 inet_addr_to_ipaddr(&remote_addr, &to_in->sin_addr);
845 if (sock->conn->type == NETCONN_RAW) {
846 err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, &remote_addr);
848 #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
849 err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p,
850 &remote_addr, ntohs(to_in->sin_port), 1, chksum);
851 #else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
852 err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p,
853 &remote_addr, ntohs(to_in->sin_port));
854 #endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
864 /* initialize a buffer */
865 buf.p = buf.ptr = NULL;
866 #if LWIP_CHECKSUM_ON_COPY
868 #endif /* LWIP_CHECKSUM_ON_COPY */
870 inet_addr_to_ipaddr(&remote_addr, &to_in->sin_addr);
871 remote_port = ntohs(to_in->sin_port);
872 netbuf_fromaddr(&buf) = &remote_addr;
873 netbuf_fromport(&buf) = remote_port;
875 ip_addr_set_zero(&remote_addr);
877 netbuf_fromaddr(&buf) = NULL;
878 netbuf_fromport(&buf) = 0;
881 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=",
882 s, data, short_size, flags));
883 ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
884 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port));
886 /* make the buffer point to the data that should be sent */
887 #if LWIP_NETIF_TX_SINGLE_PBUF
888 /* Allocate a new netbuf and copy the data into it. */
889 if (netbuf_alloc(&buf, short_size) == NULL) {
892 #if LWIP_CHECKSUM_ON_COPY
893 if (sock->conn->type != NETCONN_RAW) {
894 u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size);
895 netbuf_set_chksum(&buf, chksum);
898 #endif /* LWIP_CHECKSUM_ON_COPY */
900 err = netbuf_take(&buf, data, short_size);
903 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
904 err = netbuf_ref(&buf, data, short_size);
905 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
908 err = netconn_send(sock->conn, &buf);
911 /* deallocated the buffer */
913 #endif /* LWIP_TCPIP_CORE_LOCKING */
914 sock_set_errno(sock, err_to_errno(err));
915 return (err == ERR_OK ? short_size : -1);
919 lwip_socket(int domain, int type, int protocol)
921 struct netconn *conn;
924 LWIP_UNUSED_ARG(domain);
926 /* create a netconn */
929 conn = netconn_new_with_proto_and_callback(NETCONN_RAW, (u8_t)protocol, event_callback);
930 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ",
931 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
934 conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
935 NETCONN_UDPLITE : NETCONN_UDP, event_callback);
936 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
937 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
940 conn = netconn_new_with_callback(NETCONN_TCP, event_callback);
941 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
942 domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
944 /* Prevent automatic window updates, we do this on our own! */
945 netconn_set_noautorecved(conn, 1);
949 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
950 domain, type, protocol));
956 LWIP_DEBUGF(SOCKETS_DEBUG, ("-1 / ENOBUFS (could not create netconn)\n"));
961 i = alloc_socket(conn, 0);
964 netconn_delete(conn);
969 LWIP_DEBUGF(SOCKETS_DEBUG, ("%d\n", i));
975 lwip_write(int s, const void *data, size_t size)
977 return lwip_send(s, data, size, 0);
981 * Go through the readset and writeset lists and see which socket of the sockets
982 * set in the sets has events. On return, readset, writeset and exceptset have
983 * the sockets enabled that had events.
985 * exceptset is not used for now!!!
987 * @param maxfdp1 the highest socket index in the sets
988 * @param readset_in: set of sockets to check for read events
989 * @param writeset_in: set of sockets to check for write events
990 * @param exceptset_in: set of sockets to check for error events
991 * @param readset_out: set of sockets that had read events
992 * @param writeset_out: set of sockets that had write events
993 * @param exceptset_out: set os sockets that had error events
994 * @return number of sockets that had events (read/write/exception) (>= 0)
997 lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *exceptset_in,
998 fd_set *readset_out, fd_set *writeset_out, fd_set *exceptset_out)
1001 fd_set lreadset, lwriteset, lexceptset;
1002 struct lwip_sock *sock;
1003 SYS_ARCH_DECL_PROTECT(lev);
1006 FD_ZERO(&lwriteset);
1007 FD_ZERO(&lexceptset);
1009 /* Go through each socket in each list to count number of sockets which
1011 for(i = 0; i < maxfdp1; i++) {
1012 void* lastdata = NULL;
1014 u16_t sendevent = 0;
1016 /* First get the socket's status (protected)... */
1017 SYS_ARCH_PROTECT(lev);
1018 sock = tryget_socket(i);
1020 lastdata = sock->lastdata;
1021 rcvevent = sock->rcvevent;
1022 sendevent = sock->sendevent;
1023 errevent = sock->errevent;
1025 SYS_ARCH_UNPROTECT(lev);
1026 /* ... then examine it: */
1027 /* See if netconn of this socket is ready for read */
1028 if (readset_in && FD_ISSET(i, readset_in) && ((lastdata != NULL) || (rcvevent > 0))) {
1029 FD_SET(i, &lreadset);
1030 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for reading\n", i));
1033 /* See if netconn of this socket is ready for write */
1034 if (writeset_in && FD_ISSET(i, writeset_in) && (sendevent != 0)) {
1035 FD_SET(i, &lwriteset);
1036 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for writing\n", i));
1039 /* See if netconn of this socket had an error */
1040 if (exceptset_in && FD_ISSET(i, exceptset_in) && (errevent != 0)) {
1041 FD_SET(i, &lexceptset);
1042 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_selscan: fd=%d ready for exception\n", i));
1046 /* copy local sets to the ones provided as arguments */
1047 *readset_out = lreadset;
1048 *writeset_out = lwriteset;
1049 *exceptset_out = lexceptset;
1051 LWIP_ASSERT("nready >= 0", nready >= 0);
1056 * Processing exceptset is not yet implemented.
1059 lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
1060 struct timeval *timeout)
1064 fd_set lreadset, lwriteset, lexceptset;
1066 struct lwip_select_cb select_cb;
1069 SYS_ARCH_DECL_PROTECT(lev);
1071 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
1072 maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
1073 timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
1074 timeout ? (s32_t)timeout->tv_usec : (s32_t)-1));
1076 /* Go through each socket in each list to count number of sockets which
1078 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1080 /* If we don't have any current events, then suspend if we are supposed to */
1082 if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
1083 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
1084 /* This is OK as the local fdsets are empty and nready is zero,
1085 or we would have returned earlier. */
1086 goto return_copy_fdsets;
1089 /* None ready: add our semaphore to list:
1090 We don't actually need any dynamic memory. Our entry on the
1091 list is only valid while we are in this function, so it's ok
1092 to use local variables. */
1094 select_cb.next = NULL;
1095 select_cb.prev = NULL;
1096 select_cb.readset = readset;
1097 select_cb.writeset = writeset;
1098 select_cb.exceptset = exceptset;
1099 select_cb.sem_signalled = 0;
1100 err = sys_sem_new(&select_cb.sem, 0);
1101 if (err != ERR_OK) {
1102 /* failed to create semaphore */
1107 /* Protect the select_cb_list */
1108 SYS_ARCH_PROTECT(lev);
1110 /* Put this select_cb on top of list */
1111 select_cb.next = select_cb_list;
1112 if (select_cb_list != NULL) {
1113 select_cb_list->prev = &select_cb;
1115 select_cb_list = &select_cb;
1116 /* Increasing this counter tells even_callback that the list has changed. */
1119 /* Now we can safely unprotect */
1120 SYS_ARCH_UNPROTECT(lev);
1122 /* Increase select_waiting for each socket we are interested in */
1123 for(i = 0; i < maxfdp1; i++) {
1124 if ((readset && FD_ISSET(i, readset)) ||
1125 (writeset && FD_ISSET(i, writeset)) ||
1126 (exceptset && FD_ISSET(i, exceptset))) {
1127 struct lwip_sock *sock = tryget_socket(i);
1128 LWIP_ASSERT("sock != NULL", sock != NULL);
1129 SYS_ARCH_PROTECT(lev);
1130 sock->select_waiting++;
1131 LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0);
1132 SYS_ARCH_UNPROTECT(lev);
1136 /* Call lwip_selscan again: there could have been events between
1137 the last scan (whithout us on the list) and putting us on the list! */
1138 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1140 /* Still none ready, just wait to be woken */
1145 msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
1146 if (msectimeout == 0) {
1147 /* Wait 1ms at least (0 means wait forever) */
1152 waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout);
1154 /* Increase select_waiting for each socket we are interested in */
1155 for(i = 0; i < maxfdp1; i++) {
1156 if ((readset && FD_ISSET(i, readset)) ||
1157 (writeset && FD_ISSET(i, writeset)) ||
1158 (exceptset && FD_ISSET(i, exceptset))) {
1159 struct lwip_sock *sock = tryget_socket(i);
1160 LWIP_ASSERT("sock != NULL", sock != NULL);
1161 SYS_ARCH_PROTECT(lev);
1162 sock->select_waiting--;
1163 LWIP_ASSERT("sock->select_waiting >= 0", sock->select_waiting >= 0);
1164 SYS_ARCH_UNPROTECT(lev);
1167 /* Take us off the list */
1168 SYS_ARCH_PROTECT(lev);
1169 if (select_cb.next != NULL) {
1170 select_cb.next->prev = select_cb.prev;
1172 if (select_cb_list == &select_cb) {
1173 LWIP_ASSERT("select_cb.prev == NULL", select_cb.prev == NULL);
1174 select_cb_list = select_cb.next;
1176 LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL);
1177 select_cb.prev->next = select_cb.next;
1179 SYS_ARCH_UNPROTECT(lev);
1181 sys_sem_free(&select_cb.sem);
1182 if (waitres == SYS_ARCH_TIMEOUT) {
1184 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
1185 /* This is OK as the local fdsets are empty and nready is zero,
1186 or we would have returned earlier. */
1187 goto return_copy_fdsets;
1190 /* See what's set */
1191 nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
1194 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
1198 *readset = lreadset;
1201 *writeset = lwriteset;
1204 *exceptset = lexceptset;
1212 * Callback registered in the netconn layer for each socket-netconn.
1213 * Processes recvevent (data available) and wakes up tasks waiting for select.
1216 event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
1219 struct lwip_sock *sock;
1220 struct lwip_select_cb *scb;
1221 SYS_ARCH_DECL_PROTECT(lev);
1223 LWIP_UNUSED_ARG(len);
1229 /* Data comes in right away after an accept, even though
1230 * the server task might not have created a new socket yet.
1231 * Just count down (or up) if that's the case and we
1232 * will use the data later. Note that only receive events
1233 * can happen before the new socket is set up. */
1234 SYS_ARCH_PROTECT(lev);
1235 if (conn->socket < 0) {
1236 if (evt == NETCONN_EVT_RCVPLUS) {
1239 SYS_ARCH_UNPROTECT(lev);
1243 SYS_ARCH_UNPROTECT(lev);
1246 sock = get_socket(s);
1254 SYS_ARCH_PROTECT(lev);
1255 /* Set event as required */
1257 case NETCONN_EVT_RCVPLUS:
1260 case NETCONN_EVT_RCVMINUS:
1263 case NETCONN_EVT_SENDPLUS:
1264 sock->sendevent = 1;
1266 case NETCONN_EVT_SENDMINUS:
1267 sock->sendevent = 0;
1269 case NETCONN_EVT_ERROR:
1273 LWIP_ASSERT("unknown event", 0);
1277 if (sock->select_waiting == 0) {
1278 /* noone is waiting for this socket, no need to check select_cb_list */
1279 SYS_ARCH_UNPROTECT(lev);
1283 SYS_ARCH_UNPROTECT(lev);
1285 /* Now decide if anyone is waiting for this socket */
1286 /* NOTE: This code is written this way to protect the select link list
1287 but to avoid a deadlock situation by releasing select_lock before
1288 signalling for the select. This means we need to go through the list
1289 multiple times ONLY IF a select was actually waiting. We go through
1290 the list the number of waiting select calls + 1. This list is
1291 expected to be small. */
1293 int last_select_cb_ctr;
1294 SYS_ARCH_PROTECT(lev);
1295 for (scb = select_cb_list; scb; scb = scb->next) {
1296 /* @todo: unprotect with each loop and check for changes? */
1297 if (scb->sem_signalled == 0) {
1298 /* Test this select call for our socket */
1299 if (scb->readset && FD_ISSET(s, scb->readset)) {
1300 if (sock->rcvevent > 0) {
1304 if (scb->writeset && FD_ISSET(s, scb->writeset)) {
1305 if (sock->sendevent != 0) {
1309 if (scb->exceptset && FD_ISSET(s, scb->exceptset)) {
1310 if (sock->errevent != 0) {
1315 /* unlock interrupts with each step */
1316 last_select_cb_ctr = select_cb_ctr;
1317 SYS_ARCH_UNPROTECT(lev);
1318 SYS_ARCH_PROTECT(lev);
1319 if (last_select_cb_ctr != select_cb_ctr) {
1320 /* someone has changed select_cb_list, restart at the beginning */
1321 scb = select_cb_list;
1325 scb->sem_signalled = 1;
1326 sys_sem_signal(&scb->sem);
1327 SYS_ARCH_UNPROTECT(lev);
1329 SYS_ARCH_UNPROTECT(lev);
1336 * Unimplemented: Close one end of a full-duplex connection.
1337 * Currently, the full connection is closed.
1340 lwip_shutdown(int s, int how)
1342 LWIP_UNUSED_ARG(how);
1343 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
1344 return lwip_close(s); /* XXX temporary hack until proper implementation */
1348 lwip_getaddrname(int s, struct sockaddr *name, socklen_t *namelen, u8_t local)
1350 struct lwip_sock *sock;
1351 struct sockaddr_in sin;
1354 sock = get_socket(s);
1359 memset(&sin, 0, sizeof(sin));
1360 sin.sin_len = sizeof(sin);
1361 sin.sin_family = AF_INET;
1363 /* get the IP address and port */
1364 netconn_getaddr(sock->conn, &naddr, &sin.sin_port, local);
1366 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s));
1367 ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
1368 LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", sin.sin_port));
1370 sin.sin_port = htons(sin.sin_port);
1371 inet_addr_from_ipaddr(&sin.sin_addr, &naddr);
1373 if (*namelen > sizeof(sin)) {
1374 *namelen = sizeof(sin);
1377 MEMCPY(name, &sin, *namelen);
1378 sock_set_errno(sock, 0);
1383 lwip_getpeername(int s, struct sockaddr *name, socklen_t *namelen)
1385 return lwip_getaddrname(s, name, namelen, 0);
1389 lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
1391 return lwip_getaddrname(s, name, namelen, 1);
1395 lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
1398 struct lwip_sock *sock = get_socket(s);
1399 struct lwip_setgetsockopt_data data;
1405 if ((NULL == optval) || (NULL == optlen)) {
1406 sock_set_errno(sock, EFAULT);
1410 /* Do length and type checks for the various options first, to keep it readable. */
1413 /* Level: SOL_SOCKET */
1419 /* UNIMPL case SO_DEBUG: */
1420 /* UNIMPL case SO_DONTROUTE: */
1423 /* UNIMPL case SO_CONTIMEO: */
1424 /* UNIMPL case SO_SNDTIMEO: */
1425 #if LWIP_SO_RCVTIMEO
1427 #endif /* LWIP_SO_RCVTIMEO */
1430 #endif /* LWIP_SO_RCVBUF */
1431 /* UNIMPL case SO_OOBINLINE: */
1432 /* UNIMPL case SO_SNDBUF: */
1433 /* UNIMPL case SO_RCVLOWAT: */
1434 /* UNIMPL case SO_SNDLOWAT: */
1438 #endif /* SO_REUSE */
1440 /* UNIMPL case SO_USELOOPBACK: */
1441 if (*optlen < sizeof(int)) {
1447 if (*optlen < sizeof(int)) {
1451 if ((sock->conn->type != NETCONN_UDP) ||
1452 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1453 /* this flag is only available for UDP, not for UDP lite */
1456 #endif /* LWIP_UDP */
1460 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1463 } /* switch (optname) */
1466 /* Level: IPPROTO_IP */
1469 /* UNIMPL case IP_HDRINCL: */
1470 /* UNIMPL case IP_RCVDSTADDR: */
1471 /* UNIMPL case IP_RCVIF: */
1474 if (*optlen < sizeof(int)) {
1479 case IP_MULTICAST_TTL:
1480 if (*optlen < sizeof(u8_t)) {
1484 case IP_MULTICAST_IF:
1485 if (*optlen < sizeof(struct in_addr)) {
1489 #endif /* LWIP_IGMP */
1492 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1495 } /* switch (optname) */
1499 /* Level: IPPROTO_TCP */
1501 if (*optlen < sizeof(int)) {
1506 /* If this is no TCP socket, ignore any options. */
1507 if (sock->conn->type != NETCONN_TCP)
1513 #if LWIP_TCP_KEEPALIVE
1517 #endif /* LWIP_TCP_KEEPALIVE */
1521 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1524 } /* switch (optname) */
1526 #endif /* LWIP_TCP */
1527 #if LWIP_UDP && LWIP_UDPLITE
1528 /* Level: IPPROTO_UDPLITE */
1529 case IPPROTO_UDPLITE:
1530 if (*optlen < sizeof(int)) {
1535 /* If this is no UDP lite socket, ignore any options. */
1536 if (sock->conn->type != NETCONN_UDPLITE) {
1541 case UDPLITE_SEND_CSCOV:
1542 case UDPLITE_RECV_CSCOV:
1546 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
1549 } /* switch (optname) */
1551 #endif /* LWIP_UDP && LWIP_UDPLITE*/
1552 /* UNDEFINED LEVEL */
1554 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
1555 s, level, optname));
1560 if (err != ERR_OK) {
1561 sock_set_errno(sock, err);
1565 /* Now do the actual option processing */
1568 data.optname = optname;
1569 data.optval = optval;
1570 data.optlen = optlen;
1572 tcpip_callback(lwip_getsockopt_internal, &data);
1573 sys_arch_sem_wait(&sock->conn->op_completed, 0);
1574 /* maybe lwip_getsockopt_internal has changed err */
1577 sock_set_errno(sock, err);
1578 return err ? -1 : 0;
1582 lwip_getsockopt_internal(void *arg)
1584 struct lwip_sock *sock;
1587 #endif /* LWIP_DEBUG */
1590 struct lwip_setgetsockopt_data *data;
1592 LWIP_ASSERT("arg != NULL", arg != NULL);
1594 data = (struct lwip_setgetsockopt_data*)arg;
1598 #endif /* LWIP_DEBUG */
1599 level = data->level;
1600 optname = data->optname;
1601 optval = data->optval;
1605 /* Level: SOL_SOCKET */
1609 /* The option flags */
1612 /* UNIMPL case SO_DEBUG: */
1613 /* UNIMPL case SO_DONTROUTE: */
1615 /* UNIMPL case SO_OOBINCLUDE: */
1619 #endif /* SO_REUSE */
1620 /*case SO_USELOOPBACK: UNIMPL */
1621 *(int*)optval = sock->conn->pcb.ip->so_options & optname;
1622 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
1623 s, optname, (*(int*)optval?"on":"off")));
1627 switch (NETCONNTYPE_GROUP(sock->conn->type)) {
1629 *(int*)optval = SOCK_RAW;
1632 *(int*)optval = SOCK_STREAM;
1635 *(int*)optval = SOCK_DGRAM;
1637 default: /* unrecognized socket type */
1638 *(int*)optval = sock->conn->type;
1639 LWIP_DEBUGF(SOCKETS_DEBUG,
1640 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
1641 s, *(int *)optval));
1642 } /* switch (sock->conn->type) */
1643 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
1644 s, *(int *)optval));
1648 /* only overwrite if ERR_OK before */
1649 if (sock->err == 0) {
1650 sock_set_errno(sock, err_to_errno(sock->conn->last_err));
1652 *(int *)optval = sock->err;
1654 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
1655 s, *(int *)optval));
1658 #if LWIP_SO_RCVTIMEO
1660 *(int *)optval = netconn_get_recvtimeout(sock->conn);
1662 #endif /* LWIP_SO_RCVTIMEO */
1665 *(int *)optval = netconn_get_recvbufsize(sock->conn);
1667 #endif /* LWIP_SO_RCVBUF */
1670 *(int*)optval = (udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_NOCHKSUM) ? 1 : 0;
1672 #endif /* LWIP_UDP*/
1674 LWIP_ASSERT("unhandled optname", 0);
1676 } /* switch (optname) */
1679 /* Level: IPPROTO_IP */
1683 *(int*)optval = sock->conn->pcb.ip->ttl;
1684 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
1685 s, *(int *)optval));
1688 *(int*)optval = sock->conn->pcb.ip->tos;
1689 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
1690 s, *(int *)optval));
1693 case IP_MULTICAST_TTL:
1694 *(u8_t*)optval = sock->conn->pcb.ip->ttl;
1695 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
1696 s, *(int *)optval));
1698 case IP_MULTICAST_IF:
1699 inet_addr_from_ipaddr((struct in_addr*)optval, &sock->conn->pcb.udp->multicast_ip);
1700 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F"\n",
1701 s, *(u32_t *)optval));
1703 #endif /* LWIP_IGMP */
1705 LWIP_ASSERT("unhandled optname", 0);
1707 } /* switch (optname) */
1711 /* Level: IPPROTO_TCP */
1715 *(int*)optval = tcp_nagle_disabled(sock->conn->pcb.tcp);
1716 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
1717 s, (*(int*)optval)?"on":"off") );
1720 *(int*)optval = (int)sock->conn->pcb.tcp->keep_idle;
1721 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
1722 s, *(int *)optval));
1725 #if LWIP_TCP_KEEPALIVE
1727 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_idle/1000);
1728 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
1729 s, *(int *)optval));
1732 *(int*)optval = (int)(sock->conn->pcb.tcp->keep_intvl/1000);
1733 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
1734 s, *(int *)optval));
1737 *(int*)optval = (int)sock->conn->pcb.tcp->keep_cnt;
1738 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
1739 s, *(int *)optval));
1741 #endif /* LWIP_TCP_KEEPALIVE */
1743 LWIP_ASSERT("unhandled optname", 0);
1745 } /* switch (optname) */
1747 #endif /* LWIP_TCP */
1748 #if LWIP_UDP && LWIP_UDPLITE
1749 /* Level: IPPROTO_UDPLITE */
1750 case IPPROTO_UDPLITE:
1752 case UDPLITE_SEND_CSCOV:
1753 *(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
1754 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
1755 s, (*(int*)optval)) );
1757 case UDPLITE_RECV_CSCOV:
1758 *(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
1759 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
1760 s, (*(int*)optval)) );
1763 LWIP_ASSERT("unhandled optname", 0);
1765 } /* switch (optname) */
1767 #endif /* LWIP_UDP */
1769 LWIP_ASSERT("unhandled level", 0);
1771 } /* switch (level) */
1772 sys_sem_signal(&sock->conn->op_completed);
1776 lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
1778 struct lwip_sock *sock = get_socket(s);
1780 struct lwip_setgetsockopt_data data;
1786 if (NULL == optval) {
1787 sock_set_errno(sock, EFAULT);
1791 /* Do length and type checks for the various options first, to keep it readable. */
1794 /* Level: SOL_SOCKET */
1799 /* UNIMPL case SO_DEBUG: */
1800 /* UNIMPL case SO_DONTROUTE: */
1802 /* UNIMPL case case SO_CONTIMEO: */
1803 /* UNIMPL case case SO_SNDTIMEO: */
1804 #if LWIP_SO_RCVTIMEO
1806 #endif /* LWIP_SO_RCVTIMEO */
1809 #endif /* LWIP_SO_RCVBUF */
1810 /* UNIMPL case SO_OOBINLINE: */
1811 /* UNIMPL case SO_SNDBUF: */
1812 /* UNIMPL case SO_RCVLOWAT: */
1813 /* UNIMPL case SO_SNDLOWAT: */
1817 #endif /* SO_REUSE */
1818 /* UNIMPL case SO_USELOOPBACK: */
1819 if (optlen < sizeof(int)) {
1824 if (optlen < sizeof(int)) {
1828 if ((sock->conn->type != NETCONN_UDP) ||
1829 ((udp_flags(sock->conn->pcb.udp) & UDP_FLAGS_UDPLITE) != 0)) {
1830 /* this flag is only available for UDP, not for UDP lite */
1833 #endif /* LWIP_UDP */
1836 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1839 } /* switch (optname) */
1842 /* Level: IPPROTO_IP */
1845 /* UNIMPL case IP_HDRINCL: */
1846 /* UNIMPL case IP_RCVDSTADDR: */
1847 /* UNIMPL case IP_RCVIF: */
1850 if (optlen < sizeof(int)) {
1855 case IP_MULTICAST_TTL:
1856 if (optlen < sizeof(u8_t)) {
1859 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1863 case IP_MULTICAST_IF:
1864 if (optlen < sizeof(struct in_addr)) {
1867 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1871 case IP_ADD_MEMBERSHIP:
1872 case IP_DROP_MEMBERSHIP:
1873 if (optlen < sizeof(struct ip_mreq)) {
1876 if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP) {
1880 #endif /* LWIP_IGMP */
1882 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1885 } /* switch (optname) */
1889 /* Level: IPPROTO_TCP */
1891 if (optlen < sizeof(int)) {
1896 /* If this is no TCP socket, ignore any options. */
1897 if (sock->conn->type != NETCONN_TCP)
1903 #if LWIP_TCP_KEEPALIVE
1907 #endif /* LWIP_TCP_KEEPALIVE */
1911 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1914 } /* switch (optname) */
1916 #endif /* LWIP_TCP */
1917 #if LWIP_UDP && LWIP_UDPLITE
1918 /* Level: IPPROTO_UDPLITE */
1919 case IPPROTO_UDPLITE:
1920 if (optlen < sizeof(int)) {
1925 /* If this is no UDP lite socket, ignore any options. */
1926 if (sock->conn->type != NETCONN_UDPLITE)
1930 case UDPLITE_SEND_CSCOV:
1931 case UDPLITE_RECV_CSCOV:
1935 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
1938 } /* switch (optname) */
1940 #endif /* LWIP_UDP && LWIP_UDPLITE */
1941 /* UNDEFINED LEVEL */
1943 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
1944 s, level, optname));
1946 } /* switch (level) */
1949 if (err != ERR_OK) {
1950 sock_set_errno(sock, err);
1955 /* Now do the actual option processing */
1958 data.optname = optname;
1959 data.optval = (void*)optval;
1960 data.optlen = &optlen;
1962 tcpip_callback(lwip_setsockopt_internal, &data);
1963 sys_arch_sem_wait(&sock->conn->op_completed, 0);
1964 /* maybe lwip_setsockopt_internal has changed err */
1967 sock_set_errno(sock, err);
1968 return err ? -1 : 0;
1972 lwip_setsockopt_internal(void *arg)
1974 struct lwip_sock *sock;
1977 #endif /* LWIP_DEBUG */
1980 struct lwip_setgetsockopt_data *data;
1982 LWIP_ASSERT("arg != NULL", arg != NULL);
1984 data = (struct lwip_setgetsockopt_data*)arg;
1988 #endif /* LWIP_DEBUG */
1989 level = data->level;
1990 optname = data->optname;
1991 optval = data->optval;
1995 /* Level: SOL_SOCKET */
1999 /* The option flags */
2001 /* UNIMPL case SO_DEBUG: */
2002 /* UNIMPL case SO_DONTROUTE: */
2004 /* UNIMPL case SO_OOBINCLUDE: */
2008 #endif /* SO_REUSE */
2009 /* UNIMPL case SO_USELOOPBACK: */
2010 if (*(int*)optval) {
2011 sock->conn->pcb.ip->so_options |= optname;
2013 sock->conn->pcb.ip->so_options &= ~optname;
2015 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
2016 s, optname, (*(int*)optval?"on":"off")));
2018 #if LWIP_SO_RCVTIMEO
2020 netconn_set_recvtimeout(sock->conn, *(int*)optval);
2022 #endif /* LWIP_SO_RCVTIMEO */
2025 netconn_set_recvbufsize(sock->conn, *(int*)optval);
2027 #endif /* LWIP_SO_RCVBUF */
2030 if (*(int*)optval) {
2031 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) | UDP_FLAGS_NOCHKSUM);
2033 udp_setflags(sock->conn->pcb.udp, udp_flags(sock->conn->pcb.udp) & ~UDP_FLAGS_NOCHKSUM);
2036 #endif /* LWIP_UDP */
2038 LWIP_ASSERT("unhandled optname", 0);
2040 } /* switch (optname) */
2043 /* Level: IPPROTO_IP */
2047 sock->conn->pcb.ip->ttl = (u8_t)(*(int*)optval);
2048 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
2049 s, sock->conn->pcb.ip->ttl));
2052 sock->conn->pcb.ip->tos = (u8_t)(*(int*)optval);
2053 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
2054 s, sock->conn->pcb.ip->tos));
2057 case IP_MULTICAST_TTL:
2058 sock->conn->pcb.udp->ttl = (u8_t)(*(u8_t*)optval);
2060 case IP_MULTICAST_IF:
2061 inet_addr_to_ipaddr(&sock->conn->pcb.udp->multicast_ip, (struct in_addr*)optval);
2063 case IP_ADD_MEMBERSHIP:
2064 case IP_DROP_MEMBERSHIP:
2066 /* If this is a TCP or a RAW socket, ignore these options. */
2067 struct ip_mreq *imr = (struct ip_mreq *)optval;
2069 ip_addr_t multi_addr;
2070 inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
2071 inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
2072 if(optname == IP_ADD_MEMBERSHIP){
2073 data->err = igmp_joingroup(&if_addr, &multi_addr);
2075 data->err = igmp_leavegroup(&if_addr, &multi_addr);
2077 if(data->err != ERR_OK) {
2078 data->err = EADDRNOTAVAIL;
2082 #endif /* LWIP_IGMP */
2084 LWIP_ASSERT("unhandled optname", 0);
2086 } /* switch (optname) */
2090 /* Level: IPPROTO_TCP */
2094 if (*(int*)optval) {
2095 tcp_nagle_disable(sock->conn->pcb.tcp);
2097 tcp_nagle_enable(sock->conn->pcb.tcp);
2099 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
2100 s, (*(int *)optval)?"on":"off") );
2103 sock->conn->pcb.tcp->keep_idle = (u32_t)(*(int*)optval);
2104 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F"\n",
2105 s, sock->conn->pcb.tcp->keep_idle));
2108 #if LWIP_TCP_KEEPALIVE
2110 sock->conn->pcb.tcp->keep_idle = 1000*(u32_t)(*(int*)optval);
2111 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F"\n",
2112 s, sock->conn->pcb.tcp->keep_idle));
2115 sock->conn->pcb.tcp->keep_intvl = 1000*(u32_t)(*(int*)optval);
2116 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F"\n",
2117 s, sock->conn->pcb.tcp->keep_intvl));
2120 sock->conn->pcb.tcp->keep_cnt = (u32_t)(*(int*)optval);
2121 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F"\n",
2122 s, sock->conn->pcb.tcp->keep_cnt));
2124 #endif /* LWIP_TCP_KEEPALIVE */
2126 LWIP_ASSERT("unhandled optname", 0);
2128 } /* switch (optname) */
2130 #endif /* LWIP_TCP*/
2131 #if LWIP_UDP && LWIP_UDPLITE
2132 /* Level: IPPROTO_UDPLITE */
2133 case IPPROTO_UDPLITE:
2135 case UDPLITE_SEND_CSCOV:
2136 if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
2137 /* don't allow illegal values! */
2138 sock->conn->pcb.udp->chksum_len_tx = 8;
2140 sock->conn->pcb.udp->chksum_len_tx = (u16_t)*(int*)optval;
2142 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
2143 s, (*(int*)optval)) );
2145 case UDPLITE_RECV_CSCOV:
2146 if ((*(int*)optval != 0) && ((*(int*)optval < 8)) || (*(int*)optval > 0xffff)) {
2147 /* don't allow illegal values! */
2148 sock->conn->pcb.udp->chksum_len_rx = 8;
2150 sock->conn->pcb.udp->chksum_len_rx = (u16_t)*(int*)optval;
2152 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
2153 s, (*(int*)optval)) );
2156 LWIP_ASSERT("unhandled optname", 0);
2158 } /* switch (optname) */
2160 #endif /* LWIP_UDP */
2162 LWIP_ASSERT("unhandled level", 0);
2164 } /* switch (level) */
2165 sys_sem_signal(&sock->conn->op_completed);
2169 lwip_ioctl(int s, long cmd, void *argp)
2171 struct lwip_sock *sock = get_socket(s);
2183 sock_set_errno(sock, EINVAL);
2187 SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
2188 if (recv_avail < 0) {
2191 *((u16_t*)argp) = (u16_t)recv_avail;
2193 /* Check if there is data left from the last recv operation. /maq 041215 */
2194 if (sock->lastdata) {
2195 struct pbuf *p = (struct pbuf *)sock->lastdata;
2196 if (netconn_type(sock->conn) != NETCONN_TCP) {
2197 p = ((struct netbuf *)p)->p;
2199 buflen = p->tot_len;
2200 buflen -= sock->lastoffset;
2202 *((u16_t*)argp) += buflen;
2205 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp)));
2206 sock_set_errno(sock, 0);
2211 if (argp && *(u32_t*)argp) {
2214 netconn_set_nonblocking(sock->conn, val);
2215 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val));
2216 sock_set_errno(sock, 0);
2220 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp));
2221 sock_set_errno(sock, ENOSYS); /* not yet implemented */
2223 } /* switch (cmd) */
2226 /** A minimal implementation of fcntl.
2227 * Currently only the commands F_GETFL and F_SETFL are implemented.
2228 * Only the flag O_NONBLOCK is implemented.
2231 lwip_fcntl(int s, int cmd, int val)
2233 struct lwip_sock *sock = get_socket(s);
2236 if (!sock || !sock->conn) {
2242 ret = netconn_is_nonblocking(sock->conn) ? O_NONBLOCK : 0;
2245 if ((val & ~O_NONBLOCK) == 0) {
2246 /* only O_NONBLOCK, all other bits are zero */
2247 netconn_set_nonblocking(sock->conn, val & O_NONBLOCK);
2252 LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s, cmd, val));
2258 #endif /* LWIP_SOCKET */