libmicrohttpd

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

test_empty_response.c (7320B)


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