aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-01-31 18:29:45 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2022-01-31 18:29:45 +0300
commit464d174103165453f149141d505ec8a09cc2fb17 (patch)
tree40cd9b2694d654f4fab948fc816c27671dcd89dc
parent1e82d32256c98de9bda8b61444eb53c626f76561 (diff)
downloadlibmicrohttpd-464d174103165453f149141d505ec8a09cc2fb17.tar.gz
libmicrohttpd-464d174103165453f149141d505ec8a09cc2fb17.zip
MHD_ip_limit_add(): do not use syscalls while holding the lock
-rw-r--r--src/microhttpd/daemon.c44
1 files changed, 23 insertions, 21 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 47fe742d..587000de 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -378,9 +378,9 @@ MHD_ip_limit_add (struct MHD_Daemon *daemon,
378 const struct sockaddr *addr, 378 const struct sockaddr *addr,
379 socklen_t addrlen) 379 socklen_t addrlen)
380{ 380{
381 struct MHD_IPCount *key; 381 struct MHD_IPCount *newkeyp;
382 void **nodep; 382 struct MHD_IPCount *keyp;
383 void *node; 383 struct MHD_IPCount **nodep;
384 enum MHD_Result result; 384 enum MHD_Result result;
385 385
386 daemon = MHD_get_master (daemon); 386 daemon = MHD_get_master (daemon);
@@ -388,45 +388,47 @@ MHD_ip_limit_add (struct MHD_Daemon *daemon,
388 if (0 == daemon->per_ip_connection_limit) 388 if (0 == daemon->per_ip_connection_limit)
389 return MHD_YES; 389 return MHD_YES;
390 390
391 if (NULL == (key = malloc (sizeof(*key)))) 391 newkeyp = (struct MHD_IPCount *) malloc (sizeof(struct MHD_IPCount));
392 if (NULL == newkeyp)
392 return MHD_NO; 393 return MHD_NO;
393 394
394 /* Initialize key */ 395 /* Initialize key */
395 if (MHD_NO == MHD_ip_addr_to_key (addr, 396 if (MHD_NO == MHD_ip_addr_to_key (addr,
396 addrlen, 397 addrlen,
397 key)) 398 newkeyp))
398 { 399 {
399 /* Allow unhandled address types through */ 400 free (newkeyp);
400 free (key); 401 return MHD_YES; /* Allow unhandled address types through */
401 return MHD_YES;
402 } 402 }
403
403 MHD_ip_count_lock (daemon); 404 MHD_ip_count_lock (daemon);
404 405
405 /* Search for the IP address */ 406 /* Search for the IP address */
406 if (NULL == (nodep = tsearch (key, 407 nodep = (struct MHD_IPCount **) tsearch (newkeyp,
407 &daemon->per_ip_connection_count, 408 &daemon->per_ip_connection_count,
408 &MHD_ip_addr_compare))) 409 &MHD_ip_addr_compare);
410 if (NULL == nodep)
409 { 411 {
412 MHD_ip_count_unlock (daemon);
413 free (newkeyp);
410#ifdef HAVE_MESSAGES 414#ifdef HAVE_MESSAGES
411 MHD_DLOG (daemon, 415 MHD_DLOG (daemon,
412 _ ("Failed to add IP connection count node.\n")); 416 _ ("Failed to add IP connection count node.\n"));
413#endif 417#endif
414 MHD_ip_count_unlock (daemon);
415 free (key);
416 return MHD_NO; 418 return MHD_NO;
417 } 419 }
418 node = *nodep; 420 keyp = *nodep;
419 /* If we got an existing node back, free the one we created */
420 if (node != key)
421 free (key);
422 key = (struct MHD_IPCount *) node;
423 /* Test if there is room for another connection; if so, 421 /* Test if there is room for another connection; if so,
424 * increment count */ 422 * increment count */
425 result = (key->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO; 423 result = (keyp->count < daemon->per_ip_connection_limit) ? MHD_YES : MHD_NO;
426 if (MHD_NO != result) 424 if (MHD_NO != result)
427 ++key->count; 425 ++keyp->count;
428
429 MHD_ip_count_unlock (daemon); 426 MHD_ip_count_unlock (daemon);
427
428 /* If we got an existing node back, free the one we created */
429 if (keyp != newkeyp)
430 free (newkeyp);
431
430 return result; 432 return result;
431} 433}
432 434