aboutsummaryrefslogtreecommitdiff
path: root/src/dv
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-03-14 15:39:29 +0000
committerChristian Grothoff <christian@grothoff.org>2013-03-14 15:39:29 +0000
commit4bb84af9b3fe9a6808025a9c7040f3b772ebb7a8 (patch)
treebd6cdc0b03cfbe3b835f2509cd9961b916d78c0b /src/dv
parentc03a9267dd1f710c1f75550308beb5eda59171b5 (diff)
downloadgnunet-4bb84af9b3fe9a6808025a9c7040f3b772ebb7a8.tar.gz
gnunet-4bb84af9b3fe9a6808025a9c7040f3b772ebb7a8.zip
-more DV hacking
Diffstat (limited to 'src/dv')
-rw-r--r--src/dv/gnunet-service-dv.c421
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,
727static void 733static void
728release_route (struct Route *route) 734release_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 */
832static int
833free_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 */
852static int
853check_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 */
896static int
897refresh_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 */
918static int
919check_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 (&current_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 */
960static int
961check_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 &current_route->target.peer.hashPubKey,
1008 current_route,
1009 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1010 send_connect_to_plugin (&current_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 */
1023static void
1024consensus_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
853learn_route_cb (void *cls, 1126learn_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 */
1064static int
1065check_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 */
1108static int
1109refresh_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);