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);
761 #else /* (LWIP_UDP || LWIP_RAW) */
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
;
792 const struct sockaddr_in
*to_in
;
794 #if !LWIP_TCPIP_CORE_LOCKING
798 sock
= get_socket(s
);
803 if (sock
->conn
->type
== NETCONN_TCP
) {
805 return lwip_send(s
, data
, size
, flags
);
807 sock_set_errno(sock
, err_to_errno(ERR_ARG
));
809 #endif /* LWIP_TCP */
812 /* @todo: split into multiple sendto's? */
813 LWIP_ASSERT("lwip_sendto: size must fit in u16_t", size
<= 0xffff);
814 short_size
= (u16_t
)size
;
815 LWIP_ERROR("lwip_sendto: invalid address", (((to
== NULL
) && (tolen
== 0)) ||
816 ((tolen
== sizeof(struct sockaddr_in
)) &&
817 ((to
->sa_family
) == AF_INET
) && ((((mem_ptr_t
)to
) % 4) == 0))),
818 sock_set_errno(sock
, err_to_errno(ERR_ARG
)); return -1;);
819 to_in
= (const struct sockaddr_in
*)(void*)to
;
821 #if LWIP_TCPIP_CORE_LOCKING
822 /* Should only be consider like a sample or a simple way to experiment this option (no check of "to" field...) */
825 ip_addr_t
*remote_addr
;
827 #if LWIP_NETIF_TX_SINGLE_PBUF
828 p
= pbuf_alloc(PBUF_TRANSPORT
, short_size
, PBUF_RAM
);
830 #if LWIP_CHECKSUM_ON_COPY
832 if (sock
->conn
->type
!= NETCONN_RAW
) {
833 chksum
= LWIP_CHKSUM_COPY(p
->payload
, data
, short_size
);
835 #endif /* LWIP_CHECKSUM_ON_COPY */
836 MEMCPY(p
->payload
, data
, size
);
837 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
838 p
= pbuf_alloc(PBUF_TRANSPORT
, short_size
, PBUF_REF
);
840 p
->payload
= (void*)data
;
841 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
844 inet_addr_to_ipaddr_p(remote_addr
, &to_in
->sin_addr
);
845 remote_port
= ntohs(to_in
->sin_port
);
847 remote_addr
= IP_ADDR_ANY
;
852 if (sock
->conn
->type
== NETCONN_RAW
) {
853 err
= sock
->conn
->last_err
= raw_sendto(sock
->conn
->pcb
.raw
, p
, remote_addr
);
855 #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF
856 err
= sock
->conn
->last_err
= udp_sendto_chksum(sock
->conn
->pcb
.udp
, p
,
857 remote_addr
, remote_port
, 1, chksum
);
858 #else /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
859 err
= sock
->conn
->last_err
= udp_sendto(sock
->conn
->pcb
.udp
, p
,
860 remote_addr
, remote_port
);
861 #endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */
870 #else /* LWIP_TCPIP_CORE_LOCKING */
871 /* initialize a buffer */
872 buf
.p
= buf
.ptr
= NULL
;
873 #if LWIP_CHECKSUM_ON_COPY
875 #endif /* LWIP_CHECKSUM_ON_COPY */
877 inet_addr_to_ipaddr(&buf
.addr
, &to_in
->sin_addr
);
878 remote_port
= ntohs(to_in
->sin_port
);
879 netbuf_fromport(&buf
) = remote_port
;
882 ip_addr_set_any(&buf
.addr
);
883 netbuf_fromport(&buf
) = 0;
886 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F
", flags=0x%x to=",
887 s
, data
, short_size
, flags
));
888 ip_addr_debug_print(SOCKETS_DEBUG
, &buf
.addr
);
889 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%"U16_F
"\n", remote_port
));
891 /* make the buffer point to the data that should be sent */
892 #if LWIP_NETIF_TX_SINGLE_PBUF
893 /* Allocate a new netbuf and copy the data into it. */
894 if (netbuf_alloc(&buf
, short_size
) == NULL
) {
897 #if LWIP_CHECKSUM_ON_COPY
898 if (sock
->conn
->type
!= NETCONN_RAW
) {
899 u16_t chksum
= LWIP_CHKSUM_COPY(buf
.p
->payload
, data
, short_size
);
900 netbuf_set_chksum(&buf
, chksum
);
903 #endif /* LWIP_CHECKSUM_ON_COPY */
905 err
= netbuf_take(&buf
, data
, short_size
);
908 #else /* LWIP_NETIF_TX_SINGLE_PBUF */
909 err
= netbuf_ref(&buf
, data
, short_size
);
910 #endif /* LWIP_NETIF_TX_SINGLE_PBUF */
913 err
= netconn_send(sock
->conn
, &buf
);
916 /* deallocated the buffer */
918 #endif /* LWIP_TCPIP_CORE_LOCKING */
919 sock_set_errno(sock
, err_to_errno(err
));
920 return (err
== ERR_OK
? short_size
: -1);
924 lwip_socket(int domain
, int type
, int protocol
)
926 struct netconn
*conn
;
929 LWIP_UNUSED_ARG(domain
);
931 /* create a netconn */
934 conn
= netconn_new_with_proto_and_callback(NETCONN_RAW
, (u8_t
)protocol
, event_callback
);
935 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%s, SOCK_RAW, %d) = ",
936 domain
== PF_INET
? "PF_INET" : "UNKNOWN", protocol
));
939 conn
= netconn_new_with_callback( (protocol
== IPPROTO_UDPLITE
) ?
940 NETCONN_UDPLITE
: NETCONN_UDP
, event_callback
);
941 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
942 domain
== PF_INET
? "PF_INET" : "UNKNOWN", protocol
));
945 conn
= netconn_new_with_callback(NETCONN_TCP
, event_callback
);
946 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%s, SOCK_STREAM, %d) = ",
947 domain
== PF_INET
? "PF_INET" : "UNKNOWN", protocol
));
949 /* Prevent automatic window updates, we do this on our own! */
950 netconn_set_noautorecved(conn
, 1);
954 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n",
955 domain
, type
, protocol
));
961 LWIP_DEBUGF(SOCKETS_DEBUG
, ("-1 / ENOBUFS (could not create netconn)\n"));
966 i
= alloc_socket(conn
, 0);
969 netconn_delete(conn
);
974 LWIP_DEBUGF(SOCKETS_DEBUG
, ("%d\n", i
));
980 lwip_write(int s
, const void *data
, size_t size
)
982 return lwip_send(s
, data
, size
, 0);
986 * Go through the readset and writeset lists and see which socket of the sockets
987 * set in the sets has events. On return, readset, writeset and exceptset have
988 * the sockets enabled that had events.
990 * exceptset is not used for now!!!
992 * @param maxfdp1 the highest socket index in the sets
993 * @param readset_in: set of sockets to check for read events
994 * @param writeset_in: set of sockets to check for write events
995 * @param exceptset_in: set of sockets to check for error events
996 * @param readset_out: set of sockets that had read events
997 * @param writeset_out: set of sockets that had write events
998 * @param exceptset_out: set os sockets that had error events
999 * @return number of sockets that had events (read/write/exception) (>= 0)
1002 lwip_selscan(int maxfdp1
, fd_set
*readset_in
, fd_set
*writeset_in
, fd_set
*exceptset_in
,
1003 fd_set
*readset_out
, fd_set
*writeset_out
, fd_set
*exceptset_out
)
1006 fd_set lreadset
, lwriteset
, lexceptset
;
1007 struct lwip_sock
*sock
;
1008 SYS_ARCH_DECL_PROTECT(lev
);
1011 FD_ZERO(&lwriteset
);
1012 FD_ZERO(&lexceptset
);
1014 /* Go through each socket in each list to count number of sockets which
1016 for(i
= 0; i
< maxfdp1
; i
++) {
1017 void* lastdata
= NULL
;
1019 u16_t sendevent
= 0;
1021 /* First get the socket's status (protected)... */
1022 SYS_ARCH_PROTECT(lev
);
1023 sock
= tryget_socket(i
);
1025 lastdata
= sock
->lastdata
;
1026 rcvevent
= sock
->rcvevent
;
1027 sendevent
= sock
->sendevent
;
1028 errevent
= sock
->errevent
;
1030 SYS_ARCH_UNPROTECT(lev
);
1031 /* ... then examine it: */
1032 /* See if netconn of this socket is ready for read */
1033 if (readset_in
&& FD_ISSET(i
, readset_in
) && ((lastdata
!= NULL
) || (rcvevent
> 0))) {
1034 FD_SET(i
, &lreadset
);
1035 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_selscan: fd=%d ready for reading\n", i
));
1038 /* See if netconn of this socket is ready for write */
1039 if (writeset_in
&& FD_ISSET(i
, writeset_in
) && (sendevent
!= 0)) {
1040 FD_SET(i
, &lwriteset
);
1041 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_selscan: fd=%d ready for writing\n", i
));
1044 /* See if netconn of this socket had an error */
1045 if (exceptset_in
&& FD_ISSET(i
, exceptset_in
) && (errevent
!= 0)) {
1046 FD_SET(i
, &lexceptset
);
1047 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_selscan: fd=%d ready for exception\n", i
));
1051 /* copy local sets to the ones provided as arguments */
1052 *readset_out
= lreadset
;
1053 *writeset_out
= lwriteset
;
1054 *exceptset_out
= lexceptset
;
1056 LWIP_ASSERT("nready >= 0", nready
>= 0);
1061 * Processing exceptset is not yet implemented.
1064 lwip_select(int maxfdp1
, fd_set
*readset
, fd_set
*writeset
, fd_set
*exceptset
,
1065 struct timeval
*timeout
)
1069 fd_set lreadset
, lwriteset
, lexceptset
;
1071 struct lwip_select_cb select_cb
;
1074 SYS_ARCH_DECL_PROTECT(lev
);
1076 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F
" tvusec=%"S32_F
")\n",
1077 maxfdp1
, (void *)readset
, (void *) writeset
, (void *) exceptset
,
1078 timeout
? (s32_t
)timeout
->tv_sec
: (s32_t
)-1,
1079 timeout
? (s32_t
)timeout
->tv_usec
: (s32_t
)-1));
1081 /* Go through each socket in each list to count number of sockets which
1083 nready
= lwip_selscan(maxfdp1
, readset
, writeset
, exceptset
, &lreadset
, &lwriteset
, &lexceptset
);
1085 /* If we don't have any current events, then suspend if we are supposed to */
1087 if (timeout
&& timeout
->tv_sec
== 0 && timeout
->tv_usec
== 0) {
1088 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select: no timeout, returning 0\n"));
1089 /* This is OK as the local fdsets are empty and nready is zero,
1090 or we would have returned earlier. */
1091 goto return_copy_fdsets
;
1094 /* None ready: add our semaphore to list:
1095 We don't actually need any dynamic memory. Our entry on the
1096 list is only valid while we are in this function, so it's ok
1097 to use local variables. */
1099 select_cb
.next
= NULL
;
1100 select_cb
.prev
= NULL
;
1101 select_cb
.readset
= readset
;
1102 select_cb
.writeset
= writeset
;
1103 select_cb
.exceptset
= exceptset
;
1104 select_cb
.sem_signalled
= 0;
1105 err
= sys_sem_new(&select_cb
.sem
, 0);
1106 if (err
!= ERR_OK
) {
1107 /* failed to create semaphore */
1112 /* Protect the select_cb_list */
1113 SYS_ARCH_PROTECT(lev
);
1115 /* Put this select_cb on top of list */
1116 select_cb
.next
= select_cb_list
;
1117 if (select_cb_list
!= NULL
) {
1118 select_cb_list
->prev
= &select_cb
;
1120 select_cb_list
= &select_cb
;
1121 /* Increasing this counter tells even_callback that the list has changed. */
1124 /* Now we can safely unprotect */
1125 SYS_ARCH_UNPROTECT(lev
);
1127 /* Increase select_waiting for each socket we are interested in */
1128 for(i
= 0; i
< maxfdp1
; i
++) {
1129 if ((readset
&& FD_ISSET(i
, readset
)) ||
1130 (writeset
&& FD_ISSET(i
, writeset
)) ||
1131 (exceptset
&& FD_ISSET(i
, exceptset
))) {
1132 struct lwip_sock
*sock
= tryget_socket(i
);
1133 LWIP_ASSERT("sock != NULL", sock
!= NULL
);
1134 SYS_ARCH_PROTECT(lev
);
1135 sock
->select_waiting
++;
1136 LWIP_ASSERT("sock->select_waiting > 0", sock
->select_waiting
> 0);
1137 SYS_ARCH_UNPROTECT(lev
);
1141 /* Call lwip_selscan again: there could have been events between
1142 the last scan (whithout us on the list) and putting us on the list! */
1143 nready
= lwip_selscan(maxfdp1
, readset
, writeset
, exceptset
, &lreadset
, &lwriteset
, &lexceptset
);
1145 /* Still none ready, just wait to be woken */
1150 msectimeout
= ((timeout
->tv_sec
* 1000) + ((timeout
->tv_usec
+ 500)/1000));
1151 if (msectimeout
== 0) {
1152 /* Wait 1ms at least (0 means wait forever) */
1157 waitres
= sys_arch_sem_wait(&select_cb
.sem
, msectimeout
);
1159 /* Increase select_waiting for each socket we are interested in */
1160 for(i
= 0; i
< maxfdp1
; i
++) {
1161 if ((readset
&& FD_ISSET(i
, readset
)) ||
1162 (writeset
&& FD_ISSET(i
, writeset
)) ||
1163 (exceptset
&& FD_ISSET(i
, exceptset
))) {
1164 struct lwip_sock
*sock
= tryget_socket(i
);
1165 LWIP_ASSERT("sock != NULL", sock
!= NULL
);
1166 SYS_ARCH_PROTECT(lev
);
1167 sock
->select_waiting
--;
1168 LWIP_ASSERT("sock->select_waiting >= 0", sock
->select_waiting
>= 0);
1169 SYS_ARCH_UNPROTECT(lev
);
1172 /* Take us off the list */
1173 SYS_ARCH_PROTECT(lev
);
1174 if (select_cb
.next
!= NULL
) {
1175 select_cb
.next
->prev
= select_cb
.prev
;
1177 if (select_cb_list
== &select_cb
) {
1178 LWIP_ASSERT("select_cb.prev == NULL", select_cb
.prev
== NULL
);
1179 select_cb_list
= select_cb
.next
;
1181 LWIP_ASSERT("select_cb.prev != NULL", select_cb
.prev
!= NULL
);
1182 select_cb
.prev
->next
= select_cb
.next
;
1184 SYS_ARCH_UNPROTECT(lev
);
1186 sys_sem_free(&select_cb
.sem
);
1187 if (waitres
== SYS_ARCH_TIMEOUT
) {
1189 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select: timeout expired\n"));
1190 /* This is OK as the local fdsets are empty and nready is zero,
1191 or we would have returned earlier. */
1192 goto return_copy_fdsets
;
1195 /* See what's set */
1196 nready
= lwip_selscan(maxfdp1
, readset
, writeset
, exceptset
, &lreadset
, &lwriteset
, &lexceptset
);
1199 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select: nready=%d\n", nready
));
1203 *readset
= lreadset
;
1206 *writeset
= lwriteset
;
1209 *exceptset
= lexceptset
;
1217 * Callback registered in the netconn layer for each socket-netconn.
1218 * Processes recvevent (data available) and wakes up tasks waiting for select.
1221 event_callback(struct netconn
*conn
, enum netconn_evt evt
, u16_t len
)
1224 struct lwip_sock
*sock
;
1225 struct lwip_select_cb
*scb
;
1226 SYS_ARCH_DECL_PROTECT(lev
);
1228 LWIP_UNUSED_ARG(len
);
1234 /* Data comes in right away after an accept, even though
1235 * the server task might not have created a new socket yet.
1236 * Just count down (or up) if that's the case and we
1237 * will use the data later. Note that only receive events
1238 * can happen before the new socket is set up. */
1239 SYS_ARCH_PROTECT(lev
);
1240 if (conn
->socket
< 0) {
1241 if (evt
== NETCONN_EVT_RCVPLUS
) {
1244 SYS_ARCH_UNPROTECT(lev
);
1248 SYS_ARCH_UNPROTECT(lev
);
1251 sock
= get_socket(s
);
1259 SYS_ARCH_PROTECT(lev
);
1260 /* Set event as required */
1262 case NETCONN_EVT_RCVPLUS
:
1265 case NETCONN_EVT_RCVMINUS
:
1268 case NETCONN_EVT_SENDPLUS
:
1269 sock
->sendevent
= 1;
1271 case NETCONN_EVT_SENDMINUS
:
1272 sock
->sendevent
= 0;
1274 case NETCONN_EVT_ERROR
:
1278 LWIP_ASSERT("unknown event", 0);
1282 if (sock
->select_waiting
== 0) {
1283 /* noone is waiting for this socket, no need to check select_cb_list */
1284 SYS_ARCH_UNPROTECT(lev
);
1288 SYS_ARCH_UNPROTECT(lev
);
1290 /* Now decide if anyone is waiting for this socket */
1291 /* NOTE: This code is written this way to protect the select link list
1292 but to avoid a deadlock situation by releasing select_lock before
1293 signalling for the select. This means we need to go through the list
1294 multiple times ONLY IF a select was actually waiting. We go through
1295 the list the number of waiting select calls + 1. This list is
1296 expected to be small. */
1298 int last_select_cb_ctr
;
1299 SYS_ARCH_PROTECT(lev
);
1300 for (scb
= select_cb_list
; scb
; scb
= scb
->next
) {
1301 /* @todo: unprotect with each loop and check for changes? */
1302 if (scb
->sem_signalled
== 0) {
1303 /* Test this select call for our socket */
1304 if (scb
->readset
&& FD_ISSET(s
, scb
->readset
)) {
1305 if (sock
->rcvevent
> 0) {
1309 if (scb
->writeset
&& FD_ISSET(s
, scb
->writeset
)) {
1310 if (sock
->sendevent
!= 0) {
1314 if (scb
->exceptset
&& FD_ISSET(s
, scb
->exceptset
)) {
1315 if (sock
->errevent
!= 0) {
1320 /* unlock interrupts with each step */
1321 last_select_cb_ctr
= select_cb_ctr
;
1322 SYS_ARCH_UNPROTECT(lev
);
1323 SYS_ARCH_PROTECT(lev
);
1324 if (last_select_cb_ctr
!= select_cb_ctr
) {
1325 /* someone has changed select_cb_list, restart at the beginning */
1326 scb
= select_cb_list
;
1330 scb
->sem_signalled
= 1;
1331 sys_sem_signal(&scb
->sem
);
1332 SYS_ARCH_UNPROTECT(lev
);
1334 SYS_ARCH_UNPROTECT(lev
);
1341 * Unimplemented: Close one end of a full-duplex connection.
1342 * Currently, the full connection is closed.
1345 lwip_shutdown(int s
, int how
)
1347 struct lwip_sock
*sock
;
1349 u8_t shut_rx
= 0, shut_tx
= 0;
1351 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_shutdown(%d, how=%d)\n", s
, how
));
1353 sock
= get_socket(s
);
1358 if (sock
->conn
!= NULL
) {
1359 if (netconn_type(sock
->conn
) != NETCONN_TCP
) {
1360 sock_set_errno(sock
, EOPNOTSUPP
);
1364 sock_set_errno(sock
, ENOTCONN
);
1368 if (how
== SHUT_RD
) {
1370 } else if (how
== SHUT_WR
) {
1372 } else if(how
== SHUT_RDWR
) {
1376 sock_set_errno(sock
, EINVAL
);
1379 err
= netconn_shutdown(sock
->conn
, shut_rx
, shut_tx
);
1381 sock_set_errno(sock
, err_to_errno(err
));
1382 return (err
== ERR_OK
? 0 : -1);
1386 lwip_getaddrname(int s
, struct sockaddr
*name
, socklen_t
*namelen
, u8_t local
)
1388 struct lwip_sock
*sock
;
1389 struct sockaddr_in sin
;
1392 sock
= get_socket(s
);
1397 memset(&sin
, 0, sizeof(sin
));
1398 sin
.sin_len
= sizeof(sin
);
1399 sin
.sin_family
= AF_INET
;
1401 /* get the IP address and port */
1402 netconn_getaddr(sock
->conn
, &naddr
, &sin
.sin_port
, local
);
1404 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getaddrname(%d, addr=", s
));
1405 ip_addr_debug_print(SOCKETS_DEBUG
, &naddr
);
1406 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%"U16_F
")\n", sin
.sin_port
));
1408 sin
.sin_port
= htons(sin
.sin_port
);
1409 inet_addr_from_ipaddr(&sin
.sin_addr
, &naddr
);
1411 if (*namelen
> sizeof(sin
)) {
1412 *namelen
= sizeof(sin
);
1415 MEMCPY(name
, &sin
, *namelen
);
1416 sock_set_errno(sock
, 0);
1421 lwip_getpeername(int s
, struct sockaddr
*name
, socklen_t
*namelen
)
1423 return lwip_getaddrname(s
, name
, namelen
, 0);
1427 lwip_getsockname(int s
, struct sockaddr
*name
, socklen_t
*namelen
)
1429 return lwip_getaddrname(s
, name
, namelen
, 1);
1433 lwip_getsockopt(int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
1436 struct lwip_sock
*sock
= get_socket(s
);
1437 struct lwip_setgetsockopt_data data
;
1443 if ((NULL
== optval
) || (NULL
== optlen
)) {
1444 sock_set_errno(sock
, EFAULT
);
1448 /* Do length and type checks for the various options first, to keep it readable. */
1451 /* Level: SOL_SOCKET */
1457 /* UNIMPL case SO_DEBUG: */
1458 /* UNIMPL case SO_DONTROUTE: */
1461 /* UNIMPL case SO_CONTIMEO: */
1462 /* UNIMPL case SO_SNDTIMEO: */
1463 #if LWIP_SO_RCVTIMEO
1465 #endif /* LWIP_SO_RCVTIMEO */
1468 #endif /* LWIP_SO_RCVBUF */
1469 /* UNIMPL case SO_OOBINLINE: */
1470 /* UNIMPL case SO_SNDBUF: */
1471 /* UNIMPL case SO_RCVLOWAT: */
1472 /* UNIMPL case SO_SNDLOWAT: */
1476 #endif /* SO_REUSE */
1478 /* UNIMPL case SO_USELOOPBACK: */
1479 if (*optlen
< sizeof(int)) {
1485 if (*optlen
< sizeof(int)) {
1489 if ((sock
->conn
->type
!= NETCONN_UDP
) ||
1490 ((udp_flags(sock
->conn
->pcb
.udp
) & UDP_FLAGS_UDPLITE
) != 0)) {
1491 /* this flag is only available for UDP, not for UDP lite */
1494 #endif /* LWIP_UDP */
1498 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1501 } /* switch (optname) */
1504 /* Level: IPPROTO_IP */
1507 /* UNIMPL case IP_HDRINCL: */
1508 /* UNIMPL case IP_RCVDSTADDR: */
1509 /* UNIMPL case IP_RCVIF: */
1512 if (*optlen
< sizeof(int)) {
1517 case IP_MULTICAST_TTL
:
1518 if (*optlen
< sizeof(u8_t
)) {
1522 case IP_MULTICAST_IF
:
1523 if (*optlen
< sizeof(struct in_addr
)) {
1527 case IP_MULTICAST_LOOP
:
1528 if (*optlen
< sizeof(u8_t
)) {
1531 if (NETCONNTYPE_GROUP(sock
->conn
->type
) != NETCONN_UDP
) {
1535 #endif /* LWIP_IGMP */
1538 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1541 } /* switch (optname) */
1545 /* Level: IPPROTO_TCP */
1547 if (*optlen
< sizeof(int)) {
1552 /* If this is no TCP socket, ignore any options. */
1553 if (sock
->conn
->type
!= NETCONN_TCP
)
1559 #if LWIP_TCP_KEEPALIVE
1563 #endif /* LWIP_TCP_KEEPALIVE */
1567 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1570 } /* switch (optname) */
1572 #endif /* LWIP_TCP */
1573 #if LWIP_UDP && LWIP_UDPLITE
1574 /* Level: IPPROTO_UDPLITE */
1575 case IPPROTO_UDPLITE
:
1576 if (*optlen
< sizeof(int)) {
1581 /* If this is no UDP lite socket, ignore any options. */
1582 if (sock
->conn
->type
!= NETCONN_UDPLITE
) {
1587 case UDPLITE_SEND_CSCOV
:
1588 case UDPLITE_RECV_CSCOV
:
1592 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
1595 } /* switch (optname) */
1597 #endif /* LWIP_UDP && LWIP_UDPLITE*/
1598 /* UNDEFINED LEVEL */
1600 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
1601 s
, level
, optname
));
1606 if (err
!= ERR_OK
) {
1607 sock_set_errno(sock
, err
);
1611 /* Now do the actual option processing */
1614 data
.optname
= optname
;
1615 data
.optval
= optval
;
1616 data
.optlen
= optlen
;
1618 tcpip_callback(lwip_getsockopt_internal
, &data
);
1619 sys_arch_sem_wait(&sock
->conn
->op_completed
, 0);
1620 /* maybe lwip_getsockopt_internal has changed err */
1623 sock_set_errno(sock
, err
);
1624 return err
? -1 : 0;
1628 lwip_getsockopt_internal(void *arg
)
1630 struct lwip_sock
*sock
;
1633 #endif /* LWIP_DEBUG */
1636 struct lwip_setgetsockopt_data
*data
;
1638 LWIP_ASSERT("arg != NULL", arg
!= NULL
);
1640 data
= (struct lwip_setgetsockopt_data
*)arg
;
1644 #endif /* LWIP_DEBUG */
1645 level
= data
->level
;
1646 optname
= data
->optname
;
1647 optval
= data
->optval
;
1651 /* Level: SOL_SOCKET */
1655 /* The option flags */
1658 /* UNIMPL case SO_DEBUG: */
1659 /* UNIMPL case SO_DONTROUTE: */
1661 /* UNIMPL case SO_OOBINCLUDE: */
1665 #endif /* SO_REUSE */
1666 /*case SO_USELOOPBACK: UNIMPL */
1667 *(int*)optval
= sock
->conn
->pcb
.ip
->so_options
& optname
;
1668 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n",
1669 s
, optname
, (*(int*)optval
?"on":"off")));
1673 switch (NETCONNTYPE_GROUP(sock
->conn
->type
)) {
1675 *(int*)optval
= SOCK_RAW
;
1678 *(int*)optval
= SOCK_STREAM
;
1681 *(int*)optval
= SOCK_DGRAM
;
1683 default: /* unrecognized socket type */
1684 *(int*)optval
= sock
->conn
->type
;
1685 LWIP_DEBUGF(SOCKETS_DEBUG
,
1686 ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n",
1687 s
, *(int *)optval
));
1688 } /* switch (sock->conn->type) */
1689 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n",
1690 s
, *(int *)optval
));
1694 /* only overwrite if ERR_OK before */
1695 if (sock
->err
== 0) {
1696 sock_set_errno(sock
, err_to_errno(sock
->conn
->last_err
));
1698 *(int *)optval
= sock
->err
;
1700 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n",
1701 s
, *(int *)optval
));
1704 #if LWIP_SO_RCVTIMEO
1706 *(int *)optval
= netconn_get_recvtimeout(sock
->conn
);
1708 #endif /* LWIP_SO_RCVTIMEO */
1711 *(int *)optval
= netconn_get_recvbufsize(sock
->conn
);
1713 #endif /* LWIP_SO_RCVBUF */
1716 *(int*)optval
= (udp_flags(sock
->conn
->pcb
.udp
) & UDP_FLAGS_NOCHKSUM
) ? 1 : 0;
1718 #endif /* LWIP_UDP*/
1720 LWIP_ASSERT("unhandled optname", 0);
1722 } /* switch (optname) */
1725 /* Level: IPPROTO_IP */
1729 *(int*)optval
= sock
->conn
->pcb
.ip
->ttl
;
1730 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n",
1731 s
, *(int *)optval
));
1734 *(int*)optval
= sock
->conn
->pcb
.ip
->tos
;
1735 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n",
1736 s
, *(int *)optval
));
1739 case IP_MULTICAST_TTL
:
1740 *(u8_t
*)optval
= sock
->conn
->pcb
.ip
->ttl
;
1741 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_TTL) = %d\n",
1742 s
, *(int *)optval
));
1744 case IP_MULTICAST_IF
:
1745 inet_addr_from_ipaddr((struct in_addr
*)optval
, &sock
->conn
->pcb
.udp
->multicast_ip
);
1746 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_IF) = 0x%"X32_F
"\n",
1747 s
, *(u32_t
*)optval
));
1749 case IP_MULTICAST_LOOP
:
1750 if ((sock
->conn
->pcb
.udp
->flags
& UDP_FLAGS_MULTICAST_LOOP
) != 0) {
1755 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, IP_MULTICAST_LOOP) = %d\n",
1756 s
, *(int *)optval
));
1758 #endif /* LWIP_IGMP */
1760 LWIP_ASSERT("unhandled optname", 0);
1762 } /* switch (optname) */
1766 /* Level: IPPROTO_TCP */
1770 *(int*)optval
= tcp_nagle_disabled(sock
->conn
->pcb
.tcp
);
1771 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n",
1772 s
, (*(int*)optval
)?"on":"off") );
1775 *(int*)optval
= (int)sock
->conn
->pcb
.tcp
->keep_idle
;
1776 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n",
1777 s
, *(int *)optval
));
1780 #if LWIP_TCP_KEEPALIVE
1782 *(int*)optval
= (int)(sock
->conn
->pcb
.tcp
->keep_idle
/1000);
1783 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPIDLE) = %d\n",
1784 s
, *(int *)optval
));
1787 *(int*)optval
= (int)(sock
->conn
->pcb
.tcp
->keep_intvl
/1000);
1788 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPINTVL) = %d\n",
1789 s
, *(int *)optval
));
1792 *(int*)optval
= (int)sock
->conn
->pcb
.tcp
->keep_cnt
;
1793 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPCNT) = %d\n",
1794 s
, *(int *)optval
));
1796 #endif /* LWIP_TCP_KEEPALIVE */
1798 LWIP_ASSERT("unhandled optname", 0);
1800 } /* switch (optname) */
1802 #endif /* LWIP_TCP */
1803 #if LWIP_UDP && LWIP_UDPLITE
1804 /* Level: IPPROTO_UDPLITE */
1805 case IPPROTO_UDPLITE
:
1807 case UDPLITE_SEND_CSCOV
:
1808 *(int*)optval
= sock
->conn
->pcb
.udp
->chksum_len_tx
;
1809 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
1810 s
, (*(int*)optval
)) );
1812 case UDPLITE_RECV_CSCOV
:
1813 *(int*)optval
= sock
->conn
->pcb
.udp
->chksum_len_rx
;
1814 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
1815 s
, (*(int*)optval
)) );
1818 LWIP_ASSERT("unhandled optname", 0);
1820 } /* switch (optname) */
1822 #endif /* LWIP_UDP */
1824 LWIP_ASSERT("unhandled level", 0);
1826 } /* switch (level) */
1827 sys_sem_signal(&sock
->conn
->op_completed
);
1831 lwip_setsockopt(int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1833 struct lwip_sock
*sock
= get_socket(s
);
1835 struct lwip_setgetsockopt_data data
;
1841 if (NULL
== optval
) {
1842 sock_set_errno(sock
, EFAULT
);
1846 /* Do length and type checks for the various options first, to keep it readable. */
1849 /* Level: SOL_SOCKET */
1854 /* UNIMPL case SO_DEBUG: */
1855 /* UNIMPL case SO_DONTROUTE: */
1857 /* UNIMPL case case SO_CONTIMEO: */
1858 /* UNIMPL case case SO_SNDTIMEO: */
1859 #if LWIP_SO_RCVTIMEO
1861 #endif /* LWIP_SO_RCVTIMEO */
1864 #endif /* LWIP_SO_RCVBUF */
1865 /* UNIMPL case SO_OOBINLINE: */
1866 /* UNIMPL case SO_SNDBUF: */
1867 /* UNIMPL case SO_RCVLOWAT: */
1868 /* UNIMPL case SO_SNDLOWAT: */
1872 #endif /* SO_REUSE */
1873 /* UNIMPL case SO_USELOOPBACK: */
1874 if (optlen
< sizeof(int)) {
1879 if (optlen
< sizeof(int)) {
1883 if ((sock
->conn
->type
!= NETCONN_UDP
) ||
1884 ((udp_flags(sock
->conn
->pcb
.udp
) & UDP_FLAGS_UDPLITE
) != 0)) {
1885 /* this flag is only available for UDP, not for UDP lite */
1888 #endif /* LWIP_UDP */
1891 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n",
1894 } /* switch (optname) */
1897 /* Level: IPPROTO_IP */
1900 /* UNIMPL case IP_HDRINCL: */
1901 /* UNIMPL case IP_RCVDSTADDR: */
1902 /* UNIMPL case IP_RCVIF: */
1905 if (optlen
< sizeof(int)) {
1910 case IP_MULTICAST_TTL
:
1911 if (optlen
< sizeof(u8_t
)) {
1914 if (NETCONNTYPE_GROUP(sock
->conn
->type
) != NETCONN_UDP
) {
1918 case IP_MULTICAST_IF
:
1919 if (optlen
< sizeof(struct in_addr
)) {
1922 if (NETCONNTYPE_GROUP(sock
->conn
->type
) != NETCONN_UDP
) {
1926 case IP_MULTICAST_LOOP
:
1927 if (optlen
< sizeof(u8_t
)) {
1930 if (NETCONNTYPE_GROUP(sock
->conn
->type
) != NETCONN_UDP
) {
1934 case IP_ADD_MEMBERSHIP
:
1935 case IP_DROP_MEMBERSHIP
:
1936 if (optlen
< sizeof(struct ip_mreq
)) {
1939 if (NETCONNTYPE_GROUP(sock
->conn
->type
) != NETCONN_UDP
) {
1943 #endif /* LWIP_IGMP */
1945 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n",
1948 } /* switch (optname) */
1952 /* Level: IPPROTO_TCP */
1954 if (optlen
< sizeof(int)) {
1959 /* If this is no TCP socket, ignore any options. */
1960 if (sock
->conn
->type
!= NETCONN_TCP
)
1966 #if LWIP_TCP_KEEPALIVE
1970 #endif /* LWIP_TCP_KEEPALIVE */
1974 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
1977 } /* switch (optname) */
1979 #endif /* LWIP_TCP */
1980 #if LWIP_UDP && LWIP_UDPLITE
1981 /* Level: IPPROTO_UDPLITE */
1982 case IPPROTO_UDPLITE
:
1983 if (optlen
< sizeof(int)) {
1988 /* If this is no UDP lite socket, ignore any options. */
1989 if (sock
->conn
->type
!= NETCONN_UDPLITE
)
1993 case UDPLITE_SEND_CSCOV
:
1994 case UDPLITE_RECV_CSCOV
:
1998 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
2001 } /* switch (optname) */
2003 #endif /* LWIP_UDP && LWIP_UDPLITE */
2004 /* UNDEFINED LEVEL */
2006 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
2007 s
, level
, optname
));
2009 } /* switch (level) */
2012 if (err
!= ERR_OK
) {
2013 sock_set_errno(sock
, err
);
2018 /* Now do the actual option processing */
2021 data
.optname
= optname
;
2022 data
.optval
= (void*)optval
;
2023 data
.optlen
= &optlen
;
2025 tcpip_callback(lwip_setsockopt_internal
, &data
);
2026 sys_arch_sem_wait(&sock
->conn
->op_completed
, 0);
2027 /* maybe lwip_setsockopt_internal has changed err */
2030 sock_set_errno(sock
, err
);
2031 return err
? -1 : 0;
2035 lwip_setsockopt_internal(void *arg
)
2037 struct lwip_sock
*sock
;
2040 #endif /* LWIP_DEBUG */
2043 struct lwip_setgetsockopt_data
*data
;
2045 LWIP_ASSERT("arg != NULL", arg
!= NULL
);
2047 data
= (struct lwip_setgetsockopt_data
*)arg
;
2051 #endif /* LWIP_DEBUG */
2052 level
= data
->level
;
2053 optname
= data
->optname
;
2054 optval
= data
->optval
;
2058 /* Level: SOL_SOCKET */
2062 /* The option flags */
2064 /* UNIMPL case SO_DEBUG: */
2065 /* UNIMPL case SO_DONTROUTE: */
2067 /* UNIMPL case SO_OOBINCLUDE: */
2071 #endif /* SO_REUSE */
2072 /* UNIMPL case SO_USELOOPBACK: */
2073 if (*(int*)optval
) {
2074 sock
->conn
->pcb
.ip
->so_options
|= optname
;
2076 sock
->conn
->pcb
.ip
->so_options
&= ~optname
;
2078 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n",
2079 s
, optname
, (*(int*)optval
?"on":"off")));
2081 #if LWIP_SO_RCVTIMEO
2083 netconn_set_recvtimeout(sock
->conn
, *(int*)optval
);
2085 #endif /* LWIP_SO_RCVTIMEO */
2088 netconn_set_recvbufsize(sock
->conn
, *(int*)optval
);
2090 #endif /* LWIP_SO_RCVBUF */
2093 if (*(int*)optval
) {
2094 udp_setflags(sock
->conn
->pcb
.udp
, udp_flags(sock
->conn
->pcb
.udp
) | UDP_FLAGS_NOCHKSUM
);
2096 udp_setflags(sock
->conn
->pcb
.udp
, udp_flags(sock
->conn
->pcb
.udp
) & ~UDP_FLAGS_NOCHKSUM
);
2099 #endif /* LWIP_UDP */
2101 LWIP_ASSERT("unhandled optname", 0);
2103 } /* switch (optname) */
2106 /* Level: IPPROTO_IP */
2110 sock
->conn
->pcb
.ip
->ttl
= (u8_t
)(*(int*)optval
);
2111 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %d\n",
2112 s
, sock
->conn
->pcb
.ip
->ttl
));
2115 sock
->conn
->pcb
.ip
->tos
= (u8_t
)(*(int*)optval
);
2116 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %d\n",
2117 s
, sock
->conn
->pcb
.ip
->tos
));
2120 case IP_MULTICAST_TTL
:
2121 sock
->conn
->pcb
.udp
->ttl
= (u8_t
)(*(u8_t
*)optval
);
2123 case IP_MULTICAST_IF
:
2124 inet_addr_to_ipaddr(&sock
->conn
->pcb
.udp
->multicast_ip
, (struct in_addr
*)optval
);
2126 case IP_MULTICAST_LOOP
:
2127 if (*(u8_t
*)optval
) {
2128 udp_setflags(sock
->conn
->pcb
.udp
, udp_flags(sock
->conn
->pcb
.udp
) | UDP_FLAGS_MULTICAST_LOOP
);
2130 udp_setflags(sock
->conn
->pcb
.udp
, udp_flags(sock
->conn
->pcb
.udp
) & ~UDP_FLAGS_MULTICAST_LOOP
);
2133 case IP_ADD_MEMBERSHIP
:
2134 case IP_DROP_MEMBERSHIP
:
2136 /* If this is a TCP or a RAW socket, ignore these options. */
2137 struct ip_mreq
*imr
= (struct ip_mreq
*)optval
;
2139 ip_addr_t multi_addr
;
2140 inet_addr_to_ipaddr(&if_addr
, &imr
->imr_interface
);
2141 inet_addr_to_ipaddr(&multi_addr
, &imr
->imr_multiaddr
);
2142 if(optname
== IP_ADD_MEMBERSHIP
){
2143 data
->err
= igmp_joingroup(&if_addr
, &multi_addr
);
2145 data
->err
= igmp_leavegroup(&if_addr
, &multi_addr
);
2147 if(data
->err
!= ERR_OK
) {
2148 data
->err
= EADDRNOTAVAIL
;
2152 #endif /* LWIP_IGMP */
2154 LWIP_ASSERT("unhandled optname", 0);
2156 } /* switch (optname) */
2160 /* Level: IPPROTO_TCP */
2164 if (*(int*)optval
) {
2165 tcp_nagle_disable(sock
->conn
->pcb
.tcp
);
2167 tcp_nagle_enable(sock
->conn
->pcb
.tcp
);
2169 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n",
2170 s
, (*(int *)optval
)?"on":"off") );
2173 sock
->conn
->pcb
.tcp
->keep_idle
= (u32_t
)(*(int*)optval
);
2174 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %"U32_F
"\n",
2175 s
, sock
->conn
->pcb
.tcp
->keep_idle
));
2178 #if LWIP_TCP_KEEPALIVE
2180 sock
->conn
->pcb
.tcp
->keep_idle
= 1000*(u32_t
)(*(int*)optval
);
2181 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPIDLE) -> %"U32_F
"\n",
2182 s
, sock
->conn
->pcb
.tcp
->keep_idle
));
2185 sock
->conn
->pcb
.tcp
->keep_intvl
= 1000*(u32_t
)(*(int*)optval
);
2186 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPINTVL) -> %"U32_F
"\n",
2187 s
, sock
->conn
->pcb
.tcp
->keep_intvl
));
2190 sock
->conn
->pcb
.tcp
->keep_cnt
= (u32_t
)(*(int*)optval
);
2191 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPCNT) -> %"U32_F
"\n",
2192 s
, sock
->conn
->pcb
.tcp
->keep_cnt
));
2194 #endif /* LWIP_TCP_KEEPALIVE */
2196 LWIP_ASSERT("unhandled optname", 0);
2198 } /* switch (optname) */
2200 #endif /* LWIP_TCP*/
2201 #if LWIP_UDP && LWIP_UDPLITE
2202 /* Level: IPPROTO_UDPLITE */
2203 case IPPROTO_UDPLITE
:
2205 case UDPLITE_SEND_CSCOV
:
2206 if ((*(int*)optval
!= 0) && ((*(int*)optval
< 8)) || (*(int*)optval
> 0xffff)) {
2207 /* don't allow illegal values! */
2208 sock
->conn
->pcb
.udp
->chksum_len_tx
= 8;
2210 sock
->conn
->pcb
.udp
->chksum_len_tx
= (u16_t
)*(int*)optval
;
2212 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %d\n",
2213 s
, (*(int*)optval
)) );
2215 case UDPLITE_RECV_CSCOV
:
2216 if ((*(int*)optval
!= 0) && ((*(int*)optval
< 8)) || (*(int*)optval
> 0xffff)) {
2217 /* don't allow illegal values! */
2218 sock
->conn
->pcb
.udp
->chksum_len_rx
= 8;
2220 sock
->conn
->pcb
.udp
->chksum_len_rx
= (u16_t
)*(int*)optval
;
2222 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %d\n",
2223 s
, (*(int*)optval
)) );
2226 LWIP_ASSERT("unhandled optname", 0);
2228 } /* switch (optname) */
2230 #endif /* LWIP_UDP */
2232 LWIP_ASSERT("unhandled level", 0);
2234 } /* switch (level) */
2235 sys_sem_signal(&sock
->conn
->op_completed
);
2239 lwip_ioctl(int s
, long cmd
, void *argp
)
2241 struct lwip_sock
*sock
= get_socket(s
);
2253 sock_set_errno(sock
, EINVAL
);
2257 SYS_ARCH_GET(sock
->conn
->recv_avail
, recv_avail
);
2258 if (recv_avail
< 0) {
2261 *((u16_t
*)argp
) = (u16_t
)recv_avail
;
2263 /* Check if there is data left from the last recv operation. /maq 041215 */
2264 if (sock
->lastdata
) {
2265 struct pbuf
*p
= (struct pbuf
*)sock
->lastdata
;
2266 if (netconn_type(sock
->conn
) != NETCONN_TCP
) {
2267 p
= ((struct netbuf
*)p
)->p
;
2269 buflen
= p
->tot_len
;
2270 buflen
-= sock
->lastoffset
;
2272 *((u16_t
*)argp
) += buflen
;
2275 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F
"\n", s
, argp
, *((u16_t
*)argp
)));
2276 sock_set_errno(sock
, 0);
2281 if (argp
&& *(u32_t
*)argp
) {
2284 netconn_set_nonblocking(sock
->conn
, val
);
2285 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_ioctl(%d, FIONBIO, %d)\n", s
, val
));
2286 sock_set_errno(sock
, 0);
2290 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s
, cmd
, argp
));
2291 sock_set_errno(sock
, ENOSYS
); /* not yet implemented */
2293 } /* switch (cmd) */
2296 /** A minimal implementation of fcntl.
2297 * Currently only the commands F_GETFL and F_SETFL are implemented.
2298 * Only the flag O_NONBLOCK is implemented.
2301 lwip_fcntl(int s
, int cmd
, int val
)
2303 struct lwip_sock
*sock
= get_socket(s
);
2306 if (!sock
|| !sock
->conn
) {
2312 ret
= netconn_is_nonblocking(sock
->conn
) ? O_NONBLOCK
: 0;
2315 if ((val
& ~O_NONBLOCK
) == 0) {
2316 /* only O_NONBLOCK, all other bits are zero */
2317 netconn_set_nonblocking(sock
->conn
, val
& O_NONBLOCK
);
2322 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_fcntl(%d, UNIMPL: %d, %d)\n", s
, cmd
, val
));
2328 #endif /* LWIP_SOCKET */