test_https_get_parallel.c (6417B)
1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007 Christian Grothoff 4 Copyright (C) 2014-2022 Evgeny Grin (Karlson2k) 5 6 libmicrohttpd is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published 8 by the Free Software Foundation; either version 2, or (at your 9 option) any later version. 10 11 libmicrohttpd is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with libmicrohttpd; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1301, USA. 20 */ 21 22 /** 23 * @file test_https_get_parallel.c 24 * @brief Testcase for libmicrohttpd HTTPS GET operations with single-threaded 25 * MHD daemon and several clients working in parallel 26 * @author Sagie Amir 27 * @author Christian Grothoff 28 * @author Karlson2k (Evgeny Grin) 29 */ 30 31 #include "platform.h" 32 #include "microhttpd.h" 33 #include <sys/stat.h> 34 #include <limits.h> 35 #include <curl/curl.h> 36 #include <pthread.h> 37 #ifdef MHD_HTTPS_REQUIRE_GCRYPT 38 #include <gcrypt.h> 39 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */ 40 #include "tls_test_common.h" 41 #include "tls_test_keys.h" 42 43 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this 44 test into a marked, classifiable test error (TESTING.md, P5). */ 45 #include "mhd_panic_tripwire.h" 46 47 #if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 4 48 #undef MHD_CPU_COUNT 49 #endif 50 #if ! defined(MHD_CPU_COUNT) 51 #define MHD_CPU_COUNT 4 52 #endif 53 54 55 /** 56 * used when spawning multiple threads executing curl server requests 57 * 58 */ 59 static void * 60 https_transfer_thread_adapter (void *args) 61 { 62 static int nonnull; 63 struct https_test_data *cargs = args; 64 unsigned int ret; 65 66 ret = test_https_transfer (NULL, cargs->port, 67 cargs->cipher_suite, cargs->proto_version); 68 if (ret == 0) 69 return NULL; 70 return &nonnull; 71 } 72 73 74 /** 75 * Test non-parallel requests. 76 * 77 * @return: 0 upon all client requests returning '0', 1 otherwise. 78 * 79 * TODO : make client_count a parameter - number of curl client threads to spawn 80 */ 81 static unsigned int 82 test_single_client (void *cls, uint16_t port, const char *cipher_suite, 83 int curl_proto_version) 84 { 85 void *client_thread_ret; 86 struct https_test_data client_args = 87 { NULL, port, cipher_suite, curl_proto_version }; 88 (void) cls; /* Unused. Silent compiler warning. */ 89 90 client_thread_ret = https_transfer_thread_adapter (&client_args); 91 if (client_thread_ret != NULL) 92 return 1; 93 return 0; 94 } 95 96 97 /** 98 * Test parallel request handling. 99 * 100 * @return: 0 upon all client requests returning '0', 1 otherwise. 101 * 102 * TODO : make client_count a parameter - number of curl client threads to spawn 103 */ 104 static unsigned int 105 test_parallel_clients (void *cls, uint16_t port, const char *cipher_suite, 106 int curl_proto_version) 107 { 108 int i; 109 int client_count = (MHD_CPU_COUNT - 1); 110 void *client_thread_ret; 111 pthread_t client_arr[client_count]; 112 struct https_test_data client_args = 113 { NULL, port, cipher_suite, curl_proto_version }; 114 (void) cls; /* Unused. Silent compiler warning. */ 115 116 for (i = 0; i < client_count; ++i) 117 { 118 if (pthread_create (&client_arr[i], NULL, 119 &https_transfer_thread_adapter, &client_args) != 0) 120 { 121 fprintf (stderr, "Error: failed to spawn test client threads.\n"); 122 return 1; 123 } 124 } 125 126 /* check all client requests fulfilled correctly */ 127 for (i = 0; i < client_count; ++i) 128 { 129 if ((pthread_join (client_arr[i], &client_thread_ret) != 0) || 130 (client_thread_ret != NULL)) 131 return 1; 132 } 133 134 return 0; 135 } 136 137 138 int 139 main (int argc, char *const *argv) 140 { 141 unsigned int errorCount = 0; 142 uint16_t port; 143 unsigned int iseed; 144 (void) argc; /* Unused. Silent compiler warning. */ 145 146 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 147 port = 0; 148 else 149 port = 3020; 150 151 /* initialize random seed used by curl clients */ 152 iseed = (unsigned int) time (NULL); 153 srand (iseed); 154 if (! testsuite_curl_global_init ()) 155 return 99; 156 157 if (NULL == curl_version_info (CURLVERSION_NOW)->ssl_version) 158 { 159 fprintf (stderr, "Curl does not support SSL. Cannot run the test.\n"); 160 return 77; 161 } 162 #ifdef EPOLL_SUPPORT 163 errorCount += 164 test_wrap ("single threaded daemon, single client, epoll", 165 &test_single_client, 166 NULL, port, 167 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 168 | MHD_USE_ERROR_LOG | MHD_USE_EPOLL, 169 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 170 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 171 srv_self_signed_cert_pem, MHD_OPTION_END); 172 #endif 173 errorCount += 174 test_wrap ("single threaded daemon, single client", &test_single_client, 175 NULL, port, 176 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 177 | MHD_USE_ERROR_LOG, 178 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 179 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 180 srv_self_signed_cert_pem, MHD_OPTION_END); 181 #ifdef EPOLL_SUPPORT 182 errorCount += 183 test_wrap ("single threaded daemon, parallel clients, epoll", 184 &test_parallel_clients, NULL, port, 185 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 186 | MHD_USE_ERROR_LOG | MHD_USE_EPOLL, 187 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 188 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 189 srv_self_signed_cert_pem, MHD_OPTION_END); 190 #endif 191 errorCount += 192 test_wrap ("single threaded daemon, parallel clients", 193 &test_parallel_clients, NULL, port, 194 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 195 | MHD_USE_ERROR_LOG, 196 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 197 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 198 srv_self_signed_cert_pem, MHD_OPTION_END); 199 200 curl_global_cleanup (); 201 if (errorCount != 0) 202 fprintf (stderr, "Failed test: %s, error: %u.\n", argv[0], errorCount); 203 return errorCount != 0 ? 1 : 0; 204 }