diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-10-26 18:52:53 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-10-26 18:52:53 +0200 |
commit | 5e5dbf980de763480f7957f64af78bbb2159d9a0 (patch) | |
tree | c769f03c3d7b78df899023ff4366042670ca23f8 | |
parent | b8516d23ba11cf3a94fcbf2ea228ea0456354017 (diff) | |
download | libmicrohttpd-5e5dbf980de763480f7957f64af78bbb2159d9a0.tar.gz libmicrohttpd-5e5dbf980de763480f7957f64af78bbb2159d9a0.zip |
add tests for empty reply in HTTPS
-rw-r--r-- | src/examples/.gitignore | 2 | ||||
-rw-r--r-- | src/examples/Makefile.am | 9 | ||||
-rw-r--r-- | src/examples/minimal_example_empty_tls.c | 150 | ||||
-rw-r--r-- | src/microhttpd/mhd_send.c | 23 | ||||
-rw-r--r-- | src/testcurl/.gitignore | 1 | ||||
-rw-r--r-- | src/testcurl/https/test_https_get.c | 156 | ||||
-rw-r--r-- | src/testcurl/https/tls_test_common.c | 61 | ||||
-rw-r--r-- | src/testcurl/test_get.c | 20 | ||||
-rw-r--r-- | src/testcurl/test_get_empty.c | 941 |
9 files changed, 1331 insertions, 32 deletions
diff --git a/src/examples/.gitignore b/src/examples/.gitignore index 9da24b59..7fa3e9b8 100644 --- a/src/examples/.gitignore +++ b/src/examples/.gitignore | |||
@@ -35,3 +35,5 @@ upgrade_example | |||
35 | /timeout | 35 | /timeout |
36 | http_chunked_compression | 36 | http_chunked_compression |
37 | http_compression | 37 | http_compression |
38 | minimal_example_empty | ||
39 | minimal_example_empty_tls | ||
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am index 7ffddff5..5dcee4d2 100644 --- a/src/examples/Makefile.am +++ b/src/examples/Makefile.am | |||
@@ -39,7 +39,9 @@ EXTRA_DIST = msgs_i18n.c | |||
39 | noinst_EXTRA_DIST = msgs_i18n.c | 39 | noinst_EXTRA_DIST = msgs_i18n.c |
40 | 40 | ||
41 | if ENABLE_HTTPS | 41 | if ENABLE_HTTPS |
42 | noinst_PROGRAMS += https_fileserver_example | 42 | noinst_PROGRAMS += \ |
43 | https_fileserver_example \ | ||
44 | minimal_example_empty_tls | ||
43 | endif | 45 | endif |
44 | if HAVE_POSTPROCESSOR | 46 | if HAVE_POSTPROCESSOR |
45 | noinst_PROGRAMS += \ | 47 | noinst_PROGRAMS += \ |
@@ -89,6 +91,11 @@ minimal_example_empty_SOURCES = \ | |||
89 | minimal_example_empty_LDADD = \ | 91 | minimal_example_empty_LDADD = \ |
90 | $(top_builddir)/src/microhttpd/libmicrohttpd.la | 92 | $(top_builddir)/src/microhttpd/libmicrohttpd.la |
91 | 93 | ||
94 | minimal_example_empty_tls_SOURCES = \ | ||
95 | minimal_example_empty_tls.c | ||
96 | minimal_example_empty_tls_LDADD = \ | ||
97 | $(top_builddir)/src/microhttpd/libmicrohttpd.la | ||
98 | |||
92 | upgrade_example_SOURCES = \ | 99 | upgrade_example_SOURCES = \ |
93 | upgrade_example.c | 100 | upgrade_example.c |
94 | upgrade_example_CFLAGS = \ | 101 | upgrade_example_CFLAGS = \ |
diff --git a/src/examples/minimal_example_empty_tls.c b/src/examples/minimal_example_empty_tls.c new file mode 100644 index 00000000..e3daca5f --- /dev/null +++ b/src/examples/minimal_example_empty_tls.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2007 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | /** | ||
20 | * @file minimal_example_empty_ssl.c | ||
21 | * @brief minimal example for how to use libmicrohttpd | ||
22 | * @author Christian Grothoff | ||
23 | */ | ||
24 | |||
25 | #include "platform.h" | ||
26 | #include <microhttpd.h> | ||
27 | |||
28 | |||
29 | static int | ||
30 | ahc_echo (void *cls, | ||
31 | struct MHD_Connection *connection, | ||
32 | const char *url, | ||
33 | const char *method, | ||
34 | const char *version, | ||
35 | const char *upload_data, | ||
36 | size_t *upload_data_size, | ||
37 | void **ptr) | ||
38 | { | ||
39 | static int aptr; | ||
40 | struct MHD_Response *response; | ||
41 | int ret; | ||
42 | |||
43 | (void) url; /* Unused. Silent compiler warning. */ | ||
44 | (void) version; /* Unused. Silent compiler warning. */ | ||
45 | (void) upload_data; /* Unused. Silent compiler warning. */ | ||
46 | (void) upload_data_size; /* Unused. Silent compiler warning. */ | ||
47 | |||
48 | if (0 != strcmp (method, "GET")) | ||
49 | return MHD_NO; /* unexpected method */ | ||
50 | if (&aptr != *ptr) | ||
51 | { | ||
52 | /* do never respond on first call */ | ||
53 | *ptr = &aptr; | ||
54 | return MHD_YES; | ||
55 | } | ||
56 | *ptr = NULL; /* reset when done */ | ||
57 | response = MHD_create_response_from_buffer (0, | ||
58 | NULL, | ||
59 | MHD_RESPMEM_PERSISTENT); | ||
60 | ret = MHD_queue_response (connection, | ||
61 | MHD_HTTP_NO_CONTENT, | ||
62 | response); | ||
63 | MHD_destroy_response (response); | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | |||
68 | /* test server key */ | ||
69 | const char srv_signed_key_pem[] = "-----BEGIN RSA PRIVATE KEY-----\n" | ||
70 | "MIIEowIBAAKCAQEAvfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW\n" | ||
71 | "+K03KwEku55QvnUndwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8IL\n" | ||
72 | "q4sw32vo0fbMu5BZF49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ0\n" | ||
73 | "20Q5EAAEseD1YtWCIpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6\n" | ||
74 | "QYGGh1QmHRPAy3CBII6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6x\n" | ||
75 | "yoOl204xuekZOaG9RUPId74Rtmwfi1TLbBzo2wIDAQABAoIBADu09WSICNq5cMe4\n" | ||
76 | "+NKCLlgAT1NiQpLls1gKRbDhKiHU9j8QWNvWWkJWrCya4QdUfLCfeddCMeiQmv3K\n" | ||
77 | "lJMvDs+5OjJSHFoOsGiuW2Ias7IjnIojaJalfBml6frhJ84G27IXmdz6gzOiTIer\n" | ||
78 | "DjeAgcwBaKH5WwIay2TxIaScl7AwHBauQkrLcyb4hTmZuQh6ArVIN6+pzoVuORXM\n" | ||
79 | "bpeNWl2l/HSN3VtUN6aCAKbN/X3o0GavCCMn5Fa85uJFsab4ss/uP+2PusU71+zP\n" | ||
80 | "sBm6p/2IbGvF5k3VPDA7X5YX61sukRjRBihY8xSnNYx1UcoOsX6AiPnbhifD8+xQ\n" | ||
81 | "Tlf8oJUCgYEA0BTfzqNpr9Wxw5/QXaSdw7S/0eP5a0C/nwURvmfSzuTD4equzbEN\n" | ||
82 | "d+dI/s2JMxrdj/I4uoAfUXRGaabevQIjFzC9uyE3LaOyR2zhuvAzX+vVcs6bSXeU\n" | ||
83 | "pKpCAcN+3Z3evMaX2f+z/nfSUAl2i4J2R+/LQAWJW4KwRky/m+cxpfUCgYEA6bN1\n" | ||
84 | "b73bMgM8wpNt6+fcmS+5n0iZihygQ2U2DEud8nZJL4Nrm1dwTnfZfJBnkGj6+0Q0\n" | ||
85 | "cOwj2KS0/wcEdJBP0jucU4v60VMhp75AQeHqidIde0bTViSRo3HWKXHBIFGYoU3T\n" | ||
86 | "LyPyKndbqsOObnsFXHn56Nwhr2HLf6nw4taGQY8CgYBoSW36FLCNbd6QGvLFXBGt\n" | ||
87 | "2lMhEM8az/K58kJ4WXSwOLtr6MD/WjNT2tkcy0puEJLm6BFCd6A6pLn9jaKou/92\n" | ||
88 | "SfltZjJPb3GUlp9zn5tAAeSSi7YMViBrfuFiHObij5LorefBXISLjuYbMwL03MgH\n" | ||
89 | "Ocl2JtA2ywMp2KFXs8GQWQKBgFyIVv5ogQrbZ0pvj31xr9HjqK6d01VxIi+tOmpB\n" | ||
90 | "4ocnOLEcaxX12BzprW55ytfOCVpF1jHD/imAhb3YrHXu0fwe6DXYXfZV4SSG2vB7\n" | ||
91 | "IB9z14KBN5qLHjNGFpMQXHSMek+b/ftTU0ZnPh9uEM5D3YqRLVd7GcdUhHvG8P8Q\n" | ||
92 | "C9aXAoGBAJtID6h8wOGMP0XYX5YYnhlC7dOLfk8UYrzlp3xhqVkzKthTQTj6wx9R\n" | ||
93 | "GtC4k7U1ki8oJsfcIlBNXd768fqDVWjYju5rzShMpo8OCTS6ipAblKjCxPPVhIpv\n" | ||
94 | "tWPlbSn1qj6wylstJ5/3Z+ZW5H4wIKp5jmLiioDhcP0L/Ex3Zx8O\n" | ||
95 | "-----END RSA PRIVATE KEY-----\n"; | ||
96 | |||
97 | /* test server CA signed certificates */ | ||
98 | const char srv_signed_cert_pem[] = "-----BEGIN CERTIFICATE-----\n" | ||
99 | "MIIDGzCCAgWgAwIBAgIES0KCvTALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAxMMdGVz\n" | ||
100 | "dF9jYV9jZXJ0MB4XDTEwMDEwNTAwMDcyNVoXDTQ1MDMxMjAwMDcyNVowFzEVMBMG\n" | ||
101 | "A1UEAxMMdGVzdF9jYV9jZXJ0MIIBHzALBgkqhkiG9w0BAQEDggEOADCCAQkCggEA\n" | ||
102 | "vfTdv+3fgvVTKRnP/HVNG81cr8TrUP/iiyuve/THMzvFXhCW+K03KwEku55QvnUn\n" | ||
103 | "dwBfU/ROzLlv+5hotgiDRNFT3HxurmhouySBrJNJv7qWp8ILq4sw32vo0fbMu5BZ\n" | ||
104 | "F49bUXK9L3kW2PdhTtSQPWHEzNrCxO+YgCilKHkY3vQNfdJ020Q5EAAEseD1YtWC\n" | ||
105 | "IpRvJzYlZMpjYB1ubTl24kwrgOKUJYKqM4jmF4DVQp4oOK/6QYGGh1QmHRPAy3CB\n" | ||
106 | "II6sbb+sZT9cAqU6GYQVB35lm4XAgibXV6KgmpVxVQQ69U6xyoOl204xuekZOaG9\n" | ||
107 | "RUPId74Rtmwfi1TLbBzo2wIDAQABo3YwdDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM\n" | ||
108 | "MAoGCCsGAQUFBwMBMA8GA1UdDwEB/wQFAwMHIAAwHQYDVR0OBBYEFOFi4ilKOP1d\n" | ||
109 | "XHlWCMwmVKr7mgy8MB8GA1UdIwQYMBaAFP2olB4s2T/xuoQ5pT2RKojFwZo2MAsG\n" | ||
110 | "CSqGSIb3DQEBBQOCAQEAHVWPxazupbOkG7Did+dY9z2z6RjTzYvurTtEKQgzM2Vz\n" | ||
111 | "GQBA+3pZ3c5mS97fPIs9hZXfnQeelMeZ2XP1a+9vp35bJjZBBhVH+pqxjCgiUflg\n" | ||
112 | "A3Zqy0XwwVCgQLE2HyaU3DLUD/aeIFK5gJaOSdNTXZLv43K8kl4cqDbMeRpVTbkt\n" | ||
113 | "YmG4AyEOYRNKGTqMEJXJoxD5E3rBUNrVI/XyTjYrulxbNPcMWEHKNeeqWpKDYTFo\n" | ||
114 | "Bb01PCthGXiq/4A2RLAFosadzRa8SBpoSjPPfZ0b2w4MJpReHqKbR5+T2t6hzml6\n" | ||
115 | "4ToyOKPDmamiTuN5KzLN3cw7DQlvWMvqSOChPLnA3Q==\n" | ||
116 | "-----END CERTIFICATE-----\n"; | ||
117 | |||
118 | |||
119 | int | ||
120 | main (int argc, | ||
121 | char *const *argv) | ||
122 | { | ||
123 | struct MHD_Daemon *d; | ||
124 | |||
125 | if (argc != 2) | ||
126 | { | ||
127 | printf ("%s PORT\n", argv[0]); | ||
128 | return 1; | ||
129 | } | ||
130 | d = MHD_start_daemon (/* MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */ | ||
131 | MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
132 | | MHD_USE_TLS, | ||
133 | /* MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, */ | ||
134 | /* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | MHD_USE_POLL, */ | ||
135 | /* MHD_USE_THREAD_PER_CONNECTION | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG, */ | ||
136 | atoi (argv[1]), | ||
137 | NULL, NULL, &ahc_echo, NULL, | ||
138 | MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 120, | ||
139 | MHD_OPTION_STRICT_FOR_CLIENT, (int) 1, | ||
140 | /* Optionally, the gnutls_load_file() can be used to | ||
141 | load the key and the certificate from file. */ | ||
142 | MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, | ||
143 | MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, | ||
144 | MHD_OPTION_END); | ||
145 | if (d == NULL) | ||
146 | return 1; | ||
147 | (void) getc (stdin); | ||
148 | MHD_stop_daemon (d); | ||
149 | return 0; | ||
150 | } | ||
diff --git a/src/microhttpd/mhd_send.c b/src/microhttpd/mhd_send.c index e50be96e..db621cb2 100644 --- a/src/microhttpd/mhd_send.c +++ b/src/microhttpd/mhd_send.c | |||
@@ -240,7 +240,8 @@ MHD_send_on_connection_ (struct MHD_Connection *connection, | |||
240 | ssize_t ret; | 240 | ssize_t ret; |
241 | 241 | ||
242 | /* error handling from send_param_adapter() */ | 242 | /* error handling from send_param_adapter() */ |
243 | if ((MHD_INVALID_SOCKET == s) || (MHD_CONNECTION_CLOSED == connection->state)) | 243 | if ( (MHD_INVALID_SOCKET == s) || |
244 | (MHD_CONNECTION_CLOSED == connection->state) ) | ||
244 | { | 245 | { |
245 | return MHD_ERR_NOTCONN_; | 246 | return MHD_ERR_NOTCONN_; |
246 | } | 247 | } |
@@ -382,10 +383,22 @@ MHD_send_on_connection2_ (struct MHD_Connection *connection, | |||
382 | { | 383 | { |
383 | #ifdef HTTPS_SUPPORT | 384 | #ifdef HTTPS_SUPPORT |
384 | if (0 != (connection->daemon->options & MHD_USE_TLS)) | 385 | if (0 != (connection->daemon->options & MHD_USE_TLS)) |
385 | return MHD_send_on_connection_ (connection, | 386 | { |
386 | header, | 387 | ssize_t ret; |
387 | header_size, | 388 | |
388 | MHD_SSO_HDR_CORK); | 389 | ret = MHD_send_on_connection_ (connection, |
390 | header, | ||
391 | header_size, | ||
392 | MHD_SSO_HDR_CORK); | ||
393 | if ( (ret == header_size) && | ||
394 | (0 == buffer_size) && | ||
395 | connection->sk_cork_on) | ||
396 | { | ||
397 | (void) gnutls_record_uncork (connection->tls_session, 0); | ||
398 | connection->sk_cork_on = false; | ||
399 | } | ||
400 | return ret; | ||
401 | } | ||
389 | #endif | 402 | #endif |
390 | #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV) | 403 | #if defined(HAVE_SENDMSG) || defined(HAVE_WRITEV) |
391 | MHD_socket s = connection->socket_fd; | 404 | MHD_socket s = connection->socket_fd; |
diff --git a/src/testcurl/.gitignore b/src/testcurl/.gitignore index 800bdffe..52457fa4 100644 --- a/src/testcurl/.gitignore +++ b/src/testcurl/.gitignore | |||
@@ -108,3 +108,4 @@ test_large_put_inc11 | |||
108 | test_delete | 108 | test_delete |
109 | test_digestauth_sha256 | 109 | test_digestauth_sha256 |
110 | perf_get_concurrent11 | 110 | perf_get_concurrent11 |
111 | test_get_empty | ||
diff --git a/src/testcurl/https/test_https_get.c b/src/testcurl/https/test_https_get.c index 17248bf7..8f62e46c 100644 --- a/src/testcurl/https/test_https_get.c +++ b/src/testcurl/https/test_https_get.c | |||
@@ -37,6 +37,10 @@ | |||
37 | extern const char srv_signed_cert_pem[]; | 37 | extern const char srv_signed_cert_pem[]; |
38 | extern const char srv_signed_key_pem[]; | 38 | extern const char srv_signed_key_pem[]; |
39 | 39 | ||
40 | |||
41 | static int global_port; | ||
42 | |||
43 | |||
40 | /* perform a HTTP GET request via SSL/TLS */ | 44 | /* perform a HTTP GET request via SSL/TLS */ |
41 | static int | 45 | static int |
42 | test_secure_get (FILE *test_fd, | 46 | test_secure_get (FILE *test_fd, |
@@ -55,7 +59,8 @@ test_secure_get (FILE *test_fd, | |||
55 | d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | 59 | d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION |
56 | | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS | 60 | | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS |
57 | | MHD_USE_ERROR_LOG, port, | 61 | | MHD_USE_ERROR_LOG, port, |
58 | NULL, NULL, &http_ahc, NULL, | 62 | NULL, NULL, |
63 | &http_ahc, NULL, | ||
59 | MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, | 64 | MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, |
60 | MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, | 65 | MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, |
61 | MHD_OPTION_END); | 66 | MHD_OPTION_END); |
@@ -76,13 +81,156 @@ test_secure_get (FILE *test_fd, | |||
76 | port = (int) dinfo->port; | 81 | port = (int) dinfo->port; |
77 | } | 82 | } |
78 | 83 | ||
79 | ret = test_https_transfer (test_fd, port, cipher_suite, proto_version); | 84 | ret = test_https_transfer (test_fd, |
85 | port, | ||
86 | cipher_suite, | ||
87 | proto_version); | ||
80 | 88 | ||
81 | MHD_stop_daemon (d); | 89 | MHD_stop_daemon (d); |
82 | return ret; | 90 | return ret; |
83 | } | 91 | } |
84 | 92 | ||
85 | 93 | ||
94 | static int | ||
95 | ahc_empty (void *cls, | ||
96 | struct MHD_Connection *connection, | ||
97 | const char *url, | ||
98 | const char *method, | ||
99 | const char *version, | ||
100 | const char *upload_data, | ||
101 | size_t *upload_data_size, | ||
102 | void **unused) | ||
103 | { | ||
104 | static int ptr; | ||
105 | struct MHD_Response *response; | ||
106 | int ret; | ||
107 | (void) cls; | ||
108 | (void) url; | ||
109 | (void) url; | ||
110 | (void) version; /* Unused. Silent compiler warning. */ | ||
111 | (void) upload_data; | ||
112 | (void) upload_data_size; /* Unused. Silent compiler warning. */ | ||
113 | |||
114 | if (0 != strcasecmp ("GET", | ||
115 | method)) | ||
116 | return MHD_NO; /* unexpected method */ | ||
117 | if (&ptr != *unused) | ||
118 | { | ||
119 | *unused = &ptr; | ||
120 | return MHD_YES; | ||
121 | } | ||
122 | *unused = NULL; | ||
123 | response = MHD_create_response_from_buffer (0, | ||
124 | NULL, | ||
125 | MHD_RESPMEM_PERSISTENT); | ||
126 | ret = MHD_queue_response (connection, | ||
127 | MHD_HTTP_OK, | ||
128 | response); | ||
129 | MHD_destroy_response (response); | ||
130 | if (ret == MHD_NO) | ||
131 | { | ||
132 | fprintf (stderr, "Failed to queue response.\n"); | ||
133 | _exit (20); | ||
134 | } | ||
135 | return ret; | ||
136 | } | ||
137 | |||
138 | |||
139 | static int | ||
140 | curlExcessFound (CURL *c, | ||
141 | curl_infotype type, | ||
142 | char *data, | ||
143 | size_t size, | ||
144 | void *cls) | ||
145 | { | ||
146 | static const char *excess_found = "Excess found"; | ||
147 | const size_t str_size = strlen (excess_found); | ||
148 | (void) c; /* Unused. Silence compiler warning. */ | ||
149 | |||
150 | if ((CURLINFO_TEXT == type) | ||
151 | &&(size >= str_size) | ||
152 | &&(0 == strncmp (excess_found, data, str_size))) | ||
153 | *(int *) cls = 1; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | |||
158 | static int | ||
159 | testEmptyGet (int poll_flag) | ||
160 | { | ||
161 | struct MHD_Daemon *d; | ||
162 | CURL *c; | ||
163 | char buf[2048]; | ||
164 | struct CBC cbc; | ||
165 | CURLcode errornum; | ||
166 | int excess_found = 0; | ||
167 | |||
168 | |||
169 | if ( (0 == global_port) && | ||
170 | (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) | ||
171 | { | ||
172 | global_port = 1225; | ||
173 | |||
174 | } | ||
175 | |||
176 | cbc.buf = buf; | ||
177 | cbc.size = 2048; | ||
178 | cbc.pos = 0; | ||
179 | d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
180 | | poll_flag | MHD_USE_TLS, | ||
181 | global_port, NULL, NULL, | ||
182 | &ahc_empty, NULL, | ||
183 | MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem, | ||
184 | MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem, | ||
185 | MHD_OPTION_END); | ||
186 | if (d == NULL) | ||
187 | return 4194304; | ||
188 | if (0 == global_port) | ||
189 | { | ||
190 | const union MHD_DaemonInfo *dinfo; | ||
191 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
192 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
193 | { | ||
194 | MHD_stop_daemon (d); return 32; | ||
195 | } | ||
196 | global_port = (int) dinfo->port; | ||
197 | } | ||
198 | c = curl_easy_init (); | ||
199 | curl_easy_setopt (c, CURLOPT_URL, "https://127.0.0.1/"); | ||
200 | curl_easy_setopt (c, CURLOPT_PORT, (long) global_port); | ||
201 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
202 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
203 | curl_easy_setopt (c, CURLOPT_DEBUGFUNCTION, &curlExcessFound); | ||
204 | curl_easy_setopt (c, CURLOPT_DEBUGDATA, &excess_found); | ||
205 | curl_easy_setopt (c, CURLOPT_VERBOSE, 1L); | ||
206 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
207 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
208 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
209 | curl_easy_setopt (c, CURLOPT_SSL_VERIFYPEER, 0L); | ||
210 | curl_easy_setopt (c, CURLOPT_SSL_VERIFYHOST, 0L); | ||
211 | /* NOTE: use of CONNECTTIMEOUT without also | ||
212 | setting NOSIGNAL results in really weird | ||
213 | crashes on my system!*/ | ||
214 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
215 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
216 | { | ||
217 | fprintf (stderr, | ||
218 | "curl_easy_perform failed: `%s'\n", | ||
219 | curl_easy_strerror (errornum)); | ||
220 | curl_easy_cleanup (c); | ||
221 | MHD_stop_daemon (d); | ||
222 | return 8388608; | ||
223 | } | ||
224 | curl_easy_cleanup (c); | ||
225 | MHD_stop_daemon (d); | ||
226 | if (cbc.pos != 0) | ||
227 | return 16777216; | ||
228 | if (excess_found) | ||
229 | return 33554432; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | |||
86 | int | 234 | int |
87 | main (int argc, char *const *argv) | 235 | main (int argc, char *const *argv) |
88 | { | 236 | { |
@@ -109,11 +257,9 @@ main (int argc, char *const *argv) | |||
109 | { | 257 | { |
110 | aes256_sha_tlsv1 = "rsa_aes_256_sha"; | 258 | aes256_sha_tlsv1 = "rsa_aes_256_sha"; |
111 | } | 259 | } |
112 | |||
113 | errorCount += | 260 | errorCount += |
114 | test_secure_get (NULL, aes256_sha_tlsv1, CURL_SSLVERSION_TLSv1); | 261 | test_secure_get (NULL, aes256_sha_tlsv1, CURL_SSLVERSION_TLSv1); |
115 | print_test_result (errorCount, argv[0]); | 262 | errorCount += testEmptyGet (0); |
116 | |||
117 | curl_global_cleanup (); | 263 | curl_global_cleanup (); |
118 | 264 | ||
119 | return errorCount != 0 ? 1 : 0; | 265 | return errorCount != 0 ? 1 : 0; |
diff --git a/src/testcurl/https/tls_test_common.c b/src/testcurl/https/tls_test_common.c index eb7cb14c..9d988451 100644 --- a/src/testcurl/https/tls_test_common.c +++ b/src/testcurl/https/tls_test_common.c | |||
@@ -62,7 +62,8 @@ setup_ca_cert () | |||
62 | */ | 62 | */ |
63 | int | 63 | int |
64 | test_daemon_get (void *cls, | 64 | test_daemon_get (void *cls, |
65 | const char *cipher_suite, int proto_version, | 65 | const char *cipher_suite, |
66 | int proto_version, | ||
66 | int port, | 67 | int port, |
67 | int ver_peer) | 68 | int ver_peer) |
68 | { | 69 | { |
@@ -71,7 +72,7 @@ test_daemon_get (void *cls, | |||
71 | CURLcode errornum; | 72 | CURLcode errornum; |
72 | char url[255]; | 73 | char url[255]; |
73 | size_t len; | 74 | size_t len; |
74 | (void) cls; /* Unused. Silent compiler warning. */ | 75 | (void) cls; /* Unused. Silence compiler warning. */ |
75 | 76 | ||
76 | len = strlen (test_data); | 77 | len = strlen (test_data); |
77 | if (NULL == (cbc.buf = malloc (sizeof (char) * len))) | 78 | if (NULL == (cbc.buf = malloc (sizeof (char) * len))) |
@@ -138,20 +139,29 @@ test_daemon_get (void *cls, | |||
138 | 139 | ||
139 | 140 | ||
140 | void | 141 | void |
141 | print_test_result (int test_outcome, char *test_name) | 142 | print_test_result (int test_outcome, |
143 | char *test_name) | ||
142 | { | 144 | { |
143 | if (test_outcome != 0) | 145 | if (test_outcome != 0) |
144 | fprintf (stderr, "running test: %s [fail: %u]\n", test_name, (unsigned | 146 | fprintf (stderr, |
145 | int) | 147 | "running test: %s [fail: %u]\n", |
148 | test_name, (unsigned | ||
149 | int) | ||
146 | test_outcome); | 150 | test_outcome); |
147 | #if 0 | 151 | #if 0 |
148 | else | 152 | else |
149 | fprintf (stdout, "running test: %s [pass]\n", test_name); | 153 | fprintf (stdout, |
154 | "running test: %s [pass]\n", | ||
155 | test_name); | ||
150 | #endif | 156 | #endif |
151 | } | 157 | } |
152 | 158 | ||
159 | |||
153 | size_t | 160 | size_t |
154 | copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) | 161 | copyBuffer (void *ptr, |
162 | size_t size, | ||
163 | size_t nmemb, | ||
164 | void *ctx) | ||
155 | { | 165 | { |
156 | struct CBC *cbc = ctx; | 166 | struct CBC *cbc = ctx; |
157 | 167 | ||
@@ -162,13 +172,19 @@ copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) | |||
162 | return size * nmemb; | 172 | return size * nmemb; |
163 | } | 173 | } |
164 | 174 | ||
175 | |||
165 | /** | 176 | /** |
166 | * HTTP access handler call back | 177 | * HTTP access handler call back |
167 | */ | 178 | */ |
168 | int | 179 | int |
169 | http_ahc (void *cls, struct MHD_Connection *connection, | 180 | http_ahc (void *cls, |
170 | const char *url, const char *method, const char *version, | 181 | struct MHD_Connection *connection, |
171 | const char *upload_data, size_t *upload_data_size, void **ptr) | 182 | const char *url, |
183 | const char *method, | ||
184 | const char *version, | ||
185 | const char *upload_data, | ||
186 | size_t *upload_data_size, | ||
187 | void **ptr) | ||
172 | { | 188 | { |
173 | static int aptr; | 189 | static int aptr; |
174 | struct MHD_Response *response; | 190 | struct MHD_Response *response; |
@@ -193,15 +209,26 @@ http_ahc (void *cls, struct MHD_Connection *connection, | |||
193 | return ret; | 209 | return ret; |
194 | } | 210 | } |
195 | 211 | ||
212 | |||
196 | /* HTTP access handler call back */ | 213 | /* HTTP access handler call back */ |
197 | int | 214 | int |
198 | http_dummy_ahc (void *cls, struct MHD_Connection *connection, | 215 | http_dummy_ahc (void *cls, |
199 | const char *url, const char *method, const char *version, | 216 | struct MHD_Connection *connection, |
200 | const char *upload_data, size_t *upload_data_size, | 217 | const char *url, |
218 | const char *method, | ||
219 | const char *version, | ||
220 | const char *upload_data, | ||
221 | size_t *upload_data_size, | ||
201 | void **ptr) | 222 | void **ptr) |
202 | { | 223 | { |
203 | (void) cls; (void) connection; (void) url; (void) method; (void) version; /* Unused. Silent compiler warning. */ | 224 | (void) cls; |
204 | (void) upload_data; (void) upload_data_size; (void) ptr; /* Unused. Silent compiler warning. */ | 225 | (void) connection; |
226 | (void) url; | ||
227 | (void) method; | ||
228 | (void) version; /* Unused. Silent compiler warning. */ | ||
229 | (void) upload_data; | ||
230 | (void) upload_data_size; | ||
231 | (void) ptr; /* Unused. Silent compiler warning. */ | ||
205 | return 0; | 232 | return 0; |
206 | } | 233 | } |
207 | 234 | ||
@@ -215,7 +242,9 @@ http_dummy_ahc (void *cls, struct MHD_Connection *connection, | |||
215 | */ | 242 | */ |
216 | /* TODO have test wrap consider a NULL cbc */ | 243 | /* TODO have test wrap consider a NULL cbc */ |
217 | int | 244 | int |
218 | send_curl_req (char *url, struct CBC *cbc, const char *cipher_suite, | 245 | send_curl_req (char *url, |
246 | struct CBC *cbc, | ||
247 | const char *cipher_suite, | ||
219 | int proto_version) | 248 | int proto_version) |
220 | { | 249 | { |
221 | CURL *c; | 250 | CURL *c; |
diff --git a/src/testcurl/test_get.c b/src/testcurl/test_get.c index dee5a9c1..09cae5f6 100644 --- a/src/testcurl/test_get.c +++ b/src/testcurl/test_get.c | |||
@@ -719,14 +719,19 @@ ahc_empty (void *cls, | |||
719 | const char *url, | 719 | const char *url, |
720 | const char *method, | 720 | const char *method, |
721 | const char *version, | 721 | const char *version, |
722 | const char *upload_data, size_t *upload_data_size, | 722 | const char *upload_data, |
723 | size_t *upload_data_size, | ||
723 | void **unused) | 724 | void **unused) |
724 | { | 725 | { |
725 | static int ptr; | 726 | static int ptr; |
726 | struct MHD_Response *response; | 727 | struct MHD_Response *response; |
727 | int ret; | 728 | int ret; |
728 | (void) cls; (void) url; (void) url; (void) version; /* Unused. Silent compiler warning. */ | 729 | (void) cls; |
729 | (void) upload_data; (void) upload_data_size; /* Unused. Silent compiler warning. */ | 730 | (void) url; |
731 | (void) url; | ||
732 | (void) version; /* Unused. Silent compiler warning. */ | ||
733 | (void) upload_data; | ||
734 | (void) upload_data_size; /* Unused. Silent compiler warning. */ | ||
730 | 735 | ||
731 | if (0 != strcasecmp ("GET", method)) | 736 | if (0 != strcasecmp ("GET", method)) |
732 | return MHD_NO; /* unexpected method */ | 737 | return MHD_NO; /* unexpected method */ |
@@ -739,7 +744,9 @@ ahc_empty (void *cls, | |||
739 | response = MHD_create_response_from_buffer (0, | 744 | response = MHD_create_response_from_buffer (0, |
740 | NULL, | 745 | NULL, |
741 | MHD_RESPMEM_PERSISTENT); | 746 | MHD_RESPMEM_PERSISTENT); |
742 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | 747 | ret = MHD_queue_response (connection, |
748 | MHD_HTTP_OK, | ||
749 | response); | ||
743 | MHD_destroy_response (response); | 750 | MHD_destroy_response (response); |
744 | if (ret == MHD_NO) | 751 | if (ret == MHD_NO) |
745 | { | 752 | { |
@@ -751,7 +758,10 @@ ahc_empty (void *cls, | |||
751 | 758 | ||
752 | 759 | ||
753 | static int | 760 | static int |
754 | curlExcessFound (CURL *c, curl_infotype type, char *data, size_t size, | 761 | curlExcessFound (CURL *c, |
762 | curl_infotype type, | ||
763 | char *data, | ||
764 | size_t size, | ||
755 | void *cls) | 765 | void *cls) |
756 | { | 766 | { |
757 | static const char *excess_found = "Excess found"; | 767 | static const char *excess_found = "Excess found"; |
diff --git a/src/testcurl/test_get_empty.c b/src/testcurl/test_get_empty.c new file mode 100644 index 00000000..0fffb37d --- /dev/null +++ b/src/testcurl/test_get_empty.c | |||
@@ -0,0 +1,941 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2007, 2009, 2011, 2019 Christian Grothoff | ||
4 | |||
5 | libmicrohttpd is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | libmicrohttpd is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with libmicrohttpd; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file test_get_empty.c | ||
22 | * @brief Testcase for libmicrohttpd GET operations returning an empty body | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "MHD_config.h" | ||
26 | #include "platform.h" | ||
27 | #include <curl/curl.h> | ||
28 | #include <microhttpd.h> | ||
29 | #include <stdlib.h> | ||
30 | #include <string.h> | ||
31 | #include <time.h> | ||
32 | #include "test_helpers.h" | ||
33 | #include "mhd_sockets.h" /* only macros used */ | ||
34 | |||
35 | |||
36 | #define EXPECTED_URI_PATH "/hello_world?a=%26&b=c" | ||
37 | |||
38 | #ifdef _WIN32 | ||
39 | #ifndef WIN32_LEAN_AND_MEAN | ||
40 | #define WIN32_LEAN_AND_MEAN 1 | ||
41 | #endif /* !WIN32_LEAN_AND_MEAN */ | ||
42 | #include <windows.h> | ||
43 | #endif | ||
44 | |||
45 | #ifndef WINDOWS | ||
46 | #include <unistd.h> | ||
47 | #include <sys/socket.h> | ||
48 | #endif | ||
49 | |||
50 | #if defined(CPU_COUNT) && (CPU_COUNT + 0) < 2 | ||
51 | #undef CPU_COUNT | ||
52 | #endif | ||
53 | #if ! defined(CPU_COUNT) | ||
54 | #define CPU_COUNT 2 | ||
55 | #endif | ||
56 | |||
57 | static int oneone; | ||
58 | static int global_port; | ||
59 | |||
60 | struct CBC | ||
61 | { | ||
62 | char *buf; | ||
63 | size_t pos; | ||
64 | size_t size; | ||
65 | }; | ||
66 | |||
67 | |||
68 | static size_t | ||
69 | copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx) | ||
70 | { | ||
71 | struct CBC *cbc = ctx; | ||
72 | |||
73 | if (cbc->pos + size * nmemb > cbc->size) | ||
74 | return 0; /* overflow */ | ||
75 | memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb); | ||
76 | cbc->pos += size * nmemb; | ||
77 | return size * nmemb; | ||
78 | } | ||
79 | |||
80 | |||
81 | static void * | ||
82 | log_cb (void *cls, | ||
83 | const char *uri, | ||
84 | struct MHD_Connection *con) | ||
85 | { | ||
86 | (void) cls; | ||
87 | (void) con; | ||
88 | if (0 != strcmp (uri, | ||
89 | EXPECTED_URI_PATH)) | ||
90 | { | ||
91 | fprintf (stderr, | ||
92 | "Wrong URI: `%s'\n", | ||
93 | uri); | ||
94 | _exit (22); | ||
95 | } | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | |||
100 | static int | ||
101 | ahc_echo (void *cls, | ||
102 | struct MHD_Connection *connection, | ||
103 | const char *url, | ||
104 | const char *method, | ||
105 | const char *version, | ||
106 | const char *upload_data, size_t *upload_data_size, | ||
107 | void **unused) | ||
108 | { | ||
109 | static int ptr; | ||
110 | const char *me = cls; | ||
111 | struct MHD_Response *response; | ||
112 | int ret; | ||
113 | (void) version; | ||
114 | (void) upload_data; | ||
115 | (void) upload_data_size; /* Unused. Silence compiler warning. */ | ||
116 | |||
117 | if (0 != strcasecmp (me, method)) | ||
118 | return MHD_NO; /* unexpected method */ | ||
119 | if (&ptr != *unused) | ||
120 | { | ||
121 | *unused = &ptr; | ||
122 | return MHD_YES; | ||
123 | } | ||
124 | *unused = NULL; | ||
125 | response = MHD_create_response_from_buffer (0, | ||
126 | NULL, | ||
127 | MHD_RESPMEM_PERSISTENT); | ||
128 | ret = MHD_queue_response (connection, | ||
129 | MHD_HTTP_NO_CONTENT, | ||
130 | response); | ||
131 | MHD_destroy_response (response); | ||
132 | if (ret == MHD_NO) | ||
133 | { | ||
134 | fprintf (stderr, "Failed to queue response.\n"); | ||
135 | _exit (19); | ||
136 | } | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | |||
141 | static int | ||
142 | testInternalGet (int poll_flag) | ||
143 | { | ||
144 | struct MHD_Daemon *d; | ||
145 | CURL *c; | ||
146 | char buf[2048]; | ||
147 | struct CBC cbc; | ||
148 | CURLcode errornum; | ||
149 | |||
150 | if ( (0 == global_port) && | ||
151 | (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) | ||
152 | { | ||
153 | global_port = 1220; | ||
154 | if (oneone) | ||
155 | global_port += 20; | ||
156 | } | ||
157 | |||
158 | cbc.buf = buf; | ||
159 | cbc.size = 2048; | ||
160 | cbc.pos = 0; | ||
161 | d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
162 | | poll_flag, | ||
163 | global_port, NULL, NULL, | ||
164 | &ahc_echo, "GET", | ||
165 | MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, | ||
166 | MHD_OPTION_END); | ||
167 | if (d == NULL) | ||
168 | return 1; | ||
169 | if (0 == global_port) | ||
170 | { | ||
171 | const union MHD_DaemonInfo *dinfo; | ||
172 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
173 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
174 | { | ||
175 | MHD_stop_daemon (d); return 32; | ||
176 | } | ||
177 | global_port = (int) dinfo->port; | ||
178 | } | ||
179 | c = curl_easy_init (); | ||
180 | curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1" EXPECTED_URI_PATH); | ||
181 | curl_easy_setopt (c, CURLOPT_PORT, (long) global_port); | ||
182 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
183 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
184 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
185 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
186 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
187 | if (oneone) | ||
188 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
189 | else | ||
190 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
191 | /* NOTE: use of CONNECTTIMEOUT without also | ||
192 | setting NOSIGNAL results in really weird | ||
193 | crashes on my system!*/ | ||
194 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
195 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
196 | { | ||
197 | fprintf (stderr, | ||
198 | "curl_easy_perform failed: `%s'\n", | ||
199 | curl_easy_strerror (errornum)); | ||
200 | curl_easy_cleanup (c); | ||
201 | MHD_stop_daemon (d); | ||
202 | return 2; | ||
203 | } | ||
204 | curl_easy_cleanup (c); | ||
205 | MHD_stop_daemon (d); | ||
206 | if (cbc.pos != 0) | ||
207 | return 4; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | |||
212 | static int | ||
213 | testMultithreadedGet (int poll_flag) | ||
214 | { | ||
215 | struct MHD_Daemon *d; | ||
216 | CURL *c; | ||
217 | char buf[2048]; | ||
218 | struct CBC cbc; | ||
219 | CURLcode errornum; | ||
220 | |||
221 | if ( (0 == global_port) && | ||
222 | (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) | ||
223 | { | ||
224 | global_port = 1221; | ||
225 | if (oneone) | ||
226 | global_port += 20; | ||
227 | } | ||
228 | |||
229 | cbc.buf = buf; | ||
230 | cbc.size = 2048; | ||
231 | cbc.pos = 0; | ||
232 | d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | ||
233 | | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
234 | | poll_flag, | ||
235 | global_port, NULL, NULL, | ||
236 | &ahc_echo, "GET", | ||
237 | MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, | ||
238 | MHD_OPTION_END); | ||
239 | if (d == NULL) | ||
240 | return 16; | ||
241 | if (0 == global_port) | ||
242 | { | ||
243 | const union MHD_DaemonInfo *dinfo; | ||
244 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
245 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
246 | { | ||
247 | MHD_stop_daemon (d); return 32; | ||
248 | } | ||
249 | global_port = (int) dinfo->port; | ||
250 | } | ||
251 | c = curl_easy_init (); | ||
252 | curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1" EXPECTED_URI_PATH); | ||
253 | curl_easy_setopt (c, CURLOPT_PORT, (long) global_port); | ||
254 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
255 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
256 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
257 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
258 | if (oneone) | ||
259 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
260 | else | ||
261 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
262 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
263 | /* NOTE: use of CONNECTTIMEOUT without also | ||
264 | setting NOSIGNAL results in really weird | ||
265 | crashes on my system! */ | ||
266 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
267 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
268 | { | ||
269 | fprintf (stderr, | ||
270 | "curl_easy_perform failed: `%s'\n", | ||
271 | curl_easy_strerror (errornum)); | ||
272 | curl_easy_cleanup (c); | ||
273 | MHD_stop_daemon (d); | ||
274 | return 32; | ||
275 | } | ||
276 | curl_easy_cleanup (c); | ||
277 | MHD_stop_daemon (d); | ||
278 | if (cbc.pos != 0) | ||
279 | return 64; | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | |||
284 | static int | ||
285 | testMultithreadedPoolGet (int poll_flag) | ||
286 | { | ||
287 | struct MHD_Daemon *d; | ||
288 | CURL *c; | ||
289 | char buf[2048]; | ||
290 | struct CBC cbc; | ||
291 | CURLcode errornum; | ||
292 | |||
293 | if ( (0 == global_port) && | ||
294 | (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) | ||
295 | { | ||
296 | global_port = 1222; | ||
297 | if (oneone) | ||
298 | global_port += 20; | ||
299 | } | ||
300 | |||
301 | cbc.buf = buf; | ||
302 | cbc.size = 2048; | ||
303 | cbc.pos = 0; | ||
304 | d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
305 | | poll_flag, | ||
306 | global_port, NULL, NULL, | ||
307 | &ahc_echo, "GET", | ||
308 | MHD_OPTION_THREAD_POOL_SIZE, CPU_COUNT, | ||
309 | MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, | ||
310 | MHD_OPTION_END); | ||
311 | if (d == NULL) | ||
312 | return 16; | ||
313 | if (0 == global_port) | ||
314 | { | ||
315 | const union MHD_DaemonInfo *dinfo; | ||
316 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
317 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
318 | { | ||
319 | MHD_stop_daemon (d); return 32; | ||
320 | } | ||
321 | global_port = (int) dinfo->port; | ||
322 | } | ||
323 | c = curl_easy_init (); | ||
324 | curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1" EXPECTED_URI_PATH); | ||
325 | curl_easy_setopt (c, CURLOPT_PORT, (long) global_port); | ||
326 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
327 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
328 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
329 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
330 | if (oneone) | ||
331 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
332 | else | ||
333 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
334 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
335 | /* NOTE: use of CONNECTTIMEOUT without also | ||
336 | setting NOSIGNAL results in really weird | ||
337 | crashes on my system!*/ | ||
338 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
339 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
340 | { | ||
341 | fprintf (stderr, | ||
342 | "curl_easy_perform failed: `%s'\n", | ||
343 | curl_easy_strerror (errornum)); | ||
344 | curl_easy_cleanup (c); | ||
345 | MHD_stop_daemon (d); | ||
346 | return 32; | ||
347 | } | ||
348 | curl_easy_cleanup (c); | ||
349 | MHD_stop_daemon (d); | ||
350 | if (cbc.pos != 0) | ||
351 | return 64; | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | |||
356 | static int | ||
357 | testExternalGet () | ||
358 | { | ||
359 | struct MHD_Daemon *d; | ||
360 | CURL *c; | ||
361 | char buf[2048]; | ||
362 | struct CBC cbc; | ||
363 | CURLM *multi; | ||
364 | CURLMcode mret; | ||
365 | fd_set rs; | ||
366 | fd_set ws; | ||
367 | fd_set es; | ||
368 | MHD_socket maxsock; | ||
369 | int maxposixs; | ||
370 | int running; | ||
371 | struct CURLMsg *msg; | ||
372 | time_t start; | ||
373 | struct timeval tv; | ||
374 | |||
375 | if ( (0 == global_port) && | ||
376 | (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) | ||
377 | { | ||
378 | global_port = 1223; | ||
379 | if (oneone) | ||
380 | global_port += 20; | ||
381 | } | ||
382 | |||
383 | multi = NULL; | ||
384 | cbc.buf = buf; | ||
385 | cbc.size = 2048; | ||
386 | cbc.pos = 0; | ||
387 | d = MHD_start_daemon (MHD_USE_ERROR_LOG, | ||
388 | global_port, NULL, NULL, | ||
389 | &ahc_echo, "GET", | ||
390 | MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, | ||
391 | MHD_OPTION_END); | ||
392 | if (d == NULL) | ||
393 | return 256; | ||
394 | if (0 == global_port) | ||
395 | { | ||
396 | const union MHD_DaemonInfo *dinfo; | ||
397 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
398 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
399 | { | ||
400 | MHD_stop_daemon (d); return 32; | ||
401 | } | ||
402 | global_port = (int) dinfo->port; | ||
403 | } | ||
404 | c = curl_easy_init (); | ||
405 | curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1" EXPECTED_URI_PATH); | ||
406 | curl_easy_setopt (c, CURLOPT_PORT, (long) global_port); | ||
407 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
408 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
409 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
410 | if (oneone) | ||
411 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
412 | else | ||
413 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
414 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
415 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
416 | /* NOTE: use of CONNECTTIMEOUT without also | ||
417 | setting NOSIGNAL results in really weird | ||
418 | crashes on my system! */ | ||
419 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
420 | |||
421 | |||
422 | multi = curl_multi_init (); | ||
423 | if (multi == NULL) | ||
424 | { | ||
425 | curl_easy_cleanup (c); | ||
426 | MHD_stop_daemon (d); | ||
427 | return 512; | ||
428 | } | ||
429 | mret = curl_multi_add_handle (multi, c); | ||
430 | if (mret != CURLM_OK) | ||
431 | { | ||
432 | curl_multi_cleanup (multi); | ||
433 | curl_easy_cleanup (c); | ||
434 | MHD_stop_daemon (d); | ||
435 | return 1024; | ||
436 | } | ||
437 | start = time (NULL); | ||
438 | while ((time (NULL) - start < 5) && (multi != NULL)) | ||
439 | { | ||
440 | maxsock = MHD_INVALID_SOCKET; | ||
441 | maxposixs = -1; | ||
442 | FD_ZERO (&rs); | ||
443 | FD_ZERO (&ws); | ||
444 | FD_ZERO (&es); | ||
445 | curl_multi_perform (multi, &running); | ||
446 | mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs); | ||
447 | if (mret != CURLM_OK) | ||
448 | { | ||
449 | curl_multi_remove_handle (multi, c); | ||
450 | curl_multi_cleanup (multi); | ||
451 | curl_easy_cleanup (c); | ||
452 | MHD_stop_daemon (d); | ||
453 | return 2048; | ||
454 | } | ||
455 | if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &maxsock)) | ||
456 | { | ||
457 | curl_multi_remove_handle (multi, c); | ||
458 | curl_multi_cleanup (multi); | ||
459 | curl_easy_cleanup (c); | ||
460 | MHD_stop_daemon (d); | ||
461 | return 4096; | ||
462 | } | ||
463 | tv.tv_sec = 0; | ||
464 | tv.tv_usec = 1000; | ||
465 | #ifdef MHD_POSIX_SOCKETS | ||
466 | if (maxsock > maxposixs) | ||
467 | maxposixs = maxsock; | ||
468 | #endif /* MHD_POSIX_SOCKETS */ | ||
469 | if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv)) | ||
470 | { | ||
471 | #ifdef MHD_POSIX_SOCKETS | ||
472 | if (EINTR != errno) | ||
473 | abort (); | ||
474 | #else | ||
475 | if ((WSAEINVAL != WSAGetLastError ()) ||(0 != rs.fd_count) ||(0 != | ||
476 | ws.fd_count) | ||
477 | ||(0 != es.fd_count) ) | ||
478 | _exit (99); | ||
479 | Sleep (1000); | ||
480 | #endif | ||
481 | } | ||
482 | curl_multi_perform (multi, &running); | ||
483 | if (running == 0) | ||
484 | { | ||
485 | msg = curl_multi_info_read (multi, &running); | ||
486 | if (msg == NULL) | ||
487 | break; | ||
488 | if (msg->msg == CURLMSG_DONE) | ||
489 | { | ||
490 | if (msg->data.result != CURLE_OK) | ||
491 | printf ("%s failed at %s:%d: `%s'\n", | ||
492 | "curl_multi_perform", | ||
493 | __FILE__, | ||
494 | __LINE__, curl_easy_strerror (msg->data.result)); | ||
495 | curl_multi_remove_handle (multi, c); | ||
496 | curl_multi_cleanup (multi); | ||
497 | curl_easy_cleanup (c); | ||
498 | c = NULL; | ||
499 | multi = NULL; | ||
500 | } | ||
501 | } | ||
502 | MHD_run (d); | ||
503 | } | ||
504 | if (multi != NULL) | ||
505 | { | ||
506 | curl_multi_remove_handle (multi, c); | ||
507 | curl_easy_cleanup (c); | ||
508 | curl_multi_cleanup (multi); | ||
509 | } | ||
510 | MHD_stop_daemon (d); | ||
511 | if (cbc.pos != 0) | ||
512 | return 8192; | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | |||
517 | static int | ||
518 | testUnknownPortGet (int poll_flag) | ||
519 | { | ||
520 | struct MHD_Daemon *d; | ||
521 | const union MHD_DaemonInfo *di; | ||
522 | CURL *c; | ||
523 | char buf[2048]; | ||
524 | struct CBC cbc; | ||
525 | CURLcode errornum; | ||
526 | int port; | ||
527 | |||
528 | struct sockaddr_in addr; | ||
529 | socklen_t addr_len = sizeof(addr); | ||
530 | memset (&addr, 0, sizeof(addr)); | ||
531 | addr.sin_family = AF_INET; | ||
532 | addr.sin_port = 0; | ||
533 | addr.sin_addr.s_addr = INADDR_ANY; | ||
534 | |||
535 | cbc.buf = buf; | ||
536 | cbc.size = 2048; | ||
537 | cbc.pos = 0; | ||
538 | d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
539 | | poll_flag, | ||
540 | 0, NULL, NULL, &ahc_echo, "GET", | ||
541 | MHD_OPTION_SOCK_ADDR, &addr, | ||
542 | MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, | ||
543 | MHD_OPTION_END); | ||
544 | if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) | ||
545 | { | ||
546 | di = MHD_get_daemon_info (d, MHD_DAEMON_INFO_LISTEN_FD); | ||
547 | if (di == NULL) | ||
548 | return 65536; | ||
549 | |||
550 | if (0 != getsockname (di->listen_fd, (struct sockaddr *) &addr, &addr_len)) | ||
551 | return 131072; | ||
552 | |||
553 | if (addr.sin_family != AF_INET) | ||
554 | return 26214; | ||
555 | port = (int) ntohs (addr.sin_port); | ||
556 | } | ||
557 | else | ||
558 | { | ||
559 | const union MHD_DaemonInfo *dinfo; | ||
560 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
561 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
562 | { | ||
563 | MHD_stop_daemon (d); return 32; | ||
564 | } | ||
565 | port = (int) dinfo->port; | ||
566 | } | ||
567 | |||
568 | snprintf (buf, | ||
569 | sizeof(buf), | ||
570 | "http://127.0.0.1:%d%s", | ||
571 | port, | ||
572 | EXPECTED_URI_PATH); | ||
573 | |||
574 | c = curl_easy_init (); | ||
575 | curl_easy_setopt (c, CURLOPT_URL, buf); | ||
576 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
577 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
578 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
579 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
580 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
581 | if (oneone) | ||
582 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
583 | else | ||
584 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
585 | /* NOTE: use of CONNECTTIMEOUT without also | ||
586 | setting NOSIGNAL results in really weird | ||
587 | crashes on my system! */ | ||
588 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
589 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
590 | { | ||
591 | fprintf (stderr, | ||
592 | "curl_easy_perform failed: `%s'\n", | ||
593 | curl_easy_strerror (errornum)); | ||
594 | curl_easy_cleanup (c); | ||
595 | MHD_stop_daemon (d); | ||
596 | return 524288; | ||
597 | } | ||
598 | curl_easy_cleanup (c); | ||
599 | MHD_stop_daemon (d); | ||
600 | if (cbc.pos != 0) | ||
601 | return 1048576; | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | |||
606 | static int | ||
607 | testStopRace (int poll_flag) | ||
608 | { | ||
609 | struct sockaddr_in sin; | ||
610 | MHD_socket fd; | ||
611 | struct MHD_Daemon *d; | ||
612 | |||
613 | if ( (0 == global_port) && | ||
614 | (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) | ||
615 | { | ||
616 | global_port = 1224; | ||
617 | if (oneone) | ||
618 | global_port += 20; | ||
619 | } | ||
620 | |||
621 | d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | ||
622 | | MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
623 | | poll_flag, | ||
624 | global_port, NULL, NULL, | ||
625 | &ahc_echo, "GET", | ||
626 | MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, | ||
627 | MHD_OPTION_END); | ||
628 | if (d == NULL) | ||
629 | return 16; | ||
630 | if (0 == global_port) | ||
631 | { | ||
632 | const union MHD_DaemonInfo *dinfo; | ||
633 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
634 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
635 | { | ||
636 | MHD_stop_daemon (d); return 32; | ||
637 | } | ||
638 | global_port = (int) dinfo->port; | ||
639 | } | ||
640 | |||
641 | fd = socket (PF_INET, SOCK_STREAM, 0); | ||
642 | if (fd == MHD_INVALID_SOCKET) | ||
643 | { | ||
644 | fprintf (stderr, "socket error\n"); | ||
645 | return 256; | ||
646 | } | ||
647 | |||
648 | memset (&sin, 0, sizeof(sin)); | ||
649 | sin.sin_family = AF_INET; | ||
650 | sin.sin_port = htons (global_port); | ||
651 | sin.sin_addr.s_addr = htonl (0x7f000001); | ||
652 | |||
653 | if (connect (fd, (struct sockaddr *) (&sin), sizeof(sin)) < 0) | ||
654 | { | ||
655 | fprintf (stderr, "connect error\n"); | ||
656 | MHD_socket_close_chk_ (fd); | ||
657 | return 512; | ||
658 | } | ||
659 | |||
660 | /* printf("Waiting\n"); */ | ||
661 | /* Let the thread get going. */ | ||
662 | usleep (500000); | ||
663 | |||
664 | /* printf("Stopping daemon\n"); */ | ||
665 | MHD_stop_daemon (d); | ||
666 | |||
667 | MHD_socket_close_chk_ (fd); | ||
668 | |||
669 | /* printf("good\n"); */ | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | |||
674 | static int | ||
675 | ahc_empty (void *cls, | ||
676 | struct MHD_Connection *connection, | ||
677 | const char *url, | ||
678 | const char *method, | ||
679 | const char *version, | ||
680 | const char *upload_data, size_t *upload_data_size, | ||
681 | void **unused) | ||
682 | { | ||
683 | static int ptr; | ||
684 | struct MHD_Response *response; | ||
685 | int ret; | ||
686 | (void) cls; | ||
687 | (void) url; | ||
688 | (void) url; | ||
689 | (void) version; /* Unused. Silence compiler warning. */ | ||
690 | (void) upload_data; | ||
691 | (void) upload_data_size; /* Unused. Silent compiler warning. */ | ||
692 | |||
693 | if (0 != strcasecmp ("GET", method)) | ||
694 | return MHD_NO; /* unexpected method */ | ||
695 | if (&ptr != *unused) | ||
696 | { | ||
697 | *unused = &ptr; | ||
698 | return MHD_YES; | ||
699 | } | ||
700 | *unused = NULL; | ||
701 | response = MHD_create_response_from_buffer (0, | ||
702 | NULL, | ||
703 | MHD_RESPMEM_PERSISTENT); | ||
704 | ret = MHD_queue_response (connection, MHD_HTTP_OK, response); | ||
705 | MHD_destroy_response (response); | ||
706 | if (ret == MHD_NO) | ||
707 | { | ||
708 | fprintf (stderr, "Failed to queue response.\n"); | ||
709 | _exit (20); | ||
710 | } | ||
711 | return ret; | ||
712 | } | ||
713 | |||
714 | |||
715 | static int | ||
716 | curlExcessFound (CURL *c, curl_infotype type, char *data, size_t size, | ||
717 | void *cls) | ||
718 | { | ||
719 | static const char *excess_found = "Excess found"; | ||
720 | const size_t str_size = strlen (excess_found); | ||
721 | (void) c; /* Unused. Silent compiler warning. */ | ||
722 | |||
723 | if ((CURLINFO_TEXT == type) | ||
724 | &&(size >= str_size) | ||
725 | &&(0 == strncmp (excess_found, data, str_size))) | ||
726 | *(int *) cls = 1; | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | |||
731 | static int | ||
732 | testEmptyGet (int poll_flag) | ||
733 | { | ||
734 | struct MHD_Daemon *d; | ||
735 | CURL *c; | ||
736 | char buf[2048]; | ||
737 | struct CBC cbc; | ||
738 | CURLcode errornum; | ||
739 | int excess_found = 0; | ||
740 | |||
741 | if ( (0 == global_port) && | ||
742 | (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT)) ) | ||
743 | { | ||
744 | global_port = 1225; | ||
745 | if (oneone) | ||
746 | global_port += 20; | ||
747 | } | ||
748 | |||
749 | cbc.buf = buf; | ||
750 | cbc.size = 2048; | ||
751 | cbc.pos = 0; | ||
752 | d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG | ||
753 | | poll_flag, | ||
754 | global_port, NULL, NULL, | ||
755 | &ahc_empty, NULL, | ||
756 | MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL, | ||
757 | MHD_OPTION_END); | ||
758 | if (d == NULL) | ||
759 | return 4194304; | ||
760 | if (0 == global_port) | ||
761 | { | ||
762 | const union MHD_DaemonInfo *dinfo; | ||
763 | dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT); | ||
764 | if ((NULL == dinfo) ||(0 == dinfo->port) ) | ||
765 | { | ||
766 | MHD_stop_daemon (d); return 32; | ||
767 | } | ||
768 | global_port = (int) dinfo->port; | ||
769 | } | ||
770 | c = curl_easy_init (); | ||
771 | curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1" EXPECTED_URI_PATH); | ||
772 | curl_easy_setopt (c, CURLOPT_PORT, (long) global_port); | ||
773 | curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, ©Buffer); | ||
774 | curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc); | ||
775 | curl_easy_setopt (c, CURLOPT_DEBUGFUNCTION, &curlExcessFound); | ||
776 | curl_easy_setopt (c, CURLOPT_DEBUGDATA, &excess_found); | ||
777 | curl_easy_setopt (c, CURLOPT_VERBOSE, 1L); | ||
778 | curl_easy_setopt (c, CURLOPT_FAILONERROR, 1L); | ||
779 | curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L); | ||
780 | curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L); | ||
781 | if (oneone) | ||
782 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); | ||
783 | else | ||
784 | curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | ||
785 | /* NOTE: use of CONNECTTIMEOUT without also | ||
786 | setting NOSIGNAL results in really weird | ||
787 | crashes on my system!*/ | ||
788 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1L); | ||
789 | if (CURLE_OK != (errornum = curl_easy_perform (c))) | ||
790 | { | ||
791 | fprintf (stderr, | ||
792 | "curl_easy_perform failed: `%s'\n", | ||
793 | curl_easy_strerror (errornum)); | ||
794 | curl_easy_cleanup (c); | ||
795 | MHD_stop_daemon (d); | ||
796 | return 8388608; | ||
797 | } | ||
798 | curl_easy_cleanup (c); | ||
799 | MHD_stop_daemon (d); | ||
800 | if (cbc.pos != 0) | ||
801 | return 16777216; | ||
802 | if (excess_found) | ||
803 | return 33554432; | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | |||
808 | int | ||
809 | main (int argc, char *const *argv) | ||
810 | { | ||
811 | unsigned int errorCount = 0; | ||
812 | unsigned int test_result = 0; | ||
813 | int verbose = 0; | ||
814 | |||
815 | if ((NULL == argv)||(0 == argv[0])) | ||
816 | return 99; | ||
817 | oneone = has_in_name (argv[0], "11"); | ||
818 | verbose = has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose"); | ||
819 | if (0 != curl_global_init (CURL_GLOBAL_WIN32)) | ||
820 | return 2; | ||
821 | global_port = 0; | ||
822 | test_result = testExternalGet (); | ||
823 | if (test_result) | ||
824 | fprintf (stderr, "FAILED: testExternalGet () - %u.\n", test_result); | ||
825 | else if (verbose) | ||
826 | printf ("PASSED: testExternalGet ().\n"); | ||
827 | errorCount += test_result; | ||
828 | if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_THREADS)) | ||
829 | { | ||
830 | test_result += testInternalGet (0); | ||
831 | if (test_result) | ||
832 | fprintf (stderr, "FAILED: testInternalGet (0) - %u.\n", test_result); | ||
833 | else if (verbose) | ||
834 | printf ("PASSED: testInternalGet (0).\n"); | ||
835 | errorCount += test_result; | ||
836 | test_result += testMultithreadedGet (0); | ||
837 | if (test_result) | ||
838 | fprintf (stderr, "FAILED: testMultithreadedGet (0) - %u.\n", test_result); | ||
839 | else if (verbose) | ||
840 | printf ("PASSED: testMultithreadedGet (0).\n"); | ||
841 | errorCount += test_result; | ||
842 | test_result += testMultithreadedPoolGet (0); | ||
843 | if (test_result) | ||
844 | fprintf (stderr, "FAILED: testMultithreadedPoolGet (0) - %u.\n", | ||
845 | test_result); | ||
846 | else if (verbose) | ||
847 | printf ("PASSED: testMultithreadedPoolGet (0).\n"); | ||
848 | errorCount += test_result; | ||
849 | test_result += testUnknownPortGet (0); | ||
850 | if (test_result) | ||
851 | fprintf (stderr, "FAILED: testUnknownPortGet (0) - %u.\n", test_result); | ||
852 | else if (verbose) | ||
853 | printf ("PASSED: testUnknownPortGet (0).\n"); | ||
854 | errorCount += test_result; | ||
855 | test_result += testEmptyGet (0); | ||
856 | if (test_result) | ||
857 | fprintf (stderr, "FAILED: testEmptyGet (0) - %u.\n", test_result); | ||
858 | else if (verbose) | ||
859 | printf ("PASSED: testEmptyGet (0).\n"); | ||
860 | errorCount += test_result; | ||
861 | if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_POLL)) | ||
862 | { | ||
863 | test_result += testInternalGet (MHD_USE_POLL); | ||
864 | if (test_result) | ||
865 | fprintf (stderr, "FAILED: testInternalGet (MHD_USE_POLL) - %u.\n", | ||
866 | test_result); | ||
867 | else if (verbose) | ||
868 | printf ("PASSED: testInternalGet (MHD_USE_POLL).\n"); | ||
869 | errorCount += test_result; | ||
870 | test_result += testMultithreadedGet (MHD_USE_POLL); | ||
871 | if (test_result) | ||
872 | fprintf (stderr, "FAILED: testMultithreadedGet (MHD_USE_POLL) - %u.\n", | ||
873 | test_result); | ||
874 | else if (verbose) | ||
875 | printf ("PASSED: testMultithreadedGet (MHD_USE_POLL).\n"); | ||
876 | errorCount += test_result; | ||
877 | test_result += testMultithreadedPoolGet (MHD_USE_POLL); | ||
878 | if (test_result) | ||
879 | fprintf (stderr, | ||
880 | "FAILED: testMultithreadedPoolGet (MHD_USE_POLL) - %u.\n", | ||
881 | test_result); | ||
882 | else if (verbose) | ||
883 | printf ("PASSED: testMultithreadedPoolGet (MHD_USE_POLL).\n"); | ||
884 | errorCount += test_result; | ||
885 | test_result += testUnknownPortGet (MHD_USE_POLL); | ||
886 | if (test_result) | ||
887 | fprintf (stderr, "FAILED: testUnknownPortGet (MHD_USE_POLL) - %u.\n", | ||
888 | test_result); | ||
889 | else if (verbose) | ||
890 | printf ("PASSED: testUnknownPortGet (MHD_USE_POLL).\n"); | ||
891 | errorCount += test_result; | ||
892 | test_result += testEmptyGet (MHD_USE_POLL); | ||
893 | if (test_result) | ||
894 | fprintf (stderr, "FAILED: testEmptyGet (MHD_USE_POLL) - %u.\n", | ||
895 | test_result); | ||
896 | else if (verbose) | ||
897 | printf ("PASSED: testEmptyGet (MHD_USE_POLL).\n"); | ||
898 | errorCount += test_result; | ||
899 | } | ||
900 | if (MHD_YES == MHD_is_feature_supported (MHD_FEATURE_EPOLL)) | ||
901 | { | ||
902 | test_result += testInternalGet (MHD_USE_EPOLL); | ||
903 | if (test_result) | ||
904 | fprintf (stderr, "FAILED: testInternalGet (MHD_USE_EPOLL) - %u.\n", | ||
905 | test_result); | ||
906 | else if (verbose) | ||
907 | printf ("PASSED: testInternalGet (MHD_USE_EPOLL).\n"); | ||
908 | errorCount += test_result; | ||
909 | test_result += testMultithreadedPoolGet (MHD_USE_EPOLL); | ||
910 | if (test_result) | ||
911 | fprintf (stderr, | ||
912 | "FAILED: testMultithreadedPoolGet (MHD_USE_EPOLL) - %u.\n", | ||
913 | test_result); | ||
914 | else if (verbose) | ||
915 | printf ("PASSED: testMultithreadedPoolGet (MHD_USE_EPOLL).\n"); | ||
916 | errorCount += test_result; | ||
917 | test_result += testUnknownPortGet (MHD_USE_EPOLL); | ||
918 | if (test_result) | ||
919 | fprintf (stderr, "FAILED: testUnknownPortGet (MHD_USE_EPOLL) - %u.\n", | ||
920 | test_result); | ||
921 | else if (verbose) | ||
922 | printf ("PASSED: testUnknownPortGet (MHD_USE_EPOLL).\n"); | ||
923 | errorCount += test_result; | ||
924 | test_result += testEmptyGet (MHD_USE_EPOLL); | ||
925 | if (test_result) | ||
926 | fprintf (stderr, "FAILED: testEmptyGet (MHD_USE_EPOLL) - %u.\n", | ||
927 | test_result); | ||
928 | else if (verbose) | ||
929 | printf ("PASSED: testEmptyGet (MHD_USE_EPOLL).\n"); | ||
930 | errorCount += test_result; | ||
931 | } | ||
932 | } | ||
933 | if (0 != errorCount) | ||
934 | fprintf (stderr, | ||
935 | "Error (code: %u)\n", | ||
936 | errorCount); | ||
937 | else if (verbose) | ||
938 | printf ("All tests passed.\n"); | ||
939 | curl_global_cleanup (); | ||
940 | return errorCount != 0; /* 0 == pass */ | ||
941 | } | ||