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_https.c
22 * @brief testcase for plugin_transport_https.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 PLUGIN libgnunet_plugin_transport_template
51 #define PROTOCOL_PREFIX "https"
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;
206 /* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */
211 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
216 static struct GNUNET_PeerIdentity my_identity;
221 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
226 static long long unsigned int port;
231 static char *test_addr;
234 * Our statistics handle.
236 struct GNUNET_STATISTICS_Handle *stats;
242 const struct GNUNET_CONFIGURATION_Handle *cfg;
245 * Number of neighbours we'd like to have.
247 static uint32_t max_connect_per_transport;
250 * Environment for this plugin.
252 static struct GNUNET_TRANSPORT_PluginEnvironment env;
255 *handle for the api provided by this plugin
257 static struct GNUNET_TRANSPORT_PluginFunctions *api;
260 * ID of the task controlling the testcase timeout
262 static GNUNET_SCHEDULER_TaskIdentifier ti_timeout;
264 static GNUNET_SCHEDULER_TaskIdentifier ti_send;
266 //const struct GNUNET_PeerIdentity * p;
269 * buffer for data to send
271 static struct HTTP_Message buffer_out;
274 * buffer for data to recieve
276 static struct HTTP_Message buffer_in;
279 struct Plugin_Address *addr_head;
282 * Did the test pass or fail?
284 static int fail_notify_address;
287 * Did the test pass or fail?
289 static int fail_notify_address_count;
292 * Did the test pass or fail?
294 static int fail_pretty_printer;
297 * Did the test pass or fail?
299 static int fail_pretty_printer_count;
302 * Did the test pass or fail?
304 static int fail_addr_to_str;
307 * No. of msgs transmitted successfully to local addresses
309 static int fail_msgs_transmited_to_local_addrs;
312 * Test: transmit msg of max. size
314 static int fail_msg_transmited_bigger_max_size;
317 * Test: transmit msg of max. size
319 static int fail_msg_transmited_max_size;
322 * Test: transmit 2 msgs. in in send operation
324 static int fail_multiple_msgs_in_transmission;
327 * Test: connect to peer without peer identification
329 static struct HTTP_Transfer test_no_ident;
332 * Test: connect to peer without peer identification
334 static struct HTTP_Transfer test_too_short_ident;
337 * Test: connect to peer without peer identification
339 static struct HTTP_Transfer test_too_long_ident;
342 * Test: connect to peer with valid peer identification
344 static struct HTTP_Transfer test_valid_ident;
347 * Test: session selection, use any existing
349 static int fail_session_selection_any;
352 * Test: session selection, use existing inbound session
354 static int fail_session_selection_session;
357 * Test: session selection, use existing inbound session
358 * max message, not fitting in send & recv buffers at one time
360 static int fail_session_selection_session_big;
363 * Test: session selection, use reliable existing
365 static int fail_session_selection_reliable;
368 * Did the test pass or fail?
373 * Number of local addresses
375 static unsigned int count_str_addr;
382 static CURLM *multi_handle;
385 * The task sending data
387 static GNUNET_SCHEDULER_TaskIdentifier http_task_send;
390 static char *key_file;
391 static char *cert_file;
393 static char *servicehome;
401 struct Plugin_Address *tmp;
403 /* Evaluate results */
405 if ((fail_notify_address == GNUNET_YES) || (fail_pretty_printer == GNUNET_YES)
406 || (fail_addr_to_str == GNUNET_YES))
408 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
409 _("Phase 0: Test plugin functions failed\n"));
412 if ((test_no_ident.test_failed == GNUNET_YES) ||
413 (test_too_short_ident.test_failed == GNUNET_YES) ||
414 (test_too_long_ident.test_failed == GNUNET_YES) ||
415 (test_valid_ident.test_failed == GNUNET_YES))
417 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
418 _("Phase 1: Test connect with wrong data failed\n"));
421 if ((fail_session_selection_any != GNUNET_NO) ||
422 (fail_session_selection_reliable != GNUNET_NO) ||
423 (fail_session_selection_session != GNUNET_NO) ||
424 (fail_session_selection_session_big != GNUNET_NO))
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427 _("Phase 2: Test session selection failed\n"));
430 if ((fail_msgs_transmited_to_local_addrs != count_str_addr) ||
431 (fail_multiple_msgs_in_transmission != 2) ||
432 (fail_msg_transmited_max_size == GNUNET_YES))
434 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
435 _("Phase 3: Test sending with plugin failed\n"));
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All tests successful\n");
443 api->disconnect (api->cls, &my_identity);
445 curl_multi_cleanup (multi_handle);
447 if (NULL != curl_handle)
448 curl_easy_cleanup (curl_handle);
450 /* cleaning addresses */
451 while (addr_head != NULL)
453 tmp = addr_head->next;
454 GNUNET_free (addr_head->addr);
455 GNUNET_free (addr_head);
459 if (ti_send != GNUNET_SCHEDULER_NO_TASK)
461 GNUNET_SCHEDULER_cancel (ti_send);
462 ti_send = GNUNET_SCHEDULER_NO_TASK;
465 if (http_task_send != GNUNET_SCHEDULER_NO_TASK)
467 GNUNET_SCHEDULER_cancel (http_task_send);
468 http_task_send = GNUNET_SCHEDULER_NO_TASK;
471 if (ti_timeout != GNUNET_SCHEDULER_NO_TASK)
473 GNUNET_SCHEDULER_cancel (ti_timeout);
474 ti_timeout = GNUNET_SCHEDULER_NO_TASK;
477 GNUNET_free (test_addr);
478 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unloading https plugin\n");
479 GNUNET_assert (NULL ==
481 ("libgnunet_gnunet_transport_plugin.https", api));
483 GNUNET_SCHEDULER_shutdown ();
484 GNUNET_DISK_directory_remove ("/tmp/test_gnunet_transport_plugin.http");
488 if (0 == stat (cert_file, &sbuf))
490 if (0 == remove (cert_file))
491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
492 "Successfully removed existing certificate file `%s'\n",
495 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to remove certfile `%s'\n",
499 if (0 == stat (key_file, &sbuf))
501 if (0 == remove (key_file))
502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
503 "Successfully removed private key file `%s'\n", key_file);
505 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to private key file `%s'\n",
509 GNUNET_free (key_file);
510 GNUNET_free (cert_file);
512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exiting testcase\n");
514 if (servicehome != NULL)
516 GNUNET_DISK_directory_remove (servicehome);
517 GNUNET_free (servicehome);
526 * Continuation called after plugin send message
529 * @result GNUNET_OK or GNUNET_SYSERR
533 task_send_cont (void *cls, const struct GNUNET_PeerIdentity *target, int result)
535 if ((cls == &fail_msg_transmited_bigger_max_size) &&
536 (result == GNUNET_SYSERR))
538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
539 "Message bigger max msg size was not sent!\n");
540 fail_msg_transmited_bigger_max_size = GNUNET_NO;
544 if ((cls == &fail_msg_transmited_max_size) && (result == GNUNET_OK))
546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
547 "Message with max msg size succesfully sent!\n",
548 fail_msgs_transmited_to_local_addrs);
549 fail_msg_transmited_max_size = GNUNET_NO;
555 run_connection_tests (int phase, void *cls);
558 * Recieves messages from plugin, in real world transport
560 static struct GNUNET_TIME_Relative
561 receive (void *cls, const struct GNUNET_PeerIdentity *peer,
562 const struct GNUNET_MessageHeader *message,
563 const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count,
564 struct Session *session, const char *sender_address,
565 uint16_t sender_address_len)
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
568 "Testcase recieved new message from peer `%s' with type %u and length %u, session %X\n",
569 GNUNET_i2s (peer), ntohs (message->type), ntohs (message->size),
572 if ((ntohs (message->type) >= 10) && (ntohs (message->type) < 20))
574 fail_msgs_transmited_to_local_addrs++;
575 if (fail_msgs_transmited_to_local_addrs == count_str_addr)
576 run_connection_tests (2, session);
580 if ((ntohs (message->type) == 20))
582 fail_session_selection_reliable = GNUNET_NO;
585 if ((ntohs (message->type) == 21))
587 fail_session_selection_any = GNUNET_NO;
589 if ((ntohs (message->type) == 22))
591 fail_session_selection_session = GNUNET_NO;
594 if ((ntohs (message->type) == 23))
596 fail_session_selection_session_big = GNUNET_NO;
597 run_connection_tests (3, NULL);
600 if ((ntohs (message->type) == 30) || (ntohs (message->type) == 31))
602 fail_multiple_msgs_in_transmission++;
605 if ((ntohs (message->type) == 32) &&
606 (ntohs (message->size) == GNUNET_SERVER_MAX_MESSAGE_SIZE - 1))
608 fail_msg_transmited_max_size = GNUNET_NO;
612 return GNUNET_TIME_UNIT_ZERO;
616 send_function (void *stream, size_t size, size_t nmemb, void *ptr)
620 len = buffer_out.len;
622 if ((buffer_out.pos == len) || (len > (size * nmemb)))
624 memcpy (stream, buffer_out.buf, len);
625 buffer_out.pos = len;
630 recv_function (void *ptr, size_t size, size_t nmemb, void *ctx)
633 if (buffer_in.pos + size * nmemb > buffer_in.size)
634 return 0; /* overflow */
636 buffer_in.len = size * nmemb;
637 memcpy (&buffer_in.buf[buffer_in.pos], ptr, size * nmemb);
638 buffer_in.pos += size * nmemb;
639 buffer_in.len = buffer_in.pos;
640 buffer_in.buf[buffer_in.pos] = '\0';
641 return buffer_in.pos;
645 header_function (void *ptr, size_t size, size_t nmemb, void *stream)
647 struct HTTP_Transfer *res = (struct HTTP_Transfer *) stream;
649 unsigned int len = size * nmemb;
651 tmp = GNUNET_malloc (len + 1);
652 memcpy (tmp, ptr, len);
653 if (tmp[len - 2] == 13)
656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: `%s'\n", tmp);
658 if (0 == strcmp (tmp, "HTTP/1.1 100 Continue"))
660 res->http_result_code = 100;
662 if (0 == strcmp (tmp, "HTTP/1.1 200 OK"))
664 res->http_result_code = 200;
666 if (0 == strcmp (tmp, "HTTP/1.1 400 Bad Request"))
668 res->http_result_code = 400;
670 if (0 == strcmp (tmp, "HTTP/1.1 404 Not Found"))
672 res->http_result_code = 404;
674 if (0 == strcmp (tmp, "HTTP/1.1 413 Request entity too large"))
676 res->http_result_code = 413;
684 send_prepare (struct HTTP_Transfer *result);
689 send_execute (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
691 struct HTTP_Transfer *res;
697 res = (struct HTTP_Transfer *) cls;
698 http_task_send = GNUNET_SCHEDULER_NO_TASK;
699 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
705 mret = curl_multi_perform (multi_handle, &running);
711 msg = curl_multi_info_read (multi_handle, &running);
714 /* get session for affected curl handle */
715 //cs = find_session_by_curlhandle (msg->easy_handle);
716 //GNUNET_assert ( cs != NULL );
721 if ((msg->data.result != CURLE_OK) &&
722 (msg->data.result != CURLE_GOT_NOTHING))
725 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
726 _("curl failed for `%s' at %s:%d: `%s'\n"),
727 "curl_multi_perform", __FILE__, __LINE__,
728 curl_easy_strerror (msg->data.result));
729 /* sending msg failed */
730 curl_easy_cleanup (curl_handle);
733 run_connection_tests (0, NULL);
735 if (res == &test_no_ident)
737 if ((res->http_result_code == 404) && (buffer_in.len == 208))
739 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
740 "Connecting to peer without any peer identification: test passed\n");
741 res->test_failed = GNUNET_NO;
744 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
746 ("Connecting to peer without any peer identification: test failed\n"));
748 if (res == &test_too_short_ident)
750 if ((res->http_result_code == 404) && (buffer_in.len == 208))
752 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
753 "Connecting to peer with too short peer identification: test passed\n");
754 res->test_failed = GNUNET_NO;
757 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
759 ("Connecting to peer with too short peer identification: test failed\n"));
761 if (res == &test_too_long_ident)
763 if ((res->http_result_code == 404) && (buffer_in.len == 208))
765 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
766 "Connecting to peer with too long peer identification: test passed\n");
767 res->test_failed = GNUNET_NO;
770 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
772 ("Connecting to peer with too long peer identification: test failed\n"));
774 if (res == &test_valid_ident)
776 if ((res->http_result_code == 200))
778 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
779 "Connecting to peer with valid peer identification: test passed\n");
780 res->test_failed = GNUNET_NO;
783 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
785 ("Connecting to peer with valid peer identification: test failed\n"));
787 curl_easy_cleanup (curl_handle);
789 if ((res == &test_valid_ident) && (res->test_failed == GNUNET_NO))
790 run_connection_tests (1, NULL);
791 run_connection_tests (0, NULL);
798 while ((running > 0));
801 while (mret == CURLM_CALL_MULTI_PERFORM);
806 * Function setting up file descriptors and scheduling task to run
807 * @param ses session to send data to
808 * @return bytes sent to peer
811 send_prepare (struct HTTP_Transfer *result)
817 struct GNUNET_NETWORK_FDSet *grs;
818 struct GNUNET_NETWORK_FDSet *gws;
826 mret = curl_multi_fdset (multi_handle, &rs, &ws, &es, &max);
827 if (mret != CURLM_OK)
829 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
830 "curl_multi_fdset", __FILE__, __LINE__,
831 curl_multi_strerror (mret));
834 mret = curl_multi_timeout (multi_handle, &to);
835 if (mret != CURLM_OK)
837 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("%s failed at %s:%d: `%s'\n"),
838 "curl_multi_timeout", __FILE__, __LINE__,
839 curl_multi_strerror (mret));
843 grs = GNUNET_NETWORK_fdset_create ();
844 gws = GNUNET_NETWORK_fdset_create ();
845 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
846 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
848 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
849 GNUNET_SCHEDULER_NO_TASK,
850 GNUNET_TIME_relative_multiply
851 (GNUNET_TIME_UNIT_SECONDS, 0), grs, gws,
852 &send_execute, result);
853 GNUNET_NETWORK_fdset_destroy (gws);
854 GNUNET_NETWORK_fdset_destroy (grs);
856 /* FIXME: return bytes REALLY sent */
861 * function to send data to server
864 send_data (struct HTTP_Transfer *result, char *url)
867 curl_handle = curl_easy_init ();
868 if (NULL == curl_handle)
870 printf ("easy_init failed \n");
871 return GNUNET_SYSERR;
874 curl_easy_setopt (curl_handle, CURLOPT_VERBOSE, 1L);
876 curl_easy_setopt (curl_handle, CURLOPT_URL, url);
877 curl_easy_setopt (curl_handle, CURLOPT_PUT, 1L);
878 //curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
879 curl_easy_setopt (curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
880 curl_easy_setopt (curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
881 curl_easy_setopt (curl_handle, CURLOPT_HEADERFUNCTION, &header_function);
882 curl_easy_setopt (curl_handle, CURLOPT_WRITEHEADER, result);
883 curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, &recv_function);
884 curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, result);
885 curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &send_function);
886 curl_easy_setopt (curl_handle, CURLOPT_READDATA, result);
887 curl_easy_setopt (curl_handle, CURLOPT_INFILESIZE_LARGE,
888 (curl_off_t) buffer_out.len);
889 curl_easy_setopt (curl_handle, CURLOPT_TIMEOUT, 30);
890 curl_easy_setopt (curl_handle, CURLOPT_CONNECTTIMEOUT, 20);
892 curl_multi_add_handle (multi_handle, curl_handle);
894 send_prepare (result);
900 * Plugin notifies transport (aka testcase) about its addresses
903 notify_address (void *cls, int add_remove, const void *addr, size_t addrlen)
905 char address[INET6_ADDRSTRLEN];
907 struct Plugin_Address *pl_addr;
908 struct Plugin_Address *cur;
910 if (addrlen == (sizeof (struct IPv4HttpAddress)))
912 inet_ntop (AF_INET, (struct in_addr *) addr, address, INET_ADDRSTRLEN);
913 port = ntohs (((struct IPv4HttpAddress *) addr)->u_port);
915 else if (addrlen == (sizeof (struct IPv6HttpAddress)))
917 inet_ntop (AF_INET6, (struct in6_addr *) addr, address, INET6_ADDRSTRLEN);
918 port = ntohs (((struct IPv6HttpAddress *) addr)->u6_port);
922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
924 ("Unknown address size: ipv6 has %u ipv4 has %u but this has %u\n"),
925 sizeof (struct IPv6HttpAddress),
926 sizeof (struct IPv4HttpAddress), addrlen);
929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
930 _("Transport plugin notification for address: `%s':%u\n"),
932 pl_addr = GNUNET_malloc (sizeof (struct Plugin_Address));
933 pl_addr->addrlen = addrlen;
934 pl_addr->addr = GNUNET_malloc (addrlen);
935 memcpy (pl_addr->addr, addr, addrlen);
936 pl_addr->next = NULL;
938 if (NULL == addr_head)
945 while (NULL != cur->next)
951 fail_notify_address_count++;
952 fail_notify_address = GNUNET_NO;
956 plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
957 struct Session *session)
959 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
960 "Pluging tells me: session %X to peer `%s' ended\n", session,
966 * Setup plugin environment
969 setup_plugin_environment ()
973 env.my_identity = &my_identity;
975 env.receive = &receive;
976 env.notify_address = ¬ify_address;
977 env.max_connections = max_connect_per_transport;
978 env.session_end = &plugin_env_session_end;
983 * Task shutting down testcase if it a timeout occurs
986 task_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
988 ti_timeout = GNUNET_SCHEDULER_NO_TASK;
989 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
992 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n");
999 pretty_printer_cb (void *cls, const char *address)
1001 if (NULL == address)
1003 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plugin returned pretty address: `%s'\n",
1005 fail_pretty_printer_count++;
1009 * Runs every single test to test the plugin
1012 run_connection_tests (int phase, void *cls)
1014 struct GNUNET_MessageHeader *msg;
1019 char *host_str = NULL;
1021 /* resetting buffers */
1022 buffer_in.size = HTTP_BUFFER_SIZE;
1026 buffer_out.size = HTTP_BUFFER_SIZE;
1030 if (test_no_ident.test_executed == GNUNET_NO)
1032 /* Connecting to peer without identification */
1035 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1037 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1038 _("Connecting to peer without any peer identification.\n"));
1039 test_no_ident.test_executed = GNUNET_YES;
1040 send_data (&test_no_ident, host_str);
1041 GNUNET_free (host_str);
1044 if (test_too_short_ident.test_executed == GNUNET_NO)
1046 char *ident = "AAAAAAAAAA";
1048 /* Connecting to peer with too short identification */
1049 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1051 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1053 ("Connecting to peer with too short peer identification.\n"));
1054 test_too_short_ident.test_executed = GNUNET_YES;
1055 send_data (&test_too_short_ident, host_str);
1056 GNUNET_free (host_str);
1060 if (test_too_long_ident.test_executed == GNUNET_NO)
1063 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
1065 /* Connecting to peer with too long identification */
1066 GNUNET_asprintf (&host_str, "%s://%s/%s", PROTOCOL_PREFIX, test_addr,
1068 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1069 _("Connecting to peer with too long peer identification.\n"));
1070 test_too_long_ident.test_executed = GNUNET_YES;
1071 send_data (&test_too_long_ident, host_str);
1072 GNUNET_free (host_str);
1075 if (test_valid_ident.test_executed == GNUNET_NO)
1077 struct GNUNET_CRYPTO_HashAsciiEncoded ident;
1079 GNUNET_CRYPTO_hash_to_enc (&my_identity.hashPubKey, &ident);
1080 GNUNET_asprintf (&host_str, "%s://%s/%s%s", PROTOCOL_PREFIX, test_addr,
1081 (char *) &ident, ";0");
1082 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1083 _("Connecting to peer with valid peer identification.\n"));
1084 test_valid_ident.test_executed = GNUNET_YES;
1085 send_data (&test_valid_ident, host_str);
1086 GNUNET_free (host_str);
1092 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1093 _("\nPhase 1: transmit data to all suggested addresses\n\n"));
1094 /* Using one of the addresses the plugin proposed */
1095 GNUNET_assert (addr_head->addr != NULL);
1097 struct Plugin_Address *tmp_addr;
1098 struct GNUNET_MessageHeader msg;
1099 char *tmp = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1100 char address[INET6_ADDRSTRLEN];
1102 unsigned int type = 10;
1104 msg.size = htons (sizeof (struct GNUNET_MessageHeader));
1105 tmp_addr = addr_head;
1106 /* send a message to all addresses advertised by plugin */
1110 while (tmp_addr != NULL)
1112 if (tmp_addr->addrlen == (sizeof (struct IPv4HttpAddress)))
1114 inet_ntop (AF_INET, (struct in_addr *) tmp_addr->addr, address,
1116 port = ntohs (((struct IPv4HttpAddress *) tmp_addr->addr)->u_port);
1117 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1118 "Sending message to addres no. %u: `%s':%u\n", count,
1121 if (tmp_addr->addrlen == (sizeof (struct IPv6HttpAddress)))
1123 inet_ntop (AF_INET6, (struct in6_addr *) tmp_addr->addr, address,
1125 port = ntohs (((struct IPv6HttpAddress *) tmp_addr->addr)->u6_port);
1126 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1127 "Sending message to addres no. %u: `%s':%u\n", count,
1130 msg.type = htons (type);
1131 memcpy (tmp, &msg, sizeof (struct GNUNET_MessageHeader));
1132 api->send (api->cls, &my_identity, tmp,
1133 sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL,
1134 tmp_addr->addr, tmp_addr->addrlen, GNUNET_YES, &task_send_cont,
1135 &fail_msgs_transmited_to_local_addrs);
1136 tmp_addr = tmp_addr->next;
1147 struct Session *session = cls;
1149 msg = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader));
1151 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("\nPhase 2: session selection\n\n"));
1152 size = sizeof (struct GNUNET_MessageHeader);
1153 msg->size = htons (size);
1154 msg->type = htons (20);
1155 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1156 NULL, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1158 msg->type = htons (21);
1159 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1160 NULL, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL);
1162 /* answer on session */
1163 size = sizeof (struct GNUNET_MessageHeader);
1164 msg->size = htons (size);
1165 msg->type = htons (22);
1166 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1167 session, NULL, 0, GNUNET_SYSERR, &task_send_cont, NULL);
1171 /* answer on session with big message not fitting in mhd send buffer */
1172 size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1173 msg = GNUNET_malloc (size);
1174 msg->size = htons (size);
1175 msg->type = htons (23);
1176 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1177 session, NULL, 0, GNUNET_NO, &task_send_cont, NULL);
1185 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1187 ("\nPhase 3: send multiple or big messages after disconnect\n\n"));
1188 /* disconnect from peer, so new connections are created */
1189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect from peer: `%s'\n",
1190 GNUNET_i2s (&my_identity));
1191 api->disconnect (api->cls, &my_identity);
1193 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Phase 3: sending messages\n"));
1194 /* send a multiple GNUNET_messages at a time */
1195 size = 2 * sizeof (struct GNUNET_MessageHeader);
1196 msg = GNUNET_malloc (2 * size);
1197 msg->size = htons (size);
1198 msg->type = htons (30);
1199 struct GNUNET_MessageHeader *msg2 = &msg[2];
1201 msg2->size = htons (2 * sizeof (struct GNUNET_MessageHeader));
1202 msg2->type = htons (31);
1203 api->send (api->cls, &my_identity, (const char *) msg,
1204 4 * sizeof (struct GNUNET_MessageHeader), 0, TIMEOUT, NULL,
1205 addr_head->addr, addr_head->addrlen, GNUNET_NO, &task_send_cont,
1206 &fail_multiple_msgs_in_transmission);
1208 /* send a message with size GNUNET_SERVER_MAX_MESSAGE_SIZE-1 */
1210 size = GNUNET_SERVER_MAX_MESSAGE_SIZE - 1;
1211 msg = GNUNET_malloc (size);
1212 msg->size = htons (size);
1213 msg->type = htons (32);
1214 api->send (api->cls, &my_identity, (const char *) msg, size, 0, TIMEOUT,
1215 NULL, addr_head->addr, addr_head->addrlen, GNUNET_NO,
1216 &task_send_cont, &fail_msg_transmited_max_size);
1218 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No more tests to run\n");
1226 * @param cls closure
1227 * @param c configuration to use
1230 run (void *cls, char *const *args, const char *cfgfile,
1231 const struct GNUNET_CONFIGURATION_Handle *c)
1237 unsigned long long tneigh;
1238 struct Plugin_Address *cur;
1239 const char *addr_str;
1241 unsigned int suggest_res;
1243 fail_pretty_printer = GNUNET_YES;
1244 fail_notify_address = GNUNET_YES;
1245 fail_addr_to_str = GNUNET_YES;
1246 fail_msgs_transmited_to_local_addrs = 0;
1247 fail_msg_transmited_max_size = GNUNET_YES;
1248 fail_multiple_msgs_in_transmission = 0;
1249 fail_session_selection_reliable = GNUNET_YES;
1250 fail_session_selection_reliable = GNUNET_YES;
1251 fail_session_selection_session = GNUNET_YES;
1252 fail_session_selection_session_big = GNUNET_YES;
1256 /* parse configuration */
1257 if (GNUNET_CONFIGURATION_have_value (c, "PATHS", "SERVICEHOME"))
1258 GNUNET_CONFIGURATION_get_value_string (c, "PATHS", "SERVICEHOME",
1263 GNUNET_CONFIGURATION_get_value_number (c, "TRANSPORT", "NEIGHBOUR_LIMIT",
1266 GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
1269 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1271 ("Transport service is lacking key configuration settings. Exiting.\n"));
1272 GNUNET_SCHEDULER_shutdown ();
1278 GNUNET_CONFIGURATION_get_value_number (cfg, "transport-https", "PORT",
1279 &port)) || (port > 65535) ||
1282 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "https",
1284 ("Require valid port number for transport plugin `%s' in configuration!\n"),
1288 /* Get private key file from config */
1289 if (GNUNET_CONFIGURATION_have_value (cfg, "transport-https", "KEY_FILE"))
1291 GNUNET_CONFIGURATION_get_value_string (cfg, "transport-https", "KEY_FILE",
1294 if (key_file == NULL)
1295 GNUNET_asprintf (&key_file, "https.key");
1297 if (0 == stat (key_file, &sbuf))
1299 if (0 == remove (key_file))
1300 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1301 "Successfully removed existing private key file `%s'\n",
1304 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1305 "Failed to remove private key file `%s'\n", key_file);
1308 /* Get private key file from config */
1309 if (GNUNET_CONFIGURATION_have_value (cfg, "transport-https", "CERT_FILE"))
1311 GNUNET_CONFIGURATION_get_value_string (cfg, "transport-https", "CERT_FILE",
1314 if (cert_file == NULL)
1315 GNUNET_asprintf (&cert_file, "https.cert");
1317 if (0 == stat (cert_file, &sbuf))
1319 if (0 == remove (cert_file))
1320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1321 "Successfully removed existing certificate file `%s'\n",
1324 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1325 "Failed to remove existing certificate file `%s'\n",
1329 max_connect_per_transport = (uint32_t) tneigh;
1330 my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
1331 GNUNET_free (keyfile);
1332 if (my_private_key == NULL)
1334 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1335 _("Transport service could not access hostkey. Exiting.\n"));
1336 GNUNET_SCHEDULER_shutdown ();
1341 GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
1342 GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
1343 &my_identity.hashPubKey);
1345 /* assertions before start */
1346 GNUNET_assert ((port > 0) && (port <= 65535));
1348 /* load plugins... */
1349 setup_plugin_environment ();
1350 GNUNET_asprintf (&libname, "libgnunet_plugin_transport_https");
1351 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1352 _("Loading HTTPS transport plugin `%s'\n"), libname);
1353 api = GNUNET_PLUGIN_load (libname, &env);
1354 GNUNET_free (libname);
1357 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1358 _("Failed to load transport plugin for https\n"));
1363 ti_timeout = GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &task_timeout, NULL);
1365 /* testing plugin functionality */
1366 GNUNET_assert (0 != fail_notify_address_count);
1367 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1368 _("Transport plugin returned %u addresses to connect to\n"),
1369 fail_notify_address_count);
1371 /* testing pretty printer with all addresses obtained from the plugin */
1376 api->address_pretty_printer (api->cls, "http", cur->addr, cur->addrlen,
1377 GNUNET_NO, TEST_TIMEOUT, &pretty_printer_cb,
1379 addr_str = api->address_to_string (api->cls, cur->addr, cur->addrlen);
1380 suggest_res = api->check_address (api->cls, cur->addr, cur->addrlen);
1382 GNUNET_assert (GNUNET_OK == suggest_res);
1383 GNUNET_assert (NULL != addr_str);
1385 GNUNET_free ((char *) addr_str);
1388 GNUNET_assert (fail_pretty_printer_count > 0);
1389 GNUNET_assert (fail_pretty_printer_count == fail_notify_address_count);
1390 GNUNET_assert (fail_pretty_printer_count == count_str_addr);
1391 fail_pretty_printer = GNUNET_NO;
1392 fail_addr_to_str = GNUNET_NO;
1394 struct IPv4HttpAddress failing_addr;
1396 /* Suggesting addresses with wrong size */
1397 failing_addr.ipv4_addr = htonl (INADDR_LOOPBACK);
1398 failing_addr.u_port = htons (0);
1400 api->check_address (api->cls, &failing_addr,
1401 sizeof (struct IPv6HttpAddress));
1402 GNUNET_assert (GNUNET_SYSERR == suggest_res);
1404 /* Suggesting addresses with wrong address */
1405 failing_addr.ipv4_addr = htonl (0xffc00000);
1406 failing_addr.u_port = htons (12389);
1407 suggest_res = api->check_address (api->cls, &failing_addr, 100);
1408 GNUNET_assert (GNUNET_SYSERR == suggest_res);
1410 /* test sending to client */
1411 multi_handle = curl_multi_init ();
1413 /* Setting up buffers */
1414 buffer_in.size = HTTP_BUFFER_SIZE;
1418 buffer_out.size = HTTP_BUFFER_SIZE;
1422 /* Setting up connection tests */
1424 /* Test: connecting without a peer identification */
1425 test_no_ident.test_executed = GNUNET_NO;
1426 test_no_ident.test_failed = GNUNET_YES;
1428 /* Test: connecting with too short peer identification */
1429 test_too_short_ident.test_executed = GNUNET_NO;
1430 test_too_short_ident.test_failed = GNUNET_YES;
1432 /* Test: connecting with too long peer identification */
1433 test_too_long_ident.test_executed = GNUNET_NO;
1434 test_too_long_ident.test_failed = GNUNET_YES;
1436 /* Test: connecting with valid identification */
1437 test_valid_ident.test_executed = GNUNET_NO;
1438 test_valid_ident.test_failed = GNUNET_YES;
1441 (char *) api->address_to_string (api->cls, addr_head->addr,
1442 addr_head->addrlen);
1444 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("\nPhase 0\n\n"));
1445 run_connection_tests (0, NULL);
1447 /* testing finished */
1454 * The main function for the transport service.
1456 * @param argc number of arguments from the command line
1457 * @param argv command line arguments
1458 * @return 0 ok, 1 on error
1461 main (int argc, char *const *argv)
1464 static struct GNUNET_GETOPT_CommandLineOption options[] = {
1465 GNUNET_GETOPT_OPTION_END
1469 char *const argv_prog[] = {
1470 "test_gnunet_transport_plugin.https",
1472 "test_plugin_transport_data_http.conf",
1481 GNUNET_log_setup ("test_gnunet_transport_plugin.https",
1489 struct GNUNET_CONFIGURATION_Handle *cfg;
1491 cfg = GNUNET_CONFIGURATION_create ();
1493 GNUNET_assert (GNUNET_OK ==
1494 GNUNET_CONFIGURATION_load (cfg,
1495 "test_plugin_transport_data_http.conf"));
1496 if (GNUNET_CONFIGURATION_have_value (cfg, "PATHS", "SERVICEHOME"))
1497 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME",
1499 GNUNET_DISK_directory_remove (servicehome);
1500 GNUNET_CONFIGURATION_destroy (cfg);
1504 GNUNET_PROGRAM_run (5, argv_prog, "test_gnunet_transport_plugin.https",
1505 "testcase", options, &run,
1506 NULL)) ? GNUNET_NO : GNUNET_YES;
1507 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("\ndelete\n\n"));
1508 if (servicehome != NULL)
1510 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("\ndelete\n\n"));
1511 GNUNET_DISK_directory_remove (servicehome);
1512 GNUNET_free (servicehome);
1514 if (GNUNET_OK != ret)
1519 /* end of test_plugin_transport_https.c */