libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

test_https_get_parallel_threads.c (5671B)


      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_threads.c
     24  * @brief  Testcase for libmicrohttpd HTTPS GET operations with multi-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  * TODO: add test for external select!
     31  */
     32 
     33 #include "platform.h"
     34 #include "microhttpd.h"
     35 #include <sys/stat.h>
     36 #include <limits.h>
     37 #include <curl/curl.h>
     38 #include <pthread.h>
     39 #ifdef MHD_HTTPS_REQUIRE_GCRYPT
     40 #include <gcrypt.h>
     41 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */
     42 #include "tls_test_common.h"
     43 #include "tls_test_keys.h"
     44 
     45 #if defined(MHD_CPU_COUNT) && (MHD_CPU_COUNT + 0) < 4
     46 #undef MHD_CPU_COUNT
     47 #endif
     48 #if ! defined(MHD_CPU_COUNT)
     49 #define MHD_CPU_COUNT 4
     50 #endif
     51 
     52 /**
     53  * used when spawning multiple threads executing curl server requests
     54  *
     55  */
     56 static void *
     57 https_transfer_thread_adapter (void *args)
     58 {
     59   static int nonnull;
     60   struct https_test_data *cargs = args;
     61   unsigned int ret;
     62 
     63   ret = test_https_transfer (cargs->cls, cargs->port,
     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  */
     78 static unsigned int
     79 test_single_client (void *cls, uint16_t port, const char *cipher_suite,
     80                     int curl_proto_version)
     81 {
     82   void *client_thread_ret;
     83   struct https_test_data client_args =
     84   { NULL, port, cipher_suite, curl_proto_version };
     85   (void) cls;    /* Unused. Silent compiler warning. */
     86 
     87   client_thread_ret = https_transfer_thread_adapter (&client_args);
     88   if (client_thread_ret != NULL)
     89     return 1;
     90   return 0;
     91 }
     92 
     93 
     94 /**
     95  * Test parallel request handling.
     96  *
     97  * @return: 0 upon all client requests returning '0', 1 otherwise.
     98  *
     99  * TODO : make client_count a parameter - number of curl client threads to spawn
    100  */
    101 static unsigned int
    102 test_parallel_clients (void *cls, uint16_t port, const char *cipher_suite,
    103                        int curl_proto_version)
    104 {
    105   int i;
    106   int client_count = (MHD_CPU_COUNT - 1);
    107   void *client_thread_ret;
    108   pthread_t client_arr[client_count];
    109   struct https_test_data client_args =
    110   { NULL, port, cipher_suite, curl_proto_version };
    111   (void) cls;    /* Unused. Silent compiler warning. */
    112 
    113   for (i = 0; i < client_count; ++i)
    114   {
    115     if (pthread_create (&client_arr[i], NULL,
    116                         &https_transfer_thread_adapter, &client_args) != 0)
    117     {
    118       fprintf (stderr, "Error: failed to spawn test client threads.\n");
    119 
    120       return 1;
    121     }
    122   }
    123 
    124   /* check all client requests fulfilled correctly */
    125   for (i = 0; i < client_count; ++i)
    126   {
    127     if ((pthread_join (client_arr[i], &client_thread_ret) != 0) ||
    128         (client_thread_ret != NULL))
    129       return 1;
    130   }
    131 
    132   return 0;
    133 }
    134 
    135 
    136 int
    137 main (int argc, char *const *argv)
    138 {
    139   unsigned int errorCount = 0;
    140   const char *ssl_version;
    141   uint16_t port;
    142   unsigned int iseed;
    143   (void) argc;   /* Unused. Silent compiler warning. */
    144 
    145   if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
    146     port = 0;
    147   else
    148     port = 3010;
    149 
    150   /* initialize random seed used by curl clients */
    151   iseed = (unsigned int) time (NULL);
    152 
    153 #ifdef MHD_HTTPS_REQUIRE_GCRYPT
    154 #ifdef GCRYCTL_INITIALIZATION_FINISHED
    155   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    156 #endif
    157 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */
    158   srand (iseed);
    159   if (! testsuite_curl_global_init ())
    160     return 99;
    161   ssl_version = curl_version_info (CURLVERSION_NOW)->ssl_version;
    162   if (NULL == ssl_version)
    163   {
    164     fprintf (stderr, "Curl does not support SSL.  Cannot run the test.\n");
    165     curl_global_cleanup ();
    166     return 77;
    167   }
    168 
    169   errorCount +=
    170     test_wrap ("multi threaded daemon, single client", &test_single_client,
    171                NULL, port,
    172                MHD_USE_TLS | MHD_USE_ERROR_LOG | MHD_USE_THREAD_PER_CONNECTION
    173                | MHD_USE_INTERNAL_POLLING_THREAD,
    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 
    178   errorCount +=
    179     test_wrap ("multi threaded daemon, parallel client",
    180                &test_parallel_clients, NULL, port,
    181                MHD_USE_TLS | MHD_USE_ERROR_LOG | MHD_USE_THREAD_PER_CONNECTION
    182                | MHD_USE_INTERNAL_POLLING_THREAD,
    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 
    187   if (errorCount != 0)
    188     fprintf (stderr, "Failed test: %s, error: %u.\n", argv[0], errorCount);
    189 
    190   curl_global_cleanup ();
    191   return errorCount != 0 ? 1 : 0;
    192 }