test_https_get_select.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, 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 maxsock;
  77. #ifdef MHD_WINSOCK_SOCKETS
  78. int maxposixs; /* Max socket number unused on W32 */
  79. #else /* MHD_POSIX_SOCKETS */
  80. #define maxposixs maxsock
  81. #endif /* MHD_POSIX_SOCKETS */
  82. int running;
  83. struct CURLMsg *msg;
  84. time_t start;
  85. struct timeval tv;
  86. const char *aes256_sha = "AES256-SHA";
  87. multi = NULL;
  88. cbc.buf = buf;
  89. cbc.size = 2048;
  90. cbc.pos = 0;
  91. d = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL | flags,
  92. 1082, NULL, NULL, &ahc_echo, "GET",
  93. MHD_OPTION_HTTPS_MEM_KEY, srv_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. if (curl_uses_nss_ssl() == 0)
  99. aes256_sha = "rsa_aes_256_sha";
  100. c = curl_easy_init ();
  101. curl_easy_setopt (c, CURLOPT_URL, "https://127.0.0.1:1082/hello_world");
  102. curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
  103. curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
  104. /* TLS options */
  105. curl_easy_setopt (c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
  106. curl_easy_setopt (c, CURLOPT_SSL_CIPHER_LIST, aes256_sha);
  107. curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0);
  108. curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0);
  109. curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
  110. if (oneone)
  111. curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  112. else
  113. curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  114. curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
  115. curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
  116. /* NOTE: use of CONNECTTIMEOUT without also
  117. setting NOSIGNAL results in really weird
  118. crashes on my system! */
  119. curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
  120. multi = curl_multi_init ();
  121. if (multi == NULL)
  122. {
  123. curl_easy_cleanup (c);
  124. MHD_stop_daemon (d);
  125. return 512;
  126. }
  127. mret = curl_multi_add_handle (multi, c);
  128. if (mret != CURLM_OK)
  129. {
  130. curl_multi_cleanup (multi);
  131. curl_easy_cleanup (c);
  132. MHD_stop_daemon (d);
  133. return 1024;
  134. }
  135. start = time (NULL);
  136. while ((time (NULL) - start < 5) && (multi != NULL))
  137. {
  138. maxsock = MHD_INVALID_SOCKET;
  139. maxposixs = -1;
  140. FD_ZERO (&rs);
  141. FD_ZERO (&ws);
  142. FD_ZERO (&es);
  143. mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
  144. if (mret != CURLM_OK)
  145. {
  146. curl_multi_remove_handle (multi, c);
  147. curl_multi_cleanup (multi);
  148. curl_easy_cleanup (c);
  149. MHD_stop_daemon (d);
  150. return 2048;
  151. }
  152. if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock))
  153. {
  154. curl_multi_remove_handle (multi, c);
  155. curl_multi_cleanup (multi);
  156. curl_easy_cleanup (c);
  157. MHD_stop_daemon (d);
  158. return 4096;
  159. }
  160. tv.tv_sec = 0;
  161. tv.tv_usec = 1000;
  162. select (maxposixs + 1, &rs, &ws, &es, &tv);
  163. curl_multi_perform (multi, &running);
  164. if (running == 0)
  165. {
  166. msg = curl_multi_info_read (multi, &running);
  167. if (msg == NULL)
  168. break;
  169. if (msg->msg == CURLMSG_DONE)
  170. {
  171. if (msg->data.result != CURLE_OK)
  172. printf ("%s failed at %s:%d: `%s'\n",
  173. "curl_multi_perform",
  174. __FILE__,
  175. __LINE__, curl_easy_strerror (msg->data.result));
  176. curl_multi_remove_handle (multi, c);
  177. curl_multi_cleanup (multi);
  178. curl_easy_cleanup (c);
  179. c = NULL;
  180. multi = NULL;
  181. }
  182. }
  183. MHD_run (d);
  184. }
  185. if (multi != NULL)
  186. {
  187. curl_multi_remove_handle (multi, c);
  188. curl_easy_cleanup (c);
  189. curl_multi_cleanup (multi);
  190. }
  191. MHD_stop_daemon (d);
  192. if (cbc.pos != strlen ("/hello_world"))
  193. return 8192;
  194. if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
  195. return 16384;
  196. return 0;
  197. }
  198. int
  199. main (int argc, char *const *argv)
  200. {
  201. unsigned int errorCount = 0;
  202. if (0 != curl_global_init (CURL_GLOBAL_ALL))
  203. {
  204. fprintf (stderr, "Error: %s\n", strerror (errno));
  205. return -1;
  206. }
  207. #if EPOLL_SUPPORT
  208. if (0 != (errorCount = testExternalGet (MHD_USE_EPOLL_LINUX_ONLY)))
  209. fprintf (stderr, "Fail: %d\n", errorCount);
  210. #endif
  211. if (0 != (errorCount = testExternalGet (0)))
  212. fprintf (stderr, "Fail: %d\n", errorCount);
  213. curl_global_cleanup ();
  214. return errorCount != 0;
  215. }