aboutsummaryrefslogtreecommitdiff
path: root/src/testcurl/test_iplimit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testcurl/test_iplimit.c')
-rw-r--r--src/testcurl/test_iplimit.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/testcurl/test_iplimit.c b/src/testcurl/test_iplimit.c
new file mode 100644
index 00000000..0b2b9b6c
--- /dev/null
+++ b/src/testcurl/test_iplimit.c
@@ -0,0 +1,302 @@
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_get.c
23 * @brief Testcase for libmicrohttpd GET operations
24 * TODO: test parsing of query
25 * @author Christian Grothoff
26 */
27
28#include "MHD_config.h"
29#include "platform.h"
30#include <curl/curl.h>
31#include <microhttpd.h>
32#include <stdlib.h>
33#include <string.h>
34#include <time.h>
35
36#ifndef WINDOWS
37#include <unistd.h>
38#endif
39
40static int oneone;
41
42struct CBC
43{
44 char *buf;
45 size_t pos;
46 size_t size;
47};
48
49static size_t
50copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
51{
52 struct CBC *cbc = ctx;
53
54 if (cbc->pos + size * nmemb > cbc->size)
55 return 0; /* overflow */
56 memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
57 cbc->pos += size * nmemb;
58 return size * nmemb;
59}
60
61static int
62ahc_echo (void *cls,
63 struct MHD_Connection *connection,
64 const char *url,
65 const char *method,
66 const char *version,
67 const char *upload_data, size_t *upload_data_size,
68 void **unused)
69{
70 static int ptr;
71 const char *me = cls;
72 struct MHD_Response *response;
73 int ret;
74
75 if (0 != strcmp (me, method))
76 return MHD_NO; /* unexpected method */
77 if (&ptr != *unused)
78 {
79 *unused = &ptr;
80 return MHD_YES;
81 }
82 *unused = NULL;
83 response = MHD_create_response_from_buffer (strlen (url),
84 (void *) url,
85 MHD_RESPMEM_MUST_COPY);
86 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
87 MHD_destroy_response (response);
88 if (ret == MHD_NO)
89 abort ();
90 return ret;
91}
92
93static int
94testMultithreadedGet ()
95{
96 struct MHD_Daemon *d;
97 char buf[2048];
98 int k;
99
100 /* Test only valid for HTTP/1.1 (uses persistent connections) */
101 if (!oneone)
102 return 0;
103
104 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
105 1081, NULL, NULL, &ahc_echo, "GET",
106 MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
107 MHD_OPTION_END);
108 if (d == NULL)
109 return 16;
110
111 for (k = 0; k < 3; ++k)
112 {
113 struct CBC cbc[3];
114 CURL *cenv[3];
115 int i;
116
117 for (i = 0; i < 3; ++i)
118 {
119 CURL *c;
120 CURLcode errornum;
121
122 cenv[i] = c = curl_easy_init ();
123 cbc[i].buf = buf;
124 cbc[i].size = 2048;
125 cbc[i].pos = 0;
126
127 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
128 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
129 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]);
130 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
131 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
132 curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L);
133 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
134 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
135 // NOTE: use of CONNECTTIMEOUT without also
136 // setting NOSIGNAL results in really weird
137 // crashes on my system!
138 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
139
140 errornum = curl_easy_perform (c);
141 if ( ( (CURLE_OK != errornum) && (i < 2) ) ||
142 ( (CURLE_OK == errornum) && (i == 2) ) )
143 {
144 int j;
145
146 /* First 2 should succeed */
147 if (i < 2)
148 fprintf (stderr,
149 "curl_easy_perform failed: `%s'\n",
150 curl_easy_strerror (errornum));
151
152 /* Last request should have failed */
153 else
154 fprintf (stderr,
155 "No error on IP address over limit\n");
156
157 for (j = 0; j < i; ++j)
158 curl_easy_cleanup (cenv[j]);
159 MHD_stop_daemon (d);
160 return 32;
161 }
162 }
163
164 /* Cleanup the environments */
165 for (i = 0; i < 3; ++i)
166 curl_easy_cleanup (cenv[i]);
167
168 sleep(2);
169
170 for (i = 0; i < 2; ++i)
171 {
172 if (cbc[i].pos != strlen ("/hello_world"))
173 {
174 MHD_stop_daemon (d);
175 return 64;
176 }
177 if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world")))
178 {
179 MHD_stop_daemon (d);
180 return 128;
181 }
182 }
183
184
185 }
186 MHD_stop_daemon (d);
187 return 0;
188}
189
190static int
191testMultithreadedPoolGet ()
192{
193 struct MHD_Daemon *d;
194 char buf[2048];
195 int k;
196
197 /* Test only valid for HTTP/1.1 (uses persistent connections) */
198 if (!oneone)
199 return 0;
200
201 d = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG,
202 1081, NULL, NULL, &ahc_echo, "GET",
203 MHD_OPTION_PER_IP_CONNECTION_LIMIT, 2,
204 MHD_OPTION_THREAD_POOL_SIZE, 4,
205 MHD_OPTION_END);
206 if (d == NULL)
207 return 16;
208
209 for (k = 0; k < 3; ++k)
210 {
211 struct CBC cbc[3];
212 CURL *cenv[3];
213 int i;
214
215 for (i = 0; i < 3; ++i)
216 {
217 CURL *c;
218 CURLcode errornum;
219
220 cenv[i] = c = curl_easy_init ();
221 cbc[i].buf = buf;
222 cbc[i].size = 2048;
223 cbc[i].pos = 0;
224
225 curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1:1081/hello_world");
226 curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
227 curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc[i]);
228 curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
229 curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
230 curl_easy_setopt (c, CURLOPT_FORBID_REUSE, 0L);
231 curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
232 curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
233 // NOTE: use of CONNECTTIMEOUT without also
234 // setting NOSIGNAL results in really weird
235 // crashes on my system!
236 curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
237
238 errornum = curl_easy_perform (c);
239 if ( ( (CURLE_OK != errornum) && (i < 2) ) ||
240 ( (CURLE_OK == errornum) && (i == 2) ) )
241 {
242 int j;
243
244 /* First 2 should succeed */
245 if (i < 2)
246 fprintf (stderr,
247 "curl_easy_perform failed: `%s'\n",
248 curl_easy_strerror (errornum));
249
250 /* Last request should have failed */
251 else
252 fprintf (stderr,
253 "No error on IP address over limit\n");
254
255 for (j = 0; j < i; ++j)
256 curl_easy_cleanup (cenv[j]);
257 MHD_stop_daemon (d);
258 return 32;
259 }
260 }
261
262 /* Cleanup the environments */
263 for (i = 0; i < 3; ++i)
264 curl_easy_cleanup (cenv[i]);
265
266 sleep(2);
267
268 for (i = 0; i < 2; ++i)
269 {
270 if (cbc[i].pos != strlen ("/hello_world"))
271 {
272 MHD_stop_daemon (d);
273 return 64;
274 }
275 if (0 != strncmp ("/hello_world", cbc[i].buf, strlen ("/hello_world")))
276 {
277 MHD_stop_daemon (d);
278 return 128;
279 }
280 }
281
282
283 }
284 MHD_stop_daemon (d);
285 return 0;
286}
287
288int
289main (int argc, char *const *argv)
290{
291 unsigned int errorCount = 0;
292
293 oneone = NULL != strstr (argv[0], "11");
294 if (0 != curl_global_init (CURL_GLOBAL_WIN32))
295 return 2;
296 errorCount += testMultithreadedGet ();
297 errorCount += testMultithreadedPoolGet ();
298 if (errorCount != 0)
299 fprintf (stderr, "Error (code: %u)\n", errorCount);
300 curl_global_cleanup ();
301 return errorCount != 0; /* 0 == pass */
302}