diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-03-14 15:39:29 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-03-14 15:39:29 +0000 |
commit | 4bb84af9b3fe9a6808025a9c7040f3b772ebb7a8 (patch) | |
tree | bd6cdc0b03cfbe3b835f2509cd9961b916d78c0b /src/dv | |
parent | c03a9267dd1f710c1f75550308beb5eda59171b5 (diff) | |
download | gnunet-4bb84af9b3fe9a6808025a9c7040f3b772ebb7a8.tar.gz gnunet-4bb84af9b3fe9a6808025a9c7040f3b772ebb7a8.zip |
-more DV hacking
Diffstat (limited to 'src/dv')
-rw-r--r-- | src/dv/gnunet-service-dv.c | 421 |
1 files changed, 338 insertions, 83 deletions
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c index 63f49f53a..c42d9344e 100644 --- a/src/dv/gnunet-service-dv.c +++ b/src/dv/gnunet-service-dv.c | |||
@@ -28,11 +28,11 @@ | |||
28 | * @author Nathan Evans | 28 | * @author Nathan Evans |
29 | * | 29 | * |
30 | * TODO: | 30 | * TODO: |
31 | * - routing tables are not exchanged with direct neighbors | 31 | * - even _local_ flow control (send ACK only after core took our message) is |
32 | * not implemented, but should be (easy fix, but needs adjustments to data | ||
33 | * structures) | ||
32 | * - distance updates are not properly communicate to US by core, | 34 | * - distance updates are not properly communicate to US by core, |
33 | * and conversely we don't give distance updates properly to the plugin yet | 35 | * and conversely we don't give distance updates properly to the plugin yet |
34 | * - even local flow control (send ACK only after core took our message) is | ||
35 | * not implemented, but should be (easy fix) | ||
36 | * - we send 'ACK' even if a message was dropped due to no route (may | 36 | * - we send 'ACK' even if a message was dropped due to no route (may |
37 | * be harmless, but should at least be documented) | 37 | * be harmless, but should at least be documented) |
38 | */ | 38 | */ |
@@ -45,6 +45,7 @@ | |||
45 | #include "gnunet_statistics_service.h" | 45 | #include "gnunet_statistics_service.h" |
46 | #include "gnunet_consensus_service.h" | 46 | #include "gnunet_consensus_service.h" |
47 | #include "dv.h" | 47 | #include "dv.h" |
48 | #include <gcrypt.h> | ||
48 | 49 | ||
49 | /** | 50 | /** |
50 | * How often do we establish the consensu? | 51 | * How often do we establish the consensu? |
@@ -84,7 +85,7 @@ struct Target | |||
84 | struct GNUNET_PeerIdentity peer; | 85 | struct GNUNET_PeerIdentity peer; |
85 | 86 | ||
86 | /** | 87 | /** |
87 | * How many hops (1-3) is this peer away? | 88 | * How many hops (1-3) is this peer away? in network byte order |
88 | */ | 89 | */ |
89 | uint32_t distance GNUNET_PACKED; | 90 | uint32_t distance GNUNET_PACKED; |
90 | 91 | ||
@@ -231,6 +232,11 @@ struct DirectNeighbor | |||
231 | */ | 232 | */ |
232 | unsigned int pm_queue_size; | 233 | unsigned int pm_queue_size; |
233 | 234 | ||
235 | /** | ||
236 | * Flag set within 'check_target_removed' to trigger full global route refresh. | ||
237 | */ | ||
238 | int target_removed; | ||
239 | |||
234 | }; | 240 | }; |
235 | 241 | ||
236 | 242 | ||
@@ -715,7 +721,7 @@ allocate_route (struct Route *route, | |||
715 | i = get_consensus_slot (distance); | 721 | i = get_consensus_slot (distance); |
716 | route->set_offset = i; | 722 | route->set_offset = i; |
717 | consensi[distance].targets[i] = route; | 723 | consensi[distance].targets[i] = route; |
718 | route->target.distance = distance; | 724 | route->target.distance = htonl (distance); |
719 | } | 725 | } |
720 | 726 | ||
721 | 727 | ||
@@ -727,7 +733,7 @@ allocate_route (struct Route *route, | |||
727 | static void | 733 | static void |
728 | release_route (struct Route *route) | 734 | release_route (struct Route *route) |
729 | { | 735 | { |
730 | consensi[route->target.distance].targets[route->set_offset] = NULL; | 736 | consensi[ntohl (route->target.distance)].targets[route->set_offset] = NULL; |
731 | route->set_offset = UINT_MAX; /* indicate invalid slot */ | 737 | route->set_offset = UINT_MAX; /* indicate invalid slot */ |
732 | } | 738 | } |
733 | 739 | ||
@@ -748,7 +754,7 @@ move_route (struct Route *route, | |||
748 | i = get_consensus_slot (new_distance); | 754 | i = get_consensus_slot (new_distance); |
749 | route->set_offset = i; | 755 | route->set_offset = i; |
750 | consensi[new_distance].targets[i] = route; | 756 | consensi[new_distance].targets[i] = route; |
751 | route->target.distance = new_distance; | 757 | route->target.distance = htonl (new_distance); |
752 | } | 758 | } |
753 | 759 | ||
754 | 760 | ||
@@ -816,6 +822,245 @@ handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
816 | 822 | ||
817 | 823 | ||
818 | /** | 824 | /** |
825 | * Called for each 'target' in a neighbor table to free the associated memory. | ||
826 | * | ||
827 | * @param cls NULL | ||
828 | * @param key key of the value | ||
829 | * @param value value to free | ||
830 | * @return GNUNET_OK to continue to iterate | ||
831 | */ | ||
832 | static int | ||
833 | free_targets (void *cls, | ||
834 | const struct GNUNET_HashCode *key, | ||
835 | void *value) | ||
836 | { | ||
837 | GNUNET_free (value); | ||
838 | return GNUNET_OK; | ||
839 | } | ||
840 | |||
841 | |||
842 | /** | ||
843 | * Multihashmap iterator for checking if a given route is | ||
844 | * (now) useful to this peer. | ||
845 | * | ||
846 | * @param cls the direct neighbor for the given route | ||
847 | * @param key key value stored under | ||
848 | * @param value a 'struct Target' that may or may not be useful; not that | ||
849 | * the distance in 'target' does not include the first hop yet | ||
850 | * @return GNUNET_YES to continue iteration, GNUNET_NO to stop | ||
851 | */ | ||
852 | static int | ||
853 | check_possible_route (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
854 | { | ||
855 | struct DirectNeighbor *neighbor = cls; | ||
856 | struct Target *target = value; | ||
857 | struct Route *route; | ||
858 | |||
859 | route = GNUNET_CONTAINER_multihashmap_get (all_routes, | ||
860 | key); | ||
861 | if (NULL != route) | ||
862 | { | ||
863 | if (ntohl (route->target.distance) > ntohl (target->distance) + 1) | ||
864 | { | ||
865 | /* this 'target' is cheaper than the existing route; switch to alternative route! */ | ||
866 | move_route (route, ntohl (target->distance) + 1); | ||
867 | route->next_hop = neighbor; | ||
868 | // FIXME: notify plugin about distance update? | ||
869 | } | ||
870 | return GNUNET_YES; /* got a route to this target already */ | ||
871 | } | ||
872 | route = GNUNET_malloc (sizeof (struct Route)); | ||
873 | route->next_hop = neighbor; | ||
874 | route->target.distance = htonl (ntohl (target->distance) + 1); | ||
875 | route->target.peer = target->peer; | ||
876 | allocate_route (route, ntohl (route->target.distance)); | ||
877 | GNUNET_assert (GNUNET_YES == | ||
878 | GNUNET_CONTAINER_multihashmap_put (all_routes, | ||
879 | &route->target.peer.hashPubKey, | ||
880 | route, | ||
881 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
882 | send_connect_to_plugin (&route->target.peer, ntohl (target->distance)); | ||
883 | return GNUNET_YES; | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Multihashmap iterator for finding routes that were previously | ||
889 | * "hidden" due to a better route (called after a disconnect event). | ||
890 | * | ||
891 | * @param cls NULL | ||
892 | * @param key peer identity of the given direct neighbor | ||
893 | * @param value a 'struct DirectNeighbor' to check for additional routes | ||
894 | * @return GNUNET_YES to continue iteration | ||
895 | */ | ||
896 | static int | ||
897 | refresh_routes (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
898 | { | ||
899 | struct DirectNeighbor *neighbor = value; | ||
900 | |||
901 | if (NULL != neighbor->neighbor_table) | ||
902 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
903 | &check_possible_route, | ||
904 | neighbor); | ||
905 | return GNUNET_YES; | ||
906 | } | ||
907 | |||
908 | |||
909 | /** | ||
910 | * Check if a target was removed from the set of the other peer; if so, | ||
911 | * if we also used it for our route, we need to remove it from our | ||
912 | * 'all_routes' set (and later check if an alternative path now exists). | ||
913 | * | ||
914 | * @param cls the 'struct DirectNeighbor' | ||
915 | * @param key peer identity for the target | ||
916 | * @param value a 'struct Target' previously reachable via the given neighbor | ||
917 | */ | ||
918 | static int | ||
919 | check_target_removed (void *cls, | ||
920 | const struct GNUNET_HashCode *key, | ||
921 | void *value) | ||
922 | { | ||
923 | struct DirectNeighbor *neighbor = cls; | ||
924 | struct Target *new_target; | ||
925 | struct Route *current_route; | ||
926 | |||
927 | new_target = GNUNET_CONTAINER_multihashmap_get (neighbor->neighbor_table_consensus, | ||
928 | key); | ||
929 | if (NULL == new_target) | ||
930 | { | ||
931 | /* target was revoked, check if it was used */ | ||
932 | current_route = GNUNET_CONTAINER_multihashmap_get (all_routes, | ||
933 | key); | ||
934 | if ( (NULL == current_route) || | ||
935 | (current_route->next_hop != neighbor) ) | ||
936 | { | ||
937 | /* didn't matter, wasn't used */ | ||
938 | return GNUNET_OK; | ||
939 | } | ||
940 | /* remove existing route */ | ||
941 | GNUNET_assert (GNUNET_YES == | ||
942 | GNUNET_CONTAINER_multihashmap_remove (all_routes, key, current_route)); | ||
943 | send_disconnect_to_plugin (¤t_route->target.peer); | ||
944 | GNUNET_free (current_route); | ||
945 | neighbor->target_removed = GNUNET_YES; | ||
946 | return GNUNET_OK; | ||
947 | } | ||
948 | return GNUNET_OK; | ||
949 | } | ||
950 | |||
951 | |||
952 | /** | ||
953 | * Check if a target was added to the set of the other peer; if it | ||
954 | * was added or impoves the existing route, do the needed updates. | ||
955 | * | ||
956 | * @param cls the 'struct DirectNeighbor' | ||
957 | * @param key peer identity for the target | ||
958 | * @param value a 'struct Target' now reachable via the given neighbor | ||
959 | */ | ||
960 | static int | ||
961 | check_target_added (void *cls, | ||
962 | const struct GNUNET_HashCode *key, | ||
963 | void *value) | ||
964 | { | ||
965 | struct DirectNeighbor *neighbor = cls; | ||
966 | struct Target *target = value; | ||
967 | struct Route *current_route; | ||
968 | |||
969 | /* target was revoked, check if it was used */ | ||
970 | current_route = GNUNET_CONTAINER_multihashmap_get (all_routes, | ||
971 | key); | ||
972 | if (NULL != current_route) | ||
973 | { | ||
974 | /* route exists */ | ||
975 | if (current_route->next_hop == neighbor) | ||
976 | { | ||
977 | /* we had the same route before, no change */ | ||
978 | if (ntohl (target->distance) != ntohl (current_route->target.distance)) | ||
979 | { | ||
980 | current_route->target.distance = target->distance; | ||
981 | // FIXME: notify about distance change... | ||
982 | } | ||
983 | return GNUNET_OK; | ||
984 | } | ||
985 | if (ntohl (current_route->target.distance) >= ntohl (target->distance)) | ||
986 | { | ||
987 | /* alternative, shorter route exists, ignore */ | ||
988 | return GNUNET_OK; | ||
989 | } | ||
990 | /* new route is better than the existing one, take over! */ | ||
991 | /* NOTE: minor security issue: malicious peers may advertise | ||
992 | very short routes to take over longer paths; as we don't | ||
993 | check that the shorter routes actually work, a malicious | ||
994 | direct neighbor can use this to DoS our long routes */ | ||
995 | current_route->next_hop = neighbor; | ||
996 | current_route->target.distance = target->distance; | ||
997 | // FIXME: notify about distance change | ||
998 | return GNUNET_OK; | ||
999 | } | ||
1000 | /* new route */ | ||
1001 | current_route = GNUNET_malloc (sizeof (struct Route)); | ||
1002 | current_route->next_hop = neighbor; | ||
1003 | current_route->target.peer = target->peer; | ||
1004 | current_route->target.distance = htonl (ntohl (target->distance) + 1); | ||
1005 | GNUNET_assert (GNUNET_YES == | ||
1006 | GNUNET_CONTAINER_multihashmap_put (all_routes, | ||
1007 | ¤t_route->target.peer.hashPubKey, | ||
1008 | current_route, | ||
1009 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1010 | send_connect_to_plugin (¤t_route->target.peer, | ||
1011 | ntohl (current_route->target.distance)); | ||
1012 | return GNUNET_OK; | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | |||
1017 | /** | ||
1018 | * The consensus has concluded, clean up and schedule the next one. | ||
1019 | * | ||
1020 | * @param cls the 'struct GNUNET_DirectNeighbor' with which we created the consensus | ||
1021 | * @param group FIXME | ||
1022 | */ | ||
1023 | static void | ||
1024 | consensus_done_cb (void *cls, | ||
1025 | const struct GNUNET_CONSENSUS_Group *group) | ||
1026 | { | ||
1027 | struct DirectNeighbor *neighbor = cls; | ||
1028 | |||
1029 | GNUNET_CONSENSUS_destroy (neighbor->consensus); | ||
1030 | neighbor->consensus = NULL; | ||
1031 | /* remove targets that disappeared */ | ||
1032 | neighbor->target_removed = GNUNET_NO; | ||
1033 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
1034 | &check_target_removed, | ||
1035 | neighbor); | ||
1036 | if (GNUNET_YES == neighbor->target_removed) | ||
1037 | { | ||
1038 | /* check if we got an alternative for the removed routes */ | ||
1039 | GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, | ||
1040 | &refresh_routes, | ||
1041 | NULL); | ||
1042 | } | ||
1043 | /* add targets that appeared (and check for improved routes) */ | ||
1044 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, | ||
1045 | &check_target_added, | ||
1046 | neighbor); | ||
1047 | if (NULL != neighbor->neighbor_table) | ||
1048 | { | ||
1049 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
1050 | &free_targets, | ||
1051 | NULL); | ||
1052 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); | ||
1053 | neighbor->neighbor_table = NULL; | ||
1054 | } | ||
1055 | neighbor->neighbor_table = neighbor->neighbor_table_consensus; | ||
1056 | neighbor->neighbor_table_consensus = NULL; | ||
1057 | neighbor->consensus_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, | ||
1058 | &start_consensus, | ||
1059 | neighbor); | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | /** | ||
819 | * We inserted the last element into the consensus, get ready to | 1064 | * We inserted the last element into the consensus, get ready to |
820 | * insert the next element into the consensus or conclude if | 1065 | * insert the next element into the consensus or conclude if |
821 | * we're done. | 1066 | * we're done. |
@@ -832,7 +1077,35 @@ insert_next_element (void *cls, | |||
832 | struct DirectNeighbor *neighbor = cls; | 1077 | struct DirectNeighbor *neighbor = cls; |
833 | struct GNUNET_CONSENSUS_Element element; | 1078 | struct GNUNET_CONSENSUS_Element element; |
834 | 1079 | ||
835 | // FIXME: initialize element... | 1080 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && |
1081 | (consensi[neighbor->consensus_insertion_distance].array_length == neighbor->consensus_insertion_offset) ) | ||
1082 | { | ||
1083 | neighbor->consensus_insertion_offset = 0; | ||
1084 | neighbor->consensus_insertion_distance++; | ||
1085 | /* skip over NULL entries */ | ||
1086 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
1087 | (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && | ||
1088 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
1089 | neighbor->consensus_insertion_offset++; | ||
1090 | } | ||
1091 | if (DEFAULT_FISHEYE_DEPTH - 1 == neighbor->consensus_insertion_distance) | ||
1092 | { | ||
1093 | /* we're done, conclude! */ | ||
1094 | GNUNET_CONSENSUS_conclude (neighbor->consensus, | ||
1095 | GNUNET_DV_CONSENSUS_FREQUENCY, | ||
1096 | 2 /* both peers */, | ||
1097 | &consensus_done_cb, | ||
1098 | neighbor); | ||
1099 | return; | ||
1100 | } | ||
1101 | element.size = sizeof (struct Target); | ||
1102 | element.data = &consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset++]->target; | ||
1103 | |||
1104 | /* skip over NULL entries */ | ||
1105 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
1106 | (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && | ||
1107 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
1108 | neighbor->consensus_insertion_offset++; | ||
836 | GNUNET_CONSENSUS_insert (neighbor->consensus, | 1109 | GNUNET_CONSENSUS_insert (neighbor->consensus, |
837 | &element, | 1110 | &element, |
838 | &insert_next_element, | 1111 | &insert_next_element, |
@@ -853,8 +1126,27 @@ static int | |||
853 | learn_route_cb (void *cls, | 1126 | learn_route_cb (void *cls, |
854 | const struct GNUNET_CONSENSUS_Element *element) | 1127 | const struct GNUNET_CONSENSUS_Element *element) |
855 | { | 1128 | { |
856 | GNUNET_break (0); // FIXME | 1129 | struct DirectNeighbor *neighbor = cls; |
857 | return GNUNET_SYSERR; | 1130 | struct Target *target; |
1131 | |||
1132 | if (sizeof (struct Target) != element->size) | ||
1133 | { | ||
1134 | GNUNET_break_op (0); | ||
1135 | return GNUNET_SYSERR; | ||
1136 | } | ||
1137 | target = GNUNET_malloc (sizeof (struct Target)); | ||
1138 | memcpy (target, element->data, sizeof (struct Target)); | ||
1139 | if (GNUNET_YES != | ||
1140 | GNUNET_CONTAINER_multihashmap_put (neighbor->neighbor_table_consensus, | ||
1141 | &target->peer.hashPubKey, | ||
1142 | target, | ||
1143 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1144 | { | ||
1145 | GNUNET_break_op (0); | ||
1146 | GNUNET_free (target); | ||
1147 | return GNUNET_SYSERR; | ||
1148 | } | ||
1149 | return GNUNET_OK; | ||
858 | } | 1150 | } |
859 | 1151 | ||
860 | 1152 | ||
@@ -871,14 +1163,28 @@ start_consensus (void *cls, | |||
871 | { | 1163 | { |
872 | struct DirectNeighbor *neighbor = cls; | 1164 | struct DirectNeighbor *neighbor = cls; |
873 | struct GNUNET_HashCode session_id; | 1165 | struct GNUNET_HashCode session_id; |
1166 | struct GNUNET_HashCode real_session_id; | ||
874 | 1167 | ||
875 | neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK; | 1168 | neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK; |
1169 | neighbor->consensus_insertion_offset = 0; | ||
1170 | neighbor->consensus_insertion_distance = 0; | ||
1171 | GNUNET_assert (NULL == neighbor->neighbor_table_consensus); | ||
876 | GNUNET_assert (NULL == neighbor->consensus); | 1172 | GNUNET_assert (NULL == neighbor->consensus); |
877 | GNUNET_CRYPTO_hash_xor (&session_id, &my_identity.hashPubKey, &neighbor->peer.hashPubKey); // ARG order? | 1173 | neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES); |
1174 | /* construct session ID seed as XOR of both peer's identities */ | ||
1175 | GNUNET_CRYPTO_hash_xor (&my_identity.hashPubKey, | ||
1176 | &neighbor->peer.hashPubKey, | ||
1177 | &session_id); | ||
1178 | /* make sure session ID is unique across applications by salting it with 'DV' */ | ||
1179 | GNUNET_CRYPTO_hkdf (&real_session_id, sizeof (real_session_id), | ||
1180 | GCRY_MD_SHA512, GCRY_MD_SHA256, | ||
1181 | "DV-SALT", 2, | ||
1182 | &session_id, sizeof (session_id), | ||
1183 | NULL, 0); | ||
878 | neighbor->consensus = GNUNET_CONSENSUS_create (cfg, | 1184 | neighbor->consensus = GNUNET_CONSENSUS_create (cfg, |
879 | 1, | 1185 | 1, |
880 | &neighbor->peer, | 1186 | &neighbor->peer, |
881 | &session_id, | 1187 | &real_session_id, |
882 | &learn_route_cb, | 1188 | &learn_route_cb, |
883 | neighbor); | 1189 | neighbor); |
884 | if (NULL == neighbor->consensus) | 1190 | if (NULL == neighbor->consensus) |
@@ -944,7 +1250,7 @@ handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
944 | } | 1250 | } |
945 | send_data_to_plugin (payload, | 1251 | send_data_to_plugin (payload, |
946 | &rm->sender, | 1252 | &rm->sender, |
947 | route->target.distance); | 1253 | ntohl (route->target.distance)); |
948 | return GNUNET_OK; | 1254 | return GNUNET_OK; |
949 | } | 1255 | } |
950 | route = GNUNET_CONTAINER_multihashmap_get (all_routes, | 1256 | route = GNUNET_CONTAINER_multihashmap_get (all_routes, |
@@ -956,7 +1262,7 @@ handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
956 | 1, GNUNET_NO); | 1262 | 1, GNUNET_NO); |
957 | return GNUNET_OK; | 1263 | return GNUNET_OK; |
958 | } | 1264 | } |
959 | if (route->target.distance > ntohl (rm->distance) + 1) | 1265 | if (ntohl (route->target.distance) > ntohl (rm->distance) + 1) |
960 | { | 1266 | { |
961 | GNUNET_STATISTICS_update (stats, | 1267 | GNUNET_STATISTICS_update (stats, |
962 | "# messages discarded (target too far)", | 1268 | "# messages discarded (target too far)", |
@@ -964,7 +1270,7 @@ handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
964 | return GNUNET_OK; | 1270 | return GNUNET_OK; |
965 | } | 1271 | } |
966 | forward_payload (route->next_hop, | 1272 | forward_payload (route->next_hop, |
967 | route->target.distance, | 1273 | ntohl (route->target.distance), |
968 | &rm->sender, | 1274 | &rm->sender, |
969 | payload); | 1275 | payload); |
970 | return GNUNET_OK; | 1276 | return GNUNET_OK; |
@@ -1017,7 +1323,7 @@ handle_dv_send_message (void *cls, struct GNUNET_SERVER_Client *client, | |||
1017 | // FIXME: flow control (send ACK only once message has left the queue...) | 1323 | // FIXME: flow control (send ACK only once message has left the queue...) |
1018 | send_ack_to_plugin (&msg->target, htonl (msg->uid)); | 1324 | send_ack_to_plugin (&msg->target, htonl (msg->uid)); |
1019 | forward_payload (route->next_hop, | 1325 | forward_payload (route->next_hop, |
1020 | route->target.distance, | 1326 | ntohl (route->target.distance), |
1021 | &my_identity, | 1327 | &my_identity, |
1022 | payload); | 1328 | payload); |
1023 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1329 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
@@ -1052,73 +1358,6 @@ cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value) | |||
1052 | 1358 | ||
1053 | 1359 | ||
1054 | /** | 1360 | /** |
1055 | * Multihashmap iterator for checking if a given route is | ||
1056 | * (now) useful to this peer. | ||
1057 | * | ||
1058 | * @param cls the direct neighbor for the given route | ||
1059 | * @param key key value stored under | ||
1060 | * @param value a 'struct Target' that may or may not be useful; not that | ||
1061 | * the distance in 'target' does not include the first hop yet | ||
1062 | * @return GNUNET_YES to continue iteration, GNUNET_NO to stop | ||
1063 | */ | ||
1064 | static int | ||
1065 | check_possible_route (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
1066 | { | ||
1067 | struct DirectNeighbor *neighbor = cls; | ||
1068 | struct Target *target = value; | ||
1069 | struct Route *route; | ||
1070 | |||
1071 | route = GNUNET_CONTAINER_multihashmap_get (all_routes, | ||
1072 | key); | ||
1073 | if (NULL != route) | ||
1074 | { | ||
1075 | if (route->target.distance > target->distance + 1) | ||
1076 | { | ||
1077 | /* this 'target' is cheaper than the existing route; switch to alternative route! */ | ||
1078 | move_route (route, target->distance + 1); | ||
1079 | route->next_hop = neighbor; | ||
1080 | // FIXME: notify plugin about distance update? | ||
1081 | } | ||
1082 | return GNUNET_YES; /* got a route to this target already */ | ||
1083 | } | ||
1084 | route = GNUNET_malloc (sizeof (struct Route)); | ||
1085 | route->next_hop = neighbor; | ||
1086 | route->target.distance = target->distance + 1; | ||
1087 | route->target.peer = target->peer; | ||
1088 | allocate_route (route, route->target.distance); | ||
1089 | GNUNET_assert (GNUNET_YES == | ||
1090 | GNUNET_CONTAINER_multihashmap_put (all_routes, | ||
1091 | &route->target.peer.hashPubKey, | ||
1092 | route, | ||
1093 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1094 | send_connect_to_plugin (&route->target.peer, target->distance); | ||
1095 | return GNUNET_YES; | ||
1096 | } | ||
1097 | |||
1098 | |||
1099 | /** | ||
1100 | * Multihashmap iterator for finding routes that were previously | ||
1101 | * "hidden" due to a better route (called after a disconnect event). | ||
1102 | * | ||
1103 | * @param cls NULL | ||
1104 | * @param key peer identity of the given direct neighbor | ||
1105 | * @param value a 'struct DirectNeighbor' to check for additional routes | ||
1106 | * @return GNUNET_YES to continue iteration | ||
1107 | */ | ||
1108 | static int | ||
1109 | refresh_routes (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
1110 | { | ||
1111 | struct DirectNeighbor *neighbor = value; | ||
1112 | |||
1113 | if (NULL != neighbor->neighbor_table) | ||
1114 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
1115 | &check_possible_route, | ||
1116 | neighbor); | ||
1117 | return GNUNET_YES; | ||
1118 | } | ||
1119 | |||
1120 | |||
1121 | /** | ||
1122 | * Cleanup all of the data structures associated with a given neighbor. | 1361 | * Cleanup all of the data structures associated with a given neighbor. |
1123 | * | 1362 | * |
1124 | * @param neighbor neighbor to clean up | 1363 | * @param neighbor neighbor to clean up |
@@ -1144,6 +1383,22 @@ cleanup_neighbor (struct DirectNeighbor *neighbor) | |||
1144 | GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth); | 1383 | GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth); |
1145 | neighbor->cth = NULL; | 1384 | neighbor->cth = NULL; |
1146 | } | 1385 | } |
1386 | if (NULL != neighbor->neighbor_table_consensus) | ||
1387 | { | ||
1388 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, | ||
1389 | &free_targets, | ||
1390 | NULL); | ||
1391 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table_consensus); | ||
1392 | neighbor->neighbor_table_consensus = NULL; | ||
1393 | } | ||
1394 | if (NULL != neighbor->neighbor_table) | ||
1395 | { | ||
1396 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
1397 | &free_targets, | ||
1398 | NULL); | ||
1399 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); | ||
1400 | neighbor->neighbor_table = NULL; | ||
1401 | } | ||
1147 | if (GNUNET_SCHEDULER_NO_TASK != neighbor->consensus_task) | 1402 | if (GNUNET_SCHEDULER_NO_TASK != neighbor->consensus_task) |
1148 | { | 1403 | { |
1149 | GNUNET_SCHEDULER_cancel (neighbor->consensus_task); | 1404 | GNUNET_SCHEDULER_cancel (neighbor->consensus_task); |