aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/test_client_put_stop.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/test_client_put_stop.c')
-rw-r--r--src/microhttpd/test_client_put_stop.c155
1 files changed, 91 insertions, 64 deletions
diff --git a/src/microhttpd/test_client_put_stop.c b/src/microhttpd/test_client_put_stop.c
index eb481567..16a09d65 100644
--- a/src/microhttpd/test_client_put_stop.c
+++ b/src/microhttpd/test_client_put_stop.c
@@ -268,6 +268,7 @@ static uint16_t global_port; /**< MHD daemons listen port number */
268static int use_shutdown; /**< Use shutdown at client side */ 268static int use_shutdown; /**< Use shutdown at client side */
269static int use_close; /**< Use socket close at client side */ 269static int use_close; /**< Use socket close at client side */
270static int use_hard_close; /**< Use socket close with RST at client side */ 270static int use_hard_close; /**< Use socket close with RST at client side */
271static int use_stress_os; /**< Stress OS by RST before getting ACKs for sent packets */
271static int by_step; /**< Send request byte-by-byte */ 272static int by_step; /**< Send request byte-by-byte */
272static int upl_chunked; /**< Use chunked encoding for request body */ 273static int upl_chunked; /**< Use chunked encoding for request body */
273 274
@@ -277,83 +278,94 @@ static void
277test_global_init (void) 278test_global_init (void)
278{ 279{
279 rate_limiter = 0; 280 rate_limiter = 0;
280#ifdef HAVE_SYSCTLBYNAME
281 if (use_hard_close) 281 if (use_hard_close)
282 { 282 {
283 int blck_hl; 283#ifdef HAVE_SYSCTLBYNAME
284 size_t blck_hl_size = sizeof (blck_hl); 284 if (1)
285 if (0 == sysctlbyname ("net.inet.tcp.blackhole", &blck_hl, &blck_hl_size,
286 NULL, 0))
287 { 285 {
288 if (2 <= blck_hl) 286 int blck_hl;
287 size_t blck_hl_size = sizeof (blck_hl);
288 if (0 == sysctlbyname ("net.inet.tcp.blackhole", &blck_hl, &blck_hl_size,
289 NULL, 0))
289 { 290 {
290 fprintf (stderr, "'sysctl net.inet.tcp.blackhole = %d', test is " 291 if (2 <= blck_hl)
291 "unreliable with this system setting, skipping.\n", blck_hl); 292 {
292 exit (77); 293 fprintf (stderr, "'sysctl net.inet.tcp.blackhole = %d', test is "
294 "unreliable with this system setting, skipping.\n", blck_hl);
295 exit (77);
296 }
297 }
298 else
299 {
300 if (ENOENT != errno)
301 externalErrorExitDesc ("Cannot get 'net.inet.tcp.blackhole' value");
293 } 302 }
294 } 303 }
295 else
296 {
297 if (ENOENT != errno)
298 externalErrorExitDesc ("Cannot get 'net.inet.tcp.blackhole' value");
299 }
300 }
301#endif 304#endif
302#if defined(HAVE_SYSCTL) && defined(CTL_NET) && defined(PF_INET) && \ 305#if defined(HAVE_SYSCTL) && defined(CTL_NET) && defined(PF_INET) && \
303 defined(IPPROTO_ICMP) && defined(ICMPCTL_ICMPLIM) 306 defined(IPPROTO_ICMP) && defined(ICMPCTL_ICMPLIM)
304 if (use_hard_close) 307 if (1)
305 {
306 int mib[4];
307 int limit;
308 size_t limit_size = sizeof(limit);
309 mib[0] = CTL_NET;
310 mib[1] = PF_INET;
311 mib[2] = IPPROTO_ICMP;
312 mib[3] = ICMPCTL_ICMPLIM;
313 if (0 != sysctl (mib, 4, &limit, &limit_size, NULL, 0))
314 {
315 if (ENOENT == errno)
316 limit = 0; /* No such parameter (Darwin) */
317 else
318 externalErrorExitDesc ("Cannot get RST rate limit value");
319 }
320 else if (sizeof(limit) != limit_size)
321 externalErrorExitDesc ("Cannot get RST rate limit value");
322 if (limit > 0)
323 { 308 {
324#ifndef _MHD_HEAVY_TESTS 309 int mib[4];
325 fprintf (stderr, "This system has limits on number of RST packet" 310 int limit;
326 " per second (%d).\nThis test will be used only if configured " 311 size_t limit_size = sizeof(limit);
327 "with '--enable-heavy-test'.\n", limit); 312 mib[0] = CTL_NET;
328 exit (77); 313 mib[1] = PF_INET;
329#else /* _MHD_HEAVY_TESTS */ 314 mib[2] = IPPROTO_ICMP;
330 int test_limit; /**< Maximum number of checks per second */ 315 mib[3] = ICMPCTL_ICMPLIM;
331 test_limit = limit - limit / 10; /* Add some space to not hit the limiter */ 316 if (0 != sysctl (mib, 4, &limit, &limit_size, NULL, 0))
332 test_limit /= 4; /* Assume that all four tests with 'hard_close' run in parallel */
333 test_limit -= 5; /* Add some more space to not hit the limiter */
334 test_limit /= 3; /* Use only one third of available limit */
335 if (test_limit <= 0)
336 { 317 {
337 fprintf (stderr, "System limit for 'net.inet.icmp.icmplim' is " 318 if (ENOENT == errno)
338 "too strict for this test (value: %d).\n", limit); 319 limit = 0; /* No such parameter (new Darwin versions) */
339 exit (77); 320 else
321 externalErrorExitDesc ("Cannot get RST rate limit value");
340 } 322 }
341 if (verbose) 323 else if (sizeof(limit) != limit_size)
324 externalErrorExitDesc ("Cannot get RST rate limit value");
325 if (limit > 0)
342 { 326 {
343 printf ("Limiting number of checks to %d checks/second.\n", test_limit); 327#ifndef _MHD_HEAVY_TESTS
344 fflush (stdout); 328 fprintf (stderr, "This system has limits on number of RST packet"
345 } 329 " per second (%d).\nThis test will be used only if configured "
346 rate_limiter = (unsigned int) test_limit; 330 "with '--enable-heavy-test'.\n", limit);
331 exit (77);
332#else /* _MHD_HEAVY_TESTS */
333 int test_limit; /**< Maximum number of checks per second */
334
335 if (use_stress_os)
336 {
337 fprintf (stderr, "This system has limits on number of RST packet"
338 " per second (%d).\n'_stress_os' is not possible.\n", limit);
339 exit (77);
340 }
341 test_limit = limit - limit / 10; /* Add some space to not hit the limiter */
342 test_limit /= 4; /* Assume that all four tests with 'hard_close' run in parallel */
343 test_limit -= 5; /* Add some more space to not hit the limiter */
344 test_limit /= 3; /* Use only one third of available limit */
345 if (test_limit <= 0)
346 {
347 fprintf (stderr, "System limit for 'net.inet.icmp.icmplim' is "
348 "too strict for this test (value: %d).\n", limit);
349 exit (77);
350 }
351 if (verbose)
352 {
353 printf ("Limiting number of checks to %d checks/second.\n",
354 test_limit);
355 fflush (stdout);
356 }
357 rate_limiter = (unsigned int) test_limit;
347#if ! defined(HAVE_USLEEP) && ! defined(HAVE_NANOSLEEP) && ! defined(_WIN32) 358#if ! defined(HAVE_USLEEP) && ! defined(HAVE_NANOSLEEP) && ! defined(_WIN32)
348 fprintf (stderr, "Sleep function is required for this test, " 359 fprintf (stderr, "Sleep function is required for this test, "
349 "but not available on this system.\n"); 360 "but not available on this system.\n");
350 exit (77); 361 exit (77);
351#endif 362#endif
352#endif /* _MHD_HEAVY_TESTS */ 363#endif /* _MHD_HEAVY_TESTS */
364 }
353 } 365 }
354 }
355#endif /* HAVE_SYSCTL && CTL_NET && PF_INET && 366#endif /* HAVE_SYSCTL && CTL_NET && PF_INET &&
356 IPPROTO_ICMP && ICMPCTL_ICMPLIM */ 367 IPPROTO_ICMP && ICMPCTL_ICMPLIM */
368 }
357 if (MHD_YES != MHD_is_feature_supported (MHD_FEATURE_AUTOSUPPRESS_SIGPIPE)) 369 if (MHD_YES != MHD_is_feature_supported (MHD_FEATURE_AUTOSUPPRESS_SIGPIPE))
358 { 370 {
359#if defined(HAVE_SIGNAL_H) && defined(SIGPIPE) 371#if defined(HAVE_SIGNAL_H) && defined(SIGPIPE)
@@ -1523,12 +1535,24 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt)
1523 /* All request data has been sent. 1535 /* All request data has been sent.
1524 * Client will close the socket as the next step. */ 1536 * Client will close the socket as the next step. */
1525 if (full_req_recieved) 1537 if (full_req_recieved)
1526 do_client = 1; /* All data has been received by the MHD */
1527 else if ((0 == rate_limiter) && some_data_recieved)
1528 { 1538 {
1529 /* No RST rate limiter, no need to avoid extra RST 1539 /* All data has been received by the MHD */
1540 do_client = 1; /* Close the client socket */
1541 }
1542 else if (some_data_recieved &&
1543 (! use_hard_close || ((0 == rate_limiter) && use_stress_os)))
1544 {
1545 /* No RST rate limiter or no "hard close", no need to avoid extra RST
1530 * and at least something was received by the MHD */ 1546 * and at least something was received by the MHD */
1531 do_client = 1; 1547 /* In case of 'hard close' this can stress the OS, especially
1548 * if 'by_step' is enabled as several ACKs (for delivered packets
1549 * containing the request) from the server may arrive to the client
1550 * when the client has closed port and may be reflected by several
1551 * RSTs from the client side to the server side (when ACK received
1552 * without active connection then RST packet should be sent).
1553 * When listening socket receives RST packets, it may block
1554 * the sender preventing the next connection. */
1555 do_client = 1; /* Proceed with the closure of the client socket */
1532 } 1556 }
1533 else 1557 else
1534 { 1558 {
@@ -1536,7 +1560,7 @@ performQueryExternal (struct MHD_Daemon *d, struct _MHD_dumbClient *clnt)
1536 * before client closes connection to avoid RST for every ACK. 1560 * before client closes connection to avoid RST for every ACK.
1537 * When rate limiter is not enabled, the MHD must receive at 1561 * When rate limiter is not enabled, the MHD must receive at
1538 * least something before closing the connection. */ 1562 * least something before closing the connection. */
1539 do_client = 0; 1563 do_client = 0; /* Do not close the client socket yet */
1540 } 1564 }
1541 } 1565 }
1542 1566
@@ -2074,6 +2098,7 @@ main (int argc, char *const *argv)
2074 use_shutdown = has_in_name (argv[0], "_shutdown") ? 1 : 0; 2098 use_shutdown = has_in_name (argv[0], "_shutdown") ? 1 : 0;
2075 use_close = has_in_name (argv[0], "_close") ? 1 : 0; 2099 use_close = has_in_name (argv[0], "_close") ? 1 : 0;
2076 use_hard_close = has_in_name (argv[0], "_hard_close") ? 1 : 0; 2100 use_hard_close = has_in_name (argv[0], "_hard_close") ? 1 : 0;
2101 use_stress_os = has_in_name (argv[0], "_stress_os") ? 1 : 0;
2077 by_step = has_in_name (argv[0], "_steps") ? 1 : 0; 2102 by_step = has_in_name (argv[0], "_steps") ? 1 : 0;
2078 upl_chunked = has_in_name (argv[0], "_chunked") ? 1 : 0; 2103 upl_chunked = has_in_name (argv[0], "_chunked") ? 1 : 0;
2079#ifndef SO_LINGER 2104#ifndef SO_LINGER
@@ -2089,6 +2114,8 @@ main (int argc, char *const *argv)
2089 has_param (argc, argv, "--quiet") || 2114 has_param (argc, argv, "--quiet") ||
2090 has_param (argc, argv, "-s") || 2115 has_param (argc, argv, "-s") ||
2091 has_param (argc, argv, "--silent")); 2116 has_param (argc, argv, "--silent"));
2117 if (use_stress_os && ! use_hard_close)
2118 return 99;
2092 2119
2093 test_global_init (); 2120 test_global_init ();
2094 2121