aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/test_process_headers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/test_process_headers.c')
-rw-r--r--src/testcurl/test_process_headers.c429
1 files changed, 429 insertions, 0 deletions
diff --git a/src/testcurl/test_process_headers.c b/src/testcurl/test_process_headers.c
new file mode 100644
index 00000000..fbe28849
--- /dev/null
+++ b/src/testcurl/test_process_headers.c
@@ -0,0 +1,429 @@
1
2/*
3 This file is part of libmicrohttpd
4 (C) 2007 Christian Grothoff
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 2, 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., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20*/
21
22/**
23 * @file daemontest_process_headers.c
24 * @brief Testcase for HTTP header access
25 * @author Christian Grothoff
26 */
27
28#include "MHD_config.h"
29#include "platform.h"
30#include <curl/curl.h>
31#include <microhttpd.h>
32#include <stdlib.h>
33#include <string.h>
34#include <time.h>
35
36#ifndef WINDOWS
37#include <unistd.h>
38#endif
39
40static int oneone;
41
42struct CBC
43{
44 char *buf;
45 size_t pos;
46 size_t size;
47};
48
49static size_t
50copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
51{
52 struct CBC *cbc = ctx;
53
54 if (cbc->pos + size * nmemb > cbc->size)
55 return 0; /* overflow */
56 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
57 cbc->pos += size * nmemb;
58 return size * nmemb;
59}
60
61static int
62kv_cb (void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
63{
64 if ((0 == strcmp (key, MHD_HTTP_HEADER_HOST)) &&
65 (0 == strcmp (value, "127.0.0.1:21080")) && (kind == MHD_HEADER_KIND))
66 {
67 *((int *) cls) = 1;
68 return MHD_NO;
69 }
70 return MHD_YES;
71}
72
73static int
74ahc_echo (void *cls,
75 struct MHD_Connection *connection,
76 const char *url,
77 const char *method,
78 const char *version,
79 const char *upload_data, size_t *upload_data_size,
80 void **unused)
81{
82 static int ptr;
83 const char *me = cls;
84 struct MHD_Response *response;
85 int ret;
86 const char *hdr;
87
88 if (0 != strcmp (me, method))
89 return MHD_NO; /* unexpected method */
90 if (&ptr != *unused)
91 {
92 *unused = &ptr;
93 return MHD_YES;
94 }
95 *unused = NULL;
96 ret = 0;
97 MHD_get_connection_values (connection, MHD_HEADER_KIND, &kv_cb, &ret);
98 if (ret != 1)
99 abort ();
100 hdr = MHD_lookup_connection_value (connection, MHD_HEADER_KIND, "NotFound");
101 if (hdr != NULL)
102 abort ();
103 hdr = MHD_lookup_connection_value (connection,
104 MHD_HEADER_KIND, MHD_HTTP_HEADER_ACCEPT);
105 if ((hdr == NULL) || (0 != strcmp (hdr, "*/*")))
106 abort ();
107 hdr = MHD_lookup_connection_value (connection,
108 MHD_HEADER_KIND, MHD_HTTP_HEADER_HOST);
109 if ((hdr == NULL) || (0 != strcmp (hdr, "127.0.0.1:21080")))
110 abort ();
111 MHD_set_connection_value (connection,
112 MHD_HEADER_KIND, "FakeHeader", "NowPresent");
113 hdr = MHD_lookup_connection_value (connection,
114 MHD_HEADER_KIND, "FakeHeader");
115 if ((hdr == NULL) || (0 != strcmp (hdr, "NowPresent")))
116 abort ();
117
118 response = MHD_create_response_from_buffer (strlen (url),
119 (void *) url,
120 MHD_RESPMEM_MUST_COPY);
121 MHD_add_response_header (response, "MyHeader", "MyValue");
122 hdr = MHD_get_response_header (response, "MyHeader");
123 if (0 != strcmp ("MyValue", hdr))
124 abort ();
125 MHD_add_response_header (response, "MyHeader", "MyValueToo");
126 if (MHD_YES != MHD_del_response_header (response, "MyHeader", "MyValue"))
127 abort ();
128 hdr = MHD_get_response_header (response, "MyHeader");
129 if (0 != strcmp ("MyValueToo", hdr))
130 abort ();
131 if (1 != MHD_get_response_headers (response, NULL, NULL))
132 abort ();
133 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
134 MHD_destroy_response (response);
135 if (ret == MHD_NO)
136 abort ();
137 return ret;
138}
139
140
141static int
142testInternalGet ()
143{
144 struct MHD_Daemon *d;
145 CURL *c;
146 char buf[2048];
147 struct CBC cbc;
148 CURLcode errornum;
149
150 cbc.buf = buf;
151 cbc.size = 2048;
152 cbc.pos = 0;
153 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
154 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
155 if (d == NULL)
156 return 1;
157 c = curl_easy_init ();
158 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:21080/hello_world");
159 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
160 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
161 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
162 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
163 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
164 if (oneone)
165 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
166 else
167 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
168 /* NOTE: use of CONNECTTIMEOUT without also
169 setting NOSIGNAL results in really weird
170 crashes on my system! */
171 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
172 if (CURLE_OK != (errornum = curl_easy_perform (c)))
173 {
174 fprintf (stderr,
175 "curl_easy_perform failed: `%s'\n",
176 curl_easy_strerror (errornum));
177 curl_easy_cleanup (c);
178 MHD_stop_daemon (d);
179 return 2;
180 }
181 curl_easy_cleanup (c);
182 MHD_stop_daemon (d);
183 if (cbc.pos != strlen ("/hello_world"))
184 return 4;
185 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
186 return 8;
187 return 0;
188}
189
190static int
191testMultithreadedGet ()
192{
193 struct MHD_Daemon *d;
194 CURL *c;
195 char buf[2048];
196 struct CBC cbc;
197 CURLcode errornum;
198
199 cbc.buf = buf;
200 cbc.size = 2048;
201 cbc.pos = 0;
202 d = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
203 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
204 if (d == NULL)
205 return 16;
206 c = curl_easy_init ();
207 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:21080/hello_world");
208 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
209 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
210 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
211 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
212 if (oneone)
213 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
214 else
215 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
216 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
217 /* NOTE: use of CONNECTTIMEOUT without also
218 setting NOSIGNAL results in really weird
219 crashes on my system! */
220 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
221 if (CURLE_OK != (errornum = curl_easy_perform (c)))
222 {
223 fprintf (stderr,
224 "curl_easy_perform failed: `%s'\n",
225 curl_easy_strerror (errornum));
226 curl_easy_cleanup (c);
227 MHD_stop_daemon (d);
228 return 32;
229 }
230 curl_easy_cleanup (c);
231 MHD_stop_daemon (d);
232 if (cbc.pos != strlen ("/hello_world"))
233 return 64;
234 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
235 return 128;
236 return 0;
237}
238
239static int
240testMultithreadedPoolGet ()
241{
242 struct MHD_Daemon *d;
243 CURL *c;
244 char buf[2048];
245 struct CBC cbc;
246 CURLcode errornum;
247
248 cbc.buf = buf;
249 cbc.size = 2048;
250 cbc.pos = 0;
251 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
252 21080, NULL, NULL, &ahc_echo, "GET",
253 MHD_OPTION_THREAD_POOL_SIZE, 4, MHD_OPTION_END);
254 if (d == NULL)
255 return 16;
256 c = curl_easy_init ();
257 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:21080/hello_world");
258 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
259 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
260 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
261 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
262 if (oneone)
263 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
264 else
265 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
266 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
267 /* NOTE: use of CONNECTTIMEOUT without also
268 setting NOSIGNAL results in really weird
269 crashes on my system! */
270 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
271 if (CURLE_OK != (errornum = curl_easy_perform (c)))
272 {
273 fprintf (stderr,
274 "curl_easy_perform failed: `%s'\n",
275 curl_easy_strerror (errornum));
276 curl_easy_cleanup (c);
277 MHD_stop_daemon (d);
278 return 32;
279 }
280 curl_easy_cleanup (c);
281 MHD_stop_daemon (d);
282 if (cbc.pos != strlen ("/hello_world"))
283 return 64;
284 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
285 return 128;
286 return 0;
287}
288
289static int
290testExternalGet ()
291{
292 struct MHD_Daemon *d;
293 CURL *c;
294 char buf[2048];
295 struct CBC cbc;
296 CURLM *multi;
297 CURLMcode mret;
298 fd_set rs;
299 fd_set ws;
300 fd_set es;
301 int max;
302 int running;
303 struct CURLMsg *msg;
304 time_t start;
305 struct timeval tv;
306
307 multi = NULL;
308 cbc.buf = buf;
309 cbc.size = 2048;
310 cbc.pos = 0;
311 d = MHD_start_daemon (MHD_USE_DEBUG,
312 21080, NULL, NULL, &ahc_echo, "GET", MHD_OPTION_END);
313 if (d == NULL)
314 return 256;
315 c = curl_easy_init ();
316 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:21080/hello_world");
317 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
318 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
319 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
320 if (oneone)
321 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
322 else
323 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
324 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
325 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
326 /* NOTE: use of CONNECTTIMEOUT without also
327 setting NOSIGNAL results in really weird
328 crashes on my system! */
329 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
330
331
332 multi = curl_multi_init ();
333 if (multi == NULL)
334 {
335 curl_easy_cleanup (c);
336 MHD_stop_daemon (d);
337 return 512;
338 }
339 mret = curl_multi_add_handle (multi, c);
340 if (mret != CURLM_OK)
341 {
342 curl_multi_cleanup (multi);
343 curl_easy_cleanup (c);
344 MHD_stop_daemon (d);
345 return 1024;
346 }
347 start = time (NULL);
348 while ((time (NULL) - start < 5) && (multi != NULL))
349 {
350 max = 0;
351 FD_ZERO (&rs);
352 FD_ZERO (&ws);
353 FD_ZERO (&es);
354 curl_multi_perform (multi, &running);
355 mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
356 if (mret != CURLM_OK)
357 {
358 curl_multi_remove_handle (multi, c);
359 curl_multi_cleanup (multi);
360 curl_easy_cleanup (c);
361 MHD_stop_daemon (d);
362 return 2048;
363 }
364 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
365 {
366 curl_multi_remove_handle (multi, c);
367 curl_multi_cleanup (multi);
368 curl_easy_cleanup (c);
369 MHD_stop_daemon (d);
370 return 4096;
371 }
372 tv.tv_sec = 0;
373 tv.tv_usec = 1000;
374 select (max + 1, &rs, &ws, &es, &tv);
375 curl_multi_perform (multi, &running);
376 if (running == 0)
377 {
378 msg = curl_multi_info_read (multi, &running);
379 if (msg == NULL)
380 break;
381 if (msg->msg == CURLMSG_DONE)
382 {
383 if (msg->data.result != CURLE_OK)
384 printf ("%s failed at %s:%d: `%s'\n",
385 "curl_multi_perform",
386 __FILE__,
387 __LINE__, curl_easy_strerror (msg->data.result));
388 curl_multi_remove_handle (multi, c);
389 curl_multi_cleanup (multi);
390 curl_easy_cleanup (c);
391 c = NULL;
392 multi = NULL;
393 }
394 }
395 MHD_run (d);
396 }
397 if (multi != NULL)
398 {
399 curl_multi_remove_handle (multi, c);
400 curl_easy_cleanup (c);
401 curl_multi_cleanup (multi);
402 }
403 MHD_stop_daemon (d);
404 if (cbc.pos != strlen ("/hello_world"))
405 return 8192;
406 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
407 return 16384;
408 return 0;
409}
410
411
412
413int
414main (int argc, char *const *argv)
415{
416 unsigned int errorCount = 0;
417
418 oneone = NULL != strstr (argv[0], "11");
419 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
420 return 2;
421 errorCount += testInternalGet ();
422 errorCount += testMultithreadedGet ();
423 errorCount += testMultithreadedPoolGet ();
424 errorCount += testExternalGet ();
425 if (errorCount != 0)
426 fprintf (stderr, "Error (code: %u)\n", errorCount);
427 curl_global_cleanup ();
428 return errorCount != 0; /* 0 == pass */
429}