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