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