aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-05-29 08:18:28 +0000
committerChristian Grothoff <christian@grothoff.org>2013-05-29 08:18:28 +0000
commitf06d0beb1ea96498ddec2a42354ddfdabef54b6f (patch)
tree1b902cc0e06f57b0a5c788bab9610307914eece0
parent9e09bc6eab5ce05e07c7b1501ac5f2cace54acae (diff)
downloadgnunet-f06d0beb1ea96498ddec2a42354ddfdabef54b6f.tar.gz
gnunet-f06d0beb1ea96498ddec2a42354ddfdabef54b6f.zip
-towards using SET api in DV
-rw-r--r--src/dv/Makefile.am2
-rw-r--r--src/dv/gnunet-service-dv.c455
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
43gnunet_service_dv_LDADD = \ 43gnunet_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 */
360static void 379static void
361start_consensus (void *cls, 380initiate_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 */
400static void
401listen_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 */
752static void
753build_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
710handle_direct_connect (struct DirectNeighbor *neighbor) 801handle_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 */
1150static void
1151consensus_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 */
1202static void
1203insert_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 */
1251static void 1274static void
1252learn_route_cb (void *cls, 1275handle_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 */
1304static void 1383static void
1305start_consensus (void *cls, 1384listen_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 */
1422static void
1423initiate_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