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, ©Buffer); 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 }