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;
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, uint32_t ats_count,
534 struct Session *session, const char *sender_address,
535 uint16_t sender_address_len)
537 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
538 "Testcase recieved new message from peer `%s' with type %u and length %u, session %X\n",
539 GNUNET_i2s (peer), ntohs (message->type), ntohs (message->size),
542 if ((ntohs (message->type) >= 10) && (ntohs (message->type) < 20))
544 fail_msgs_transmited_to_local_addrs++;
545 if (fail_msgs_transmited_to_local_addrs == count_str_addr)
546 run_connection_tests (2, session);
548 if ((ntohs (message->type) == 20))
550 fail_session_selection_reliable = GNUNET_NO;
552 if ((ntohs (message->type) == 21))
554 fail_session_selection_any = GNUNET_NO;
556 if ((ntohs (message->type) == 22))
558 fail_session_selection_session = GNUNET_NO;
560 if ((ntohs (message->type) == 23))
562 fail_session_selection_session_big = GNUNET_NO;
563 run_connection_tests (3, NULL);
565 if ((ntohs (message->type) == 30) || (ntohs (message->type) == 31))
567 fail_multiple_msgs_in_transmission++;
569 if ((ntohs (message->type) == 32) &&
570 (ntohs (message->size) == GNUNET_SERVER_MAX_MESSAGE_SIZE - 1))
572 fail_msg_transmited_max_size = GNUNET_NO;
575 return GNUNET_TIME_UNIT_ZERO;
580 send_function (void *stream, size_t size, size_t nmemb, void *ptr)
584 len = buffer_out.len;
586 if ((buffer_out.pos == len) || (len > (size * nmemb)))
588 memcpy (stream, buffer_out.buf, len);
589 buffer_out.pos = len;
595 recv_function (void *ptr, size_t size, size_t nmemb, void *ctx)
598 if (buffer_in.pos + size * nmemb > buffer_in.size)
599 return 0; /* overflow */
601 buffer_in.len = size * nmemb;
602 memcpy (&buffer_in.buf[buffer_in.pos], ptr, size * nmemb);
603 buffer_in.pos += size * nmemb;
604 buffer_in.len = buffer_in.pos;
605 buffer_in.buf[buffer_in.pos] = '\0';
606 return buffer_in.pos;
610 header_function (void *ptr, size_t size, size_t nmemb, void *stream)
612 struct HTTP_Transfer *res = stream;
614 unsigned int len = size * nmemb;
616 tmp = GNUNET_malloc (len + 1);
617 memcpy (tmp, ptr, len);
618 if (tmp[len - 2] == 13)
621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: `%s'\n", tmp);
623 if (0 == strcmp (tmp, "HTTP/1.1 100 Continue"))
625 res->http_result_code = 100;
627 if (0 == strcmp (tmp, "HTTP/1.1 200 OK"))
629 res->http_result_code = 200;
631 if (0 == strcmp (tmp, "HTTP/1.1 400 Bad Request"))
633 res->http_result_code = 400;
635 if (0 == strcmp (tmp, "HTTP/1.1 404 Not Found"))
637 res->http_result_code = 404;
639 if (0 == strcmp (tmp, "HTTP/1.1 413 Request entity too large"))
641 res->http_result_code = 413;
649 static size_t send_prepare (struct HTTP_Transfer *result);
653 send_execute (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
655 struct HTTP_Transfer *res;
661 res = (struct HTTP_Transfer *) cls;
662 http_task_send = GNUNET_SCHEDULER_NO_TASK;
663 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
669 mret = curl_multi_perform (multi_handle, &running);
675 msg = curl_multi_info_read (multi_handle, &running);
678 /* get session for affected curl handle */
679 //cs = find_session_by_curlhandle (msg->easy_handle);
680 //GNUNET_assert ( cs != NULL );
685 if ((msg->data.result != CURLE_OK) &&
686 (msg->data.result != CURLE_GOT_NOTHING))
689 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
690 _("curl failed for `%s' at %s:%d: `%s'\n"),
691 "curl_multi_perform", __FILE__, __LINE__,
692 curl_easy_strerror (msg->data.result));
693 /* sending msg failed */
694 curl_easy_cleanup (curl_handle);
697 run_connection_tests (0, NULL);
699 if (res == &test_no_ident)
701 if ((res->http_result_code == 404) && (buffer_in.len == 208))
703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
704 "Connecting to peer without any peer identification: test passed\n");
705 res->test_failed = GNUNET_NO;
708 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
710 ("Connecting to peer without any peer identification: test failed\n"));
712 if (res == &test_too_short_ident)
714 if ((res->http_result_code == 404) && (buffer_in.len == 208))
716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
717 "Connecting to peer with too short peer identification: test passed\n");
718 res->test_failed = GNUNET_NO;
721 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
723 ("Connecting to peer with too short peer identification: test failed\n"));
725 if (res == &test_too_long_ident)
727 if ((res->http_result_code == 404) && (buffer_in.len == 208))
729 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
730 "Connecting to peer with too long peer identification: test passed\n");
731 res->test_failed = GNUNET_NO;
734 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
736 ("Connecting to peer with too long peer identification: test failed\n"));
738 if (res == &test_valid_ident)
740 if ((res->http_result_code == 200))
742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
743 "Connecting to peer with valid peer identification: test passed\n");
744 res->test_failed = GNUNET_NO;
747 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
748 "Connecting to peer with valid peer identification: test failed\n");
750 curl_easy_cleanup (curl_handle);
752 if ((res == &test_valid_ident) && (res->test_failed == GNUNET_NO))
753 run_connection_tests (1, NULL);
754 run_connection_tests (0, NULL);
761 while ((running > 0));
764 while (mret == CURLM_CALL_MULTI_PERFORM);
770 * Function setting up file descriptors and scheduling task to run
771 * @param ses session to send data to
772 * @return bytes sent to peer
775 send_prepare (struct HTTP_Transfer *result)
781 struct GNUNET_NETWORK_FDSet *grs;
782 struct GNUNET_NETWORK_FDSet *gws;
790 mret = curl_multi_fdset (multi_handle, &rs, &ws, &es, &max);
791 if (mret != CURLM_OK)
793 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
794 "curl_multi_fdset", __FILE__, __LINE__,
795 curl_multi_strerror (mret));
798 mret = curl_multi_timeout (multi_handle, &to);
799 if (mret != CURLM_OK)
801 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
802 "curl_multi_timeout", __FILE__, __LINE__,
803 curl_multi_strerror (mret));
807 grs = GNUNET_NETWORK_fdset_create ();
808 gws = GNUNET_NETWORK_fdset_create ();
809 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
810 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
812 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
813 GNUNET_SCHEDULER_NO_TASK,
814 GNUNET_TIME_relative_multiply
815 (GNUNET_TIME_UNIT_SECONDS, 0), grs, gws,
816 &send_execute, result);
817 GNUNET_NETWORK_fdset_destroy (gws);
818 GNUNET_NETWORK_fdset_destroy (grs);
820 /* FIXME: return bytes REALLY sent */
825 * function to send data to server
828 send_data (struct HTTP_Transfer *result, char *url)
831 curl_handle = curl_easy_init ();
832 if (NULL == curl_handle)
834 printf ("easy_init failed \n");
835 return GNUNET_SYSERR;
838 curl_easy_setopt (curl_handle, CURLOPT_VERBOSE, 1L);
840 curl_easy_setopt (curl_handle, CURLOPT_URL, url);
841 curl_easy_setopt (curl_handle, CURLOPT_PUT, 1L);
842 curl_easy_setopt (curl_handle, CURLOPT_HEADERFUNCTION, &header_function);
843 curl_easy_setopt (curl_handle, CURLOPT_WRITEHEADER, result);
844 curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, &recv_function);
845 curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, result);
846 curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &send_function);
847 curl_easy_setopt (curl_handle, CURLOPT_READDATA, result);
848 curl_easy_setopt (curl_handle, CURLOPT_INFILESIZE_LARGE,
849 (curl_off_t) buffer_out.len);
850 curl_easy_setopt (curl_handle, CURLOPT_TIMEOUT, 30);
851 curl_easy_setopt (curl_handle, CURLOPT_CONNECTTIMEOUT, 20);
853 curl_multi_add_handle (multi_handle, curl_handle);
855 send_prepare (result);
861 * Plugin notifies transport (aka testcase) about its addresses
864 notify_address (void *cls, int add_remove, const void *addr, size_t addrlen)
866 char address[INET6_ADDRSTRLEN];
868 struct Plugin_Address *pl_addr;
869 struct Plugin_Address *cur;
871 if (addrlen == (sizeof (struct IPv4HttpAddress)))
873 inet_ntop (AF_INET, (struct in_addr *) addr, address, INET_ADDRSTRLEN);
874 port = ntohs (((struct IPv4HttpAddress *) addr)->u_port);
876 else if (addrlen == (sizeof (struct IPv6HttpAddress)))
878 inet_ntop (AF_INET6, (struct in6_addr *) addr, address, INET6_ADDRSTRLEN);
879 port = ntohs (((struct IPv6HttpAddress *) addr)->u6_port);
883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
885 ("Unknown address size: ipv6 has %u ipv4 has %u but this has %u\n"),
886 sizeof (struct IPv6HttpAddress),
887 sizeof (struct IPv4HttpAddress), addrlen);
890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
891 _("Transport plugin notification for address: `%s':%u\n"),
893 pl_addr = GNUNET_malloc (sizeof (struct Plugin_Address));
894 pl_addr->addrlen = addrlen;
895 pl_addr->addr = GNUNET_malloc (addrlen);
896 memcpy (pl_addr->addr, addr, addrlen);
897 pl_addr->next = NULL;
899 if (NULL == addr_head)
906 while (NULL != cur->next)
912 fail_notify_address_count++;
913 fail_notify_address = GNUNET_NO;
917 plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
918 struct Session *session)
920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
921 "Pluging tells me: session %X to peer `%s' ended\n", session,
927 * Setup plugin environment
930 setup_plugin_environment ()
934 env.my_identity = &my_identity;
936 env.receive = &receive;
937 env.notify_address = ¬ify_address;
938 env.max_connections = max_connect_per_transport;
939 env.session_end = &plugin_env_session_end;
944 * Task shutting down testcase if it a timeout occurs
947 task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
949 ti_timeout = GNUNET_SCHEDULER_NO_TASK;
950 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
953 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n");
961 pretty_printer_cb (void *cls, const char *address)
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin returned pretty address: `%s'\n",
967 fail_pretty_printer_count++;
971 * Runs every single test to test the plugin
974 run_connection_tests (int phase, void *cls)
976 struct GNUNET_MessageHeader *msg;
981 char *host_str = NULL;
983 /* resetting buffers */
984 buffer_in.size = HTTP_BUFFER_SIZE;
988 buffer_out.size = HTTP_BUFFER_SIZE;
992 if (test_no_ident.test_executed == GNUNET_NO)
994 /* Connecting to peer without identification */
995 const char *ident = "";
997 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
999 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1000 _("Connecting to peer without any peer identification.\n"));
1001 test_no_ident.test_executed = GNUNET_YES;
1002 send_data (&test_no_ident, host_str);
1003 GNUNET_free (host_str);
1006 if (test_too_short_ident.test_executed == GNUNET_NO)
1008 const char *ident = "AAAAAAAAAA";
1010 /* Connecting to peer with too short identification */
1011 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1015 ("Connecting to peer with too short peer identification.\n"));
1016 test_too_short_ident.test_executed = GNUNET_YES;
1017 send_data (&test_too_short_ident, host_str);
1018 GNUNET_free (host_str);
1022 if (test_too_long_ident.test_executed == GNUNET_NO)
1025 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1027 /* Connecting to peer with too long identification */
1028 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1030 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1031 _("Connecting to peer with too long peer identification.\n"));
1032 test_too_long_ident.test_executed = GNUNET_YES;
1033 send_data (&test_too_long_ident, host_str);
1034 GNUNET_free (host_str);
1037 if (test_valid_ident.test_executed == GNUNET_NO)
1039 struct GNUNET_CRYPTO_HashAsciiEncoded ident;
1041 GNUNET_CRYPTO_hash_to_enc (&my_identity.hashPubKey, &ident);
1042 GNUNET_asprintf (&host_str, "%s://%s/%s%s", PROTOCOL_PREFIX, test_addr,
1043 (char *) &ident, ";0");
1044 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1045 _("Connecting to peer with valid peer identification.\n"));
1046 test_valid_ident.test_executed = GNUNET_YES;
1047 send_data (&test_valid_ident, host_str);
1048 GNUNET_free (host_str);
1054 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1055 "\nPhase 1: transmit data to all suggested addresses\n\n");
1056 /* Using one of the addresses the plugin proposed */
1057 GNUNET_assert (addr_head->addr != NULL);
1059 struct Plugin_Address *tmp_addr;
1060 struct GNUNET_MessageHeader msg;
1061 char *tmp = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1062 char address[INET6_ADDRSTRLEN];
1064 unsigned int type = 10;
1066 msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1067 tmp_addr = addr_head;
1068 /* send a message to all addresses advertised by plugin */
1072 while (tmp_addr != NULL)
1074 if (tmp_addr->addrlen == (sizeof (struct IPv4HttpAddress)))
1076 inet_ntop (AF_INET, (struct in_addr *) tmp_addr->addr, address,
1078 port = ntohs (((struct IPv4HttpAddress *) tmp_addr->addr)->u_port);
1079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080 "Sending message to addres no. %u: `%s':%u\n", count,
1083 if (tmp_addr->addrlen == (sizeof (struct IPv6HttpAddress)))
1085 inet_ntop (AF_INET6, (struct in6_addr *) tmp_addr->addr, address,
1087 port = ntohs (((struct IPv6HttpAddress *) tmp_addr->addr)->u6_port);
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089 "Sending message to addres no. %u: `%s':%u\n", count,
1092 msg.type = htons (type);
1093 memcpy (tmp, &msg, sizeof (struct GNUNET_MessageHeader));
1094 api->send (api->cls, &my_identity, tmp,
1095 sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL,
1096 tmp_addr->addr, tmp_addr->addrlen, GNUNET_YES, &task_send_cont,
1097 &fail_msgs_transmited_to_local_addrs);
1098 tmp_addr = tmp_addr->next;
1108 struct Session *session = cls;
1110 msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1112 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 2: session selection\n\n");
1113 size = sizeof (struct GNUNET_MessageHeader);
1114 msg->size = htons (size);
1115 msg->type = htons (20);
1116 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1117 NULL, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1119 msg->type = htons (21);
1120 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1121 NULL, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL);
1123 /* answer on session */
1124 size = sizeof (struct GNUNET_MessageHeader);
1125 msg->size = htons (size);
1126 msg->type = htons (22);
1127 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1128 session, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL);
1131 /* answer on session with big message not fitting in mhd send buffer */
1132 size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1133 msg = GNUNET_malloc (size);
1134 msg->size = htons (size);
1135 msg->type = htons (23);
1136 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1137 session, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1146 "Phase 3: send multiple or big messages after disconnect\n\n");
1147 /* disconnect from peer, so new connections are created */
1148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect from peer: `%s'\n",
1149 GNUNET_i2s (&my_identity));
1150 api->disconnect (api->cls, &my_identity);
1152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Phase 3: sending messages\n");
1153 /* send a multiple GNUNET_messages at a time */
1154 size = 2 * sizeof (struct GNUNET_MessageHeader);
1155 msg = GNUNET_malloc (2 * size);
1156 msg->size = htons (size);
1157 msg->type = htons (30);
1158 struct GNUNET_MessageHeader *msg2 = &msg[2];
1160 msg2->size = htons (2 * sizeof (struct GNUNET_MessageHeader));
1161 msg2->type = htons (31);
1162 api->send (api->cls, &my_identity, (const char *) msg,
1163 4 * sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL,
1164 addr_head->addr, addr_head->addrlen, GNUNET_NO, &task_send_cont,
1165 &fail_multiple_msgs_in_transmission);
1167 /* send a message with size GNUNET_SERVER_MAX_MESSAGE_SIZE-1 */
1169 size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1170 msg = GNUNET_malloc (size);
1171 msg->size = htons (size);
1172 msg->type = htons (32);
1173 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1174 NULL, addr_head->addr, addr_head->addrlen, GNUNET_NO,
1175 &task_send_cont, &fail_msg_transmited_max_size);
1177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more tests to run\n");
1185 * @param cls closure
1186 * @param c configuration to use
1189 run (void *cls, char *const *args, const char *cfgfile,
1190 const struct GNUNET_CONFIGURATION_Handle *c)
1196 unsigned long long tneigh;
1197 struct Plugin_Address *cur;
1198 const char *addr_str;
1201 unsigned int suggest_res;
1203 fail_pretty_printer = GNUNET_YES;
1204 fail_notify_address = GNUNET_YES;
1205 fail_addr_to_str = GNUNET_YES;
1206 fail_msgs_transmited_to_local_addrs = 0;
1207 fail_msg_transmited_max_size = GNUNET_YES;
1208 fail_multiple_msgs_in_transmission = 0;
1209 fail_session_selection_reliable = GNUNET_YES;
1210 fail_session_selection_reliable = GNUNET_YES;
1211 fail_session_selection_session = GNUNET_YES;
1212 fail_session_selection_session_big = GNUNET_YES;
1216 /* parse configuration */
1217 if (GNUNET_CONFIGURATION_have_value (c, "PATHS", "SERVICEHOME"))
1218 GNUNET_CONFIGURATION_get_value_string (c, "PATHS", "SERVICEHOME",
1222 GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", "NEIGHBOUR_LIMIT",
1225 GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
1228 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1230 ("Transport service is lacking key configuration settings. Exiting.\n"));
1231 GNUNET_SCHEDULER_shutdown ();
1237 GNUNET_CONFIGURATION_get_value_number (cfg, "transport-http", "PORT",
1238 &port)) || (port > 65535) ||
1241 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "http",
1243 ("Require valid port number for transport plugin `%s' in configuration!\n"),
1247 max_connect_per_transport = (uint32_t) tneigh;
1248 my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
1249 GNUNET_free (keyfile);
1250 if (my_private_key == NULL)
1252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1253 _("Transport service could not access hostkey. Exiting.\n"));
1254 GNUNET_SCHEDULER_shutdown ();
1259 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
1260 GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
1261 &my_identity.hashPubKey);
1263 /* assertions before start */
1264 GNUNET_assert ((port > 0) && (port <= 65535));
1266 /* load plugins... */
1267 setup_plugin_environment ();
1268 GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http");
1269 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading HTTP transport plugin `%s'\n"),
1271 api = GNUNET_PLUGIN_load (libname, &env);
1272 GNUNET_free (libname);
1275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1276 _("Failed to load transport plugin for http\n"));
1282 ti_timeout = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &task_timeout, NULL);
1284 /* testing plugin functionality */
1285 GNUNET_assert (0 != fail_notify_address_count);
1286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1287 "Transport plugin returned %u addresses to connect to\n",
1288 fail_notify_address_count);
1290 /* testing pretty printer with all addresses obtained from the plugin */
1294 api->address_pretty_printer (api->cls, "http", cur->addr, cur->addrlen,
1295 GNUNET_NO, TEST_TIMEOUT, &pretty_printer_cb,
1297 addr_str = api->address_to_string (api->cls, cur->addr, cur->addrlen);
1298 suggest_res = api->check_address (api->cls, cur->addr, cur->addrlen);
1300 GNUNET_assert (GNUNET_OK == suggest_res);
1301 GNUNET_assert (NULL != addr_str);
1303 GNUNET_free ((char *) addr_str);
1306 GNUNET_assert (fail_pretty_printer_count > 0);
1307 GNUNET_assert (fail_pretty_printer_count == fail_notify_address_count);
1308 GNUNET_assert (fail_pretty_printer_count == count_str_addr);
1309 fail_pretty_printer = GNUNET_NO;
1310 fail_addr_to_str = GNUNET_NO;
1312 struct IPv4HttpAddress failing_addr;
1314 /* Suggesting addresses with wrong size */
1315 failing_addr.ipv4_addr = htonl (INADDR_LOOPBACK);
1316 failing_addr.u_port = htons (0);
1318 api->check_address (api->cls, &failing_addr,
1319 sizeof (struct IPv6HttpAddress));
1320 GNUNET_assert (GNUNET_SYSERR == suggest_res);
1322 /* Suggesting addresses with wrong address */
1323 failing_addr.ipv4_addr = htonl (0xffc00000);
1324 failing_addr.u_port = htons (12389);
1325 suggest_res = api->check_address (api->cls, &failing_addr, 100);
1326 GNUNET_assert (GNUNET_SYSERR == suggest_res);
1328 /* test sending to client */
1329 multi_handle = curl_multi_init ();
1331 /* Setting up buffers */
1332 buffer_in.size = HTTP_BUFFER_SIZE;
1336 buffer_out.size = HTTP_BUFFER_SIZE;
1340 /* Setting up connection tests */
1342 /* Test: connecting without a peer identification */
1343 test_no_ident.test_executed = GNUNET_NO;
1344 test_no_ident.test_failed = GNUNET_YES;
1346 /* Test: connecting with too short peer identification */
1347 test_too_short_ident.test_executed = GNUNET_NO;
1348 test_too_short_ident.test_failed = GNUNET_YES;
1350 /* Test: connecting with too long peer identification */
1351 test_too_long_ident.test_executed = GNUNET_NO;
1352 test_too_long_ident.test_failed = GNUNET_YES;
1354 /* Test: connecting with valid identification */
1355 test_valid_ident.test_executed = GNUNET_NO;
1356 test_valid_ident.test_failed = GNUNET_YES;
1359 (char *) api->address_to_string (api->cls, addr_head->addr,
1360 addr_head->addrlen);
1362 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Phase 0\n\n"));
1363 run_connection_tests (0, NULL);
1364 /* testing finished */
1369 * The main function for the transport service.
1371 * @param argc number of arguments from the command line
1372 * @param argv command line arguments
1373 * @return 0 ok, 1 on error
1376 main (int argc, char *const *argv)
1378 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1379 GNUNET_GETOPT_OPTION_END
1383 char *const argv_prog[] = {
1384 "test_gnunet_transport_plugin_http",
1386 "test_plugin_transport_data_http.conf",
1395 GNUNET_log_setup ("test_gnunet_transport_plugin_http",
1403 struct GNUNET_CONFIGURATION_Handle *cfg;
1405 cfg = GNUNET_CONFIGURATION_create ();
1407 GNUNET_assert (GNUNET_OK ==
1408 GNUNET_CONFIGURATION_load (cfg,
1409 "test_plugin_transport_data_http.conf"));
1410 if (GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "SERVICEHOME"))
1411 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME",
1413 GNUNET_DISK_directory_remove (servicehome);
1414 GNUNET_CONFIGURATION_destroy (cfg);
1418 GNUNET_PROGRAM_run (5, argv_prog, "test_gnunet_transport_plugin_http",
1419 "testcase", options, &run,
1420 NULL)) ? GNUNET_NO : GNUNET_YES;
1422 if (servicehome != NULL)
1424 GNUNET_DISK_directory_remove (servicehome);
1425 GNUNET_free (servicehome);
1427 if (ret != GNUNET_OK)
1432 /* end of test_gnunet_transport_plugin_http.c */