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