diff options
author | Bart Polot <bart@net.in.tum.de> | 2011-09-26 12:24:41 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2011-09-26 12:24:41 +0000 |
commit | 535d51c21e7ed8b8e1f9bec144c54f177de6b2f5 (patch) | |
tree | a824b52be525a48289f2191c638f4d5c9d26d138 /src/mesh | |
parent | aa390e34b0b9e793e1c9f82a606ad0c10fcc84ca (diff) | |
download | gnunet-535d51c21e7ed8b8e1f9bec144c54f177de6b2f5.tar.gz gnunet-535d51c21e7ed8b8e1f9bec144c54f177de6b2f5.zip |
Added new api in the tree module to handle core or remote disconnections
Added reconnecting mechanism to find new paths in case of peer disconnection
Diffstat (limited to 'src/mesh')
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 125 | ||||
-rw-r--r-- | src/mesh/mesh_tunnel_tree.c | 109 | ||||
-rw-r--r-- | src/mesh/mesh_tunnel_tree.h | 28 |
3 files changed, 242 insertions, 20 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 122280369..79f9182f0 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -601,6 +601,32 @@ announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
601 | } | 601 | } |
602 | 602 | ||
603 | 603 | ||
604 | /** | ||
605 | * Function to process paths received for a new peer addition. The recorded | ||
606 | * paths form the initial tunnel, which can be optimized later. | ||
607 | * Called on each result obtained for the DHT search. | ||
608 | * | ||
609 | * @param cls closure | ||
610 | * @param exp when will this value expire | ||
611 | * @param key key of the result | ||
612 | * @param get_path NULL-terminated array of pointers | ||
613 | * to the peers on reverse GET path (or NULL if not recorded) | ||
614 | * @param put_path NULL-terminated array of pointers | ||
615 | * to the peers on the PUT path (or NULL if not recorded) | ||
616 | * @param type type of the result | ||
617 | * @param size number of bytes in data | ||
618 | * @param data pointer to the result data | ||
619 | * | ||
620 | * FIXME path | ||
621 | */ | ||
622 | static void | ||
623 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
624 | const GNUNET_HashCode * key, | ||
625 | const struct GNUNET_PeerIdentity *const *get_path, | ||
626 | const struct GNUNET_PeerIdentity *const *put_path, | ||
627 | enum GNUNET_BLOCK_Type type, size_t size, const void *data); | ||
628 | |||
629 | |||
604 | /******************************************************************************/ | 630 | /******************************************************************************/ |
605 | /****************** GENERAL HELPER FUNCTIONS ************************/ | 631 | /****************** GENERAL HELPER FUNCTIONS ************************/ |
606 | /******************************************************************************/ | 632 | /******************************************************************************/ |
@@ -661,33 +687,43 @@ peer_info_destroy (struct MeshPeerInfo *pi) | |||
661 | * Notify a tunnel that a connection has broken that affects at least | 687 | * Notify a tunnel that a connection has broken that affects at least |
662 | * some of its peers. | 688 | * some of its peers. |
663 | * | 689 | * |
664 | * @param t Tunnel affected | 690 | * @param t Tunnel affected. |
665 | * @param peer Peer that (at least) has been affected by the disconnection | 691 | * @param peer Peer that (at least) has been affected by the disconnection. |
666 | * @param p1 Peer that got disconnected from p2 | 692 | * @param p1 Peer that got disconnected from p2. |
667 | * @param p2 Peer that got disconnected from p1 | 693 | * @param p2 Peer that got disconnected from p1. |
694 | * | ||
695 | * @return Short ID of the peer disconnected (either p1 or p2). | ||
696 | * 0 if the tunnel remained unaffected. | ||
668 | */ | 697 | */ |
669 | static void | 698 | static GNUNET_PEER_Id |
670 | tunnel_notify_connection_broken (struct MeshTunnel *t, | 699 | tunnel_notify_connection_broken (struct MeshTunnel *t, |
671 | struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, | 700 | struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, |
672 | GNUNET_PEER_Id p2); | 701 | GNUNET_PEER_Id p2); |
673 | 702 | ||
674 | |||
675 | /** | 703 | /** |
676 | * Remove all paths that rely on a direct connection between p1 and p2 | 704 | * Remove all paths that rely on a direct connection between p1 and p2 |
677 | * from the peer itself and notify all tunnels about it. | 705 | * from the peer itself and notify all tunnels about it. |
678 | * | 706 | * |
679 | * @param pi PeerInfo of affected peer | 707 | * @param peer PeerInfo of affected peer. |
680 | * @param p1 GNUNET_PEER_Id of one peer. | 708 | * @param p1 GNUNET_PEER_Id of one peer. |
681 | * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and | 709 | * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and |
682 | * no longer is. | 710 | * no longer is. |
711 | * | ||
712 | * TODO: optimize (see below) | ||
683 | */ | 713 | */ |
684 | static void | 714 | static void |
685 | path_remove_from_peer (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, | 715 | path_remove_from_peer (struct MeshPeerInfo *peer, |
716 | GNUNET_PEER_Id p1, | ||
686 | GNUNET_PEER_Id p2) | 717 | GNUNET_PEER_Id p2) |
687 | { | 718 | { |
719 | struct GNUNET_PeerIdentity id; | ||
688 | struct MeshPeerPath *p; | 720 | struct MeshPeerPath *p; |
689 | struct MeshPeerPath *aux; | 721 | struct MeshPeerPath *aux; |
722 | struct MeshPeerInfo *peer_d; | ||
723 | GNUNET_PEER_Id d; | ||
690 | unsigned int destroyed; | 724 | unsigned int destroyed; |
725 | unsigned int best; | ||
726 | unsigned int cost; | ||
691 | unsigned int i; | 727 | unsigned int i; |
692 | 728 | ||
693 | destroyed = 0; | 729 | destroyed = 0; |
@@ -712,7 +748,56 @@ path_remove_from_peer (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, | |||
712 | 748 | ||
713 | for (i = 0; i < peer->ntunnels; i++) | 749 | for (i = 0; i < peer->ntunnels; i++) |
714 | { | 750 | { |
715 | tunnel_notify_connection_broken (peer->tunnels[i], peer, p1, p2); | 751 | d = tunnel_notify_connection_broken (peer->tunnels[i], peer, p1, p2); |
752 | /* TODO | ||
753 | * Problem: one or more peers have been deleted from the tunnel tree. | ||
754 | * We don't know who they are to try to add them again. | ||
755 | * We need to try to find a new path for each of the disconnected peers. | ||
756 | * Some of them might already have a path to reach them that does not | ||
757 | * involve p1 and p2. Adding all anew might render in a better tree than | ||
758 | * the trivial immediate fix. | ||
759 | * | ||
760 | * Trivial immiediate fix: try to reconnect to the disconnected node. All | ||
761 | * its children will be reachable trough him. | ||
762 | */ | ||
763 | GNUNET_PEER_resolve(d, &id); | ||
764 | peer_d = peer_info_get(&id); | ||
765 | best = UINT_MAX; | ||
766 | aux = NULL; | ||
767 | for (p = peer_d->path_head; NULL != p; p = p->next) | ||
768 | { | ||
769 | if ((cost = path_get_cost(peer->tunnels[i]->tree, p)) < best) | ||
770 | { | ||
771 | best = cost; | ||
772 | aux = p; | ||
773 | } | ||
774 | } | ||
775 | if (NULL != aux) | ||
776 | { | ||
777 | /* No callback, as peer will be already disconnected */ | ||
778 | tree_add_path(peer->tunnels[i]->tree, aux, NULL); | ||
779 | } | ||
780 | else | ||
781 | { | ||
782 | struct MeshPathInfo *path_info; | ||
783 | |||
784 | path_info = GNUNET_malloc(sizeof(struct MeshPathInfo)); | ||
785 | path_info->path = p; | ||
786 | path_info->peer = peer_d; | ||
787 | path_info->t = peer->tunnels[i]; | ||
788 | peer_d->dhtget = GNUNET_DHT_get_start(dht_handle, /* handle */ | ||
789 | GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */ | ||
790 | GNUNET_BLOCK_TYPE_TEST, /* type */ | ||
791 | &id.hashPubKey, /*key to search */ | ||
792 | 4, /* replication level */ | ||
793 | GNUNET_DHT_RO_RECORD_ROUTE, | ||
794 | NULL, /* bloom filter */ | ||
795 | 0, /* mutator */ | ||
796 | NULL, /* xquery */ | ||
797 | 0, /* xquery bits */ | ||
798 | dht_get_id_handler, | ||
799 | (void *) path_info); | ||
800 | } | ||
716 | } | 801 | } |
717 | } | 802 | } |
718 | 803 | ||
@@ -1051,18 +1136,24 @@ tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) | |||
1051 | * Notify a tunnel that a connection has broken that affects at least | 1136 | * Notify a tunnel that a connection has broken that affects at least |
1052 | * some of its peers. | 1137 | * some of its peers. |
1053 | * | 1138 | * |
1054 | * @param t Tunnel affected | 1139 | * @param t Tunnel affected. |
1055 | * @param peer Peer that (at least) has been affected by the disconnection | 1140 | * @param peer Peer that (at least) has been affected by the disconnection. |
1056 | * @param p1 Peer that got disconnected from p2 | 1141 | * @param p1 Peer that got disconnected from p2. |
1057 | * @param p2 Peer that got disconnected from p1 | 1142 | * @param p2 Peer that got disconnected from p1. |
1058 | * | 1143 | * |
1059 | * FIXME path | 1144 | * @return Short ID of the peer disconnected (either p1 or p2). |
1145 | * 0 if the tunnel remained unaffected. | ||
1146 | * | ||
1147 | * FIXME working on it | ||
1060 | */ | 1148 | */ |
1061 | static void | 1149 | static GNUNET_PEER_Id |
1062 | tunnel_notify_connection_broken (struct MeshTunnel *t, | 1150 | tunnel_notify_connection_broken (struct MeshTunnel *t, |
1063 | struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, | 1151 | struct MeshPeerInfo *peer, |
1152 | GNUNET_PEER_Id p1, | ||
1064 | GNUNET_PEER_Id p2) | 1153 | GNUNET_PEER_Id p2) |
1065 | { | 1154 | { |
1155 | return tree_notify_connection_broken (t->tree, p1, p2, | ||
1156 | ¬ify_peer_disconnected); | ||
1066 | } | 1157 | } |
1067 | 1158 | ||
1068 | 1159 | ||
diff --git a/src/mesh/mesh_tunnel_tree.c b/src/mesh/mesh_tunnel_tree.c index 748683a34..9c8d5e97d 100644 --- a/src/mesh/mesh_tunnel_tree.c +++ b/src/mesh/mesh_tunnel_tree.c | |||
@@ -386,9 +386,22 @@ tree_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, | |||
386 | struct MeshTunnelTreeNode *node; | 386 | struct MeshTunnelTreeNode *node; |
387 | struct MeshTunnelTreeNode *n; | 387 | struct MeshTunnelTreeNode *n; |
388 | 388 | ||
389 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting path to %u.\n", peer_id); | 389 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, |
390 | "tree: Deleting path to %u.\n", peer_id); | ||
390 | if (peer_id == t->root->peer) | 391 | if (peer_id == t->root->peer) |
391 | return NULL; | 392 | return NULL; |
393 | |||
394 | for (n = t->disconnected_head; NULL != n; n = n->next) | ||
395 | { | ||
396 | if (n->peer == peer_id) | ||
397 | { | ||
398 | /* Was already pathless, waiting for reconnection */ | ||
399 | GNUNET_CONTAINER_DLL_remove (t->disconnected_head, | ||
400 | t->disconnected_tail, | ||
401 | n); | ||
402 | return n; | ||
403 | } | ||
404 | } | ||
392 | n = tree_find_peer (t->me, peer_id); | 405 | n = tree_find_peer (t->me, peer_id); |
393 | if (NULL == n) | 406 | if (NULL == n) |
394 | return NULL; | 407 | return NULL; |
@@ -470,8 +483,9 @@ tree_get_path_to_peer(struct MeshTunnelTree *t, GNUNET_PEER_Id peer) | |||
470 | * - do not disconnect peers until new path is created & connected | 483 | * - do not disconnect peers until new path is created & connected |
471 | */ | 484 | */ |
472 | int | 485 | int |
473 | tree_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, | 486 | tree_add_path (struct MeshTunnelTree *t, |
474 | MeshNodeDisconnectCB cb) | 487 | const struct MeshPeerPath *p, |
488 | MeshNodeDisconnectCB cb) | ||
475 | { | 489 | { |
476 | struct MeshTunnelTreeNode *parent; | 490 | struct MeshTunnelTreeNode *parent; |
477 | struct MeshTunnelTreeNode *oldnode; | 491 | struct MeshTunnelTreeNode *oldnode; |
@@ -589,6 +603,95 @@ tree_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, | |||
589 | 603 | ||
590 | 604 | ||
591 | /** | 605 | /** |
606 | * Notifies a tree that a connection it might be using is broken. | ||
607 | * Marks all peers down the paths as disconnected and notifies the client. | ||
608 | * | ||
609 | * @param t Tree to use. | ||
610 | * @param p1 Short id of one of the peers (order unimportant) | ||
611 | * @param p2 Short id of one of the peers (order unimportant) | ||
612 | * @param cb Function to call for every peer that is marked as disconnected. | ||
613 | * | ||
614 | * @return Short ID of the first disconnected peer in the tree. | ||
615 | */ | ||
616 | GNUNET_PEER_Id | ||
617 | tree_notify_connection_broken (struct MeshTunnelTree *t, | ||
618 | GNUNET_PEER_Id p1, | ||
619 | GNUNET_PEER_Id p2, | ||
620 | MeshNodeDisconnectCB cb) | ||
621 | { | ||
622 | struct MeshTunnelTreeNode *n; | ||
623 | struct MeshTunnelTreeNode *c; | ||
624 | |||
625 | n = tree_find_peer(t->me, p1); | ||
626 | if (NULL == n) | ||
627 | return 0; | ||
628 | if (NULL != n->parent && n->parent->peer == p2) | ||
629 | { | ||
630 | tree_mark_peers_disconnected(t, n, cb); | ||
631 | GNUNET_CONTAINER_DLL_remove(n->parent->children_head, | ||
632 | n->parent->children_tail, | ||
633 | n); | ||
634 | GNUNET_CONTAINER_DLL_insert(t->disconnected_head, | ||
635 | t->disconnected_tail, | ||
636 | n); | ||
637 | return p1; | ||
638 | } | ||
639 | for (c = n->children_head; NULL != c; c = c->next) | ||
640 | { | ||
641 | if (c->peer == p2) | ||
642 | { | ||
643 | tree_mark_peers_disconnected(t, c, cb); | ||
644 | GNUNET_CONTAINER_DLL_remove(n->children_head, | ||
645 | n->children_tail, | ||
646 | c); | ||
647 | GNUNET_CONTAINER_DLL_insert(t->disconnected_head, | ||
648 | t->disconnected_tail, | ||
649 | c); | ||
650 | return p2; | ||
651 | } | ||
652 | } | ||
653 | return 0; | ||
654 | } | ||
655 | |||
656 | |||
657 | /** | ||
658 | * Deletes a peer from a tunnel, marking its children as disconnected. | ||
659 | * | ||
660 | * @param t Tunnel tree to use. | ||
661 | * @param peer Short ID of the peer to remove from the tunnel tree. | ||
662 | * @param cb Callback to notify client of disconnected peers. | ||
663 | * | ||
664 | * @return GNUNET_OK or GNUNET_SYSERR | ||
665 | */ | ||
666 | int | ||
667 | tree_del_peer (struct MeshTunnelTree *t, | ||
668 | GNUNET_PEER_Id peer, | ||
669 | MeshNodeDisconnectCB cb) | ||
670 | { | ||
671 | struct MeshTunnelTreeNode *n; | ||
672 | struct MeshTunnelTreeNode *c; | ||
673 | struct MeshTunnelTreeNode *aux; | ||
674 | |||
675 | n = tree_del_path(t, peer, cb); | ||
676 | c = n->children_head; | ||
677 | while (NULL != c) | ||
678 | { | ||
679 | aux = c->next; | ||
680 | GNUNET_CONTAINER_DLL_remove(n->children_head, | ||
681 | n->children_tail, | ||
682 | c); | ||
683 | GNUNET_CONTAINER_DLL_insert(t->disconnected_head, | ||
684 | t->disconnected_tail, | ||
685 | c); | ||
686 | cb (c); | ||
687 | c = aux; | ||
688 | } | ||
689 | tree_node_destroy(n); | ||
690 | return GNUNET_OK; | ||
691 | } | ||
692 | |||
693 | |||
694 | /** | ||
592 | * Print the tree on stderr | 695 | * Print the tree on stderr |
593 | * | 696 | * |
594 | * @param t The tree | 697 | * @param t The tree |
diff --git a/src/mesh/mesh_tunnel_tree.h b/src/mesh/mesh_tunnel_tree.h index 252929549..f187e7957 100644 --- a/src/mesh/mesh_tunnel_tree.h +++ b/src/mesh/mesh_tunnel_tree.h | |||
@@ -128,6 +128,16 @@ struct MeshTunnelTree | |||
128 | struct MeshTunnelTreeNode *me; | 128 | struct MeshTunnelTreeNode *me; |
129 | 129 | ||
130 | /** | 130 | /** |
131 | * DLL of disconneted nodes | ||
132 | */ | ||
133 | struct MeshTunnelTreeNode *disconnected_head; | ||
134 | |||
135 | /** | ||
136 | * DLL of disconneted nodes | ||
137 | */ | ||
138 | struct MeshTunnelTreeNode *disconnected_tail; | ||
139 | |||
140 | /** | ||
131 | * Cache of all peers and the first hop to them. | 141 | * Cache of all peers and the first hop to them. |
132 | * Indexed by PeerIdentity, contains a pointer to the PeerIdentity | 142 | * Indexed by PeerIdentity, contains a pointer to the PeerIdentity |
133 | * of 1st hop. | 143 | * of 1st hop. |
@@ -298,6 +308,24 @@ tree_add_path (struct MeshTunnelTree *t, | |||
298 | 308 | ||
299 | 309 | ||
300 | /** | 310 | /** |
311 | * Notifies a tree that a connection it might be using is broken. | ||
312 | * Marks all peers down the paths as disconnected and notifies the client. | ||
313 | * | ||
314 | * @param t Tree to use. | ||
315 | * @param p1 Short id of one of the peers (order unimportant) | ||
316 | * @param p2 Short id of one of the peers (order unimportant) | ||
317 | * @param cb Function to call for every peer that is marked as disconnected. | ||
318 | * | ||
319 | * @return Short ID of the first disconnected peer in the tree. | ||
320 | */ | ||
321 | GNUNET_PEER_Id | ||
322 | tree_notify_connection_broken (struct MeshTunnelTree *t, | ||
323 | GNUNET_PEER_Id p1, | ||
324 | GNUNET_PEER_Id p2, | ||
325 | MeshNodeDisconnectCB cb); | ||
326 | |||
327 | |||
328 | /** | ||
301 | * Print the tree on stderr | 329 | * Print the tree on stderr |
302 | * | 330 | * |
303 | * @param t The tree | 331 | * @param t The tree |