68
* Trace up to and return master daemon. If the supplied daemon
69
* is a master, then return the daemon itself.
71
static struct MHD_Daemon*
72
MHD_get_master (struct MHD_Daemon *daemon)
74
while (NULL != daemon->master)
75
daemon = daemon->master;
80
* Maintain connection count for single address.
96
* Lock shared structure for IP connection counts
99
MHD_ip_count_lock(struct MHD_Daemon *daemon)
101
if (0 != pthread_mutex_lock(&daemon->per_ip_connection_mutex))
104
MHD_DLOG (daemon, "Failed to acquire IP connection limit mutex\n");
111
* Unlock shared structure for IP connection counts
114
MHD_ip_count_unlock(struct MHD_Daemon *daemon)
116
if (0 != pthread_mutex_unlock(&daemon->per_ip_connection_mutex))
119
MHD_DLOG (daemon, "Failed to release IP connection limit mutex\n");
126
* Tree comparison function for IP addresses (supplied to tsearch() family).
127
* We compare everything in the struct up through the beginning of the
131
MHD_ip_addr_compare(const void *a1, const void *a2)
133
return memcmp (a1, a2, offsetof(struct MHD_IPCount, count));
137
* Parse address and initialize 'key' using the address. Returns MHD_YES
138
* on success and MHD_NO otherwise (e.g., invalid address type).
141
MHD_ip_addr_to_key(struct sockaddr *addr, socklen_t addrlen,
142
struct MHD_IPCount *key)
144
memset(key, 0, sizeof(*key));
147
if (addrlen == sizeof(struct sockaddr_in))
149
const struct sockaddr_in *addr4 = (const struct sockaddr_in*)addr;
150
key->family = AF_INET;
151
memcpy (&key->addr.ipv4, &addr4->sin_addr, sizeof(addr4->sin_addr));
157
if (addrlen == sizeof (struct sockaddr_in6))
159
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)addr;
160
key->family = AF_INET6;
161
memcpy (&key->addr.ipv6, &addr6->sin6_addr, sizeof(addr6->sin6_addr));
166
/* Some other address */
171
* Check if IP address is over its limit.
173
* @return Return MHD_YES if IP below limit, MHD_NO if IP has surpassed limit.
174
* Also returns MHD_NO if fails to allocate memory.
177
MHD_ip_limit_add(struct MHD_Daemon *daemon,
178
struct sockaddr *addr, socklen_t addrlen)
180
struct MHD_IPCount *key;
184
daemon = MHD_get_master (daemon);
186
/* Ignore if no connection limit assigned */
187
if (daemon->per_ip_connection_limit == 0)
190
key = malloc (sizeof(*key));
195
if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, key))
197
/* Allow unhandled address types through */
202
MHD_ip_count_lock (daemon);
204
/* Search for the IP address */
205
node = TSEARCH (key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
210
"Failed to add IP connection count node\n");
212
MHD_ip_count_unlock (daemon);
215
node = *(void**)node;
217
/* If we got an existing node back, free the one we created */
220
key = (struct MHD_IPCount*)node;
222
/* Test if there is room for another connection; if so,
224
result = (key->count < daemon->per_ip_connection_limit);
225
if (result == MHD_YES)
228
MHD_ip_count_unlock (daemon);
233
* Decrement connection count for IP address, removing from table
237
MHD_ip_limit_del(struct MHD_Daemon *daemon,
238
struct sockaddr *addr, socklen_t addrlen)
240
struct MHD_IPCount search_key;
241
struct MHD_IPCount *found_key;
244
daemon = MHD_get_master (daemon);
246
/* Ignore if no connection limit assigned */
247
if (daemon->per_ip_connection_limit == 0)
250
/* Initialize search key */
251
if (MHD_NO == MHD_ip_addr_to_key (addr, addrlen, &search_key))
254
MHD_ip_count_lock (daemon);
256
/* Search for the IP address */
257
node = TFIND (&search_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
259
/* Something's wrong if we couldn't find an IP address
260
* that was previously added */
265
"Failed to find previously-added IP address\n");
269
found_key = (struct MHD_IPCount*)*(void**)node;
271
/* Validate existing count for IP address */
272
if (found_key->count == 0)
276
"Previously-added IP address had 0 count\n");
281
/* Remove the node entirely if count reduces to 0 */
282
if (--found_key->count == 0)
284
TDELETE (found_key, &daemon->per_ip_connection_count, MHD_ip_addr_compare);
288
MHD_ip_count_unlock (daemon);
68
292
pthread_mutex_t MHD_gnutls_init_mutex;
368
598
MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
372
if ((daemon->per_ip_connection_limit != 0) && (daemon->max_connections > 0))
374
pos = daemon->connections;
377
if ((pos->addr != NULL) && (pos->addr_len == addrlen))
379
if (addrlen == sizeof (struct sockaddr_in))
381
const struct sockaddr_in *a1 =
382
(const struct sockaddr_in *) addr;
383
const struct sockaddr_in *a2 =
384
(const struct sockaddr_in *) pos->addr;
385
if (0 == memcmp (&a1->sin_addr, &a2->sin_addr,
386
sizeof (struct in_addr)))
390
if (addrlen == sizeof (struct sockaddr_in6))
392
const struct sockaddr_in6 *a1 =
393
(const struct sockaddr_in6 *) addr;
394
const struct sockaddr_in6 *a2 =
395
(const struct sockaddr_in6 *) pos->addr;
396
if (0 == memcmp (&a1->sin6_addr, &a2->sin6_addr,
397
sizeof (struct in6_addr)))
406
if ((daemon->max_connections == 0) || ((daemon->per_ip_connection_limit
408
&& (daemon->per_ip_connection_limit
601
if ((daemon->max_connections == 0)
602
|| (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO))
411
604
/* above connection limit - reject */
412
605
#if HAVE_MESSAGES
1023
1254
MHD_DLOG (retVal, "Failed to initialize TLS support\n");
1025
1256
CLOSE (socket_fd);
1257
pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
1030
1262
if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
1031
(0 != (options & MHD_USE_SELECT_INTERNALLY)))
1263
((0 != (options & MHD_USE_SELECT_INTERNALLY))
1264
&& (0 == retVal->worker_pool_size)))
1033
1266
pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal)))
1035
1268
#if HAVE_MESSAGES
1036
1269
MHD_DLOG (retVal,
1037
1270
"Failed to create listen thread: %s\n", STRERROR (errno));
1272
pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
1040
1274
CLOSE (socket_fd);
1277
else if (retVal->worker_pool_size > 0)
1282
unsigned long sk_flags;
1285
/* Coarse-grained count of connections per thread (note error
1286
* due to integer division). Also keep track of how many
1287
* connections are leftover after an equal split. */
1288
unsigned int conns_per_thread = retVal->max_connections
1289
/ retVal->worker_pool_size;
1290
unsigned int leftover_conns = retVal->max_connections
1291
% retVal->worker_pool_size;
1293
i = 0; /* we need this in case fcntl or malloc fails */
1295
/* Accept must be non-blocking. Multiple children may wake up
1296
* to handle a new connection, but only one will win the race.
1297
* The others must immediately return. */
1299
sk_flags = fcntl (socket_fd, F_GETFL);
1302
if (fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK) < 0)
1307
if (ioctlsocket (plibc_fd_get_handle (socket_fd), FIONBIO, &sk_flags) ==
1310
if (ioctlsocket (socket_fd, FIONBIO, &sk_flags) == SOCKET_ERROR)
1315
/* Allocate memory for pooled objects */
1316
retVal->worker_pool = malloc (sizeof (struct MHD_Daemon)
1317
* retVal->worker_pool_size);
1318
if (NULL == retVal->worker_pool)
1321
/* Start the workers in the pool */
1322
for (i = 0; i < retVal->worker_pool_size; ++i)
1324
/* Create copy of the Daemon object for each worker */
1325
struct MHD_Daemon *d = &retVal->worker_pool[i];
1326
memcpy (d, retVal, sizeof (struct MHD_Daemon));
1328
/* Adjust pooling params for worker daemons; note that memcpy()
1329
has already copied MHD_USE_SELECT_INTERNALLY thread model into
1330
the worker threads. */
1332
d->worker_pool_size = 0;
1333
d->worker_pool = NULL;
1335
/* Divide available connections evenly amongst the threads.
1336
* Thread indexes in [0, leftover_conns) each get one of the
1337
* leftover connections. */
1338
d->max_connections = conns_per_thread;
1339
if (i < leftover_conns)
1340
++d->max_connections;
1342
/* Spawn the worker thread */
1343
if (0 != pthread_create (&d->pid, NULL, &MHD_select_thread, d))
1347
"Failed to create pool thread: %d\n", STRERROR (errno));
1349
/* Free memory for this worker; cleanup below handles
1350
* all previously-created workers. */
1047
* Shutdown an http daemon.
1358
/* If no worker threads created, then shut down normally. Calling
1359
MHD_stop_daemon (as we do below) doesn't work here since it
1360
assumes a 0-sized thread pool means we had been in the default
1361
MHD_USE_SELECT_INTERNALLY mode. */
1365
pthread_mutex_destroy (&retVal->per_ip_connection_mutex);
1366
if (NULL != retVal->worker_pool)
1367
free (retVal->worker_pool);
1372
/* Shutdown worker threads we've already created. Pretend
1373
as though we had fully initialized our daemon, but
1374
with a smaller number of threads than had been
1376
retVal->worker_pool_size = i - 1;
1377
MHD_stop_daemon (retVal);
1382
* Close all connections for the daemon
1385
MHD_close_connections (struct MHD_Daemon *daemon)
1387
while (daemon->connections != NULL)
1389
if (-1 != daemon->connections->socket_fd)
1393
MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
1396
MHD_connection_close (daemon->connections,
1397
MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
1399
MHD_cleanup_connections (daemon);
1404
* Shutdown an http daemon
1050
1407
MHD_stop_daemon (struct MHD_Daemon *daemon)
1055
1413
if (daemon == NULL)
1057
1415
daemon->shutdown = MHD_YES;
1058
1416
fd = daemon->socket_fd;
1059
1417
daemon->socket_fd = -1;
1419
/* Prepare workers for shutdown */
1420
for (i = 0; i < daemon->worker_pool_size; ++i)
1422
daemon->worker_pool[i].shutdown = MHD_YES;
1423
daemon->worker_pool[i].socket_fd = -1;
1427
/* without this, either (thread pool = 0) threads would get stuck or
1428
* CLOSE would get stuck if attempted before (thread pool > 0)
1429
* threads have ended */
1430
SHUTDOWN (fd, SHUT_RDWR);
1060
1432
#if DEBUG_CLOSE
1061
1433
#if HAVE_MESSAGES
1062
1434
MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
1440
/* Signal workers to stop and clean them up */
1441
for (i = 0; i < daemon->worker_pool_size; ++i)
1442
pthread_kill (daemon->worker_pool[i].pid, SIGALRM);
1443
for (i = 0; i < daemon->worker_pool_size; ++i)
1445
pthread_join (daemon->worker_pool[i].pid, &unused);
1446
MHD_close_connections (&daemon->worker_pool[i]);
1448
free (daemon->worker_pool);
1066
1450
if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
1067
(0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
1451
((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
1452
&& (0 == daemon->worker_pool_size)))
1069
1454
pthread_kill (daemon->pid, SIGALRM);
1070
1455
pthread_join (daemon->pid, &unused);
1072
while (daemon->connections != NULL)
1074
if (-1 != daemon->connections->socket_fd)
1457
MHD_close_connections (daemon);
1076
1460
#if DEBUG_CLOSE
1077
1461
#if HAVE_MESSAGES
1078
MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
1081
MHD_connection_close (daemon->connections,
1082
MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
1084
MHD_cleanup_connections (daemon);
1462
MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
1087
1468
/* TLS clean up */
1088
1469
#if HTTPS_SUPPORT