test_https_get_select.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. This file is part of libmicrohttpd
  3. Copyright (C) 2007 Christian Grothoff
  4. libmicrohttpd is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 2, or (at your
  7. option) any later version.
  8. libmicrohttpd is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with libmicrohttpd; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file test_https_get_select.c
  19. * @brief Testcase for libmicrohttpd HTTPS GET operations
  20. * @author Sagie Amir
  21. */
  22. #include "platform.h"
  23. #include "microhttpd.h"
  24. #include <limits.h>
  25. #include <sys/stat.h>
  26. #include <curl/curl.h>
  27. #include <gcrypt.h>
  28. #include "tls_test_common.h"
  29. extern const char srv_key_pem[];
  30. extern const char srv_self_signed_cert_pem[];
  31. extern const char srv_signed_cert_pem[];
  32. extern const char srv_signed_key_pem[];
  33. static int oneone;
  34. static int
  35. ahc_echo (void *cls,
  36. struct MHD_Connection *connection,
  37. const char *url,
  38. const char *method,
  39. const char *version,
  40. const char *upload_data, size_t *upload_data_size,
  41. void **unused)
  42. {
  43. static int ptr;
  44. const char *me = cls;
  45. struct MHD_Response *response;
  46. int ret;
  47. if (0 != strcmp (me, method))
  48. return MHD_NO; /* unexpected method */
  49. if (&ptr != *unused)
  50. {
  51. *unused = &ptr;
  52. return MHD_YES;
  53. }
  54. *unused = NULL;
  55. response = MHD_create_response_from_buffer (strlen (url),
  56. (void *) url,
  57. MHD_RESPMEM_MUST_COPY);
  58. ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
  59. MHD_destroy_response (response);
  60. if (ret == MHD_NO)
  61. abort ();
  62. return ret;
  63. }
  64. static int
  65. testExternalGet (int flags)
  66. {
  67. struct MHD_Daemon *d;
  68. CURL *c;
  69. char buf[2048];
  70. struct CBC cbc;
  71. CURLM *multi;
  72. CURLMcode mret;
  73. fd_set rs;
  74. fd_set ws;
  75. fd_set es;
  76. MHD_socket max;
  77. int running;
  78. struct CURLMsg *msg;
  79. time_t start;
  80. struct timeval tv;
  81. const char *aes256_sha = "AES256-SHA";
  82. multi = NULL;
  83. cbc.buf = buf;
  84. cbc.size = 2048;
  85. cbc.pos = 0;
  86. d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | flags,
  87. 1082, NULL, NULL, &ahc_echo, "GET",
  88. MHD_OPTION_HTTPS_MEM_KEY, srv_key_pem,
  89. MHD_OPTION_HTTPS_MEM_CERT, srv_self_signed_cert_pem,
  90. MHD_OPTION_END);
  91. if (d == NULL)
  92. return 256;
  93. if (curl_uses_nss_ssl() == 0)
  94. aes256_sha = "rsa_aes_256_sha";
  95. c = curl_easy_init ();
  96. curl_easy_setopt (c, CURLOPT_URL, "https://127.0.0.1:1082/hello_world");
  97. curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
  98. curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
  99. /* TLS options */
  100. curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
  101. curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, aes256_sha);
  102. curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
  103. curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
  104. curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
  105. if (oneone)
  106. curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  107. else
  108. curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  109. curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
  110. curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
  111. /* NOTE: use of CONNECTTIMEOUT without also
  112. setting NOSIGNAL results in really weird
  113. crashes on my system! */
  114. curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
  115. multi = curl_multi_init ();
  116. if (multi == NULL)
  117. {
  118. curl_easy_cleanup (c);
  119. MHD_stop_daemon (d);
  120. return 512;
  121. }
  122. mret = curl_multi_add_handle (multi, c);
  123. if (mret != CURLM_OK)
  124. {
  125. curl_multi_cleanup (multi);
  126. curl_easy_cleanup (c);
  127. MHD_stop_daemon (d);
  128. return 1024;
  129. }
  130. start = time (NULL);
  131. while ((time (NULL) - start < 5) && (multi != NULL))
  132. {
  133. max = 0;
  134. FD_ZERO (&rs);
  135. FD_ZERO (&ws);
  136. FD_ZERO (&es);
  137. mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
  138. if (mret != CURLM_OK)
  139. {
  140. curl_multi_remove_handle (multi, c);
  141. curl_multi_cleanup (multi);
  142. curl_easy_cleanup (c);
  143. MHD_stop_daemon (d);
  144. return 2048;
  145. }
  146. if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
  147. {
  148. curl_multi_remove_handle (multi, c);
  149. curl_multi_cleanup (multi);
  150. curl_easy_cleanup (c);
  151. MHD_stop_daemon (d);
  152. return 4096;
  153. }
  154. tv.tv_sec = 0;
  155. tv.tv_usec = 1000;
  156. select (max + 1, &rs, &ws, &es, &tv);
  157. curl_multi_perform (multi, &running);
  158. if (running == 0)
  159. {
  160. msg = curl_multi_info_read (multi, &running);
  161. if (msg == NULL)
  162. break;
  163. if (msg->msg == CURLMSG_DONE)
  164. {
  165. if (msg->data.result != CURLE_OK)
  166. printf ("%s failed at %s:%d: `%s'\n",
  167. "curl_multi_perform",
  168. __FILE__,
  169. __LINE__, curl_easy_strerror (msg->data.result));
  170. curl_multi_remove_handle (multi, c);
  171. curl_multi_cleanup (multi);
  172. curl_easy_cleanup (c);
  173. c = NULL;
  174. multi = NULL;
  175. }
  176. }
  177. MHD_run (d);
  178. }
  179. if (multi != NULL)
  180. {
  181. curl_multi_remove_handle (multi, c);
  182. curl_easy_cleanup (c);
  183. curl_multi_cleanup (multi);
  184. }
  185. MHD_stop_daemon (d);
  186. if (cbc.pos != strlen ("/hello_world"))
  187. return 8192;
  188. if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
  189. return 16384;
  190. return 0;
  191. }
  192. int
  193. main (int argc, char *const *argv)
  194. {
  195. unsigned int errorCount = 0;
  196. if (0 != curl_global_init (CURL_GLOBAL_ALL))
  197. {
  198. fprintf (stderr, "Error: %s\n", strerror (errno));
  199. return -1;
  200. }
  201. #if EPOLL_SUPPORT
  202. if (0 != (errorCount = testExternalGet (MHD_USE_EPOLL_LINUX_ONLY)))
  203. fprintf (stderr, "Fail: %d\n", errorCount);
  204. #endif
  205. if (0 != (errorCount = testExternalGet (0)))
  206. fprintf (stderr, "Fail: %d\n", errorCount);
  207. curl_global_cleanup ();
  208. return errorCount != 0;
  209. }