aboutsummaryrefslogtreecommitdiff
path: root/src/gns/test_gns_dht_threepeer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gns/test_gns_dht_threepeer.c')
-rw-r--r--src/gns/test_gns_dht_threepeer.c524
1 files changed, 524 insertions, 0 deletions
diff --git a/src/gns/test_gns_dht_threepeer.c b/src/gns/test_gns_dht_threepeer.c
new file mode 100644
index 0000000..ed9600f
--- /dev/null
+++ b/src/gns/test_gns_dht_threepeer.c
@@ -0,0 +1,524 @@
+/*
+ This file is part of GNUnet.
+ (C) 2009 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file gns/test_gns_dht_threepeer.c
+ * @brief tests dht lookup over 3 peers
+ *
+ * topology:
+ * alice <----> bob <-----> dave
+ *
+ * alice queries for www.buddy.bob.gnunet
+ *
+ */
+#include "platform.h"
+#include "gnunet_disk_lib.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_dht_service.h"
+#include "block_dns.h"
+#include "gnunet_signatures.h"
+#include "gnunet_namestore_service.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_gns_service.h"
+
+/* DEFINES */
+#define VERBOSE GNUNET_YES
+
+/* Timeout for entire testcase */
+#define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 180)
+#define ZONE_PUT_WAIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
+
+/* If number of peers not in config file, use this number */
+#define DEFAULT_NUM_PEERS 2
+
+#define TEST_DOMAIN "www.buddy.bob.gnunet"
+#define TEST_IP "1.1.1.1"
+#define TEST_DAVE_PSEU "hagbard"
+#define TEST_NUM_PEERS 3
+#define TEST_NUM_CON 3
+
+/* Globals */
+
+/**
+ * Directory to store temp data in, defined in config file
+ */
+static char *test_directory;
+
+/**
+ * Variable used to store the number of connections we should wait for.
+ */
+static unsigned int expected_connections;
+
+/**
+ * Variable used to keep track of how many peers aren't yet started.
+ */
+static unsigned long long peers_left;
+
+struct GNUNET_TESTING_Daemon *d1;
+struct GNUNET_TESTING_Daemon *d2;
+struct GNUNET_TESTING_Daemon *d3;
+
+
+/**
+ * Total number of peers to run, set based on config file.
+ */
+static unsigned long long num_peers;
+
+/**
+ * Global used to count how many connections we have currently
+ * been notified about (how many times has topology_callback been called
+ * with success?)
+ */
+static unsigned int total_connections;
+
+/**
+ * Global used to count how many failed connections we have
+ * been notified about (how many times has topology_callback
+ * been called with failure?)
+ */
+static unsigned int failed_connections;
+
+/* Task handle to use to schedule test failure */
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+GNUNET_SCHEDULER_TaskIdentifier bob_task;
+
+/* Global return value (0 for success, anything else for failure) */
+static int ok;
+
+int bob_online, alice_online, dave_online;
+
+const struct GNUNET_CONFIGURATION_Handle *alice_cfg;
+struct GNUNET_CONFIGURATION_Handle *cfg_bob;
+struct GNUNET_CONFIGURATION_Handle *cfg_dave;
+
+struct GNUNET_CRYPTO_ShortHashCode bob_hash;
+struct GNUNET_CRYPTO_ShortHashCode dave_hash;
+struct GNUNET_TESTING_Daemon *alice_daemon;
+struct GNUNET_TESTING_Daemon *bob_daemon;
+struct GNUNET_TESTING_Daemon *dave_daemon;
+
+struct GNUNET_TESTING_PeerGroup *pg;
+struct GNUNET_GNS_Handle *gh;
+
+/**
+ * Function scheduled to be run on the successful completion of this
+ * testcase. Specifically, called when our get request completes.
+ */
+static void
+finish_testing (void *cls, const char *emsg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test finished! (ret=%d)\n", ok);
+}
+
+/**
+ * Continuation for the GNUNET_DHT_get_stop call, so that we don't shut
+ * down the peers without freeing memory associated with GET request.
+ */
+static void
+end_badly_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &finish_testing, NULL);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request. Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failing test with error: `%s'!\n",
+ (char *) cls);
+ die_task = GNUNET_SCHEDULER_add_now (&end_badly_cont, NULL);
+ ok = 1;
+}
+
+
+static void
+on_lookup_result(void *cls, uint32_t rd_count,
+ const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+ int i;
+ char* string_val;
+ const char* typename;
+
+ if (rd_count == 0)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup failed!\n");
+ ok = 2;
+ }
+ else
+ {
+ ok = 1;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
+ for (i=0; i<rd_count; i++)
+ {
+ typename = GNUNET_NAMESTORE_number_to_typename (rd[i].record_type);
+ string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
+ rd[i].data,
+ rd[i].data_size);
+ printf("Got %s record: %s\n", typename, string_val);
+ if (0 == strcmp(string_val, TEST_IP))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "%s correctly resolved to %s!\n", TEST_DOMAIN, string_val);
+ ok = 0;
+ }
+ }
+ }
+ GNUNET_GNS_disconnect(gh);
+ GNUNET_SCHEDULER_cancel(die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &finish_testing, NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down!\n");
+
+}
+
+static void
+commence_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+
+
+ gh = GNUNET_GNS_connect(alice_cfg);
+
+ GNUNET_GNS_lookup(gh, TEST_DOMAIN, GNUNET_GNS_RECORD_TYPE_A,
+ &on_lookup_result, TEST_DOMAIN);
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from lookup");
+}
+
+
+/**
+ * This function is called whenever a connection attempt is finished between two of
+ * the started peers (started with GNUNET_TESTING_daemons_start). The total
+ * number of times this function is called should equal the number returned
+ * from the GNUNET_TESTING_connect_topology call.
+ *
+ * The emsg variable is NULL on success (peers connected), and non-NULL on
+ * failure (peers failed to connect).
+ */
+void
+daemon_connected (void *cls, const struct GNUNET_PeerIdentity *first,
+ const struct GNUNET_PeerIdentity *second, uint32_t distance,
+ const struct GNUNET_CONFIGURATION_Handle *first_cfg,
+ const struct GNUNET_CONFIGURATION_Handle *second_cfg,
+ struct GNUNET_TESTING_Daemon *first_daemon,
+ struct GNUNET_TESTING_Daemon *second_daemon,
+ const char *emsg)
+{
+ if (emsg == NULL)
+ {
+ total_connections++;
+#if VERBOSE
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "connected peer %s to peer %s, distance %u\n",
+ first_daemon->shortname, second_daemon->shortname, distance);
+#endif
+ }
+#if VERBOSE
+ else
+ {
+ failed_connections++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to connect peer %s to peer %s with error :\n%s\n",
+ first_daemon->shortname, second_daemon->shortname, emsg);
+ }
+#endif
+
+ if (total_connections == expected_connections)
+ {
+#if VERBOSE
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Created %d total connections, which is our target number! Starting next phase of testing.\n",
+ total_connections);
+#endif
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task = GNUNET_SCHEDULER_NO_TASK;
+ //die_task =
+ // GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from connect");
+
+ //commence_testing();
+
+ }
+ else if (total_connections + failed_connections == expected_connections)
+ {
+ GNUNET_SCHEDULER_cancel (die_task);
+ die_task =
+ GNUNET_SCHEDULER_add_now (&end_badly,
+ "from topology_callback (too many failed connections)");
+ }
+}
+
+void
+all_connected(void *cls, const char *emsg)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Created all connections! Starting next phase of testing.\n");
+ GNUNET_SCHEDULER_add_delayed (ZONE_PUT_WAIT_TIME, &commence_testing, NULL);
+}
+
+void
+ns_create_cont(void *cls, int32_t s, const char *emsg)
+{
+ GNUNET_NAMESTORE_disconnect((struct GNUNET_NAMESTORE_Handle *)cls, 0);
+}
+
+static void
+daemon_started (void *cls, const struct GNUNET_PeerIdentity *id,
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+ struct GNUNET_NAMESTORE_Handle *ns;
+ char* keyfile;
+ struct GNUNET_CRYPTO_RsaPrivateKey *key;
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
+ struct in_addr *web;
+ struct GNUNET_NAMESTORE_RecordData rd;
+
+ rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY | GNUNET_NAMESTORE_RF_NONE;
+ rd.expiration = GNUNET_TIME_UNIT_FOREVER_ABS;
+
+ if (NULL == dave_daemon)
+ {
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+ dave_daemon = d;
+
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now dave\n");
+ ns = GNUNET_NAMESTORE_connect(cfg);
+
+ GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
+ GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash);
+
+ web = GNUNET_malloc(sizeof(struct in_addr));
+ GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web));
+ rd.data_size = sizeof(struct in_addr);
+ rd.data = web;
+ rd.record_type = GNUNET_GNS_RECORD_TYPE_A;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "www", &rd, NULL, NULL);
+
+ rd.data_size = strlen(TEST_DAVE_PSEU);
+ rd.data = TEST_DAVE_PSEU;
+ rd.record_type = GNUNET_GNS_RECORD_PSEU;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "+", &rd, ns_create_cont, ns);
+
+ GNUNET_CRYPTO_rsa_key_free(key);
+ GNUNET_free(keyfile);
+ GNUNET_free(web);
+
+ return;
+ }
+
+
+ if (NULL == bob_daemon)
+ {
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+ bob_daemon = d;
+
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now bob\n");
+ ns = GNUNET_NAMESTORE_connect(cfg);
+
+ GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
+ GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &dave_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "buddy", &rd, ns_create_cont, ns);
+
+ GNUNET_CRYPTO_rsa_key_free(key);
+ GNUNET_free(keyfile);
+
+ return;
+ }
+
+
+
+ if (NULL == alice_daemon)
+ {
+
+ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
+ "ZONEKEY",
+ &keyfile))
+ {
+ GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
+ ok = -1;
+ return;
+ }
+ alice_daemon = d;
+ alice_cfg = cfg;
+
+ key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is now alice\n");
+ ns = GNUNET_NAMESTORE_connect(cfg);
+
+ rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
+ rd.data = &bob_hash;
+ rd.record_type = GNUNET_GNS_RECORD_PKEY;
+
+ GNUNET_NAMESTORE_record_create (ns, key, "bob", &rd, ns_create_cont, ns);
+
+ GNUNET_CRYPTO_rsa_key_free(key);
+ GNUNET_free(keyfile);
+
+ GNUNET_TESTING_connect_topology (pg, GNUNET_TESTING_TOPOLOGY_CLIQUE,
+ GNUNET_TESTING_TOPOLOGY_OPTION_ALL,
+ 0,
+ TIMEOUT,
+ 3,
+ &all_connected, NULL);
+ return;
+
+ }
+
+
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "This is a random guy\n");
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+
+ /* Get path from configuration file */
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+ &test_directory))
+ {
+ ok = 404;
+ return;
+ }
+
+ GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "starting\n");
+
+ /* Get number of peers to start from configuration (should be two) */
+ if (GNUNET_SYSERR ==
+ GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
+ &num_peers))
+ num_peers = DEFAULT_NUM_PEERS;
+
+ /* Set peers_left so we know when all peers started */
+ peers_left = num_peers;
+
+ bob_daemon = NULL;
+ dave_daemon = NULL;
+ alice_daemon = NULL;
+
+ pg = GNUNET_TESTING_daemons_start (cfg, TEST_NUM_PEERS, TEST_NUM_CON,
+ TEST_NUM_CON, TIMEOUT, NULL, NULL, &daemon_started, NULL,
+ &daemon_connected, NULL, NULL);
+
+ /* Set up a task to end testing if peer start fails */
+ die_task =
+ GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+ "didn't start all daemons in reasonable amount of time!!!");
+
+ alice_online = 0;
+ bob_online = 0;
+ dave_online = 0;
+ expected_connections = 2;
+
+ /* Start alice */
+ //d1 = GNUNET_TESTING_daemon_start(cfg_alice, TIMEOUT, GNUNET_NO, NULL, NULL, 0,
+ // NULL, NULL, NULL, &alice_started, NULL);
+
+
+
+
+}
+
+static int
+check ()
+{
+ int ret;
+
+ /* Arguments for GNUNET_PROGRAM_run */
+ char *const argv[] = { "test-gns-twopeer", /* Name to give running binary */
+ "-c",
+ "test_gns_dht_default.conf", /* Config file to use */
+#if VERBOSE
+ "-L", "DEBUG",
+#endif
+ NULL
+ };
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ /* Run the run function as a new program */
+ ret =
+ GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+ "test-gns-threepeer", "nohelp", options, &run,
+ &ok);
+ if (ret != GNUNET_OK)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "`test-gns-threepeer': Failed with error code %d\n", ret);
+ }
+ return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int ret;
+
+ GNUNET_log_setup ("test-gns-threepeer",
+#if VERBOSE
+ "DEBUG",
+#else
+ "WARNING",
+#endif
+ NULL);
+ ret = check ();
+ /**
+ * Need to remove base directory, subdirectories taken care
+ * of by the testing framework.
+ */
+ return ret;
+}
+
+/* end of test_gns_threepeer.c */