libmicrohttpd

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

test_empty_response.c (7153B)


      1 /*
      2  This file is part of libmicrohttpd
      3  Copyright (C) 2013 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 3, 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_empty_response.c
     24  * @brief  Testcase for libmicrohttpd HTTPS GET operations with empty reply
     25  * @author Christian Grothoff
     26  * @author Karlson2k (Evgeny Grin)
     27  */
     28 #include "platform.h"
     29 #include "microhttpd.h"
     30 #include <limits.h>
     31 #include <sys/stat.h>
     32 #include <curl/curl.h>
     33 #ifdef MHD_HTTPS_REQUIRE_GCRYPT
     34 #include <gcrypt.h>
     35 #endif /* MHD_HTTPS_REQUIRE_GCRYPT */
     36 #include "tls_test_common.h"
     37 #include "tls_test_keys.h"
     38 
     39 static int oneone;
     40 
     41 static enum MHD_Result
     42 ahc_echo (void *cls,
     43           struct MHD_Connection *connection,
     44           const char *url,
     45           const char *method,
     46           const char *version,
     47           const char *upload_data, size_t *upload_data_size,
     48           void **req_cls)
     49 {
     50   struct MHD_Response *response;
     51   enum MHD_Result ret;
     52   (void) cls; (void) url; (void) method; (void) version;             /* Unused. Silent compiler warning. */
     53   (void) upload_data; (void) upload_data_size; (void) req_cls;       /* Unused. Silent compiler warning. */
     54 
     55   response = MHD_create_response_empty (MHD_RF_NONE);
     56   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
     57   MHD_destroy_response (response);
     58   return ret;
     59 }
     60 
     61 
     62 static unsigned int
     63 testInternalSelectGet (void)
     64 {
     65   struct MHD_Daemon *d;
     66   CURL *c;
     67   char buf[2048];
     68   struct CBC cbc;
     69   CURLM *multi;
     70   CURLMcode mret;
     71   fd_set rs;
     72   fd_set ws;
     73   fd_set es;
     74   int maxposixs; /* Max socket number unused on W32 */
     75   int running;
     76   struct CURLMsg *msg;
     77   time_t start;
     78   struct timeval tv;
     79   uint16_t port;
     80 
     81   if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
     82     port = 0;
     83   else
     84     port = 3000;
     85 
     86   multi = NULL;
     87   cbc.buf = buf;
     88   cbc.size = 2048;
     89   cbc.pos = 0;
     90   d = MHD_start_daemon (MHD_USE_ERROR_LOG | MHD_USE_TLS
     91                         | MHD_USE_INTERNAL_POLLING_THREAD,
     92                         port, NULL, NULL, &ahc_echo, NULL,
     93                         MHD_OPTION_HTTPS_MEM_KEY, srv_self_signed_key_pem,
     94                         MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
     95                         MHD_OPTION_END);
     96   if (d == NULL)
     97     return 256;
     98 
     99   if (0 == port)
    100   {
    101     const union MHD_DaemonInfo *dinfo;
    102     dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
    103     if ((NULL == dinfo) || (0 == dinfo->port) )
    104     {
    105       MHD_stop_daemon (d); return 32;
    106     }
    107     port = dinfo->port;
    108   }
    109 
    110   c = curl_easy_init ();
    111 #ifdef _DEBUG
    112   curl_easy_setopt (c, CURLOPT_VERBOSE, 1L);
    113 #endif
    114   curl_easy_setopt (c, CURLOPT_URL, "https://127.0.0.1/hello_world");
    115   curl_easy_setopt (c, CURLOPT_PORT, (long) port);
    116   curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
    117   curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
    118   /* TLS options */
    119   curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_DEFAULT);
    120   curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0L);
    121   curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0L);
    122   curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L);
    123   if (oneone)
    124     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    125   else
    126     curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    127   curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
    128   curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
    129   /* NOTE: use of CONNECTTIMEOUT without also
    130      setting NOSIGNAL results in really weird
    131      crashes on my system! */
    132   curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L);
    133 
    134 
    135   multi = curl_multi_init ();
    136   if (multi == NULL)
    137   {
    138     curl_easy_cleanup (c);
    139     MHD_stop_daemon (d);
    140     return 512;
    141   }
    142   mret = curl_multi_add_handle (multi, c);
    143   if (mret != CURLM_OK)
    144   {
    145     curl_multi_cleanup (multi);
    146     curl_easy_cleanup (c);
    147     MHD_stop_daemon (d);
    148     return 1024;
    149   }
    150   start = time (NULL);
    151   while ((time (NULL) - start < 5) && (multi != NULL))
    152   {
    153     maxposixs = -1;
    154     FD_ZERO (&rs);
    155     FD_ZERO (&ws);
    156     FD_ZERO (&es);
    157     mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
    158     if (mret != CURLM_OK)
    159     {
    160       curl_multi_remove_handle (multi, c);
    161       curl_multi_cleanup (multi);
    162       curl_easy_cleanup (c);
    163       MHD_stop_daemon (d);
    164       return 2048;
    165     }
    166     tv.tv_sec = 0;
    167     tv.tv_usec = 1000;
    168     if (-1 != maxposixs)
    169     {
    170       if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv))
    171       {
    172 #ifdef MHD_POSIX_SOCKETS
    173         if (EINTR != errno)
    174           abort ();
    175 #else
    176         if ((WSAEINVAL != WSAGetLastError ()) || (0 != rs.fd_count) || (0 !=
    177                                                                         ws.
    178                                                                         fd_count)
    179             || (0 != es.fd_count) )
    180           abort ();
    181         Sleep (1000);
    182 #endif
    183       }
    184     }
    185     else
    186       (void) sleep (1);
    187     curl_multi_perform (multi, &running);
    188     if (0 == running)
    189     {
    190       int pending;
    191       int curl_fine = 0;
    192       while (NULL != (msg = curl_multi_info_read (multi, &pending)))
    193       {
    194         if (msg->msg == CURLMSG_DONE)
    195         {
    196           if (msg->data.result == CURLE_OK)
    197             curl_fine = 1;
    198           else
    199           {
    200             fprintf (stderr,
    201                      "%s failed at %s:%d: `%s'\n",
    202                      "curl_multi_perform",
    203                      __FILE__,
    204                      __LINE__, curl_easy_strerror (msg->data.result));
    205             abort ();
    206           }
    207         }
    208       }
    209       if (! curl_fine)
    210       {
    211         fprintf (stderr, "libcurl haven't returned OK code\n");
    212         abort ();
    213       }
    214       curl_multi_remove_handle (multi, c);
    215       curl_multi_cleanup (multi);
    216       curl_easy_cleanup (c);
    217       c = NULL;
    218       multi = NULL;
    219     }
    220   }
    221   if (multi != NULL)
    222   {
    223     curl_multi_remove_handle (multi, c);
    224     curl_easy_cleanup (c);
    225     curl_multi_cleanup (multi);
    226   }
    227   MHD_stop_daemon (d);
    228   if (cbc.pos != 0)
    229     return 8192;
    230   return 0;
    231 }
    232 
    233 
    234 int
    235 main (int argc, char *const *argv)
    236 {
    237   unsigned int errorCount = 0;
    238   (void) argc;   /* Unused. Silent compiler warning. */
    239 
    240   oneone = 1;
    241   if (! testsuite_curl_global_init ())
    242     return 99;
    243   if (NULL == curl_version_info (CURLVERSION_NOW)->ssl_version)
    244   {
    245     fprintf (stderr, "Curl does not support SSL.  Cannot run the test.\n");
    246     curl_global_cleanup ();
    247     return 77;
    248   }
    249   if (0 != (errorCount = testInternalSelectGet ()))
    250     fprintf (stderr, "Failed test: %s, error: %u.\n", argv[0], errorCount);
    251   curl_global_cleanup ();
    252   return errorCount != 0 ? 1 : 0;
    253 }