2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
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.
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.
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.
21 * @file transport/test_plugin_transport_http.c
22 * @brief testcase for plugin_transport_http.c
23 * @author Matthias Wachs
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"
40 #include "gnunet_transport_plugin.h"
41 #include "gnunet_statistics_service.h"
42 #include "transport.h"
43 #include <curl/curl.h>
45 #define VERBOSE GNUNET_NO
46 #define DEBUG_CURL GNUNET_NO
47 #define HTTP_BUFFER_SIZE 2048
49 #define PROTOCOL_PREFIX "http"
51 #define PLUGIN libgnunet_plugin_transport_template
54 * How long until we give up on transmitting the message?
56 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
61 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
64 * How long between recieve and send?
66 #define WAIT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
71 * Struct for plugin addresses
76 * Next field for linked list
78 struct Plugin_Address *next;
81 * buffer containing data to send
86 * amount of data to sent
92 * Message to send using http
99 unsigned char buf[HTTP_BUFFER_SIZE];
102 * current position in buffer
119 * Struct for plugin addresses
124 * amount of bytes we recieved
129 * buffer for http transfers
131 unsigned char buf[HTTP_BUFFER_SIZE];
134 * buffer size this transfer
139 * amount of bytes we recieved
144 * HTTP Header result for transfer
146 unsigned int http_result_code;
151 unsigned int test_failed;
154 * was this test already executed?
156 unsigned int test_executed;
161 * Network format for IPv4 addresses.
163 struct IPv4HttpAddress
165 struct IPv4HttpAddress *next;
167 struct IPv4HttpAddress *prev;
170 * IPv4 address, in network byte order.
172 uint32_t ipv4_addr GNUNET_PACKED;
175 * Port number, in network byte order.
177 uint16_t u_port GNUNET_PACKED;
183 * Network format for IPv6 addresses.
185 struct IPv6HttpAddress
187 struct IPv6HttpAddress *next;
189 struct IPv6HttpAddress *prev;
194 struct in6_addr ipv6_addr GNUNET_PACKED;
197 * Port number, in network byte order.
199 uint16_t u6_port GNUNET_PACKED;
207 /* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */
212 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
217 static struct GNUNET_PeerIdentity my_identity;
222 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
227 static long long unsigned int port;
232 static char *test_addr;
235 * Our statistics handle.
237 struct GNUNET_STATISTICS_Handle *stats;
243 const struct GNUNET_CONFIGURATION_Handle *cfg;
246 * Number of neighbours we'd like to have.
248 static uint32_t max_connect_per_transport;
251 * Environment for this plugin.
253 static struct GNUNET_TRANSPORT_PluginEnvironment env;
256 *handle for the api provided by this plugin
258 static struct GNUNET_TRANSPORT_PluginFunctions *api;
261 * ID of the task controlling the testcase timeout
263 static GNUNET_SCHEDULER_TaskIdentifier ti_timeout;
265 static GNUNET_SCHEDULER_TaskIdentifier ti_send;
267 //const struct GNUNET_PeerIdentity * p;
270 * buffer for data to send
272 static struct HTTP_Message buffer_out;
275 * buffer for data to recieve
277 static struct HTTP_Message buffer_in;
280 struct Plugin_Address *addr_head;
283 * Did the test pass or fail?
285 static int fail_notify_address;
288 * Did the test pass or fail?
290 static int fail_notify_address_count;
293 * Did the test pass or fail?
295 static int fail_pretty_printer;
298 * Did the test pass or fail?
300 static int fail_pretty_printer_count;
303 * Did the test pass or fail?
305 static int fail_addr_to_str;
308 * No. of msgs transmitted successfully to local addresses
310 static int fail_msgs_transmited_to_local_addrs;
313 * Test: transmit msg of max. size
315 static int fail_msg_transmited_bigger_max_size;
318 * Test: transmit msg of max. size
320 static int fail_msg_transmited_max_size;
323 * Test: transmit 2 msgs. in in send operation
325 static int fail_multiple_msgs_in_transmission;
328 * Test: connect to peer without peer identification
330 static struct HTTP_Transfer test_no_ident;
333 * Test: connect to peer without peer identification
335 static struct HTTP_Transfer test_too_short_ident;
338 * Test: connect to peer without peer identification
340 static struct HTTP_Transfer test_too_long_ident;
343 * Test: connect to peer with valid peer identification
345 static struct HTTP_Transfer test_valid_ident;
348 * Test: session selection, use any existing
350 static int fail_session_selection_any;
353 * Test: session selection, use existing inbound session
355 static int fail_session_selection_session;
358 * Test: session selection, use existing inbound session
359 * max message, not fitting in send & recv buffers at one time
361 static int fail_session_selection_session_big;
364 * Test: session selection, use reliable existing
366 static int fail_session_selection_reliable;
369 * Did the test pass or fail?
374 * Number of local addresses
376 static unsigned int count_str_addr;
383 static CURLM *multi_handle;
386 * The task sending data
388 static GNUNET_SCHEDULER_TaskIdentifier http_task_send;
390 static char *servicehome;
398 struct Plugin_Address *tmp;
400 /* Evaluate results */
402 if ((fail_notify_address == GNUNET_YES) || (fail_pretty_printer == GNUNET_YES)
403 || (fail_addr_to_str == GNUNET_YES))
405 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
406 "Phase 0: Test plugin functions failed\n");
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))
414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
415 "Phase 1: Test connect with wrong data failed\n");
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))
423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424 "Phase 2: Test session selection failed\n");
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))
431 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
432 "Phase 3: Test sending with plugin failed\n");
437 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All tests successful\n");
440 api->disconnect (api->cls, &my_identity);
442 curl_multi_cleanup (multi_handle);
444 if (NULL != curl_handle)
445 curl_easy_cleanup (curl_handle);
447 /* cleaning addresses */
448 while (addr_head != NULL)
450 tmp = addr_head->next;
451 GNUNET_free (addr_head->addr);
452 GNUNET_free (addr_head);
456 if (ti_send != GNUNET_SCHEDULER_NO_TASK)
458 GNUNET_SCHEDULER_cancel (ti_send);
459 ti_send = GNUNET_SCHEDULER_NO_TASK;
462 if (http_task_send != GNUNET_SCHEDULER_NO_TASK)
464 GNUNET_SCHEDULER_cancel (http_task_send);
465 http_task_send = GNUNET_SCHEDULER_NO_TASK;
468 if (ti_timeout != GNUNET_SCHEDULER_NO_TASK)
470 GNUNET_SCHEDULER_cancel (ti_timeout);
471 ti_timeout = GNUNET_SCHEDULER_NO_TASK;
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",
480 GNUNET_SCHEDULER_shutdown ();
481 GNUNET_DISK_directory_remove ("/tmp/test_gnunet_transport_plugin_http");
483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exiting testcase\n");
485 if (servicehome != NULL)
487 GNUNET_DISK_directory_remove (servicehome);
488 GNUNET_free (servicehome);
497 * Continuation called after plugin send message
500 * @result GNUNET_OK or GNUNET_SYSERR
504 task_send_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result)
506 if ((cls == &fail_msg_transmited_bigger_max_size) &&
507 (result == GNUNET_SYSERR))
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;
515 if ((cls == &fail_msg_transmited_max_size) && (result == GNUNET_OK))
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;
526 run_connection_tests (int phase, void *cls);
529 * Recieves messages from plugin, in real world transport
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)
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),
543 if ((ntohs (message->type) >= 10) && (ntohs (message->type) < 20))
545 fail_msgs_transmited_to_local_addrs++;
546 if (fail_msgs_transmited_to_local_addrs == count_str_addr)
547 run_connection_tests (2, session);
549 if ((ntohs (message->type) == 20))
551 fail_session_selection_reliable = GNUNET_NO;
553 if ((ntohs (message->type) == 21))
555 fail_session_selection_any = GNUNET_NO;
557 if ((ntohs (message->type) == 22))
559 fail_session_selection_session = GNUNET_NO;
561 if ((ntohs (message->type) == 23))
563 fail_session_selection_session_big = GNUNET_NO;
564 run_connection_tests (3, NULL);
566 if ((ntohs (message->type) == 30) || (ntohs (message->type) == 31))
568 fail_multiple_msgs_in_transmission++;
570 if ((ntohs (message->type) == 32) &&
571 (ntohs (message->size) == GNUNET_SERVER_MAX_MESSAGE_SIZE - 1))
573 fail_msg_transmited_max_size = GNUNET_NO;
576 return GNUNET_TIME_UNIT_ZERO;
581 send_function (void *stream, size_t size, size_t nmemb, void *ptr)
585 len = buffer_out.len;
587 if ((buffer_out.pos == len) || (len > (size * nmemb)))
589 memcpy (stream, buffer_out.buf, len);
590 buffer_out.pos = len;
596 recv_function (void *ptr, size_t size, size_t nmemb, void *ctx)
599 if (buffer_in.pos + size * nmemb > buffer_in.size)
600 return 0; /* overflow */
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;
611 header_function (void *ptr, size_t size, size_t nmemb, void *stream)
613 struct HTTP_Transfer *res = stream;
615 unsigned int len = size * nmemb;
617 tmp = GNUNET_malloc (len + 1);
618 memcpy (tmp, ptr, len);
619 if (tmp[len - 2] == 13)
622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: `%s'\n", tmp);
624 if (0 == strcmp (tmp, "HTTP/1.1 100 Continue"))
626 res->http_result_code = 100;
628 if (0 == strcmp (tmp, "HTTP/1.1 200 OK"))
630 res->http_result_code = 200;
632 if (0 == strcmp (tmp, "HTTP/1.1 400 Bad Request"))
634 res->http_result_code = 400;
636 if (0 == strcmp (tmp, "HTTP/1.1 404 Not Found"))
638 res->http_result_code = 404;
640 if (0 == strcmp (tmp, "HTTP/1.1 413 Request entity too large"))
642 res->http_result_code = 413;
651 send_prepare (struct HTTP_Transfer *result);
655 send_execute (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
657 struct HTTP_Transfer *res;
663 res = (struct HTTP_Transfer *) cls;
664 http_task_send = GNUNET_SCHEDULER_NO_TASK;
665 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
671 mret = curl_multi_perform (multi_handle, &running);
677 msg = curl_multi_info_read (multi_handle, &running);
680 /* get session for affected curl handle */
681 //cs = find_session_by_curlhandle (msg->easy_handle);
682 //GNUNET_assert ( cs != NULL );
687 if ((msg->data.result != CURLE_OK) &&
688 (msg->data.result != CURLE_GOT_NOTHING))
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);
699 run_connection_tests (0, NULL);
701 if (res == &test_no_ident)
703 if ((res->http_result_code == 404) && (buffer_in.len == 208))
705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
706 "Connecting to peer without any peer identification: test passed\n");
707 res->test_failed = GNUNET_NO;
710 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
712 ("Connecting to peer without any peer identification: test failed\n"));
714 if (res == &test_too_short_ident)
716 if ((res->http_result_code == 404) && (buffer_in.len == 208))
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;
723 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
725 ("Connecting to peer with too short peer identification: test failed\n"));
727 if (res == &test_too_long_ident)
729 if ((res->http_result_code == 404) && (buffer_in.len == 208))
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;
736 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
738 ("Connecting to peer with too long peer identification: test failed\n"));
740 if (res == &test_valid_ident)
742 if ((res->http_result_code == 200))
744 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
745 "Connecting to peer with valid peer identification: test passed\n");
746 res->test_failed = GNUNET_NO;
749 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
750 "Connecting to peer with valid peer identification: test failed\n");
752 curl_easy_cleanup (curl_handle);
754 if ((res == &test_valid_ident) && (res->test_failed == GNUNET_NO))
755 run_connection_tests (1, NULL);
756 run_connection_tests (0, NULL);
763 while ((running > 0));
766 while (mret == CURLM_CALL_MULTI_PERFORM);
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
777 send_prepare (struct HTTP_Transfer *result)
783 struct GNUNET_NETWORK_FDSet *grs;
784 struct GNUNET_NETWORK_FDSet *gws;
792 mret = curl_multi_fdset (multi_handle, &rs, &ws, &es, &max);
793 if (mret != CURLM_OK)
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));
800 mret = curl_multi_timeout (multi_handle, &to);
801 if (mret != CURLM_OK)
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));
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);
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);
822 /* FIXME: return bytes REALLY sent */
827 * function to send data to server
830 send_data (struct HTTP_Transfer *result, char *url)
833 curl_handle = curl_easy_init ();
834 if (NULL == curl_handle)
836 printf ("easy_init failed \n");
837 return GNUNET_SYSERR;
840 curl_easy_setopt (curl_handle, CURLOPT_VERBOSE, 1L);
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);
855 curl_multi_add_handle (multi_handle, curl_handle);
857 send_prepare (result);
863 * Plugin notifies transport (aka testcase) about its addresses
866 notify_address (void *cls, int add_remove, const void *addr, size_t addrlen)
868 char address[INET6_ADDRSTRLEN];
870 struct Plugin_Address *pl_addr;
871 struct Plugin_Address *cur;
873 if (addrlen == (sizeof (struct IPv4HttpAddress)))
875 inet_ntop (AF_INET, (struct in_addr *) addr, address, INET_ADDRSTRLEN);
876 port = ntohs (((struct IPv4HttpAddress *) addr)->u_port);
878 else if (addrlen == (sizeof (struct IPv6HttpAddress)))
880 inet_ntop (AF_INET6, (struct in6_addr *) addr, address, INET6_ADDRSTRLEN);
881 port = ntohs (((struct IPv6HttpAddress *) addr)->u6_port);
885 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
887 ("Unknown address size: ipv6 has %u ipv4 has %u but this has %u\n"),
888 sizeof (struct IPv6HttpAddress),
889 sizeof (struct IPv4HttpAddress), addrlen);
892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
893 _("Transport plugin notification for address: `%s':%u\n"),
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;
901 if (NULL == addr_head)
908 while (NULL != cur->next)
914 fail_notify_address_count++;
915 fail_notify_address = GNUNET_NO;
919 plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
920 struct Session *session)
922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
923 "Pluging tells me: session %X to peer `%s' ended\n", session,
929 * Setup plugin environment
932 setup_plugin_environment ()
936 env.my_identity = &my_identity;
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;
946 * Task shutting down testcase if it a timeout occurs
949 task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
951 ti_timeout = GNUNET_SCHEDULER_NO_TASK;
952 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
955 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n");
963 pretty_printer_cb (void *cls, const char *address)
967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin returned pretty address: `%s'\n",
969 fail_pretty_printer_count++;
973 * Runs every single test to test the plugin
976 run_connection_tests (int phase, void *cls)
978 struct GNUNET_MessageHeader *msg;
983 char *host_str = NULL;
985 /* resetting buffers */
986 buffer_in.size = HTTP_BUFFER_SIZE;
990 buffer_out.size = HTTP_BUFFER_SIZE;
994 if (test_no_ident.test_executed == GNUNET_NO)
996 /* Connecting to peer without identification */
997 const char *ident = "";
999 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
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);
1008 if (test_too_short_ident.test_executed == GNUNET_NO)
1010 const char *ident = "AAAAAAAAAA";
1012 /* Connecting to peer with too short identification */
1013 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1015 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
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);
1024 if (test_too_long_ident.test_executed == GNUNET_NO)
1027 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1029 /* Connecting to peer with too long identification */
1030 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
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);
1039 if (test_valid_ident.test_executed == GNUNET_NO)
1041 struct GNUNET_CRYPTO_HashAsciiEncoded ident;
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);
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);
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];
1066 unsigned int type = 10;
1068 msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1069 tmp_addr = addr_head;
1070 /* send a message to all addresses advertised by plugin */
1074 while (tmp_addr != NULL)
1076 if (tmp_addr->addrlen == (sizeof (struct IPv4HttpAddress)))
1078 inet_ntop (AF_INET, (struct in_addr *) tmp_addr->addr, address,
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,
1085 if (tmp_addr->addrlen == (sizeof (struct IPv6HttpAddress)))
1087 inet_ntop (AF_INET6, (struct in6_addr *) tmp_addr->addr, address,
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,
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;
1110 struct Session *session = cls;
1112 msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
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);
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);
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);
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);
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);
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];
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);
1169 /* send a message with size GNUNET_SERVER_MAX_MESSAGE_SIZE-1 */
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);
1179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more tests to run\n");
1187 * @param cls closure
1188 * @param c configuration to use
1191 run (void *cls, char *const *args, const char *cfgfile,
1192 const struct GNUNET_CONFIGURATION_Handle *c)
1198 unsigned long long tneigh;
1199 struct Plugin_Address *cur;
1200 const char *addr_str;
1203 unsigned int suggest_res;
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;
1218 /* parse configuration */
1219 if (GNUNET_CONFIGURATION_have_value (c, "PATHS", "SERVICEHOME"))
1220 GNUNET_CONFIGURATION_get_value_string (c, "PATHS", "SERVICEHOME",
1224 GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", "NEIGHBOUR_LIMIT",
1227 GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
1230 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1232 ("Transport service is lacking key configuration settings. Exiting.\n"));
1233 GNUNET_SCHEDULER_shutdown ();
1239 GNUNET_CONFIGURATION_get_value_number (cfg, "transport-http", "PORT",
1240 &port)) || (port > 65535) ||
1243 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "http",
1245 ("Require valid port number for transport plugin `%s' in configuration!\n"),
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)
1254 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1255 _("Transport service could not access hostkey. Exiting.\n"));
1256 GNUNET_SCHEDULER_shutdown ();
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);
1265 /* assertions before start */
1266 GNUNET_assert ((port > 0) && (port <= 65535));
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"),
1273 api = GNUNET_PLUGIN_load (libname, &env);
1274 GNUNET_free (libname);
1277 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1278 _("Failed to load transport plugin for http\n"));
1284 ti_timeout = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &task_timeout, NULL);
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);
1292 /* testing pretty printer with all addresses obtained from the plugin */
1296 api->address_pretty_printer (api->cls, "http", cur->addr, cur->addrlen,
1297 GNUNET_NO, TEST_TIMEOUT, &pretty_printer_cb,
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);
1302 GNUNET_assert (GNUNET_OK == suggest_res);
1303 GNUNET_assert (NULL != addr_str);
1305 GNUNET_free ((char *) addr_str);
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;
1314 struct IPv4HttpAddress failing_addr;
1316 /* Suggesting addresses with wrong size */
1317 failing_addr.ipv4_addr = htonl (INADDR_LOOPBACK);
1318 failing_addr.u_port = htons (0);
1320 api->check_address (api->cls, &failing_addr,
1321 sizeof (struct IPv6HttpAddress));
1322 GNUNET_assert (GNUNET_SYSERR == suggest_res);
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);
1330 /* test sending to client */
1331 multi_handle = curl_multi_init ();
1333 /* Setting up buffers */
1334 buffer_in.size = HTTP_BUFFER_SIZE;
1338 buffer_out.size = HTTP_BUFFER_SIZE;
1342 /* Setting up connection tests */
1344 /* Test: connecting without a peer identification */
1345 test_no_ident.test_executed = GNUNET_NO;
1346 test_no_ident.test_failed = GNUNET_YES;
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;
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;
1356 /* Test: connecting with valid identification */
1357 test_valid_ident.test_executed = GNUNET_NO;
1358 test_valid_ident.test_failed = GNUNET_YES;
1361 (char *) api->address_to_string (api->cls, addr_head->addr,
1362 addr_head->addrlen);
1364 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Phase 0\n\n"));
1365 run_connection_tests (0, NULL);
1366 /* testing finished */
1371 * The main function for the transport service.
1373 * @param argc number of arguments from the command line
1374 * @param argv command line arguments
1375 * @return 0 ok, 1 on error
1378 main (int argc, char *const *argv)
1380 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1381 GNUNET_GETOPT_OPTION_END
1385 char *const argv_prog[] = {
1386 "test_gnunet_transport_plugin_http",
1388 "test_plugin_transport_data_http.conf",
1397 GNUNET_log_setup ("test_gnunet_transport_plugin_http",
1405 struct GNUNET_CONFIGURATION_Handle *cfg;
1407 cfg = GNUNET_CONFIGURATION_create ();
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",
1415 GNUNET_DISK_directory_remove (servicehome);
1416 GNUNET_CONFIGURATION_destroy (cfg);
1420 GNUNET_PROGRAM_run (5, argv_prog, "test_gnunet_transport_plugin_http",
1421 "testcase", options, &run,
1422 NULL)) ? GNUNET_NO : GNUNET_YES;
1424 if (servicehome != NULL)
1426 GNUNET_DISK_directory_remove (servicehome);
1427 GNUNET_free (servicehome);
1429 if (ret != GNUNET_OK)
1434 /* end of test_gnunet_transport_plugin_http.c */