aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/test_timeout.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/test_timeout.c')
-rw-r--r--src/testcurl/test_timeout.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/testcurl/test_timeout.c b/src/testcurl/test_timeout.c
new file mode 100644
index 00000000..0596a73a
--- /dev/null
+++ b/src/testcurl/test_timeout.c
@@ -0,0 +1,285 @@
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_timeout.c
23 * @brief Testcase for libmicrohttpd PUT operations
24 * @author Matthias Wachs
25 */
26
27#include "MHD_config.h"
28#include "platform.h"
29#include <curl/curl.h>
30#include <microhttpd.h>
31#include <stdlib.h>
32#include <string.h>
33#include <time.h>
34
35#ifndef WINDOWS
36#include <unistd.h>
37#endif
38
39static int oneone;
40
41static int withTimeout = 1;
42static int withoutTimeout = 1;
43
44struct CBC
45{
46 char *buf;
47 size_t pos;
48 size_t size;
49};
50
51
52static void
53termination_cb (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe);
54
55
56static size_t
57putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
58{
59 unsigned int *pos = ptr;
60 unsigned int wrt;
61
62 wrt = size * nmemb;
63 if (wrt > 8 - (*pos))
64 wrt = 8 - (*pos);
65 memcpy (stream, &("Hello123"[*pos]), wrt);
66 (*pos) += wrt;
67 return wrt;
68}
69
70
71static size_t
72putBuffer_fail (void *stream, size_t size, size_t nmemb, void *ptr)
73{
74 return 0;
75}
76
77static size_t
78copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
79{
80 struct CBC *cbc = ctx;
81
82 if (cbc->pos + size * nmemb > cbc->size)
83 return 0; /* overflow */
84 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
85 cbc->pos += size * nmemb;
86 return size * nmemb;
87}
88
89static int
90ahc_echo (void *cls,
91 struct MHD_Connection *connection,
92 const char *url,
93 const char *method,
94 const char *version,
95 const char *upload_data, size_t *upload_data_size,
96 void **unused)
97{
98 int *done = cls;
99 struct MHD_Response *response;
100 int ret;
101
102 if (0 != strcmp ("PUT", method))
103 return MHD_NO; /* unexpected method */
104 if ((*done) == 0)
105 {
106 if (*upload_data_size != 8)
107 return MHD_YES; /* not yet ready */
108 if (0 == memcmp (upload_data, "Hello123", 8))
109 {
110 *upload_data_size = 0;
111 }
112 else
113 {
114 printf ("Invalid upload data `%8s'!\n", upload_data);
115 return MHD_NO;
116 }
117 *done = 1;
118 return MHD_YES;
119 }
120 response = MHD_create_response_from_buffer (strlen (url),
121 (void *) url,
122 MHD_RESPMEM_MUST_COPY);
123 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
124 MHD_destroy_response (response);
125 return ret;
126}
127
128static int
129testWithoutTimeout ()
130{
131 struct MHD_Daemon *d;
132 CURL *c;
133 char buf[2048];
134 struct CBC cbc;
135 unsigned int pos = 0;
136 int done_flag = 0;
137 CURLcode errornum;
138
139 cbc.buf = buf;
140 cbc.size = 2048;
141 cbc.pos = 0;
142 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
143 1080,
144 NULL, NULL, &ahc_echo, &done_flag,
145 MHD_OPTION_CONNECTION_TIMEOUT, 2,
146 MHD_OPTION_NOTIFY_COMPLETED, &termination_cb, &withTimeout,
147 MHD_OPTION_END);
148 if (d == NULL)
149 return 1;
150 c = curl_easy_init ();
151 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1080/hello_world");
152 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
153 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
154 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer);
155 curl_easy_setopt (c, CURLOPT_READDATA, &pos);
156 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
157 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
158 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
159 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
160 if (oneone)
161 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
162 else
163 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
164 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
165 // NOTE: use of CONNECTTIMEOUT without also
166 // setting NOSIGNAL results in really weird
167 // crashes on my system!
168 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
169 if (CURLE_OK != (errornum = curl_easy_perform (c)))
170 {
171 curl_easy_cleanup (c);
172 MHD_stop_daemon (d);
173 return 2;
174 }
175 curl_easy_cleanup (c);
176 MHD_stop_daemon (d);
177 if (cbc.pos != strlen ("/hello_world"))
178 return 4;
179 if (0 != strncmp ("/hello_world", cbc.buf, strlen ("/hello_world")))
180 return 8;
181 return 0;
182}
183
184static int
185testWithTimeout ()
186{
187 struct MHD_Daemon *d;
188 CURL *c;
189 char buf[2048];
190 struct CBC cbc;
191 int done_flag = 0;
192 CURLcode errornum;
193
194 cbc.buf = buf;
195 cbc.size = 2048;
196 cbc.pos = 0;
197 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
198 1080,
199 NULL, NULL, &ahc_echo, &done_flag,
200 MHD_OPTION_CONNECTION_TIMEOUT, 2,
201 MHD_OPTION_NOTIFY_COMPLETED, &termination_cb, &withoutTimeout,
202 MHD_OPTION_END);
203 if (d == NULL)
204 return 16;
205 c = curl_easy_init ();
206 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1080/hello_world");
207 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
208 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
209 curl_easy_setopt (c, CURLOPT_READFUNCTION, &putBuffer_fail);
210 curl_easy_setopt (c, CURLOPT_READDATA, &testWithTimeout);
211 curl_easy_setopt (c, CURLOPT_UPLOAD, 1L);
212 curl_easy_setopt (c, CURLOPT_INFILESIZE_LARGE, (curl_off_t) 8L);
213 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
214 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
215 if (oneone)
216 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
217 else
218 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
219 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
220 // NOTE: use of CONNECTTIMEOUT without also
221 // setting NOSIGNAL results in really weird
222 // crashes on my system!
223 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
224 if (CURLE_OK != (errornum = curl_easy_perform (c)))
225 {
226 curl_easy_cleanup (c);
227 MHD_stop_daemon (d);
228 if (errornum == CURLE_GOT_NOTHING)
229 /* mhd had the timeout */
230 return 0;
231 else
232 /* curl had the timeout first */
233 return 32;
234 }
235 curl_easy_cleanup (c);
236 MHD_stop_daemon (d);
237 return 64;
238}
239
240
241static void
242termination_cb (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe)
243{
244 int * test = cls;
245 switch (toe)
246 {
247 case MHD_REQUEST_TERMINATED_COMPLETED_OK :
248 if (test==&withoutTimeout)
249 {
250 withoutTimeout = 0;
251 }
252 break;
253 case MHD_REQUEST_TERMINATED_WITH_ERROR :
254 case MHD_REQUEST_TERMINATED_READ_ERROR :
255 break;
256 case MHD_REQUEST_TERMINATED_TIMEOUT_REACHED :
257 if (test==&withTimeout)
258 {
259 withTimeout = 0;
260 }
261 break;
262 case MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN :
263 break;
264 }
265}
266
267
268int
269main (int argc, char *const *argv)
270{
271 unsigned int errorCount = 0;
272
273 oneone = NULL != strstr (argv[0], "11");
274 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
275 return 16;
276 errorCount += testWithoutTimeout ();
277 errorCount += testWithTimeout ();
278 if (errorCount != 0)
279 fprintf (stderr, "Error during test execution (code: %u)\n", errorCount);
280 curl_global_cleanup ();
281 if ((withTimeout == 0) && (withoutTimeout == 0))
282 return 0;
283 else
284 return errorCount; /* 0 == pass */
285}