From 563b71afee70ac213a8bb28ce0697fcbae06aac3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 5 Sep 2011 21:18:45 +0000 Subject: fixing API and clean up issues in testing --- contrib/defaults.conf | 1 + src/dht/gnunet-dht-driver.c | 168 +++++----------- src/fs/fs_test_lib.c | 32 ++- src/fs/fs_test_lib.h | 14 +- src/fs/test_fs_test_lib.c | 12 +- src/fs/test_gnunet_service_fs_migration.c | 14 +- src/fs/test_gnunet_service_fs_p2p.c | 12 +- src/include/gnunet_testing_lib.h | 26 ++- src/nse/gnunet-nse-profiler.c | 2 +- src/testing/test_testing_connect.c | 7 +- src/testing/test_testing_reconnect.c | 9 +- src/testing/testing.c | 311 ++++++++--------------------- src/testing/testing_group.c | 84 +++++--- src/topology/test_gnunet_daemon_topology.c | 33 ++- 14 files changed, 321 insertions(+), 404 deletions(-) diff --git a/contrib/defaults.conf b/contrib/defaults.conf index b54af434f..bb4193433 100644 --- a/contrib/defaults.conf +++ b/contrib/defaults.conf @@ -217,6 +217,7 @@ HOSTNAME = localhost HOME = $SERVICEHOME CONFIG = $DEFAULTCONFIG BINARY = gnunet-service-transport +#PREFIX = valgrind NEIGHBOUR_LIMIT = 50 ACCEPT_FROM = 127.0.0.1; ACCEPT_FROM6 = ::1; diff --git a/src/dht/gnunet-dht-driver.c b/src/dht/gnunet-dht-driver.c index 4f411f4a9..a7641098e 100644 --- a/src/dht/gnunet-dht-driver.c +++ b/src/dht/gnunet-dht-driver.c @@ -36,9 +36,6 @@ #include "dht.h" #include "gauger.h" -/* Specific DEBUG hack, do not use normally (may leak memory, segfault, or eat children.) */ -#define ONLY_TESTING GNUNET_NO - /* DEFINES */ #define VERBOSE GNUNET_NO @@ -331,6 +328,11 @@ struct FindPeerContext */ struct GNUNET_CONTAINER_MultiHashMap *peer_hash; + /** + * Handle to an active attempt to connect this peer. + */ + struct GNUNET_TESTING_ConnectContext *cc; + /** * Min heap which orders values in the peer_hash for * easy lookup. @@ -446,21 +448,6 @@ static unsigned int do_find_peer; */ static unsigned int insert_gauger_data; -#if ONLY_TESTING -/** - * Are we currently trying to connect two peers repeatedly? - */ -static unsigned int repeat_connect_mode; - -/** - * Task for repeating connects. - */ -GNUNET_SCHEDULER_TaskIdentifier repeat_connect_task; - -struct GNUNET_TESTING_Daemon *repeat_connect_peer1; -struct GNUNET_TESTING_Daemon *repeat_connect_peer2; -#endif - /** * Boolean value, should replication be done by the dht * service (GNUNET_YES) or by the driver (GNUNET_NO) @@ -724,6 +711,7 @@ static unsigned long long cumulative_successful_gets; */ static unsigned long long gets_failed; +#ifndef HAVE_MALICIOUS /** * How many malicious control messages do * we currently have in flight? @@ -734,6 +722,7 @@ static unsigned long long outstanding_malicious; * How many set malicious peers are done? */ static unsigned int malicious_completed; +#endif /** * For gauger logging, what specific identifier (svn revision) @@ -1417,6 +1406,30 @@ add_new_connection (struct FindPeerContext *find_peer_context, } } +static void +did_connect (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) +{ + struct FindPeerContext *find_peer_context = cls; + + find_peer_context->cc = NULL; +} + /** * Iterate over min heap of connections per peer. For any * peer that has 0 connections, attempt to connect them to @@ -1444,7 +1457,7 @@ iterate_min_heap_peers (void *cls, struct GNUNET_CONTAINER_HeapNode *node, d1 = GNUNET_TESTING_daemon_get_by_id (pg, &peer_count->peer_id); GNUNET_assert (d1 != NULL); d2 = d1; - while ((d2 == d1) || (GNUNET_YES != GNUNET_TESTING_daemon_running (d2))) + while ((d2 == d1) || (GNUNET_YES != GNUNET_TESTING_test_daemon_running (d2))) { d2 = GNUNET_TESTING_daemon_get (pg, GNUNET_CRYPTO_random_u32 @@ -1464,14 +1477,17 @@ iterate_min_heap_peers (void *cls, struct GNUNET_CONTAINER_HeapNode *node, { timeout = GNUNET_TIME_absolute_get_remaining (find_peer_context->endtime); } - GNUNET_TESTING_daemons_connect (d1, d2, timeout, DEFAULT_RECONNECT_ATTEMPTS, - GNUNET_YES, NULL, NULL); + if (NULL != find_peer_context->cc) + GNUNET_TESTING_daemons_connect_cancel (find_peer_context->cc); + find_peer_context->cc = GNUNET_TESTING_daemons_connect (d1, d2, timeout, DEFAULT_RECONNECT_ATTEMPTS, + GNUNET_YES, + &did_connect, + find_peer_context); } if (GNUNET_TIME_absolute_get_remaining (find_peer_context->endtime).rel_value > 0) return GNUNET_YES; - else - return GNUNET_NO; + return GNUNET_NO; } /** @@ -1585,6 +1601,8 @@ count_peers_churn_cb (void *cls, const struct GNUNET_PeerIdentity *first, find_peer_context); GNUNET_CONTAINER_multihashmap_destroy (find_peer_context->peer_hash); GNUNET_CONTAINER_heap_destroy (find_peer_context->peer_min_heap); + if (NULL != find_peer_context->cc) + GNUNET_TESTING_daemons_connect_cancel (find_peer_context->cc); GNUNET_free (find_peer_context); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Churn round %u of %llu finished, scheduling next GET round.\n", @@ -1756,7 +1774,7 @@ churn_complete (void *cls, const char *emsg) for (i = 0; i < num_peers; i++) { temp_daemon = GNUNET_TESTING_daemon_get (pg, i); - if (GNUNET_YES == GNUNET_TESTING_daemon_running (temp_daemon)) + if (GNUNET_YES == GNUNET_TESTING_test_daemon_running (temp_daemon)) { peer_count = GNUNET_malloc (sizeof (struct PeerCount)); memcpy (&peer_count->peer_id, &temp_daemon->id, @@ -2102,7 +2120,7 @@ do_get (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /* Set this here in case we are re-running gets */ test_get->succeeded = GNUNET_NO; - if (GNUNET_YES != GNUNET_TESTING_daemon_running (test_get->daemon)) /* If the peer has been churned off, don't try issuing request from it! */ + if (GNUNET_YES != GNUNET_TESTING_test_daemon_running (test_get->daemon)) /* If the peer has been churned off, don't try issuing request from it! */ { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer we should issue get request from is down, skipping.\n"); @@ -2219,7 +2237,7 @@ do_put (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (test_put == NULL) return; /* End of list */ - if (GNUNET_YES != GNUNET_TESTING_daemon_running (test_put->daemon)) /* If the peer has been churned off, don't try issuing request from it! */ + if (GNUNET_YES != GNUNET_TESTING_test_daemon_running (test_put->daemon)) /* If the peer has been churned off, don't try issuing request from it! */ { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer we should issue put request at is down, skipping.\n"); @@ -2338,6 +2356,8 @@ count_peers_cb (void *cls, const struct GNUNET_PeerIdentity *first, find_peer_context); GNUNET_CONTAINER_multihashmap_destroy (find_peer_context->peer_hash); GNUNET_CONTAINER_heap_destroy (find_peer_context->peer_min_heap); + if (NULL != find_peer_context->cc) + GNUNET_TESTING_daemons_connect_cancel (find_peer_context->cc); GNUNET_free (find_peer_context); fprintf (stderr, "Not sending any more find peer requests.\n"); @@ -2663,6 +2683,7 @@ continue_puts_and_gets (void *cls, } } +#if HAVE_MALICIOUS /** * Task to release DHT handles */ @@ -2686,7 +2707,6 @@ malicious_disconnect_task (void *cls, } } -#if HAVE_MALICIOUS /** * Task to release DHT handles */ @@ -2784,7 +2804,7 @@ choose_next_malicious (struct GNUNET_TESTING_PeerGroup *pg, temp_daemon = GNUNET_TESTING_daemon_get (pg, i); hash_from_uid (i, &uid_hash); /* Check if this peer matches the bloomfilter */ - if ((GNUNET_NO == GNUNET_TESTING_daemon_running (temp_daemon)) || + if ((GNUNET_NO == GNUNET_TESTING_test_daemon_running (temp_daemon)) || (GNUNET_YES == GNUNET_CONTAINER_bloomfilter_test (bloom, &uid_hash))) continue; @@ -2877,43 +2897,6 @@ setup_malicious_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } #endif -#if ONLY_TESTING -/* Forward declaration */ -static void -topology_callback (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); - -/** - * Retry connecting two specific peers until they connect, - * at a specific interval. These two peers previously failed - * to connect, and we hope they continue to so that we can - * debug the reason they are having issues. - */ -static void -repeat_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Repeating connect attempt between %s and %s.\n", - repeat_connect_peer1->shortname, repeat_connect_peer2->shortname); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peer 1 configuration `%s'\n", - repeat_connect_peer1->cfgfile); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peer 2 configuration `%s'\n", - repeat_connect_peer2->cfgfile); - - repeat_connect_task = GNUNET_SCHEDULER_NO_TASK; - GNUNET_TESTING_daemons_connect (repeat_connect_peer1, repeat_connect_peer2, - GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 60), 2, - &topology_callback, NULL); -} -#endif - /** * This function is called whenever a connection attempt is finished between two of * the started peers (started with GNUNET_TESTING_daemons_start). The total @@ -2945,36 +2928,6 @@ topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, char *temp_conn_failed_string; char *revision_str; -#if ONLY_TESTING - if (repeat_connect_mode == GNUNET_YES) - { - if ((first_daemon == repeat_connect_peer1) && - (second_daemon == repeat_connect_peer2)) - { - if (emsg != NULL) /* Peers failed to connect again! */ - { - GNUNET_assert (repeat_connect_task == GNUNET_SCHEDULER_NO_TASK); - repeat_connect_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 60), - &repeat_connect, NULL); - return; - } - else /* Repeat peers actually connected! */ - { - if (repeat_connect_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (repeat_connect_task); - repeat_connect_peer1 = NULL; - repeat_connect_peer2 = NULL; - repeat_connect_mode = GNUNET_NO; - GNUNET_TESTING_resume_connections (pg); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Resuming normal connection mode, debug connection was successful!\n"); - } - } - } -#endif - if (GNUNET_TIME_absolute_get_difference (connect_last_time, GNUNET_TIME_absolute_get ()).rel_value > @@ -3013,26 +2966,6 @@ topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "have %llu total_connections, %llu failed\n", total_connections, failed_connections); -#if ONLY_TESTING - /* These conditions likely mean we've entered the death spiral of doom */ - if ((total_connections > 20000) && (conns_per_sec_recent < 5.0) && - (conns_per_sec_total > 10.0) && (emsg != NULL) && - (repeat_connect_mode == GNUNET_NO)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Entering repeat connection attempt mode!\n"); - repeat_connect_peer1 = first_daemon; - repeat_connect_peer2 = second_daemon; - repeat_connect_mode = GNUNET_YES; - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Stopping NEW connections from being scheduled!\n"); - GNUNET_TESTING_stop_connections (pg); - repeat_connect_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 60), - &repeat_connect, NULL); - } -#endif } if (emsg == NULL) @@ -3058,11 +2991,6 @@ topology_callback (void *cls, const struct GNUNET_PeerIdentity *first, #endif } -#if ONLY_TESTING - if ((repeat_connect_mode == GNUNET_YES)) - return; -#endif - GNUNET_assert (peer_connect_meter != NULL); if (GNUNET_YES == update_meter (peer_connect_meter)) { diff --git a/src/fs/fs_test_lib.c b/src/fs/fs_test_lib.c index 17291d1bd..40a9f6276 100644 --- a/src/fs/fs_test_lib.c +++ b/src/fs/fs_test_lib.c @@ -379,10 +379,11 @@ GNUNET_FS_TEST_daemons_start (const char *template_cfg_file, } -struct ConnectContext +struct GNUNET_FS_TEST_ConnectContext { GNUNET_SCHEDULER_Task cont; void *cont_cls; + struct GNUNET_TESTING_ConnectContext *cc; }; @@ -409,8 +410,9 @@ notify_connection (void *cls, const struct GNUNET_PeerIdentity *first, struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) { - struct ConnectContext *cc = cls; + struct GNUNET_FS_TEST_ConnectContext *cc = cls; + cc->cc = NULL; if (emsg != NULL) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to connect peers: %s\n", emsg); @@ -432,20 +434,34 @@ notify_connection (void *cls, const struct GNUNET_PeerIdentity *first, * @param cont function to call when done * @param cont_cls closure for cont */ -void +struct GNUNET_FS_TEST_ConnectContext * GNUNET_FS_TEST_daemons_connect (struct GNUNET_FS_TestDaemon *daemon1, struct GNUNET_FS_TestDaemon *daemon2, struct GNUNET_TIME_Relative timeout, GNUNET_SCHEDULER_Task cont, void *cont_cls) { - struct ConnectContext *ncc; + struct GNUNET_FS_TEST_ConnectContext *ncc; - ncc = GNUNET_malloc (sizeof (struct ConnectContext)); + ncc = GNUNET_malloc (sizeof (struct GNUNET_FS_TEST_ConnectContext)); ncc->cont = cont; ncc->cont_cls = cont_cls; - GNUNET_TESTING_daemons_connect (daemon1->daemon, daemon2->daemon, timeout, - CONNECT_ATTEMPTS, GNUNET_YES, - ¬ify_connection, ncc); + ncc->cc = GNUNET_TESTING_daemons_connect (daemon1->daemon, daemon2->daemon, timeout, + CONNECT_ATTEMPTS, GNUNET_YES, + ¬ify_connection, ncc); + return ncc; +} + + +/** + * Cancel connect operation. + * + * @param cc operation to cancel + */ +void +GNUNET_FS_TEST_daemons_connect_cancel (struct GNUNET_FS_TEST_ConnectContext *cc) +{ + GNUNET_TESTING_daemons_connect_cancel (cc->cc); + GNUNET_free (cc); } diff --git a/src/fs/fs_test_lib.h b/src/fs/fs_test_lib.h index ad1d96bf0..204d5b2ab 100644 --- a/src/fs/fs_test_lib.h +++ b/src/fs/fs_test_lib.h @@ -61,6 +61,9 @@ GNUNET_FS_TEST_daemons_start (const char *template_cfg_file, GNUNET_SCHEDULER_Task cont, void *cont_cls); +struct GNUNET_FS_TEST_ConnectContext; + + /** * Connect two daemons for testing. * @@ -71,13 +74,22 @@ GNUNET_FS_TEST_daemons_start (const char *template_cfg_file, * @param cont function to call when done * @param cont_cls closure for cont */ -void +struct GNUNET_FS_TEST_ConnectContext * GNUNET_FS_TEST_daemons_connect (struct GNUNET_FS_TestDaemon *daemon1, struct GNUNET_FS_TestDaemon *daemon2, struct GNUNET_TIME_Relative timeout, GNUNET_SCHEDULER_Task cont, void *cont_cls); +/** + * Cancel connect operation. + * + * @param cc operation to cancel + */ +void +GNUNET_FS_TEST_daemons_connect_cancel (struct GNUNET_FS_TEST_ConnectContext *cc); + + /** * Obtain peer group used for testing. * diff --git a/src/fs/test_fs_test_lib.c b/src/fs/test_fs_test_lib.c index 458d4606b..1f2119259 100644 --- a/src/fs/test_fs_test_lib.c +++ b/src/fs/test_fs_test_lib.c @@ -44,11 +44,18 @@ static struct GNUNET_FS_TestDaemon *daemons[NUM_DAEMONS]; +static struct GNUNET_FS_TEST_ConnectContext *cc; + static int ret; static void do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + if (NULL != cc) + { + GNUNET_FS_TEST_daemons_connect_cancel (cc); + cc = NULL; + } if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { GNUNET_break (0); @@ -83,6 +90,7 @@ do_download (void *cls, const struct GNUNET_FS_Uri *uri) static void do_publish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + cc = NULL; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { GNUNET_break (0); @@ -109,8 +117,8 @@ do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemons started, will now try to connect them\n"); - GNUNET_FS_TEST_daemons_connect (daemons[0], daemons[1], TIMEOUT, &do_publish, - NULL); + cc = GNUNET_FS_TEST_daemons_connect (daemons[0], daemons[1], TIMEOUT, &do_publish, + NULL); } diff --git a/src/fs/test_gnunet_service_fs_migration.c b/src/fs/test_gnunet_service_fs_migration.c index a5570e1d4..bbf2534d2 100644 --- a/src/fs/test_gnunet_service_fs_migration.c +++ b/src/fs/test_gnunet_service_fs_migration.c @@ -52,12 +52,19 @@ static int ok; static struct GNUNET_TIME_Absolute start_time; +static struct GNUNET_FS_TEST_ConnectContext *cc; + static void do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Relative del; char *fancy; - + + if (NULL != cc) + { + GNUNET_FS_TEST_daemons_connect_cancel (cc); + cc = NULL; + } GNUNET_FS_TEST_daemons_stop (2, daemons); if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { @@ -138,6 +145,7 @@ do_wait (void *cls, const struct GNUNET_FS_Uri *uri) static void do_publish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + cc = NULL; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { GNUNET_FS_TEST_daemons_stop (2, daemons); @@ -165,8 +173,8 @@ do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemons started, will now try to connect them\n"); - GNUNET_FS_TEST_daemons_connect (daemons[0], daemons[1], TIMEOUT, &do_publish, - NULL); + cc = GNUNET_FS_TEST_daemons_connect (daemons[0], daemons[1], TIMEOUT, &do_publish, + NULL); } diff --git a/src/fs/test_gnunet_service_fs_p2p.c b/src/fs/test_gnunet_service_fs_p2p.c index aece0e80a..26372cfa8 100644 --- a/src/fs/test_gnunet_service_fs_p2p.c +++ b/src/fs/test_gnunet_service_fs_p2p.c @@ -48,12 +48,19 @@ static int ok; static struct GNUNET_TIME_Absolute start_time; +static struct GNUNET_FS_TEST_ConnectContext *cc; + static void do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_TIME_Relative del; char *fancy; + if (NULL != cc) + { + GNUNET_FS_TEST_daemons_connect_cancel (cc); + cc = NULL; + } GNUNET_FS_TEST_daemons_stop (NUM_DAEMONS, daemons); if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { @@ -99,6 +106,7 @@ do_download (void *cls, const struct GNUNET_FS_Uri *uri) static void do_publish (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + cc = NULL; if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)) { GNUNET_FS_TEST_daemons_stop (NUM_DAEMONS, daemons); @@ -120,8 +128,8 @@ do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemons started, will now try to connect them\n"); - GNUNET_FS_TEST_daemons_connect (daemons[0], daemons[1], TIMEOUT, &do_publish, - NULL); + cc = GNUNET_FS_TEST_daemons_connect (daemons[0], daemons[1], TIMEOUT, &do_publish, + NULL); } diff --git a/src/include/gnunet_testing_lib.h b/src/include/gnunet_testing_lib.h index 945a3900b..39bc9d161 100644 --- a/src/include/gnunet_testing_lib.h +++ b/src/include/gnunet_testing_lib.h @@ -432,6 +432,7 @@ typedef void (*GNUNET_TESTING_NotifyConnection) (void *cls, second_daemon, const char *emsg); + /** * Prototype of a callback function indicating that two peers * are currently connected. @@ -497,12 +498,11 @@ GNUNET_TESTING_daemon_continue_startup (struct GNUNET_TESTING_Daemon *daemon); * Check whether the given daemon is running. * * @param daemon the daemon to check - * * @return GNUNET_YES if the daemon is up, GNUNET_NO if the * daemon is down, GNUNET_SYSERR on error. */ int -GNUNET_TESTING_daemon_running (struct GNUNET_TESTING_Daemon *daemon); +GNUNET_TESTING_test_daemon_running (struct GNUNET_TESTING_Daemon *daemon); /** @@ -545,7 +545,7 @@ GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon, */ void GNUNET_TESTING_daemon_start_service (struct GNUNET_TESTING_Daemon *d, - char *service, + const char *service, struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_NotifyDaemonRunning cb, void *cb_cls); @@ -643,7 +643,7 @@ GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, */ void GNUNET_TESTING_daemon_stop_service (struct GNUNET_TESTING_Daemon *d, - char *service, + const char *service, struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_NotifyCompletion cb, void *cb_cls); @@ -715,7 +715,16 @@ GNUNET_TESTING_daemons_continue_startup (struct GNUNET_TESTING_PeerGroup *pg); /** - * Establish a connection between two GNUnet daemons. + * Handle for an active request to connect two peers. + */ +struct GNUNET_TESTING_ConnectContext; + + +/** + * Establish a connection between two GNUnet daemons. The daemons + * must both be running and not be stopped until either the + * 'cb' callback is called OR the connection request has been + * explicitly cancelled. * * @param d1 handle for the first daemon * @param d2 handle for the second daemon @@ -727,8 +736,9 @@ GNUNET_TESTING_daemons_continue_startup (struct GNUNET_TESTING_PeerGroup *pg); * the HELLO has already been exchanged * @param cb function to call at the end * @param cb_cls closure for cb + * @return handle to cancel the request, NULL on error */ -void /* struct GNUNET_TESTING_ConnectContext * */ +struct GNUNET_TESTING_ConnectContext * GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, struct GNUNET_TESTING_Daemon *d2, struct GNUNET_TIME_Relative timeout, @@ -738,7 +748,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, void *cb_cls); -#if 0 + /** * Cancel an attempt to connect two daemons. * @@ -747,7 +757,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, void GNUNET_TESTING_daemons_connect_cancel (struct GNUNET_TESTING_ConnectContext *cc); -#endif + /** diff --git a/src/nse/gnunet-nse-profiler.c b/src/nse/gnunet-nse-profiler.c index 0df6ddf7d..9342480c2 100644 --- a/src/nse/gnunet-nse-profiler.c +++ b/src/nse/gnunet-nse-profiler.c @@ -251,7 +251,7 @@ connect_nse_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) current_peer = GNUNET_malloc (sizeof (struct NSEPeer)); current_peer->daemon = GNUNET_TESTING_daemon_get (pg, i); if (GNUNET_YES == - GNUNET_TESTING_daemon_running (GNUNET_TESTING_daemon_get (pg, i))) + GNUNET_TESTING_test_daemon_running (GNUNET_TESTING_daemon_get (pg, i))) { current_peer->nse_handle = GNUNET_NSE_connect (current_peer->daemon->cfg, &handle_estimate, diff --git a/src/testing/test_testing_connect.c b/src/testing/test_testing_connect.c index 4fe3a1dd6..fd14f76be 100644 --- a/src/testing/test_testing_connect.c +++ b/src/testing/test_testing_connect.c @@ -43,6 +43,8 @@ static struct GNUNET_CONFIGURATION_Handle *c1; static struct GNUNET_CONFIGURATION_Handle *c2; +static struct GNUNET_TESTING_ConnectContext *cc; + static void end2_cb (void *cls, const char *emsg) { @@ -99,6 +101,7 @@ my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first, struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) { + cc = NULL; GNUNET_SCHEDULER_add_now (&finish_testing, NULL); } @@ -113,8 +116,8 @@ my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", GNUNET_i2s (id)); #endif - GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, GNUNET_YES, - &my_connect_complete, NULL); + cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, GNUNET_YES, + &my_connect_complete, NULL); } diff --git a/src/testing/test_testing_reconnect.c b/src/testing/test_testing_reconnect.c index 69b871303..36675012f 100644 --- a/src/testing/test_testing_reconnect.c +++ b/src/testing/test_testing_reconnect.c @@ -43,6 +43,8 @@ static struct GNUNET_CONFIGURATION_Handle *c1; static struct GNUNET_CONFIGURATION_Handle *c2; +static struct GNUNET_TESTING_ConnectContext *cc; + /** * How many start-connect-stop iterations should we do? */ @@ -55,7 +57,7 @@ static int phase; * stopping them again. */ static void -run_phase (); +run_phase (void); static void end2_cb (void *cls, const char *emsg) @@ -123,6 +125,7 @@ my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first, struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg) { + cc = NULL; #if VERBOSE fprintf (stderr, "Peer %s ", GNUNET_i2s (first)); fprintf (stderr, "connected to %s\n", GNUNET_i2s (second)); @@ -143,8 +146,8 @@ my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n", GNUNET_i2s (id)); #endif - GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, GNUNET_YES, - &my_connect_complete, NULL); + cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS, GNUNET_YES, + &my_connect_complete, NULL); } diff --git a/src/testing/testing.c b/src/testing/testing.c index ecd6140a6..78ed39e4a 100644 --- a/src/testing/testing.c +++ b/src/testing/testing.c @@ -41,8 +41,6 @@ #define DEBUG_TESTING_RECONNECT GNUNET_NO -#define WAIT_FOR_HELLO GNUNET_NO - /** * Hack to deal with initial HELLO's being often devoid of addresses. * This hack causes 'process_hello' to ignore HELLOs without addresses. @@ -90,10 +88,6 @@ process_hello (void *cls, const struct GNUNET_MessageHeader *message) { struct GNUNET_TESTING_Daemon *daemon = cls; int msize; - -#if WAIT_FOR_HELLO - GNUNET_TESTING_NotifyDaemonRunning cb; -#endif #if EMPTY_HACK int empty; @@ -109,14 +103,8 @@ process_hello (void *cls, const struct GNUNET_MessageHeader *message) return; } #endif - if (daemon == NULL) - return; - GNUNET_assert (daemon->phase == SP_GET_HELLO || daemon->phase == SP_START_DONE); -#if WAIT_FOR_HELLO - cb = daemon->cb; -#endif daemon->cb = NULL; if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */ GNUNET_SCHEDULER_cancel (daemon->task); @@ -157,105 +145,11 @@ process_hello (void *cls, const struct GNUNET_MessageHeader *message) daemon->th = NULL; } daemon->phase = SP_START_DONE; - -#if WAIT_FOR_HELLO - if (NULL != cb) /* FIXME: what happens when this callback calls GNUNET_TESTING_daemon_stop? */ - cb (daemon->cb_cls, &daemon->id, daemon->cfg, daemon, NULL); -#endif } static void start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); -#if WAIT_FOR_HELLO -/** - * Function called after GNUNET_CORE_connect has succeeded - * (or failed for good). Note that the private key of the - * peer is intentionally not exposed here; if you need it, - * your process should try to read the private key file - * directly (which should work if you are authorized...). - * - * @param cls closure - * @param server handle to the server, NULL if we failed - * @param my_identity ID of this peer, NULL if we failed - * @param publicKey public key of this peer, NULL if we failed - */ -static void -testing_init (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *my_identity, - const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey) -{ - struct GNUNET_TESTING_Daemon *d = cls; - - GNUNET_assert (d->phase == SP_START_CORE); - d->phase = SP_GET_HELLO; - - if (server == NULL) - { - d->server = NULL; - if (GNUNET_YES == d->dead) - GNUNET_TESTING_daemon_stop (d, - GNUNET_TIME_absolute_get_remaining - (d->max_timeout), d->dead_cb, d->dead_cb_cls, - GNUNET_YES, GNUNET_NO); - else if (NULL != d->cb) - d->cb (d->cb_cls, NULL, d->cfg, d, - _("Failed to connect to core service\n")); - return; - } -#if DEBUG_TESTING - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully started peer `%4s'.\n", - GNUNET_i2s (my_identity)); -#endif - d->id = *my_identity; /* FIXME: shouldn't we already have this from reading the hostkey file? */ - if (d->shortname == NULL) - d->shortname = strdup (GNUNET_i2s (my_identity)); - d->server = server; - d->running = GNUNET_YES; - - if (GNUNET_NO == d->running) - { -#if DEBUG_TESTING - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Peer is dead (d->running == GNUNET_NO)\n"); -#endif - return; - } -#if DEBUG_TESTING - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Successfully started peer `%4s', connecting to transport service.\n", - GNUNET_i2s (my_identity)); -#endif - - d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL); - if (d->th == NULL) - { - if (GNUNET_YES == d->dead) - GNUNET_TESTING_daemon_stop (d, - GNUNET_TIME_absolute_get_remaining - (d->max_timeout), d->dead_cb, d->dead_cb_cls, - GNUNET_YES, GNUNET_NO); - else if (NULL != d->cb) - d->cb (d->cb_cls, &d->id, d->cfg, d, - _("Failed to connect to transport service!\n")); - return; - } -#if DEBUG_TESTING - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected to transport service `%s', getting HELLO\n", - GNUNET_i2s (my_identity)); -#endif - - d->ghh = GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d); - /* wait some more */ - if (d->task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (d->task); - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d); -} -#endif - -#if !WAIT_FOR_HELLO /** * Notify of a peer being up and running. Scheduled as a task * so that variables which may need to be set are set before @@ -275,7 +169,7 @@ notify_daemon_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (NULL != cb) cb (d->cb_cls, &d->id, d->cfg, d, NULL); } -#endif + /** * Finite-state machine for starting GNUnet. @@ -664,29 +558,6 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (d->server != NULL) GNUNET_CORE_disconnect (d->server); -#if WAIT_FOR_HELLO - if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) - { - cb = d->cb; - d->cb = NULL; - if (NULL != cb) - cb (d->cb_cls, NULL, d->cfg, d, - _("Unable to connect to CORE service for peer!\n")); - GNUNET_CONFIGURATION_destroy (d->cfg); - GNUNET_free (d->cfgfile); - GNUNET_free_non_null (d->hostname); - GNUNET_free_non_null (d->username); - GNUNET_free (d); - return; - } - d->server = - GNUNET_CORE_connect (d->cfg, 1, d, &testing_init, NULL, NULL, NULL, - NULL, GNUNET_NO, NULL, GNUNET_NO, no_handlers); - d->task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_CONSTANTS_SERVICE_RETRY, 2), - &start_fsm, d); -#else d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL); if (d->th == NULL) { @@ -707,6 +578,7 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) #endif d->ghh = GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d); + /* FIXME: store task ID somewhere! */ GNUNET_SCHEDULER_add_now (¬ify_daemon_started, d); /*cb = d->cb; * d->cb = NULL; @@ -714,7 +586,6 @@ start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * cb (d->cb_cls, &d->id, d->cfg, d, NULL); */ d->running = GNUNET_YES; d->phase = SP_GET_HELLO; -#endif break; case SP_GET_HELLO: if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0) @@ -985,7 +856,7 @@ GNUNET_TESTING_daemon_continue_startup (struct GNUNET_TESTING_Daemon *daemon) * daemon is down, GNUNET_SYSERR on error. */ int -GNUNET_TESTING_daemon_running (struct GNUNET_TESTING_Daemon *daemon) +GNUNET_TESTING_test_daemon_running (struct GNUNET_TESTING_Daemon *daemon) { if (daemon == NULL) return GNUNET_SYSERR; @@ -1098,7 +969,7 @@ GNUNET_TESTING_daemon_start_stopped_service (struct GNUNET_TESTING_Daemon *d, */ void GNUNET_TESTING_daemon_start_service (struct GNUNET_TESTING_Daemon *d, - char *service, + const char *service, struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_NotifyDaemonRunning cb, void *cb_cls) @@ -1202,7 +1073,7 @@ GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon, daemon->cb_cls = cb_cls; daemon->phase = SP_TOPOLOGY_SETUP; daemon->max_timeout = GNUNET_TIME_relative_to_absolute (timeout); - + /* FIXME: why add_continuation? */ GNUNET_SCHEDULER_add_continuation (&start_fsm, daemon, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } @@ -1429,6 +1300,7 @@ GNUNET_TESTING_daemon_start (const struct GNUNET_CONFIGURATION_Handle *cfg, "No need to copy configuration file since we are running locally.\n"); #endif ret->phase = SP_COPIED; + /* FIXME: why add_cont? */ GNUNET_SCHEDULER_add_continuation (&start_fsm, ret, GNUNET_SCHEDULER_REASON_PREREQ_DONE); } @@ -1551,7 +1423,7 @@ GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d, */ void GNUNET_TESTING_daemon_stop_service (struct GNUNET_TESTING_Daemon *d, - char *service, + const char *service, struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_NotifyCompletion cb, void *cb_cls) @@ -1852,7 +1724,7 @@ GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d, * Data kept for each pair of peers that we try * to connect. */ -struct ConnectContext +struct GNUNET_TESTING_ConnectContext { /** * Testing handle to the first daemon. @@ -1949,13 +1821,13 @@ reattempt_daemons_connect (void *cls, * Notify callback about success or failure of the attempt * to connect the two peers * - * @param cls our "struct ConnectContext" (freed) + * @param cls our "struct GNUNET_TESTING_ConnectContext" (freed) * @param tc reason tells us if we succeeded or failed */ static void notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ConnectContext *ctx = cls; + struct GNUNET_TESTING_ConnectContext *ctx = cls; ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK; if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK) @@ -1977,11 +1849,6 @@ notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) ctx->d1th = NULL; if (ctx->d1core != NULL) GNUNET_CORE_disconnect (ctx->d1core); -#if CONNECT_CORE2 - if (ctx->d2core != NULL) - GNUNET_CORE_disconnect (ctx->d2core); - ctx->d2core = NULL; -#endif ctx->d1core = NULL; GNUNET_free (ctx); return; @@ -2005,14 +1872,7 @@ notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) else if (ctx->connect_attempts > 0) { ctx->d1core_ready = GNUNET_NO; -#if CONNECT_CORE2 - if (ctx->d2core != NULL) - { - GNUNET_CORE_disconnect (ctx->d2core); - ctx->d2core = NULL; - } -#endif - GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx); + ctx->timeout_task = GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx); return; } else @@ -2023,7 +1883,6 @@ notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) ctx->d2->cfg, ctx->d1, ctx->d2, _("Peers failed to connect")); } } - GNUNET_free (ctx); } @@ -2031,7 +1890,7 @@ notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /** * Success, connection is up. Signal client our success. * - * @param cls our "struct ConnectContext" + * @param cls our "struct GNUNET_TESTING_ConnectContext" * @param peer identity of the peer that has connected * @param atsi performance information * @@ -2040,64 +1899,36 @@ static void connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TRANSPORT_ATS_Information *atsi) { - struct ConnectContext *ctx = cls; + struct GNUNET_TESTING_ConnectContext *ctx = cls; #if DEBUG_TESTING GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Connected peer %s to peer %s\n", ctx->d1->shortname, GNUNET_i2s (peer)); #endif - if (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity))) - { - - ctx->connected = GNUNET_YES; - ctx->distance = 0; /* FIXME: distance */ - if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK) + if (0 != memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity))) + return; + ctx->connected = GNUNET_YES; + ctx->distance = 0; /* FIXME: distance */ + if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (ctx->hello_send_task); ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; } - GNUNET_SCHEDULER_cancel (ctx->timeout_task); - ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); - } -} - -#if CONNECT_CORE2 -/** - * Success, connection is up. Signal client our success. - * - * @param cls our "struct ConnectContext" - * @param peer identity of the peer that has connected - * @param atsi performance information - * - */ -static void -connect_notify_core2 (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_TRANSPORT_ATS_Information *atsi) -{ - struct ConnectContext *ctx = cls; - - if (memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)) == 0) - { - ctx->connected = GNUNET_YES; - ctx->distance = 0; /* FIXME: distance */ - GNUNET_SCHEDULER_cancel (ctx->timeout_task); - ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); - } - + GNUNET_SCHEDULER_cancel (ctx->timeout_task); + ctx->timeout_task = GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); } -#endif /** * Task called once a core connect request has been transmitted. * - * @param cls struct ConnectContext + * @param cls struct GNUNET_TESTING_ConnectContext * @param success was the request successful? */ void core_connect_request_cont (void *cls, int success) { - struct ConnectContext *ctx = cls; + struct GNUNET_TESTING_ConnectContext *ctx = cls; ctx->connect_request_handle = NULL; } @@ -2105,7 +1936,7 @@ core_connect_request_cont (void *cls, int success) static void send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ConnectContext *ctx = cls; + struct GNUNET_TESTING_ConnectContext *ctx = cls; struct GNUNET_MessageHeader *hello; ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK; @@ -2156,7 +1987,7 @@ core_init_notify (void *cls, struct GNUNET_CORE_Handle *server, const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey) { - struct ConnectContext *connect_ctx = cls; + struct GNUNET_TESTING_ConnectContext *connect_ctx = cls; connect_ctx->d1core_ready = GNUNET_YES; @@ -2182,13 +2013,11 @@ static void reattempt_daemons_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct ConnectContext *ctx = cls; + struct GNUNET_TESTING_ConnectContext *ctx = cls; + ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) - { - GNUNET_free (ctx); return; - } #if DEBUG_TESTING_RECONNECT GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "re-attempting connect of peer %s to peer %s\n", @@ -2264,6 +2093,7 @@ reattempt_daemons_connect (void *cls, _("Failed to connect to transport service!\n")); return; } + GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task); ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx); } else @@ -2282,7 +2112,7 @@ reattempt_daemons_connect (void *cls, * that we don't try to send duplicate connect * requests to core. * - * @param cls our "struct ConnectContext" + * @param cls our "struct GNUNET_TESTING_ConnectContext" * @param peer identity of the peer that has connected, * NULL when iteration has finished * @param atsi performance information @@ -2292,7 +2122,7 @@ static void core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TRANSPORT_ATS_Information *atsi) { - struct ConnectContext *ctx = cls; + struct GNUNET_TESTING_ConnectContext *ctx = cls; if ((peer != NULL) && (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))) @@ -2301,8 +2131,11 @@ core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, ctx->distance = 0; /* FIXME: distance */ return; } - else if (peer == NULL) /* End of iteration over peers */ - { + if (peer != NULL) + return; /* ignore other peers */ + /* peer == NULL: End of iteration over peers */ + + GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->timeout_task); if (ctx->connected == GNUNET_YES) { ctx->timeout_task = @@ -2325,11 +2158,8 @@ core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, if (ctx->d1core == NULL) { - GNUNET_free (ctx); - if (NULL != ctx->cb) - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, - _("Failed to connect to core service of first peer!\n")); + ctx->timeout_task = + GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); return; } @@ -2341,11 +2171,9 @@ core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, if (ctx->d2->th == NULL) { GNUNET_CORE_disconnect (ctx->d1core); - GNUNET_free (ctx); - if (NULL != ctx->cb) - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, - _("Failed to connect to transport service!\n")); + ctx->d1core = NULL; + ctx->timeout_task = + GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); return; } ctx->d2->ghh = @@ -2360,25 +2188,27 @@ core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, if (ctx->d1th == NULL) { GNUNET_CORE_disconnect (ctx->d1core); - GNUNET_free (ctx); - if (NULL != ctx->cb) - ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, - ctx->d2->cfg, ctx->d1, ctx->d2, - _("Failed to connect to transport service!\n")); + ctx->d1core = NULL; + ctx->timeout_task = + GNUNET_SCHEDULER_add_now (¬ify_connect_result, ctx); return; } + GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task); ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx); } ctx->timeout_task = GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout, ¬ify_connect_result, ctx); - } + } /** - * Establish a connection between two GNUnet daemons. + * Establish a connection between two GNUnet daemons. The daemons + * must both be running and not be stopped until either the + * 'cb' callback is called OR the connection request has been + * explicitly cancelled. * * @param d1 handle for the first daemon * @param d2 handle for the second daemon @@ -2390,8 +2220,9 @@ core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer, * the HELLO has already been exchanged * @param cb function to call at the end * @param cb_cls closure for cb + * @return handle to cancel the request */ -void +struct GNUNET_TESTING_ConnectContext * GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, struct GNUNET_TESTING_Daemon *d2, struct GNUNET_TIME_Relative timeout, @@ -2400,7 +2231,7 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, GNUNET_TESTING_NotifyConnection cb, void *cb_cls) { - struct ConnectContext *ctx; + struct GNUNET_TESTING_ConnectContext *ctx; if ((d1->running == GNUNET_NO) || (d2->running == GNUNET_NO)) { @@ -2408,10 +2239,10 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, cb (cb_cls, &d1->id, &d2->id, 0, d1->cfg, d2->cfg, d1, d2, _("Peers are not fully running yet, can not connect!\n")); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peers are not up!\n"); - return; + return NULL; } - ctx = GNUNET_malloc (sizeof (struct ConnectContext)); + ctx = GNUNET_malloc (sizeof (struct GNUNET_TESTING_ConnectContext)); ctx->d1 = d1; ctx->d2 = d2; ctx->timeout_hello = @@ -2432,7 +2263,41 @@ GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1, GNUNET_assert (GNUNET_OK == GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id, &core_initial_iteration, ctx)); - /*GNUNET_assert(GNUNET_OK == GNUNET_CORE_iterate_peers (ctx->d1->cfg, &core_initial_iteration, ctx)); */ + return ctx; } + +/** + * Cancel an attempt to connect two daemons. + * + * @param cc connect context + */ +void +GNUNET_TESTING_daemons_connect_cancel (struct GNUNET_TESTING_ConnectContext + *cc) +{ + if (GNUNET_SCHEDULER_NO_TASK != cc->timeout_task) + { + GNUNET_SCHEDULER_cancel (cc->timeout_task); + cc->timeout_task = GNUNET_SCHEDULER_NO_TASK; + } + if (GNUNET_SCHEDULER_NO_TASK != cc->hello_send_task) + { + GNUNET_SCHEDULER_cancel (cc->hello_send_task); + cc->hello_send_task = GNUNET_SCHEDULER_NO_TASK; + } + if (NULL != cc->d1core) + { + GNUNET_CORE_disconnect (cc->d1core); + cc->d1core = NULL; + } + if (NULL != cc->d1th) + { + GNUNET_TRANSPORT_disconnect (cc->d1th); + cc->d1th = NULL; + } + GNUNET_free (cc); +} + + /* end of testing.c */ diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index 88c51abe0..c81373025 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c @@ -23,7 +23,6 @@ * @brief convenience API for writing testcases for GNUnet * @author Nathan Evans * @author Christian Grothoff - * */ #include "platform.h" #include "gnunet_constants.h" @@ -710,6 +709,8 @@ struct ConnectTopologyContext void *notify_cls; }; +struct ConnectContext; + /** * Handle to a group of GNUnet peers. */ @@ -720,6 +721,10 @@ struct GNUNET_TESTING_PeerGroup */ const struct GNUNET_CONFIGURATION_Handle *cfg; + struct ConnectContext *cc_head; + + struct ConnectContext *cc_tail; + /** * Function to call on each started daemon. */ @@ -866,6 +871,11 @@ struct UpdateContext struct ConnectContext { + + struct ConnectContext *next; + + struct ConnectContext *prev; + /** * Index of peer to connect second to. */ @@ -876,6 +886,16 @@ struct ConnectContext */ uint32_t second_index; + /** + * Task associated with the attempt to connect. + */ + GNUNET_SCHEDULER_TaskIdentifier task; + + /** + * Context in 'testing.c', to cancel connection attempt. + */ + struct GNUNET_TESTING_ConnectContext *cc; + /** * Higher level topology connection context. */ @@ -3188,7 +3208,7 @@ schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); * Choose a random peer's next connection to create, and * call schedule_connect to set up the connect task. * - * @param ct_ctx the overall connection context + * @param pg the peer group to connect */ static void preschedule_connect (struct GNUNET_TESTING_PeerGroup *pg) @@ -3211,7 +3231,10 @@ preschedule_connect (struct GNUNET_TESTING_PeerGroup *pg) connect_context->first_index = random_peer; connect_context->second_index = connection_iter->index; connect_context->ct_ctx = ct_ctx; - GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); + connect_context->task = GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); + GNUNET_CONTAINER_DLL_insert (pg->cc_head, + pg->cc_tail, + connect_context); GNUNET_CONTAINER_DLL_remove (pg->peers[random_peer].connect_peers_head, pg->peers[random_peer].connect_peers_tail, connection_iter); @@ -3508,15 +3531,6 @@ hello_sent_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert (send_hello_context->peer->daemon->th != NULL); GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th); send_hello_context->peer->daemon->th = NULL; - - /*if (send_hello_context->pg->remaining_hellos == 0) - * { - * for (pg_iter = 0; pg_iter < send_hello_context->pg->max_outstanding_connections; pg_iter++) - * { - * preschedule_connect(&send_hello_context->pg->ct_ctx); - * } - * } - */ GNUNET_assert (send_hello_context->peer->daemon->server == NULL); send_hello_context->peer->daemon->server = GNUNET_CORE_connect (send_hello_context->peer->cfg, 1, @@ -3621,9 +3635,13 @@ internal_connect_notify (void *cls, const struct GNUNET_PeerIdentity *first, struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg; struct PeerConnection *connection; + GNUNET_assert (NULL != connect_ctx->cc); + connect_ctx->cc = NULL; GNUNET_assert (0 < pg->outstanding_connects); pg->outstanding_connects--; - + GNUNET_CONTAINER_DLL_remove (pg->cc_head, + pg->cc_tail, + connect_ctx); /* * Check whether the inverse connection has been scheduled yet, * if not, we can remove it from the other peers list and avoid @@ -3638,9 +3656,7 @@ internal_connect_notify (void *cls, const struct GNUNET_PeerIdentity *first, (0 != memcmp (first, &pg->peers[connection->index].daemon->id, sizeof (struct GNUNET_PeerIdentity)))) - { connection = connection->next; - } if (connection != NULL) /* Can safely remove! */ { @@ -3675,7 +3691,6 @@ internal_connect_notify (void *cls, const struct GNUNET_PeerIdentity *first, pg->notify_connection (pg->notify_connection_cls, first, second, distance, first_cfg, second_cfg, first_daemon, second_daemon, emsg); - GNUNET_free (connect_ctx); } @@ -3692,6 +3707,7 @@ schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct ConnectContext *connect_context = cls; struct GNUNET_TESTING_PeerGroup *pg = connect_context->ct_ctx->pg; + connect_context->task = GNUNET_SCHEDULER_NO_TASK; if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) return; @@ -3703,12 +3719,11 @@ schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) _ ("Delaying connect, we have too many outstanding connections!\n")); #endif - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_MILLISECONDS, 100), - &schedule_connect, connect_context); + connect_context->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply + (GNUNET_TIME_UNIT_MILLISECONDS, 100), + &schedule_connect, connect_context); + return; } - else - { #if VERBOSE_TESTING GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _ @@ -3717,7 +3732,9 @@ schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) #endif pg->outstanding_connects++; pg->total_connects_scheduled++; - GNUNET_TESTING_daemons_connect (pg-> + GNUNET_assert (NULL == connect_context->cc); + connect_context->cc + = GNUNET_TESTING_daemons_connect (pg-> peers[connect_context->first_index].daemon, pg->peers[connect_context-> second_index].daemon, @@ -3728,8 +3745,8 @@ schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) #else GNUNET_YES, #endif - &internal_connect_notify, connect_context); /* FIXME: free connect context! */ - } + &internal_connect_notify, connect_context); + } #if !OLD @@ -3755,8 +3772,10 @@ connect_iterator (void *cls, const GNUNET_HashCode * key, void *value) connect_context->first = first->daemon; connect_context->second = second; connect_context->ct_ctx = ct_ctx; - GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); - + connect_context->task = GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); + GNUNET_CONTAINER_DLL_insert (ct_ctx->pg->cc_head, + ct_ctx->pg->cc_tail, + connect_context); return GNUNET_YES; } #endif @@ -7080,8 +7099,20 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, struct PeerConnection *conn_iter; struct PeerConnection *temp_conn; #endif + struct ConnectContext *cc; GNUNET_assert (pg->total > 0); + while (NULL != (cc = pg->cc_head)) + { + GNUNET_CONTAINER_DLL_remove (pg->cc_head, + pg->cc_tail, + cc); + if (GNUNET_SCHEDULER_NO_TASK != cc->task) + GNUNET_SCHEDULER_cancel (cc->task); + if (NULL != cc->cc) + GNUNET_TESTING_daemons_connect_cancel (cc->cc); + GNUNET_free (cc); + } shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext)); shutdown_ctx->delete_files = @@ -7091,7 +7122,6 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg, shutdown_ctx->total_peers = pg->total; shutdown_ctx->timeout = timeout; shutdown_ctx->pg = pg; - /* shtudown_ctx->outstanding = 0; */ for (off = 0; off < pg->total; off++) { diff --git a/src/topology/test_gnunet_daemon_topology.c b/src/topology/test_gnunet_daemon_topology.c index c9a43ecd7..3429f50ec 100644 --- a/src/topology/test_gnunet_daemon_topology.c +++ b/src/topology/test_gnunet_daemon_topology.c @@ -48,6 +48,11 @@ static struct GNUNET_TESTING_Daemon *first; static struct GNUNET_TESTING_Daemon *last; +/** + * Active connection attempt. + */ +struct GNUNET_TESTING_ConnectContext *cc[NUM_PEERS]; + /** * Check whether peers successfully shut down. */ @@ -74,6 +79,16 @@ shutdown_callback (void *cls, const char *emsg) static void clean_up_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { + unsigned int i; + + for (i=0;i