1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
Description: Remove limit on number of sockets
Forwarded: https://savannah.nongnu.org/patch/?9431
Author: Joan Lledó <jlledom@member.fsf.org>
Last-Update: 2024-03-19
--- a/src/include/lwip/opt.h
+++ b/src/include/lwip/opt.h
@@ -2070,6 +2070,15 @@
#endif
/**
+ * LWIP_SOCKET_OPEN_COUNT==1: Number of sockets is not limited to MEMP_NUM_NETCONN.
+ * When enabled, sockets are allocated in the heap and the amount of sockets is
+ * only limited by the heap size. Handle with care regarding execution speed.
+ */
+#if !defined LWIP_SOCKET_OPEN_COUNT || defined __DOXYGEN__
+#define LWIP_SOCKET_OPEN_COUNT 0
+#endif
+
+/**
* LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT
* options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set
* in seconds. (does not require sockets.c, and will affect tcp.c)
--- a/contrib/ports/unix/posixlib/lwipopts.h
+++ b/contrib/ports/unix/posixlib/lwipopts.h
@@ -33,6 +33,7 @@
/* Sockets API config */
#define LWIP_COMPAT_SOCKETS 0
#define LWIP_SOCKET_OFFSET 1
+#define LWIP_SOCKET_OPEN_COUNT 1
/* User posix socket headers */
#define LWIP_SOCKET_EXTERNAL_HEADERS 1
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -301,7 +301,12 @@
#endif /* LWIP_IPV6_MLD */
/** The global array of available sockets */
+static int sockets_slots_count = NUM_SOCKETS;
+#if LWIP_SOCKET_OPEN_COUNT
+static struct lwip_sock *sockets = NULL;
+#else
static struct lwip_sock sockets[NUM_SOCKETS];
+#endif /* LWIP_SOCKET_OPEN_COUNT */
#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
#if LWIP_TCPIP_CORE_LOCKING
@@ -450,7 +455,7 @@
tryget_socket_unconn_nouse(int fd)
{
int s = fd - LWIP_SOCKET_OFFSET;
- if ((s < 0) || (s >= NUM_SOCKETS)) {
+ if ((s < 0) || (s >= sockets_slots_count)) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("tryget_socket_unconn(%d): invalid\n", fd));
return NULL;
}
@@ -519,7 +524,7 @@
{
struct lwip_sock *sock = tryget_socket(fd);
if (!sock) {
- if ((fd < LWIP_SOCKET_OFFSET) || (fd >= (LWIP_SOCKET_OFFSET + NUM_SOCKETS))) {
+ if ((fd < LWIP_SOCKET_OFFSET) || (fd >= (LWIP_SOCKET_OFFSET + sockets_slots_count))) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("get_socket(%d): invalid\n", fd));
}
set_errno(EBADF);
@@ -528,6 +533,57 @@
return sock;
}
+#if LWIP_SOCKET_OPEN_COUNT
+/**
+ * Allocate MEMP_NUM_NETCONN slots for new sockets.
+ *
+ * @return 0 on success; -1 on error
+ */
+static int
+alloc_socket_slots_locked(void) {
+ int sockets_new_count;
+ struct lwip_sock *old_sockets, *new_sockets;
+
+ sockets_new_count = sockets_slots_count + MEMP_NUM_NETCONN;
+ new_sockets = (struct lwip_sock*)mem_calloc(sockets_new_count, sizeof(struct lwip_sock));
+ if(!new_sockets) {
+ /* No free memory */
+ return -1;
+ }
+ old_sockets = sockets;
+ MEMCPY(new_sockets, old_sockets, sizeof(struct lwip_sock) * sockets_slots_count);
+ sockets = new_sockets;
+ sockets_slots_count = sockets_new_count;
+ mem_free(old_sockets);
+
+ return 0;
+}
+#endif /* LWIP_SOCKET_OPEN_COUNT */
+
+/**
+ * Initialize a new allocated socket.
+ *
+ * @param idx ths socket index in the internal array
+ * @param newconn the netconn for which to initialize a socket
+ * @param accepted 1 if socket has been created by accept(),
+ * 0 if socket has been created by socket()
+ * @return the index of the new socket; -1 on error
+ */
+static int
+init_socket(int idx, struct netconn *newconn, int accepted)
+{
+ sockets[idx].lastdata.pbuf = NULL;
+#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
+ LWIP_ASSERT("sockets[i].select_waiting == 0", sockets[idx].select_waiting == 0);
+ sockets[idx].rcvevent = 0;
+ /* TCP sendbuf is empty, but the socket is not yet writable until connected
+ * (unless it has been created by accept()). */
+ sockets[idx].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
+ sockets[idx].errevent = 0;
+#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
+ return idx + LWIP_SOCKET_OFFSET;
+}
+
/**
* Allocate a new socket for a given netconn.
*
@@ -541,10 +597,15 @@
{
int i;
SYS_ARCH_DECL_PROTECT(lev);
- LWIP_UNUSED_ARG(accepted);
+
+#if LWIP_SOCKET_OPEN_COUNT
+ if (sockets == NULL) {
+ sockets = (struct lwip_sock*)mem_calloc(NUM_SOCKETS, sizeof(struct lwip_sock));
+ }
+#endif /* LWIP_SOCKET_OPEN_COUNT */
/* allocate a new socket identifier */
- for (i = 0; i < NUM_SOCKETS; ++i) {
+ for (i = 0; i < sockets_slots_count; ++i) {
/* Protect socket array */
SYS_ARCH_PROTECT(lev);
if (!sockets[i].conn) {
@@ -560,20 +621,23 @@
/* The socket is not yet known to anyone, so no need to protect
after having marked it as used. */
SYS_ARCH_UNPROTECT(lev);
- sockets[i].lastdata.pbuf = NULL;
-#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
- LWIP_ASSERT("sockets[i].select_waiting == 0", sockets[i].select_waiting == 0);
- sockets[i].rcvevent = 0;
- /* TCP sendbuf is empty, but the socket is not yet writable until connected
- * (unless it has been created by accept()). */
- sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
- sockets[i].errevent = 0;
-#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
- return i + LWIP_SOCKET_OFFSET;
+ return init_socket(i, newconn, accepted);
}
SYS_ARCH_UNPROTECT(lev);
}
+#if LWIP_SOCKET_OPEN_COUNT
+ SYS_ARCH_PROTECT(lev);
+ if (alloc_socket_slots_locked() < 0) {
+ SYS_ARCH_UNPROTECT(lev);
+ return -1;
+ }
+ sockets[i].conn = newconn;
+ SYS_ARCH_UNPROTECT(lev);
+
+ return init_socket(i, newconn, accepted);
+#else /* LWIP_SOCKET_OPEN_COUNT */
return -1;
+#endif /* LWIP_SOCKET_OPEN_COUNT */
}
/** Free a socket (under lock)
@@ -696,7 +760,7 @@
done_socket(sock);
return -1;
}
- LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < NUM_SOCKETS + LWIP_SOCKET_OFFSET));
+ LWIP_ASSERT("invalid socket index", (newsock >= LWIP_SOCKET_OFFSET) && (newsock < sockets_slots_count + LWIP_SOCKET_OFFSET));
nsock = &sockets[newsock - LWIP_SOCKET_OFFSET];
/* Note that POSIX only requires us to check addr is non-NULL. addrlen must
|