PORT: Use always interruptible functions for waiting Return SYS_ARCH_INTR when a waiting thread is cancelled POLL: Use always interruptible functions for waiting Fix some debug messages MAX_SOCKETS: Protect the socket list every time it's read All but AUTOCONF: Converted to DOS format to mach lwip sources All: Remove fuzziness
--- debian/patches/bug-36167 | 8 +- debian/patches/errno | 20 +- debian/patches/max_sockets | 75 +- debian/patches/poll | 146 ++-- debian/patches/port | 1943 +++++++++++++++++++++----------------------- debian/patches/posix | 1733 ++++++++++++++++++++------------------- 6 files changed, 1917 insertions(+), 2008 deletions(-) diff --git a/debian/patches/bug-36167 b/debian/patches/bug-36167 index 4220301..e0a6d92 100644 --- a/debian/patches/bug-36167 +++ b/debian/patches/bug-36167 @@ -1,10 +1,8 @@ Already upstream -diff --git a/src/core/tcp.c b/src/core/tcp.c -index 7103a52..ccfa3c1 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c -@@ -804,7 +804,7 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len) +@@ -804,7 +804,7 @@ pcb->rcv_wnd = TCP_WND_MAX(pcb); } else if (pcb->rcv_wnd == 0) { /* rcv_wnd overflowed */ @@ -13,11 +11,9 @@ index 7103a52..ccfa3c1 100644 /* In passive close, we allow this, since the FIN bit is added to rcv_wnd by the stack itself, since it is not mandatory for an application to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */ -diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h -index 3845b9f..fb7fa17 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h -@@ -424,6 +424,9 @@ const char* tcp_debug_state_str(enum tcp_state s); +@@ -424,6 +424,9 @@ /* for compatibility with older implementation */ #define tcp_new_ip6() tcp_new_ip_type(IPADDR_TYPE_V6) diff --git a/debian/patches/errno b/debian/patches/errno index 1cf5d42..9aed02a 100644 --- a/debian/patches/errno +++ b/debian/patches/errno @@ -1,10 +1,8 @@ Already upstream -Index: lwip/src/api/sockets.c -=================================================================== ---- lwip.orig/src/api/sockets.c -+++ lwip/src/api/sockets.c -@@ -213,7 +213,7 @@ struct lwip_sock { +--- a/src/api/sockets.c ++++ b/src/api/sockets.c +@@ -223,7 +223,7 @@ /** error happened for this socket, set by event_callback(), tested by select */ u16_t errevent; /** last error that occurred on this socket (in fact, all our errnos fit into an u8_t) */ @@ -13,7 +11,7 @@ Index: lwip/src/api/sockets.c /** counter of how many threads are waiting for this socket using select */ SELWAIT_T select_waiting; }; -@@ -299,7 +299,7 @@ static volatile int select_cb_ctr; +@@ -309,7 +309,7 @@ #define sock_set_errno(sk, e) do { \ const int sockerr = (e); \ @@ -22,7 +20,7 @@ Index: lwip/src/api/sockets.c set_errno(sockerr); \ } while (0) -@@ -309,8 +309,8 @@ static void event_callback(struct netcon +@@ -319,8 +319,8 @@ static void lwip_getsockopt_callback(void *arg); static void lwip_setsockopt_callback(void *arg); #endif @@ -33,7 +31,7 @@ Index: lwip/src/api/sockets.c #if LWIP_IPV4 && LWIP_IPV6 static void -@@ -1792,7 +1792,7 @@ lwip_getsockname(int s, struct sockaddr +@@ -1804,7 +1804,7 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) { @@ -42,7 +40,7 @@ Index: lwip/src/api/sockets.c struct lwip_sock *sock = get_socket(s); #if !LWIP_TCPIP_CORE_LOCKING LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -@@ -1887,10 +1887,10 @@ lwip_getsockopt_callback(void *arg) +@@ -1899,10 +1899,10 @@ /** lwip_getsockopt_impl: the actual implementation of getsockopt: * same argument as lwip_getsockopt, either called directly or through callback */ @@ -55,7 +53,7 @@ Index: lwip/src/api/sockets.c struct lwip_sock *sock = tryget_socket(s); if (!sock) { return EBADF; -@@ -2198,7 +2198,7 @@ lwip_getsockopt_impl(int s, int level, i +@@ -2210,7 +2210,7 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) { @@ -64,7 +62,7 @@ Index: lwip/src/api/sockets.c struct lwip_sock *sock = get_socket(s); #if !LWIP_TCPIP_CORE_LOCKING LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data); -@@ -2288,10 +2288,10 @@ lwip_setsockopt_callback(void *arg) +@@ -2300,10 +2300,10 @@ /** lwip_setsockopt_impl: the actual implementation of setsockopt: * same argument as lwip_setsockopt, either called directly or through callback */ diff --git a/debian/patches/max_sockets b/debian/patches/max_sockets index 53b4555..1862444 100644 --- a/debian/patches/max_sockets +++ b/debian/patches/max_sockets @@ -33,7 +33,7 @@ Won't get to upstream * in seconds. (does not require sockets.c, and will affect tcp.c) --- a/src/api/sockets.c +++ b/src/api/sockets.c -@@ -198,6 +198,12 @@ +@@ -208,6 +208,12 @@ /** Contains all internal pointers and states used for a socket */ struct lwip_sock { @@ -46,7 +46,7 @@ Won't get to upstream /** sockets currently are built on netconns, each socket has one netconn */ struct netconn *conn; /** data that was left from the previous read */ -@@ -287,8 +293,13 @@ +@@ -297,8 +303,13 @@ static void lwip_socket_drop_registered_memberships(int s); #endif /* LWIP_IGMP */ @@ -60,7 +60,7 @@ Won't get to upstream /** The global list of tasks waiting for select */ static struct lwip_select_cb *select_cb_list; /** This counter is increased from lwip_select when the list is changed -@@ -359,15 +370,26 @@ +@@ -369,15 +380,29 @@ s -= LWIP_SOCKET_OFFSET; @@ -76,10 +76,13 @@ Won't get to upstream } +#if LWIP_SOCKET_OPEN_COUNT ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); + for(sock = sockets; sock != NULL; sock = sock->next) { + if(sock->count == s) + break; + } ++ SYS_ARCH_UNPROTECT(lev); +#else /* LWIP_SOCKET_OPEN_COUNT */ sock = &sockets[s]; +#endif /* LWIP_SOCKET_OPEN_COUNT */ @@ -89,9 +92,14 @@ Won't get to upstream LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): not active\n", s + LWIP_SOCKET_OFFSET)); set_errno(EBADF); return NULL; -@@ -386,13 +408,26 @@ +@@ -395,14 +420,33 @@ + static struct lwip_sock * tryget_socket(int s) { ++#if LWIP_SOCKET_OPEN_COUNT ++ struct lwip_sock *sock; ++#endif /* LWIP_SOCKET_OPEN_COUNT */ ++ s -= LWIP_SOCKET_OFFSET; - if ((s < 0) || (s >= NUM_SOCKETS)) { + if ((s < 0) @@ -102,11 +110,13 @@ Won't get to upstream return NULL; } +#if LWIP_SOCKET_OPEN_COUNT -+ struct lwip_sock *sock; ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); + for(sock = sockets; sock != NULL; sock = sock->next) { + if(sock->count == s) + break; + } ++ SYS_ARCH_UNPROTECT(lev); + return sock; +#else /* LWIP_SOCKET_OPEN_COUNT */ if (!sockets[s].conn) { @@ -117,7 +127,7 @@ Won't get to upstream } /** -@@ -407,30 +442,70 @@ +@@ -417,30 +461,70 @@ alloc_socket(struct netconn *newconn, int accepted) { int i; @@ -199,33 +209,34 @@ Won't get to upstream } /** Free a socket. The socket's netconn must have been -@@ -442,9 +517,14 @@ - static void +@@ -453,6 +537,9 @@ free_socket(struct lwip_sock *sock, int is_tcp) { -- void *lastdata; -- -- lastdata = sock->lastdata; -+ void *lastdata = sock->lastdata; + void *lastdata; +#if LWIP_SOCKET_OPEN_COUNT + struct lwip_sock **it = &sockets; -+ -+ while(*it != sock) it = &(*it)->next; -+ *it = (*it)->next; -+ mem_free(sock); -+#else /* LWIP_SOCKET_OPEN_COUNT */ ++#endif /* LWIP_SOCKET_OPEN_COUNT */ + + lastdata = sock->lastdata; sock->lastdata = NULL; - sock->lastoffset = 0; +@@ -460,7 +547,15 @@ sock->err = 0; -@@ -452,6 +532,7 @@ + /* Protect socket array */ - SYS_ARCH_SET(sock->conn, NULL); - /* don't use 'sock' after this line, as another task might have allocated it */ +- SYS_ARCH_SET(sock->conn, NULL); ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); ++ sock->conn = NULL; ++#if LWIP_SOCKET_OPEN_COUNT ++ while(*it != sock) it = &(*it)->next; ++ *it = (*it)->next; ++ mem_free(sock); +#endif /* LWIP_SOCKET_OPEN_COUNT */ ++ SYS_ARCH_UNPROTECT(lev); + /* don't use 'sock' after this line, as another task might have allocated it */ if (lastdata != NULL) { - if (is_tcp) { -@@ -512,7 +593,9 @@ +@@ -522,7 +617,9 @@ sock_set_errno(sock, ENFILE); return -1; } @@ -238,12 +249,12 @@ Won't get to upstream --- a/port/include/lwipopts.h +++ b/port/include/lwipopts.h @@ -26,6 +26,9 @@ - /* Don't rename Sockets API functions */ - #define LWIP_COMPAT_SOCKETS 0 - -+/* Don't limit the number of sockets */ -+#define LWIP_SOCKET_OPEN_COUNT 1 -+ - /* We're using lwip_poll() */ - #define LWIP_POLL 1 - + /* Don't rename Sockets API functions */ + #define LWIP_COMPAT_SOCKETS 0 + ++/* Don't limit the number of sockets */ ++#define LWIP_SOCKET_OPEN_COUNT 1 ++ + /* We're using lwip_poll() */ + #define LWIP_POLL 1 + diff --git a/debian/patches/poll b/debian/patches/poll index c060cf3..198e258 100644 --- a/debian/patches/poll +++ b/debian/patches/poll @@ -2,7 +2,7 @@ Already upstream --- a/src/api/sockets.c +++ b/src/api/sockets.c -@@ -238,6 +238,12 @@ +@@ -248,6 +248,12 @@ fd_set *writeset; /** unimplemented: exceptset passed to select */ fd_set *exceptset; @@ -15,7 +15,7 @@ Already upstream /** don't signal the same semaphore twice: set to 1 when signalled */ int sem_signalled; /** semaphore to wake up a task waiting for select */ -@@ -1288,6 +1294,51 @@ +@@ -1302,6 +1308,51 @@ return lwip_sendmsg(s, &msg, 0); } @@ -67,7 +67,7 @@ Already upstream /** * Go through the readset and writeset lists and see which socket of the sockets * set in the sets has events. On return, readset, writeset and exceptset have -@@ -1411,6 +1462,10 @@ +@@ -1425,6 +1476,10 @@ select_cb.readset = readset; select_cb.writeset = writeset; select_cb.exceptset = exceptset; @@ -78,7 +78,7 @@ Already upstream select_cb.sem_signalled = 0; #if LWIP_NETCONN_SEM_PER_THREAD select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); -@@ -1422,20 +1477,7 @@ +@@ -1436,20 +1491,7 @@ } #endif /* LWIP_NETCONN_SEM_PER_THREAD */ @@ -100,7 +100,7 @@ Already upstream /* Increase select_waiting for each socket we are interested in */ maxfdp2 = maxfdp1; -@@ -1505,21 +1547,7 @@ +@@ -1519,21 +1561,7 @@ SYS_ARCH_UNPROTECT(lev); } } @@ -123,7 +123,7 @@ Already upstream #if LWIP_NETCONN_SEM_PER_THREAD if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { -@@ -1563,6 +1591,253 @@ +@@ -1577,6 +1605,253 @@ return nready; } @@ -304,7 +304,7 @@ Already upstream + LWIP_ASSERT("timeout > 0", timeout > 0); + msectimeout = timeout; + } -+ waitres = sys_arch_sem_wait_intr(SELECT_SEM_PTR(select_cb.sem), msectimeout); ++ waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); +#if LWIP_NETCONN_SEM_PER_THREAD + waited = 1; +#endif @@ -332,12 +332,12 @@ Already upstream + + if (waitres == SYS_ARCH_TIMEOUT) { + /* Timeout */ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_poll: timeout expired\n")); + goto return_success; + } + } + -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready)); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_poll: nready=%d\n", nready)); +return_success: + set_errno(0); + return nready; @@ -377,7 +377,7 @@ Already upstream /** * Callback registered in the netconn layer for each socket-netconn. * Processes recvevent (data available) and wakes up tasks waiting for select. -@@ -1649,20 +1924,27 @@ +@@ -1663,20 +1938,27 @@ if (scb->sem_signalled == 0) { /* semaphore not signalled yet */ int do_signal = 0; @@ -419,7 +419,7 @@ Already upstream if (do_signal) { --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h -@@ -1751,6 +1751,17 @@ +@@ -1751,6 +1751,17 @@ #endif /** @@ -439,49 +439,49 @@ Already upstream * names (read, write & close). (only used if you use sockets.c) --- a/src/include/lwip/lwip_sockets.h +++ b/src/include/lwip/lwip_sockets.h -@@ -430,6 +430,21 @@ - #error "external FD_SETSIZE too small for number of sockets" - #endif /* FD_SET */ - -+#if LWIP_POLL == 2 -+#define POLLIN 0x01 -+#define POLLOUT 0x02 -+#define POLLERR 0x04 -+#define POLLNVAL 0x08 -+/* No support for POLLPRI, POLLHUP, POLLMSG, POLLRDBAND, POLLWRBAND. */ -+typedef int nfds_t; -+struct pollfd -+{ -+ int fd; -+ short events; -+ short revents; -+}; -+#endif -+ - /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided - * by your system, set this to 0 and include <sys/time.h> in cc.h */ - #ifndef LWIP_TIMEVAL_PRIVATE -@@ -466,6 +481,9 @@ - #define lwip_sendto sendto - #define lwip_socket socket - #define lwip_select select -+#if LWIP_POLL -+#define lwip_poll poll -+#endif - #define lwip_ioctlsocket ioctl - - #if LWIP_POSIX_SOCKETS_IO_NAMES -@@ -516,6 +534,10 @@ - #define socket(domain,type,protocol) lwip_socket(domain,type,protocol) - /** @ingroup socket */ - #define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) -+#if LWIP_POLL -+/** @ingroup socket */ -+#define poll(fds,nfds,timeout) lwip_poll(fds,nfds,timeout) -+#endif - /** @ingroup socket */ - #define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) - +@@ -432,6 +432,21 @@ + #error "external FD_SETSIZE too small for number of sockets" + #endif /* FD_SET */ + ++#if LWIP_POLL == 2 ++#define POLLIN 0x01 ++#define POLLOUT 0x02 ++#define POLLERR 0x04 ++#define POLLNVAL 0x08 ++/* No support for POLLPRI, POLLHUP, POLLMSG, POLLRDBAND, POLLWRBAND. */ ++typedef int nfds_t; ++struct pollfd ++{ ++ int fd; ++ short events; ++ short revents; ++}; ++#endif ++ + /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided + * by your system, set this to 0 and include <sys/time.h> in cc.h */ + #ifndef LWIP_TIMEVAL_PRIVATE +@@ -468,6 +483,9 @@ + #define lwip_sendto sendto + #define lwip_socket socket + #define lwip_select select ++#if LWIP_POLL ++#define lwip_poll poll ++#endif + #define lwip_ioctlsocket ioctl + + #if LWIP_POSIX_SOCKETS_IO_NAMES +@@ -518,6 +536,10 @@ + #define socket(domain,type,protocol) lwip_socket(domain,type,protocol) + /** @ingroup socket */ + #define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) ++#if LWIP_POLL ++/** @ingroup socket */ ++#define poll(fds,nfds,timeout) lwip_poll(fds,nfds,timeout) ++#endif + /** @ingroup socket */ + #define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) + --- a/src/include/lwip/sockets.h +++ b/src/include/lwip/sockets.h @@ -75,6 +75,9 @@ @@ -497,24 +497,24 @@ Already upstream --- a/port/include/lwipopts.h +++ b/port/include/lwipopts.h @@ -26,6 +26,9 @@ - /* Don't rename Sockets API functions */ - #define LWIP_COMPAT_SOCKETS 0 - -+/* We're using lwip_poll() */ -+#define LWIP_POLL 1 -+ - /* Use Glibc's sockets headers */ - #define LWIP_STD_SOCKETS 1 - #define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" + /* Don't rename Sockets API functions */ + #define LWIP_COMPAT_SOCKETS 0 + ++/* We're using lwip_poll() */ ++#define LWIP_POLL 1 ++ + /* Use Glibc's sockets headers */ + #define LWIP_STD_SOCKETS 1 + #define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" --- a/port/include/arch/cc.h +++ b/port/include/arch/cc.h -@@ -46,6 +46,9 @@ - #include <netinet/tcp.h> - #include <netinet/udp.h> - -+/* We use poll() instead of select()*/ -+#include <poll.h> -+ - /* Use our own htons() and pals */ - #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 - +@@ -40,6 +40,9 @@ + /* Use our own ioctls */ + #include <sys/ioctl.h> + ++/* We use poll() instead of select()*/ ++#include <poll.h> ++ + /* Use our own htons() and pals */ + #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 + diff --git a/debian/patches/port b/debian/patches/port index c6c9d82..b0ab392 100644 --- a/debian/patches/port +++ b/debian/patches/port @@ -3,1022 +3,941 @@ Not intended to be upstream --- /dev/null +++ b/port/include/arch/cc.h @@ -0,0 +1,68 @@ -+/* -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ -+ -+#ifndef LWIP_ARCH_CC_H -+#define LWIP_ARCH_CC_H -+ -+#include <stdlib.h> /* rand() */ -+#include <stdio.h> /* printf() */ -+ -+/* Use Glibc's fcntl() macros */ -+#include <fcntl.h> -+ -+/* Use Glibc's <errno.h> */ -+#include <errno.h> -+#define LWIP_ERR_T int -+ -+/* System provides its own struct timeval */ -+#define LWIP_TIMEVAL_PRIVATE 0 -+#include <sys/time.h> -+ -+/* We need INT_MAX */ -+#include <limits.h> -+ -+/* Use our own ioctls */ -+#include <sys/ioctl.h> -+ -+/* Use our own htons() and pals */ -+#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 -+ -+/* printf() codes */ -+#define S16_F "d" -+#define U16_F "u" -+#define X16_F "x" -+ -+#define S32_F "d" -+#define U32_F "u" -+#define X32_F "x" -+ -+#ifdef LWIP_DEBUG -+#define LWIP_PLATFORM_DIAG(x) do { printf x; fflush(NULL);} while(0) -+#endif -+ -+/* Redefine LWIP_ERROR to not abort the process if the assertion failed */ -+#define LWIP_ERROR(message, expression, handler) \ -+ do { \ -+ if (!(expression)) { \ -+ printf("Assertion \"%s\" failed at line %d in %s\n", \ -+ message, __LINE__, __FILE__); fflush(NULL); \ -+ handler;} \ -+ } while(0) -+ -+#endif /* LWIP_ARCH_CC_H */ ++/* ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ ++ ++#ifndef LWIP_ARCH_CC_H ++#define LWIP_ARCH_CC_H ++ ++#include <stdlib.h> /* rand() */ ++#include <stdio.h> /* printf() */ ++ ++/* Use Glibc's fcntl() macros */ ++#include <fcntl.h> ++ ++/* Use Glibc's <errno.h> */ ++#include <errno.h> ++#define LWIP_ERR_T int ++ ++/* System provides its own struct timeval */ ++#define LWIP_TIMEVAL_PRIVATE 0 ++#include <sys/time.h> ++ ++/* We need INT_MAX */ ++#include <limits.h> ++ ++/* Use our own ioctls */ ++#include <sys/ioctl.h> ++ ++/* Use our own htons() and pals */ ++#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 ++ ++/* printf() codes */ ++#define S16_F "d" ++#define U16_F "u" ++#define X16_F "x" ++ ++#define S32_F "d" ++#define U32_F "u" ++#define X32_F "x" ++ ++#ifdef LWIP_DEBUG ++#define LWIP_PLATFORM_DIAG(x) do { printf x; fflush(NULL);} while(0) ++#endif ++ ++/* Redefine LWIP_ERROR to not abort the process if the assertion failed */ ++#define LWIP_ERROR(message, expression, handler) \ ++ do { \ ++ if (!(expression)) { \ ++ printf("Assertion \"%s\" failed at line %d in %s\n", \ ++ message, __LINE__, __FILE__); fflush(NULL); \ ++ handler;} \ ++ } while(0) ++ ++#endif /* LWIP_ARCH_CC_H */ --- /dev/null +++ b/port/include/arch/sys_arch.h -@@ -0,0 +1,64 @@ -+/* -+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -+ * OF SUCH DAMAGE. -+ * -+ * This file is part of the lwIP TCP/IP stack. -+ * -+ * Author: Adam Dunkels <a...@sics.se> -+ * -+ */ -+#ifndef LWIP_ARCH_SYS_ARCH_H -+#define LWIP_ARCH_SYS_ARCH_H -+ -+#define SYS_MBOX_NULL NULL -+#define SYS_SEM_NULL NULL -+ -+/* Return code for an interrupted timed wait */ -+#define SYS_ARCH_INTR 0xfffffffeUL -+ -+typedef u32_t sys_prot_t; -+ -+struct sys_sem; -+typedef struct sys_sem * sys_sem_t; -+#define sys_sem_valid(sem) (*(sem) != NULL) -+#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) -+ -+struct sys_mutex; -+typedef struct sys_mutex * sys_mutex_t; -+#define sys_mutex_valid(mutex) sys_sem_valid(mutex) -+#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) -+ -+struct sys_mbox; -+typedef struct sys_mbox * sys_mbox_t; -+#define sys_mbox_valid(mbox) sys_sem_valid(mbox) -+#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox) -+ -+struct sys_thread; -+typedef struct sys_thread * sys_thread_t; -+ -+u32_t sys_arch_sem_wait_intr(sys_sem_t *sem, u32_t timeout); -+ -+#endif /* LWIP_ARCH_SYS_ARCH_H */ -+ +@@ -0,0 +1,62 @@ ++/* ++ * Copyright (c) 2001-2003 Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without modification, ++ * are permitted provided that the following conditions are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ++ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING ++ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY ++ * OF SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels <a...@sics.se> ++ * ++ */ ++#ifndef LWIP_ARCH_SYS_ARCH_H ++#define LWIP_ARCH_SYS_ARCH_H ++ ++#define SYS_MBOX_NULL NULL ++#define SYS_SEM_NULL NULL ++ ++/* Return code for an interrupted timed wait */ ++#define SYS_ARCH_INTR 0xfffffffeUL ++ ++typedef u32_t sys_prot_t; ++ ++struct sys_sem; ++typedef struct sys_sem * sys_sem_t; ++#define sys_sem_valid(sem) (*(sem) != NULL) ++#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0) ++ ++struct sys_mutex; ++typedef struct sys_mutex * sys_mutex_t; ++#define sys_mutex_valid(mutex) sys_sem_valid(mutex) ++#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) ++ ++struct sys_mbox; ++typedef struct sys_mbox * sys_mbox_t; ++#define sys_mbox_valid(mbox) sys_sem_valid(mbox) ++#define sys_mbox_set_invalid(mbox) sys_sem_set_invalid(mbox) ++ ++struct sys_thread; ++typedef struct sys_thread * sys_thread_t; ++ ++#endif /* LWIP_ARCH_SYS_ARCH_H */ ++ --- /dev/null +++ b/port/include/lwipopts.h @@ -0,0 +1,131 @@ -+/* -+ Copyright (C) 2017 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ -+ -+#ifndef HURD_LWIP_LWIPOPTS_H -+#define HURD_LWIP_LWIPOPTS_H -+ -+/* An OS is present */ -+#define NO_SYS 0 -+ -+/* Don't rename Sockets API functions */ -+#define LWIP_COMPAT_SOCKETS 0 -+ -+/* Use Glibc malloc()/free() */ -+#define MEM_LIBC_MALLOC 1 -+#define MEMP_MEM_MALLOC 1 -+#define MEM_USE_POOLS 0 -+#define MEM_ALIGNMENT 4 -+ -+/* Only send complete packets to the device */ -+#define LWIP_NETIF_TX_SINGLE_PBUF 1 -+ -+/* Randomize local ports */ -+#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 -+ -+/* Glibc sends more than one packet in a row during an ARP resolution */ -+#define ARP_QUEUEING 1 -+#define ARP_QUEUE_LEN 10 -+ -+/* Netif API is needed to add or remove interfaces on run time */ -+#define LWIP_NETIF_API 1 -+ -+/* IPv4 stuff */ -+#define IP_FORWARD 1 -+ -+/* SLAAC support and other IPv6 stuff */ -+#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 -+#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 -+#define LWIP_IPV6_AUTOCONFIG 1 -+#define LWIP_IPV6_FORWARD 1 -+#define MEMP_NUM_MLD6_GROUP 16 -+#define LWIP_IPV6_NUM_ADDRESSES 6 -+ -+/* TCP tuning */ -+#define TCP_MSS 1460 -+#define TCP_WND 0xFFFF -+#define TCP_SND_BUF TCP_WND -+ -+/* Throughput settings */ -+#define LWIP_CHECKSUM_ON_COPY 1 -+ -+/* Disable stats */ -+#define LWIP_STATS 0 -+#define LWIP_STATS_DISPLAY 0 -+ -+/* Enable all socket operations */ -+#define LWIP_TCP_KEEPALIVE 1 -+#define LWIP_SO_SNDTIMEO 1 -+#define LWIP_SO_RCVTIMEO 1 -+#define LWIP_SO_RCVBUF 1 -+#define LWIP_SO_LINGER 1 -+#define SO_REUSE 1 -+#define LWIP_MULTICAST_TX_OPTIONS 1 -+ -+/* Enable modules */ -+#define LWIP_ARP 1 -+#define LWIP_ETHERNET 1 -+#define LWIP_IPV4 1 -+#define LWIP_ICMP 1 -+#define LWIP_IGMP 1 -+#define LWIP_RAW 1 -+#define LWIP_UDP 1 -+#define LWIP_UDPLITE 1 -+#define LWIP_TCP 1 -+#define LWIP_IPV6 1 -+#define LWIP_ICMP6 1 -+#define LWIP_IPV6_MLD 1 -+#define LWIP_NETIF_LOOPBACK 1 -+ -+/* Debug mode */ -+#ifdef LWIP_DEBUG -+#define ETHARP_DEBUG LWIP_DBG_OFF -+#define NETIF_DEBUG LWIP_DBG_OFF -+#define PBUF_DEBUG LWIP_DBG_OFF -+#define API_LIB_DEBUG LWIP_DBG_OFF -+#define API_MSG_DEBUG LWIP_DBG_OFF -+#define SOCKETS_DEBUG LWIP_DBG_OFF -+#define ICMP_DEBUG LWIP_DBG_OFF -+#define IGMP_DEBUG LWIP_DBG_OFF -+#define INET_DEBUG LWIP_DBG_OFF -+#define IP_DEBUG LWIP_DBG_OFF -+#define IP_REASS_DEBUG LWIP_DBG_OFF -+#define RAW_DEBUG LWIP_DBG_OFF -+#define MEM_DEBUG LWIP_DBG_OFF -+#define MEMP_DEBUG LWIP_DBG_OFF -+#define SYS_DEBUG LWIP_DBG_OFF -+#define TIMERS_DEBUG LWIP_DBG_OFF -+#define TCP_DEBUG LWIP_DBG_OFF -+#define TCP_INPUT_DEBUG LWIP_DBG_OFF -+#define TCP_FR_DEBUG LWIP_DBG_OFF -+#define TCP_RTO_DEBUG LWIP_DBG_OFF -+#define TCP_CWND_DEBUG LWIP_DBG_OFF -+#define TCP_WND_DEBUG LWIP_DBG_OFF -+#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF -+#define TCP_RST_DEBUG LWIP_DBG_OFF -+#define TCP_QLEN_DEBUG LWIP_DBG_OFF -+#define UDP_DEBUG LWIP_DBG_OFF -+#define TCPIP_DEBUG LWIP_DBG_OFF -+#define SLIP_DEBUG LWIP_DBG_OFF -+#define DHCP_DEBUG LWIP_DBG_OFF -+#define AUTOIP_DEBUG LWIP_DBG_OFF -+#define DNS_DEBUG LWIP_DBG_OFF -+#define IP6_DEBUG LWIP_DBG_OFF -+#endif -+ -+#endif ++/* ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ ++ ++#ifndef HURD_LWIP_LWIPOPTS_H ++#define HURD_LWIP_LWIPOPTS_H ++ ++/* An OS is present */ ++#define NO_SYS 0 ++ ++/* Don't rename Sockets API functions */ ++#define LWIP_COMPAT_SOCKETS 0 ++ ++/* Use Glibc malloc()/free() */ ++#define MEM_LIBC_MALLOC 1 ++#define MEMP_MEM_MALLOC 1 ++#define MEM_USE_POOLS 0 ++#define MEM_ALIGNMENT 4 ++ ++/* Only send complete packets to the device */ ++#define LWIP_NETIF_TX_SINGLE_PBUF 1 ++ ++/* Randomize local ports */ ++#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 1 ++ ++/* Glibc sends more than one packet in a row during an ARP resolution */ ++#define ARP_QUEUEING 1 ++#define ARP_QUEUE_LEN 10 ++ ++/* Netif API is needed to add or remove interfaces on run time */ ++#define LWIP_NETIF_API 1 ++ ++/* IPv4 stuff */ ++#define IP_FORWARD 1 ++ ++/* SLAAC support and other IPv6 stuff */ ++#define LWIP_IPV6_DUP_DETECT_ATTEMPTS 1 ++#define LWIP_IPV6_SEND_ROUTER_SOLICIT 1 ++#define LWIP_IPV6_AUTOCONFIG 1 ++#define LWIP_IPV6_FORWARD 1 ++#define MEMP_NUM_MLD6_GROUP 16 ++#define LWIP_IPV6_NUM_ADDRESSES 6 ++ ++/* TCP tuning */ ++#define TCP_MSS 1460 ++#define TCP_WND 0xFFFF ++#define TCP_SND_BUF TCP_WND ++ ++/* Throughput settings */ ++#define LWIP_CHECKSUM_ON_COPY 1 ++ ++/* Disable stats */ ++#define LWIP_STATS 0 ++#define LWIP_STATS_DISPLAY 0 ++ ++/* Enable all socket operations */ ++#define LWIP_TCP_KEEPALIVE 1 ++#define LWIP_SO_SNDTIMEO 1 ++#define LWIP_SO_RCVTIMEO 1 ++#define LWIP_SO_RCVBUF 1 ++#define LWIP_SO_LINGER 1 ++#define SO_REUSE 1 ++#define LWIP_MULTICAST_TX_OPTIONS 1 ++ ++/* Enable modules */ ++#define LWIP_ARP 1 ++#define LWIP_ETHERNET 1 ++#define LWIP_IPV4 1 ++#define LWIP_ICMP 1 ++#define LWIP_IGMP 1 ++#define LWIP_RAW 1 ++#define LWIP_UDP 1 ++#define LWIP_UDPLITE 1 ++#define LWIP_TCP 1 ++#define LWIP_IPV6 1 ++#define LWIP_ICMP6 1 ++#define LWIP_IPV6_MLD 1 ++#define LWIP_NETIF_LOOPBACK 1 ++ ++/* Debug mode */ ++#ifdef LWIP_DEBUG ++#define ETHARP_DEBUG LWIP_DBG_OFF ++#define NETIF_DEBUG LWIP_DBG_OFF ++#define PBUF_DEBUG LWIP_DBG_OFF ++#define API_LIB_DEBUG LWIP_DBG_OFF ++#define API_MSG_DEBUG LWIP_DBG_OFF ++#define SOCKETS_DEBUG LWIP_DBG_OFF ++#define ICMP_DEBUG LWIP_DBG_OFF ++#define IGMP_DEBUG LWIP_DBG_OFF ++#define INET_DEBUG LWIP_DBG_OFF ++#define IP_DEBUG LWIP_DBG_OFF ++#define IP_REASS_DEBUG LWIP_DBG_OFF ++#define RAW_DEBUG LWIP_DBG_OFF ++#define MEM_DEBUG LWIP_DBG_OFF ++#define MEMP_DEBUG LWIP_DBG_OFF ++#define SYS_DEBUG LWIP_DBG_OFF ++#define TIMERS_DEBUG LWIP_DBG_OFF ++#define TCP_DEBUG LWIP_DBG_OFF ++#define TCP_INPUT_DEBUG LWIP_DBG_OFF ++#define TCP_FR_DEBUG LWIP_DBG_OFF ++#define TCP_RTO_DEBUG LWIP_DBG_OFF ++#define TCP_CWND_DEBUG LWIP_DBG_OFF ++#define TCP_WND_DEBUG LWIP_DBG_OFF ++#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF ++#define TCP_RST_DEBUG LWIP_DBG_OFF ++#define TCP_QLEN_DEBUG LWIP_DBG_OFF ++#define UDP_DEBUG LWIP_DBG_OFF ++#define TCPIP_DEBUG LWIP_DBG_OFF ++#define SLIP_DEBUG LWIP_DBG_OFF ++#define DHCP_DEBUG LWIP_DBG_OFF ++#define AUTOIP_DEBUG LWIP_DBG_OFF ++#define DNS_DEBUG LWIP_DBG_OFF ++#define IP6_DEBUG LWIP_DBG_OFF ++#endif ++ ++#endif --- /dev/null +++ b/port/sys_arch.c -@@ -0,0 +1,747 @@ -+/* -+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -+ * OF SUCH DAMAGE. -+ * -+ * This file is part of the lwIP TCP/IP stack. -+ * -+ * Author: Adam Dunkels <a...@sics.se> -+ * -+ */ -+ -+/* -+ * Wed Apr 17 16:05:29 EDT 2002 (James Roth) -+ * -+ * - Fixed an unlikely sys_thread_new() race condition. -+ * -+ * - Made current_thread() work with threads which where -+ * not created with sys_thread_new(). This includes -+ * the main thread and threads made with pthread_create(). -+ * -+ * - Catch overflows where more than SYS_MBOX_SIZE messages -+ * are waiting to be read. The sys_mbox_post() routine -+ * will block until there is more room instead of just -+ * leaking messages. -+ */ -+#include "lwip/debug.h" -+ -+#include <string.h> -+#include <sys/time.h> -+#include <sys/types.h> -+#include <stdlib.h> -+#include <unistd.h> -+#include <pthread.h> -+ -+#include "lwip/def.h" -+ -+#ifdef LWIP_UNIX_MACH -+#include <mach/mach.h> -+#include <mach/mach_time.h> -+#endif -+ -+#include "lwip/sys.h" -+#include "lwip/opt.h" -+#include "lwip/stats.h" -+ -+static void -+get_monotonic_time(struct timespec *ts) -+{ -+#ifdef LWIP_UNIX_MACH -+ /* darwin impl (no CLOCK_MONOTONIC) */ -+ uint64_t t = mach_absolute_time(); -+ mach_timebase_info_data_t timebase_info = {0, 0}; -+ mach_timebase_info(&timebase_info); -+ uint64_t nano = (t * timebase_info.numer) / (timebase_info.denom); -+ uint64_t sec = nano/1000000000L; -+ nano -= sec * 1000000000L; -+ ts->tv_sec = sec; -+ ts->tv_nsec = nano; -+#else -+ clock_gettime(CLOCK_MONOTONIC, ts); -+#endif -+} -+ -+#if !NO_SYS -+ -+static struct sys_thread *threads = NULL; -+static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER; -+ -+struct sys_mbox_msg { -+ struct sys_mbox_msg *next; -+ void *msg; -+}; -+ -+#define SYS_MBOX_SIZE 128 -+ -+struct sys_mbox { -+ int first, last; -+ void *msgs[SYS_MBOX_SIZE]; -+ struct sys_sem *not_empty; -+ struct sys_sem *not_full; -+ struct sys_sem *mutex; -+ int wait_send; -+}; -+ -+struct sys_sem { -+ unsigned int c; -+ pthread_condattr_t condattr; -+ pthread_cond_t cond; -+ pthread_mutex_t mutex; -+}; -+ -+struct sys_mutex { -+ pthread_mutex_t mutex; -+}; -+ -+struct sys_thread { -+ struct sys_thread *next; -+ pthread_t pthread; -+}; -+ -+#if SYS_LIGHTWEIGHT_PROT -+static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER; -+static pthread_t lwprot_thread = (pthread_t)0xDEAD; -+static int lwprot_count = 0; -+#endif /* SYS_LIGHTWEIGHT_PROT */ -+ -+static struct sys_sem *sys_sem_new_internal(u8_t count); -+static void sys_sem_free_internal(struct sys_sem *sem); -+ -+static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex, -+ u32_t timeout); -+ -+static u32_t cond_wait_intr(pthread_cond_t * cond, pthread_mutex_t * mutex, -+ u32_t timeout); -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Threads */ -+static struct sys_thread * -+introduce_thread(pthread_t id) -+{ -+ struct sys_thread *thread; -+ -+ thread = (struct sys_thread *)malloc(sizeof(struct sys_thread)); -+ -+ if (thread != NULL) { -+ pthread_mutex_lock(&threads_mutex); -+ thread->next = threads; -+ thread->pthread = id; -+ threads = thread; -+ pthread_mutex_unlock(&threads_mutex); -+ } -+ -+ return thread; -+} -+ -+sys_thread_t -+sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) -+{ -+ int code; -+ pthread_t tmp; -+ struct sys_thread *st = NULL; -+ LWIP_UNUSED_ARG(name); -+ LWIP_UNUSED_ARG(stacksize); -+ LWIP_UNUSED_ARG(prio); -+ -+ code = pthread_create(&tmp, -+ NULL, -+ (void *(*)(void *)) -+ function, -+ arg); -+ -+ if (0 == code) { -+ st = introduce_thread(tmp); -+ } -+ -+ if (NULL == st) { -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%lx", -+ code, (unsigned long)st)); -+ abort(); -+ } -+ return st; -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Mailbox */ -+err_t -+sys_mbox_new(struct sys_mbox **mb, int size) -+{ -+ struct sys_mbox *mbox; -+ LWIP_UNUSED_ARG(size); -+ -+ mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox)); -+ if (mbox == NULL) { -+ return ERR_MEM; -+ } -+ mbox->first = mbox->last = 0; -+ mbox->not_empty = sys_sem_new_internal(0); -+ mbox->not_full = sys_sem_new_internal(0); -+ mbox->mutex = sys_sem_new_internal(1); -+ mbox->wait_send = 0; -+ -+ SYS_STATS_INC_USED(mbox); -+ *mb = mbox; -+ return ERR_OK; -+} -+ -+void -+sys_mbox_free(struct sys_mbox **mb) -+{ -+ if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) { -+ struct sys_mbox *mbox = *mb; -+ SYS_STATS_DEC(mbox.used); -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ sys_sem_free_internal(mbox->not_empty); -+ sys_sem_free_internal(mbox->not_full); -+ sys_sem_free_internal(mbox->mutex); -+ mbox->not_empty = mbox->not_full = mbox->mutex = NULL; -+ /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */ -+ free(mbox); -+ } -+} -+ -+err_t -+sys_mbox_trypost(struct sys_mbox **mb, void *msg) -+{ -+ u8_t first; -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n", -+ (void *)mbox, (void *)msg)); -+ -+ if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { -+ sys_sem_signal(&mbox->mutex); -+ return ERR_MEM; -+ } -+ -+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; -+ -+ if (mbox->last == mbox->first) { -+ first = 1; -+ } else { -+ first = 0; -+ } -+ -+ mbox->last++; -+ -+ if (first) { -+ sys_sem_signal(&mbox->not_empty); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+ -+ return ERR_OK; -+} -+ -+void -+sys_mbox_post(struct sys_mbox **mb, void *msg) -+{ -+ u8_t first; -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg)); -+ -+ while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { -+ mbox->wait_send++; -+ sys_sem_signal(&mbox->mutex); -+ sys_arch_sem_wait(&mbox->not_full, 0); -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ mbox->wait_send--; -+ } -+ -+ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; -+ -+ if (mbox->last == mbox->first) { -+ first = 1; -+ } else { -+ first = 0; -+ } -+ -+ mbox->last++; -+ -+ if (first) { -+ sys_sem_signal(&mbox->not_empty); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+} -+ -+u32_t -+sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg) -+{ -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ if (mbox->first == mbox->last) { -+ sys_sem_signal(&mbox->mutex); -+ return SYS_MBOX_EMPTY; -+ } -+ -+ if (msg != NULL) { -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg)); -+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; -+ } -+ else{ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox)); -+ } -+ -+ mbox->first++; -+ -+ if (mbox->wait_send) { -+ sys_sem_signal(&mbox->not_full); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+ -+ return 0; -+} -+ -+u32_t -+sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout) -+{ -+ u32_t time_needed = 0; -+ struct sys_mbox *mbox; -+ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); -+ mbox = *mb; -+ -+ /* The mutex lock is quick so we don't bother with the timeout -+ stuff here. */ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ -+ while (mbox->first == mbox->last) { -+ sys_sem_signal(&mbox->mutex); -+ -+ /* We block while waiting for a mail to arrive in the mailbox. We -+ must be prepared to timeout. */ -+ if (timeout != 0) { -+ time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout); -+ -+ if (time_needed == SYS_ARCH_TIMEOUT) { -+ return SYS_ARCH_TIMEOUT; -+ } -+ } else { -+ sys_arch_sem_wait(&mbox->not_empty, 0); -+ } -+ -+ sys_arch_sem_wait(&mbox->mutex, 0); -+ } -+ -+ if (msg != NULL) { -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg)); -+ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; -+ } -+ else{ -+ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox)); -+ } -+ -+ mbox->first++; -+ -+ if (mbox->wait_send) { -+ sys_sem_signal(&mbox->not_full); -+ } -+ -+ sys_sem_signal(&mbox->mutex); -+ -+ return time_needed; -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Semaphore */ -+static struct sys_sem * -+sys_sem_new_internal(u8_t count) -+{ -+ struct sys_sem *sem; -+ -+ sem = (struct sys_sem *)malloc(sizeof(struct sys_sem)); -+ if (sem != NULL) { -+ sem->c = count; -+ pthread_condattr_init(&(sem->condattr)); -+#if !(defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21)) -+ pthread_condattr_setclock(&(sem->condattr), CLOCK_MONOTONIC); -+#endif -+ pthread_cond_init(&(sem->cond), &(sem->condattr)); -+ pthread_mutex_init(&(sem->mutex), NULL); -+ } -+ return sem; -+} -+ -+err_t -+sys_sem_new(struct sys_sem **sem, u8_t count) -+{ -+ SYS_STATS_INC_USED(sem); -+ *sem = sys_sem_new_internal(count); -+ if (*sem == NULL) { -+ return ERR_MEM; -+ } -+ return ERR_OK; -+} -+ -+static u32_t -+cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) -+{ -+ struct timespec rtime1, rtime2, ts; -+ int ret; -+ -+ if (timeout == 0) { -+ pthread_cond_wait(cond, mutex); -+ return 0; -+ } -+ -+ /* Get a timestamp and add the timeout value. */ -+ get_monotonic_time(&rtime1); -+#if defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21) -+ ts.tv_sec = timeout / 1000L; -+ ts.tv_nsec = (timeout % 1000L) * 1000000L; -+ ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -+#else -+ ts.tv_sec = rtime1.tv_sec + timeout / 1000L; -+ ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L; -+ if (ts.tv_nsec >= 1000000000L) { -+ ts.tv_sec++; -+ ts.tv_nsec -= 1000000000L; -+ } -+ -+ ret = pthread_cond_timedwait(cond, mutex, &ts); -+#endif -+ if (ret == ETIMEDOUT) { -+ return SYS_ARCH_TIMEOUT; -+ } -+ -+ /* Calculate for how long we waited for the cond. */ -+ get_monotonic_time(&rtime2); -+ ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec; -+ ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec; -+ if (ts.tv_nsec < 0) { -+ ts.tv_sec--; -+ ts.tv_nsec += 1000000000L; -+ } -+ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); -+} -+ -+u32_t -+sys_arch_sem_wait(struct sys_sem **s, u32_t timeout) -+{ -+ u32_t time_needed = 0; -+ struct sys_sem *sem; -+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); -+ sem = *s; -+ -+ pthread_mutex_lock(&(sem->mutex)); -+ while (sem->c <= 0) { -+ if (timeout > 0) { -+ time_needed = cond_wait(&(sem->cond), &(sem->mutex), timeout); -+ -+ if (time_needed == SYS_ARCH_TIMEOUT) { -+ pthread_mutex_unlock(&(sem->mutex)); -+ return SYS_ARCH_TIMEOUT; -+ } -+ /* pthread_mutex_unlock(&(sem->mutex)); -+ return time_needed; */ -+ } else { -+ cond_wait(&(sem->cond), &(sem->mutex), 0); -+ } -+ } -+ sem->c--; -+ pthread_mutex_unlock(&(sem->mutex)); -+ return (u32_t)time_needed; -+} -+ -+/* -+ * Like cond_wait(), but it calls Hurd's non portable -+ * functions to receive cancellation requests -+ */ -+static u32_t -+cond_wait_intr(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) -+{ -+ struct timespec rtime1, rtime2, ts; -+ int ret; -+ -+#ifdef __GNU__ -+ #define pthread_cond_wait pthread_hurd_cond_wait_np -+ #define pthread_cond_timedwait pthread_hurd_cond_timedwait_np -+#endif -+ -+ if (timeout == 0) { -+ ret = pthread_cond_wait(cond, mutex); -+ return ret; -+ } -+ -+ /* Get a timestamp and add the timeout value. */ -+ get_monotonic_time(&rtime1); -+#if defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21) -+ ts.tv_sec = timeout / 1000L; -+ ts.tv_nsec = (timeout % 1000L) * 1000000L; -+ ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts); -+#else -+ ts.tv_sec = rtime1.tv_sec + timeout / 1000L; -+ ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L; -+ if (ts.tv_nsec >= 1000000000L) { -+ ts.tv_sec++; -+ ts.tv_nsec -= 1000000000L; -+ } -+ -+ ret = pthread_cond_timedwait(cond, mutex, &ts); -+#endif -+ if (ret == ETIMEDOUT) { -+ return SYS_ARCH_TIMEOUT; -+ } else if (ret == EINTR) { -+ return SYS_ARCH_INTR; -+ } -+ -+ /* Calculate for how long we waited for the cond. */ -+ get_monotonic_time(&rtime2); -+ ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec; -+ ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec; -+ if (ts.tv_nsec < 0) { -+ ts.tv_sec--; -+ ts.tv_nsec += 1000000000L; -+ } -+ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); -+} -+ -+/* -+ * Like sys_arch_sem_wait(), but it handles thread cancellations. -+ */ -+u32_t -+sys_arch_sem_wait_intr(struct sys_sem **s, u32_t timeout) -+{ -+ u32_t time_needed = 0; -+ struct sys_sem *sem; -+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); -+ sem = *s; -+ -+ pthread_mutex_lock(&(sem->mutex)); -+ while (sem->c <= 0) { -+ if (timeout > 0) { -+ time_needed = cond_wait_intr(&(sem->cond), &(sem->mutex), timeout); -+ -+ if (time_needed == SYS_ARCH_TIMEOUT) { -+ pthread_mutex_unlock(&(sem->mutex)); -+ return SYS_ARCH_TIMEOUT; -+ } else if(time_needed == SYS_ARCH_INTR) { -+ /* This means we were interrupted, so don't wait again */ -+ sem->c++; -+ -+ if (sem->c > 1) { -+ sem->c = 1; -+ } -+ } -+ } else { -+ if(cond_wait_intr(&(sem->cond), &(sem->mutex), 0)) { -+ /* This means we were interrupted, so don't wait again */ -+ sem->c++; -+ -+ if (sem->c > 1) { -+ sem->c = 1; -+ } -+ } -+ } -+ } -+ sem->c--; -+ pthread_mutex_unlock(&(sem->mutex)); -+ return (u32_t)time_needed; -+} -+ -+void -+sys_sem_signal(struct sys_sem **s) -+{ -+ struct sys_sem *sem; -+ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); -+ sem = *s; -+ -+ pthread_mutex_lock(&(sem->mutex)); -+ sem->c++; -+ -+ if (sem->c > 1) { -+ sem->c = 1; -+ } -+ -+ pthread_cond_broadcast(&(sem->cond)); -+ pthread_mutex_unlock(&(sem->mutex)); -+} -+ -+static void -+sys_sem_free_internal(struct sys_sem *sem) -+{ -+ pthread_cond_destroy(&(sem->cond)); -+ pthread_condattr_destroy(&(sem->condattr)); -+ pthread_mutex_destroy(&(sem->mutex)); -+ free(sem); -+} -+ -+void -+sys_sem_free(struct sys_sem **sem) -+{ -+ if ((sem != NULL) && (*sem != SYS_SEM_NULL)) { -+ SYS_STATS_DEC(sem.used); -+ sys_sem_free_internal(*sem); -+ } -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Mutex */ -+/** Create a new mutex -+ * @param mutex pointer to the mutex to create -+ * @return a new mutex */ -+err_t -+sys_mutex_new(struct sys_mutex **mutex) -+{ -+ struct sys_mutex *mtx; -+ -+ mtx = (struct sys_mutex *)malloc(sizeof(struct sys_mutex)); -+ if (mtx != NULL) { -+ pthread_mutex_init(&(mtx->mutex), NULL); -+ *mutex = mtx; -+ return ERR_OK; -+ } -+ else { -+ return ERR_MEM; -+ } -+} -+ -+/** Lock a mutex -+ * @param mutex the mutex to lock */ -+void -+sys_mutex_lock(struct sys_mutex **mutex) -+{ -+ pthread_mutex_lock(&((*mutex)->mutex)); -+} -+ -+/** Unlock a mutex -+ * @param mutex the mutex to unlock */ -+void -+sys_mutex_unlock(struct sys_mutex **mutex) -+{ -+ pthread_mutex_unlock(&((*mutex)->mutex)); -+} -+ -+/** Delete a mutex -+ * @param mutex the mutex to delete */ -+void -+sys_mutex_free(struct sys_mutex **mutex) -+{ -+ pthread_mutex_destroy(&((*mutex)->mutex)); -+ free(*mutex); -+} -+ -+#endif /* !NO_SYS */ -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Time */ -+u32_t -+sys_now(void) -+{ -+ struct timespec ts; -+ -+ get_monotonic_time(&ts); -+ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); -+} -+ -+u32_t -+sys_jiffies(void) -+{ -+ struct timespec ts; -+ -+ get_monotonic_time(&ts); -+ return (u32_t)(ts.tv_sec * 1000000000L + ts.tv_nsec); -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Init */ -+ -+void -+sys_init(void) -+{ -+} -+ -+/*-----------------------------------------------------------------------------------*/ -+/* Critical section */ -+#if SYS_LIGHTWEIGHT_PROT -+/** sys_prot_t sys_arch_protect(void) -+ -+This optional function does a "fast" critical region protection and returns -+the previous protection level. This function is only called during very short -+critical regions. An embedded system which supports ISR-based drivers might -+want to implement this function by disabling interrupts. Task-based systems -+might want to implement this by using a mutex or disabling tasking. This -+function should support recursive calls from the same task or interrupt. In -+other words, sys_arch_protect() could be called while already protected. In -+that case the return value indicates that it is already protected. -+ -+sys_arch_protect() is only required if your port is supporting an operating -+system. -+*/ -+sys_prot_t -+sys_arch_protect(void) -+{ -+ /* Note that for the UNIX port, we are using a lightweight mutex, and our -+ * own counter (which is locked by the mutex). The return code is not actually -+ * used. */ -+ if (lwprot_thread != pthread_self()) -+ { -+ /* We are locking the mutex where it has not been locked before * -+ * or is being locked by another thread */ -+ pthread_mutex_lock(&lwprot_mutex); -+ lwprot_thread = pthread_self(); -+ lwprot_count = 1; -+ } -+ else -+ /* It is already locked by THIS thread */ -+ lwprot_count++; -+ return 0; -+} -+ -+/** void sys_arch_unprotect(sys_prot_t pval) -+ -+This optional function does a "fast" set of critical region protection to the -+value specified by pval. See the documentation for sys_arch_protect() for -+more information. This function is only required if your port is supporting -+an operating system. -+*/ -+void -+sys_arch_unprotect(sys_prot_t pval) -+{ -+ LWIP_UNUSED_ARG(pval); -+ if (lwprot_thread == pthread_self()) -+ { -+ if (--lwprot_count == 0) -+ { -+ lwprot_thread = (pthread_t) 0xDEAD; -+ pthread_mutex_unlock(&lwprot_mutex); -+ } -+ } -+} -+#endif /* SYS_LIGHTWEIGHT_PROT */ +@@ -0,0 +1,668 @@ ++/* ++ * Copyright (c) 2001-2003 Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without modification, ++ * are permitted provided that the following conditions are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ++ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING ++ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY ++ * OF SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels <a...@sics.se> ++ * ++ */ ++ ++/* ++ * Wed Apr 17 16:05:29 EDT 2002 (James Roth) ++ * ++ * - Fixed an unlikely sys_thread_new() race condition. ++ * ++ * - Made current_thread() work with threads which where ++ * not created with sys_thread_new(). This includes ++ * the main thread and threads made with pthread_create(). ++ * ++ * - Catch overflows where more than SYS_MBOX_SIZE messages ++ * are waiting to be read. The sys_mbox_post() routine ++ * will block until there is more room instead of just ++ * leaking messages. ++ */ ++#include "lwip/debug.h" ++ ++#include <string.h> ++#include <sys/time.h> ++#include <sys/types.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <pthread.h> ++ ++#include "lwip/def.h" ++ ++#ifdef LWIP_UNIX_MACH ++#include <mach/mach.h> ++#include <mach/mach_time.h> ++#endif ++ ++#include "lwip/sys.h" ++#include "lwip/opt.h" ++#include "lwip/stats.h" ++ ++static void ++get_monotonic_time(struct timespec *ts) ++{ ++#ifdef LWIP_UNIX_MACH ++ /* darwin impl (no CLOCK_MONOTONIC) */ ++ uint64_t t = mach_absolute_time(); ++ mach_timebase_info_data_t timebase_info = {0, 0}; ++ mach_timebase_info(&timebase_info); ++ uint64_t nano = (t * timebase_info.numer) / (timebase_info.denom); ++ uint64_t sec = nano/1000000000L; ++ nano -= sec * 1000000000L; ++ ts->tv_sec = sec; ++ ts->tv_nsec = nano; ++#else ++ clock_gettime(CLOCK_MONOTONIC, ts); ++#endif ++} ++ ++#if !NO_SYS ++ ++static struct sys_thread *threads = NULL; ++static pthread_mutex_t threads_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++struct sys_mbox_msg { ++ struct sys_mbox_msg *next; ++ void *msg; ++}; ++ ++#define SYS_MBOX_SIZE 128 ++ ++struct sys_mbox { ++ int first, last; ++ void *msgs[SYS_MBOX_SIZE]; ++ struct sys_sem *not_empty; ++ struct sys_sem *not_full; ++ struct sys_sem *mutex; ++ int wait_send; ++}; ++ ++struct sys_sem { ++ unsigned int c; ++ pthread_condattr_t condattr; ++ pthread_cond_t cond; ++ pthread_mutex_t mutex; ++}; ++ ++struct sys_mutex { ++ pthread_mutex_t mutex; ++}; ++ ++struct sys_thread { ++ struct sys_thread *next; ++ pthread_t pthread; ++}; ++ ++#if SYS_LIGHTWEIGHT_PROT ++static pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER; ++static pthread_t lwprot_thread = (pthread_t)0xDEAD; ++static int lwprot_count = 0; ++#endif /* SYS_LIGHTWEIGHT_PROT */ ++ ++static struct sys_sem *sys_sem_new_internal(u8_t count); ++static void sys_sem_free_internal(struct sys_sem *sem); ++ ++static u32_t cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex, ++ u32_t timeout); ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Threads */ ++static struct sys_thread * ++introduce_thread(pthread_t id) ++{ ++ struct sys_thread *thread; ++ ++ thread = (struct sys_thread *)malloc(sizeof(struct sys_thread)); ++ ++ if (thread != NULL) { ++ pthread_mutex_lock(&threads_mutex); ++ thread->next = threads; ++ thread->pthread = id; ++ threads = thread; ++ pthread_mutex_unlock(&threads_mutex); ++ } ++ ++ return thread; ++} ++ ++sys_thread_t ++sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) ++{ ++ int code; ++ pthread_t tmp; ++ struct sys_thread *st = NULL; ++ LWIP_UNUSED_ARG(name); ++ LWIP_UNUSED_ARG(stacksize); ++ LWIP_UNUSED_ARG(prio); ++ ++ code = pthread_create(&tmp, ++ NULL, ++ (void *(*)(void *)) ++ function, ++ arg); ++ ++ if (0 == code) { ++ st = introduce_thread(tmp); ++ } ++ ++ if (NULL == st) { ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_thread_new: pthread_create %d, st = 0x%lx", ++ code, (unsigned long)st)); ++ abort(); ++ } ++ return st; ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Mailbox */ ++err_t ++sys_mbox_new(struct sys_mbox **mb, int size) ++{ ++ struct sys_mbox *mbox; ++ LWIP_UNUSED_ARG(size); ++ ++ mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox)); ++ if (mbox == NULL) { ++ return ERR_MEM; ++ } ++ mbox->first = mbox->last = 0; ++ mbox->not_empty = sys_sem_new_internal(0); ++ mbox->not_full = sys_sem_new_internal(0); ++ mbox->mutex = sys_sem_new_internal(1); ++ mbox->wait_send = 0; ++ ++ SYS_STATS_INC_USED(mbox); ++ *mb = mbox; ++ return ERR_OK; ++} ++ ++void ++sys_mbox_free(struct sys_mbox **mb) ++{ ++ if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) { ++ struct sys_mbox *mbox = *mb; ++ SYS_STATS_DEC(mbox.used); ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ sys_sem_free_internal(mbox->not_empty); ++ sys_sem_free_internal(mbox->not_full); ++ sys_sem_free_internal(mbox->mutex); ++ mbox->not_empty = mbox->not_full = mbox->mutex = NULL; ++ /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */ ++ free(mbox); ++ } ++} ++ ++err_t ++sys_mbox_trypost(struct sys_mbox **mb, void *msg) ++{ ++ u8_t first; ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n", ++ (void *)mbox, (void *)msg)); ++ ++ if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { ++ sys_sem_signal(&mbox->mutex); ++ return ERR_MEM; ++ } ++ ++ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; ++ ++ if (mbox->last == mbox->first) { ++ first = 1; ++ } else { ++ first = 0; ++ } ++ ++ mbox->last++; ++ ++ if (first) { ++ sys_sem_signal(&mbox->not_empty); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++ ++ return ERR_OK; ++} ++ ++void ++sys_mbox_post(struct sys_mbox **mb, void *msg) ++{ ++ u8_t first; ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg)); ++ ++ while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) { ++ mbox->wait_send++; ++ sys_sem_signal(&mbox->mutex); ++ sys_arch_sem_wait(&mbox->not_full, 0); ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ mbox->wait_send--; ++ } ++ ++ mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg; ++ ++ if (mbox->last == mbox->first) { ++ first = 1; ++ } else { ++ first = 0; ++ } ++ ++ mbox->last++; ++ ++ if (first) { ++ sys_sem_signal(&mbox->not_empty); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++} ++ ++u32_t ++sys_arch_mbox_tryfetch(struct sys_mbox **mb, void **msg) ++{ ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ if (mbox->first == mbox->last) { ++ sys_sem_signal(&mbox->mutex); ++ return SYS_MBOX_EMPTY; ++ } ++ ++ if (msg != NULL) { ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg)); ++ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; ++ } ++ else{ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox)); ++ } ++ ++ mbox->first++; ++ ++ if (mbox->wait_send) { ++ sys_sem_signal(&mbox->not_full); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++ ++ return 0; ++} ++ ++u32_t ++sys_arch_mbox_fetch(struct sys_mbox **mb, void **msg, u32_t timeout) ++{ ++ u32_t time_needed = 0; ++ struct sys_mbox *mbox; ++ LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL)); ++ mbox = *mb; ++ ++ /* The mutex lock is quick so we don't bother with the timeout ++ stuff here. */ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ ++ while (mbox->first == mbox->last) { ++ sys_sem_signal(&mbox->mutex); ++ ++ /* We block while waiting for a mail to arrive in the mailbox. We ++ must be prepared to timeout. */ ++ if (timeout != 0) { ++ time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout); ++ ++ if (time_needed == SYS_ARCH_TIMEOUT) { ++ return SYS_ARCH_TIMEOUT; ++ } ++ } else { ++ sys_arch_sem_wait(&mbox->not_empty, 0); ++ } ++ ++ sys_arch_sem_wait(&mbox->mutex, 0); ++ } ++ ++ if (msg != NULL) { ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg)); ++ *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE]; ++ } ++ else{ ++ LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox)); ++ } ++ ++ mbox->first++; ++ ++ if (mbox->wait_send) { ++ sys_sem_signal(&mbox->not_full); ++ } ++ ++ sys_sem_signal(&mbox->mutex); ++ ++ return time_needed; ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Semaphore */ ++static struct sys_sem * ++sys_sem_new_internal(u8_t count) ++{ ++ struct sys_sem *sem; ++ ++ sem = (struct sys_sem *)malloc(sizeof(struct sys_sem)); ++ if (sem != NULL) { ++ sem->c = count; ++ pthread_condattr_init(&(sem->condattr)); ++#if !(defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21)) ++ pthread_condattr_setclock(&(sem->condattr), CLOCK_MONOTONIC); ++#endif ++ pthread_cond_init(&(sem->cond), &(sem->condattr)); ++ pthread_mutex_init(&(sem->mutex), NULL); ++ } ++ return sem; ++} ++ ++err_t ++sys_sem_new(struct sys_sem **sem, u8_t count) ++{ ++ SYS_STATS_INC_USED(sem); ++ *sem = sys_sem_new_internal(count); ++ if (*sem == NULL) { ++ return ERR_MEM; ++ } ++ return ERR_OK; ++} ++ ++/* ++ * Like cond_wait(), but it calls Hurd's non portable ++ * functions to receive cancellation requests ++ */ ++static u32_t ++cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex, u32_t timeout) ++{ ++ struct timespec rtime1, rtime2, ts; ++ int ret; ++ ++#ifdef __GNU__ ++ #define pthread_cond_wait pthread_hurd_cond_wait_np ++ #define pthread_cond_timedwait pthread_hurd_cond_timedwait_np ++#endif ++ ++ if (timeout == 0) { ++ ret = pthread_cond_wait(cond, mutex); ++ return ret; ++ } ++ ++ /* Get a timestamp and add the timeout value. */ ++ get_monotonic_time(&rtime1); ++#if defined(LWIP_UNIX_MACH) || (defined(LWIP_UNIX_ANDROID) && __ANDROID_API__ < 21) ++ ts.tv_sec = timeout / 1000L; ++ ts.tv_nsec = (timeout % 1000L) * 1000000L; ++ ret = pthread_cond_timedwait_relative_np(cond, mutex, &ts); ++#else ++ ts.tv_sec = rtime1.tv_sec + timeout / 1000L; ++ ts.tv_nsec = rtime1.tv_nsec + (timeout % 1000L) * 1000000L; ++ if (ts.tv_nsec >= 1000000000L) { ++ ts.tv_sec++; ++ ts.tv_nsec -= 1000000000L; ++ } ++ ++ ret = pthread_cond_timedwait(cond, mutex, &ts); ++#endif ++ if (ret == ETIMEDOUT) { ++ return SYS_ARCH_TIMEOUT; ++ } else if (ret == EINTR) { ++ return SYS_ARCH_INTR; ++ } ++ ++ /* Calculate for how long we waited for the cond. */ ++ get_monotonic_time(&rtime2); ++ ts.tv_sec = rtime2.tv_sec - rtime1.tv_sec; ++ ts.tv_nsec = rtime2.tv_nsec - rtime1.tv_nsec; ++ if (ts.tv_nsec < 0) { ++ ts.tv_sec--; ++ ts.tv_nsec += 1000000000L; ++ } ++ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); ++} ++ ++/* ++ * Like sys_arch_sem_wait(), but it handles thread cancellations. ++ */ ++u32_t ++sys_arch_sem_wait(struct sys_sem **s, u32_t timeout) ++{ ++ u32_t time_needed = 0; ++ struct sys_sem *sem; ++ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); ++ sem = *s; ++ ++ pthread_mutex_lock(&(sem->mutex)); ++ while (sem->c <= 0) { ++ if (timeout > 0) { ++ time_needed = cond_wait(&(sem->cond), &(sem->mutex), timeout); ++ ++ if (time_needed == SYS_ARCH_TIMEOUT) { ++ pthread_mutex_unlock(&(sem->mutex)); ++ return SYS_ARCH_TIMEOUT; ++ } else if(time_needed == SYS_ARCH_INTR) { ++ /* This means we were interrupted */ ++ pthread_mutex_unlock(&(sem->mutex)); ++ return SYS_ARCH_INTR; ++ } ++ } else { ++ if(cond_wait(&(sem->cond), &(sem->mutex), 0)) { ++ /* This means we were interrupted */ ++ pthread_mutex_unlock(&(sem->mutex)); ++ return SYS_ARCH_INTR; ++ } ++ } ++ } ++ sem->c--; ++ pthread_mutex_unlock(&(sem->mutex)); ++ return (u32_t)time_needed; ++} ++ ++void ++sys_sem_signal(struct sys_sem **s) ++{ ++ struct sys_sem *sem; ++ LWIP_ASSERT("invalid sem", (s != NULL) && (*s != NULL)); ++ sem = *s; ++ ++ pthread_mutex_lock(&(sem->mutex)); ++ sem->c++; ++ ++ if (sem->c > 1) { ++ sem->c = 1; ++ } ++ ++ pthread_cond_broadcast(&(sem->cond)); ++ pthread_mutex_unlock(&(sem->mutex)); ++} ++ ++static void ++sys_sem_free_internal(struct sys_sem *sem) ++{ ++ pthread_cond_destroy(&(sem->cond)); ++ pthread_condattr_destroy(&(sem->condattr)); ++ pthread_mutex_destroy(&(sem->mutex)); ++ free(sem); ++} ++ ++void ++sys_sem_free(struct sys_sem **sem) ++{ ++ if ((sem != NULL) && (*sem != SYS_SEM_NULL)) { ++ SYS_STATS_DEC(sem.used); ++ sys_sem_free_internal(*sem); ++ } ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Mutex */ ++/** Create a new mutex ++ * @param mutex pointer to the mutex to create ++ * @return a new mutex */ ++err_t ++sys_mutex_new(struct sys_mutex **mutex) ++{ ++ struct sys_mutex *mtx; ++ ++ mtx = (struct sys_mutex *)malloc(sizeof(struct sys_mutex)); ++ if (mtx != NULL) { ++ pthread_mutex_init(&(mtx->mutex), NULL); ++ *mutex = mtx; ++ return ERR_OK; ++ } ++ else { ++ return ERR_MEM; ++ } ++} ++ ++/** Lock a mutex ++ * @param mutex the mutex to lock */ ++void ++sys_mutex_lock(struct sys_mutex **mutex) ++{ ++ pthread_mutex_lock(&((*mutex)->mutex)); ++} ++ ++/** Unlock a mutex ++ * @param mutex the mutex to unlock */ ++void ++sys_mutex_unlock(struct sys_mutex **mutex) ++{ ++ pthread_mutex_unlock(&((*mutex)->mutex)); ++} ++ ++/** Delete a mutex ++ * @param mutex the mutex to delete */ ++void ++sys_mutex_free(struct sys_mutex **mutex) ++{ ++ pthread_mutex_destroy(&((*mutex)->mutex)); ++ free(*mutex); ++} ++ ++#endif /* !NO_SYS */ ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Time */ ++u32_t ++sys_now(void) ++{ ++ struct timespec ts; ++ ++ get_monotonic_time(&ts); ++ return (u32_t)(ts.tv_sec * 1000L + ts.tv_nsec / 1000000L); ++} ++ ++u32_t ++sys_jiffies(void) ++{ ++ struct timespec ts; ++ ++ get_monotonic_time(&ts); ++ return (u32_t)(ts.tv_sec * 1000000000L + ts.tv_nsec); ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Init */ ++ ++void ++sys_init(void) ++{ ++} ++ ++/*-----------------------------------------------------------------------------------*/ ++/* Critical section */ ++#if SYS_LIGHTWEIGHT_PROT ++/** sys_prot_t sys_arch_protect(void) ++ ++This optional function does a "fast" critical region protection and returns ++the previous protection level. This function is only called during very short ++critical regions. An embedded system which supports ISR-based drivers might ++want to implement this function by disabling interrupts. Task-based systems ++might want to implement this by using a mutex or disabling tasking. This ++function should support recursive calls from the same task or interrupt. In ++other words, sys_arch_protect() could be called while already protected. In ++that case the return value indicates that it is already protected. ++ ++sys_arch_protect() is only required if your port is supporting an operating ++system. ++*/ ++sys_prot_t ++sys_arch_protect(void) ++{ ++ /* Note that for the UNIX port, we are using a lightweight mutex, and our ++ * own counter (which is locked by the mutex). The return code is not actually ++ * used. */ ++ if (lwprot_thread != pthread_self()) ++ { ++ /* We are locking the mutex where it has not been locked before * ++ * or is being locked by another thread */ ++ pthread_mutex_lock(&lwprot_mutex); ++ lwprot_thread = pthread_self(); ++ lwprot_count = 1; ++ } ++ else ++ /* It is already locked by THIS thread */ ++ lwprot_count++; ++ return 0; ++} ++ ++/** void sys_arch_unprotect(sys_prot_t pval) ++ ++This optional function does a "fast" set of critical region protection to the ++value specified by pval. See the documentation for sys_arch_protect() for ++more information. This function is only required if your port is supporting ++an operating system. ++*/ ++void ++sys_arch_unprotect(sys_prot_t pval) ++{ ++ LWIP_UNUSED_ARG(pval); ++ if (lwprot_thread == pthread_self()) ++ { ++ if (--lwprot_count == 0) ++ { ++ lwprot_thread = (pthread_t) 0xDEAD; ++ pthread_mutex_unlock(&lwprot_mutex); ++ } ++ } ++} ++#endif /* SYS_LIGHTWEIGHT_PROT */ diff --git a/debian/patches/posix b/debian/patches/posix index 1818c4d..e92f542 100644 --- a/debian/patches/posix +++ b/debian/patches/posix @@ -18,117 +18,117 @@ Won't get to upstream --- /dev/null +++ b/port/include/posix/inet.h @@ -0,0 +1,63 @@ -+/* -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ -+ -+#ifndef HURD_LWIP_POSIX_INET_H -+#define HURD_LWIP_POSIX_INET_H -+ -+#include <arpa/inet.h> -+#include <netinet/in.h> -+#include <netinet/tcp.h> -+#include <netinet/udp.h> -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define SIN_ZERO_LEN sizeof (struct sockaddr) - \ -+ __SOCKADDR_COMMON_SIZE - \ -+ sizeof (in_port_t) - \ -+ sizeof (struct in_addr) -+ -+#if LWIP_IPV4 -+ -+#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) -+#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) -+/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ -+#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) -+ -+#endif /* LWIP_IPV4 */ -+ -+#if LWIP_IPV6 -+#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s6_addr32[0] = (source_ip6addr)->addr[0]; \ -+ (target_in6addr)->s6_addr32[1] = (source_ip6addr)->addr[1]; \ -+ (target_in6addr)->s6_addr32[2] = (source_ip6addr)->addr[2]; \ -+ (target_in6addr)->s6_addr32[3] = (source_ip6addr)->addr[3];} -+#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s6_addr32[0]; \ -+ (target_ip6addr)->addr[1] = (source_in6addr)->s6_addr32[1]; \ -+ (target_ip6addr)->addr[2] = (source_in6addr)->s6_addr32[2]; \ -+ (target_ip6addr)->addr[3] = (source_in6addr)->s6_addr32[3];} -+/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ -+#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) -+#endif /* LWIP_IPV6 */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* HURD_LWIP_POSIX_INET_H */ ++/* ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ ++ ++#ifndef HURD_LWIP_POSIX_INET_H ++#define HURD_LWIP_POSIX_INET_H ++ ++#include <arpa/inet.h> ++#include <netinet/in.h> ++#include <netinet/tcp.h> ++#include <netinet/udp.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define SIN_ZERO_LEN sizeof (struct sockaddr) - \ ++ __SOCKADDR_COMMON_SIZE - \ ++ sizeof (in_port_t) - \ ++ sizeof (struct in_addr) ++ ++#if LWIP_IPV4 ++ ++#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) ++#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) ++/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ ++#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) ++ ++#endif /* LWIP_IPV4 */ ++ ++#if LWIP_IPV6 ++#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->s6_addr32[0] = (source_ip6addr)->addr[0]; \ ++ (target_in6addr)->s6_addr32[1] = (source_ip6addr)->addr[1]; \ ++ (target_in6addr)->s6_addr32[2] = (source_ip6addr)->addr[2]; \ ++ (target_in6addr)->s6_addr32[3] = (source_ip6addr)->addr[3];} ++#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->s6_addr32[0]; \ ++ (target_ip6addr)->addr[1] = (source_in6addr)->s6_addr32[1]; \ ++ (target_ip6addr)->addr[2] = (source_in6addr)->s6_addr32[2]; \ ++ (target_ip6addr)->addr[3] = (source_in6addr)->s6_addr32[3];} ++/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ ++#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) ++#endif /* LWIP_IPV6 */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HURD_LWIP_POSIX_INET_H */ --- /dev/null +++ b/port/include/posix/socket.h @@ -0,0 +1,45 @@ -+/* -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ Written by Joan Lledó. -+ -+ This file is part of the GNU Hurd. -+ -+ The GNU Hurd is free software; you can redistribute it and/or -+ modify it under the terms of the GNU General Public License as -+ published by the Free Software Foundation; either version 2, or (at -+ your option) any later version. -+ -+ The GNU Hurd is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ -+ -+#ifndef HURD_LWIP_POSIX_SOCKET_H -+#define HURD_LWIP_POSIX_SOCKET_H -+ -+#include <sys/socket.h> -+#include <poll.h> -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* Unsuported indetifiers */ -+#ifndef SO_NO_CHECK -+#define SO_NO_CHECK 0x0 -+#endif -+#ifndef MSG_MORE -+#define MSG_MORE 0x0 -+#endif -+#ifndef TCP_KEEPALIVE -+#define TCP_KEEPALIVE 0x0 -+#endif -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* HURD_LWIP_POSIX_SOCKET_H */ ++/* ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ Written by Joan Lledó. ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ ++ ++#ifndef HURD_LWIP_POSIX_SOCKET_H ++#define HURD_LWIP_POSIX_SOCKET_H ++ ++#include <sys/socket.h> ++#include <poll.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Unsuported indetifiers */ ++#ifndef SO_NO_CHECK ++#define SO_NO_CHECK 0x0 ++#endif ++#ifndef MSG_MORE ++#define MSG_MORE 0x0 ++#endif ++#ifndef TCP_KEEPALIVE ++#define TCP_KEEPALIVE 0x0 ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* HURD_LWIP_POSIX_SOCKET_H */ --- a/src/include/lwip/inet.h +++ b/src/include/lwip/inet.h @@ -41,132 +41,11 @@ @@ -270,7 +270,7 @@ Won't get to upstream #endif /* LWIP_HDR_INET_H */ --- a/src/include/lwip/ip.h +++ b/src/include/lwip/ip.h -@@ -94,9 +94,16 @@ struct ip_pcb { +@@ -94,9 +94,16 @@ /* * Option flags per-socket. These are the same like SO_XXX in sockets.h */ @@ -290,742 +290,742 @@ Won't get to upstream --- /dev/null +++ b/src/include/lwip/lwip_inet.h @@ -0,0 +1,164 @@ -+/* -+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -+ * OF SUCH DAMAGE. -+ * -+ * This file is part of the lwIP TCP/IP stack. -+ * -+ * Author: Adam Dunkels <a...@sics.se> -+ * -+ */ -+#ifndef LWIP_HDR_PRIV_INET_H -+#define LWIP_HDR_PRIV_INET_H -+ -+#include "lwip/opt.h" -+#include "lwip/def.h" -+#include "lwip/ip_addr.h" -+#include "lwip/ip6_addr.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) -+typedef u32_t in_addr_t; -+#endif -+ -+struct in_addr { -+ in_addr_t s_addr; -+}; -+ -+struct in6_addr { -+ union { -+ u32_t u32_addr[4]; -+ u8_t u8_addr[16]; -+ } un; -+#define s6_addr un.u8_addr -+}; -+ -+/** 255.255.255.255 */ -+#define INADDR_NONE IPADDR_NONE -+/** 127.0.0.1 */ -+#define INADDR_LOOPBACK IPADDR_LOOPBACK -+/** 0.0.0.0 */ -+#define INADDR_ANY IPADDR_ANY -+/** 255.255.255.255 */ -+#define INADDR_BROADCAST IPADDR_BROADCAST -+ -+/** This macro can be used to initialize a variable of type struct in6_addr -+ to the IPv6 wildcard address. */ -+#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} -+/** This macro can be used to initialize a variable of type struct in6_addr -+ to the IPv6 loopback address. */ -+#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} -+/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -+extern const struct in6_addr in6addr_any; -+ -+/* Definitions of the bits in an (IPv4) Internet address integer. -+ -+ On subnets, host and network parts are found according to -+ the subnet mask, not these masks. */ -+#define IN_CLASSA(a) IP_CLASSA(a) -+#define IN_CLASSA_NET IP_CLASSA_NET -+#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT -+#define IN_CLASSA_HOST IP_CLASSA_HOST -+#define IN_CLASSA_MAX IP_CLASSA_MAX -+ -+#define IN_CLASSB(b) IP_CLASSB(b) -+#define IN_CLASSB_NET IP_CLASSB_NET -+#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT -+#define IN_CLASSB_HOST IP_CLASSB_HOST -+#define IN_CLASSB_MAX IP_CLASSB_MAX -+ -+#define IN_CLASSC(c) IP_CLASSC(c) -+#define IN_CLASSC_NET IP_CLASSC_NET -+#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT -+#define IN_CLASSC_HOST IP_CLASSC_HOST -+#define IN_CLASSC_MAX IP_CLASSC_MAX -+ -+#define IN_CLASSD(d) IP_CLASSD(d) -+#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ -+#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ -+#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ -+#define IN_CLASSD_MAX IP_CLASSD_MAX -+ -+#define IN_MULTICAST(a) IP_MULTICAST(a) -+ -+#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) -+#define IN_BADCLASS(a) IP_BADCLASS(a) -+ -+#define IN_LOOPBACKNET IP_LOOPBACKNET -+ -+ -+#ifndef INET_ADDRSTRLEN -+#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -+#endif -+#if LWIP_IPV6 -+#ifndef INET6_ADDRSTRLEN -+#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX -+#endif -+#endif -+ -+#if LWIP_IPV4 -+ -+#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) -+#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) -+/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ -+#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) -+ -+/* directly map this to the lwip internal functions */ -+#define inet_addr(cp) ipaddr_addr(cp) -+#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -+#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) -+#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) -+ -+#endif /* LWIP_IPV4 */ -+ -+#if LWIP_IPV6 -+#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ -+ (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ -+ (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ -+ (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} -+#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ -+ (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ -+ (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ -+ (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} -+/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ -+#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) -+ -+/* directly map this to the lwip internal functions */ -+#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) -+#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) -+#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) -+ -+#endif /* LWIP_IPV6 */ -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* LWIP_HDR_PRIV_INET_H */ ++/* ++ * Copyright (c) 2001-2004 Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without modification, ++ * are permitted provided that the following conditions are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ++ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING ++ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY ++ * OF SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels <a...@sics.se> ++ * ++ */ ++#ifndef LWIP_HDR_PRIV_INET_H ++#define LWIP_HDR_PRIV_INET_H ++ ++#include "lwip/opt.h" ++#include "lwip/def.h" ++#include "lwip/ip_addr.h" ++#include "lwip/ip6_addr.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) ++typedef u32_t in_addr_t; ++#endif ++ ++struct in_addr { ++ in_addr_t s_addr; ++}; ++ ++struct in6_addr { ++ union { ++ u32_t u32_addr[4]; ++ u8_t u8_addr[16]; ++ } un; ++#define s6_addr un.u8_addr ++}; ++ ++/** 255.255.255.255 */ ++#define INADDR_NONE IPADDR_NONE ++/** 127.0.0.1 */ ++#define INADDR_LOOPBACK IPADDR_LOOPBACK ++/** 0.0.0.0 */ ++#define INADDR_ANY IPADDR_ANY ++/** 255.255.255.255 */ ++#define INADDR_BROADCAST IPADDR_BROADCAST ++ ++/** This macro can be used to initialize a variable of type struct in6_addr ++ to the IPv6 wildcard address. */ ++#define IN6ADDR_ANY_INIT {{{0,0,0,0}}} ++/** This macro can be used to initialize a variable of type struct in6_addr ++ to the IPv6 loopback address. */ ++#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} ++/** This variable is initialized by the system to contain the wildcard IPv6 address. */ ++extern const struct in6_addr in6addr_any; ++ ++/* Definitions of the bits in an (IPv4) Internet address integer. ++ ++ On subnets, host and network parts are found according to ++ the subnet mask, not these masks. */ ++#define IN_CLASSA(a) IP_CLASSA(a) ++#define IN_CLASSA_NET IP_CLASSA_NET ++#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT ++#define IN_CLASSA_HOST IP_CLASSA_HOST ++#define IN_CLASSA_MAX IP_CLASSA_MAX ++ ++#define IN_CLASSB(b) IP_CLASSB(b) ++#define IN_CLASSB_NET IP_CLASSB_NET ++#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT ++#define IN_CLASSB_HOST IP_CLASSB_HOST ++#define IN_CLASSB_MAX IP_CLASSB_MAX ++ ++#define IN_CLASSC(c) IP_CLASSC(c) ++#define IN_CLASSC_NET IP_CLASSC_NET ++#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT ++#define IN_CLASSC_HOST IP_CLASSC_HOST ++#define IN_CLASSC_MAX IP_CLASSC_MAX ++ ++#define IN_CLASSD(d) IP_CLASSD(d) ++#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */ ++#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */ ++#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */ ++#define IN_CLASSD_MAX IP_CLASSD_MAX ++ ++#define IN_MULTICAST(a) IP_MULTICAST(a) ++ ++#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a) ++#define IN_BADCLASS(a) IP_BADCLASS(a) ++ ++#define IN_LOOPBACKNET IP_LOOPBACKNET ++ ++ ++#ifndef INET_ADDRSTRLEN ++#define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX ++#endif ++#if LWIP_IPV6 ++#ifndef INET6_ADDRSTRLEN ++#define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX ++#endif ++#endif ++ ++#if LWIP_IPV4 ++ ++#define inet_addr_from_ip4addr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr)) ++#define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) ++/* ATTENTION: the next define only works because both s_addr and ip4_addr_t are an u32_t effectively! */ ++#define inet_addr_to_ip4addr_p(target_ip4addr_p, source_inaddr) ((target_ip4addr_p) = (ip4_addr_t*)&((source_inaddr)->s_addr)) ++ ++/* directly map this to the lwip internal functions */ ++#define inet_addr(cp) ipaddr_addr(cp) ++#define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) ++#define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) ++#define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) ++ ++#endif /* LWIP_IPV4 */ ++ ++#if LWIP_IPV6 ++#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ ++ (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ ++ (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ ++ (target_in6addr)->un.u32_addr[3] = (source_ip6addr)->addr[3];} ++#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) {(target_ip6addr)->addr[0] = (source_in6addr)->un.u32_addr[0]; \ ++ (target_ip6addr)->addr[1] = (source_in6addr)->un.u32_addr[1]; \ ++ (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ ++ (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3];} ++/* ATTENTION: the next define only works because both in6_addr and ip6_addr_t are an u32_t[4] effectively! */ ++#define inet6_addr_to_ip6addr_p(target_ip6addr_p, source_in6addr) ((target_ip6addr_p) = (ip6_addr_t*)(source_in6addr)) ++ ++/* directly map this to the lwip internal functions */ ++#define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) ++#define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) ++#define inet6_ntoa_r(addr, buf, buflen) ip6addr_ntoa_r((const ip6_addr_t*)&(addr), buf, buflen) ++ ++#endif /* LWIP_IPV6 */ ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LWIP_HDR_PRIV_INET_H */ --- /dev/null +++ b/src/include/lwip/lwip_sockets.h @@ -0,0 +1,569 @@ -+/** -+ * @file -+ * Socket API (to be used from non-TCPIP threads) -+ */ -+ -+/* -+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science. -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without modification, -+ * are permitted provided that the following conditions are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright notice, -+ * this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright notice, -+ * this list of conditions and the following disclaimer in the documentation -+ * and/or other materials provided with the distribution. -+ * 3. The name of the author may not be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT -+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY -+ * OF SUCH DAMAGE. -+ * -+ * This file is part of the lwIP TCP/IP stack. -+ * -+ * Author: Adam Dunkels <a...@sics.se> -+ * -+ */ -+ -+ -+#ifndef LWIP_HDR_PRIV_SOCKETS_H -+#define LWIP_HDR_PRIV_SOCKETS_H -+ -+#include "lwip/opt.h" -+ -+#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -+ -+#include "lwip/ip_addr.h" -+#include "lwip/err.h" -+#include "lwip/inet.h" -+#include "lwip/errno.h" -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define _HAVE_SA_LEN 1 -+ -+/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) -+typedef u8_t sa_family_t; -+#endif -+/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) -+typedef u16_t in_port_t; -+#endif -+ -+#if LWIP_IPV4 -+/* members are in network byte order */ -+struct sockaddr_in { -+ u8_t sin_len; -+ sa_family_t sin_family; -+ in_port_t sin_port; -+ struct in_addr sin_addr; -+#define SIN_ZERO_LEN 8 -+ char sin_zero[SIN_ZERO_LEN]; -+}; -+#endif /* LWIP_IPV4 */ -+ -+#if LWIP_IPV6 -+struct sockaddr_in6 { -+ u8_t sin6_len; /* length of this structure */ -+ sa_family_t sin6_family; /* AF_INET6 */ -+ in_port_t sin6_port; /* Transport layer port # */ -+ u32_t sin6_flowinfo; /* IPv6 flow information */ -+ struct in6_addr sin6_addr; /* IPv6 address */ -+ u32_t sin6_scope_id; /* Set of interfaces for scope */ -+}; -+#endif /* LWIP_IPV6 */ -+ -+struct sockaddr { -+ u8_t sa_len; -+ sa_family_t sa_family; -+ char sa_data[14]; -+}; -+ -+struct sockaddr_storage { -+ u8_t s2_len; -+ sa_family_t ss_family; -+ char s2_data1[2]; -+ u32_t s2_data2[3]; -+#if LWIP_IPV6 -+ u32_t s2_data3[3]; -+#endif /* LWIP_IPV6 */ -+}; -+ -+/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED -+ to prevent this code from redefining it. */ -+#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) -+typedef u32_t socklen_t; -+#endif -+ -+struct lwip_sock; -+ -+#if !LWIP_TCPIP_CORE_LOCKING -+/** Maximum optlen used by setsockopt/getsockopt */ -+#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 -+ -+/** This struct is used to pass data to the set/getsockopt_internal -+ * functions running in tcpip_thread context (only a void* is allowed) */ -+struct lwip_setgetsockopt_data { -+ /** socket index for which to change options */ -+ int s; -+ /** level of the option to process */ -+ int level; -+ /** name of the option to process */ -+ int optname; -+ /** set: value to set the option to -+ * get: value of the option is stored here */ -+#if LWIP_MPU_COMPATIBLE -+ u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; -+#else -+ union { -+ void *p; -+ const void *pc; -+ } optval; -+#endif -+ /** size of *optval */ -+ socklen_t optlen; -+ /** if an error occurs, it is temporarily stored here */ -+ err_t err; -+ /** semaphore to wake up the calling task */ -+ void* completed_sem; -+}; -+#endif /* !LWIP_TCPIP_CORE_LOCKING */ -+ -+#if !defined(iovec) -+struct iovec { -+ void *iov_base; -+ size_t iov_len; -+}; -+#endif -+ -+struct msghdr { -+ void *msg_name; -+ socklen_t msg_namelen; -+ struct iovec *msg_iov; -+ int msg_iovlen; -+ void *msg_control; -+ socklen_t msg_controllen; -+ int msg_flags; -+}; -+ -+/* Socket protocol types (TCP/UDP/RAW) */ -+#define SOCK_STREAM 1 -+#define SOCK_DGRAM 2 -+#define SOCK_RAW 3 -+ -+/* -+ * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) -+ */ -+#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ -+#define SO_KEEPALIVE 0x0008 /* keep connections alive */ -+#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ -+ -+ -+/* -+ * Additional options, not kept in so_options. -+ */ -+#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ -+#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ -+#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ -+#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ -+#define SO_LINGER 0x0080 /* linger on close if data present */ -+#define SO_DONTLINGER ((int)(~SO_LINGER)) -+#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ -+#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ -+#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ -+#define SO_RCVBUF 0x1002 /* receive buffer size */ -+#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ -+#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ -+#define SO_SNDTIMEO 0x1005 /* send timeout */ -+#define SO_RCVTIMEO 0x1006 /* receive timeout */ -+#define SO_ERROR 0x1007 /* get error status and clear */ -+#define SO_TYPE 0x1008 /* get socket type */ -+#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ -+#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ -+ -+ -+/* -+ * Structure used for manipulating linger option. -+ */ -+struct linger { -+ int l_onoff; /* option on/off */ -+ int l_linger; /* linger time in seconds */ -+}; -+ -+/* -+ * Level number for (get/set)sockopt() to apply to socket itself. -+ */ -+#define SOL_SOCKET 0xfff /* options for socket level */ -+ -+ -+#define AF_UNSPEC 0 -+#define AF_INET 2 -+#if LWIP_IPV6 -+#define AF_INET6 10 -+#else /* LWIP_IPV6 */ -+#define AF_INET6 AF_UNSPEC -+#endif /* LWIP_IPV6 */ -+#define PF_INET AF_INET -+#define PF_INET6 AF_INET6 -+#define PF_UNSPEC AF_UNSPEC -+ -+#define IPPROTO_IP 0 -+#define IPPROTO_ICMP 1 -+#define IPPROTO_TCP 6 -+#define IPPROTO_UDP 17 -+#if LWIP_IPV6 -+#define IPPROTO_IPV6 41 -+#define IPPROTO_ICMPV6 58 -+#endif /* LWIP_IPV6 */ -+#define IPPROTO_UDPLITE 136 -+#define IPPROTO_RAW 255 -+ -+/* Flags we can use with send and recv. */ -+#define MSG_PEEK 0x01 /* Peeks at an incoming message */ -+#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ -+#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ -+#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ -+#define MSG_MORE 0x10 /* Sender will send more */ -+ -+ -+/* -+ * Options for level IPPROTO_IP -+ */ -+#define IP_TOS 1 -+#define IP_TTL 2 -+ -+#if LWIP_TCP -+/* -+ * Options for level IPPROTO_TCP -+ */ -+#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ -+#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ -+#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ -+#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ -+#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ -+#endif /* LWIP_TCP */ -+ -+#if LWIP_IPV6 -+/* -+ * Options for level IPPROTO_IPV6 -+ */ -+#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ -+#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ -+#endif /* LWIP_IPV6 */ -+ -+#if LWIP_UDP && LWIP_UDPLITE -+/* -+ * Options for level IPPROTO_UDPLITE -+ */ -+#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ -+#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ -+#endif /* LWIP_UDP && LWIP_UDPLITE*/ -+ -+ -+#if LWIP_MULTICAST_TX_OPTIONS -+/* -+ * Options and types for UDP multicast traffic handling -+ */ -+#define IP_MULTICAST_TTL 5 -+#define IP_MULTICAST_IF 6 -+#define IP_MULTICAST_LOOP 7 -+#endif /* LWIP_MULTICAST_TX_OPTIONS */ -+ -+#if LWIP_IGMP -+/* -+ * Options and types related to multicast membership -+ */ -+#define IP_ADD_MEMBERSHIP 3 -+#define IP_DROP_MEMBERSHIP 4 -+ -+typedef struct ip_mreq { -+ struct in_addr imr_multiaddr; /* IP multicast address of group */ -+ struct in_addr imr_interface; /* local IP address of interface */ -+} ip_mreq; -+#endif /* LWIP_IGMP */ -+ -+/* -+ * The Type of Service provides an indication of the abstract -+ * parameters of the quality of service desired. These parameters are -+ * to be used to guide the selection of the actual service parameters -+ * when transmitting a datagram through a particular network. Several -+ * networks offer service precedence, which somehow treats high -+ * precedence traffic as more important than other traffic (generally -+ * by accepting only traffic above a certain precedence at time of high -+ * load). The major choice is a three way tradeoff between low-delay, -+ * high-reliability, and high-throughput. -+ * The use of the Delay, Throughput, and Reliability indications may -+ * increase the cost (in some sense) of the service. In many networks -+ * better performance for one of these parameters is coupled with worse -+ * performance on another. Except for very unusual cases at most two -+ * of these three indications should be set. -+ */ -+#define IPTOS_TOS_MASK 0x1E -+#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) -+#define IPTOS_LOWDELAY 0x10 -+#define IPTOS_THROUGHPUT 0x08 -+#define IPTOS_RELIABILITY 0x04 -+#define IPTOS_LOWCOST 0x02 -+#define IPTOS_MINCOST IPTOS_LOWCOST -+ -+/* -+ * The Network Control precedence designation is intended to be used -+ * within a network only. The actual use and control of that -+ * designation is up to each network. The Internetwork Control -+ * designation is intended for use by gateway control originators only. -+ * If the actual use of these precedence designations is of concern to -+ * a particular network, it is the responsibility of that network to -+ * control the access to, and use of, those precedence designations. -+ */ -+#define IPTOS_PREC_MASK 0xe0 -+#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) -+#define IPTOS_PREC_NETCONTROL 0xe0 -+#define IPTOS_PREC_INTERNETCONTROL 0xc0 -+#define IPTOS_PREC_CRITIC_ECP 0xa0 -+#define IPTOS_PREC_FLASHOVERRIDE 0x80 -+#define IPTOS_PREC_FLASH 0x60 -+#define IPTOS_PREC_IMMEDIATE 0x40 -+#define IPTOS_PREC_PRIORITY 0x20 -+#define IPTOS_PREC_ROUTINE 0x00 -+ -+ -+/* -+ * Commands for ioctlsocket(), taken from the BSD file fcntl.h. -+ * lwip_ioctl only supports FIONREAD and FIONBIO, for now -+ * -+ * Ioctl's have the command encoded in the lower word, -+ * and the size of any in or out parameters in the upper -+ * word. The high 2 bits of the upper word are used -+ * to encode the in/out status of the parameter; for now -+ * we restrict parameters to at most 128 bytes. -+ */ -+#if !defined(FIONREAD) || !defined(FIONBIO) -+#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ -+#define IOC_VOID 0x20000000UL /* no parameters */ -+#define IOC_OUT 0x40000000UL /* copy out parameters */ -+#define IOC_IN 0x80000000UL /* copy in parameters */ -+#define IOC_INOUT (IOC_IN|IOC_OUT) -+ /* 0x20000000 distinguishes new & -+ old ioctl's */ -+#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) -+ -+#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -+ -+#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) -+#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ -+ -+#ifndef FIONREAD -+#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ -+#endif -+#ifndef FIONBIO -+#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ -+#endif -+ -+/* Socket I/O Controls: unimplemented */ -+#ifndef SIOCSHIWAT -+#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ -+#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ -+#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ -+#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ -+#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ -+#endif -+ -+/* commands for fnctl */ -+#ifndef F_GETFL -+#define F_GETFL 3 -+#endif -+#ifndef F_SETFL -+#define F_SETFL 4 -+#endif -+ -+/* File status flags and file access modes for fnctl, -+ these are bits in an int. */ -+#ifndef O_NONBLOCK -+#define O_NONBLOCK 1 /* nonblocking I/O */ -+#endif -+#ifndef O_NDELAY -+#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ -+#endif -+ -+#ifndef SHUT_RD -+ #define SHUT_RD 0 -+ #define SHUT_WR 1 -+ #define SHUT_RDWR 2 -+#endif -+ -+/* FD_SET used for lwip_select */ -+#ifndef FD_SET -+#undef FD_SETSIZE -+/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ -+#define FD_SETSIZE MEMP_NUM_NETCONN -+#define FDSETSAFESET(n, code) do { \ -+ if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ -+ code; }} while(0) -+#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ -+ (code) : 0) -+#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -+#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -+#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) -+#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) -+ -+typedef struct fd_set -+{ -+ unsigned char fd_bits [(FD_SETSIZE+7)/8]; -+} fd_set; -+ -+#elif LWIP_SOCKET_OFFSET -+#error LWIP_SOCKET_OFFSET does not work with external FD_SET! -+#elif FD_SETSIZE < MEMP_NUM_NETCONN -+#error "external FD_SETSIZE too small for number of sockets" -+#endif /* FD_SET */ -+ -+/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided -+ * by your system, set this to 0 and include <sys/time.h> in cc.h */ -+#ifndef LWIP_TIMEVAL_PRIVATE -+#define LWIP_TIMEVAL_PRIVATE 1 -+#endif -+ -+#if LWIP_TIMEVAL_PRIVATE -+struct timeval { -+ long tv_sec; /* seconds */ -+ long tv_usec; /* and microseconds */ -+}; -+#endif /* LWIP_TIMEVAL_PRIVATE */ -+ -+#define lwip_socket_init() /* Compatibility define, no init needed. */ -+void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ -+void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ -+ -+#if LWIP_COMPAT_SOCKETS == 2 -+/* This helps code parsers/code completion by not having the COMPAT functions as defines */ -+#define lwip_accept accept -+#define lwip_bind bind -+#define lwip_shutdown shutdown -+#define lwip_getpeername getpeername -+#define lwip_getsockname getsockname -+#define lwip_setsockopt setsockopt -+#define lwip_getsockopt getsockopt -+#define lwip_close closesocket -+#define lwip_connect connect -+#define lwip_listen listen -+#define lwip_recv recv -+#define lwip_recvfrom recvfrom -+#define lwip_send send -+#define lwip_sendmsg sendmsg -+#define lwip_sendto sendto -+#define lwip_socket socket -+#define lwip_select select -+#define lwip_ioctlsocket ioctl -+ -+#if LWIP_POSIX_SOCKETS_IO_NAMES -+#define lwip_read read -+#define lwip_write write -+#define lwip_writev writev -+#undef lwip_close -+#define lwip_close close -+#define closesocket(s) close(s) -+#define lwip_fcntl fcntl -+#define lwip_ioctl ioctl -+#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -+#endif /* LWIP_COMPAT_SOCKETS == 2 */ -+ -+#if LWIP_COMPAT_SOCKETS -+#if LWIP_COMPAT_SOCKETS != 2 -+/** @ingroup socket */ -+#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) -+/** @ingroup socket */ -+#define bind(s,name,namelen) lwip_bind(s,name,namelen) -+/** @ingroup socket */ -+#define shutdown(s,how) lwip_shutdown(s,how) -+/** @ingroup socket */ -+#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) -+/** @ingroup socket */ -+#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) -+/** @ingroup socket */ -+#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) -+/** @ingroup socket */ -+#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) -+/** @ingroup socket */ -+#define closesocket(s) lwip_close(s) -+/** @ingroup socket */ -+#define connect(s,name,namelen) lwip_connect(s,name,namelen) -+/** @ingroup socket */ -+#define listen(s,backlog) lwip_listen(s,backlog) -+/** @ingroup socket */ -+#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) -+/** @ingroup socket */ -+#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) -+/** @ingroup socket */ -+#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) -+/** @ingroup socket */ -+#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) -+/** @ingroup socket */ -+#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) -+/** @ingroup socket */ -+#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) -+/** @ingroup socket */ -+#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) -+/** @ingroup socket */ -+#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) -+ -+#if LWIP_POSIX_SOCKETS_IO_NAMES -+/** @ingroup socket */ -+#define read(s,mem,len) lwip_read(s,mem,len) -+/** @ingroup socket */ -+#define write(s,dataptr,len) lwip_write(s,dataptr,len) -+/** @ingroup socket */ -+#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) -+/** @ingroup socket */ -+#define close(s) lwip_close(s) -+/** @ingroup socket */ -+#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) -+/** @ingroup socket */ -+#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) -+#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ -+#endif /* LWIP_COMPAT_SOCKETS != 2 */ -+ -+#if LWIP_IPV4 && LWIP_IPV6 -+/** @ingroup socket */ -+#define inet_ntop(af,src,dst,size) \ -+ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ -+ : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) -+/** @ingroup socket */ -+#define inet_pton(af,src,dst) \ -+ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ -+ : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) -+#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ -+#define inet_ntop(af,src,dst,size) \ -+ (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) -+#define inet_pton(af,src,dst) \ -+ (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) -+#else /* LWIP_IPV4 && LWIP_IPV6 */ -+#define inet_ntop(af,src,dst,size) \ -+ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) -+#define inet_pton(af,src,dst) \ -+ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) -+#endif /* LWIP_IPV4 && LWIP_IPV6 */ -+ -+#endif /* LWIP_COMPAT_SOCKETS */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* LWIP_SOCKET */ -+ -+#endif /* LWIP_HDR_PRIV_SOCKETS_H */ ++/** ++ * @file ++ * Socket API (to be used from non-TCPIP threads) ++ */ ++ ++/* ++ * Copyright (c) 2001-2004 Swedish Institute of Computer Science. ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without modification, ++ * are permitted provided that the following conditions are met: ++ * ++ * 1. Redistributions of source code must retain the above copyright notice, ++ * this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright notice, ++ * this list of conditions and the following disclaimer in the documentation ++ * and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED ++ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ++ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT ++ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ++ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ++ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING ++ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY ++ * OF SUCH DAMAGE. ++ * ++ * This file is part of the lwIP TCP/IP stack. ++ * ++ * Author: Adam Dunkels <a...@sics.se> ++ * ++ */ ++ ++ ++#ifndef LWIP_HDR_PRIV_SOCKETS_H ++#define LWIP_HDR_PRIV_SOCKETS_H ++ ++#include "lwip/opt.h" ++ ++#if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ ++ ++#include "lwip/ip_addr.h" ++#include "lwip/err.h" ++#include "lwip/inet.h" ++#include "lwip/errno.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#define _HAVE_SA_LEN 1 ++ ++/* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) ++typedef u8_t sa_family_t; ++#endif ++/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) ++typedef u16_t in_port_t; ++#endif ++ ++#if LWIP_IPV4 ++/* members are in network byte order */ ++struct sockaddr_in { ++ u8_t sin_len; ++ sa_family_t sin_family; ++ in_port_t sin_port; ++ struct in_addr sin_addr; ++#define SIN_ZERO_LEN 8 ++ char sin_zero[SIN_ZERO_LEN]; ++}; ++#endif /* LWIP_IPV4 */ ++ ++#if LWIP_IPV6 ++struct sockaddr_in6 { ++ u8_t sin6_len; /* length of this structure */ ++ sa_family_t sin6_family; /* AF_INET6 */ ++ in_port_t sin6_port; /* Transport layer port # */ ++ u32_t sin6_flowinfo; /* IPv6 flow information */ ++ struct in6_addr sin6_addr; /* IPv6 address */ ++ u32_t sin6_scope_id; /* Set of interfaces for scope */ ++}; ++#endif /* LWIP_IPV6 */ ++ ++struct sockaddr { ++ u8_t sa_len; ++ sa_family_t sa_family; ++ char sa_data[14]; ++}; ++ ++struct sockaddr_storage { ++ u8_t s2_len; ++ sa_family_t ss_family; ++ char s2_data1[2]; ++ u32_t s2_data2[3]; ++#if LWIP_IPV6 ++ u32_t s2_data3[3]; ++#endif /* LWIP_IPV6 */ ++}; ++ ++/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED ++ to prevent this code from redefining it. */ ++#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) ++typedef u32_t socklen_t; ++#endif ++ ++struct lwip_sock; ++ ++#if !LWIP_TCPIP_CORE_LOCKING ++/** Maximum optlen used by setsockopt/getsockopt */ ++#define LWIP_SETGETSOCKOPT_MAXOPTLEN 16 ++ ++/** This struct is used to pass data to the set/getsockopt_internal ++ * functions running in tcpip_thread context (only a void* is allowed) */ ++struct lwip_setgetsockopt_data { ++ /** socket index for which to change options */ ++ int s; ++ /** level of the option to process */ ++ int level; ++ /** name of the option to process */ ++ int optname; ++ /** set: value to set the option to ++ * get: value of the option is stored here */ ++#if LWIP_MPU_COMPATIBLE ++ u8_t optval[LWIP_SETGETSOCKOPT_MAXOPTLEN]; ++#else ++ union { ++ void *p; ++ const void *pc; ++ } optval; ++#endif ++ /** size of *optval */ ++ socklen_t optlen; ++ /** if an error occurs, it is temporarily stored here */ ++ err_t err; ++ /** semaphore to wake up the calling task */ ++ void* completed_sem; ++}; ++#endif /* !LWIP_TCPIP_CORE_LOCKING */ ++ ++#if !defined(iovec) ++struct iovec { ++ void *iov_base; ++ size_t iov_len; ++}; ++#endif ++ ++struct msghdr { ++ void *msg_name; ++ socklen_t msg_namelen; ++ struct iovec *msg_iov; ++ int msg_iovlen; ++ void *msg_control; ++ socklen_t msg_controllen; ++ int msg_flags; ++}; ++ ++/* Socket protocol types (TCP/UDP/RAW) */ ++#define SOCK_STREAM 1 ++#define SOCK_DGRAM 2 ++#define SOCK_RAW 3 ++ ++/* ++ * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) ++ */ ++#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ ++#define SO_KEEPALIVE 0x0008 /* keep connections alive */ ++#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ ++ ++ ++/* ++ * Additional options, not kept in so_options. ++ */ ++#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ ++#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ ++#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ ++#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ ++#define SO_LINGER 0x0080 /* linger on close if data present */ ++#define SO_DONTLINGER ((int)(~SO_LINGER)) ++#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ ++#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ ++#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ ++#define SO_RCVBUF 0x1002 /* receive buffer size */ ++#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ ++#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ ++#define SO_SNDTIMEO 0x1005 /* send timeout */ ++#define SO_RCVTIMEO 0x1006 /* receive timeout */ ++#define SO_ERROR 0x1007 /* get error status and clear */ ++#define SO_TYPE 0x1008 /* get socket type */ ++#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ ++#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ ++ ++ ++/* ++ * Structure used for manipulating linger option. ++ */ ++struct linger { ++ int l_onoff; /* option on/off */ ++ int l_linger; /* linger time in seconds */ ++}; ++ ++/* ++ * Level number for (get/set)sockopt() to apply to socket itself. ++ */ ++#define SOL_SOCKET 0xfff /* options for socket level */ ++ ++ ++#define AF_UNSPEC 0 ++#define AF_INET 2 ++#if LWIP_IPV6 ++#define AF_INET6 10 ++#else /* LWIP_IPV6 */ ++#define AF_INET6 AF_UNSPEC ++#endif /* LWIP_IPV6 */ ++#define PF_INET AF_INET ++#define PF_INET6 AF_INET6 ++#define PF_UNSPEC AF_UNSPEC ++ ++#define IPPROTO_IP 0 ++#define IPPROTO_ICMP 1 ++#define IPPROTO_TCP 6 ++#define IPPROTO_UDP 17 ++#if LWIP_IPV6 ++#define IPPROTO_IPV6 41 ++#define IPPROTO_ICMPV6 58 ++#endif /* LWIP_IPV6 */ ++#define IPPROTO_UDPLITE 136 ++#define IPPROTO_RAW 255 ++ ++/* Flags we can use with send and recv. */ ++#define MSG_PEEK 0x01 /* Peeks at an incoming message */ ++#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ ++#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ ++#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ ++#define MSG_MORE 0x10 /* Sender will send more */ ++ ++ ++/* ++ * Options for level IPPROTO_IP ++ */ ++#define IP_TOS 1 ++#define IP_TTL 2 ++ ++#if LWIP_TCP ++/* ++ * Options for level IPPROTO_TCP ++ */ ++#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ ++#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ ++#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ ++#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ ++#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ ++#endif /* LWIP_TCP */ ++ ++#if LWIP_IPV6 ++/* ++ * Options for level IPPROTO_IPV6 ++ */ ++#define IPV6_CHECKSUM 7 /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */ ++#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */ ++#endif /* LWIP_IPV6 */ ++ ++#if LWIP_UDP && LWIP_UDPLITE ++/* ++ * Options for level IPPROTO_UDPLITE ++ */ ++#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */ ++#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */ ++#endif /* LWIP_UDP && LWIP_UDPLITE*/ ++ ++ ++#if LWIP_MULTICAST_TX_OPTIONS ++/* ++ * Options and types for UDP multicast traffic handling ++ */ ++#define IP_MULTICAST_TTL 5 ++#define IP_MULTICAST_IF 6 ++#define IP_MULTICAST_LOOP 7 ++#endif /* LWIP_MULTICAST_TX_OPTIONS */ ++ ++#if LWIP_IGMP ++/* ++ * Options and types related to multicast membership ++ */ ++#define IP_ADD_MEMBERSHIP 3 ++#define IP_DROP_MEMBERSHIP 4 ++ ++typedef struct ip_mreq { ++ struct in_addr imr_multiaddr; /* IP multicast address of group */ ++ struct in_addr imr_interface; /* local IP address of interface */ ++} ip_mreq; ++#endif /* LWIP_IGMP */ ++ ++/* ++ * The Type of Service provides an indication of the abstract ++ * parameters of the quality of service desired. These parameters are ++ * to be used to guide the selection of the actual service parameters ++ * when transmitting a datagram through a particular network. Several ++ * networks offer service precedence, which somehow treats high ++ * precedence traffic as more important than other traffic (generally ++ * by accepting only traffic above a certain precedence at time of high ++ * load). The major choice is a three way tradeoff between low-delay, ++ * high-reliability, and high-throughput. ++ * The use of the Delay, Throughput, and Reliability indications may ++ * increase the cost (in some sense) of the service. In many networks ++ * better performance for one of these parameters is coupled with worse ++ * performance on another. Except for very unusual cases at most two ++ * of these three indications should be set. ++ */ ++#define IPTOS_TOS_MASK 0x1E ++#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) ++#define IPTOS_LOWDELAY 0x10 ++#define IPTOS_THROUGHPUT 0x08 ++#define IPTOS_RELIABILITY 0x04 ++#define IPTOS_LOWCOST 0x02 ++#define IPTOS_MINCOST IPTOS_LOWCOST ++ ++/* ++ * The Network Control precedence designation is intended to be used ++ * within a network only. The actual use and control of that ++ * designation is up to each network. The Internetwork Control ++ * designation is intended for use by gateway control originators only. ++ * If the actual use of these precedence designations is of concern to ++ * a particular network, it is the responsibility of that network to ++ * control the access to, and use of, those precedence designations. ++ */ ++#define IPTOS_PREC_MASK 0xe0 ++#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) ++#define IPTOS_PREC_NETCONTROL 0xe0 ++#define IPTOS_PREC_INTERNETCONTROL 0xc0 ++#define IPTOS_PREC_CRITIC_ECP 0xa0 ++#define IPTOS_PREC_FLASHOVERRIDE 0x80 ++#define IPTOS_PREC_FLASH 0x60 ++#define IPTOS_PREC_IMMEDIATE 0x40 ++#define IPTOS_PREC_PRIORITY 0x20 ++#define IPTOS_PREC_ROUTINE 0x00 ++ ++ ++/* ++ * Commands for ioctlsocket(), taken from the BSD file fcntl.h. ++ * lwip_ioctl only supports FIONREAD and FIONBIO, for now ++ * ++ * Ioctl's have the command encoded in the lower word, ++ * and the size of any in or out parameters in the upper ++ * word. The high 2 bits of the upper word are used ++ * to encode the in/out status of the parameter; for now ++ * we restrict parameters to at most 128 bytes. ++ */ ++#if !defined(FIONREAD) || !defined(FIONBIO) ++#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */ ++#define IOC_VOID 0x20000000UL /* no parameters */ ++#define IOC_OUT 0x40000000UL /* copy out parameters */ ++#define IOC_IN 0x80000000UL /* copy in parameters */ ++#define IOC_INOUT (IOC_IN|IOC_OUT) ++ /* 0x20000000 distinguishes new & ++ old ioctl's */ ++#define _IO(x,y) (IOC_VOID|((x)<<8)|(y)) ++ ++#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) ++ ++#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)) ++#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ ++ ++#ifndef FIONREAD ++#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ ++#endif ++#ifndef FIONBIO ++#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ ++#endif ++ ++/* Socket I/O Controls: unimplemented */ ++#ifndef SIOCSHIWAT ++#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ ++#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ ++#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ ++#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ ++#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ ++#endif ++ ++/* commands for fnctl */ ++#ifndef F_GETFL ++#define F_GETFL 3 ++#endif ++#ifndef F_SETFL ++#define F_SETFL 4 ++#endif ++ ++/* File status flags and file access modes for fnctl, ++ these are bits in an int. */ ++#ifndef O_NONBLOCK ++#define O_NONBLOCK 1 /* nonblocking I/O */ ++#endif ++#ifndef O_NDELAY ++#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */ ++#endif ++ ++#ifndef SHUT_RD ++ #define SHUT_RD 0 ++ #define SHUT_WR 1 ++ #define SHUT_RDWR 2 ++#endif ++ ++/* FD_SET used for lwip_select */ ++#ifndef FD_SET ++#undef FD_SETSIZE ++/* Make FD_SETSIZE match NUM_SOCKETS in socket.c */ ++#define FD_SETSIZE MEMP_NUM_NETCONN ++#define FDSETSAFESET(n, code) do { \ ++ if (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0)) { \ ++ code; }} while(0) ++#define FDSETSAFEGET(n, code) (((n) - LWIP_SOCKET_OFFSET < MEMP_NUM_NETCONN) && (((int)(n) - LWIP_SOCKET_OFFSET) >= 0) ?\ ++ (code) : 0) ++#define FD_SET(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] |= (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) ++#define FD_CLR(n, p) FDSETSAFESET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] &= ~(1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) ++#define FD_ISSET(n,p) FDSETSAFEGET(n, (p)->fd_bits[((n)-LWIP_SOCKET_OFFSET)/8] & (1 << (((n)-LWIP_SOCKET_OFFSET) & 7))) ++#define FD_ZERO(p) memset((void*)(p), 0, sizeof(*(p))) ++ ++typedef struct fd_set ++{ ++ unsigned char fd_bits [(FD_SETSIZE+7)/8]; ++} fd_set; ++ ++#elif LWIP_SOCKET_OFFSET ++#error LWIP_SOCKET_OFFSET does not work with external FD_SET! ++#elif FD_SETSIZE < MEMP_NUM_NETCONN ++#error "external FD_SETSIZE too small for number of sockets" ++#endif /* FD_SET */ ++ ++/** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided ++ * by your system, set this to 0 and include <sys/time.h> in cc.h */ ++#ifndef LWIP_TIMEVAL_PRIVATE ++#define LWIP_TIMEVAL_PRIVATE 1 ++#endif ++ ++#if LWIP_TIMEVAL_PRIVATE ++struct timeval { ++ long tv_sec; /* seconds */ ++ long tv_usec; /* and microseconds */ ++}; ++#endif /* LWIP_TIMEVAL_PRIVATE */ ++ ++#define lwip_socket_init() /* Compatibility define, no init needed. */ ++void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ ++void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ ++ ++#if LWIP_COMPAT_SOCKETS == 2 ++/* This helps code parsers/code completion by not having the COMPAT functions as defines */ ++#define lwip_accept accept ++#define lwip_bind bind ++#define lwip_shutdown shutdown ++#define lwip_getpeername getpeername ++#define lwip_getsockname getsockname ++#define lwip_setsockopt setsockopt ++#define lwip_getsockopt getsockopt ++#define lwip_close closesocket ++#define lwip_connect connect ++#define lwip_listen listen ++#define lwip_recv recv ++#define lwip_recvfrom recvfrom ++#define lwip_send send ++#define lwip_sendmsg sendmsg ++#define lwip_sendto sendto ++#define lwip_socket socket ++#define lwip_select select ++#define lwip_ioctlsocket ioctl ++ ++#if LWIP_POSIX_SOCKETS_IO_NAMES ++#define lwip_read read ++#define lwip_write write ++#define lwip_writev writev ++#undef lwip_close ++#define lwip_close close ++#define closesocket(s) close(s) ++#define lwip_fcntl fcntl ++#define lwip_ioctl ioctl ++#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ ++#endif /* LWIP_COMPAT_SOCKETS == 2 */ ++ ++#if LWIP_COMPAT_SOCKETS ++#if LWIP_COMPAT_SOCKETS != 2 ++/** @ingroup socket */ ++#define accept(s,addr,addrlen) lwip_accept(s,addr,addrlen) ++/** @ingroup socket */ ++#define bind(s,name,namelen) lwip_bind(s,name,namelen) ++/** @ingroup socket */ ++#define shutdown(s,how) lwip_shutdown(s,how) ++/** @ingroup socket */ ++#define getpeername(s,name,namelen) lwip_getpeername(s,name,namelen) ++/** @ingroup socket */ ++#define getsockname(s,name,namelen) lwip_getsockname(s,name,namelen) ++/** @ingroup socket */ ++#define setsockopt(s,level,optname,opval,optlen) lwip_setsockopt(s,level,optname,opval,optlen) ++/** @ingroup socket */ ++#define getsockopt(s,level,optname,opval,optlen) lwip_getsockopt(s,level,optname,opval,optlen) ++/** @ingroup socket */ ++#define closesocket(s) lwip_close(s) ++/** @ingroup socket */ ++#define connect(s,name,namelen) lwip_connect(s,name,namelen) ++/** @ingroup socket */ ++#define listen(s,backlog) lwip_listen(s,backlog) ++/** @ingroup socket */ ++#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags) ++/** @ingroup socket */ ++#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen) ++/** @ingroup socket */ ++#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags) ++/** @ingroup socket */ ++#define sendmsg(s,message,flags) lwip_sendmsg(s,message,flags) ++/** @ingroup socket */ ++#define sendto(s,dataptr,size,flags,to,tolen) lwip_sendto(s,dataptr,size,flags,to,tolen) ++/** @ingroup socket */ ++#define socket(domain,type,protocol) lwip_socket(domain,type,protocol) ++/** @ingroup socket */ ++#define select(maxfdp1,readset,writeset,exceptset,timeout) lwip_select(maxfdp1,readset,writeset,exceptset,timeout) ++/** @ingroup socket */ ++#define ioctlsocket(s,cmd,argp) lwip_ioctl(s,cmd,argp) ++ ++#if LWIP_POSIX_SOCKETS_IO_NAMES ++/** @ingroup socket */ ++#define read(s,mem,len) lwip_read(s,mem,len) ++/** @ingroup socket */ ++#define write(s,dataptr,len) lwip_write(s,dataptr,len) ++/** @ingroup socket */ ++#define writev(s,iov,iovcnt) lwip_writev(s,iov,iovcnt) ++/** @ingroup socket */ ++#define close(s) lwip_close(s) ++/** @ingroup socket */ ++#define fcntl(s,cmd,val) lwip_fcntl(s,cmd,val) ++/** @ingroup socket */ ++#define ioctl(s,cmd,argp) lwip_ioctl(s,cmd,argp) ++#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */ ++#endif /* LWIP_COMPAT_SOCKETS != 2 */ ++ ++#if LWIP_IPV4 && LWIP_IPV6 ++/** @ingroup socket */ ++#define inet_ntop(af,src,dst,size) \ ++ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) \ ++ : (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL)) ++/** @ingroup socket */ ++#define inet_pton(af,src,dst) \ ++ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) \ ++ : (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0)) ++#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ ++#define inet_ntop(af,src,dst,size) \ ++ (((af) == AF_INET) ? ip4addr_ntoa_r((const ip4_addr_t*)(src),(dst),(size)) : NULL) ++#define inet_pton(af,src,dst) \ ++ (((af) == AF_INET) ? ip4addr_aton((src),(ip4_addr_t*)(dst)) : 0) ++#else /* LWIP_IPV4 && LWIP_IPV6 */ ++#define inet_ntop(af,src,dst,size) \ ++ (((af) == AF_INET6) ? ip6addr_ntoa_r((const ip6_addr_t*)(src),(dst),(size)) : NULL) ++#define inet_pton(af,src,dst) \ ++ (((af) == AF_INET6) ? ip6addr_aton((src),(ip6_addr_t*)(dst)) : 0) ++#endif /* LWIP_IPV4 && LWIP_IPV6 */ ++ ++#endif /* LWIP_COMPAT_SOCKETS */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LWIP_SOCKET */ ++ ++#endif /* LWIP_HDR_PRIV_SOCKETS_H */ --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -1760,6 +1760,15 @@ @@ -1497,7 +1497,7 @@ Won't get to upstream int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen); int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen); int lwip_shutdown(int s, int how); -@@ -506,88 +78,16 @@ int lwip_select(int maxfdp1, fd_set *rea +@@ -506,88 +78,16 @@ int lwip_ioctl(int s, long cmd, void *argp); int lwip_fcntl(int s, int cmd, int val); @@ -1596,35 +1596,20 @@ Won't get to upstream --- a/port/include/lwipopts.h +++ b/port/include/lwipopts.h @@ -26,6 +26,11 @@ - /* Don't rename Sockets API functions */ - #define LWIP_COMPAT_SOCKETS 0 - -+/* Use Glibc's sockets headers */ -+#define LWIP_STD_SOCKETS 1 -+#define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" -+#define LWIP_INCLUDE_STD_INET "posix/inet.h" -+ - /* Use Glibc malloc()/free() */ - #define MEM_LIBC_MALLOC 1 - #define MEMP_MEM_MALLOC 1 ---- a/port/include/arch/cc.h -+++ b/port/include/arch/cc.h -@@ -40,6 +40,12 @@ - /* Use our own ioctls */ - #include <sys/ioctl.h> - -+/* Use our own <sys/socket.h> */ -+#include <sys/socket.h> -+#include <netinet/in.h> -+#include <netinet/tcp.h> -+#include <netinet/udp.h> -+ - /* Use our own htons() and pals */ - #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS 1 - + /* Don't rename Sockets API functions */ + #define LWIP_COMPAT_SOCKETS 0 + ++/* Use Glibc's sockets headers */ ++#define LWIP_STD_SOCKETS 1 ++#define LWIP_INCLUDE_STD_SOCKETS "posix/socket.h" ++#define LWIP_INCLUDE_STD_INET "posix/inet.h" ++ + /* Use Glibc malloc()/free() */ + #define MEM_LIBC_MALLOC 1 + #define MEMP_MEM_MALLOC 1 --- a/src/api/netdb.c +++ b/src/api/netdb.c -@@ -374,7 +374,9 @@ lwip_getaddrinfo(const char *nodename, c +@@ -374,7 +374,9 @@ /* set up sockaddr */ inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); sa6->sin6_family = AF_INET6; @@ -1634,7 +1619,7 @@ Won't get to upstream sa6->sin6_port = lwip_htons((u16_t)port_nr); ai->ai_family = AF_INET6; #endif /* LWIP_IPV6 */ -@@ -384,7 +386,9 @@ lwip_getaddrinfo(const char *nodename, c +@@ -384,7 +386,9 @@ /* set up sockaddr */ inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); sa4->sin_family = AF_INET; @@ -1676,7 +1661,7 @@ Won't get to upstream (sin6)->sin6_family = AF_INET6; \ (sin6)->sin6_port = lwip_htons((port)); \ (sin6)->sin6_flowinfo = 0; \ -@@ -537,9 +547,11 @@ lwip_accept(int s, struct sockaddr *addr +@@ -537,9 +547,11 @@ LWIP_ASSERT("addr valid but addrlen NULL", addrlen != NULL); IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); @@ -1688,7 +1673,7 @@ Won't get to upstream MEMCPY(addr, &tempaddr, *addrlen); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock)); -@@ -878,9 +890,11 @@ lwip_recvfrom(int s, void *mem, size_t l +@@ -878,9 +890,11 @@ if (from && fromlen) #endif /* SOCKETS_DEBUG */ { @@ -1700,7 +1685,7 @@ Won't get to upstream MEMCPY(from, &saddr, *fromlen); } } -@@ -1764,9 +1778,11 @@ lwip_getaddrname(int s, struct sockaddr +@@ -1764,9 +1778,11 @@ ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); -- 2.11.0