diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-05-29 08:18:28 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-05-29 08:18:28 +0000 |
commit | f06d0beb1ea96498ddec2a42354ddfdabef54b6f (patch) | |
tree | 1b902cc0e06f57b0a5c788bab9610307914eece0 | |
parent | 9e09bc6eab5ce05e07c7b1501ac5f2cace54acae (diff) | |
download | gnunet-f06d0beb1ea96498ddec2a42354ddfdabef54b6f.tar.gz gnunet-f06d0beb1ea96498ddec2a42354ddfdabef54b6f.zip |
-towards using SET api in DV
-rw-r--r-- | src/dv/Makefile.am | 2 | ||||
-rw-r--r-- | src/dv/gnunet-service-dv.c | 455 |
2 files changed, 275 insertions, 182 deletions
diff --git a/src/dv/Makefile.am b/src/dv/Makefile.am index fecff08a7..1b90c2cc8 100644 --- a/src/dv/Makefile.am +++ b/src/dv/Makefile.am | |||
@@ -42,7 +42,7 @@ gnunet_service_dv_SOURCES = \ | |||
42 | gnunet-service-dv.c dv.h | 42 | gnunet-service-dv.c dv.h |
43 | gnunet_service_dv_LDADD = \ | 43 | gnunet_service_dv_LDADD = \ |
44 | $(top_builddir)/src/ats/libgnunetats.la \ | 44 | $(top_builddir)/src/ats/libgnunetats.la \ |
45 | $(top_builddir)/src/consensus/libgnunetconsensus.la \ | 45 | $(top_builddir)/src/set/libgnunetset.la \ |
46 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 46 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
47 | $(top_builddir)/src/core/libgnunetcore.la \ | 47 | $(top_builddir)/src/core/libgnunetcore.la \ |
48 | $(top_builddir)/src/util/libgnunetutil.la \ | 48 | $(top_builddir)/src/util/libgnunetutil.la \ |
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c index 6dc37f7d9..3b0f0783a 100644 --- a/src/dv/gnunet-service-dv.c +++ b/src/dv/gnunet-service-dv.c | |||
@@ -34,7 +34,7 @@ | |||
34 | #include "gnunet_hello_lib.h" | 34 | #include "gnunet_hello_lib.h" |
35 | #include "gnunet_peerinfo_service.h" | 35 | #include "gnunet_peerinfo_service.h" |
36 | #include "gnunet_statistics_service.h" | 36 | #include "gnunet_statistics_service.h" |
37 | #include "gnunet_consensus_service.h" | 37 | #include "gnunet_set_service.h" |
38 | #include "gnunet_ats_service.h" | 38 | #include "gnunet_ats_service.h" |
39 | #include "dv.h" | 39 | #include "dv.h" |
40 | #include <gcrypt.h> | 40 | #include <gcrypt.h> |
@@ -168,6 +168,14 @@ struct DirectNeighbor | |||
168 | * Identity of the peer. | 168 | * Identity of the peer. |
169 | */ | 169 | */ |
170 | struct GNUNET_PeerIdentity peer; | 170 | struct GNUNET_PeerIdentity peer; |
171 | |||
172 | /** | ||
173 | * Session ID we use whenever we create a set union with | ||
174 | * this neighbor; constructed from the XOR of our peer | ||
175 | * IDs and then salted with "DV-SALT" to avoid conflicts | ||
176 | * with other applications. | ||
177 | */ | ||
178 | struct GNUNET_HashCode real_session_id; | ||
171 | 179 | ||
172 | /** | 180 | /** |
173 | * Head of linked list of messages to send to this peer. | 181 | * Head of linked list of messages to send to this peer. |
@@ -202,16 +210,27 @@ struct DirectNeighbor | |||
202 | struct GNUNET_CONTAINER_MultiHashMap *neighbor_table_consensus; | 210 | struct GNUNET_CONTAINER_MultiHashMap *neighbor_table_consensus; |
203 | 211 | ||
204 | /** | 212 | /** |
205 | * Active consensus, if we are currently synchronizing the | 213 | * Our current (exposed) routing table as a set. |
206 | * routing tables. | 214 | */ |
215 | struct GNUNET_SET_Handle *my_set; | ||
216 | |||
217 | /** | ||
218 | * Handle for our current active set union operation. | ||
219 | */ | ||
220 | struct GNUNET_SET_OperationHandle *set_op; | ||
221 | |||
222 | /** | ||
223 | * Handle used if we are listening for this peer, waiting for the | ||
224 | * other peer to initiate construction of the set union. NULL if | ||
225 | * we ar the initiating peer. | ||
207 | */ | 226 | */ |
208 | struct GNUNET_CONSENSUS_Handle *consensus; | 227 | struct GNUNET_SET_ListenHandle *listen_handle; |
209 | 228 | ||
210 | /** | 229 | /** |
211 | * ID of the task we use to (periodically) update our consensus | 230 | * ID of the task we use to (periodically) update our consensus |
212 | * with this peer. | 231 | * with this peer. Used if we are the initiating peer. |
213 | */ | 232 | */ |
214 | GNUNET_SCHEDULER_TaskIdentifier consensus_task; | 233 | GNUNET_SCHEDULER_TaskIdentifier initiate_task; |
215 | 234 | ||
216 | /** | 235 | /** |
217 | * At what offset are we, with respect to inserting our own routes | 236 | * At what offset are we, with respect to inserting our own routes |
@@ -351,15 +370,38 @@ static struct GNUNET_ATS_PerformanceHandle *ats; | |||
351 | 370 | ||
352 | 371 | ||
353 | /** | 372 | /** |
354 | * Start creating a new consensus from scratch. | 373 | * Start creating a new DV set union by initiating the connection. |
355 | * | 374 | * |
356 | * @param cls the 'struct DirectNeighbor' of the peer we're building | 375 | * @param cls the 'struct DirectNeighbor' of the peer we're building |
357 | * a routing consensus with | 376 | * a routing consensus with |
358 | * @param tc scheduler context | 377 | * @param tc scheduler context |
359 | */ | 378 | */ |
360 | static void | 379 | static void |
361 | start_consensus (void *cls, | 380 | initiate_set_union (void *cls, |
362 | const struct GNUNET_SCHEDULER_TaskContext *tc); | 381 | const struct GNUNET_SCHEDULER_TaskContext *tc); |
382 | |||
383 | |||
384 | /** | ||
385 | * Start creating a new DV set union construction, our neighbour has | ||
386 | * asked for it (callback for listening peer). | ||
387 | * | ||
388 | * @param cls the 'struct DirectNeighbor' of the peer we're building | ||
389 | * a routing consensus with | ||
390 | * @param other_peer the other peer | ||
391 | * @param context_msg message with application specific information from | ||
392 | * the other peer | ||
393 | * @param request request from the other peer, use GNUNET_SET_accept | ||
394 | * to accept it, otherwise the request will be refused | ||
395 | * Note that we don't use a return value here, as it is also | ||
396 | * necessary to specify the set we want to do the operation with, | ||
397 | * whith sometimes can be derived from the context message. | ||
398 | * Also necessary to specify the timeout. | ||
399 | */ | ||
400 | static void | ||
401 | listen_set_union (void *cls, | ||
402 | const struct GNUNET_PeerIdentity *other_peer, | ||
403 | const struct GNUNET_MessageHeader *context_msg, | ||
404 | struct GNUNET_SET_Request *request); | ||
363 | 405 | ||
364 | 406 | ||
365 | /** | 407 | /** |
@@ -702,6 +744,55 @@ move_route (struct Route *route, | |||
702 | 744 | ||
703 | 745 | ||
704 | /** | 746 | /** |
747 | * Initialize this neighbors 'my_set' and when done give | ||
748 | * it to the pending set operation for execution. | ||
749 | * | ||
750 | * @param cls the neighbor for which we are building the set | ||
751 | */ | ||
752 | static void | ||
753 | build_set (void *cls) | ||
754 | { | ||
755 | struct DirectNeighbor *neighbor = cls; | ||
756 | struct GNUNET_SET_Element element; | ||
757 | |||
758 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
759 | (consensi[neighbor->consensus_insertion_distance].array_length == neighbor->consensus_insertion_offset) ) | ||
760 | { | ||
761 | neighbor->consensus_insertion_offset = 0; | ||
762 | neighbor->consensus_insertion_distance++; | ||
763 | /* skip over NULL entries */ | ||
764 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
765 | (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && | ||
766 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
767 | neighbor->consensus_insertion_offset++; | ||
768 | } | ||
769 | if (DEFAULT_FISHEYE_DEPTH - 1 == neighbor->consensus_insertion_distance) | ||
770 | { | ||
771 | /* we have added all elements to the set, run the operation */ | ||
772 | #if 0 | ||
773 | GNUNET_SET_operation_conclude (neighbor->my_op, | ||
774 | neighbor->my_set); | ||
775 | #endif | ||
776 | GNUNET_SET_destroy (neighbor->my_set); | ||
777 | neighbor->my_set = NULL; | ||
778 | return; | ||
779 | } | ||
780 | element.size = sizeof (struct Target); | ||
781 | element.data = &consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset++]->target; | ||
782 | |||
783 | /* skip over NULL entries */ | ||
784 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
785 | (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && | ||
786 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
787 | neighbor->consensus_insertion_offset++; | ||
788 | GNUNET_SET_add_element (neighbor->my_set, | ||
789 | &element, | ||
790 | &build_set, neighbor); | ||
791 | |||
792 | } | ||
793 | |||
794 | |||
795 | /** | ||
705 | * A peer is now connected to us at distance 1. Initiate DV exchange. | 796 | * A peer is now connected to us at distance 1. Initiate DV exchange. |
706 | * | 797 | * |
707 | * @param neighbor entry for the neighbor at distance 1 | 798 | * @param neighbor entry for the neighbor at distance 1 |
@@ -710,6 +801,7 @@ static void | |||
710 | handle_direct_connect (struct DirectNeighbor *neighbor) | 801 | handle_direct_connect (struct DirectNeighbor *neighbor) |
711 | { | 802 | { |
712 | struct Route *route; | 803 | struct Route *route; |
804 | struct GNUNET_HashCode session_id; | ||
713 | 805 | ||
714 | GNUNET_STATISTICS_update (stats, | 806 | GNUNET_STATISTICS_update (stats, |
715 | "# peers connected (1-hop)", | 807 | "# peers connected (1-hop)", |
@@ -722,8 +814,26 @@ handle_direct_connect (struct DirectNeighbor *neighbor) | |||
722 | release_route (route); | 814 | release_route (route); |
723 | GNUNET_free (route); | 815 | GNUNET_free (route); |
724 | } | 816 | } |
725 | neighbor->consensus_task = GNUNET_SCHEDULER_add_now (&start_consensus, | 817 | /* construct session ID seed as XOR of both peer's identities */ |
726 | neighbor); | 818 | GNUNET_CRYPTO_hash_xor (&my_identity.hashPubKey, |
819 | &neighbor->peer.hashPubKey, | ||
820 | &session_id); | ||
821 | /* make sure session ID is unique across applications by salting it with 'DV' */ | ||
822 | GNUNET_CRYPTO_hkdf (&neighbor->real_session_id, sizeof (struct GNUNET_HashCode), | ||
823 | GCRY_MD_SHA512, GCRY_MD_SHA256, | ||
824 | "DV-SALT", 2, | ||
825 | &session_id, sizeof (session_id), | ||
826 | NULL, 0); | ||
827 | if (1 == GNUNET_CRYPTO_hash_cmp (&neighbor->peer.hashPubKey, | ||
828 | &my_identity.hashPubKey)) | ||
829 | neighbor->initiate_task = GNUNET_SCHEDULER_add_now (&initiate_set_union, | ||
830 | neighbor); | ||
831 | else | ||
832 | neighbor->listen_handle = GNUNET_SET_listen (cfg, | ||
833 | GNUNET_SET_OPERATION_UNION, | ||
834 | &neighbor->real_session_id, | ||
835 | &listen_set_union, | ||
836 | neighbor); | ||
727 | } | 837 | } |
728 | 838 | ||
729 | 839 | ||
@@ -943,15 +1053,25 @@ handle_direct_disconnect (struct DirectNeighbor *neighbor) | |||
943 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); | 1053 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); |
944 | neighbor->neighbor_table = NULL; | 1054 | neighbor->neighbor_table = NULL; |
945 | } | 1055 | } |
946 | if (GNUNET_SCHEDULER_NO_TASK != neighbor->consensus_task) | 1056 | if (NULL != neighbor->set_op) |
947 | { | 1057 | { |
948 | GNUNET_SCHEDULER_cancel (neighbor->consensus_task); | 1058 | GNUNET_SET_operation_cancel (neighbor->set_op); |
949 | neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK; | 1059 | neighbor->set_op = NULL; |
950 | } | 1060 | } |
951 | if (NULL != neighbor->consensus) | 1061 | if (NULL != neighbor->my_set) |
952 | { | 1062 | { |
953 | GNUNET_CONSENSUS_destroy (neighbor->consensus); | 1063 | GNUNET_SET_destroy (neighbor->my_set); |
954 | neighbor->consensus = NULL; | 1064 | neighbor->my_set = NULL; |
1065 | } | ||
1066 | if (NULL != neighbor->listen_handle) | ||
1067 | { | ||
1068 | GNUNET_SET_listen_cancel (neighbor->listen_handle); | ||
1069 | neighbor->listen_handle = NULL; | ||
1070 | } | ||
1071 | if (GNUNET_SCHEDULER_NO_TASK != neighbor->initiate_task) | ||
1072 | { | ||
1073 | GNUNET_SCHEDULER_cancel (neighbor->initiate_task); | ||
1074 | neighbor->initiate_task = GNUNET_SCHEDULER_NO_TASK; | ||
955 | } | 1075 | } |
956 | } | 1076 | } |
957 | 1077 | ||
@@ -1141,125 +1261,50 @@ check_target_added (void *cls, | |||
1141 | } | 1261 | } |
1142 | 1262 | ||
1143 | 1263 | ||
1144 | |||
1145 | /** | ||
1146 | * The consensus has concluded, clean up and schedule the next one. | ||
1147 | * | ||
1148 | * @param cls the 'struct GNUNET_DirectNeighbor' with which we created the consensus | ||
1149 | */ | ||
1150 | static void | ||
1151 | consensus_done_cb (void *cls) | ||
1152 | { | ||
1153 | struct DirectNeighbor *neighbor = cls; | ||
1154 | |||
1155 | GNUNET_CONSENSUS_destroy (neighbor->consensus); | ||
1156 | neighbor->consensus = NULL; | ||
1157 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1158 | "Finished consensus with %s!\n", | ||
1159 | GNUNET_i2s (&neighbor->peer)); | ||
1160 | /* remove targets that disappeared */ | ||
1161 | neighbor->target_removed = GNUNET_NO; | ||
1162 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
1163 | &check_target_removed, | ||
1164 | neighbor); | ||
1165 | if (GNUNET_YES == neighbor->target_removed) | ||
1166 | { | ||
1167 | /* check if we got an alternative for the removed routes */ | ||
1168 | GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, | ||
1169 | &refresh_routes, | ||
1170 | NULL); | ||
1171 | } | ||
1172 | /* add targets that appeared (and check for improved routes) */ | ||
1173 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, | ||
1174 | &check_target_added, | ||
1175 | neighbor); | ||
1176 | if (NULL != neighbor->neighbor_table) | ||
1177 | { | ||
1178 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
1179 | &free_targets, | ||
1180 | NULL); | ||
1181 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); | ||
1182 | neighbor->neighbor_table = NULL; | ||
1183 | } | ||
1184 | neighbor->neighbor_table = neighbor->neighbor_table_consensus; | ||
1185 | neighbor->neighbor_table_consensus = NULL; | ||
1186 | neighbor->consensus_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, | ||
1187 | &start_consensus, | ||
1188 | neighbor); | ||
1189 | } | ||
1190 | |||
1191 | |||
1192 | /** | ||
1193 | * We inserted the last element into the consensus, get ready to | ||
1194 | * insert the next element into the consensus or conclude if | ||
1195 | * we're done. | ||
1196 | * | ||
1197 | * @param cls the 'struct DirectNeighbor' of the peer we're building | ||
1198 | * a routing consensus with | ||
1199 | * @param success GNUNET_OK if the last element was added successfully, | ||
1200 | * GNUNET_SYSERR if we failed | ||
1201 | */ | ||
1202 | static void | ||
1203 | insert_next_element (void *cls, | ||
1204 | int success) | ||
1205 | { | ||
1206 | struct DirectNeighbor *neighbor = cls; | ||
1207 | struct GNUNET_CONSENSUS_Element element; | ||
1208 | |||
1209 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
1210 | (consensi[neighbor->consensus_insertion_distance].array_length == neighbor->consensus_insertion_offset) ) | ||
1211 | { | ||
1212 | neighbor->consensus_insertion_offset = 0; | ||
1213 | neighbor->consensus_insertion_distance++; | ||
1214 | /* skip over NULL entries */ | ||
1215 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
1216 | (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && | ||
1217 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
1218 | neighbor->consensus_insertion_offset++; | ||
1219 | } | ||
1220 | if (DEFAULT_FISHEYE_DEPTH - 1 == neighbor->consensus_insertion_distance) | ||
1221 | { | ||
1222 | /* we're done, conclude! */ | ||
1223 | GNUNET_CONSENSUS_conclude (neighbor->consensus, | ||
1224 | GNUNET_DV_CONSENSUS_FREQUENCY, | ||
1225 | &consensus_done_cb, | ||
1226 | neighbor); | ||
1227 | return; | ||
1228 | } | ||
1229 | element.size = sizeof (struct Target); | ||
1230 | element.data = &consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset++]->target; | ||
1231 | |||
1232 | /* skip over NULL entries */ | ||
1233 | while ( (DEFAULT_FISHEYE_DEPTH - 1 > neighbor->consensus_insertion_distance) && | ||
1234 | (consensi[neighbor->consensus_insertion_distance].array_length < neighbor->consensus_insertion_offset) && | ||
1235 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
1236 | neighbor->consensus_insertion_offset++; | ||
1237 | GNUNET_CONSENSUS_insert (neighbor->consensus, | ||
1238 | &element, | ||
1239 | &insert_next_element, | ||
1240 | neighbor); | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | /** | 1264 | /** |
1265 | * Callback for set operation results. Called for each element | ||
1266 | * in the result set. | ||
1245 | * We have learned a new route from the other peer. Add it to the | 1267 | * We have learned a new route from the other peer. Add it to the |
1246 | * route set we're building. | 1268 | * route set we're building. |
1247 | * | 1269 | * |
1248 | * @param cls the 'struct DirectNeighbor' we're building the consensus with | 1270 | * @param cls the 'struct DirectNeighbor' we're building the consensus with |
1249 | * @param element the new element we have learned | 1271 | * @param element a result element, only valid if status is GNUNET_SET_STATUS_OK |
1272 | * @param status see enum GNUNET_SET_Status | ||
1250 | */ | 1273 | */ |
1251 | static void | 1274 | static void |
1252 | learn_route_cb (void *cls, | 1275 | handle_set_union_result (void *cls, |
1253 | const struct GNUNET_CONSENSUS_Element *element) | 1276 | const struct GNUNET_SET_Element *element, |
1277 | enum GNUNET_SET_Status status) | ||
1254 | { | 1278 | { |
1255 | struct DirectNeighbor *neighbor = cls; | 1279 | struct DirectNeighbor *neighbor = cls; |
1256 | struct Target *target; | 1280 | struct Target *target; |
1257 | 1281 | ||
1258 | if (NULL == element) | 1282 | switch (status) |
1259 | { | 1283 | { |
1260 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1284 | case GNUNET_SET_STATUS_OK: |
1261 | "Failed to establish DV consensus, will try again later\n"); | 1285 | if (sizeof (struct Target) != element->size) |
1262 | GNUNET_CONSENSUS_destroy (neighbor->consensus); | 1286 | { |
1287 | GNUNET_break_op (0); | ||
1288 | return; | ||
1289 | } | ||
1290 | target = GNUNET_malloc (sizeof (struct Target)); | ||
1291 | memcpy (target, element->data, sizeof (struct Target)); | ||
1292 | if (GNUNET_YES != | ||
1293 | GNUNET_CONTAINER_multihashmap_put (neighbor->neighbor_table_consensus, | ||
1294 | &target->peer.hashPubKey, | ||
1295 | target, | ||
1296 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1297 | { | ||
1298 | GNUNET_break_op (0); | ||
1299 | GNUNET_free (target); | ||
1300 | } | ||
1301 | break; | ||
1302 | case GNUNET_SET_STATUS_TIMEOUT: | ||
1303 | case GNUNET_SET_STATUS_FAILURE: | ||
1304 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1305 | "Failed to establish DV union, will try again later\n"); | ||
1306 | GNUNET_SET_operation_cancel (neighbor->set_op); /* FIXME: needed? */ | ||
1307 | neighbor->set_op = NULL; | ||
1263 | if (NULL != neighbor->neighbor_table_consensus) | 1308 | if (NULL != neighbor->neighbor_table_consensus) |
1264 | { | 1309 | { |
1265 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, | 1310 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, |
@@ -1268,82 +1313,130 @@ learn_route_cb (void *cls, | |||
1268 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table_consensus); | 1313 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table_consensus); |
1269 | neighbor->neighbor_table_consensus = NULL; | 1314 | neighbor->neighbor_table_consensus = NULL; |
1270 | } | 1315 | } |
1271 | neighbor->consensus = NULL; | 1316 | if (1 == GNUNET_CRYPTO_hash_cmp (&neighbor->peer.hashPubKey, |
1272 | neighbor->consensus_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, | 1317 | &my_identity.hashPubKey)) |
1273 | &start_consensus, | 1318 | neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, |
1274 | neighbor); | 1319 | &initiate_set_union, |
1275 | return; | 1320 | neighbor); |
1276 | } | 1321 | break; |
1277 | if (sizeof (struct Target) != element->size) | 1322 | case GNUNET_SET_STATUS_HALF_DONE: |
1278 | { | 1323 | /* we got all of our updates; integrate routing table! */ |
1279 | GNUNET_break_op (0); | 1324 | neighbor->target_removed = GNUNET_NO; |
1280 | return; | 1325 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, |
1281 | } | 1326 | &check_target_removed, |
1282 | target = GNUNET_malloc (sizeof (struct Target)); | 1327 | neighbor); |
1283 | memcpy (target, element->data, sizeof (struct Target)); | 1328 | if (GNUNET_YES == neighbor->target_removed) |
1284 | if (GNUNET_YES != | 1329 | { |
1285 | GNUNET_CONTAINER_multihashmap_put (neighbor->neighbor_table_consensus, | 1330 | /* check if we got an alternative for the removed routes */ |
1286 | &target->peer.hashPubKey, | 1331 | GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, |
1287 | target, | 1332 | &refresh_routes, |
1288 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | 1333 | NULL); |
1289 | { | 1334 | } |
1290 | GNUNET_break_op (0); | 1335 | /* add targets that appeared (and check for improved routes) */ |
1291 | GNUNET_free (target); | 1336 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table_consensus, |
1337 | &check_target_added, | ||
1338 | neighbor); | ||
1339 | if (NULL != neighbor->neighbor_table) | ||
1340 | { | ||
1341 | GNUNET_CONTAINER_multihashmap_iterate (neighbor->neighbor_table, | ||
1342 | &free_targets, | ||
1343 | NULL); | ||
1344 | GNUNET_CONTAINER_multihashmap_destroy (neighbor->neighbor_table); | ||
1345 | neighbor->neighbor_table = NULL; | ||
1346 | } | ||
1347 | neighbor->neighbor_table = neighbor->neighbor_table_consensus; | ||
1348 | neighbor->neighbor_table_consensus = NULL; | ||
1349 | break; | ||
1350 | case GNUNET_SET_STATUS_DONE: | ||
1351 | /* operation done, schedule next run! */ | ||
1352 | GNUNET_SET_operation_cancel (neighbor->set_op); /* FIXME: needed? */ | ||
1353 | neighbor->set_op = NULL; | ||
1354 | if (1 == GNUNET_CRYPTO_hash_cmp (&neighbor->peer.hashPubKey, | ||
1355 | &my_identity.hashPubKey)) | ||
1356 | neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, | ||
1357 | &initiate_set_union, | ||
1358 | neighbor); | ||
1359 | break; | ||
1360 | default: | ||
1361 | GNUNET_break (0); | ||
1292 | return; | 1362 | return; |
1293 | } | 1363 | } |
1294 | } | 1364 | } |
1295 | 1365 | ||
1296 | 1366 | ||
1297 | /** | 1367 | /** |
1298 | * Start creating a new consensus from scratch. | 1368 | * Start creating a new DV set union construction, our neighbour has |
1369 | * asked for it (callback for listening peer). | ||
1299 | * | 1370 | * |
1300 | * @param cls the 'struct DirectNeighbor' of the peer we're building | 1371 | * @param cls the 'struct DirectNeighbor' of the peer we're building |
1301 | * a routing consensus with | 1372 | * a routing consensus with |
1302 | * @param tc scheduler context | 1373 | * @param other_peer the other peer |
1374 | * @param context_msg message with application specific information from | ||
1375 | * the other peer | ||
1376 | * @param request request from the other peer, use GNUNET_SET_accept | ||
1377 | * to accept it, otherwise the request will be refused | ||
1378 | * Note that we don't use a return value here, as it is also | ||
1379 | * necessary to specify the set we want to do the operation with, | ||
1380 | * whith sometimes can be derived from the context message. | ||
1381 | * Also necessary to specify the timeout. | ||
1303 | */ | 1382 | */ |
1304 | static void | 1383 | static void |
1305 | start_consensus (void *cls, | 1384 | listen_set_union (void *cls, |
1306 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 1385 | const struct GNUNET_PeerIdentity *other_peer, |
1386 | const struct GNUNET_MessageHeader *context_msg, | ||
1387 | struct GNUNET_SET_Request *request) | ||
1307 | { | 1388 | { |
1308 | struct DirectNeighbor *neighbor = cls; | 1389 | struct DirectNeighbor *neighbor = cls; |
1309 | struct GNUNET_HashCode session_id; | ||
1310 | struct GNUNET_HashCode real_session_id; | ||
1311 | 1390 | ||
1312 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1391 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1313 | "Starting to create consensus with %s!\n", | 1392 | "Starting to create consensus with %s!\n", |
1314 | GNUNET_i2s (&neighbor->peer)); | 1393 | GNUNET_i2s (&neighbor->peer)); |
1315 | neighbor->consensus_task = GNUNET_SCHEDULER_NO_TASK; | 1394 | if (NULL != neighbor->set_op) |
1316 | neighbor->consensus_insertion_offset = 0; | ||
1317 | neighbor->consensus_insertion_distance = 0; | ||
1318 | GNUNET_assert (NULL == neighbor->neighbor_table_consensus); | ||
1319 | GNUNET_assert (NULL == neighbor->consensus); | ||
1320 | neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES); | ||
1321 | /* construct session ID seed as XOR of both peer's identities */ | ||
1322 | GNUNET_CRYPTO_hash_xor (&my_identity.hashPubKey, | ||
1323 | &neighbor->peer.hashPubKey, | ||
1324 | &session_id); | ||
1325 | /* make sure session ID is unique across applications by salting it with 'DV' */ | ||
1326 | GNUNET_CRYPTO_hkdf (&real_session_id, sizeof (real_session_id), | ||
1327 | GCRY_MD_SHA512, GCRY_MD_SHA256, | ||
1328 | "DV-SALT", 2, | ||
1329 | &session_id, sizeof (session_id), | ||
1330 | NULL, 0); | ||
1331 | neighbor->consensus = GNUNET_CONSENSUS_create (cfg, | ||
1332 | 1, | ||
1333 | &neighbor->peer, | ||
1334 | &real_session_id, | ||
1335 | &learn_route_cb, | ||
1336 | neighbor); | ||
1337 | if (NULL == neighbor->consensus) | ||
1338 | { | 1395 | { |
1339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1396 | GNUNET_SET_operation_cancel (neighbor->set_op); |
1340 | "Failed to setup consensus, will try again later!\n"); | 1397 | neighbor->set_op = NULL; |
1341 | neighbor->consensus_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, | 1398 | } |
1342 | &start_consensus, | 1399 | if (NULL != neighbor->my_set) |
1343 | neighbor); | 1400 | { |
1344 | return; | 1401 | GNUNET_SET_destroy (neighbor->my_set); |
1402 | neighbor->my_set = NULL; | ||
1345 | } | 1403 | } |
1346 | insert_next_element (neighbor, GNUNET_OK); | 1404 | neighbor->my_set = GNUNET_SET_create (cfg, |
1405 | GNUNET_SET_OPERATION_UNION); | ||
1406 | neighbor->set_op = GNUNET_SET_accept (request, | ||
1407 | neighbor->my_set /* FIXME: pass later! */, | ||
1408 | GNUNET_SET_RESULT_ADDED, | ||
1409 | &handle_set_union_result, | ||
1410 | neighbor); | ||
1411 | build_set (neighbor); | ||
1412 | } | ||
1413 | |||
1414 | |||
1415 | /** | ||
1416 | * Start creating a new DV set union by initiating the connection. | ||
1417 | * | ||
1418 | * @param cls the 'struct DirectNeighbor' of the peer we're building | ||
1419 | * a routing consensus with | ||
1420 | * @param tc scheduler context | ||
1421 | */ | ||
1422 | static void | ||
1423 | initiate_set_union (void *cls, | ||
1424 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1425 | { | ||
1426 | struct DirectNeighbor *neighbor = cls; | ||
1427 | |||
1428 | neighbor->initiate_task = GNUNET_SCHEDULER_NO_TASK; | ||
1429 | neighbor->my_set = GNUNET_SET_create (cfg, | ||
1430 | GNUNET_SET_OPERATION_UNION); | ||
1431 | neighbor->set_op = GNUNET_SET_evaluate (neighbor->my_set /* FIXME: pass later! */, | ||
1432 | &neighbor->peer, | ||
1433 | &neighbor->real_session_id, | ||
1434 | NULL, | ||
1435 | 0 /* FIXME: salt */, | ||
1436 | GNUNET_SET_RESULT_ADDED, | ||
1437 | &handle_set_union_result, | ||
1438 | neighbor); | ||
1439 | build_set (neighbor); | ||
1347 | } | 1440 | } |
1348 | 1441 | ||
1349 | 1442 | ||