From 341704937b8b07b415376f8f0bd13bbc7d26d44c Mon Sep 17 00:00:00 2001 From: Bart Polot Date: Fri, 2 Oct 2015 03:37:42 +0000 Subject: Fixed usage of known broken paths. If a connection was destroyed while handling a neighbor disconnection, cadet tried to reconnect to peers using paths containing the disconnecting peer. --- src/cadet/gnunet-service-cadet_connection.c | 59 +++++++++++++++++------------ src/cadet/gnunet-service-cadet_dht.c | 1 + src/cadet/gnunet-service-cadet_peer.c | 23 ++++++----- src/cadet/gnunet-service-cadet_peer.h | 4 +- 4 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index b82c788e9..8c25a46b7 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c @@ -1354,7 +1354,12 @@ connection_cancel_queues (struct CadetConnection *c, { GNUNET_SCHEDULER_cancel (fc->poll_task); fc->poll_task = NULL; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Cancel POLL in ccq for fc %p\n", fc); + LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL task for fc %p\n", fc); + } + if (NULL != fc->poll_msg) + { + GCC_cancel (fc->poll_msg); + LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL msg for fc %p\n", fc); } peer = get_hop (c, fwd); GCP_queue_cancel (peer, c); @@ -1851,6 +1856,30 @@ unregister_neighbors (struct CadetConnection *c) } +/** + * Invalidates all paths towards all peers that comprise the connection which + * rely on the disconnected peer. + * + * ~O(n^3) (peers in connection * paths/peer * links/path) + * + * @param c Connection whose peers' paths to clean. + * @param disconnected Peer that disconnected. + */ +static void +invalidate_paths (struct CadetConnection *c, struct CadetPeer *disconnected) +{ + struct CadetPeer *peer; + unsigned int i; + + for (i = 0; i < c->path->length; i++) + { + peer = GCP_get_short (c->path->peers[i], GNUNET_NO); + if (NULL != peer) + GCP_notify_broken_link (peer, &my_full_id, GCP_get_id (disconnected)); + } +} + + /** * Bind the connection to the peer and the tunnel to that peer. * @@ -3045,20 +3074,6 @@ GCC_destroy (struct CadetConnection *c) path_destroy (c->path); c->path = NULL; - /* Cancel maintainance task (keepalive/timeout) */ - if (NULL != c->fwd_fc.poll_msg) - { - GCC_cancel (c->fwd_fc.poll_msg); - LOG (GNUNET_ERROR_TYPE_DEBUG, - " POLL msg FWD canceled\n"); - } - if (NULL != c->bck_fc.poll_msg) - { - GCC_cancel (c->bck_fc.poll_msg); - LOG (GNUNET_ERROR_TYPE_DEBUG, - " POLL msg BCK canceled\n"); - } - /* Delete from tunnel */ if (NULL != c->t) GCT_remove_connection (c->t, c); @@ -3069,16 +3084,7 @@ GCC_destroy (struct CadetConnection *c) GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task); if (NULL != c->bck_maintenance_task) GNUNET_SCHEDULER_cancel (c->bck_maintenance_task); - if (NULL != c->fwd_fc.poll_task) - { - GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task); - LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL task FWD canceled\n"); - } - if (NULL != c->bck_fc.poll_task) - { - GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task); - LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL task BCK canceled\n"); - } + if (GNUNET_NO == c->was_removed) { GNUNET_break (GNUNET_YES == @@ -3289,6 +3295,9 @@ GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer) LOG (GNUNET_ERROR_TYPE_DEBUG, "shutting down %s, %s disconnected\n", GCC_2s (c), peer_name); + + invalidate_paths (c, peer); + hop = get_prev_hop (c); if (NULL == hop) { diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c index cdc1f5a7f..e4ae52da3 100644 --- a/src/cadet/gnunet-service-cadet_dht.c +++ b/src/cadet/gnunet-service-cadet_dht.c @@ -187,6 +187,7 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, s = path_2s (p); LOG (GNUNET_ERROR_TYPE_INFO, "Got path from DHT: %s\n", s); GNUNET_free_non_null (s); + peer = GCP_get_short (p->peers[p->length - 1], GNUNET_YES); LOG (GNUNET_ERROR_TYPE_DEBUG, "Got HELLO for %s\n", GCP_2s (peer)); h->callback (h->cls, p); diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c index d60858321..9d80336bd 100644 --- a/src/cadet/gnunet-service-cadet_peer.c +++ b/src/cadet/gnunet-service-cadet_peer.c @@ -358,9 +358,8 @@ notify_broken (void *cls, struct CadetConnection *c = value; LOG (GNUNET_ERROR_TYPE_DEBUG, - "Notifying %s due to %s\n", - GCC_2s (c), - GCP_2s (peer)); + "Notifying %s due to %s disconnect\n", + GCC_2s (c), GCP_2s (peer)); GCC_neighbor_disconnected (c, peer); return GNUNET_YES; } @@ -1016,8 +1015,8 @@ peer_get_first_message (const struct CadetPeer *peer) * paths form the initial tunnel, which can be optimized later. * Called on each result obtained for the DHT search. * - * @param cls closure - * @param path + * @param cls Closure (peer towards a path has been found). + * @param path Path created from the DHT query. Will be freed afterwards. */ static void search_handler (void *cls, const struct CadetPeerPath *path) @@ -1537,7 +1536,7 @@ GCP_queue_cancel (struct CadetPeer *peer, LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type)); - GNUNET_break (GNUNET_NO == connection_destroyed); + GNUNET_assert (GNUNET_NO == connection_destroyed); if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type) { q->c = NULL; @@ -2066,7 +2065,7 @@ GCP_add_connection (struct CadetPeer *peer, * is the shortest. * * @param peer Destination peer to add the path to. - * @param path New path to add. Last peer must be the peer in arg 1. + * @param path New path to add. Last peer must be @c peer. * Path will be either used of freed if already known. * @param trusted Do we trust that this path is real? * @@ -2206,13 +2205,13 @@ GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; for (i++; i < p->length; i++) { - struct CadetPeer *aux; + struct CadetPeer *peer; struct CadetPeerPath *copy; - aux = GCP_get_short (p->peers[i], GNUNET_YES); + peer = GCP_get_short (p->peers[i], GNUNET_YES); copy = path_duplicate (p); copy->length = i + 1; - GCP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed); + GCP_add_path (peer, copy, 3 > p->length ? GNUNET_NO : confirmed); } GCC_check_connections (); } @@ -2531,8 +2530,8 @@ GCP_try_connect (struct CadetPeer *peer) */ void GCP_notify_broken_link (struct CadetPeer *peer, - struct GNUNET_PeerIdentity *peer1, - struct GNUNET_PeerIdentity *peer2) + const struct GNUNET_PeerIdentity *peer1, + const struct GNUNET_PeerIdentity *peer2) { struct CadetPeerPath *iter; struct CadetPeerPath *next; diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h index 7a60b33bd..65704f9c4 100644 --- a/src/cadet/gnunet-service-cadet_peer.h +++ b/src/cadet/gnunet-service-cadet_peer.h @@ -450,8 +450,8 @@ GCP_try_connect (struct CadetPeer *peer); */ void GCP_notify_broken_link (struct CadetPeer *peer, - struct GNUNET_PeerIdentity *peer1, - struct GNUNET_PeerIdentity *peer2); + const struct GNUNET_PeerIdentity *peer1, + const struct GNUNET_PeerIdentity *peer2); /** -- cgit v1.2.3