1/* 2 This file is part of libmicrohttpd 3 Copyright (C) 2007 Christian Grothoff 4 5 libmicrohttpd is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 2, or (at your 8 option) any later version. 9 10 libmicrohttpd is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libmicrohttpd; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 Boston, MA 02111-1307, USA. 19*/ 20 21/** 22 * @file test_https_get_parallel.c 23 * @brief Testcase for libmicrohttpd HTTPS GET operations 24 * @author Sagie Amir 25 * @author Christian Grothoff 26 */ 27 28#include "platform.h" 29#include "microhttpd.h" 30#include <sys/stat.h> 31#include <limits.h> 32#include <curl/curl.h> 33#include <pthread.h> 34#include <gcrypt.h> 35#include "tls_test_common.h" 36 37#if defined(CPU_COUNT) && (CPU_COUNT+0) < 4 38#undef CPU_COUNT 39#endif 40#if !defined(CPU_COUNT) 41#define CPU_COUNT 4 42#endif 43 44extern const char srv_key_pem[]; 45extern const char srv_self_signed_cert_pem[]; 46 47int curl_check_version (const char *req_version, ...); 48 49 50/** 51 * used when spawning multiple threads executing curl server requests 52 * 53 */ 54static void * 55https_transfer_thread_adapter (void *args) 56{ 57 static int nonnull; 58 struct https_test_data *cargs = args; 59 int ret; 60 61 /* time spread incomming requests */ 62 usleep ((useconds_t) 10.0 * ((double) rand ()) / ((double) RAND_MAX)); 63 ret = test_https_transfer (NULL, 64 cargs->cipher_suite, cargs->proto_version); 65 if (ret == 0) 66 return NULL; 67 return &nonnull; 68} 69 70 71/** 72 * Test non-parallel requests. 73 * 74 * @return: 0 upon all client requests returning '0', -1 otherwise. 75 * 76 * TODO : make client_count a parameter - number of curl client threads to spawn 77 */ 78static int 79test_single_client (void *cls, const char *cipher_suite, 80 int curl_proto_version) 81{ 82 void *client_thread_ret; 83 struct https_test_data client_args = 84 { NULL, cipher_suite, curl_proto_version }; 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 - numver of curl client threads to spawn 99 */ 100static int 101test_parallel_clients (void * cls, const char *cipher_suite, 102 int curl_proto_version) 103{ 104 int i; 105 int client_count = (CPU_COUNT - 1); 106 void *client_thread_ret; 107 pthread_t client_arr[client_count]; 108 struct https_test_data client_args = 109 { NULL, cipher_suite, curl_proto_version }; 110 111 for (i = 0; i < client_count; ++i) 112 { 113 if (pthread_create (&client_arr[i], NULL, 114 &https_transfer_thread_adapter, &client_args) != 0) 115 { 116 fprintf (stderr, "Error: failed to spawn test client threads.\n"); 117 return -1; 118 } 119 } 120 121 /* check all client requests fulfilled correctly */ 122 for (i = 0; i < client_count; ++i) 123 { 124 if ((pthread_join (client_arr[i], &client_thread_ret) != 0) || 125 (client_thread_ret != NULL)) 126 return -1; 127 } 128 129 return 0; 130} 131 132 133int 134main (int argc, char *const *argv) 135{ 136 unsigned int errorCount = 0; 137 const char *aes256_sha = "AES256-SHA"; 138 139 /* initialize random seed used by curl clients */ 140 unsigned int iseed = (unsigned int) time (NULL); 141 srand (iseed); 142 if (0 != curl_global_init (CURL_GLOBAL_ALL)) 143 { 144 fprintf (stderr, "Error: %s\n", strerror (errno)); 145 return -1; 146 } 147 148 if (curl_uses_nss_ssl() == 0) 149 aes256_sha = "rsa_aes_256_sha"; 150#if EPOLL_SUPPORT 151 errorCount += 152 test_wrap ("single threaded daemon, single client, epoll", &test_single_client, 153 NULL, 154 MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_EPOLL_LINUX_ONLY, 155 aes256_sha, CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, 156 srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 157 srv_self_signed_cert_pem, MHD_OPTION_END); 158#endif 159 errorCount += 160 test_wrap ("single threaded daemon, single client", &test_single_client, 161 NULL, 162 MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL | MHD_USE_DEBUG, 163 aes256_sha, CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, 164 srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 165 srv_self_signed_cert_pem, MHD_OPTION_END); 166#if EPOLL_SUPPORT 167 errorCount += 168 test_wrap ("single threaded daemon, parallel clients, epoll", 169 &test_parallel_clients, NULL, 170 MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL | MHD_USE_DEBUG | MHD_USE_EPOLL_LINUX_ONLY, 171 aes256_sha, CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, 172 srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 173 srv_self_signed_cert_pem, MHD_OPTION_END); 174#endif 175 errorCount += 176 test_wrap ("single threaded daemon, parallel clients", 177 &test_parallel_clients, NULL, 178 MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL | MHD_USE_DEBUG, 179 aes256_sha, CURL_SSLVERSION_TLSv1, MHD_OPTION_HTTPS_MEM_KEY, 180 srv_key_pem, MHD_OPTION_HTTPS_MEM_CERT, 181 srv_self_signed_cert_pem, MHD_OPTION_END); 182 183 curl_global_cleanup (); 184 return errorCount != 0; 185} 186