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) ||
403 (fail_pretty_printer == GNUNET_YES) || (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;
525 static void run_connection_tests (int phase, void *cls);
528 * Recieves messages from plugin, in real world transport
530 static struct GNUNET_TIME_Relative
531 receive (void *cls, const struct GNUNET_PeerIdentity *peer,
532 const struct GNUNET_MessageHeader *message,
533 const struct GNUNET_TRANSPORT_ATS_Information *ats,
535 struct Session *session,
536 const char *sender_address, 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",
541 ntohs (message->type), ntohs (message->size), session);
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;
650 static size_t send_prepare (struct HTTP_Transfer *result);
654 send_execute (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
656 struct HTTP_Transfer *res;
662 res = (struct HTTP_Transfer *) cls;
663 http_task_send = GNUNET_SCHEDULER_NO_TASK;
664 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
670 mret = curl_multi_perform (multi_handle, &running);
676 msg = curl_multi_info_read (multi_handle, &running);
679 /* get session for affected curl handle */
680 //cs = find_session_by_curlhandle (msg->easy_handle);
681 //GNUNET_assert ( cs != NULL );
686 if ((msg->data.result != CURLE_OK) &&
687 (msg->data.result != CURLE_GOT_NOTHING))
690 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
691 _("curl failed for `%s' at %s:%d: `%s'\n"),
692 "curl_multi_perform",
694 __LINE__, 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,
796 _("%s failed at %s:%d: `%s'\n"),
797 "curl_multi_fdset", __FILE__, __LINE__,
798 curl_multi_strerror (mret));
801 mret = curl_multi_timeout (multi_handle, &to);
802 if (mret != CURLM_OK)
804 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
805 _("%s failed at %s:%d: `%s'\n"),
806 "curl_multi_timeout", __FILE__, __LINE__,
807 curl_multi_strerror (mret));
811 grs = GNUNET_NETWORK_fdset_create ();
812 gws = GNUNET_NETWORK_fdset_create ();
813 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
814 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
816 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
817 GNUNET_SCHEDULER_NO_TASK,
818 GNUNET_TIME_relative_multiply
819 (GNUNET_TIME_UNIT_SECONDS, 0), grs, gws,
820 &send_execute, result);
821 GNUNET_NETWORK_fdset_destroy (gws);
822 GNUNET_NETWORK_fdset_destroy (grs);
824 /* FIXME: return bytes REALLY sent */
829 * function to send data to server
832 send_data (struct HTTP_Transfer *result, char *url)
835 curl_handle = curl_easy_init ();
836 if (NULL == curl_handle)
838 printf ("easy_init failed \n");
839 return GNUNET_SYSERR;
842 curl_easy_setopt (curl_handle, CURLOPT_VERBOSE, 1L);
844 curl_easy_setopt (curl_handle, CURLOPT_URL, url);
845 curl_easy_setopt (curl_handle, CURLOPT_PUT, 1L);
846 curl_easy_setopt (curl_handle, CURLOPT_HEADERFUNCTION, &header_function);
847 curl_easy_setopt (curl_handle, CURLOPT_WRITEHEADER, result);
848 curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, &recv_function);
849 curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, result);
850 curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &send_function);
851 curl_easy_setopt (curl_handle, CURLOPT_READDATA, result);
852 curl_easy_setopt (curl_handle, CURLOPT_INFILESIZE_LARGE,
853 (curl_off_t) buffer_out.len);
854 curl_easy_setopt (curl_handle, CURLOPT_TIMEOUT, 30);
855 curl_easy_setopt (curl_handle, CURLOPT_CONNECTTIMEOUT, 20);
857 curl_multi_add_handle (multi_handle, curl_handle);
859 send_prepare (result);
865 * Plugin notifies transport (aka testcase) about its addresses
868 notify_address (void *cls, int add_remove, const void *addr, size_t addrlen)
870 char address[INET6_ADDRSTRLEN];
872 struct Plugin_Address *pl_addr;
873 struct Plugin_Address *cur;
875 if (addrlen == (sizeof (struct IPv4HttpAddress)))
877 inet_ntop (AF_INET, (struct in_addr *) addr, address, INET_ADDRSTRLEN);
878 port = ntohs (((struct IPv4HttpAddress *) addr)->u_port);
880 else if (addrlen == (sizeof (struct IPv6HttpAddress)))
882 inet_ntop (AF_INET6, (struct in6_addr *) addr, address, INET6_ADDRSTRLEN);
883 port = ntohs (((struct IPv6HttpAddress *) addr)->u6_port);
887 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
889 ("Unknown address size: ipv6 has %u ipv4 has %u but this has %u\n"),
890 sizeof (struct IPv6HttpAddress),
891 sizeof (struct IPv4HttpAddress), addrlen);
894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
895 _("Transport plugin notification for address: `%s':%u\n"),
897 pl_addr = GNUNET_malloc (sizeof (struct Plugin_Address));
898 pl_addr->addrlen = addrlen;
899 pl_addr->addr = GNUNET_malloc (addrlen);
900 memcpy (pl_addr->addr, addr, addrlen);
901 pl_addr->next = NULL;
903 if (NULL == addr_head)
910 while (NULL != cur->next)
916 fail_notify_address_count++;
917 fail_notify_address = GNUNET_NO;
921 plugin_env_session_end (void *cls,
922 const struct GNUNET_PeerIdentity *peer,
923 struct Session *session)
925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
926 "Pluging tells me: session %X to peer `%s' ended\n",
927 session, GNUNET_i2s (peer));
932 * Setup plugin environment
935 setup_plugin_environment ()
939 env.my_identity = &my_identity;
941 env.receive = &receive;
942 env.notify_address = ¬ify_address;
943 env.max_connections = max_connect_per_transport;
944 env.session_end = &plugin_env_session_end;
949 * Task shutting down testcase if it a timeout occurs
952 task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
954 ti_timeout = GNUNET_SCHEDULER_NO_TASK;
955 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n");
966 pretty_printer_cb (void *cls, const char *address)
970 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
971 "Plugin returned pretty address: `%s'\n", address);
972 fail_pretty_printer_count++;
976 * Runs every single test to test the plugin
979 run_connection_tests (int phase, void *cls)
981 struct GNUNET_MessageHeader *msg;
986 char *host_str = NULL;
988 /* resetting buffers */
989 buffer_in.size = HTTP_BUFFER_SIZE;
993 buffer_out.size = HTTP_BUFFER_SIZE;
997 if (test_no_ident.test_executed == GNUNET_NO)
999 /* Connecting to peer without identification */
1000 const char *ident = "";
1002 GNUNET_asprintf (&host_str,
1003 "%s://%s/%s", PROTOCOL_PREFIX, test_addr, ident);
1004 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1005 _("Connecting to peer without any peer identification.\n"));
1006 test_no_ident.test_executed = GNUNET_YES;
1007 send_data (&test_no_ident, host_str);
1008 GNUNET_free (host_str);
1011 if (test_too_short_ident.test_executed == GNUNET_NO)
1013 const char *ident = "AAAAAAAAAA";
1015 /* Connecting to peer with too short identification */
1016 GNUNET_asprintf (&host_str,
1017 "%s://%s/%s", PROTOCOL_PREFIX, test_addr, ident);
1018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1020 ("Connecting to peer with too short peer identification.\n"));
1021 test_too_short_ident.test_executed = GNUNET_YES;
1022 send_data (&test_too_short_ident, host_str);
1023 GNUNET_free (host_str);
1027 if (test_too_long_ident.test_executed == GNUNET_NO)
1030 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1032 /* Connecting to peer with too long identification */
1033 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1035 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1036 _("Connecting to peer with too long peer identification.\n"));
1037 test_too_long_ident.test_executed = GNUNET_YES;
1038 send_data (&test_too_long_ident, host_str);
1039 GNUNET_free (host_str);
1042 if (test_valid_ident.test_executed == GNUNET_NO)
1044 struct GNUNET_CRYPTO_HashAsciiEncoded ident;
1046 GNUNET_CRYPTO_hash_to_enc (&my_identity.hashPubKey, &ident);
1047 GNUNET_asprintf (&host_str,
1049 PROTOCOL_PREFIX, test_addr, (char *) &ident, ";0");
1050 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1051 _("Connecting to peer with valid peer identification.\n"));
1052 test_valid_ident.test_executed = GNUNET_YES;
1053 send_data (&test_valid_ident, host_str);
1054 GNUNET_free (host_str);
1060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1061 "\nPhase 1: transmit data to all suggested addresses\n\n");
1062 /* Using one of the addresses the plugin proposed */
1063 GNUNET_assert (addr_head->addr != NULL);
1065 struct Plugin_Address *tmp_addr;
1066 struct GNUNET_MessageHeader msg;
1067 char *tmp = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1068 char address[INET6_ADDRSTRLEN];
1070 unsigned int type = 10;
1072 msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1073 tmp_addr = addr_head;
1074 /* send a message to all addresses advertised by plugin */
1078 while (tmp_addr != NULL)
1080 if (tmp_addr->addrlen == (sizeof (struct IPv4HttpAddress)))
1082 inet_ntop (AF_INET, (struct in_addr *) tmp_addr->addr, address,
1084 port = ntohs (((struct IPv4HttpAddress *) tmp_addr->addr)->u_port);
1085 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1086 "Sending message to addres no. %u: `%s':%u\n",
1087 count, address, port);
1089 if (tmp_addr->addrlen == (sizeof (struct IPv6HttpAddress)))
1091 inet_ntop (AF_INET6, (struct in6_addr *) tmp_addr->addr, address,
1093 port = ntohs (((struct IPv6HttpAddress *) tmp_addr->addr)->u6_port);
1094 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1095 "Sending message to addres no. %u: `%s':%u\n",
1096 count, address, port);
1098 msg.type = htons (type);
1099 memcpy (tmp, &msg, sizeof (struct GNUNET_MessageHeader));
1100 api->send (api->cls,
1102 tmp, sizeof (struct GNUNET_MessageHeader),
1105 tmp_addr->addr, tmp_addr->addrlen,
1107 &task_send_cont, &fail_msgs_transmited_to_local_addrs);
1108 tmp_addr = tmp_addr->next;
1118 struct Session *session = cls;
1120 msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 2: session selection\n\n");
1123 size = sizeof (struct GNUNET_MessageHeader);
1124 msg->size = htons (size);
1125 msg->type = htons (20);
1126 api->send (api->cls,
1128 (const char *) msg, size,
1129 0, TIMEOUT, NULL, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1131 msg->type = htons (21);
1132 api->send (api->cls,
1134 (const char *) msg, size,
1135 0, TIMEOUT, NULL, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL);
1137 /* answer on session */
1138 size = sizeof (struct GNUNET_MessageHeader);
1139 msg->size = htons (size);
1140 msg->type = htons (22);
1141 api->send (api->cls,
1143 (const char *) msg, size,
1144 0, TIMEOUT, session, NULL, 0, GNUNET_SYSERR,
1145 &task_send_cont, NULL);
1148 /* answer on session with big message not fitting in mhd send buffer */
1149 size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1150 msg = GNUNET_malloc (size);
1151 msg->size = htons (size);
1152 msg->type = htons (23);
1153 api->send (api->cls,
1155 (const char *) msg, size,
1156 0, TIMEOUT, session, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1165 "Phase 3: send multiple or big messages after disconnect\n\n");
1166 /* disconnect from peer, so new connections are created */
1167 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect from peer: `%s'\n",
1168 GNUNET_i2s (&my_identity));
1169 api->disconnect (api->cls, &my_identity);
1171 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 3: sending messages\n");
1172 /* send a multiple GNUNET_messages at a time */
1173 size = 2 * sizeof (struct GNUNET_MessageHeader);
1174 msg = GNUNET_malloc (2 * size);
1175 msg->size = htons (size);
1176 msg->type = htons (30);
1177 struct GNUNET_MessageHeader *msg2 = &msg[2];
1179 msg2->size = htons (2 * sizeof (struct GNUNET_MessageHeader));
1180 msg2->type = htons (31);
1181 api->send (api->cls,
1183 (const char *) msg, 4 * sizeof (struct GNUNET_MessageHeader),
1185 addr_head->addr, addr_head->addrlen,
1186 GNUNET_NO, &task_send_cont, &fail_multiple_msgs_in_transmission);
1188 /* send a message with size GNUNET_SERVER_MAX_MESSAGE_SIZE-1 */
1190 size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1191 msg = GNUNET_malloc (size);
1192 msg->size = htons (size);
1193 msg->type = htons (32);
1194 api->send (api->cls,
1196 (const char *) msg, size,
1198 addr_head->addr, addr_head->addrlen,
1199 GNUNET_NO, &task_send_cont, &fail_msg_transmited_max_size);
1201 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more tests to run\n");
1209 * @param cls closure
1210 * @param c configuration to use
1215 const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
1221 unsigned long long tneigh;
1222 struct Plugin_Address *cur;
1223 const char *addr_str;
1226 unsigned int suggest_res;
1228 fail_pretty_printer = GNUNET_YES;
1229 fail_notify_address = GNUNET_YES;
1230 fail_addr_to_str = GNUNET_YES;
1231 fail_msgs_transmited_to_local_addrs = 0;
1232 fail_msg_transmited_max_size = GNUNET_YES;
1233 fail_multiple_msgs_in_transmission = 0;
1234 fail_session_selection_reliable = GNUNET_YES;
1235 fail_session_selection_reliable = GNUNET_YES;
1236 fail_session_selection_session = GNUNET_YES;
1237 fail_session_selection_session_big = GNUNET_YES;
1241 /* parse configuration */
1242 if (GNUNET_CONFIGURATION_have_value (c, "PATHS", "SERVICEHOME"))
1243 GNUNET_CONFIGURATION_get_value_string (c, "PATHS", "SERVICEHOME",
1247 GNUNET_CONFIGURATION_get_value_number (c,
1252 GNUNET_CONFIGURATION_get_value_filename (c,
1254 "HOSTKEY", &keyfile)))
1256 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1258 ("Transport service is lacking key configuration settings. Exiting.\n"));
1259 GNUNET_SCHEDULER_shutdown ();
1265 GNUNET_CONFIGURATION_get_value_number (cfg,
1269 (port > 65535) || (port == 0))
1271 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
1274 ("Require valid port number for transport plugin `%s' in configuration!\n"),
1278 max_connect_per_transport = (uint32_t) tneigh;
1279 my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
1280 GNUNET_free (keyfile);
1281 if (my_private_key == NULL)
1283 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1284 _("Transport service could not access hostkey. Exiting.\n"));
1285 GNUNET_SCHEDULER_shutdown ();
1290 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
1291 GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
1292 &my_identity.hashPubKey);
1294 /* assertions before start */
1295 GNUNET_assert ((port > 0) && (port <= 65535));
1297 /* load plugins... */
1298 setup_plugin_environment ();
1299 GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http");
1300 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1301 _("Loading HTTP transport plugin `%s'\n"), libname);
1302 api = GNUNET_PLUGIN_load (libname, &env);
1303 GNUNET_free (libname);
1306 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1307 _("Failed to load transport plugin for http\n"));
1313 ti_timeout = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &task_timeout, NULL);
1315 /* testing plugin functionality */
1316 GNUNET_assert (0 != fail_notify_address_count);
1317 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1318 "Transport plugin returned %u addresses to connect to\n",
1319 fail_notify_address_count);
1321 /* testing pretty printer with all addresses obtained from the plugin */
1325 api->address_pretty_printer (api->cls, "http",
1326 cur->addr, cur->addrlen, GNUNET_NO,
1327 TEST_TIMEOUT, &pretty_printer_cb, NULL);
1328 addr_str = api->address_to_string (api->cls, cur->addr, cur->addrlen);
1329 suggest_res = api->check_address (api->cls, cur->addr, cur->addrlen);
1331 GNUNET_assert (GNUNET_OK == suggest_res);
1332 GNUNET_assert (NULL != addr_str);
1334 GNUNET_free ((char *) addr_str);
1337 GNUNET_assert (fail_pretty_printer_count > 0);
1338 GNUNET_assert (fail_pretty_printer_count == fail_notify_address_count);
1339 GNUNET_assert (fail_pretty_printer_count == count_str_addr);
1340 fail_pretty_printer = GNUNET_NO;
1341 fail_addr_to_str = GNUNET_NO;
1343 struct IPv4HttpAddress failing_addr;
1345 /* Suggesting addresses with wrong size */
1346 failing_addr.ipv4_addr = htonl (INADDR_LOOPBACK);
1347 failing_addr.u_port = htons (0);
1349 api->check_address (api->cls, &failing_addr,
1350 sizeof (struct IPv6HttpAddress));
1351 GNUNET_assert (GNUNET_SYSERR == suggest_res);
1353 /* Suggesting addresses with wrong address */
1354 failing_addr.ipv4_addr = htonl (0xffc00000);
1355 failing_addr.u_port = htons (12389);
1356 suggest_res = api->check_address (api->cls, &failing_addr, 100);
1357 GNUNET_assert (GNUNET_SYSERR == suggest_res);
1359 /* test sending to client */
1360 multi_handle = curl_multi_init ();
1362 /* Setting up buffers */
1363 buffer_in.size = HTTP_BUFFER_SIZE;
1367 buffer_out.size = HTTP_BUFFER_SIZE;
1371 /* Setting up connection tests */
1373 /* Test: connecting without a peer identification */
1374 test_no_ident.test_executed = GNUNET_NO;
1375 test_no_ident.test_failed = GNUNET_YES;
1377 /* Test: connecting with too short peer identification */
1378 test_too_short_ident.test_executed = GNUNET_NO;
1379 test_too_short_ident.test_failed = GNUNET_YES;
1381 /* Test: connecting with too long peer identification */
1382 test_too_long_ident.test_executed = GNUNET_NO;
1383 test_too_long_ident.test_failed = GNUNET_YES;
1385 /* Test: connecting with valid identification */
1386 test_valid_ident.test_executed = GNUNET_NO;
1387 test_valid_ident.test_failed = GNUNET_YES;
1390 (char *) api->address_to_string (api->cls, addr_head->addr,
1391 addr_head->addrlen);
1393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Phase 0\n\n"));
1394 run_connection_tests (0, NULL);
1395 /* testing finished */
1400 * The main function for the transport service.
1402 * @param argc number of arguments from the command line
1403 * @param argv command line arguments
1404 * @return 0 ok, 1 on error
1407 main (int argc, char *const *argv)
1409 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1410 GNUNET_GETOPT_OPTION_END
1414 char *const argv_prog[] = {
1415 "test_gnunet_transport_plugin_http",
1417 "test_plugin_transport_data_http.conf",
1426 GNUNET_log_setup ("test_gnunet_transport_plugin_http",
1434 struct GNUNET_CONFIGURATION_Handle *cfg;
1436 cfg = GNUNET_CONFIGURATION_create ();
1438 GNUNET_assert (GNUNET_OK ==
1439 GNUNET_CONFIGURATION_load (cfg,
1440 "test_plugin_transport_data_http.conf"));
1441 if (GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "SERVICEHOME"))
1442 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME",
1444 GNUNET_DISK_directory_remove (servicehome);
1445 GNUNET_CONFIGURATION_destroy (cfg);
1448 GNUNET_PROGRAM_run (5,
1450 "test_gnunet_transport_plugin_http",
1451 "testcase", options, &run,
1452 NULL)) ? GNUNET_NO : GNUNET_YES;
1454 if (servicehome != NULL)
1456 GNUNET_DISK_directory_remove (servicehome);
1457 GNUNET_free (servicehome);
1459 if (ret != GNUNET_OK)
1464 /* end of test_gnunet_transport_plugin_http.c */