test_https_get_parallel.c (6250B)
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 #if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 4 44 #undef MHD_CPU_COUNT 45 #endif 46 #if ! defined(MHD_CPU_COUNT) 47 #define MHD_CPU_COUNT 4 48 #endif 49 50 51 /** 52 * used when spawning multiple threads executing curl server requests 53 * 54 */ 55 static void * 56 https_transfer_thread_adapter (void *args) 57 { 58 static int nonnull; 59 struct https_test_data *cargs = args; 60 unsigned int ret; 61 62 ret = test_https_transfer (NULL, cargs->port, 63 cargs->cipher_suite, cargs->proto_version); 64 if (ret == 0) 65 return NULL; 66 return &nonnull; 67 } 68 69 70 /** 71 * Test non-parallel requests. 72 * 73 * @return: 0 upon all client requests returning '0', 1 otherwise. 74 * 75 * TODO : make client_count a parameter - number of curl client threads to spawn 76 */ 77 static unsigned int 78 test_single_client (void *cls, uint16_t port, const char *cipher_suite, 79 int curl_proto_version) 80 { 81 void *client_thread_ret; 82 struct https_test_data client_args = 83 { NULL, port, cipher_suite, curl_proto_version }; 84 (void) cls; /* Unused. Silent compiler warning. */ 85 86 client_thread_ret = https_transfer_thread_adapter (&client_args); 87 if (client_thread_ret != NULL) 88 return 1; 89 return 0; 90 } 91 92 93 /** 94 * Test parallel request handling. 95 * 96 * @return: 0 upon all client requests returning '0', 1 otherwise. 97 * 98 * TODO : make client_count a parameter - number of curl client threads to spawn 99 */ 100 static unsigned int 101 test_parallel_clients (void *cls, uint16_t port, const char *cipher_suite, 102 int curl_proto_version) 103 { 104 int i; 105 int client_count = (MHD_CPU_COUNT - 1); 106 void *client_thread_ret; 107 pthread_t client_arr[client_count]; 108 struct https_test_data client_args = 109 { NULL, port, cipher_suite, curl_proto_version }; 110 (void) cls; /* Unused. Silent compiler warning. */ 111 112 for (i = 0; i < client_count; ++i) 113 { 114 if (pthread_create (&client_arr[i], NULL, 115 &https_transfer_thread_adapter, &client_args) != 0) 116 { 117 fprintf (stderr, "Error: failed to spawn test client threads.\n"); 118 return 1; 119 } 120 } 121 122 /* check all client requests fulfilled correctly */ 123 for (i = 0; i < client_count; ++i) 124 { 125 if ((pthread_join (client_arr[i], &client_thread_ret) != 0) || 126 (client_thread_ret != NULL)) 127 return 1; 128 } 129 130 return 0; 131 } 132 133 134 int 135 main (int argc, char *const *argv) 136 { 137 unsigned int errorCount = 0; 138 uint16_t port; 139 unsigned int iseed; 140 (void) argc; /* Unused. Silent compiler warning. */ 141 142 if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) 143 port = 0; 144 else 145 port = 3020; 146 147 /* initialize random seed used by curl clients */ 148 iseed = (unsigned int) time (NULL); 149 srand (iseed); 150 if (! testsuite_curl_global_init ()) 151 return 99; 152 153 if (NULL == curl_version_info (CURLVERSION_NOW)->ssl_version) 154 { 155 fprintf (stderr, "Curl does not support SSL. Cannot run the test.\n"); 156 return 77; 157 } 158 #ifdef EPOLL_SUPPORT 159 errorCount += 160 test_wrap ("single threaded daemon, single client, epoll", 161 &test_single_client, 162 NULL, port, 163 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 164 | MHD_USE_ERROR_LOG | MHD_USE_EPOLL, 165 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 166 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 167 srv_self_signed_cert_pem, MHD_OPTION_END); 168 #endif 169 errorCount += 170 test_wrap ("single threaded daemon, single client", &test_single_client, 171 NULL, port, 172 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 173 | MHD_USE_ERROR_LOG, 174 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 175 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 176 srv_self_signed_cert_pem, MHD_OPTION_END); 177 #ifdef EPOLL_SUPPORT 178 errorCount += 179 test_wrap ("single threaded daemon, parallel clients, epoll", 180 &test_parallel_clients, NULL, port, 181 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 182 | MHD_USE_ERROR_LOG | MHD_USE_EPOLL, 183 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 184 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 185 srv_self_signed_cert_pem, MHD_OPTION_END); 186 #endif 187 errorCount += 188 test_wrap ("single threaded daemon, parallel clients", 189 &test_parallel_clients, NULL, port, 190 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS 191 | MHD_USE_ERROR_LOG, 192 NULL, CURL_SSLVERSION_DEFAULT, MHD_OPTION_HTTPS_MEM_KEY, 193 srv_self_signed_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 194 srv_self_signed_cert_pem, MHD_OPTION_END); 195 196 curl_global_cleanup (); 197 if (errorCount != 0) 198 fprintf (stderr, "Failed test: %s, error: %u.\n", argv[0], errorCount); 199 return errorCount != 0 ? 1 : 0; 200 }