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