diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2011-10-13 08:06:28 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2011-10-13 08:06:28 +0000 |
commit | f9d82cbcd81da81a3e78bada99f54ccc7c9ac50b (patch) | |
tree | 24635e8bad579f156f4c8f2153c2d213a20f1850 | |
parent | 1a7597ebe84660f31cb5f5b22904641940ca86ab (diff) | |
download | gnunet-f9d82cbcd81da81a3e78bada99f54ccc7c9ac50b.tar.gz gnunet-f9d82cbcd81da81a3e78bada99f54ccc7c9ac50b.zip |
-rw-r--r-- | src/transport/plugin_transport_http.c | 41 | ||||
-rw-r--r-- | src/transport/plugin_transport_http.h | 33 | ||||
-rw-r--r-- | src/transport/plugin_transport_http_server.c | 32 | ||||
-rw-r--r-- | src/transport/test_plugin_transport_http.c | 1434 | ||||
-rw-r--r-- | src/transport/test_plugin_transport_https.c | 1519 |
5 files changed, 70 insertions, 2989 deletions
diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c index 11ce54331..3f7ff2a40 100644 --- a/src/transport/plugin_transport_http.c +++ b/src/transport/plugin_transport_http.c | |||
@@ -34,38 +34,6 @@ | |||
34 | #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6) | 34 | #define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6) |
35 | 35 | ||
36 | /** | 36 | /** |
37 | * IPv4 addresses | ||
38 | */ | ||
39 | struct IPv4HttpAddress | ||
40 | { | ||
41 | /** | ||
42 | * IPv4 address, in network byte order. | ||
43 | */ | ||
44 | uint32_t ipv4_addr GNUNET_PACKED; | ||
45 | |||
46 | /** | ||
47 | * Port number, in network byte order. | ||
48 | */ | ||
49 | uint16_t u4_port GNUNET_PACKED; | ||
50 | }; | ||
51 | |||
52 | /** | ||
53 | * IPv4 addresses | ||
54 | */ | ||
55 | struct IPv6HttpAddress | ||
56 | { | ||
57 | /** | ||
58 | * IPv6 address. | ||
59 | */ | ||
60 | struct in6_addr ipv6_addr GNUNET_PACKED; | ||
61 | |||
62 | /** | ||
63 | * Port number, in network byte order. | ||
64 | */ | ||
65 | uint16_t u6_port GNUNET_PACKED; | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * Wrapper to manage IPv4 addresses | 37 | * Wrapper to manage IPv4 addresses |
70 | */ | 38 | */ |
71 | struct IPv4HttpAddressWrapper | 39 | struct IPv4HttpAddressWrapper |
@@ -189,7 +157,6 @@ http_plugin_address_pretty_printer (void *cls, const char *type, | |||
189 | size_t sbs; | 157 | size_t sbs; |
190 | uint16_t port = 0 ; | 158 | uint16_t port = 0 ; |
191 | 159 | ||
192 | // BUG! Transport addrs over the network must NOT be 'struct sockaddr*'s! | ||
193 | if (addrlen == sizeof (struct IPv6HttpAddress)) | 160 | if (addrlen == sizeof (struct IPv6HttpAddress)) |
194 | { | 161 | { |
195 | struct IPv6HttpAddress * a6 = (struct IPv6HttpAddress *) addr; | 162 | struct IPv6HttpAddress * a6 = (struct IPv6HttpAddress *) addr; |
@@ -341,6 +308,7 @@ http_plugin_address_to_string (void *cls, const void *addr, size_t addrlen) | |||
341 | else | 308 | else |
342 | { | 309 | { |
343 | /* invalid address */ | 310 | /* invalid address */ |
311 | GNUNET_break (0); | ||
344 | return NULL; | 312 | return NULL; |
345 | } | 313 | } |
346 | #if !BUILD_HTTPS | 314 | #if !BUILD_HTTPS |
@@ -450,7 +418,7 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target, | |||
450 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) | 418 | GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls) |
451 | { | 419 | { |
452 | struct Session *s = NULL; | 420 | struct Session *s = NULL; |
453 | 421 | GNUNET_assert ((addrlen == sizeof (struct IPv6HttpAddress)) || (addrlen == sizeof (struct IPv4HttpAddress))); | |
454 | s = GNUNET_malloc (sizeof (struct Session)); | 422 | s = GNUNET_malloc (sizeof (struct Session)); |
455 | memcpy (&s->target, target, sizeof (struct GNUNET_PeerIdentity)); | 423 | memcpy (&s->target, target, sizeof (struct GNUNET_PeerIdentity)); |
456 | s->plugin = plugin; | 424 | s->plugin = plugin; |
@@ -532,6 +500,11 @@ http_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target, | |||
532 | 500 | ||
533 | struct Session *s = NULL; | 501 | struct Session *s = NULL; |
534 | 502 | ||
503 | |||
504 | if (addrlen != 0) | ||
505 | GNUNET_assert ((addrlen == sizeof (struct IPv4HttpAddress)) || | ||
506 | (addrlen == sizeof (struct IPv6HttpAddress))); | ||
507 | |||
535 | /* look for existing connection */ | 508 | /* look for existing connection */ |
536 | s = lookup_session (plugin, target, session, addr, addrlen, 1); | 509 | s = lookup_session (plugin, target, session, addr, addrlen, 1); |
537 | #if DEBUG_HTTP | 510 | #if DEBUG_HTTP |
diff --git a/src/transport/plugin_transport_http.h b/src/transport/plugin_transport_http.h index 16da05c32..dd0bc4b9d 100644 --- a/src/transport/plugin_transport_http.h +++ b/src/transport/plugin_transport_http.h | |||
@@ -261,6 +261,39 @@ struct Plugin | |||
261 | }; | 261 | }; |
262 | 262 | ||
263 | /** | 263 | /** |
264 | * IPv4 addresses | ||
265 | */ | ||
266 | struct IPv4HttpAddress | ||
267 | { | ||
268 | /** | ||
269 | * IPv4 address, in network byte order. | ||
270 | */ | ||
271 | uint32_t ipv4_addr GNUNET_PACKED; | ||
272 | |||
273 | /** | ||
274 | * Port number, in network byte order. | ||
275 | */ | ||
276 | uint16_t u4_port GNUNET_PACKED; | ||
277 | }; | ||
278 | |||
279 | /** | ||
280 | * IPv4 addresses | ||
281 | */ | ||
282 | struct IPv6HttpAddress | ||
283 | { | ||
284 | /** | ||
285 | * IPv6 address. | ||
286 | */ | ||
287 | struct in6_addr ipv6_addr GNUNET_PACKED; | ||
288 | |||
289 | /** | ||
290 | * Port number, in network byte order. | ||
291 | */ | ||
292 | uint16_t u6_port GNUNET_PACKED; | ||
293 | }; | ||
294 | |||
295 | |||
296 | /** | ||
264 | * Session handle for connections. | 297 | * Session handle for connections. |
265 | */ | 298 | */ |
266 | struct Session | 299 | struct Session |
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c index 68686169e..0eb88fc01 100644 --- a/src/transport/plugin_transport_http_server.c +++ b/src/transport/plugin_transport_http_server.c | |||
@@ -352,6 +352,12 @@ server_lookup_session (struct Plugin *plugin, | |||
352 | struct ServerConnection *sc = NULL; | 352 | struct ServerConnection *sc = NULL; |
353 | const union MHD_ConnectionInfo *conn_info; | 353 | const union MHD_ConnectionInfo *conn_info; |
354 | 354 | ||
355 | struct IPv4HttpAddress a4; | ||
356 | struct IPv6HttpAddress a6; | ||
357 | struct sockaddr_in * s4; | ||
358 | struct sockaddr_in6 * s6; | ||
359 | void * a; | ||
360 | size_t a_len; | ||
355 | struct GNUNET_PeerIdentity target; | 361 | struct GNUNET_PeerIdentity target; |
356 | size_t addrlen; | 362 | size_t addrlen; |
357 | int check = GNUNET_NO; | 363 | int check = GNUNET_NO; |
@@ -485,10 +491,32 @@ create: | |||
485 | "Server: Creating new session for peer `%s' \n", GNUNET_i2s (&target)); | 491 | "Server: Creating new session for peer `%s' \n", GNUNET_i2s (&target)); |
486 | #endif | 492 | #endif |
487 | 493 | ||
494 | switch (conn_info->client_addr->sa_family) | ||
495 | { | ||
496 | case (AF_INET): | ||
497 | s4 = ((struct sockaddr_in * ) conn_info->client_addr); | ||
498 | a4.u4_port = s4->sin_port; | ||
499 | memcpy (&a4.ipv4_addr, &s4->sin_addr, | ||
500 | sizeof (struct in_addr)); | ||
501 | a = &a4; | ||
502 | a_len = sizeof (struct IPv4HttpAddress); | ||
503 | break; | ||
504 | case (AF_INET6): | ||
505 | s6 = ((struct sockaddr_in6 * ) conn_info->client_addr); | ||
506 | a6.u6_port = s6->sin6_port; | ||
507 | memcpy (&a6.ipv6_addr, &s6->sin6_addr, | ||
508 | sizeof (struct in6_addr)); | ||
509 | a = &a6; | ||
510 | a_len = sizeof (struct IPv6HttpAddress); | ||
511 | break; | ||
512 | default: | ||
513 | GNUNET_break (0); | ||
514 | } | ||
515 | |||
488 | s = create_session (plugin, | 516 | s = create_session (plugin, |
489 | &target, | 517 | &target, |
490 | conn_info->client_addr, | 518 | a, |
491 | addrlen, | 519 | a_len, |
492 | NULL, | 520 | NULL, |
493 | NULL); | 521 | NULL); |
494 | 522 | ||
diff --git a/src/transport/test_plugin_transport_http.c b/src/transport/test_plugin_transport_http.c deleted file mode 100644 index aab66c22f..000000000 --- a/src/transport/test_plugin_transport_http.c +++ /dev/null | |||
@@ -1,1434 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet 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 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet 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 GNUnet; 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 | * @file transport/test_plugin_transport_http.c | ||
22 | * @brief testcase for plugin_transport_http.c | ||
23 | * @author Matthias Wachs | ||
24 | */ | ||
25 | |||
26 | #include "platform.h" | ||
27 | #include "gnunet_constants.h" | ||
28 | #include "gnunet_common.h" | ||
29 | #include "gnunet_getopt_lib.h" | ||
30 | #include "gnunet_hello_lib.h" | ||
31 | #include "gnunet_os_lib.h" | ||
32 | #include "gnunet_peerinfo_service.h" | ||
33 | #include "gnunet_plugin_lib.h" | ||
34 | #include "gnunet_protocols.h" | ||
35 | #include "gnunet_program_lib.h" | ||
36 | #include "gnunet_signatures.h" | ||
37 | #include "gnunet_service_lib.h" | ||
38 | #include "gnunet_crypto_lib.h" | ||
39 | |||
40 | #include "gnunet_transport_plugin.h" | ||
41 | #include "gnunet_statistics_service.h" | ||
42 | #include "transport.h" | ||
43 | #include <curl/curl.h> | ||
44 | |||
45 | #define VERBOSE GNUNET_EXTRA_LOGGING | ||
46 | #define DEBUG_CURL GNUNET_EXTRA_LOGGING | ||
47 | #define HTTP_BUFFER_SIZE 2048 | ||
48 | |||
49 | #define PROTOCOL_PREFIX "http" | ||
50 | |||
51 | #define PLUGIN libgnunet_plugin_transport_template | ||
52 | |||
53 | /** | ||
54 | * How long until we give up on transmitting the message? | ||
55 | */ | ||
56 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) | ||
57 | |||
58 | /** | ||
59 | * Testcase timeout | ||
60 | */ | ||
61 | #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) | ||
62 | |||
63 | /** | ||
64 | * How long between recieve and send? | ||
65 | */ | ||
66 | #define WAIT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) | ||
67 | |||
68 | |||
69 | |||
70 | /** | ||
71 | * Struct for plugin addresses | ||
72 | */ | ||
73 | struct Plugin_Address | ||
74 | { | ||
75 | /** | ||
76 | * Next field for linked list | ||
77 | */ | ||
78 | struct Plugin_Address *next; | ||
79 | |||
80 | /** | ||
81 | * buffer containing data to send | ||
82 | */ | ||
83 | void *addr; | ||
84 | |||
85 | /** | ||
86 | * amount of data to sent | ||
87 | */ | ||
88 | size_t addrlen; | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * Message to send using http | ||
93 | */ | ||
94 | struct HTTP_Message | ||
95 | { | ||
96 | /** | ||
97 | * buffer | ||
98 | */ | ||
99 | unsigned char buf[HTTP_BUFFER_SIZE]; | ||
100 | |||
101 | /** | ||
102 | * current position in buffer | ||
103 | */ | ||
104 | size_t pos; | ||
105 | |||
106 | /** | ||
107 | * buffer size | ||
108 | */ | ||
109 | size_t size; | ||
110 | |||
111 | /** | ||
112 | * data size | ||
113 | */ | ||
114 | size_t len; | ||
115 | }; | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Struct for plugin addresses | ||
120 | */ | ||
121 | struct HTTP_Transfer | ||
122 | { | ||
123 | /** | ||
124 | * amount of bytes we recieved | ||
125 | */ | ||
126 | size_t data_size; | ||
127 | |||
128 | /** | ||
129 | * buffer for http transfers | ||
130 | */ | ||
131 | unsigned char buf[HTTP_BUFFER_SIZE]; | ||
132 | |||
133 | /** | ||
134 | * buffer size this transfer | ||
135 | */ | ||
136 | size_t size; | ||
137 | |||
138 | /** | ||
139 | * amount of bytes we recieved | ||
140 | */ | ||
141 | size_t pos; | ||
142 | |||
143 | /** | ||
144 | * HTTP Header result for transfer | ||
145 | */ | ||
146 | unsigned int http_result_code; | ||
147 | |||
148 | /** | ||
149 | * did the test fail? | ||
150 | */ | ||
151 | unsigned int test_failed; | ||
152 | |||
153 | /** | ||
154 | * was this test already executed? | ||
155 | */ | ||
156 | unsigned int test_executed; | ||
157 | }; | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Network format for IPv4 addresses. | ||
162 | */ | ||
163 | struct IPv4HttpAddress | ||
164 | { | ||
165 | struct IPv4HttpAddress *next; | ||
166 | |||
167 | struct IPv4HttpAddress *prev; | ||
168 | |||
169 | /** | ||
170 | * IPv4 address, in network byte order. | ||
171 | */ | ||
172 | uint32_t ipv4_addr GNUNET_PACKED; | ||
173 | |||
174 | /** | ||
175 | * Port number, in network byte order. | ||
176 | */ | ||
177 | uint16_t u_port GNUNET_PACKED; | ||
178 | |||
179 | }; | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Network format for IPv6 addresses. | ||
184 | */ | ||
185 | struct IPv6HttpAddress | ||
186 | { | ||
187 | struct IPv6HttpAddress *next; | ||
188 | |||
189 | struct IPv6HttpAddress *prev; | ||
190 | |||
191 | /** | ||
192 | * IPv6 address. | ||
193 | */ | ||
194 | struct in6_addr ipv6_addr GNUNET_PACKED; | ||
195 | |||
196 | /** | ||
197 | * Port number, in network byte order. | ||
198 | */ | ||
199 | uint16_t u6_port GNUNET_PACKED; | ||
200 | |||
201 | }; | ||
202 | |||
203 | |||
204 | /** | ||
205 | * Our public key. | ||
206 | */ | ||
207 | /* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */ | ||
208 | |||
209 | /** | ||
210 | * Our public key. | ||
211 | */ | ||
212 | static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; | ||
213 | |||
214 | /** | ||
215 | * Our identity. | ||
216 | */ | ||
217 | static struct GNUNET_PeerIdentity my_identity; | ||
218 | |||
219 | /** | ||
220 | * Our private key. | ||
221 | */ | ||
222 | static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key; | ||
223 | |||
224 | /** | ||
225 | * Peer's port | ||
226 | */ | ||
227 | static long long unsigned int port; | ||
228 | |||
229 | /** | ||
230 | * Peer's addr | ||
231 | */ | ||
232 | static char *test_addr; | ||
233 | |||
234 | /** | ||
235 | * Our statistics handle. | ||
236 | */ | ||
237 | struct GNUNET_STATISTICS_Handle *stats; | ||
238 | |||
239 | |||
240 | /** | ||
241 | * Our configuration. | ||
242 | */ | ||
243 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
244 | |||
245 | /** | ||
246 | * Number of neighbours we'd like to have. | ||
247 | */ | ||
248 | static uint32_t max_connect_per_transport; | ||
249 | |||
250 | /** | ||
251 | * Environment for this plugin. | ||
252 | */ | ||
253 | static struct GNUNET_TRANSPORT_PluginEnvironment env; | ||
254 | |||
255 | /** | ||
256 | *handle for the api provided by this plugin | ||
257 | */ | ||
258 | static struct GNUNET_TRANSPORT_PluginFunctions *api; | ||
259 | |||
260 | /** | ||
261 | * ID of the task controlling the testcase timeout | ||
262 | */ | ||
263 | static GNUNET_SCHEDULER_TaskIdentifier ti_timeout; | ||
264 | |||
265 | static GNUNET_SCHEDULER_TaskIdentifier ti_send; | ||
266 | |||
267 | //const struct GNUNET_PeerIdentity * p; | ||
268 | |||
269 | /** | ||
270 | * buffer for data to send | ||
271 | */ | ||
272 | static struct HTTP_Message buffer_out; | ||
273 | |||
274 | /** | ||
275 | * buffer for data to recieve | ||
276 | */ | ||
277 | static struct HTTP_Message buffer_in; | ||
278 | |||
279 | |||
280 | struct Plugin_Address *addr_head; | ||
281 | |||
282 | /** | ||
283 | * Did the test pass or fail? | ||
284 | */ | ||
285 | static int fail_notify_address; | ||
286 | |||
287 | /** | ||
288 | * Did the test pass or fail? | ||
289 | */ | ||
290 | static int fail_notify_address_count; | ||
291 | |||
292 | /** | ||
293 | * Did the test pass or fail? | ||
294 | */ | ||
295 | static int fail_pretty_printer; | ||
296 | |||
297 | /** | ||
298 | * Did the test pass or fail? | ||
299 | */ | ||
300 | static int fail_pretty_printer_count; | ||
301 | |||
302 | /** | ||
303 | * Did the test pass or fail? | ||
304 | */ | ||
305 | static int fail_addr_to_str; | ||
306 | |||
307 | /** | ||
308 | * No. of msgs transmitted successfully to local addresses | ||
309 | */ | ||
310 | static int fail_msgs_transmited_to_local_addrs; | ||
311 | |||
312 | /** | ||
313 | * Test: transmit msg of max. size | ||
314 | */ | ||
315 | static int fail_msg_transmited_bigger_max_size; | ||
316 | |||
317 | /** | ||
318 | * Test: transmit msg of max. size | ||
319 | */ | ||
320 | static int fail_msg_transmited_max_size; | ||
321 | |||
322 | /** | ||
323 | * Test: transmit 2 msgs. in in send operation | ||
324 | */ | ||
325 | static int fail_multiple_msgs_in_transmission; | ||
326 | |||
327 | /** | ||
328 | * Test: connect to peer without peer identification | ||
329 | */ | ||
330 | static struct HTTP_Transfer test_no_ident; | ||
331 | |||
332 | /** | ||
333 | * Test: connect to peer without peer identification | ||
334 | */ | ||
335 | static struct HTTP_Transfer test_too_short_ident; | ||
336 | |||
337 | /** | ||
338 | * Test: connect to peer without peer identification | ||
339 | */ | ||
340 | static struct HTTP_Transfer test_too_long_ident; | ||
341 | |||
342 | /** | ||
343 | * Test: connect to peer with valid peer identification | ||
344 | */ | ||
345 | static struct HTTP_Transfer test_valid_ident; | ||
346 | |||
347 | /** | ||
348 | * Test: session selection, use any existing | ||
349 | */ | ||
350 | static int fail_session_selection_any; | ||
351 | |||
352 | /** | ||
353 | * Test: session selection, use existing inbound session | ||
354 | */ | ||
355 | static int fail_session_selection_session; | ||
356 | |||
357 | /** | ||
358 | * Test: session selection, use existing inbound session | ||
359 | * max message, not fitting in send & recv buffers at one time | ||
360 | */ | ||
361 | static int fail_session_selection_session_big; | ||
362 | |||
363 | /** | ||
364 | * Test: session selection, use reliable existing | ||
365 | */ | ||
366 | static int fail_session_selection_reliable; | ||
367 | |||
368 | /** | ||
369 | * Did the test pass or fail? | ||
370 | */ | ||
371 | static int fail; | ||
372 | |||
373 | /** | ||
374 | * Number of local addresses | ||
375 | */ | ||
376 | static unsigned int count_str_addr; | ||
377 | |||
378 | CURL *curl_handle; | ||
379 | |||
380 | /** | ||
381 | * cURL Multihandle | ||
382 | */ | ||
383 | static CURLM *multi_handle; | ||
384 | |||
385 | /** | ||
386 | * The task sending data | ||
387 | */ | ||
388 | static GNUNET_SCHEDULER_TaskIdentifier http_task_send; | ||
389 | |||
390 | static char *servicehome; | ||
391 | |||
392 | /** | ||
393 | * Shutdown testcase | ||
394 | */ | ||
395 | static void | ||
396 | shutdown_clean () | ||
397 | { | ||
398 | struct Plugin_Address *tmp; | ||
399 | |||
400 | /* Evaluate results */ | ||
401 | fail = 0; | ||
402 | if ((fail_notify_address == GNUNET_YES) || (fail_pretty_printer == GNUNET_YES) | ||
403 | || (fail_addr_to_str == GNUNET_YES)) | ||
404 | { | ||
405 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
406 | "Phase 0: Test plugin functions failed\n"); | ||
407 | fail = 1; | ||
408 | } | ||
409 | if ((test_no_ident.test_failed == GNUNET_YES) || | ||
410 | (test_too_short_ident.test_failed == GNUNET_YES) || | ||
411 | (test_too_long_ident.test_failed == GNUNET_YES) || | ||
412 | (test_valid_ident.test_failed == GNUNET_YES)) | ||
413 | { | ||
414 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
415 | "Phase 1: Test connect with wrong data failed\n"); | ||
416 | fail = 1; | ||
417 | } | ||
418 | if ((fail_session_selection_any != GNUNET_NO) || | ||
419 | (fail_session_selection_reliable != GNUNET_NO) || | ||
420 | (fail_session_selection_session != GNUNET_NO) || | ||
421 | (fail_session_selection_session_big != GNUNET_NO)) | ||
422 | { | ||
423 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
424 | "Phase 2: Test session selection failed\n"); | ||
425 | fail = 1; | ||
426 | } | ||
427 | if ((fail_msgs_transmited_to_local_addrs != count_str_addr) || | ||
428 | (fail_multiple_msgs_in_transmission != 2) || | ||
429 | (fail_msg_transmited_max_size == GNUNET_YES)) | ||
430 | { | ||
431 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
432 | "Phase 3: Test sending with plugin failed\n"); | ||
433 | fail = 1; | ||
434 | } | ||
435 | if (fail != 1) | ||
436 | { | ||
437 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All tests successful\n"); | ||
438 | } | ||
439 | |||
440 | api->disconnect (api->cls, &my_identity); | ||
441 | |||
442 | curl_multi_cleanup (multi_handle); | ||
443 | |||
444 | if (NULL != curl_handle) | ||
445 | curl_easy_cleanup (curl_handle); | ||
446 | |||
447 | /* cleaning addresses */ | ||
448 | while (addr_head != NULL) | ||
449 | { | ||
450 | tmp = addr_head->next; | ||
451 | GNUNET_free (addr_head->addr); | ||
452 | GNUNET_free (addr_head); | ||
453 | addr_head = tmp; | ||
454 | } | ||
455 | |||
456 | if (ti_send != GNUNET_SCHEDULER_NO_TASK) | ||
457 | { | ||
458 | GNUNET_SCHEDULER_cancel (ti_send); | ||
459 | ti_send = GNUNET_SCHEDULER_NO_TASK; | ||
460 | } | ||
461 | |||
462 | if (http_task_send != GNUNET_SCHEDULER_NO_TASK) | ||
463 | { | ||
464 | GNUNET_SCHEDULER_cancel (http_task_send); | ||
465 | http_task_send = GNUNET_SCHEDULER_NO_TASK; | ||
466 | } | ||
467 | |||
468 | if (ti_timeout != GNUNET_SCHEDULER_NO_TASK) | ||
469 | { | ||
470 | GNUNET_SCHEDULER_cancel (ti_timeout); | ||
471 | ti_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
472 | } | ||
473 | |||
474 | GNUNET_free (test_addr); | ||
475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unloading http plugin\n"); | ||
476 | GNUNET_assert (NULL == | ||
477 | GNUNET_PLUGIN_unload ("libgnunet_gnunet_transport_plugin_http", | ||
478 | api)); | ||
479 | |||
480 | GNUNET_SCHEDULER_shutdown (); | ||
481 | GNUNET_DISK_directory_remove ("/tmp/test_gnunet_transport_plugin_http"); | ||
482 | |||
483 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exiting testcase\n"); | ||
484 | |||
485 | if (servicehome != NULL) | ||
486 | { | ||
487 | GNUNET_DISK_directory_remove (servicehome); | ||
488 | GNUNET_free (servicehome); | ||
489 | } | ||
490 | |||
491 | exit (fail); | ||
492 | return; | ||
493 | } | ||
494 | |||
495 | |||
496 | /** | ||
497 | * Continuation called after plugin send message | ||
498 | * @cls closure | ||
499 | * @target target | ||
500 | * @result GNUNET_OK or GNUNET_SYSERR | ||
501 | */ | ||
502 | |||
503 | static void | ||
504 | task_send_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result) | ||
505 | { | ||
506 | if ((cls == &fail_msg_transmited_bigger_max_size) && | ||
507 | (result == GNUNET_SYSERR)) | ||
508 | { | ||
509 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
510 | "Message bigger max msg size was not sent!\n"); | ||
511 | fail_msg_transmited_bigger_max_size = GNUNET_NO; | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | if ((cls == &fail_msg_transmited_max_size) && (result == GNUNET_OK)) | ||
516 | { | ||
517 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
518 | "Message with max msg size succesfully sent!\n", | ||
519 | fail_msgs_transmited_to_local_addrs); | ||
520 | fail_msg_transmited_max_size = GNUNET_NO; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | |||
525 | static void | ||
526 | run_connection_tests (int phase, void *cls); | ||
527 | |||
528 | /** | ||
529 | * Recieves messages from plugin, in real world transport | ||
530 | */ | ||
531 | static struct GNUNET_TIME_Relative | ||
532 | receive (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
533 | const struct GNUNET_MessageHeader *message, | ||
534 | const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count, | ||
535 | struct Session *session, const char *sender_address, | ||
536 | uint16_t sender_address_len) | ||
537 | { | ||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | "Testcase recieved new message from peer `%s' with type %u and length %u, session %X\n", | ||
540 | GNUNET_i2s (peer), ntohs (message->type), ntohs (message->size), | ||
541 | session); | ||
542 | |||
543 | if ((ntohs (message->type) >= 10) && (ntohs (message->type) < 20)) | ||
544 | { | ||
545 | fail_msgs_transmited_to_local_addrs++; | ||
546 | if (fail_msgs_transmited_to_local_addrs == count_str_addr) | ||
547 | run_connection_tests (2, session); | ||
548 | } | ||
549 | if ((ntohs (message->type) == 20)) | ||
550 | { | ||
551 | fail_session_selection_reliable = GNUNET_NO; | ||
552 | } | ||
553 | if ((ntohs (message->type) == 21)) | ||
554 | { | ||
555 | fail_session_selection_any = GNUNET_NO; | ||
556 | } | ||
557 | if ((ntohs (message->type) == 22)) | ||
558 | { | ||
559 | fail_session_selection_session = GNUNET_NO; | ||
560 | } | ||
561 | if ((ntohs (message->type) == 23)) | ||
562 | { | ||
563 | fail_session_selection_session_big = GNUNET_NO; | ||
564 | run_connection_tests (3, NULL); | ||
565 | } | ||
566 | if ((ntohs (message->type) == 30) || (ntohs (message->type) == 31)) | ||
567 | { | ||
568 | fail_multiple_msgs_in_transmission++; | ||
569 | } | ||
570 | if ((ntohs (message->type) == 32) && | ||
571 | (ntohs (message->size) == GNUNET_SERVER_MAX_MESSAGE_SIZE - 1)) | ||
572 | { | ||
573 | fail_msg_transmited_max_size = GNUNET_NO; | ||
574 | shutdown_clean (); | ||
575 | } | ||
576 | return GNUNET_TIME_UNIT_ZERO; | ||
577 | } | ||
578 | |||
579 | |||
580 | static size_t | ||
581 | send_function (void *stream, size_t size, size_t nmemb, void *ptr) | ||
582 | { | ||
583 | unsigned int len; | ||
584 | |||
585 | len = buffer_out.len; | ||
586 | |||
587 | if ((buffer_out.pos == len) || (len > (size * nmemb))) | ||
588 | return 0; | ||
589 | memcpy (stream, buffer_out.buf, len); | ||
590 | buffer_out.pos = len; | ||
591 | return len; | ||
592 | |||
593 | } | ||
594 | |||
595 | static size_t | ||
596 | recv_function (void *ptr, size_t size, size_t nmemb, void *ctx) | ||
597 | { | ||
598 | |||
599 | if (buffer_in.pos + size * nmemb > buffer_in.size) | ||
600 | return 0; /* overflow */ | ||
601 | |||
602 | buffer_in.len = size * nmemb; | ||
603 | memcpy (&buffer_in.buf[buffer_in.pos], ptr, size * nmemb); | ||
604 | buffer_in.pos += size * nmemb; | ||
605 | buffer_in.len = buffer_in.pos; | ||
606 | buffer_in.buf[buffer_in.pos] = '\0'; | ||
607 | return buffer_in.pos; | ||
608 | } | ||
609 | |||
610 | static size_t | ||
611 | header_function (void *ptr, size_t size, size_t nmemb, void *stream) | ||
612 | { | ||
613 | struct HTTP_Transfer *res = stream; | ||
614 | char *tmp; | ||
615 | unsigned int len = size * nmemb; | ||
616 | |||
617 | tmp = GNUNET_malloc (len + 1); | ||
618 | memcpy (tmp, ptr, len); | ||
619 | if (tmp[len - 2] == 13) | ||
620 | tmp[len - 2] = '\0'; | ||
621 | #if DEBUG_CURL | ||
622 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: `%s'\n", tmp); | ||
623 | #endif | ||
624 | if (0 == strcmp (tmp, "HTTP/1.1 100 Continue")) | ||
625 | { | ||
626 | res->http_result_code = 100; | ||
627 | } | ||
628 | if (0 == strcmp (tmp, "HTTP/1.1 200 OK")) | ||
629 | { | ||
630 | res->http_result_code = 200; | ||
631 | } | ||
632 | if (0 == strcmp (tmp, "HTTP/1.1 400 Bad Request")) | ||
633 | { | ||
634 | res->http_result_code = 400; | ||
635 | } | ||
636 | if (0 == strcmp (tmp, "HTTP/1.1 404 Not Found")) | ||
637 | { | ||
638 | res->http_result_code = 404; | ||
639 | } | ||
640 | if (0 == strcmp (tmp, "HTTP/1.1 413 Request entity too large")) | ||
641 | { | ||
642 | res->http_result_code = 413; | ||
643 | } | ||
644 | |||
645 | GNUNET_free (tmp); | ||
646 | return size * nmemb; | ||
647 | } | ||
648 | |||
649 | |||
650 | static size_t | ||
651 | send_prepare (struct HTTP_Transfer *result); | ||
652 | |||
653 | |||
654 | static void | ||
655 | send_execute (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
656 | { | ||
657 | struct HTTP_Transfer *res; | ||
658 | |||
659 | int running; | ||
660 | struct CURLMsg *msg; | ||
661 | CURLMcode mret; | ||
662 | |||
663 | res = (struct HTTP_Transfer *) cls; | ||
664 | http_task_send = GNUNET_SCHEDULER_NO_TASK; | ||
665 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
666 | return; | ||
667 | |||
668 | do | ||
669 | { | ||
670 | running = 0; | ||
671 | mret = curl_multi_perform (multi_handle, &running); | ||
672 | if (running == 0) | ||
673 | { | ||
674 | do | ||
675 | { | ||
676 | |||
677 | msg = curl_multi_info_read (multi_handle, &running); | ||
678 | if (msg == NULL) | ||
679 | break; | ||
680 | /* get session for affected curl handle */ | ||
681 | //cs = find_session_by_curlhandle (msg->easy_handle); | ||
682 | //GNUNET_assert ( cs != NULL ); | ||
683 | switch (msg->msg) | ||
684 | { | ||
685 | |||
686 | case CURLMSG_DONE: | ||
687 | if ((msg->data.result != CURLE_OK) && | ||
688 | (msg->data.result != CURLE_GOT_NOTHING)) | ||
689 | { | ||
690 | |||
691 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
692 | _("curl failed for `%s' at %s:%d: `%s'\n"), | ||
693 | "curl_multi_perform", __FILE__, __LINE__, | ||
694 | curl_easy_strerror (msg->data.result)); | ||
695 | /* sending msg failed */ | ||
696 | curl_easy_cleanup (curl_handle); | ||
697 | curl_handle = NULL; | ||
698 | |||
699 | run_connection_tests (0, NULL); | ||
700 | } | ||
701 | if (res == &test_no_ident) | ||
702 | { | ||
703 | if ((res->http_result_code == 404) && (buffer_in.len == 208)) | ||
704 | { | ||
705 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
706 | "Connecting to peer without any peer identification: test passed\n"); | ||
707 | res->test_failed = GNUNET_NO; | ||
708 | } | ||
709 | else | ||
710 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
711 | _ | ||
712 | ("Connecting to peer without any peer identification: test failed\n")); | ||
713 | } | ||
714 | if (res == &test_too_short_ident) | ||
715 | { | ||
716 | if ((res->http_result_code == 404) && (buffer_in.len == 208)) | ||
717 | { | ||
718 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
719 | "Connecting to peer with too short peer identification: test passed\n"); | ||
720 | res->test_failed = GNUNET_NO; | ||
721 | } | ||
722 | else | ||
723 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
724 | _ | ||
725 | ("Connecting to peer with too short peer identification: test failed\n")); | ||
726 | } | ||
727 | if (res == &test_too_long_ident) | ||
728 | { | ||
729 | if ((res->http_result_code == 404) && (buffer_in.len == 208)) | ||
730 | { | ||
731 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
732 | "Connecting to peer with too long peer identification: test passed\n"); | ||
733 | res->test_failed = GNUNET_NO; | ||
734 | } | ||
735 | else | ||
736 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
737 | _ | ||
738 | ("Connecting to peer with too long peer identification: test failed\n")); | ||
739 | } | ||
740 | if (res == &test_valid_ident) | ||
741 | { | ||
742 | if ((res->http_result_code == 200)) | ||
743 | { | ||
744 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
745 | "Connecting to peer with valid peer identification: test passed\n"); | ||
746 | res->test_failed = GNUNET_NO; | ||
747 | } | ||
748 | else | ||
749 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
750 | "Connecting to peer with valid peer identification: test failed\n"); | ||
751 | } | ||
752 | curl_easy_cleanup (curl_handle); | ||
753 | curl_handle = NULL; | ||
754 | if ((res == &test_valid_ident) && (res->test_failed == GNUNET_NO)) | ||
755 | run_connection_tests (1, NULL); | ||
756 | run_connection_tests (0, NULL); | ||
757 | return; | ||
758 | default: | ||
759 | break; | ||
760 | } | ||
761 | |||
762 | } | ||
763 | while ((running > 0)); | ||
764 | } | ||
765 | } | ||
766 | while (mret == CURLM_CALL_MULTI_PERFORM); | ||
767 | send_prepare (cls); | ||
768 | } | ||
769 | |||
770 | |||
771 | /** | ||
772 | * Function setting up file descriptors and scheduling task to run | ||
773 | * @param ses session to send data to | ||
774 | * @return bytes sent to peer | ||
775 | */ | ||
776 | static size_t | ||
777 | send_prepare (struct HTTP_Transfer *result) | ||
778 | { | ||
779 | fd_set rs; | ||
780 | fd_set ws; | ||
781 | fd_set es; | ||
782 | int max; | ||
783 | struct GNUNET_NETWORK_FDSet *grs; | ||
784 | struct GNUNET_NETWORK_FDSet *gws; | ||
785 | long to; | ||
786 | CURLMcode mret; | ||
787 | |||
788 | max = -1; | ||
789 | FD_ZERO (&rs); | ||
790 | FD_ZERO (&ws); | ||
791 | FD_ZERO (&es); | ||
792 | mret = curl_multi_fdset (multi_handle, &rs, &ws, &es, &max); | ||
793 | if (mret != CURLM_OK) | ||
794 | { | ||
795 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), | ||
796 | "curl_multi_fdset", __FILE__, __LINE__, | ||
797 | curl_multi_strerror (mret)); | ||
798 | return -1; | ||
799 | } | ||
800 | mret = curl_multi_timeout (multi_handle, &to); | ||
801 | if (mret != CURLM_OK) | ||
802 | { | ||
803 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), | ||
804 | "curl_multi_timeout", __FILE__, __LINE__, | ||
805 | curl_multi_strerror (mret)); | ||
806 | return -1; | ||
807 | } | ||
808 | |||
809 | grs = GNUNET_NETWORK_fdset_create (); | ||
810 | gws = GNUNET_NETWORK_fdset_create (); | ||
811 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); | ||
812 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); | ||
813 | http_task_send = | ||
814 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
815 | GNUNET_SCHEDULER_NO_TASK, | ||
816 | GNUNET_TIME_relative_multiply | ||
817 | (GNUNET_TIME_UNIT_SECONDS, 0), grs, gws, | ||
818 | &send_execute, result); | ||
819 | GNUNET_NETWORK_fdset_destroy (gws); | ||
820 | GNUNET_NETWORK_fdset_destroy (grs); | ||
821 | |||
822 | /* FIXME: return bytes REALLY sent */ | ||
823 | return 0; | ||
824 | } | ||
825 | |||
826 | /** | ||
827 | * function to send data to server | ||
828 | */ | ||
829 | static int | ||
830 | send_data (struct HTTP_Transfer *result, char *url) | ||
831 | { | ||
832 | |||
833 | curl_handle = curl_easy_init (); | ||
834 | if (NULL == curl_handle) | ||
835 | { | ||
836 | printf ("easy_init failed \n"); | ||
837 | return GNUNET_SYSERR; | ||
838 | } | ||
839 | #if DEBUG_CURL | ||
840 | curl_easy_setopt (curl_handle, CURLOPT_VERBOSE, 1L); | ||
841 | #endif | ||
842 | curl_easy_setopt (curl_handle, CURLOPT_URL, url); | ||
843 | curl_easy_setopt (curl_handle, CURLOPT_PUT, 1L); | ||
844 | curl_easy_setopt (curl_handle, CURLOPT_HEADERFUNCTION, &header_function); | ||
845 | curl_easy_setopt (curl_handle, CURLOPT_WRITEHEADER, result); | ||
846 | curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, &recv_function); | ||
847 | curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, result); | ||
848 | curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &send_function); | ||
849 | curl_easy_setopt (curl_handle, CURLOPT_READDATA, result); | ||
850 | curl_easy_setopt (curl_handle, CURLOPT_INFILESIZE_LARGE, | ||
851 | (curl_off_t) buffer_out.len); | ||
852 | curl_easy_setopt (curl_handle, CURLOPT_TIMEOUT, 30); | ||
853 | curl_easy_setopt (curl_handle, CURLOPT_CONNECTTIMEOUT, 20); | ||
854 | |||
855 | curl_multi_add_handle (multi_handle, curl_handle); | ||
856 | |||
857 | send_prepare (result); | ||
858 | |||
859 | return GNUNET_OK; | ||
860 | } | ||
861 | |||
862 | /** | ||
863 | * Plugin notifies transport (aka testcase) about its addresses | ||
864 | */ | ||
865 | static void | ||
866 | notify_address (void *cls, int add_remove, const void *addr, size_t addrlen) | ||
867 | { | ||
868 | char address[INET6_ADDRSTRLEN]; | ||
869 | unsigned int port; | ||
870 | struct Plugin_Address *pl_addr; | ||
871 | struct Plugin_Address *cur; | ||
872 | |||
873 | if (addrlen == (sizeof (struct IPv4HttpAddress))) | ||
874 | { | ||
875 | inet_ntop (AF_INET, (struct in_addr *) addr, address, INET_ADDRSTRLEN); | ||
876 | port = ntohs (((struct IPv4HttpAddress *) addr)->u_port); | ||
877 | } | ||
878 | else if (addrlen == (sizeof (struct IPv6HttpAddress))) | ||
879 | { | ||
880 | inet_ntop (AF_INET6, (struct in6_addr *) addr, address, INET6_ADDRSTRLEN); | ||
881 | port = ntohs (((struct IPv6HttpAddress *) addr)->u6_port); | ||
882 | } | ||
883 | else | ||
884 | { | ||
885 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
886 | _ | ||
887 | ("Unknown address size: ipv6 has %u ipv4 has %u but this has %u\n"), | ||
888 | sizeof (struct IPv6HttpAddress), | ||
889 | sizeof (struct IPv4HttpAddress), addrlen); | ||
890 | return; | ||
891 | } | ||
892 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
893 | _("Transport plugin notification for address: `%s':%u\n"), | ||
894 | address, port); | ||
895 | pl_addr = GNUNET_malloc (sizeof (struct Plugin_Address)); | ||
896 | pl_addr->addrlen = addrlen; | ||
897 | pl_addr->addr = GNUNET_malloc (addrlen); | ||
898 | memcpy (pl_addr->addr, addr, addrlen); | ||
899 | pl_addr->next = NULL; | ||
900 | |||
901 | if (NULL == addr_head) | ||
902 | { | ||
903 | addr_head = pl_addr; | ||
904 | } | ||
905 | else | ||
906 | { | ||
907 | cur = addr_head; | ||
908 | while (NULL != cur->next) | ||
909 | { | ||
910 | cur = cur->next; | ||
911 | } | ||
912 | cur->next = pl_addr; | ||
913 | } | ||
914 | fail_notify_address_count++; | ||
915 | fail_notify_address = GNUNET_NO; | ||
916 | } | ||
917 | |||
918 | static void | ||
919 | plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
920 | struct Session *session) | ||
921 | { | ||
922 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
923 | "Pluging tells me: session %X to peer `%s' ended\n", session, | ||
924 | GNUNET_i2s (peer)); | ||
925 | } | ||
926 | |||
927 | |||
928 | /** | ||
929 | * Setup plugin environment | ||
930 | */ | ||
931 | static void | ||
932 | setup_plugin_environment () | ||
933 | { | ||
934 | env.cfg = cfg; | ||
935 | env.stats = stats; | ||
936 | env.my_identity = &my_identity; | ||
937 | env.cls = &env; | ||
938 | env.receive = &receive; | ||
939 | env.notify_address = ¬ify_address; | ||
940 | env.max_connections = max_connect_per_transport; | ||
941 | env.session_end = &plugin_env_session_end; | ||
942 | } | ||
943 | |||
944 | |||
945 | /** | ||
946 | * Task shutting down testcase if it a timeout occurs | ||
947 | */ | ||
948 | static void | ||
949 | task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
950 | { | ||
951 | ti_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
952 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
953 | return; | ||
954 | |||
955 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n"); | ||
956 | fail = GNUNET_YES; | ||
957 | shutdown_clean (); | ||
958 | return; | ||
959 | } | ||
960 | |||
961 | |||
962 | static void | ||
963 | pretty_printer_cb (void *cls, const char *address) | ||
964 | { | ||
965 | if (NULL == address) | ||
966 | return; | ||
967 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin returned pretty address: `%s'\n", | ||
968 | address); | ||
969 | fail_pretty_printer_count++; | ||
970 | } | ||
971 | |||
972 | /** | ||
973 | * Runs every single test to test the plugin | ||
974 | */ | ||
975 | static void | ||
976 | run_connection_tests (int phase, void *cls) | ||
977 | { | ||
978 | struct GNUNET_MessageHeader *msg; | ||
979 | unsigned int size; | ||
980 | |||
981 | if (phase == 0) | ||
982 | { | ||
983 | char *host_str = NULL; | ||
984 | |||
985 | /* resetting buffers */ | ||
986 | buffer_in.size = HTTP_BUFFER_SIZE; | ||
987 | buffer_in.pos = 0; | ||
988 | buffer_in.len = 0; | ||
989 | |||
990 | buffer_out.size = HTTP_BUFFER_SIZE; | ||
991 | buffer_out.pos = 0; | ||
992 | buffer_out.len = 0; | ||
993 | |||
994 | if (test_no_ident.test_executed == GNUNET_NO) | ||
995 | { | ||
996 | /* Connecting to peer without identification */ | ||
997 | const char *ident = ""; | ||
998 | |||
999 | GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr, | ||
1000 | ident); | ||
1001 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1002 | _("Connecting to peer without any peer identification.\n")); | ||
1003 | test_no_ident.test_executed = GNUNET_YES; | ||
1004 | send_data (&test_no_ident, host_str); | ||
1005 | GNUNET_free (host_str); | ||
1006 | return; | ||
1007 | } | ||
1008 | if (test_too_short_ident.test_executed == GNUNET_NO) | ||
1009 | { | ||
1010 | const char *ident = "AAAAAAAAAA"; | ||
1011 | |||
1012 | /* Connecting to peer with too short identification */ | ||
1013 | GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr, | ||
1014 | ident); | ||
1015 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1016 | _ | ||
1017 | ("Connecting to peer with too short peer identification.\n")); | ||
1018 | test_too_short_ident.test_executed = GNUNET_YES; | ||
1019 | send_data (&test_too_short_ident, host_str); | ||
1020 | GNUNET_free (host_str); | ||
1021 | return; | ||
1022 | } | ||
1023 | |||
1024 | if (test_too_long_ident.test_executed == GNUNET_NO) | ||
1025 | { | ||
1026 | const char *ident = | ||
1027 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; | ||
1028 | |||
1029 | /* Connecting to peer with too long identification */ | ||
1030 | GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr, | ||
1031 | ident); | ||
1032 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1033 | _("Connecting to peer with too long peer identification.\n")); | ||
1034 | test_too_long_ident.test_executed = GNUNET_YES; | ||
1035 | send_data (&test_too_long_ident, host_str); | ||
1036 | GNUNET_free (host_str); | ||
1037 | return; | ||
1038 | } | ||
1039 | if (test_valid_ident.test_executed == GNUNET_NO) | ||
1040 | { | ||
1041 | struct GNUNET_CRYPTO_HashAsciiEncoded ident; | ||
1042 | |||
1043 | GNUNET_CRYPTO_hash_to_enc (&my_identity.hashPubKey, &ident); | ||
1044 | GNUNET_asprintf (&host_str, "%s://%s/%s%s", PROTOCOL_PREFIX, test_addr, | ||
1045 | (char *) &ident, ";0"); | ||
1046 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1047 | _("Connecting to peer with valid peer identification.\n")); | ||
1048 | test_valid_ident.test_executed = GNUNET_YES; | ||
1049 | send_data (&test_valid_ident, host_str); | ||
1050 | GNUNET_free (host_str); | ||
1051 | return; | ||
1052 | } | ||
1053 | } | ||
1054 | if (phase == 1) | ||
1055 | { | ||
1056 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1057 | "\nPhase 1: transmit data to all suggested addresses\n\n"); | ||
1058 | /* Using one of the addresses the plugin proposed */ | ||
1059 | GNUNET_assert (addr_head->addr != NULL); | ||
1060 | |||
1061 | struct Plugin_Address *tmp_addr; | ||
1062 | struct GNUNET_MessageHeader msg; | ||
1063 | char *tmp = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader)); | ||
1064 | char address[INET6_ADDRSTRLEN]; | ||
1065 | unsigned int port; | ||
1066 | unsigned int type = 10; | ||
1067 | |||
1068 | msg.size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
1069 | tmp_addr = addr_head; | ||
1070 | /* send a message to all addresses advertised by plugin */ | ||
1071 | |||
1072 | int count = 0; | ||
1073 | |||
1074 | while (tmp_addr != NULL) | ||
1075 | { | ||
1076 | if (tmp_addr->addrlen == (sizeof (struct IPv4HttpAddress))) | ||
1077 | { | ||
1078 | inet_ntop (AF_INET, (struct in_addr *) tmp_addr->addr, address, | ||
1079 | INET_ADDRSTRLEN); | ||
1080 | port = ntohs (((struct IPv4HttpAddress *) tmp_addr->addr)->u_port); | ||
1081 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1082 | "Sending message to addres no. %u: `%s':%u\n", count, | ||
1083 | address, port); | ||
1084 | } | ||
1085 | if (tmp_addr->addrlen == (sizeof (struct IPv6HttpAddress))) | ||
1086 | { | ||
1087 | inet_ntop (AF_INET6, (struct in6_addr *) tmp_addr->addr, address, | ||
1088 | INET6_ADDRSTRLEN); | ||
1089 | port = ntohs (((struct IPv6HttpAddress *) tmp_addr->addr)->u6_port); | ||
1090 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1091 | "Sending message to addres no. %u: `%s':%u\n", count, | ||
1092 | address, port); | ||
1093 | } | ||
1094 | msg.type = htons (type); | ||
1095 | memcpy (tmp, &msg, sizeof (struct GNUNET_MessageHeader)); | ||
1096 | api->send (api->cls, &my_identity, tmp, | ||
1097 | sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL, | ||
1098 | tmp_addr->addr, tmp_addr->addrlen, GNUNET_YES, &task_send_cont, | ||
1099 | &fail_msgs_transmited_to_local_addrs); | ||
1100 | tmp_addr = tmp_addr->next; | ||
1101 | count++; | ||
1102 | type++; | ||
1103 | } | ||
1104 | GNUNET_free (tmp); | ||
1105 | return; | ||
1106 | } | ||
1107 | |||
1108 | if (phase == 2) | ||
1109 | { | ||
1110 | struct Session *session = cls; | ||
1111 | |||
1112 | msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader)); | ||
1113 | |||
1114 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 2: session selection\n\n"); | ||
1115 | size = sizeof (struct GNUNET_MessageHeader); | ||
1116 | msg->size = htons (size); | ||
1117 | msg->type = htons (20); | ||
1118 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1119 | NULL, NULL, 0, GNUNET_NO, &task_send_cont, NULL); | ||
1120 | |||
1121 | msg->type = htons (21); | ||
1122 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1123 | NULL, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL); | ||
1124 | |||
1125 | /* answer on session */ | ||
1126 | size = sizeof (struct GNUNET_MessageHeader); | ||
1127 | msg->size = htons (size); | ||
1128 | msg->type = htons (22); | ||
1129 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1130 | session, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL); | ||
1131 | GNUNET_free (msg); | ||
1132 | |||
1133 | /* answer on session with big message not fitting in mhd send buffer */ | ||
1134 | size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1; | ||
1135 | msg = GNUNET_malloc (size); | ||
1136 | msg->size = htons (size); | ||
1137 | msg->type = htons (23); | ||
1138 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1139 | session, NULL, 0, GNUNET_NO, &task_send_cont, NULL); | ||
1140 | GNUNET_free (msg); | ||
1141 | return; | ||
1142 | } | ||
1143 | |||
1144 | if (phase == 3) | ||
1145 | { | ||
1146 | |||
1147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1148 | "Phase 3: send multiple or big messages after disconnect\n\n"); | ||
1149 | /* disconnect from peer, so new connections are created */ | ||
1150 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect from peer: `%s'\n", | ||
1151 | GNUNET_i2s (&my_identity)); | ||
1152 | api->disconnect (api->cls, &my_identity); | ||
1153 | |||
1154 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 3: sending messages\n"); | ||
1155 | /* send a multiple GNUNET_messages at a time */ | ||
1156 | size = 2 * sizeof (struct GNUNET_MessageHeader); | ||
1157 | msg = GNUNET_malloc (2 * size); | ||
1158 | msg->size = htons (size); | ||
1159 | msg->type = htons (30); | ||
1160 | struct GNUNET_MessageHeader *msg2 = &msg[2]; | ||
1161 | |||
1162 | msg2->size = htons (2 * sizeof (struct GNUNET_MessageHeader)); | ||
1163 | msg2->type = htons (31); | ||
1164 | api->send (api->cls, &my_identity, (const char *) msg, | ||
1165 | 4 * sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL, | ||
1166 | addr_head->addr, addr_head->addrlen, GNUNET_NO, &task_send_cont, | ||
1167 | &fail_multiple_msgs_in_transmission); | ||
1168 | GNUNET_free (msg); | ||
1169 | /* send a message with size GNUNET_SERVER_MAX_MESSAGE_SIZE-1 */ | ||
1170 | |||
1171 | size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1; | ||
1172 | msg = GNUNET_malloc (size); | ||
1173 | msg->size = htons (size); | ||
1174 | msg->type = htons (32); | ||
1175 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1176 | NULL, addr_head->addr, addr_head->addrlen, GNUNET_NO, | ||
1177 | &task_send_cont, &fail_msg_transmited_max_size); | ||
1178 | GNUNET_free (msg); | ||
1179 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more tests to run\n"); | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | |||
1184 | /** | ||
1185 | * Runs the test. | ||
1186 | * | ||
1187 | * @param cls closure | ||
1188 | * @param c configuration to use | ||
1189 | */ | ||
1190 | static void | ||
1191 | run (void *cls, char *const *args, const char *cfgfile, | ||
1192 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
1193 | { | ||
1194 | char *libname; | ||
1195 | |||
1196 | cfg = c; | ||
1197 | char *keyfile; | ||
1198 | unsigned long long tneigh; | ||
1199 | struct Plugin_Address *cur; | ||
1200 | const char *addr_str; | ||
1201 | |||
1202 | |||
1203 | unsigned int suggest_res; | ||
1204 | |||
1205 | fail_pretty_printer = GNUNET_YES; | ||
1206 | fail_notify_address = GNUNET_YES; | ||
1207 | fail_addr_to_str = GNUNET_YES; | ||
1208 | fail_msgs_transmited_to_local_addrs = 0; | ||
1209 | fail_msg_transmited_max_size = GNUNET_YES; | ||
1210 | fail_multiple_msgs_in_transmission = 0; | ||
1211 | fail_session_selection_reliable = GNUNET_YES; | ||
1212 | fail_session_selection_reliable = GNUNET_YES; | ||
1213 | fail_session_selection_session = GNUNET_YES; | ||
1214 | fail_session_selection_session_big = GNUNET_YES; | ||
1215 | |||
1216 | addr_head = NULL; | ||
1217 | count_str_addr = 0; | ||
1218 | /* parse configuration */ | ||
1219 | if (GNUNET_CONFIGURATION_have_value (c, "PATHS", "SERVICEHOME")) | ||
1220 | GNUNET_CONFIGURATION_get_value_string (c, "PATHS", "SERVICEHOME", | ||
1221 | &servicehome); | ||
1222 | |||
1223 | if ((GNUNET_OK != | ||
1224 | GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", "NEIGHBOUR_LIMIT", | ||
1225 | &tneigh)) || | ||
1226 | (GNUNET_OK != | ||
1227 | GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", | ||
1228 | &keyfile))) | ||
1229 | { | ||
1230 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1231 | _ | ||
1232 | ("Transport service is lacking key configuration settings. Exiting.\n")); | ||
1233 | GNUNET_SCHEDULER_shutdown (); | ||
1234 | fail = 1; | ||
1235 | return; | ||
1236 | } | ||
1237 | |||
1238 | if ((GNUNET_OK != | ||
1239 | GNUNET_CONFIGURATION_get_value_number (cfg, "transport-http", "PORT", | ||
1240 | &port)) || (port > 65535) || | ||
1241 | (port == 0)) | ||
1242 | { | ||
1243 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "http", | ||
1244 | _ | ||
1245 | ("Require valid port number for transport plugin `%s' in configuration!\n"), | ||
1246 | "transport-http"); | ||
1247 | } | ||
1248 | |||
1249 | max_connect_per_transport = (uint32_t) tneigh; | ||
1250 | my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); | ||
1251 | GNUNET_free (keyfile); | ||
1252 | if (my_private_key == NULL) | ||
1253 | { | ||
1254 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1255 | _("Transport service could not access hostkey. Exiting.\n")); | ||
1256 | GNUNET_SCHEDULER_shutdown (); | ||
1257 | fail = 1; | ||
1258 | return; | ||
1259 | } | ||
1260 | |||
1261 | GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); | ||
1262 | GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), | ||
1263 | &my_identity.hashPubKey); | ||
1264 | |||
1265 | /* assertions before start */ | ||
1266 | GNUNET_assert ((port > 0) && (port <= 65535)); | ||
1267 | |||
1268 | /* load plugins... */ | ||
1269 | setup_plugin_environment (); | ||
1270 | GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http"); | ||
1271 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading HTTP transport plugin `%s'\n"), | ||
1272 | libname); | ||
1273 | api = GNUNET_PLUGIN_load (libname, &env); | ||
1274 | GNUNET_free (libname); | ||
1275 | if (api == NULL) | ||
1276 | { | ||
1277 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1278 | _("Failed to load transport plugin for http\n")); | ||
1279 | fail = 1; | ||
1280 | return; | ||
1281 | } | ||
1282 | |||
1283 | |||
1284 | ti_timeout = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &task_timeout, NULL); | ||
1285 | |||
1286 | /* testing plugin functionality */ | ||
1287 | GNUNET_assert (0 != fail_notify_address_count); | ||
1288 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1289 | "Transport plugin returned %u addresses to connect to\n", | ||
1290 | fail_notify_address_count); | ||
1291 | |||
1292 | /* testing pretty printer with all addresses obtained from the plugin */ | ||
1293 | cur = addr_head; | ||
1294 | while (cur != NULL) | ||
1295 | { | ||
1296 | api->address_pretty_printer (api->cls, "http", cur->addr, cur->addrlen, | ||
1297 | GNUNET_NO, TEST_TIMEOUT, &pretty_printer_cb, | ||
1298 | NULL); | ||
1299 | addr_str = api->address_to_string (api->cls, cur->addr, cur->addrlen); | ||
1300 | suggest_res = api->check_address (api->cls, cur->addr, cur->addrlen); | ||
1301 | |||
1302 | GNUNET_assert (GNUNET_OK == suggest_res); | ||
1303 | GNUNET_assert (NULL != addr_str); | ||
1304 | count_str_addr++; | ||
1305 | GNUNET_free ((char *) addr_str); | ||
1306 | cur = cur->next; | ||
1307 | } | ||
1308 | GNUNET_assert (fail_pretty_printer_count > 0); | ||
1309 | GNUNET_assert (fail_pretty_printer_count == fail_notify_address_count); | ||
1310 | GNUNET_assert (fail_pretty_printer_count == count_str_addr); | ||
1311 | fail_pretty_printer = GNUNET_NO; | ||
1312 | fail_addr_to_str = GNUNET_NO; | ||
1313 | |||
1314 | struct IPv4HttpAddress failing_addr; | ||
1315 | |||
1316 | /* Suggesting addresses with wrong size */ | ||
1317 | failing_addr.ipv4_addr = htonl (INADDR_LOOPBACK); | ||
1318 | failing_addr.u_port = htons (0); | ||
1319 | suggest_res = | ||
1320 | api->check_address (api->cls, &failing_addr, | ||
1321 | sizeof (struct IPv6HttpAddress)); | ||
1322 | GNUNET_assert (GNUNET_SYSERR == suggest_res); | ||
1323 | |||
1324 | /* Suggesting addresses with wrong address */ | ||
1325 | failing_addr.ipv4_addr = htonl (0xffc00000); | ||
1326 | failing_addr.u_port = htons (12389); | ||
1327 | suggest_res = api->check_address (api->cls, &failing_addr, 100); | ||
1328 | GNUNET_assert (GNUNET_SYSERR == suggest_res); | ||
1329 | |||
1330 | /* test sending to client */ | ||
1331 | multi_handle = curl_multi_init (); | ||
1332 | |||
1333 | /* Setting up buffers */ | ||
1334 | buffer_in.size = HTTP_BUFFER_SIZE; | ||
1335 | buffer_in.pos = 0; | ||
1336 | buffer_in.len = 0; | ||
1337 | |||
1338 | buffer_out.size = HTTP_BUFFER_SIZE; | ||
1339 | buffer_out.pos = 0; | ||
1340 | buffer_out.len = 0; | ||
1341 | |||
1342 | /* Setting up connection tests */ | ||
1343 | |||
1344 | /* Test: connecting without a peer identification */ | ||
1345 | test_no_ident.test_executed = GNUNET_NO; | ||
1346 | test_no_ident.test_failed = GNUNET_YES; | ||
1347 | |||
1348 | /* Test: connecting with too short peer identification */ | ||
1349 | test_too_short_ident.test_executed = GNUNET_NO; | ||
1350 | test_too_short_ident.test_failed = GNUNET_YES; | ||
1351 | |||
1352 | /* Test: connecting with too long peer identification */ | ||
1353 | test_too_long_ident.test_executed = GNUNET_NO; | ||
1354 | test_too_long_ident.test_failed = GNUNET_YES; | ||
1355 | |||
1356 | /* Test: connecting with valid identification */ | ||
1357 | test_valid_ident.test_executed = GNUNET_NO; | ||
1358 | test_valid_ident.test_failed = GNUNET_YES; | ||
1359 | |||
1360 | test_addr = | ||
1361 | (char *) api->address_to_string (api->cls, addr_head->addr, | ||
1362 | addr_head->addrlen); | ||
1363 | |||
1364 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Phase 0\n\n")); | ||
1365 | run_connection_tests (0, NULL); | ||
1366 | /* testing finished */ | ||
1367 | } | ||
1368 | |||
1369 | |||
1370 | /** | ||
1371 | * The main function for the transport service. | ||
1372 | * | ||
1373 | * @param argc number of arguments from the command line | ||
1374 | * @param argv command line arguments | ||
1375 | * @return 0 ok, 1 on error | ||
1376 | */ | ||
1377 | int | ||
1378 | main (int argc, char *const *argv) | ||
1379 | { | ||
1380 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1381 | GNUNET_GETOPT_OPTION_END | ||
1382 | }; | ||
1383 | int ret; | ||
1384 | |||
1385 | char *const argv_prog[] = { | ||
1386 | "test_gnunet_transport_plugin_http", | ||
1387 | "-c", | ||
1388 | "test_plugin_transport_data_http.conf", | ||
1389 | "-L", | ||
1390 | #if VERBOSE | ||
1391 | "DEBUG", | ||
1392 | #else | ||
1393 | "WARNING", | ||
1394 | #endif | ||
1395 | NULL | ||
1396 | }; | ||
1397 | GNUNET_log_setup ("test_gnunet_transport_plugin_http", | ||
1398 | #if VERBOSE | ||
1399 | "DEBUG", | ||
1400 | #else | ||
1401 | "WARNING", | ||
1402 | #endif | ||
1403 | NULL); | ||
1404 | |||
1405 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
1406 | |||
1407 | cfg = GNUNET_CONFIGURATION_create (); | ||
1408 | |||
1409 | GNUNET_assert (GNUNET_OK == | ||
1410 | GNUNET_CONFIGURATION_load (cfg, | ||
1411 | "test_plugin_transport_data_http.conf")); | ||
1412 | if (GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "SERVICEHOME")) | ||
1413 | GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME", | ||
1414 | &servicehome); | ||
1415 | GNUNET_DISK_directory_remove (servicehome); | ||
1416 | GNUNET_CONFIGURATION_destroy (cfg); | ||
1417 | |||
1418 | ret = | ||
1419 | (GNUNET_OK == | ||
1420 | GNUNET_PROGRAM_run (5, argv_prog, "test_gnunet_transport_plugin_http", | ||
1421 | "testcase", options, &run, | ||
1422 | NULL)) ? GNUNET_NO : GNUNET_YES; | ||
1423 | |||
1424 | if (servicehome != NULL) | ||
1425 | { | ||
1426 | GNUNET_DISK_directory_remove (servicehome); | ||
1427 | GNUNET_free (servicehome); | ||
1428 | } | ||
1429 | if (ret != GNUNET_OK) | ||
1430 | return 1; | ||
1431 | return fail; | ||
1432 | } | ||
1433 | |||
1434 | /* end of test_gnunet_transport_plugin_http.c */ | ||
diff --git a/src/transport/test_plugin_transport_https.c b/src/transport/test_plugin_transport_https.c deleted file mode 100644 index 1027c2b0f..000000000 --- a/src/transport/test_plugin_transport_https.c +++ /dev/null | |||
@@ -1,1519 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet 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 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet 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 GNUnet; 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 | * @file transport/test_plugin_transport_https.c | ||
22 | * @brief testcase for plugin_transport_https.c | ||
23 | * @author Matthias Wachs | ||
24 | */ | ||
25 | |||
26 | #include "platform.h" | ||
27 | #include "gnunet_constants.h" | ||
28 | #include "gnunet_common.h" | ||
29 | #include "gnunet_getopt_lib.h" | ||
30 | #include "gnunet_hello_lib.h" | ||
31 | #include "gnunet_os_lib.h" | ||
32 | #include "gnunet_peerinfo_service.h" | ||
33 | #include "gnunet_plugin_lib.h" | ||
34 | #include "gnunet_protocols.h" | ||
35 | #include "gnunet_program_lib.h" | ||
36 | #include "gnunet_signatures.h" | ||
37 | #include "gnunet_service_lib.h" | ||
38 | #include "gnunet_crypto_lib.h" | ||
39 | |||
40 | #include "gnunet_transport_plugin.h" | ||
41 | #include "gnunet_statistics_service.h" | ||
42 | #include "transport.h" | ||
43 | #include <curl/curl.h> | ||
44 | |||
45 | #define VERBOSE GNUNET_EXTRA_LOGGING | ||
46 | #define DEBUG_CURL GNUNET_EXTRA_LOGGING | ||
47 | #define HTTP_BUFFER_SIZE 2048 | ||
48 | |||
49 | #define PLUGIN libgnunet_plugin_transport_template | ||
50 | |||
51 | #define PROTOCOL_PREFIX "https" | ||
52 | |||
53 | /** | ||
54 | * How long until we give up on transmitting the message? | ||
55 | */ | ||
56 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) | ||
57 | |||
58 | /** | ||
59 | * Testcase timeout | ||
60 | */ | ||
61 | #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) | ||
62 | |||
63 | /** | ||
64 | * How long between recieve and send? | ||
65 | */ | ||
66 | #define WAIT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1) | ||
67 | |||
68 | |||
69 | |||
70 | /** | ||
71 | * Struct for plugin addresses | ||
72 | */ | ||
73 | struct Plugin_Address | ||
74 | { | ||
75 | /** | ||
76 | * Next field for linked list | ||
77 | */ | ||
78 | struct Plugin_Address *next; | ||
79 | |||
80 | /** | ||
81 | * buffer containing data to send | ||
82 | */ | ||
83 | void *addr; | ||
84 | |||
85 | /** | ||
86 | * amount of data to sent | ||
87 | */ | ||
88 | size_t addrlen; | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * Message to send using http | ||
93 | */ | ||
94 | struct HTTP_Message | ||
95 | { | ||
96 | /** | ||
97 | * buffer | ||
98 | */ | ||
99 | unsigned char buf[HTTP_BUFFER_SIZE]; | ||
100 | |||
101 | /** | ||
102 | * current position in buffer | ||
103 | */ | ||
104 | size_t pos; | ||
105 | |||
106 | /** | ||
107 | * buffer size | ||
108 | */ | ||
109 | size_t size; | ||
110 | |||
111 | /** | ||
112 | * data size | ||
113 | */ | ||
114 | size_t len; | ||
115 | }; | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Struct for plugin addresses | ||
120 | */ | ||
121 | struct HTTP_Transfer | ||
122 | { | ||
123 | /** | ||
124 | * amount of bytes we recieved | ||
125 | */ | ||
126 | size_t data_size; | ||
127 | |||
128 | /** | ||
129 | * buffer for http transfers | ||
130 | */ | ||
131 | unsigned char buf[HTTP_BUFFER_SIZE]; | ||
132 | |||
133 | /** | ||
134 | * buffer size this transfer | ||
135 | */ | ||
136 | size_t size; | ||
137 | |||
138 | /** | ||
139 | * amount of bytes we recieved | ||
140 | */ | ||
141 | size_t pos; | ||
142 | |||
143 | /** | ||
144 | * HTTP Header result for transfer | ||
145 | */ | ||
146 | unsigned int http_result_code; | ||
147 | |||
148 | /** | ||
149 | * did the test fail? | ||
150 | */ | ||
151 | unsigned int test_failed; | ||
152 | |||
153 | /** | ||
154 | * was this test already executed? | ||
155 | */ | ||
156 | unsigned int test_executed; | ||
157 | }; | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Network format for IPv4 addresses. | ||
162 | */ | ||
163 | struct IPv4HttpAddress | ||
164 | { | ||
165 | struct IPv4HttpAddress *next; | ||
166 | |||
167 | struct IPv4HttpAddress *prev; | ||
168 | |||
169 | /** | ||
170 | * IPv4 address, in network byte order. | ||
171 | */ | ||
172 | uint32_t ipv4_addr GNUNET_PACKED; | ||
173 | |||
174 | /** | ||
175 | * Port number, in network byte order. | ||
176 | */ | ||
177 | uint16_t u_port GNUNET_PACKED; | ||
178 | |||
179 | }; | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Network format for IPv6 addresses. | ||
184 | */ | ||
185 | struct IPv6HttpAddress | ||
186 | { | ||
187 | struct IPv6HttpAddress *next; | ||
188 | |||
189 | struct IPv6HttpAddress *prev; | ||
190 | |||
191 | /** | ||
192 | * IPv6 address. | ||
193 | */ | ||
194 | struct in6_addr ipv6_addr GNUNET_PACKED; | ||
195 | |||
196 | /** | ||
197 | * Port number, in network byte order. | ||
198 | */ | ||
199 | uint16_t u6_port GNUNET_PACKED; | ||
200 | |||
201 | }; | ||
202 | |||
203 | /** | ||
204 | * Our public key. | ||
205 | */ | ||
206 | /* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */ | ||
207 | |||
208 | /** | ||
209 | * Our public key. | ||
210 | */ | ||
211 | static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; | ||
212 | |||
213 | /** | ||
214 | * Our identity. | ||
215 | */ | ||
216 | static struct GNUNET_PeerIdentity my_identity; | ||
217 | |||
218 | /** | ||
219 | * Our private key. | ||
220 | */ | ||
221 | static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key; | ||
222 | |||
223 | /** | ||
224 | * Peer's port | ||
225 | */ | ||
226 | static long long unsigned int port; | ||
227 | |||
228 | /** | ||
229 | * Peer's addr | ||
230 | */ | ||
231 | static char *test_addr; | ||
232 | |||
233 | /** | ||
234 | * Our statistics handle. | ||
235 | */ | ||
236 | struct GNUNET_STATISTICS_Handle *stats; | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Our configuration. | ||
241 | */ | ||
242 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
243 | |||
244 | /** | ||
245 | * Number of neighbours we'd like to have. | ||
246 | */ | ||
247 | static uint32_t max_connect_per_transport; | ||
248 | |||
249 | /** | ||
250 | * Environment for this plugin. | ||
251 | */ | ||
252 | static struct GNUNET_TRANSPORT_PluginEnvironment env; | ||
253 | |||
254 | /** | ||
255 | *handle for the api provided by this plugin | ||
256 | */ | ||
257 | static struct GNUNET_TRANSPORT_PluginFunctions *api; | ||
258 | |||
259 | /** | ||
260 | * ID of the task controlling the testcase timeout | ||
261 | */ | ||
262 | static GNUNET_SCHEDULER_TaskIdentifier ti_timeout; | ||
263 | |||
264 | static GNUNET_SCHEDULER_TaskIdentifier ti_send; | ||
265 | |||
266 | //const struct GNUNET_PeerIdentity * p; | ||
267 | |||
268 | /** | ||
269 | * buffer for data to send | ||
270 | */ | ||
271 | static struct HTTP_Message buffer_out; | ||
272 | |||
273 | /** | ||
274 | * buffer for data to recieve | ||
275 | */ | ||
276 | static struct HTTP_Message buffer_in; | ||
277 | |||
278 | |||
279 | struct Plugin_Address *addr_head; | ||
280 | |||
281 | /** | ||
282 | * Did the test pass or fail? | ||
283 | */ | ||
284 | static int fail_notify_address; | ||
285 | |||
286 | /** | ||
287 | * Did the test pass or fail? | ||
288 | */ | ||
289 | static int fail_notify_address_count; | ||
290 | |||
291 | /** | ||
292 | * Did the test pass or fail? | ||
293 | */ | ||
294 | static int fail_pretty_printer; | ||
295 | |||
296 | /** | ||
297 | * Did the test pass or fail? | ||
298 | */ | ||
299 | static int fail_pretty_printer_count; | ||
300 | |||
301 | /** | ||
302 | * Did the test pass or fail? | ||
303 | */ | ||
304 | static int fail_addr_to_str; | ||
305 | |||
306 | /** | ||
307 | * No. of msgs transmitted successfully to local addresses | ||
308 | */ | ||
309 | static int fail_msgs_transmited_to_local_addrs; | ||
310 | |||
311 | /** | ||
312 | * Test: transmit msg of max. size | ||
313 | */ | ||
314 | static int fail_msg_transmited_bigger_max_size; | ||
315 | |||
316 | /** | ||
317 | * Test: transmit msg of max. size | ||
318 | */ | ||
319 | static int fail_msg_transmited_max_size; | ||
320 | |||
321 | /** | ||
322 | * Test: transmit 2 msgs. in in send operation | ||
323 | */ | ||
324 | static int fail_multiple_msgs_in_transmission; | ||
325 | |||
326 | /** | ||
327 | * Test: connect to peer without peer identification | ||
328 | */ | ||
329 | static struct HTTP_Transfer test_no_ident; | ||
330 | |||
331 | /** | ||
332 | * Test: connect to peer without peer identification | ||
333 | */ | ||
334 | static struct HTTP_Transfer test_too_short_ident; | ||
335 | |||
336 | /** | ||
337 | * Test: connect to peer without peer identification | ||
338 | */ | ||
339 | static struct HTTP_Transfer test_too_long_ident; | ||
340 | |||
341 | /** | ||
342 | * Test: connect to peer with valid peer identification | ||
343 | */ | ||
344 | static struct HTTP_Transfer test_valid_ident; | ||
345 | |||
346 | /** | ||
347 | * Test: session selection, use any existing | ||
348 | */ | ||
349 | static int fail_session_selection_any; | ||
350 | |||
351 | /** | ||
352 | * Test: session selection, use existing inbound session | ||
353 | */ | ||
354 | static int fail_session_selection_session; | ||
355 | |||
356 | /** | ||
357 | * Test: session selection, use existing inbound session | ||
358 | * max message, not fitting in send & recv buffers at one time | ||
359 | */ | ||
360 | static int fail_session_selection_session_big; | ||
361 | |||
362 | /** | ||
363 | * Test: session selection, use reliable existing | ||
364 | */ | ||
365 | static int fail_session_selection_reliable; | ||
366 | |||
367 | /** | ||
368 | * Did the test pass or fail? | ||
369 | */ | ||
370 | static int fail; | ||
371 | |||
372 | /** | ||
373 | * Number of local addresses | ||
374 | */ | ||
375 | static unsigned int count_str_addr; | ||
376 | |||
377 | CURL *curl_handle; | ||
378 | |||
379 | /** | ||
380 | * cURL Multihandle | ||
381 | */ | ||
382 | static CURLM *multi_handle; | ||
383 | |||
384 | /** | ||
385 | * The task sending data | ||
386 | */ | ||
387 | static GNUNET_SCHEDULER_TaskIdentifier http_task_send; | ||
388 | |||
389 | |||
390 | static char *key_file; | ||
391 | static char *cert_file; | ||
392 | |||
393 | static char *servicehome; | ||
394 | |||
395 | /** | ||
396 | * Shutdown testcase | ||
397 | */ | ||
398 | static void | ||
399 | shutdown_clean () | ||
400 | { | ||
401 | struct Plugin_Address *tmp; | ||
402 | |||
403 | /* Evaluate results */ | ||
404 | fail = 0; | ||
405 | if ((fail_notify_address == GNUNET_YES) || (fail_pretty_printer == GNUNET_YES) | ||
406 | || (fail_addr_to_str == GNUNET_YES)) | ||
407 | { | ||
408 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
409 | _("Phase 0: Test plugin functions failed\n")); | ||
410 | fail = 1; | ||
411 | } | ||
412 | if ((test_no_ident.test_failed == GNUNET_YES) || | ||
413 | (test_too_short_ident.test_failed == GNUNET_YES) || | ||
414 | (test_too_long_ident.test_failed == GNUNET_YES) || | ||
415 | (test_valid_ident.test_failed == GNUNET_YES)) | ||
416 | { | ||
417 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
418 | _("Phase 1: Test connect with wrong data failed\n")); | ||
419 | fail = 1; | ||
420 | } | ||
421 | if ((fail_session_selection_any != GNUNET_NO) || | ||
422 | (fail_session_selection_reliable != GNUNET_NO) || | ||
423 | (fail_session_selection_session != GNUNET_NO) || | ||
424 | (fail_session_selection_session_big != GNUNET_NO)) | ||
425 | { | ||
426 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
427 | _("Phase 2: Test session selection failed\n")); | ||
428 | fail = 1; | ||
429 | } | ||
430 | if ((fail_msgs_transmited_to_local_addrs != count_str_addr) || | ||
431 | (fail_multiple_msgs_in_transmission != 2) || | ||
432 | (fail_msg_transmited_max_size == GNUNET_YES)) | ||
433 | { | ||
434 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
435 | _("Phase 3: Test sending with plugin failed\n")); | ||
436 | fail = 1; | ||
437 | } | ||
438 | if (fail != 1) | ||
439 | { | ||
440 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All tests successful\n"); | ||
441 | } | ||
442 | |||
443 | api->disconnect (api->cls, &my_identity); | ||
444 | |||
445 | curl_multi_cleanup (multi_handle); | ||
446 | |||
447 | if (NULL != curl_handle) | ||
448 | curl_easy_cleanup (curl_handle); | ||
449 | |||
450 | /* cleaning addresses */ | ||
451 | while (addr_head != NULL) | ||
452 | { | ||
453 | tmp = addr_head->next; | ||
454 | GNUNET_free (addr_head->addr); | ||
455 | GNUNET_free (addr_head); | ||
456 | addr_head = tmp; | ||
457 | } | ||
458 | |||
459 | if (ti_send != GNUNET_SCHEDULER_NO_TASK) | ||
460 | { | ||
461 | GNUNET_SCHEDULER_cancel (ti_send); | ||
462 | ti_send = GNUNET_SCHEDULER_NO_TASK; | ||
463 | } | ||
464 | |||
465 | if (http_task_send != GNUNET_SCHEDULER_NO_TASK) | ||
466 | { | ||
467 | GNUNET_SCHEDULER_cancel (http_task_send); | ||
468 | http_task_send = GNUNET_SCHEDULER_NO_TASK; | ||
469 | } | ||
470 | |||
471 | if (ti_timeout != GNUNET_SCHEDULER_NO_TASK) | ||
472 | { | ||
473 | GNUNET_SCHEDULER_cancel (ti_timeout); | ||
474 | ti_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
475 | } | ||
476 | |||
477 | GNUNET_free (test_addr); | ||
478 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unloading https plugin\n"); | ||
479 | GNUNET_assert (NULL == | ||
480 | GNUNET_PLUGIN_unload | ||
481 | ("libgnunet_gnunet_transport_plugin.https", api)); | ||
482 | |||
483 | GNUNET_SCHEDULER_shutdown (); | ||
484 | GNUNET_DISK_directory_remove ("/tmp/test_gnunet_transport_plugin.http"); | ||
485 | |||
486 | struct stat sbuf; | ||
487 | |||
488 | if (0 == stat (cert_file, &sbuf)) | ||
489 | { | ||
490 | if (0 == remove (cert_file)) | ||
491 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
492 | "Successfully removed existing certificate file `%s'\n", | ||
493 | cert_file); | ||
494 | else | ||
495 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove certfile `%s'\n", | ||
496 | cert_file); | ||
497 | } | ||
498 | |||
499 | if (0 == stat (key_file, &sbuf)) | ||
500 | { | ||
501 | if (0 == remove (key_file)) | ||
502 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
503 | "Successfully removed private key file `%s'\n", key_file); | ||
504 | else | ||
505 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to private key file `%s'\n", | ||
506 | key_file); | ||
507 | } | ||
508 | |||
509 | GNUNET_free (key_file); | ||
510 | GNUNET_free (cert_file); | ||
511 | |||
512 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exiting testcase\n"); | ||
513 | |||
514 | if (servicehome != NULL) | ||
515 | { | ||
516 | GNUNET_DISK_directory_remove (servicehome); | ||
517 | GNUNET_free (servicehome); | ||
518 | } | ||
519 | |||
520 | exit (fail); | ||
521 | return; | ||
522 | } | ||
523 | |||
524 | |||
525 | /** | ||
526 | * Continuation called after plugin send message | ||
527 | * @cls closure | ||
528 | * @target target | ||
529 | * @result GNUNET_OK or GNUNET_SYSERR | ||
530 | */ | ||
531 | |||
532 | static void | ||
533 | task_send_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result) | ||
534 | { | ||
535 | if ((cls == &fail_msg_transmited_bigger_max_size) && | ||
536 | (result == GNUNET_SYSERR)) | ||
537 | { | ||
538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
539 | "Message bigger max msg size was not sent!\n"); | ||
540 | fail_msg_transmited_bigger_max_size = GNUNET_NO; | ||
541 | return; | ||
542 | } | ||
543 | |||
544 | if ((cls == &fail_msg_transmited_max_size) && (result == GNUNET_OK)) | ||
545 | { | ||
546 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
547 | "Message with max msg size succesfully sent!\n", | ||
548 | fail_msgs_transmited_to_local_addrs); | ||
549 | fail_msg_transmited_max_size = GNUNET_NO; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | |||
554 | static void | ||
555 | run_connection_tests (int phase, void *cls); | ||
556 | |||
557 | /** | ||
558 | * Recieves messages from plugin, in real world transport | ||
559 | */ | ||
560 | static struct GNUNET_TIME_Relative | ||
561 | receive (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
562 | const struct GNUNET_MessageHeader *message, | ||
563 | const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count, | ||
564 | struct Session *session, const char *sender_address, | ||
565 | uint16_t sender_address_len) | ||
566 | { | ||
567 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
568 | "Testcase recieved new message from peer `%s' with type %u and length %u, session %X\n", | ||
569 | GNUNET_i2s (peer), ntohs (message->type), ntohs (message->size), | ||
570 | session); | ||
571 | |||
572 | if ((ntohs (message->type) >= 10) && (ntohs (message->type) < 20)) | ||
573 | { | ||
574 | fail_msgs_transmited_to_local_addrs++; | ||
575 | if (fail_msgs_transmited_to_local_addrs == count_str_addr) | ||
576 | run_connection_tests (2, session); | ||
577 | } | ||
578 | |||
579 | |||
580 | if ((ntohs (message->type) == 20)) | ||
581 | { | ||
582 | fail_session_selection_reliable = GNUNET_NO; | ||
583 | } | ||
584 | |||
585 | if ((ntohs (message->type) == 21)) | ||
586 | { | ||
587 | fail_session_selection_any = GNUNET_NO; | ||
588 | } | ||
589 | if ((ntohs (message->type) == 22)) | ||
590 | { | ||
591 | fail_session_selection_session = GNUNET_NO; | ||
592 | } | ||
593 | |||
594 | if ((ntohs (message->type) == 23)) | ||
595 | { | ||
596 | fail_session_selection_session_big = GNUNET_NO; | ||
597 | run_connection_tests (3, NULL); | ||
598 | } | ||
599 | |||
600 | if ((ntohs (message->type) == 30) || (ntohs (message->type) == 31)) | ||
601 | { | ||
602 | fail_multiple_msgs_in_transmission++; | ||
603 | } | ||
604 | |||
605 | if ((ntohs (message->type) == 32) && | ||
606 | (ntohs (message->size) == GNUNET_SERVER_MAX_MESSAGE_SIZE - 1)) | ||
607 | { | ||
608 | fail_msg_transmited_max_size = GNUNET_NO; | ||
609 | shutdown_clean (); | ||
610 | } | ||
611 | |||
612 | return GNUNET_TIME_UNIT_ZERO; | ||
613 | } | ||
614 | |||
615 | static size_t | ||
616 | send_function (void *stream, size_t size, size_t nmemb, void *ptr) | ||
617 | { | ||
618 | unsigned int len; | ||
619 | |||
620 | len = buffer_out.len; | ||
621 | |||
622 | if ((buffer_out.pos == len) || (len > (size * nmemb))) | ||
623 | return 0; | ||
624 | memcpy (stream, buffer_out.buf, len); | ||
625 | buffer_out.pos = len; | ||
626 | return len; | ||
627 | } | ||
628 | |||
629 | static size_t | ||
630 | recv_function (void *ptr, size_t size, size_t nmemb, void *ctx) | ||
631 | { | ||
632 | |||
633 | if (buffer_in.pos + size * nmemb > buffer_in.size) | ||
634 | return 0; /* overflow */ | ||
635 | |||
636 | buffer_in.len = size * nmemb; | ||
637 | memcpy (&buffer_in.buf[buffer_in.pos], ptr, size * nmemb); | ||
638 | buffer_in.pos += size * nmemb; | ||
639 | buffer_in.len = buffer_in.pos; | ||
640 | buffer_in.buf[buffer_in.pos] = '\0'; | ||
641 | return buffer_in.pos; | ||
642 | } | ||
643 | |||
644 | static size_t | ||
645 | header_function (void *ptr, size_t size, size_t nmemb, void *stream) | ||
646 | { | ||
647 | struct HTTP_Transfer *res = (struct HTTP_Transfer *) stream; | ||
648 | char *tmp; | ||
649 | unsigned int len = size * nmemb; | ||
650 | |||
651 | tmp = GNUNET_malloc (len + 1); | ||
652 | memcpy (tmp, ptr, len); | ||
653 | if (tmp[len - 2] == 13) | ||
654 | tmp[len - 2] = '\0'; | ||
655 | #if DEBUG_CURL | ||
656 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: `%s'\n", tmp); | ||
657 | #endif | ||
658 | if (0 == strcmp (tmp, "HTTP/1.1 100 Continue")) | ||
659 | { | ||
660 | res->http_result_code = 100; | ||
661 | } | ||
662 | if (0 == strcmp (tmp, "HTTP/1.1 200 OK")) | ||
663 | { | ||
664 | res->http_result_code = 200; | ||
665 | } | ||
666 | if (0 == strcmp (tmp, "HTTP/1.1 400 Bad Request")) | ||
667 | { | ||
668 | res->http_result_code = 400; | ||
669 | } | ||
670 | if (0 == strcmp (tmp, "HTTP/1.1 404 Not Found")) | ||
671 | { | ||
672 | res->http_result_code = 404; | ||
673 | } | ||
674 | if (0 == strcmp (tmp, "HTTP/1.1 413 Request entity too large")) | ||
675 | { | ||
676 | res->http_result_code = 413; | ||
677 | } | ||
678 | |||
679 | GNUNET_free (tmp); | ||
680 | return size * nmemb; | ||
681 | } | ||
682 | |||
683 | static size_t | ||
684 | send_prepare (struct HTTP_Transfer *result); | ||
685 | |||
686 | |||
687 | |||
688 | static void | ||
689 | send_execute (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
690 | { | ||
691 | struct HTTP_Transfer *res; | ||
692 | |||
693 | int running; | ||
694 | struct CURLMsg *msg; | ||
695 | CURLMcode mret; | ||
696 | |||
697 | res = (struct HTTP_Transfer *) cls; | ||
698 | http_task_send = GNUNET_SCHEDULER_NO_TASK; | ||
699 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
700 | return; | ||
701 | |||
702 | do | ||
703 | { | ||
704 | running = 0; | ||
705 | mret = curl_multi_perform (multi_handle, &running); | ||
706 | if (running == 0) | ||
707 | { | ||
708 | do | ||
709 | { | ||
710 | |||
711 | msg = curl_multi_info_read (multi_handle, &running); | ||
712 | if (msg == NULL) | ||
713 | break; | ||
714 | /* get session for affected curl handle */ | ||
715 | //cs = find_session_by_curlhandle (msg->easy_handle); | ||
716 | //GNUNET_assert ( cs != NULL ); | ||
717 | switch (msg->msg) | ||
718 | { | ||
719 | |||
720 | case CURLMSG_DONE: | ||
721 | if ((msg->data.result != CURLE_OK) && | ||
722 | (msg->data.result != CURLE_GOT_NOTHING)) | ||
723 | { | ||
724 | |||
725 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
726 | _("curl failed for `%s' at %s:%d: `%s'\n"), | ||
727 | "curl_multi_perform", __FILE__, __LINE__, | ||
728 | curl_easy_strerror (msg->data.result)); | ||
729 | /* sending msg failed */ | ||
730 | curl_easy_cleanup (curl_handle); | ||
731 | curl_handle = NULL; | ||
732 | |||
733 | run_connection_tests (0, NULL); | ||
734 | } | ||
735 | if (res == &test_no_ident) | ||
736 | { | ||
737 | if ((res->http_result_code == 404) && (buffer_in.len == 208)) | ||
738 | { | ||
739 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
740 | "Connecting to peer without any peer identification: test passed\n"); | ||
741 | res->test_failed = GNUNET_NO; | ||
742 | } | ||
743 | else | ||
744 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
745 | _ | ||
746 | ("Connecting to peer without any peer identification: test failed\n")); | ||
747 | } | ||
748 | if (res == &test_too_short_ident) | ||
749 | { | ||
750 | if ((res->http_result_code == 404) && (buffer_in.len == 208)) | ||
751 | { | ||
752 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
753 | "Connecting to peer with too short peer identification: test passed\n"); | ||
754 | res->test_failed = GNUNET_NO; | ||
755 | } | ||
756 | else | ||
757 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
758 | _ | ||
759 | ("Connecting to peer with too short peer identification: test failed\n")); | ||
760 | } | ||
761 | if (res == &test_too_long_ident) | ||
762 | { | ||
763 | if ((res->http_result_code == 404) && (buffer_in.len == 208)) | ||
764 | { | ||
765 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
766 | "Connecting to peer with too long peer identification: test passed\n"); | ||
767 | res->test_failed = GNUNET_NO; | ||
768 | } | ||
769 | else | ||
770 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
771 | _ | ||
772 | ("Connecting to peer with too long peer identification: test failed\n")); | ||
773 | } | ||
774 | if (res == &test_valid_ident) | ||
775 | { | ||
776 | if ((res->http_result_code == 200)) | ||
777 | { | ||
778 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
779 | "Connecting to peer with valid peer identification: test passed\n"); | ||
780 | res->test_failed = GNUNET_NO; | ||
781 | } | ||
782 | else | ||
783 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
784 | _ | ||
785 | ("Connecting to peer with valid peer identification: test failed\n")); | ||
786 | } | ||
787 | curl_easy_cleanup (curl_handle); | ||
788 | curl_handle = NULL; | ||
789 | if ((res == &test_valid_ident) && (res->test_failed == GNUNET_NO)) | ||
790 | run_connection_tests (1, NULL); | ||
791 | run_connection_tests (0, NULL); | ||
792 | return; | ||
793 | default: | ||
794 | break; | ||
795 | } | ||
796 | |||
797 | } | ||
798 | while ((running > 0)); | ||
799 | } | ||
800 | } | ||
801 | while (mret == CURLM_CALL_MULTI_PERFORM); | ||
802 | send_prepare (cls); | ||
803 | } | ||
804 | |||
805 | /** | ||
806 | * Function setting up file descriptors and scheduling task to run | ||
807 | * @param ses session to send data to | ||
808 | * @return bytes sent to peer | ||
809 | */ | ||
810 | static size_t | ||
811 | send_prepare (struct HTTP_Transfer *result) | ||
812 | { | ||
813 | fd_set rs; | ||
814 | fd_set ws; | ||
815 | fd_set es; | ||
816 | int max; | ||
817 | struct GNUNET_NETWORK_FDSet *grs; | ||
818 | struct GNUNET_NETWORK_FDSet *gws; | ||
819 | long to; | ||
820 | CURLMcode mret; | ||
821 | |||
822 | max = -1; | ||
823 | FD_ZERO (&rs); | ||
824 | FD_ZERO (&ws); | ||
825 | FD_ZERO (&es); | ||
826 | mret = curl_multi_fdset (multi_handle, &rs, &ws, &es, &max); | ||
827 | if (mret != CURLM_OK) | ||
828 | { | ||
829 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), | ||
830 | "curl_multi_fdset", __FILE__, __LINE__, | ||
831 | curl_multi_strerror (mret)); | ||
832 | return -1; | ||
833 | } | ||
834 | mret = curl_multi_timeout (multi_handle, &to); | ||
835 | if (mret != CURLM_OK) | ||
836 | { | ||
837 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"), | ||
838 | "curl_multi_timeout", __FILE__, __LINE__, | ||
839 | curl_multi_strerror (mret)); | ||
840 | return -1; | ||
841 | } | ||
842 | |||
843 | grs = GNUNET_NETWORK_fdset_create (); | ||
844 | gws = GNUNET_NETWORK_fdset_create (); | ||
845 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); | ||
846 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); | ||
847 | http_task_send = | ||
848 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
849 | GNUNET_SCHEDULER_NO_TASK, | ||
850 | GNUNET_TIME_relative_multiply | ||
851 | (GNUNET_TIME_UNIT_SECONDS, 0), grs, gws, | ||
852 | &send_execute, result); | ||
853 | GNUNET_NETWORK_fdset_destroy (gws); | ||
854 | GNUNET_NETWORK_fdset_destroy (grs); | ||
855 | |||
856 | /* FIXME: return bytes REALLY sent */ | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | /** | ||
861 | * function to send data to server | ||
862 | */ | ||
863 | static int | ||
864 | send_data (struct HTTP_Transfer *result, char *url) | ||
865 | { | ||
866 | |||
867 | curl_handle = curl_easy_init (); | ||
868 | if (NULL == curl_handle) | ||
869 | { | ||
870 | printf ("easy_init failed \n"); | ||
871 | return GNUNET_SYSERR; | ||
872 | } | ||
873 | #if DEBUG_CURL | ||
874 | curl_easy_setopt (curl_handle, CURLOPT_VERBOSE, 1L); | ||
875 | #endif | ||
876 | curl_easy_setopt (curl_handle, CURLOPT_URL, url); | ||
877 | curl_easy_setopt (curl_handle, CURLOPT_PUT, 1L); | ||
878 | //curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); | ||
879 | curl_easy_setopt (curl_handle, CURLOPT_SSL_VERIFYPEER, 0); | ||
880 | curl_easy_setopt (curl_handle, CURLOPT_SSL_VERIFYHOST, 0); | ||
881 | curl_easy_setopt (curl_handle, CURLOPT_HEADERFUNCTION, &header_function); | ||
882 | curl_easy_setopt (curl_handle, CURLOPT_WRITEHEADER, result); | ||
883 | curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, &recv_function); | ||
884 | curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, result); | ||
885 | curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &send_function); | ||
886 | curl_easy_setopt (curl_handle, CURLOPT_READDATA, result); | ||
887 | curl_easy_setopt (curl_handle, CURLOPT_INFILESIZE_LARGE, | ||
888 | (curl_off_t) buffer_out.len); | ||
889 | curl_easy_setopt (curl_handle, CURLOPT_TIMEOUT, 30); | ||
890 | curl_easy_setopt (curl_handle, CURLOPT_CONNECTTIMEOUT, 20); | ||
891 | |||
892 | curl_multi_add_handle (multi_handle, curl_handle); | ||
893 | |||
894 | send_prepare (result); | ||
895 | |||
896 | return GNUNET_OK; | ||
897 | } | ||
898 | |||
899 | /** | ||
900 | * Plugin notifies transport (aka testcase) about its addresses | ||
901 | */ | ||
902 | void | ||
903 | notify_address (void *cls, int add_remove, const void *addr, size_t addrlen) | ||
904 | { | ||
905 | char address[INET6_ADDRSTRLEN]; | ||
906 | unsigned int port; | ||
907 | struct Plugin_Address *pl_addr; | ||
908 | struct Plugin_Address *cur; | ||
909 | |||
910 | if (addrlen == (sizeof (struct IPv4HttpAddress))) | ||
911 | { | ||
912 | inet_ntop (AF_INET, (struct in_addr *) addr, address, INET_ADDRSTRLEN); | ||
913 | port = ntohs (((struct IPv4HttpAddress *) addr)->u_port); | ||
914 | } | ||
915 | else if (addrlen == (sizeof (struct IPv6HttpAddress))) | ||
916 | { | ||
917 | inet_ntop (AF_INET6, (struct in6_addr *) addr, address, INET6_ADDRSTRLEN); | ||
918 | port = ntohs (((struct IPv6HttpAddress *) addr)->u6_port); | ||
919 | } | ||
920 | else | ||
921 | { | ||
922 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
923 | _ | ||
924 | ("Unknown address size: ipv6 has %u ipv4 has %u but this has %u\n"), | ||
925 | sizeof (struct IPv6HttpAddress), | ||
926 | sizeof (struct IPv4HttpAddress), addrlen); | ||
927 | return; | ||
928 | } | ||
929 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
930 | _("Transport plugin notification for address: `%s':%u\n"), | ||
931 | address, port); | ||
932 | pl_addr = GNUNET_malloc (sizeof (struct Plugin_Address)); | ||
933 | pl_addr->addrlen = addrlen; | ||
934 | pl_addr->addr = GNUNET_malloc (addrlen); | ||
935 | memcpy (pl_addr->addr, addr, addrlen); | ||
936 | pl_addr->next = NULL; | ||
937 | |||
938 | if (NULL == addr_head) | ||
939 | { | ||
940 | addr_head = pl_addr; | ||
941 | } | ||
942 | else | ||
943 | { | ||
944 | cur = addr_head; | ||
945 | while (NULL != cur->next) | ||
946 | { | ||
947 | cur = cur->next; | ||
948 | } | ||
949 | cur->next = pl_addr; | ||
950 | } | ||
951 | fail_notify_address_count++; | ||
952 | fail_notify_address = GNUNET_NO; | ||
953 | } | ||
954 | |||
955 | static void | ||
956 | plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
957 | struct Session *session) | ||
958 | { | ||
959 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
960 | "Pluging tells me: session %X to peer `%s' ended\n", session, | ||
961 | GNUNET_i2s (peer)); | ||
962 | } | ||
963 | |||
964 | |||
965 | /** | ||
966 | * Setup plugin environment | ||
967 | */ | ||
968 | static void | ||
969 | setup_plugin_environment () | ||
970 | { | ||
971 | env.cfg = cfg; | ||
972 | env.stats = stats; | ||
973 | env.my_identity = &my_identity; | ||
974 | env.cls = &env; | ||
975 | env.receive = &receive; | ||
976 | env.notify_address = ¬ify_address; | ||
977 | env.max_connections = max_connect_per_transport; | ||
978 | env.session_end = &plugin_env_session_end; | ||
979 | } | ||
980 | |||
981 | |||
982 | /** | ||
983 | * Task shutting down testcase if it a timeout occurs | ||
984 | */ | ||
985 | static void | ||
986 | task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
987 | { | ||
988 | ti_timeout = GNUNET_SCHEDULER_NO_TASK; | ||
989 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
990 | return; | ||
991 | |||
992 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n"); | ||
993 | fail = GNUNET_YES; | ||
994 | shutdown_clean (); | ||
995 | return; | ||
996 | } | ||
997 | |||
998 | static void | ||
999 | pretty_printer_cb (void *cls, const char *address) | ||
1000 | { | ||
1001 | if (NULL == address) | ||
1002 | return; | ||
1003 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin returned pretty address: `%s'\n", | ||
1004 | address); | ||
1005 | fail_pretty_printer_count++; | ||
1006 | } | ||
1007 | |||
1008 | /** | ||
1009 | * Runs every single test to test the plugin | ||
1010 | */ | ||
1011 | static void | ||
1012 | run_connection_tests (int phase, void *cls) | ||
1013 | { | ||
1014 | struct GNUNET_MessageHeader *msg; | ||
1015 | unsigned int size; | ||
1016 | |||
1017 | if (phase == 0) | ||
1018 | { | ||
1019 | char *host_str = NULL; | ||
1020 | |||
1021 | /* resetting buffers */ | ||
1022 | buffer_in.size = HTTP_BUFFER_SIZE; | ||
1023 | buffer_in.pos = 0; | ||
1024 | buffer_in.len = 0; | ||
1025 | |||
1026 | buffer_out.size = HTTP_BUFFER_SIZE; | ||
1027 | buffer_out.pos = 0; | ||
1028 | buffer_out.len = 0; | ||
1029 | |||
1030 | if (test_no_ident.test_executed == GNUNET_NO) | ||
1031 | { | ||
1032 | /* Connecting to peer without identification */ | ||
1033 | char *ident = ""; | ||
1034 | |||
1035 | GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr, | ||
1036 | ident); | ||
1037 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1038 | _("Connecting to peer without any peer identification.\n")); | ||
1039 | test_no_ident.test_executed = GNUNET_YES; | ||
1040 | send_data (&test_no_ident, host_str); | ||
1041 | GNUNET_free (host_str); | ||
1042 | return; | ||
1043 | } | ||
1044 | if (test_too_short_ident.test_executed == GNUNET_NO) | ||
1045 | { | ||
1046 | char *ident = "AAAAAAAAAA"; | ||
1047 | |||
1048 | /* Connecting to peer with too short identification */ | ||
1049 | GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr, | ||
1050 | ident); | ||
1051 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1052 | _ | ||
1053 | ("Connecting to peer with too short peer identification.\n")); | ||
1054 | test_too_short_ident.test_executed = GNUNET_YES; | ||
1055 | send_data (&test_too_short_ident, host_str); | ||
1056 | GNUNET_free (host_str); | ||
1057 | return; | ||
1058 | } | ||
1059 | |||
1060 | if (test_too_long_ident.test_executed == GNUNET_NO) | ||
1061 | { | ||
1062 | char *ident = | ||
1063 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; | ||
1064 | |||
1065 | /* Connecting to peer with too long identification */ | ||
1066 | GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr, | ||
1067 | ident); | ||
1068 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1069 | _("Connecting to peer with too long peer identification.\n")); | ||
1070 | test_too_long_ident.test_executed = GNUNET_YES; | ||
1071 | send_data (&test_too_long_ident, host_str); | ||
1072 | GNUNET_free (host_str); | ||
1073 | return; | ||
1074 | } | ||
1075 | if (test_valid_ident.test_executed == GNUNET_NO) | ||
1076 | { | ||
1077 | struct GNUNET_CRYPTO_HashAsciiEncoded ident; | ||
1078 | |||
1079 | GNUNET_CRYPTO_hash_to_enc (&my_identity.hashPubKey, &ident); | ||
1080 | GNUNET_asprintf (&host_str, "%s://%s/%s%s", PROTOCOL_PREFIX, test_addr, | ||
1081 | (char *) &ident, ";0"); | ||
1082 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1083 | _("Connecting to peer with valid peer identification.\n")); | ||
1084 | test_valid_ident.test_executed = GNUNET_YES; | ||
1085 | send_data (&test_valid_ident, host_str); | ||
1086 | GNUNET_free (host_str); | ||
1087 | return; | ||
1088 | } | ||
1089 | } | ||
1090 | if (phase == 1) | ||
1091 | { | ||
1092 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1093 | _("\nPhase 1: transmit data to all suggested addresses\n\n")); | ||
1094 | /* Using one of the addresses the plugin proposed */ | ||
1095 | GNUNET_assert (addr_head->addr != NULL); | ||
1096 | |||
1097 | struct Plugin_Address *tmp_addr; | ||
1098 | struct GNUNET_MessageHeader msg; | ||
1099 | char *tmp = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader)); | ||
1100 | char address[INET6_ADDRSTRLEN]; | ||
1101 | unsigned int port; | ||
1102 | unsigned int type = 10; | ||
1103 | |||
1104 | msg.size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
1105 | tmp_addr = addr_head; | ||
1106 | /* send a message to all addresses advertised by plugin */ | ||
1107 | |||
1108 | int count = 0; | ||
1109 | |||
1110 | while (tmp_addr != NULL) | ||
1111 | { | ||
1112 | if (tmp_addr->addrlen == (sizeof (struct IPv4HttpAddress))) | ||
1113 | { | ||
1114 | inet_ntop (AF_INET, (struct in_addr *) tmp_addr->addr, address, | ||
1115 | INET_ADDRSTRLEN); | ||
1116 | port = ntohs (((struct IPv4HttpAddress *) tmp_addr->addr)->u_port); | ||
1117 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1118 | "Sending message to addres no. %u: `%s':%u\n", count, | ||
1119 | address, port); | ||
1120 | } | ||
1121 | if (tmp_addr->addrlen == (sizeof (struct IPv6HttpAddress))) | ||
1122 | { | ||
1123 | inet_ntop (AF_INET6, (struct in6_addr *) tmp_addr->addr, address, | ||
1124 | INET6_ADDRSTRLEN); | ||
1125 | port = ntohs (((struct IPv6HttpAddress *) tmp_addr->addr)->u6_port); | ||
1126 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1127 | "Sending message to addres no. %u: `%s':%u\n", count, | ||
1128 | address, port); | ||
1129 | } | ||
1130 | msg.type = htons (type); | ||
1131 | memcpy (tmp, &msg, sizeof (struct GNUNET_MessageHeader)); | ||
1132 | api->send (api->cls, &my_identity, tmp, | ||
1133 | sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL, | ||
1134 | tmp_addr->addr, tmp_addr->addrlen, GNUNET_YES, &task_send_cont, | ||
1135 | &fail_msgs_transmited_to_local_addrs); | ||
1136 | tmp_addr = tmp_addr->next; | ||
1137 | |||
1138 | count++; | ||
1139 | type++; | ||
1140 | } | ||
1141 | GNUNET_free (tmp); | ||
1142 | return; | ||
1143 | } | ||
1144 | |||
1145 | if (phase == 2) | ||
1146 | { | ||
1147 | struct Session *session = cls; | ||
1148 | |||
1149 | msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader)); | ||
1150 | |||
1151 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("\nPhase 2: session selection\n\n")); | ||
1152 | size = sizeof (struct GNUNET_MessageHeader); | ||
1153 | msg->size = htons (size); | ||
1154 | msg->type = htons (20); | ||
1155 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1156 | NULL, NULL, 0, GNUNET_NO, &task_send_cont, NULL); | ||
1157 | |||
1158 | msg->type = htons (21); | ||
1159 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1160 | NULL, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL); | ||
1161 | |||
1162 | /* answer on session */ | ||
1163 | size = sizeof (struct GNUNET_MessageHeader); | ||
1164 | msg->size = htons (size); | ||
1165 | msg->type = htons (22); | ||
1166 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1167 | session, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL); | ||
1168 | |||
1169 | GNUNET_free (msg); | ||
1170 | |||
1171 | /* answer on session with big message not fitting in mhd send buffer */ | ||
1172 | size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1; | ||
1173 | msg = GNUNET_malloc (size); | ||
1174 | msg->size = htons (size); | ||
1175 | msg->type = htons (23); | ||
1176 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1177 | session, NULL, 0, GNUNET_NO, &task_send_cont, NULL); | ||
1178 | GNUNET_free (msg); | ||
1179 | return; | ||
1180 | } | ||
1181 | |||
1182 | if (phase == 3) | ||
1183 | { | ||
1184 | |||
1185 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1186 | _ | ||
1187 | ("\nPhase 3: send multiple or big messages after disconnect\n\n")); | ||
1188 | /* disconnect from peer, so new connections are created */ | ||
1189 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect from peer: `%s'\n", | ||
1190 | GNUNET_i2s (&my_identity)); | ||
1191 | api->disconnect (api->cls, &my_identity); | ||
1192 | |||
1193 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Phase 3: sending messages\n")); | ||
1194 | /* send a multiple GNUNET_messages at a time */ | ||
1195 | size = 2 * sizeof (struct GNUNET_MessageHeader); | ||
1196 | msg = GNUNET_malloc (2 * size); | ||
1197 | msg->size = htons (size); | ||
1198 | msg->type = htons (30); | ||
1199 | struct GNUNET_MessageHeader *msg2 = &msg[2]; | ||
1200 | |||
1201 | msg2->size = htons (2 * sizeof (struct GNUNET_MessageHeader)); | ||
1202 | msg2->type = htons (31); | ||
1203 | api->send (api->cls, &my_identity, (const char *) msg, | ||
1204 | 4 * sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL, | ||
1205 | addr_head->addr, addr_head->addrlen, GNUNET_NO, &task_send_cont, | ||
1206 | &fail_multiple_msgs_in_transmission); | ||
1207 | GNUNET_free (msg); | ||
1208 | /* send a message with size GNUNET_SERVER_MAX_MESSAGE_SIZE-1 */ | ||
1209 | |||
1210 | size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1; | ||
1211 | msg = GNUNET_malloc (size); | ||
1212 | msg->size = htons (size); | ||
1213 | msg->type = htons (32); | ||
1214 | api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT, | ||
1215 | NULL, addr_head->addr, addr_head->addrlen, GNUNET_NO, | ||
1216 | &task_send_cont, &fail_msg_transmited_max_size); | ||
1217 | GNUNET_free (msg); | ||
1218 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more tests to run\n"); | ||
1219 | } | ||
1220 | } | ||
1221 | |||
1222 | |||
1223 | /** | ||
1224 | * Runs the test. | ||
1225 | * | ||
1226 | * @param cls closure | ||
1227 | * @param c configuration to use | ||
1228 | */ | ||
1229 | static void | ||
1230 | run (void *cls, char *const *args, const char *cfgfile, | ||
1231 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
1232 | { | ||
1233 | char *libname; | ||
1234 | |||
1235 | cfg = c; | ||
1236 | char *keyfile; | ||
1237 | unsigned long long tneigh; | ||
1238 | struct Plugin_Address *cur; | ||
1239 | const char *addr_str; | ||
1240 | struct stat sbuf; | ||
1241 | unsigned int suggest_res; | ||
1242 | |||
1243 | fail_pretty_printer = GNUNET_YES; | ||
1244 | fail_notify_address = GNUNET_YES; | ||
1245 | fail_addr_to_str = GNUNET_YES; | ||
1246 | fail_msgs_transmited_to_local_addrs = 0; | ||
1247 | fail_msg_transmited_max_size = GNUNET_YES; | ||
1248 | fail_multiple_msgs_in_transmission = 0; | ||
1249 | fail_session_selection_reliable = GNUNET_YES; | ||
1250 | fail_session_selection_reliable = GNUNET_YES; | ||
1251 | fail_session_selection_session = GNUNET_YES; | ||
1252 | fail_session_selection_session_big = GNUNET_YES; | ||
1253 | |||
1254 | addr_head = NULL; | ||
1255 | count_str_addr = 0; | ||
1256 | /* parse configuration */ | ||
1257 | if (GNUNET_CONFIGURATION_have_value (c, "PATHS", "SERVICEHOME")) | ||
1258 | GNUNET_CONFIGURATION_get_value_string (c, "PATHS", "SERVICEHOME", | ||
1259 | &servicehome); | ||
1260 | |||
1261 | |||
1262 | if ((GNUNET_OK != | ||
1263 | GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", "NEIGHBOUR_LIMIT", | ||
1264 | &tneigh)) || | ||
1265 | (GNUNET_OK != | ||
1266 | GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY", | ||
1267 | &keyfile))) | ||
1268 | { | ||
1269 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1270 | _ | ||
1271 | ("Transport service is lacking key configuration settings. Exiting.\n")); | ||
1272 | GNUNET_SCHEDULER_shutdown (); | ||
1273 | fail = 1; | ||
1274 | return; | ||
1275 | } | ||
1276 | |||
1277 | if ((GNUNET_OK != | ||
1278 | GNUNET_CONFIGURATION_get_value_number (cfg, "transport-https", "PORT", | ||
1279 | &port)) || (port > 65535) || | ||
1280 | (port == 0)) | ||
1281 | { | ||
1282 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "https", | ||
1283 | _ | ||
1284 | ("Require valid port number for transport plugin `%s' in configuration!\n"), | ||
1285 | "transport-http"); | ||
1286 | } | ||
1287 | |||
1288 | /* Get private key file from config */ | ||
1289 | if (GNUNET_CONFIGURATION_have_value (cfg, "transport-https", "KEY_FILE")) | ||
1290 | { | ||
1291 | GNUNET_CONFIGURATION_get_value_string (cfg, "transport-https", "KEY_FILE", | ||
1292 | &key_file); | ||
1293 | } | ||
1294 | if (key_file == NULL) | ||
1295 | GNUNET_asprintf (&key_file, "https.key"); | ||
1296 | |||
1297 | if (0 == stat (key_file, &sbuf)) | ||
1298 | { | ||
1299 | if (0 == remove (key_file)) | ||
1300 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1301 | "Successfully removed existing private key file `%s'\n", | ||
1302 | key_file); | ||
1303 | else | ||
1304 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1305 | "Failed to remove private key file `%s'\n", key_file); | ||
1306 | } | ||
1307 | |||
1308 | /* Get private key file from config */ | ||
1309 | if (GNUNET_CONFIGURATION_have_value (cfg, "transport-https", "CERT_FILE")) | ||
1310 | { | ||
1311 | GNUNET_CONFIGURATION_get_value_string (cfg, "transport-https", "CERT_FILE", | ||
1312 | &cert_file); | ||
1313 | } | ||
1314 | if (cert_file == NULL) | ||
1315 | GNUNET_asprintf (&cert_file, "https.cert"); | ||
1316 | |||
1317 | if (0 == stat (cert_file, &sbuf)) | ||
1318 | { | ||
1319 | if (0 == remove (cert_file)) | ||
1320 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1321 | "Successfully removed existing certificate file `%s'\n", | ||
1322 | cert_file); | ||
1323 | else | ||
1324 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1325 | "Failed to remove existing certificate file `%s'\n", | ||
1326 | cert_file); | ||
1327 | } | ||
1328 | |||
1329 | max_connect_per_transport = (uint32_t) tneigh; | ||
1330 | my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); | ||
1331 | GNUNET_free (keyfile); | ||
1332 | if (my_private_key == NULL) | ||
1333 | { | ||
1334 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1335 | _("Transport service could not access hostkey. Exiting.\n")); | ||
1336 | GNUNET_SCHEDULER_shutdown (); | ||
1337 | fail = 1; | ||
1338 | return; | ||
1339 | } | ||
1340 | |||
1341 | GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); | ||
1342 | GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), | ||
1343 | &my_identity.hashPubKey); | ||
1344 | |||
1345 | /* assertions before start */ | ||
1346 | GNUNET_assert ((port > 0) && (port <= 65535)); | ||
1347 | |||
1348 | /* load plugins... */ | ||
1349 | setup_plugin_environment (); | ||
1350 | GNUNET_asprintf (&libname, "libgnunet_plugin_transport_https"); | ||
1351 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1352 | _("Loading HTTPS transport plugin `%s'\n"), libname); | ||
1353 | api = GNUNET_PLUGIN_load (libname, &env); | ||
1354 | GNUNET_free (libname); | ||
1355 | if (api == NULL) | ||
1356 | { | ||
1357 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1358 | _("Failed to load transport plugin for https\n")); | ||
1359 | fail = 1; | ||
1360 | return; | ||
1361 | } | ||
1362 | |||
1363 | ti_timeout = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &task_timeout, NULL); | ||
1364 | |||
1365 | /* testing plugin functionality */ | ||
1366 | GNUNET_assert (0 != fail_notify_address_count); | ||
1367 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1368 | _("Transport plugin returned %u addresses to connect to\n"), | ||
1369 | fail_notify_address_count); | ||
1370 | |||
1371 | /* testing pretty printer with all addresses obtained from the plugin */ | ||
1372 | cur = addr_head; | ||
1373 | while (cur != NULL) | ||
1374 | { | ||
1375 | |||
1376 | api->address_pretty_printer (api->cls, "http", cur->addr, cur->addrlen, | ||
1377 | GNUNET_NO, TEST_TIMEOUT, &pretty_printer_cb, | ||
1378 | NULL); | ||
1379 | addr_str = api->address_to_string (api->cls, cur->addr, cur->addrlen); | ||
1380 | suggest_res = api->check_address (api->cls, cur->addr, cur->addrlen); | ||
1381 | |||
1382 | GNUNET_assert (GNUNET_OK == suggest_res); | ||
1383 | GNUNET_assert (NULL != addr_str); | ||
1384 | count_str_addr++; | ||
1385 | GNUNET_free ((char *) addr_str); | ||
1386 | cur = cur->next; | ||
1387 | } | ||
1388 | GNUNET_assert (fail_pretty_printer_count > 0); | ||
1389 | GNUNET_assert (fail_pretty_printer_count == fail_notify_address_count); | ||
1390 | GNUNET_assert (fail_pretty_printer_count == count_str_addr); | ||
1391 | fail_pretty_printer = GNUNET_NO; | ||
1392 | fail_addr_to_str = GNUNET_NO; | ||
1393 | |||
1394 | struct IPv4HttpAddress failing_addr; | ||
1395 | |||
1396 | /* Suggesting addresses with wrong size */ | ||
1397 | failing_addr.ipv4_addr = htonl (INADDR_LOOPBACK); | ||
1398 | failing_addr.u_port = htons (0); | ||
1399 | suggest_res = | ||
1400 | api->check_address (api->cls, &failing_addr, | ||
1401 | sizeof (struct IPv6HttpAddress)); | ||
1402 | GNUNET_assert (GNUNET_SYSERR == suggest_res); | ||
1403 | |||
1404 | /* Suggesting addresses with wrong address */ | ||
1405 | failing_addr.ipv4_addr = htonl (0xffc00000); | ||
1406 | failing_addr.u_port = htons (12389); | ||
1407 | suggest_res = api->check_address (api->cls, &failing_addr, 100); | ||
1408 | GNUNET_assert (GNUNET_SYSERR == suggest_res); | ||
1409 | |||
1410 | /* test sending to client */ | ||
1411 | multi_handle = curl_multi_init (); | ||
1412 | |||
1413 | /* Setting up buffers */ | ||
1414 | buffer_in.size = HTTP_BUFFER_SIZE; | ||
1415 | buffer_in.pos = 0; | ||
1416 | buffer_in.len = 0; | ||
1417 | |||
1418 | buffer_out.size = HTTP_BUFFER_SIZE; | ||
1419 | buffer_out.pos = 0; | ||
1420 | buffer_out.len = 0; | ||
1421 | |||
1422 | /* Setting up connection tests */ | ||
1423 | |||
1424 | /* Test: connecting without a peer identification */ | ||
1425 | test_no_ident.test_executed = GNUNET_NO; | ||
1426 | test_no_ident.test_failed = GNUNET_YES; | ||
1427 | |||
1428 | /* Test: connecting with too short peer identification */ | ||
1429 | test_too_short_ident.test_executed = GNUNET_NO; | ||
1430 | test_too_short_ident.test_failed = GNUNET_YES; | ||
1431 | |||
1432 | /* Test: connecting with too long peer identification */ | ||
1433 | test_too_long_ident.test_executed = GNUNET_NO; | ||
1434 | test_too_long_ident.test_failed = GNUNET_YES; | ||
1435 | |||
1436 | /* Test: connecting with valid identification */ | ||
1437 | test_valid_ident.test_executed = GNUNET_NO; | ||
1438 | test_valid_ident.test_failed = GNUNET_YES; | ||
1439 | |||
1440 | test_addr = | ||
1441 | (char *) api->address_to_string (api->cls, addr_head->addr, | ||
1442 | addr_head->addrlen); | ||
1443 | |||
1444 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("\nPhase 0\n\n")); | ||
1445 | run_connection_tests (0, NULL); | ||
1446 | |||
1447 | /* testing finished */ | ||
1448 | |||
1449 | return; | ||
1450 | } | ||
1451 | |||
1452 | |||
1453 | /** | ||
1454 | * The main function for the transport service. | ||
1455 | * | ||
1456 | * @param argc number of arguments from the command line | ||
1457 | * @param argv command line arguments | ||
1458 | * @return 0 ok, 1 on error | ||
1459 | */ | ||
1460 | int | ||
1461 | main (int argc, char *const *argv) | ||
1462 | { | ||
1463 | |||
1464 | static struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1465 | GNUNET_GETOPT_OPTION_END | ||
1466 | }; | ||
1467 | int ret; | ||
1468 | |||
1469 | char *const argv_prog[] = { | ||
1470 | "test_gnunet_transport_plugin.https", | ||
1471 | "-c", | ||
1472 | "test_plugin_transport_data_http.conf", | ||
1473 | "-L", | ||
1474 | #if VERBOSE | ||
1475 | "DEBUG", | ||
1476 | #else | ||
1477 | "WARNING", | ||
1478 | #endif | ||
1479 | NULL | ||
1480 | }; | ||
1481 | GNUNET_log_setup ("test_gnunet_transport_plugin.https", | ||
1482 | #if VERBOSE | ||
1483 | "DEBUG", | ||
1484 | #else | ||
1485 | "WARNING", | ||
1486 | #endif | ||
1487 | NULL); | ||
1488 | |||
1489 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
1490 | |||
1491 | cfg = GNUNET_CONFIGURATION_create (); | ||
1492 | |||
1493 | GNUNET_assert (GNUNET_OK == | ||
1494 | GNUNET_CONFIGURATION_load (cfg, | ||
1495 | "test_plugin_transport_data_http.conf")); | ||
1496 | if (GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "SERVICEHOME")) | ||
1497 | GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME", | ||
1498 | &servicehome); | ||
1499 | GNUNET_DISK_directory_remove (servicehome); | ||
1500 | GNUNET_CONFIGURATION_destroy (cfg); | ||
1501 | |||
1502 | ret = | ||
1503 | (GNUNET_OK == | ||
1504 | GNUNET_PROGRAM_run (5, argv_prog, "test_gnunet_transport_plugin.https", | ||
1505 | "testcase", options, &run, | ||
1506 | NULL)) ? GNUNET_NO : GNUNET_YES; | ||
1507 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("\ndelete\n\n")); | ||
1508 | if (servicehome != NULL) | ||
1509 | { | ||
1510 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("\ndelete\n\n")); | ||
1511 | GNUNET_DISK_directory_remove (servicehome); | ||
1512 | GNUNET_free (servicehome); | ||
1513 | } | ||
1514 | if (GNUNET_OK != ret) | ||
1515 | return 1; | ||
1516 | return fail; | ||
1517 | } | ||
1518 | |||
1519 | /* end of test_plugin_transport_https.c */ | ||