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