2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
31 * Improved by Marc Boucher <marc@mbsi.ca> and David Haas <dhaas@alum.rpi.edu>
37 #include "lwip/arch.h"
40 #include "lwip/sockets.h"
48 #define NUM_SOCKETS MEMP_NUM_NETCONN
52 struct netbuf
*lastdata
;
62 struct lwip_select_cb
*next
;
70 static struct lwip_socket sockets
[NUM_SOCKETS
];
71 static struct lwip_select_cb
*select_cb_list
= 0;
73 static sys_sem_t socksem
= 0;
74 static sys_sem_t selectsem
= 0;
77 event_callback(struct netconn
*conn
, enum netconn_evt evt
, u16_t len
);
79 static int err_to_errno_table
[11] = {
80 0, /* ERR_OK 0 No error, everything OK. */
81 ENOMEM
, /* ERR_MEM -1 Out of memory error. */
82 ENOBUFS
, /* ERR_BUF -2 Buffer error. */
83 ECONNABORTED
, /* ERR_ABRT -3 Connection aborted. */
84 ECONNRESET
, /* ERR_RST -4 Connection reset. */
85 ESHUTDOWN
, /* ERR_CLSD -5 Connection closed. */
86 ENOTCONN
, /* ERR_CONN -6 Not connected. */
87 EINVAL
, /* ERR_VAL -7 Illegal value. */
88 EIO
, /* ERR_ARG -8 Illegal argument. */
89 EHOSTUNREACH
, /* ERR_RTE -9 Routing problem. */
90 EADDRINUSE
/* ERR_USE -10 Address in use. */
93 #define err_to_errno(err) \
94 ((err) < (sizeof(err_to_errno_table)/sizeof(int))) ? \
95 err_to_errno_table[-(err)] : EIO
98 #define set_errno(err) errno = (err)
100 #define set_errno(err)
103 #define sock_set_errno(sk, e) do { \
105 set_errno(sk->err); \
109 static struct lwip_socket
*
112 struct lwip_socket
*sock
;
114 if ((s
< 0) || (s
> NUM_SOCKETS
)) {
115 LWIP_DEBUGF(SOCKETS_DEBUG
, ("get_socket(%d): invalid\n", s
));
123 LWIP_DEBUGF(SOCKETS_DEBUG
, ("get_socket(%d): not active\n", s
));
132 alloc_socket(struct netconn
*newconn
)
137 socksem
= sys_sem_new(1);
139 /* Protect socket array */
140 sys_sem_wait(socksem
);
142 /* allocate a new socket identifier */
143 for(i
= 0; i
< NUM_SOCKETS
; ++i
) {
144 if (!sockets
[i
].conn
) {
145 sockets
[i
].conn
= newconn
;
146 sockets
[i
].lastdata
= NULL
;
147 sockets
[i
].lastoffset
= 0;
148 sockets
[i
].rcvevent
= 0;
149 sockets
[i
].sendevent
= 1; /* TCP send buf is empty */
150 sockets
[i
].flags
= 0;
152 sys_sem_signal(socksem
);
156 sys_sem_signal(socksem
);
161 lwip_accept(int s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
163 struct lwip_socket
*sock
;
164 struct netconn
*newconn
;
165 struct ip_addr naddr
;
168 struct sockaddr_in sin
;
170 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_accept(%d)...\n", s
));
171 sock
= get_socket(s
);
177 newconn
= netconn_accept(sock
->conn
);
179 /* get the IP address and port of the remote host */
180 netconn_peer(newconn
, &naddr
, &port
);
182 mips_memset(&sin
, 0, sizeof(sin
));
183 sin
.sin_len
= sizeof(sin
);
184 sin
.sin_family
= AF_INET
;
185 sin
.sin_port
= htons(port
);
186 sin
.sin_addr
.s_addr
= naddr
.addr
;
188 if (*addrlen
> sizeof(sin
))
189 *addrlen
= sizeof(sin
);
191 mips_memcpy(addr
, &sin
, *addrlen
);
193 newsock
= alloc_socket(newconn
);
195 netconn_delete(newconn
);
196 sock_set_errno(sock
, ENOBUFS
);
199 newconn
->callback
= event_callback
;
200 sock
= get_socket(newsock
);
202 sys_sem_wait(socksem
);
203 sock
->rcvevent
+= -1 - newconn
->socket
;
204 newconn
->socket
= newsock
;
205 sys_sem_signal(socksem
);
207 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_accept(%d) returning new sock=%d addr=", s
, newsock
));
208 ip_addr_debug_print(SOCKETS_DEBUG
, &naddr
);
209 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%u\n", port
));
211 sock_set_errno(sock
, 0);
216 lwip_bind(int s
, struct sockaddr
*name
, socklen_t namelen
)
218 struct lwip_socket
*sock
;
219 struct ip_addr local_addr
;
223 sock
= get_socket(s
);
229 local_addr
.addr
= ((struct sockaddr_in
*)name
)->sin_addr
.s_addr
;
230 local_port
= ((struct sockaddr_in
*)name
)->sin_port
;
232 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_bind(%d, addr=", s
));
233 ip_addr_debug_print(SOCKETS_DEBUG
, &local_addr
);
234 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%u)\n", ntohs(local_port
)));
236 err
= netconn_bind(sock
->conn
, &local_addr
, ntohs(local_port
));
239 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_bind(%d) failed, err=%d\n", s
, err
));
240 sock_set_errno(sock
, err_to_errno(err
));
244 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_bind(%d) succeeded\n", s
));
245 sock_set_errno(sock
, 0);
252 struct lwip_socket
*sock
;
254 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_close(%d)\n", s
));
256 socksem
= sys_sem_new(1);
258 /* We cannot allow multiple closes of the same socket. */
259 sys_sem_wait(socksem
);
261 sock
= get_socket(s
);
263 sys_sem_signal(socksem
);
268 netconn_delete(sock
->conn
);
269 if (sock
->lastdata
) {
270 netbuf_delete(sock
->lastdata
);
272 sock
->lastdata
= NULL
;
273 sock
->lastoffset
= 0;
275 sys_sem_signal(socksem
);
276 sock_set_errno(sock
, 0);
281 lwip_connect(int s
, struct sockaddr
*name
, socklen_t namelen
)
283 struct lwip_socket
*sock
;
286 sock
= get_socket(s
);
292 if (((struct sockaddr_in
*)name
)->sin_family
== AF_UNSPEC
) {
293 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_connect(%d, AF_UNSPEC)\n", s
));
294 err
= netconn_disconnect(sock
->conn
);
296 struct ip_addr remote_addr
;
299 remote_addr
.addr
= ((struct sockaddr_in
*)name
)->sin_addr
.s_addr
;
300 remote_port
= ((struct sockaddr_in
*)name
)->sin_port
;
302 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_connect(%d, addr=", s
));
303 ip_addr_debug_print(SOCKETS_DEBUG
, &remote_addr
);
304 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%u)\n", ntohs(remote_port
)));
306 err
= netconn_connect(sock
->conn
, &remote_addr
, ntohs(remote_port
));
310 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_connect(%d) failed, err=%d\n", s
, err
));
311 sock_set_errno(sock
, err_to_errno(err
));
315 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_connect(%d) succeeded\n", s
));
316 sock_set_errno(sock
, 0);
321 lwip_listen(int s
, int backlog
)
323 struct lwip_socket
*sock
;
326 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_listen(%d, backlog=%d)\n", s
, backlog
));
327 sock
= get_socket(s
);
333 err
= netconn_listen(sock
->conn
);
336 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_listen(%d) failed, err=%d\n", s
, err
));
337 sock_set_errno(sock
, err_to_errno(err
));
341 sock_set_errno(sock
, 0);
346 lwip_recvfrom(int s
, void *header
, int index
, void *payload
, int plen
, unsigned int flags
,
347 struct sockaddr
*from
, socklen_t
*fromlen
)
349 struct lwip_socket
*sock
;
351 u16_t avail_len
, copylen
= 0;
352 struct ip_addr
*addr
;
356 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s
, payload
, plen
, flags
));
357 sock
= get_socket(s
);
363 /* Check if there is data left from the last recv operation. */
364 if (sock
->lastdata
) {
365 buf
= sock
->lastdata
;
367 /* If this is non-blocking call, then check first */
368 if (((flags
& MSG_DONTWAIT
) || (sock
->flags
& O_NONBLOCK
))
371 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_recvfrom(%d): returning EWOULDBLOCK\n", s
));
372 sock_set_errno(sock
, EWOULDBLOCK
);
376 /* No data was left from the previous operation, so we try to get
377 some from the network. */
378 buf
= netconn_recv(sock
->conn
);
381 /* We should really do some error checking here. */
382 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_recvfrom(%d): buf == NULL!\n", s
));
383 sock_set_errno(sock
, 0);
388 avail_len
= netbuf_len(buf
);
390 avail_len
-= sock
->lastoffset
;
392 /* copy the contents of the received buffer into
393 the supplied memory pointer mem */
395 if (avail_len
>= 63) { // header of READ ANDX RESPONSE is 63 + padding bytes, which are "0x00" thus useless
396 netbuf_copy_partial(buf
, header
, 63, sock
->lastoffset
);
397 index
= ((u8_t
*)header
)[index
] + 4;
401 netbuf_copy_partial(buf
, header
, avail_len
, sock
->lastoffset
);
408 if (plen
> avail_len
)
411 netbuf_copy_partial(buf
, payload
, plen
, sock
->lastoffset
+ index
);
416 /* Check to see from where the data was. */
417 if (from
&& fromlen
) {
418 struct sockaddr_in sin
;
420 addr
= netbuf_fromaddr(buf
);
421 port
= netbuf_fromport(buf
);
423 mips_memset(&sin
, 0, sizeof(sin
));
424 sin
.sin_len
= sizeof(sin
);
425 sin
.sin_family
= AF_INET
;
426 sin
.sin_port
= htons(port
);
427 sin
.sin_addr
.s_addr
= addr
->addr
;
429 if (*fromlen
> sizeof(sin
))
430 *fromlen
= sizeof(sin
);
432 mips_memcpy(from
, &sin
, *fromlen
);
434 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_recvfrom(%d): addr=", s
));
435 ip_addr_debug_print(SOCKETS_DEBUG
, addr
);
436 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%u len=%u\n", port
, copylen
));
438 #if SOCKETS_DEBUG > 0
439 addr
= netbuf_fromaddr(buf
);
440 port
= netbuf_fromport(buf
);
442 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_recvfrom(%d): addr=", s
));
443 ip_addr_debug_print(SOCKETS_DEBUG
, addr
);
444 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%u len=%u\n", port
, copylen
));
448 /* If this is a TCP socket, check if there is data left in the
449 buffer. If so, it should be saved in the sock structure for next
451 if (netconn_type(sock
->conn
) == NETCONN_TCP
&& avail_len
> 0) {
452 sock
->lastdata
= buf
;
453 sock
->lastoffset
+= copylen
;
455 sock
->lastdata
= NULL
;
456 sock
->lastoffset
= 0;
460 sock_set_errno(sock
, 0);
465 lwip_read(int s
, void *mem
, int len
)
467 return lwip_recvfrom(s
, NULL
, 0, mem
, len
, 0, NULL
, NULL
);
471 lwip_recv(int s
, void *mem
, int len
, unsigned int flags
)
473 return lwip_recvfrom(s
, NULL
, 0, mem
, len
, flags
, NULL
, NULL
);
477 lwip_send(int s
, void *data
, int size
, unsigned int flags
)
479 struct lwip_socket
*sock
;
483 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s
, data
, size
, flags
));
485 sock
= get_socket(s
);
491 switch (netconn_type(sock
->conn
)) {
494 case NETCONN_UDPLITE
:
495 case NETCONN_UDPNOCHKSUM
:
496 /* create a buffer */
500 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_send(%d) ENOBUFS\n", s
));
501 sock_set_errno(sock
, ENOBUFS
);
505 /* make the buffer point to the data that should
507 netbuf_ref(buf
, data
, size
);
510 err
= netconn_send(sock
->conn
, buf
);
512 /* deallocated the buffer */
516 err
= netconn_write(sock
->conn
, data
, size
, NETCONN_COPY
);
523 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_send(%d) err=%d\n", s
, err
));
524 sock_set_errno(sock
, err_to_errno(err
));
528 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_send(%d) ok size=%d\n", s
, size
));
529 sock_set_errno(sock
, 0);
534 lwip_sendto(int s
, void *data
, int size
, unsigned int flags
,
535 struct sockaddr
*to
, socklen_t tolen
)
537 struct lwip_socket
*sock
;
538 struct ip_addr remote_addr
, addr
;
539 u16_t remote_port
, port
;
542 sock
= get_socket(s
);
548 /* get the peer if currently connected */
549 connected
= (netconn_peer(sock
->conn
, &addr
, &port
) == ERR_OK
);
551 remote_addr
.addr
= ((struct sockaddr_in
*)to
)->sin_addr
.s_addr
;
552 remote_port
= ((struct sockaddr_in
*)to
)->sin_port
;
554 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s
, data
, size
, flags
));
555 ip_addr_debug_print(SOCKETS_DEBUG
, &remote_addr
);
556 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%u\n", ntohs(remote_port
)));
558 netconn_connect(sock
->conn
, &remote_addr
, ntohs(remote_port
));
560 ret
= lwip_send(s
, data
, size
, flags
);
562 /* reset the remote address and port number
565 netconn_connect(sock
->conn
, &addr
, port
);
567 netconn_disconnect(sock
->conn
);
572 lwip_socket(int domain
, int type
, int protocol
)
574 struct netconn
*conn
;
577 /* create a netconn */
580 conn
= netconn_new_with_proto_and_callback(NETCONN_RAW
, protocol
, event_callback
);
581 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain
== PF_INET
? "PF_INET" : "UNKNOWN", protocol
));
584 conn
= netconn_new_with_callback(NETCONN_UDP
, event_callback
);
585 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain
== PF_INET
? "PF_INET" : "UNKNOWN", protocol
));
588 conn
= netconn_new_with_callback(NETCONN_TCP
, event_callback
);
589 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%s, SOCK_STREAM, %d) = ", domain
== PF_INET
? "PF_INET" : "UNKNOWN", protocol
));
592 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_socket(%d, %d/UNKNOWN, %d) = -1\n", domain
, type
, protocol
));
598 LWIP_DEBUGF(SOCKETS_DEBUG
, ("-1 / ENOBUFS (could not create netconn)\n"));
603 i
= alloc_socket(conn
);
606 netconn_delete(conn
);
611 LWIP_DEBUGF(SOCKETS_DEBUG
, ("%d\n", i
));
617 lwip_write(int s
, void *data
, int size
)
619 return lwip_send(s
, data
, size
, 0);
624 lwip_selscan(int maxfdp1
, fd_set
*readset
, fd_set
*writeset
, fd_set
*exceptset
)
627 fd_set lreadset
, lwriteset
, lexceptset
;
628 struct lwip_socket
*p_sock
;
632 FD_ZERO(&lexceptset
);
634 /* Go through each socket in each list to count number of sockets which
636 for(i
= 0; i
< maxfdp1
; i
++)
638 if (FD_ISSET(i
, readset
))
640 /* See if netconn of this socket is ready for read */
641 p_sock
= get_socket(i
);
642 if (p_sock
&& (p_sock
->lastdata
|| p_sock
->rcvevent
))
644 FD_SET(i
, &lreadset
);
645 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_selscan: fd=%d ready for reading\n", i
));
649 if (FD_ISSET(i
, writeset
))
651 /* See if netconn of this socket is ready for write */
652 p_sock
= get_socket(i
);
653 if (p_sock
&& p_sock
->sendevent
)
655 FD_SET(i
, &lwriteset
);
656 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_selscan: fd=%d ready for writing\n", i
));
662 *writeset
= lwriteset
;
669 lwip_select(int maxfdp1
, fd_set
*readset
, fd_set
*writeset
, fd_set
*exceptset
,
670 struct timeval
*timeout
)
674 fd_set lreadset
, lwriteset
, lexceptset
;
676 struct lwip_select_cb select_cb
;
677 struct lwip_select_cb
*p_selcb
;
679 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", maxfdp1
, (void *)readset
, (void *) writeset
, (void *) exceptset
, timeout
? timeout
->tv_sec
: -1L, timeout
? timeout
->tv_usec
: -1L));
682 select_cb
.readset
= readset
;
683 select_cb
.writeset
= writeset
;
684 select_cb
.exceptset
= exceptset
;
685 select_cb
.sem_signalled
= 0;
687 /* Protect ourselves searching through the list */
689 selectsem
= sys_sem_new(1);
690 sys_sem_wait(selectsem
);
697 lwriteset
= *writeset
;
701 lexceptset
= *exceptset
;
703 FD_ZERO(&lexceptset
);
705 /* Go through each socket in each list to count number of sockets which
707 nready
= lwip_selscan(maxfdp1
, &lreadset
, &lwriteset
, &lexceptset
);
709 /* If we don't have any current events, then suspend if we are supposed to */
712 if (timeout
&& timeout
->tv_sec
== 0 && timeout
->tv_usec
== 0)
714 sys_sem_signal(selectsem
);
722 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select: no timeout, returning 0\n"));
728 /* add our semaphore to list */
729 /* We don't actually need any dynamic memory. Our entry on the
730 * list is only valid while we are in this function, so it's ok
731 * to use local variables */
733 select_cb
.sem
= sys_sem_new(0);
734 /* Note that we are still protected */
735 /* Put this select_cb on top of list */
736 select_cb
.next
= select_cb_list
;
737 select_cb_list
= &select_cb
;
739 /* Now we can safely unprotect */
740 sys_sem_signal(selectsem
);
742 /* Now just wait to be woken */
747 msectimeout
= ((timeout
->tv_sec
* 1000) + ((timeout
->tv_usec
+ 500)/1000));
749 i
= sys_sem_wait_timeout(select_cb
.sem
, msectimeout
);
751 /* Take us off the list */
752 sys_sem_wait(selectsem
);
753 if (select_cb_list
== &select_cb
)
754 select_cb_list
= select_cb
.next
;
756 for (p_selcb
= select_cb_list
; p_selcb
; p_selcb
= p_selcb
->next
)
757 if (p_selcb
->next
== &select_cb
)
759 p_selcb
->next
= select_cb
.next
;
763 sys_sem_signal(selectsem
);
765 sys_sem_free(select_cb
.sem
);
766 if (i
== 0) /* Timeout */
775 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select: timeout expired\n"));
786 lwriteset
= *writeset
;
790 lexceptset
= *exceptset
;
792 FD_ZERO(&lexceptset
);
795 nready
= lwip_selscan(maxfdp1
, &lreadset
, &lwriteset
, &lexceptset
);
798 sys_sem_signal(selectsem
);
803 *writeset
= lwriteset
;
805 *exceptset
= lexceptset
;
807 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_select: nready=%d\n", nready
));
815 event_callback(struct netconn
*conn
, enum netconn_evt evt
, u16_t len
)
818 struct lwip_socket
*sock
;
819 struct lwip_select_cb
*scb
;
827 /* Data comes in right away after an accept, even though
828 * the server task might not have created a new socket yet.
829 * Just count down (or up) if that's the case and we
830 * will use the data later. Note that only receive events
831 * can happen before the new socket is set up. */
832 if (evt
== NETCONN_EVT_RCVPLUS
)
837 sock
= get_socket(s
);
845 selectsem
= sys_sem_new(1);
847 sys_sem_wait(selectsem
);
848 /* Set event as required */
851 case NETCONN_EVT_RCVPLUS
:
854 case NETCONN_EVT_RCVMINUS
:
857 case NETCONN_EVT_SENDPLUS
:
860 case NETCONN_EVT_SENDMINUS
:
864 sys_sem_signal(selectsem
);
866 /* Now decide if anyone is waiting for this socket */
867 /* NOTE: This code is written this way to protect the select link list
868 but to avoid a deadlock situation by releasing socksem before
869 signalling for the select. This means we need to go through the list
870 multiple times ONLY IF a select was actually waiting. We go through
871 the list the number of waiting select calls + 1. This list is
872 expected to be small. */
875 sys_sem_wait(selectsem
);
876 for (scb
= select_cb_list
; scb
; scb
= scb
->next
)
878 if (scb
->sem_signalled
== 0)
880 /* Test this select call for our socket */
881 if (scb
->readset
&& FD_ISSET(s
, scb
->readset
))
884 if (scb
->writeset
&& FD_ISSET(s
, scb
->writeset
))
891 scb
->sem_signalled
= 1;
892 sys_sem_signal(selectsem
);
893 sys_sem_signal(scb
->sem
);
895 sys_sem_signal(selectsem
);
905 int lwip_shutdown(int s
, int how
)
907 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_shutdown(%d, how=%d)\n", s
, how
));
908 return lwip_close(s
); /* XXX temporary hack until proper implementation */
911 int lwip_getpeername (int s
, struct sockaddr
*name
, socklen_t
*namelen
)
913 struct lwip_socket
*sock
;
914 struct sockaddr_in sin
;
915 struct ip_addr naddr
;
917 sock
= get_socket(s
);
923 mips_memset(&sin
, 0, sizeof(sin
));
924 sin
.sin_len
= sizeof(sin
);
925 sin
.sin_family
= AF_INET
;
927 /* get the IP address and port of the remote host */
928 netconn_peer(sock
->conn
, &naddr
, &sin
.sin_port
);
930 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getpeername(%d, addr=", s
));
931 ip_addr_debug_print(SOCKETS_DEBUG
, &naddr
);
932 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%d)\n", sin
.sin_port
));
934 sin
.sin_port
= htons(sin
.sin_port
);
935 sin
.sin_addr
.s_addr
= naddr
.addr
;
937 if (*namelen
> sizeof(sin
))
938 *namelen
= sizeof(sin
);
940 mips_memcpy(name
, &sin
, *namelen
);
941 sock_set_errno(sock
, 0);
945 int lwip_getsockname (int s
, struct sockaddr
*name
, socklen_t
*namelen
)
947 struct lwip_socket
*sock
;
948 struct sockaddr_in sin
;
949 struct ip_addr
*naddr
;
951 sock
= get_socket(s
);
957 mips_memset(&sin
, 0, sizeof(sin
));
958 sin
.sin_len
= sizeof(sin
);
959 sin
.sin_family
= AF_INET
;
961 /* get the IP address and port of the remote host */
962 netconn_addr(sock
->conn
, &naddr
, &sin
.sin_port
);
964 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockname(%d, addr=", s
));
965 ip_addr_debug_print(SOCKETS_DEBUG
, naddr
);
966 LWIP_DEBUGF(SOCKETS_DEBUG
, (" port=%d)\n", sin
.sin_port
));
968 sin
.sin_port
= htons(sin
.sin_port
);
969 sin
.sin_addr
.s_addr
= naddr
->addr
;
971 if (*namelen
> sizeof(sin
))
972 *namelen
= sizeof(sin
);
974 mips_memcpy(name
, &sin
, *namelen
);
975 sock_set_errno(sock
, 0);
979 int lwip_getsockopt (int s
, int level
, int optname
, void *optval
, socklen_t
*optlen
)
982 struct lwip_socket
*sock
= get_socket(s
);
989 if( NULL
== optval
|| NULL
== optlen
) {
990 sock_set_errno( sock
, EFAULT
);
994 /* Do length and type checks for the various options first, to keep it readable. */
997 /* Level: SOL_SOCKET */
1003 /* UNIMPL case SO_DEBUG: */
1004 /* UNIMPL case SO_DONTROUTE: */
1007 /* UNIMPL case SO_OOBINLINE: */
1008 /* UNIMPL case SO_RCVBUF: */
1009 /* UNIMPL case SO_SNDBUF: */
1010 /* UNIMPL case SO_RCVLOWAT: */
1011 /* UNIMPL case SO_SNDLOWAT: */
1015 #endif /* SO_REUSE */
1017 /* UNIMPL case SO_USELOOPBACK: */
1018 if( *optlen
< sizeof(int) ) {
1024 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s
, optname
));
1029 /* Level: IPPROTO_IP */
1032 /* UNIMPL case IP_HDRINCL: */
1033 /* UNIMPL case IP_RCVDSTADDR: */
1034 /* UNIMPL case IP_RCVIF: */
1037 if( *optlen
< sizeof(int) ) {
1043 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s
, optname
));
1048 /* Level: IPPROTO_TCP */
1050 if( *optlen
< sizeof(int) ) {
1055 /* If this is no TCP socket, ignore any options. */
1056 if ( sock
->conn
->type
!= NETCONN_TCP
) return 0;
1061 case TCP_ACKNODELAY
:
1066 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s
, optname
));
1071 /* UNDEFINED LEVEL */
1073 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s
, level
, optname
));
1079 sock_set_errno(sock
, err
);
1085 /* Now do the actual option processing */
1089 /* Level: SOL_SOCKET */
1093 /* The option flags */
1096 /* UNIMPL case SO_DEBUG: */
1097 /* UNIMPL case SO_DONTROUTE: */
1099 /* UNIMPL case SO_OOBINCLUDE: */
1103 #endif /* SO_REUSE */
1104 /*case SO_USELOOPBACK: UNIMPL */
1105 *(int*)optval
= sock
->conn
->pcb
.tcp
->so_options
& optname
;
1106 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s
, optname
, (*(int*)optval
?"on":"off")));
1110 switch (sock
->conn
->type
) {
1112 *(int*)optval
= SOCK_RAW
;
1115 *(int*)optval
= SOCK_STREAM
;
1118 case NETCONN_UDPLITE
:
1119 case NETCONN_UDPNOCHKSUM
:
1120 *(int*)optval
= SOCK_DGRAM
;
1122 default: /* unrecognized socket type */
1123 *(int*)optval
= sock
->conn
->type
;
1124 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s
, *(int *)optval
));
1126 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s
, *(int *)optval
));
1130 *(int *)optval
= sock
->err
;
1132 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s
, *(int *)optval
));
1137 /* Level: IPPROTO_IP */
1141 *(int*)optval
= sock
->conn
->pcb
.tcp
->ttl
;
1142 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s
, *(int *)optval
));
1145 *(int*)optval
= sock
->conn
->pcb
.tcp
->tos
;
1146 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s
, *(int *)optval
));
1151 /* Level: IPPROTO_TCP */
1155 *(int*)optval
= (sock
->conn
->pcb
.tcp
->flags
& TF_NODELAY
);
1156 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s
, (*(int*)optval
)?"on":"off") );
1159 *(int*)optval
= sock
->conn
->pcb
.tcp
->keepalive
;
1160 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s
, *(int *)optval
));
1162 case TCP_ACKNODELAY
:
1163 *(int*)optval
= sock
->conn
->pcb
.tcp
->flags
& TF_ACKNODELAY
;
1164 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_ACKNODELAY) = %s\n", s
, (*(int *)optval
)?"on":"off") );
1167 *(int*)optval
= sock
->conn
->pcb
.tcp
->flags
& TF_EVENSEG
;
1168 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_EVENSEG) = %s\n", s
, (*(int *)optval
)?"on":"off") );
1175 sock_set_errno(sock
, err
);
1176 return err
? -1 : 0;
1179 int lwip_setsockopt (int s
, int level
, int optname
, const void *optval
, socklen_t optlen
)
1181 struct lwip_socket
*sock
= get_socket(s
);
1189 if( NULL
== optval
) {
1190 sock_set_errno( sock
, EFAULT
);
1195 /* Do length and type checks for the various options first, to keep it readable. */
1198 /* Level: SOL_SOCKET */
1203 /* UNIMPL case SO_DEBUG: */
1204 /* UNIMPL case SO_DONTROUTE: */
1206 /* UNIMPL case SO_OOBINLINE: */
1207 /* UNIMPL case SO_RCVBUF: */
1208 /* UNIMPL case SO_SNDBUF: */
1209 /* UNIMPL case SO_RCVLOWAT: */
1210 /* UNIMPL case SO_SNDLOWAT: */
1214 #endif /* SO_REUSE */
1215 /* UNIMPL case SO_USELOOPBACK: */
1216 if( optlen
< sizeof(int) ) {
1221 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s
, optname
));
1226 /* Level: IPPROTO_IP */
1229 /* UNIMPL case IP_HDRINCL: */
1230 /* UNIMPL case IP_RCVDSTADDR: */
1231 /* UNIMPL case IP_RCVIF: */
1234 if( optlen
< sizeof(int) ) {
1239 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s
, optname
));
1244 /* Level: IPPROTO_TCP */
1246 if( optlen
< sizeof(int) ) {
1251 /* If this is no TCP socket, ignore any options. */
1252 if ( sock
->conn
->type
!= NETCONN_TCP
) return 0;
1257 case TCP_ACKNODELAY
:
1262 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s
, optname
));
1267 /* UNDEFINED LEVEL */
1269 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s
, level
, optname
));
1275 sock_set_errno(sock
, err
);
1281 /* Now do the actual option processing */
1285 /* Level: SOL_SOCKET */
1289 /* The option flags */
1291 /* UNIMPL case SO_DEBUG: */
1292 /* UNIMPL case SO_DONTROUTE: */
1294 /* UNIMPL case SO_OOBINCLUDE: */
1298 #endif /* SO_REUSE */
1299 /* UNIMPL case SO_USELOOPBACK: */
1300 if ( *(int*)optval
) {
1301 sock
->conn
->pcb
.tcp
->so_options
|= optname
;
1303 sock
->conn
->pcb
.tcp
->so_options
&= ~optname
;
1305 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s
, optname
, (*(int*)optval
?"on":"off")));
1310 /* Level: IPPROTO_IP */
1314 sock
->conn
->pcb
.tcp
->ttl
= (u8_t
)(*(int*)optval
);
1315 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s
, sock
->conn
->pcb
.tcp
->ttl
));
1318 sock
->conn
->pcb
.tcp
->tos
= (u8_t
)(*(int*)optval
);
1319 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s
, sock
->conn
->pcb
.tcp
->tos
));
1324 /* Level: IPPROTO_TCP */
1328 if ( *(int*)optval
) {
1329 sock
->conn
->pcb
.tcp
->flags
|= TF_NODELAY
;
1331 sock
->conn
->pcb
.tcp
->flags
&= ~TF_NODELAY
;
1333 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s
, (*(int *)optval
)?"on":"off") );
1336 sock
->conn
->pcb
.tcp
->keepalive
= (u32_t
)(*(int*)optval
);
1337 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s
, sock
->conn
->pcb
.tcp
->keepalive
));
1339 case TCP_ACKNODELAY
:
1340 if ( *(int*)optval
) {
1341 sock
->conn
->pcb
.tcp
->flags
|= TF_ACKNODELAY
;
1343 sock
->conn
->pcb
.tcp
->flags
&= ~TF_ACKNODELAY
;
1345 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_ACKNODELAY) -> %s\n", s
, (*(int *)optval
)?"on":"off") );
1348 if ( *(int*)optval
) {
1349 sock
->conn
->pcb
.tcp
->flags
|= TF_EVENSEG
;
1351 sock
->conn
->pcb
.tcp
->flags
&= ~TF_EVENSEG
;
1353 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_EVENSEG) -> %s\n", s
, (*(int *)optval
)?"on":"off") );
1359 sock_set_errno(sock
, err
);
1360 return err
? -1 : 0;
1363 int lwip_ioctl(int s
, long cmd
, void *argp
)
1365 struct lwip_socket
*sock
= get_socket(s
);
1375 sock_set_errno(sock
, EINVAL
);
1379 *((u16_t
*)argp
) = sock
->conn
->recv_avail
;
1381 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s
, argp
, *((u16_t
*)argp
)));
1382 sock_set_errno(sock
, 0);
1386 if (argp
&& *(u32_t
*)argp
)
1387 sock
->flags
|= O_NONBLOCK
;
1389 sock
->flags
&= ~O_NONBLOCK
;
1390 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_ioctl(%d, FIONBIO, %d)\n", s
, !!(sock
->flags
& O_NONBLOCK
)));
1391 sock_set_errno(sock
, 0);
1395 LWIP_DEBUGF(SOCKETS_DEBUG
, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s
, cmd
, argp
));
1396 sock_set_errno(sock
, ENOSYS
); /* not yet implemented */