diff options
Diffstat (limited to 'src/testing/testing_group.c')
-rw-r--r-- | src/testing/testing_group.c | 1195 |
1 files changed, 1110 insertions, 85 deletions
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c index e617bc113..e9bc05a74 100644 --- a/src/testing/testing_group.c +++ b/src/testing/testing_group.c | |||
@@ -50,6 +50,57 @@ | |||
50 | 50 | ||
51 | #define CONNECT_ATTEMPTS 8 | 51 | #define CONNECT_ATTEMPTS 8 |
52 | 52 | ||
53 | /** | ||
54 | * Prototype of a function called whenever two peers would be connected | ||
55 | * in a certain topology. | ||
56 | */ | ||
57 | typedef int (*GNUNET_TESTING_ConnectionProcessor) | ||
58 | (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second); | ||
59 | |||
60 | struct RestartContext | ||
61 | { | ||
62 | /** | ||
63 | * The group of peers being restarted | ||
64 | */ | ||
65 | struct GNUNET_TESTING_PeerGroup *peer_group; | ||
66 | |||
67 | /** | ||
68 | * How many peers have been restarted thus far | ||
69 | */ | ||
70 | unsigned int peers_restarted; | ||
71 | |||
72 | /** | ||
73 | * How many peers got an error when restarting | ||
74 | */ | ||
75 | unsigned int peers_restart_failed; | ||
76 | |||
77 | /** | ||
78 | * The function to call once all peers have been restarted | ||
79 | */ | ||
80 | GNUNET_TESTING_NotifyCompletion callback; | ||
81 | |||
82 | /** | ||
83 | * Closure for callback function | ||
84 | */ | ||
85 | void *callback_cls; | ||
86 | |||
87 | }; | ||
88 | |||
89 | struct CreateTopologyContext | ||
90 | { | ||
91 | |||
92 | /** | ||
93 | * Function to call with number of connections | ||
94 | */ | ||
95 | GNUNET_TESTING_NotifyConnections cont; | ||
96 | |||
97 | /** | ||
98 | * Closure for connection notification | ||
99 | */ | ||
100 | void *cls; | ||
101 | }; | ||
102 | |||
103 | #if OLD | ||
53 | struct PeerConnection | 104 | struct PeerConnection |
54 | { | 105 | { |
55 | /* | 106 | /* |
@@ -63,6 +114,7 @@ struct PeerConnection | |||
63 | struct GNUNET_TESTING_Daemon *daemon; | 114 | struct GNUNET_TESTING_Daemon *daemon; |
64 | 115 | ||
65 | }; | 116 | }; |
117 | #endif | ||
66 | 118 | ||
67 | /** | 119 | /** |
68 | * Data we keep per peer. | 120 | * Data we keep per peer. |
@@ -83,9 +135,33 @@ struct PeerData | |||
83 | struct GNUNET_TESTING_Daemon *daemon; | 135 | struct GNUNET_TESTING_Daemon *daemon; |
84 | 136 | ||
85 | /** | 137 | /** |
86 | * Linked list of peer connections (simply indexes of PeerGroup) | 138 | * The peergroup this peer belongs to. |
139 | */ | ||
140 | struct GNUNET_TESTING_PeerGroup *pg; | ||
141 | |||
142 | /** | ||
143 | * Linked list of peer connections (pointers) | ||
144 | */ | ||
145 | //struct PeerConnection *connected_peers; | ||
146 | /** | ||
147 | * Hash map of allowed peer connections (F2F created topology) | ||
148 | */ | ||
149 | struct GNUNET_CONTAINER_MultiHashMap *allowed_peers; | ||
150 | |||
151 | /** | ||
152 | * Hash map of blacklisted peers | ||
153 | */ | ||
154 | struct GNUNET_CONTAINER_MultiHashMap *blacklisted_peers; | ||
155 | |||
156 | /** | ||
157 | * Hash map of peer connections | ||
158 | */ | ||
159 | struct GNUNET_CONTAINER_MultiHashMap *connect_peers; | ||
160 | |||
161 | /** | ||
162 | * Temporary hash map of peer connections | ||
87 | */ | 163 | */ |
88 | struct PeerConnection *connected_peers; | 164 | struct GNUNET_CONTAINER_MultiHashMap *connect_peers_working_set; |
89 | 165 | ||
90 | /** | 166 | /** |
91 | * Total number of connections this peer has | 167 | * Total number of connections this peer has |
@@ -165,6 +241,31 @@ struct GNUNET_TESTING_PeerGroup | |||
165 | 241 | ||
166 | }; | 242 | }; |
167 | 243 | ||
244 | /** | ||
245 | * Convert unique ID to hash code. | ||
246 | * | ||
247 | * @param uid unique ID to convert | ||
248 | * @param hash set to uid (extended with zeros) | ||
249 | */ | ||
250 | static void | ||
251 | hash_from_uid (uint32_t uid, | ||
252 | GNUNET_HashCode *hash) | ||
253 | { | ||
254 | memset (hash, 0, sizeof(GNUNET_HashCode)); | ||
255 | *((uint32_t*)hash) = uid; | ||
256 | } | ||
257 | |||
258 | /** | ||
259 | * Convert hash code to unique ID. | ||
260 | * | ||
261 | * @param uid unique ID to convert | ||
262 | * @param hash set to uid (extended with zeros) | ||
263 | */ | ||
264 | static void | ||
265 | uid_from_hash (const GNUNET_HashCode *hash, uint32_t *uid) | ||
266 | { | ||
267 | memcpy (uid, hash, sizeof(uint32_t)); | ||
268 | } | ||
168 | 269 | ||
169 | struct UpdateContext | 270 | struct UpdateContext |
170 | { | 271 | { |
@@ -279,41 +380,107 @@ make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port, con | |||
279 | return uc.ret; | 380 | return uc.ret; |
280 | } | 381 | } |
281 | 382 | ||
383 | |||
282 | /* | 384 | /* |
283 | * Add entries to the peers connected list | 385 | * Add entries to the peers connect list |
284 | * | 386 | * |
285 | * @param pg the peer group we are working with | 387 | * @param pg the peer group we are working with |
286 | * @param first index of the first peer | 388 | * @param first index of the first peer |
287 | * @param second index of the second peer | 389 | * @param second index of the second peer |
288 | * | 390 | * |
289 | * @return the number of connections added (can be 0, 1 or 2) | 391 | * @return the number of connections added (can be 0, 1 or 2) |
392 | * technically should only be 0 or 2, but the small price | ||
393 | * of iterating over the lists (hashmaps in the future) | ||
394 | * for being sure doesn't bother me! | ||
395 | * | ||
396 | */ | ||
397 | static int | ||
398 | add_actual_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) | ||
399 | { | ||
400 | int added; | ||
401 | int add_first; | ||
402 | int add_second; | ||
403 | |||
404 | GNUNET_HashCode hash_first; | ||
405 | GNUNET_HashCode hash_second; | ||
406 | |||
407 | hash_from_uid(first, &hash_first); | ||
408 | hash_from_uid(second, &hash_second); | ||
409 | |||
410 | add_first = GNUNET_NO; | ||
411 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].connect_peers, &hash_second)) | ||
412 | { | ||
413 | add_first = GNUNET_YES; | ||
414 | } | ||
415 | |||
416 | add_second = GNUNET_NO; | ||
417 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].connect_peers, &hash_first)) | ||
418 | { | ||
419 | add_second = GNUNET_YES; | ||
420 | } | ||
421 | |||
422 | added = 0; | ||
423 | if (add_first) | ||
424 | { | ||
425 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].connect_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
426 | added++; | ||
427 | } | ||
428 | |||
429 | if (add_second) | ||
430 | { | ||
431 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].connect_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
432 | added++; | ||
433 | } | ||
434 | |||
435 | return added; | ||
436 | } | ||
437 | |||
438 | |||
439 | /* | ||
440 | * Add entries to the peers allowed connections list | ||
290 | * | 441 | * |
291 | * FIXME: add both, or only add one? | 442 | * @param pg the peer group we are working with |
292 | * - if both are added, then we have to keep track | 443 | * @param first index of the first peer |
293 | * when connecting so we don't double connect | 444 | * @param second index of the second peer |
294 | * - if only one is added, we need to iterate over | ||
295 | * both lists to find out if connection already exists | ||
296 | * - having both allows the whitelisting/friend file | ||
297 | * creation to be easier | ||
298 | * | 445 | * |
299 | * -- For now, add both, we have to iterate over each to | 446 | * @return the number of connections added (can be 0, 1 or 2) |
300 | * check for duplicates anyways, so we'll take the performance | 447 | * technically should only be 0 or 2, but the small price |
301 | * hit assuming we don't have __too__ many connections | 448 | * of iterating over the lists (hashmaps in the future) |
449 | * for being sure doesn't bother me! | ||
302 | * | 450 | * |
303 | */ | 451 | */ |
304 | static int | 452 | static int |
305 | add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) | 453 | add_allowed_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) |
306 | { | 454 | { |
307 | int added; | 455 | int added; |
456 | #if OLD | ||
308 | struct PeerConnection *first_iter; | 457 | struct PeerConnection *first_iter; |
309 | struct PeerConnection *second_iter; | 458 | struct PeerConnection *second_iter; |
310 | int add_first; | ||
311 | int add_second; | ||
312 | struct PeerConnection *new_first; | 459 | struct PeerConnection *new_first; |
313 | struct PeerConnection *new_second; | 460 | struct PeerConnection *new_second; |
461 | #endif | ||
462 | int add_first; | ||
463 | int add_second; | ||
464 | |||
465 | GNUNET_HashCode hash_first; | ||
466 | GNUNET_HashCode hash_second; | ||
314 | 467 | ||
468 | hash_from_uid(first, &hash_first); | ||
469 | hash_from_uid(second, &hash_second); | ||
470 | |||
471 | add_first = GNUNET_NO; | ||
472 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].allowed_peers, &hash_second)) | ||
473 | { | ||
474 | add_first = GNUNET_YES; | ||
475 | } | ||
476 | |||
477 | add_second = GNUNET_NO; | ||
478 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].allowed_peers, &hash_first)) | ||
479 | { | ||
480 | add_second = GNUNET_YES; | ||
481 | } | ||
482 | #if OLD | ||
315 | first_iter = pg->peers[first].connected_peers; | 483 | first_iter = pg->peers[first].connected_peers; |
316 | add_first = GNUNET_YES; | ||
317 | while (first_iter != NULL) | 484 | while (first_iter != NULL) |
318 | { | 485 | { |
319 | if (first_iter->daemon == pg->peers[second].daemon) | 486 | if (first_iter->daemon == pg->peers[second].daemon) |
@@ -329,31 +496,129 @@ add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigne | |||
329 | add_second = GNUNET_NO; | 496 | add_second = GNUNET_NO; |
330 | second_iter = second_iter->next; | 497 | second_iter = second_iter->next; |
331 | } | 498 | } |
499 | #endif | ||
332 | 500 | ||
333 | added = 0; | 501 | added = 0; |
334 | if (add_first) | 502 | if (add_first) |
335 | { | 503 | { |
504 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].allowed_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
505 | #if OLD | ||
336 | new_first = GNUNET_malloc(sizeof(struct PeerConnection)); | 506 | new_first = GNUNET_malloc(sizeof(struct PeerConnection)); |
337 | new_first->daemon = pg->peers[second].daemon; | 507 | new_first->daemon = pg->peers[second].daemon; |
338 | new_first->next = pg->peers[first].connected_peers; | 508 | new_first->next = pg->peers[first].connected_peers; |
339 | pg->peers[first].connected_peers = new_first; | 509 | pg->peers[first].connected_peers = new_first; |
340 | pg->peers[first].num_connections++; | 510 | pg->peers[first].num_connections++; |
511 | #endif | ||
341 | added++; | 512 | added++; |
342 | } | 513 | } |
343 | 514 | ||
344 | if (add_second) | 515 | if (add_second) |
345 | { | 516 | { |
517 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].allowed_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
518 | #if OLD | ||
346 | new_second = GNUNET_malloc(sizeof(struct PeerConnection)); | 519 | new_second = GNUNET_malloc(sizeof(struct PeerConnection)); |
347 | new_second->daemon = pg->peers[first].daemon; | 520 | new_second->daemon = pg->peers[first].daemon; |
348 | new_second->next = pg->peers[second].connected_peers; | 521 | new_second->next = pg->peers[second].connected_peers; |
349 | pg->peers[second].connected_peers = new_second; | 522 | pg->peers[second].connected_peers = new_second; |
350 | pg->peers[first].num_connections++; | 523 | pg->peers[first].num_connections++; |
524 | #endif | ||
351 | added++; | 525 | added++; |
352 | } | 526 | } |
353 | 527 | ||
354 | return added; | 528 | return added; |
355 | } | 529 | } |
356 | 530 | ||
531 | /* | ||
532 | * Add entries to the peers blacklisted list | ||
533 | * | ||
534 | * @param pg the peer group we are working with | ||
535 | * @param first index of the first peer | ||
536 | * @param second index of the second peer | ||
537 | * | ||
538 | * @return the number of connections added (can be 0, 1 or 2) | ||
539 | * | ||
540 | */ | ||
541 | static int | ||
542 | blacklist_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) | ||
543 | { | ||
544 | int added; | ||
545 | int add_first; | ||
546 | int add_second; | ||
547 | GNUNET_HashCode hash_first; | ||
548 | GNUNET_HashCode hash_second; | ||
549 | |||
550 | hash_from_uid(first, &hash_first); | ||
551 | hash_from_uid(second, &hash_second); | ||
552 | |||
553 | add_first = GNUNET_NO; | ||
554 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].blacklisted_peers, &hash_second)) | ||
555 | { | ||
556 | add_first = GNUNET_YES; | ||
557 | } | ||
558 | |||
559 | add_second = GNUNET_NO; | ||
560 | if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].blacklisted_peers, &hash_first)) | ||
561 | { | ||
562 | add_second = GNUNET_YES; | ||
563 | } | ||
564 | |||
565 | added = 0; | ||
566 | if (add_first) | ||
567 | { | ||
568 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].blacklisted_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
569 | added++; | ||
570 | } | ||
571 | |||
572 | if (add_second) | ||
573 | { | ||
574 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].blacklisted_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
575 | added++; | ||
576 | } | ||
577 | |||
578 | return added; | ||
579 | } | ||
580 | |||
581 | /* | ||
582 | * Remove entries from the peers blacklisted list | ||
583 | * | ||
584 | * @param pg the peer group we are working with | ||
585 | * @param first index of the first peer | ||
586 | * @param second index of the second peer | ||
587 | * | ||
588 | * @return the number of connections removed (can be 0, 1 or 2) | ||
589 | * | ||
590 | */ | ||
591 | static int | ||
592 | unblacklist_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second) | ||
593 | { | ||
594 | int removed; | ||
595 | int remove_first; | ||
596 | int remove_second; | ||
597 | GNUNET_HashCode hash_first; | ||
598 | GNUNET_HashCode hash_second; | ||
599 | |||
600 | hash_from_uid(first, &hash_first); | ||
601 | hash_from_uid(second, &hash_second); | ||
602 | |||
603 | remove_first = GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].blacklisted_peers, &hash_second); | ||
604 | remove_second = GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].blacklisted_peers, &hash_first); | ||
605 | |||
606 | removed = 0; | ||
607 | if (remove_first) | ||
608 | { | ||
609 | GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(pg->peers[first].blacklisted_peers, &hash_second, pg->peers[second].daemon)); | ||
610 | removed++; | ||
611 | } | ||
612 | |||
613 | if (remove_second) | ||
614 | { | ||
615 | GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(pg->peers[second].blacklisted_peers, &hash_first, pg->peers[first].daemon)); | ||
616 | removed++; | ||
617 | } | ||
618 | |||
619 | return removed; | ||
620 | } | ||
621 | |||
357 | /** | 622 | /** |
358 | * Scale free network construction as described in: | 623 | * Scale free network construction as described in: |
359 | * | 624 | * |
@@ -369,7 +634,7 @@ add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigne | |||
369 | * @return the number of connections created | 634 | * @return the number of connections created |
370 | */ | 635 | */ |
371 | static int | 636 | static int |
372 | create_scale_free (struct GNUNET_TESTING_PeerGroup *pg) | 637 | create_scale_free (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
373 | { | 638 | { |
374 | 639 | ||
375 | unsigned int total_connections; | 640 | unsigned int total_connections; |
@@ -382,7 +647,7 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg) | |||
382 | GNUNET_assert(pg->total > 1); | 647 | GNUNET_assert(pg->total > 1); |
383 | 648 | ||
384 | /* Add a connection between the first two nodes */ | 649 | /* Add a connection between the first two nodes */ |
385 | total_connections = add_connections(pg, 0, 1); | 650 | total_connections = proc(pg, 0, 1); |
386 | 651 | ||
387 | for (outer_count = 1; outer_count < pg->total; outer_count++) | 652 | for (outer_count = 1; outer_count < pg->total; outer_count++) |
388 | { | 653 | { |
@@ -404,7 +669,7 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg) | |||
404 | "Connecting peer %d to peer %d\n", | 669 | "Connecting peer %d to peer %d\n", |
405 | outer_count, i); | 670 | outer_count, i); |
406 | #endif | 671 | #endif |
407 | total_connections += add_connections(pg, outer_count, i); | 672 | total_connections += proc(pg, outer_count, i); |
408 | } | 673 | } |
409 | } | 674 | } |
410 | } | 675 | } |
@@ -413,7 +678,7 @@ create_scale_free (struct GNUNET_TESTING_PeerGroup *pg) | |||
413 | } | 678 | } |
414 | 679 | ||
415 | int | 680 | int |
416 | create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg) | 681 | create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
417 | { | 682 | { |
418 | unsigned int i, j; | 683 | unsigned int i, j; |
419 | int nodeToConnect; | 684 | int nodeToConnect; |
@@ -502,7 +767,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg) | |||
502 | pg->total); | 767 | pg->total); |
503 | } | 768 | } |
504 | smallWorldConnections += | 769 | smallWorldConnections += |
505 | add_connections (pg, i, randomPeer); | 770 | proc (pg, i, randomPeer); |
506 | } | 771 | } |
507 | else | 772 | else |
508 | { | 773 | { |
@@ -512,7 +777,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg) | |||
512 | nodeToConnect = nodeToConnect - pg->total; | 777 | nodeToConnect = nodeToConnect - pg->total; |
513 | } | 778 | } |
514 | connect_attempts += | 779 | connect_attempts += |
515 | add_connections (pg, i, nodeToConnect); | 780 | proc (pg, i, nodeToConnect); |
516 | } | 781 | } |
517 | } | 782 | } |
518 | 783 | ||
@@ -525,7 +790,7 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg) | |||
525 | 790 | ||
526 | 791 | ||
527 | static int | 792 | static int |
528 | create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg) | 793 | create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
529 | { | 794 | { |
530 | unsigned int outer_count, inner_count; | 795 | unsigned int outer_count, inner_count; |
531 | unsigned int cutoff; | 796 | unsigned int cutoff; |
@@ -566,7 +831,7 @@ create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg) | |||
566 | "Connecting peer %d to peer %d\n", | 831 | "Connecting peer %d to peer %d\n", |
567 | outer_count, inner_count); | 832 | outer_count, inner_count); |
568 | #endif | 833 | #endif |
569 | connect_attempts += add_connections(pg, outer_count, inner_count); | 834 | connect_attempts += proc(pg, outer_count, inner_count); |
570 | } | 835 | } |
571 | } | 836 | } |
572 | } | 837 | } |
@@ -578,7 +843,7 @@ create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg) | |||
578 | 843 | ||
579 | 844 | ||
580 | static int | 845 | static int |
581 | create_small_world (struct GNUNET_TESTING_PeerGroup *pg) | 846 | create_small_world (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
582 | { | 847 | { |
583 | unsigned int i, j, k; | 848 | unsigned int i, j, k; |
584 | unsigned int square; | 849 | unsigned int square; |
@@ -662,7 +927,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg) | |||
662 | else | 927 | else |
663 | nodeToConnect = i - cols + 1; | 928 | nodeToConnect = i - cols + 1; |
664 | 929 | ||
665 | connect_attempts += add_connections (pg, i, nodeToConnect); | 930 | connect_attempts += proc (pg, i, nodeToConnect); |
666 | 931 | ||
667 | if (i < cols) | 932 | if (i < cols) |
668 | nodeToConnect = (rows * cols) - cols + i; | 933 | nodeToConnect = (rows * cols) - cols + i; |
@@ -670,7 +935,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg) | |||
670 | nodeToConnect = i - cols; | 935 | nodeToConnect = i - cols; |
671 | 936 | ||
672 | if (nodeToConnect < pg->total) | 937 | if (nodeToConnect < pg->total) |
673 | connect_attempts += add_connections (pg, i, nodeToConnect); | 938 | connect_attempts += proc (pg, i, nodeToConnect); |
674 | } | 939 | } |
675 | natLog = log (pg->total); | 940 | natLog = log (pg->total); |
676 | #if VERBOSE_TESTING > 2 | 941 | #if VERBOSE_TESTING > 2 |
@@ -703,7 +968,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg) | |||
703 | (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL); | 968 | (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL); |
704 | /* If random < probability, then connect the two nodes */ | 969 | /* If random < probability, then connect the two nodes */ |
705 | if (random < probability) | 970 | if (random < probability) |
706 | smallWorldConnections += add_connections (pg, j, k); | 971 | smallWorldConnections += proc (pg, j, k); |
707 | 972 | ||
708 | } | 973 | } |
709 | } | 974 | } |
@@ -721,7 +986,7 @@ create_small_world (struct GNUNET_TESTING_PeerGroup *pg) | |||
721 | 986 | ||
722 | 987 | ||
723 | static int | 988 | static int |
724 | create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg) | 989 | create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
725 | { | 990 | { |
726 | double temp_rand; | 991 | double temp_rand; |
727 | unsigned int outer_count; | 992 | unsigned int outer_count; |
@@ -759,7 +1024,7 @@ create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg) | |||
759 | #endif | 1024 | #endif |
760 | if (temp_rand < probability) | 1025 | if (temp_rand < probability) |
761 | { | 1026 | { |
762 | connect_attempts += add_connections (pg, outer_count, inner_count); | 1027 | connect_attempts += proc (pg, outer_count, inner_count); |
763 | } | 1028 | } |
764 | } | 1029 | } |
765 | } | 1030 | } |
@@ -768,7 +1033,7 @@ create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg) | |||
768 | } | 1033 | } |
769 | 1034 | ||
770 | static int | 1035 | static int |
771 | create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg) | 1036 | create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
772 | { | 1037 | { |
773 | unsigned int i; | 1038 | unsigned int i; |
774 | unsigned int square; | 1039 | unsigned int square; |
@@ -820,7 +1085,7 @@ create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg) | |||
820 | "Connecting peer %d to peer %d\n", | 1085 | "Connecting peer %d to peer %d\n", |
821 | i, nodeToConnect); | 1086 | i, nodeToConnect); |
822 | #endif | 1087 | #endif |
823 | connect_attempts += add_connections(pg, i, nodeToConnect); | 1088 | connect_attempts += proc(pg, i, nodeToConnect); |
824 | 1089 | ||
825 | /* Second connect to the node immediately above */ | 1090 | /* Second connect to the node immediately above */ |
826 | if (i < cols) | 1091 | if (i < cols) |
@@ -835,7 +1100,7 @@ create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg) | |||
835 | "Connecting peer %d to peer %d\n", | 1100 | "Connecting peer %d to peer %d\n", |
836 | i, nodeToConnect); | 1101 | i, nodeToConnect); |
837 | #endif | 1102 | #endif |
838 | connect_attempts += add_connections(pg, i, nodeToConnect); | 1103 | connect_attempts += proc(pg, i, nodeToConnect); |
839 | } | 1104 | } |
840 | 1105 | ||
841 | } | 1106 | } |
@@ -846,7 +1111,7 @@ create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg) | |||
846 | 1111 | ||
847 | 1112 | ||
848 | static int | 1113 | static int |
849 | create_clique (struct GNUNET_TESTING_PeerGroup *pg) | 1114 | create_clique (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
850 | { | 1115 | { |
851 | unsigned int outer_count; | 1116 | unsigned int outer_count; |
852 | unsigned int inner_count; | 1117 | unsigned int inner_count; |
@@ -864,7 +1129,7 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg) | |||
864 | "Connecting peer %d to peer %d\n", | 1129 | "Connecting peer %d to peer %d\n", |
865 | outer_count, inner_count); | 1130 | outer_count, inner_count); |
866 | #endif | 1131 | #endif |
867 | connect_attempts += add_connections(pg, outer_count, inner_count); | 1132 | connect_attempts += proc(pg, outer_count, inner_count); |
868 | } | 1133 | } |
869 | } | 1134 | } |
870 | 1135 | ||
@@ -873,7 +1138,7 @@ create_clique (struct GNUNET_TESTING_PeerGroup *pg) | |||
873 | 1138 | ||
874 | 1139 | ||
875 | static int | 1140 | static int |
876 | create_ring (struct GNUNET_TESTING_PeerGroup *pg) | 1141 | create_ring (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc) |
877 | { | 1142 | { |
878 | unsigned int count; | 1143 | unsigned int count; |
879 | int connect_attempts; | 1144 | int connect_attempts; |
@@ -888,16 +1153,77 @@ create_ring (struct GNUNET_TESTING_PeerGroup *pg) | |||
888 | "Connecting peer %d to peer %d\n", | 1153 | "Connecting peer %d to peer %d\n", |
889 | count, count + 1); | 1154 | count, count + 1); |
890 | #endif | 1155 | #endif |
891 | connect_attempts += add_connections(pg, count, count + 1); | 1156 | connect_attempts += proc(pg, count, count + 1); |
892 | } | 1157 | } |
893 | 1158 | ||
894 | /* Connect the last peer to the first peer */ | 1159 | /* Connect the last peer to the first peer */ |
895 | connect_attempts += add_connections(pg, pg->total - 1, 0); | 1160 | connect_attempts += proc(pg, pg->total - 1, 0); |
896 | 1161 | ||
897 | return connect_attempts; | 1162 | return connect_attempts; |
898 | } | 1163 | } |
899 | 1164 | ||
900 | 1165 | ||
1166 | /** | ||
1167 | * Iterator for writing friends of a peer to a file. | ||
1168 | * | ||
1169 | * @param cls closure, an open writable file handle | ||
1170 | * @param key the key the daemon was stored under | ||
1171 | * @param value the GNUNET_TESTING_Daemon that needs to be written. | ||
1172 | * | ||
1173 | * @return GNUNET_YES to continue iteration | ||
1174 | * | ||
1175 | * TODO: Could replace friend_file_iterator and blacklist_file_iterator | ||
1176 | * with a single file_iterator that takes a closure which contains | ||
1177 | * the prefix to write before the peer. Then this could be used | ||
1178 | * for blacklisting multiple transports and writing the friend | ||
1179 | * file. I'm sure *someone* will complain loudly about other | ||
1180 | * things that negate these functions even existing so no point in | ||
1181 | * "fixing" now. | ||
1182 | */ | ||
1183 | static int | ||
1184 | friend_file_iterator (void *cls, | ||
1185 | const GNUNET_HashCode * key, | ||
1186 | void *value) | ||
1187 | { | ||
1188 | FILE *temp_friend_handle = cls; | ||
1189 | struct GNUNET_TESTING_Daemon *peer = value; | ||
1190 | struct GNUNET_PeerIdentity *temppeer; | ||
1191 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
1192 | |||
1193 | temppeer = &peer->id; | ||
1194 | GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc); | ||
1195 | fprintf(temp_friend_handle, "%s\n", (char *)&peer_enc); | ||
1196 | |||
1197 | return GNUNET_YES; | ||
1198 | } | ||
1199 | |||
1200 | |||
1201 | /** | ||
1202 | * Iterator for writing blacklist data to appropriate files. | ||
1203 | * | ||
1204 | * @param cls closure, an open writable file handle | ||
1205 | * @param key the key the daemon was stored under | ||
1206 | * @param value the GNUNET_TESTING_Daemon that needs to be written. | ||
1207 | * | ||
1208 | * @return GNUNET_YES to continue iteration | ||
1209 | */ | ||
1210 | static int | ||
1211 | blacklist_file_iterator (void *cls, | ||
1212 | const GNUNET_HashCode * key, | ||
1213 | void *value) | ||
1214 | { | ||
1215 | FILE *temp_blacklist_handle = cls; | ||
1216 | struct GNUNET_TESTING_Daemon *peer = value; | ||
1217 | struct GNUNET_PeerIdentity *temppeer; | ||
1218 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
1219 | |||
1220 | temppeer = &peer->id; | ||
1221 | GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc); | ||
1222 | fprintf(temp_blacklist_handle, "tcp:%s\n", (char *)&peer_enc); | ||
1223 | |||
1224 | return GNUNET_YES; | ||
1225 | } | ||
1226 | |||
901 | /* | 1227 | /* |
902 | * Create the friend files based on the PeerConnection's | 1228 | * Create the friend files based on the PeerConnection's |
903 | * of each peer in the peer group, and copy the files | 1229 | * of each peer in the peer group, and copy the files |
@@ -910,12 +1236,9 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg) | |||
910 | { | 1236 | { |
911 | FILE *temp_friend_handle; | 1237 | FILE *temp_friend_handle; |
912 | unsigned int pg_iter; | 1238 | unsigned int pg_iter; |
913 | struct PeerConnection *connection_iter; | ||
914 | struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc; | ||
915 | char *temp_service_path; | 1239 | char *temp_service_path; |
916 | pid_t *pidarr; | 1240 | pid_t *pidarr; |
917 | char *arg; | 1241 | char *arg; |
918 | struct GNUNET_PeerIdentity *temppeer; | ||
919 | char * mytemp; | 1242 | char * mytemp; |
920 | enum GNUNET_OS_ProcessStatusType type; | 1243 | enum GNUNET_OS_ProcessStatusType type; |
921 | unsigned long return_code; | 1244 | unsigned long return_code; |
@@ -927,16 +1250,10 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg) | |||
927 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | 1250 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) |
928 | { | 1251 | { |
929 | mytemp = GNUNET_DISK_mktemp("friends"); | 1252 | mytemp = GNUNET_DISK_mktemp("friends"); |
1253 | GNUNET_assert(mytemp != NULL); | ||
930 | temp_friend_handle = fopen (mytemp, "wt"); | 1254 | temp_friend_handle = fopen (mytemp, "wt"); |
931 | connection_iter = pg->peers[pg_iter].connected_peers; | 1255 | GNUNET_assert(temp_friend_handle != NULL); |
932 | while (connection_iter != NULL) | 1256 | GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].allowed_peers, &friend_file_iterator, temp_friend_handle); |
933 | { | ||
934 | temppeer = &connection_iter->daemon->id; | ||
935 | GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc); | ||
936 | fprintf(temp_friend_handle, "%s\n", (char *)&peer_enc); | ||
937 | connection_iter = connection_iter->next; | ||
938 | } | ||
939 | |||
940 | fclose(temp_friend_handle); | 1257 | fclose(temp_friend_handle); |
941 | 1258 | ||
942 | if (GNUNET_OK != | 1259 | if (GNUNET_OK != |
@@ -1029,6 +1346,130 @@ create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg) | |||
1029 | return ret; | 1346 | return ret; |
1030 | } | 1347 | } |
1031 | 1348 | ||
1349 | |||
1350 | /* | ||
1351 | * Create the blacklist files based on the PeerConnection's | ||
1352 | * of each peer in the peer group, and copy the files | ||
1353 | * to the appropriate place. | ||
1354 | * | ||
1355 | * @param pg the peer group we are dealing with | ||
1356 | */ | ||
1357 | static int | ||
1358 | create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg) | ||
1359 | { | ||
1360 | FILE *temp_friend_handle; | ||
1361 | unsigned int pg_iter; | ||
1362 | char *temp_service_path; | ||
1363 | pid_t *pidarr; | ||
1364 | char *arg; | ||
1365 | char *mytemp; | ||
1366 | enum GNUNET_OS_ProcessStatusType type; | ||
1367 | unsigned long return_code; | ||
1368 | int count; | ||
1369 | int ret; | ||
1370 | int max_wait = 10; | ||
1371 | |||
1372 | pidarr = GNUNET_malloc(sizeof(pid_t) * pg->total); | ||
1373 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
1374 | { | ||
1375 | mytemp = GNUNET_DISK_mktemp("blacklist"); | ||
1376 | GNUNET_assert(mytemp != NULL); | ||
1377 | temp_friend_handle = fopen (mytemp, "wt"); | ||
1378 | GNUNET_assert(temp_friend_handle != NULL); | ||
1379 | GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].blacklisted_peers, &blacklist_file_iterator, temp_friend_handle); | ||
1380 | fclose(temp_friend_handle); | ||
1381 | |||
1382 | if (GNUNET_OK != | ||
1383 | GNUNET_CONFIGURATION_get_value_string(pg->peers[pg_iter].daemon->cfg, "PATHS", "SERVICEHOME", &temp_service_path)) | ||
1384 | { | ||
1385 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1386 | _("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"), | ||
1387 | "SERVICEHOME", | ||
1388 | "PATHS"); | ||
1389 | if (UNLINK (mytemp) != 0) | ||
1390 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp); | ||
1391 | GNUNET_free (mytemp); | ||
1392 | break; | ||
1393 | } | ||
1394 | |||
1395 | if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */ | ||
1396 | { | ||
1397 | GNUNET_asprintf (&arg, "%s/blacklist", temp_service_path); | ||
1398 | pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "mv", | ||
1399 | "mv", mytemp, arg, NULL); | ||
1400 | #if VERBOSE_TESTING | ||
1401 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1402 | _("Copying file with command cp %s %s\n"), mytemp, arg); | ||
1403 | #endif | ||
1404 | |||
1405 | GNUNET_free(arg); | ||
1406 | } | ||
1407 | else /* Remote, scp the file to the correct place */ | ||
1408 | { | ||
1409 | if (NULL != pg->peers[pg_iter].daemon->username) | ||
1410 | GNUNET_asprintf (&arg, "%s@%s:%s/blacklist", pg->peers[pg_iter].daemon->username, pg->peers[pg_iter].daemon->hostname, temp_service_path); | ||
1411 | else | ||
1412 | GNUNET_asprintf (&arg, "%s:%s/blacklist", pg->peers[pg_iter].daemon->hostname, temp_service_path); | ||
1413 | pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp", | ||
1414 | "scp", mytemp, arg, NULL); | ||
1415 | |||
1416 | #if VERBOSE_TESTING | ||
1417 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1418 | _("Copying file with command scp %s %s\n"), mytemp, arg); | ||
1419 | #endif | ||
1420 | GNUNET_free(arg); | ||
1421 | } | ||
1422 | GNUNET_free (temp_service_path); | ||
1423 | GNUNET_free (mytemp); | ||
1424 | } | ||
1425 | |||
1426 | count = 0; | ||
1427 | ret = GNUNET_SYSERR; | ||
1428 | while ((count < max_wait) && (ret != GNUNET_OK)) | ||
1429 | { | ||
1430 | ret = GNUNET_OK; | ||
1431 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
1432 | { | ||
1433 | #if VERBOSE_TESTING | ||
1434 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1435 | _("Checking copy status of file %d\n"), pg_iter); | ||
1436 | #endif | ||
1437 | if (pidarr[pg_iter] != 0) /* Check for already completed! */ | ||
1438 | { | ||
1439 | if (GNUNET_OS_process_status(pidarr[pg_iter], &type, &return_code) != GNUNET_OK) | ||
1440 | { | ||
1441 | ret = GNUNET_SYSERR; | ||
1442 | } | ||
1443 | else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0)) | ||
1444 | { | ||
1445 | ret = GNUNET_SYSERR; | ||
1446 | } | ||
1447 | else | ||
1448 | { | ||
1449 | pidarr[pg_iter] = 0; | ||
1450 | #if VERBOSE_TESTING | ||
1451 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1452 | _("File %d copied\n"), pg_iter); | ||
1453 | #endif | ||
1454 | } | ||
1455 | } | ||
1456 | } | ||
1457 | count++; | ||
1458 | if (ret == GNUNET_SYSERR) | ||
1459 | { | ||
1460 | sleep(1); | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1464 | #if VERBOSE_TESTING | ||
1465 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1466 | _("Finished copying all blacklist files!\n")); | ||
1467 | #endif | ||
1468 | GNUNET_free(pidarr); | ||
1469 | return ret; | ||
1470 | } | ||
1471 | |||
1472 | |||
1032 | /** | 1473 | /** |
1033 | * Internal notification of a connection, kept so that we can ensure some connections | 1474 | * Internal notification of a connection, kept so that we can ensure some connections |
1034 | * happen instead of flooding all testing daemons with requests to connect. | 1475 | * happen instead of flooding all testing daemons with requests to connect. |
@@ -1081,54 +1522,154 @@ static void schedule_connect(void *cls, const struct GNUNET_SCHEDULER_TaskContex | |||
1081 | } | 1522 | } |
1082 | } | 1523 | } |
1083 | 1524 | ||
1525 | /** | ||
1526 | * Iterator for actually scheduling connections to be created | ||
1527 | * between two peers. | ||
1528 | * | ||
1529 | * @param cls closure, a GNUNET_TESTING_Daemon | ||
1530 | * @param key the key the second Daemon was stored under | ||
1531 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
1532 | * | ||
1533 | * @return GNUNET_YES to continue iteration | ||
1534 | */ | ||
1535 | static int | ||
1536 | connect_iterator (void *cls, | ||
1537 | const GNUNET_HashCode * key, | ||
1538 | void *value) | ||
1539 | { | ||
1540 | struct PeerData *first = cls; | ||
1541 | struct GNUNET_TESTING_Daemon *second = value; | ||
1542 | struct ConnectContext *connect_context; | ||
1543 | |||
1544 | connect_context = GNUNET_malloc(sizeof(struct ConnectContext)); | ||
1545 | connect_context->pg = first->pg; | ||
1546 | connect_context->first = first->daemon; | ||
1547 | connect_context->second = second; | ||
1548 | GNUNET_SCHEDULER_add_now(first->pg->sched, &schedule_connect, connect_context); | ||
1549 | |||
1550 | return GNUNET_YES; | ||
1551 | } | ||
1552 | |||
1553 | /** | ||
1554 | * Iterator for copying all entries in the allowed hashmap to the | ||
1555 | * connect hashmap. | ||
1556 | * | ||
1557 | * @param cls closure, a GNUNET_TESTING_Daemon | ||
1558 | * @param key the key the second Daemon was stored under | ||
1559 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
1560 | * | ||
1561 | * @return GNUNET_YES to continue iteration | ||
1562 | */ | ||
1563 | static int | ||
1564 | copy_topology_iterator (void *cls, | ||
1565 | const GNUNET_HashCode * key, | ||
1566 | void *value) | ||
1567 | { | ||
1568 | struct PeerData *first = cls; | ||
1569 | |||
1570 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(first->connect_peers, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1571 | |||
1572 | return GNUNET_YES; | ||
1573 | } | ||
1574 | |||
1575 | /** | ||
1576 | * Make the peers to connect the same as those that are allowed to be | ||
1577 | * connected. | ||
1578 | * | ||
1579 | * @param pg the peer group | ||
1580 | */ | ||
1581 | static int | ||
1582 | copy_allowed_topology (struct GNUNET_TESTING_PeerGroup *pg) | ||
1583 | { | ||
1584 | unsigned int pg_iter; | ||
1585 | int ret; | ||
1586 | int total; | ||
1587 | |||
1588 | total = 0; | ||
1589 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
1590 | { | ||
1591 | ret = GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].allowed_peers, ©_topology_iterator, &pg->peers[pg_iter]); | ||
1592 | if (GNUNET_SYSERR == ret) | ||
1593 | return GNUNET_SYSERR; | ||
1594 | |||
1595 | total = total + ret; | ||
1596 | } | ||
1597 | |||
1598 | return total; | ||
1599 | } | ||
1600 | |||
1601 | |||
1084 | /* | 1602 | /* |
1085 | * Connect the topology as specified by the PeerConnection's | 1603 | * Connect the topology as specified by the PeerConnection's |
1086 | * of each peer in the peer group | 1604 | * of each peer in the peer group |
1087 | * | 1605 | * |
1088 | * @param pg the peer group we are dealing with | 1606 | * @param pg the peer group we are dealing with |
1607 | * | ||
1608 | * @return the number of connections that will be attempted | ||
1089 | */ | 1609 | */ |
1090 | static void | 1610 | static int |
1091 | connect_topology (struct GNUNET_TESTING_PeerGroup *pg) | 1611 | connect_topology (struct GNUNET_TESTING_PeerGroup *pg) |
1092 | { | 1612 | { |
1093 | unsigned int pg_iter; | 1613 | unsigned int pg_iter; |
1614 | int ret; | ||
1615 | int total; | ||
1616 | #if OLD | ||
1094 | struct PeerConnection *connection_iter; | 1617 | struct PeerConnection *connection_iter; |
1095 | struct ConnectContext *connect_context; | 1618 | struct ConnectContext *connect_context; |
1619 | #endif | ||
1096 | 1620 | ||
1621 | total = 0; | ||
1097 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | 1622 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) |
1098 | { | 1623 | { |
1099 | connection_iter = pg->peers[pg_iter].connected_peers; | 1624 | ret = GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &connect_iterator, &pg->peers[pg_iter]); |
1625 | if (GNUNET_SYSERR == ret) | ||
1626 | return GNUNET_SYSERR; | ||
1627 | |||
1628 | total = total + ret; | ||
1629 | |||
1630 | #if OLD | ||
1631 | connection_iter = ; | ||
1100 | while (connection_iter != NULL) | 1632 | while (connection_iter != NULL) |
1101 | { | 1633 | { |
1102 | connect_context = GNUNET_malloc(sizeof(struct ConnectContext)); | 1634 | connect_context = GNUNET_malloc(sizeof(struct ConnectContext)); |
1103 | connect_context->pg = pg; | 1635 | connect_context->pg = pg; |
1104 | connect_context->first = pg->peers[pg_iter].daemon; | 1636 | connect_context->first = ; |
1105 | connect_context->second = connection_iter->daemon; | 1637 | connect_context->second = connection_iter->daemon; |
1106 | GNUNET_SCHEDULER_add_now(pg->sched, &schedule_connect, connect_context); | 1638 | GNUNET_SCHEDULER_add_now(pg->sched, &schedule_connect, connect_context); |
1107 | connection_iter = connection_iter->next; | 1639 | connection_iter = connection_iter->next; |
1108 | } | 1640 | } |
1641 | #endif | ||
1109 | } | 1642 | } |
1643 | return total; | ||
1110 | } | 1644 | } |
1111 | 1645 | ||
1112 | 1646 | ||
1113 | /* | 1647 | /* |
1114 | * Takes a peer group and attempts to create a topology based on the | 1648 | * Takes a peer group and creates a topology based on the |
1115 | * one specified in the configuration file. Returns the number of connections | 1649 | * one specified. Creates a topology means generates friend |
1116 | * that will attempt to be created, but this will happen asynchronously(?) so | 1650 | * files for the peers so they can only connect to those allowed |
1117 | * the caller will have to keep track (via the callback) of whether or not | 1651 | * by the topology. This will only have an effect once peers |
1118 | * the connection actually happened. | 1652 | * are started if the FRIENDS_ONLY option is set in the base |
1653 | * config. Also takes an optional restrict topology which | ||
1654 | * disallows direct TCP connections UNLESS they are specified in | ||
1655 | * the restricted topology. | ||
1119 | * | 1656 | * |
1120 | * @param pg the peer group struct representing the running peers | 1657 | * @param pg the peer group struct representing the running peers |
1121 | * @param topology which topology to connect the peers in | 1658 | * @param topology which topology to connect the peers in |
1659 | * @param restrict_topology allow only direct TCP connections in this topology | ||
1660 | * use GNUNET_TESTING_TOPOLOGY_NONE for no restrictions | ||
1122 | * | 1661 | * |
1123 | * @return the number of connections should be created by the topology, so the | 1662 | * @return the maximum number of connections were all allowed peers |
1124 | * caller knows how many to wait for (if it so chooses) | 1663 | * connected to each other |
1125 | * | ||
1126 | */ | 1664 | */ |
1127 | int | 1665 | int |
1128 | GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET_TESTING_Topology topology) | 1666 | GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, |
1667 | enum GNUNET_TESTING_Topology topology, | ||
1668 | enum GNUNET_TESTING_Topology restrict_topology) | ||
1129 | { | 1669 | { |
1130 | int ret; | 1670 | int ret; |
1131 | int num_connections; | 1671 | int num_connections; |
1672 | int unblacklisted_connections; | ||
1132 | 1673 | ||
1133 | GNUNET_assert (pg->notify_connection != NULL); | 1674 | GNUNET_assert (pg->notify_connection != NULL); |
1134 | ret = GNUNET_OK; | 1675 | ret = GNUNET_OK; |
@@ -1140,56 +1681,56 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET | |||
1140 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1681 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1141 | _("Creating clique topology\n")); | 1682 | _("Creating clique topology\n")); |
1142 | #endif | 1683 | #endif |
1143 | num_connections = create_clique (pg); | 1684 | num_connections = create_clique (pg, &add_allowed_connections); |
1144 | break; | 1685 | break; |
1145 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: | 1686 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: |
1146 | #if VERBOSE_TESTING | 1687 | #if VERBOSE_TESTING |
1147 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1688 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1148 | _("Creating small world (ring) topology\n")); | 1689 | _("Creating small world (ring) topology\n")); |
1149 | #endif | 1690 | #endif |
1150 | num_connections = create_small_world_ring (pg); | 1691 | num_connections = create_small_world_ring (pg, &add_allowed_connections); |
1151 | break; | 1692 | break; |
1152 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: | 1693 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: |
1153 | #if VERBOSE_TESTING | 1694 | #if VERBOSE_TESTING |
1154 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1695 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1155 | _("Creating small world (2d-torus) topology\n")); | 1696 | _("Creating small world (2d-torus) topology\n")); |
1156 | #endif | 1697 | #endif |
1157 | num_connections = create_small_world (pg); | 1698 | num_connections = create_small_world (pg, &add_allowed_connections); |
1158 | break; | 1699 | break; |
1159 | case GNUNET_TESTING_TOPOLOGY_RING: | 1700 | case GNUNET_TESTING_TOPOLOGY_RING: |
1160 | #if VERBOSE_TESTING | 1701 | #if VERBOSE_TESTING |
1161 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1702 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1162 | _("Creating ring topology\n")); | 1703 | _("Creating ring topology\n")); |
1163 | #endif | 1704 | #endif |
1164 | num_connections = create_ring (pg); | 1705 | num_connections = create_ring (pg, &add_allowed_connections); |
1165 | break; | 1706 | break; |
1166 | case GNUNET_TESTING_TOPOLOGY_2D_TORUS: | 1707 | case GNUNET_TESTING_TOPOLOGY_2D_TORUS: |
1167 | #if VERBOSE_TESTING | 1708 | #if VERBOSE_TESTING |
1168 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1709 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1169 | _("Creating 2d torus topology\n")); | 1710 | _("Creating 2d torus topology\n")); |
1170 | #endif | 1711 | #endif |
1171 | num_connections = create_2d_torus (pg); | 1712 | num_connections = create_2d_torus (pg, &add_allowed_connections); |
1172 | break; | 1713 | break; |
1173 | case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: | 1714 | case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: |
1174 | #if VERBOSE_TESTING | 1715 | #if VERBOSE_TESTING |
1175 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1716 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1176 | _("Creating Erdos-Renyi topology\n")); | 1717 | _("Creating Erdos-Renyi topology\n")); |
1177 | #endif | 1718 | #endif |
1178 | num_connections = create_erdos_renyi (pg); | 1719 | num_connections = create_erdos_renyi (pg, &add_allowed_connections); |
1179 | break; | 1720 | break; |
1180 | case GNUNET_TESTING_TOPOLOGY_INTERNAT: | 1721 | case GNUNET_TESTING_TOPOLOGY_INTERNAT: |
1181 | #if VERBOSE_TESTING | 1722 | #if VERBOSE_TESTING |
1182 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1723 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1183 | _("Creating InterNAT topology\n")); | 1724 | _("Creating InterNAT topology\n")); |
1184 | #endif | 1725 | #endif |
1185 | num_connections = create_nated_internet (pg); | 1726 | num_connections = create_nated_internet (pg, &add_allowed_connections); |
1186 | break; | 1727 | break; |
1187 | case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: | 1728 | case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: |
1188 | #if VERBOSE_TESTING | 1729 | #if VERBOSE_TESTING |
1189 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1730 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1190 | _("Creating Scale Free topology\n")); | 1731 | _("Creating Scale Free topology\n")); |
1191 | #endif | 1732 | #endif |
1192 | num_connections = create_scale_free (pg); | 1733 | num_connections = create_scale_free (pg, &add_allowed_connections); |
1193 | break; | 1734 | break; |
1194 | case GNUNET_TESTING_TOPOLOGY_NONE: | 1735 | case GNUNET_TESTING_TOPOLOGY_NONE: |
1195 | num_connections = 0; | 1736 | num_connections = 0; |
@@ -1202,10 +1743,11 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET | |||
1202 | return GNUNET_SYSERR; | 1743 | return GNUNET_SYSERR; |
1203 | 1744 | ||
1204 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F")) | 1745 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F")) |
1205 | ret = create_and_copy_friend_files(pg); | 1746 | { |
1206 | if (ret == GNUNET_OK) | 1747 | ret = create_and_copy_friend_files(pg); |
1207 | connect_topology(pg); | 1748 | } |
1208 | else | 1749 | |
1750 | if (ret != GNUNET_OK) | ||
1209 | { | 1751 | { |
1210 | #if VERBOSE_TESTING | 1752 | #if VERBOSE_TESTING |
1211 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1753 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
@@ -1213,10 +1755,419 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET | |||
1213 | #endif | 1755 | #endif |
1214 | return GNUNET_SYSERR; | 1756 | return GNUNET_SYSERR; |
1215 | } | 1757 | } |
1758 | else | ||
1759 | { | ||
1760 | #if VERBOSE_TESTING | ||
1761 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1762 | _("Friend files created/copied successfully!\n")); | ||
1763 | #endif | ||
1764 | } | ||
1765 | |||
1766 | /** | ||
1767 | * Use the create clique method to initially set all connections | ||
1768 | * as blacklisted. | ||
1769 | */ | ||
1770 | create_clique (pg, &blacklist_connections); | ||
1771 | unblacklisted_connections = 0; | ||
1772 | /** | ||
1773 | * Un-blacklist connections as per the topology specified | ||
1774 | */ | ||
1775 | switch (restrict_topology) | ||
1776 | { | ||
1777 | case GNUNET_TESTING_TOPOLOGY_CLIQUE: | ||
1778 | #if VERBOSE_TESTING | ||
1779 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1780 | _("Blacklisting all but clique topology\n")); | ||
1781 | #endif | ||
1782 | unblacklisted_connections = create_clique (pg, &unblacklist_connections); | ||
1783 | break; | ||
1784 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: | ||
1785 | #if VERBOSE_TESTING | ||
1786 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1787 | _("Blacklisting all but small world (ring) topology\n")); | ||
1788 | #endif | ||
1789 | unblacklisted_connections = create_small_world_ring (pg, &unblacklist_connections); | ||
1790 | break; | ||
1791 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: | ||
1792 | #if VERBOSE_TESTING | ||
1793 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1794 | _("Blacklisting all but small world (2d-torus) topology\n")); | ||
1795 | #endif | ||
1796 | unblacklisted_connections = create_small_world (pg, &unblacklist_connections); | ||
1797 | break; | ||
1798 | case GNUNET_TESTING_TOPOLOGY_RING: | ||
1799 | #if VERBOSE_TESTING | ||
1800 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1801 | _("Blacklisting all but ring topology\n")); | ||
1802 | #endif | ||
1803 | unblacklisted_connections = create_ring (pg, &unblacklist_connections); | ||
1804 | break; | ||
1805 | case GNUNET_TESTING_TOPOLOGY_2D_TORUS: | ||
1806 | #if VERBOSE_TESTING | ||
1807 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1808 | _("Blacklisting all but 2d torus topology\n")); | ||
1809 | #endif | ||
1810 | unblacklisted_connections = create_2d_torus (pg, &unblacklist_connections); | ||
1811 | break; | ||
1812 | case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: | ||
1813 | #if VERBOSE_TESTING | ||
1814 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1815 | _("Blacklisting all but Erdos-Renyi topology\n")); | ||
1816 | #endif | ||
1817 | unblacklisted_connections = create_erdos_renyi (pg, &unblacklist_connections); | ||
1818 | break; | ||
1819 | case GNUNET_TESTING_TOPOLOGY_INTERNAT: | ||
1820 | #if VERBOSE_TESTING | ||
1821 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1822 | _("Blacklisting all but InterNAT topology\n")); | ||
1823 | #endif | ||
1824 | unblacklisted_connections = create_nated_internet (pg, &unblacklist_connections); | ||
1825 | break; | ||
1826 | case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: | ||
1827 | #if VERBOSE_TESTING | ||
1828 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1829 | _("Blacklisting all but Scale Free topology\n")); | ||
1830 | #endif | ||
1831 | unblacklisted_connections = create_scale_free (pg, &unblacklist_connections); | ||
1832 | break; | ||
1833 | case GNUNET_TESTING_TOPOLOGY_NONE: | ||
1834 | /* Fall through */ | ||
1835 | default: | ||
1836 | break; | ||
1837 | } | ||
1838 | |||
1839 | if (unblacklisted_connections > 0) | ||
1840 | { | ||
1841 | ret = create_and_copy_blacklist_files(pg); | ||
1842 | if (ret != GNUNET_OK) | ||
1843 | { | ||
1844 | #if VERBOSE_TESTING | ||
1845 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1846 | _("Failed during blacklist file copying!\n")); | ||
1847 | #endif | ||
1848 | return GNUNET_SYSERR; | ||
1849 | } | ||
1850 | else | ||
1851 | { | ||
1852 | #if VERBOSE_TESTING | ||
1853 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1854 | _("Blacklist files created/copied successfully!\n")); | ||
1855 | #endif | ||
1856 | } | ||
1857 | } | ||
1858 | |||
1216 | 1859 | ||
1217 | return num_connections; | 1860 | return num_connections; |
1218 | } | 1861 | } |
1219 | 1862 | ||
1863 | struct RandomContext | ||
1864 | { | ||
1865 | /** | ||
1866 | * The peergroup | ||
1867 | */ | ||
1868 | struct GNUNET_TESTING_PeerGroup *pg; | ||
1869 | |||
1870 | /** | ||
1871 | * uid of the first peer | ||
1872 | */ | ||
1873 | uint32_t first_uid; | ||
1874 | |||
1875 | /** | ||
1876 | * Peer data for first peer. | ||
1877 | */ | ||
1878 | struct PeerData *first; | ||
1879 | |||
1880 | /** | ||
1881 | * Random percentage to use | ||
1882 | */ | ||
1883 | double percentage; | ||
1884 | }; | ||
1885 | |||
1886 | struct MinimumContext | ||
1887 | { | ||
1888 | /** | ||
1889 | * The peergroup | ||
1890 | */ | ||
1891 | struct GNUNET_TESTING_PeerGroup *pg; | ||
1892 | |||
1893 | /** | ||
1894 | * uid of the first peer | ||
1895 | */ | ||
1896 | uint32_t first_uid; | ||
1897 | |||
1898 | /** | ||
1899 | * Peer data for first peer. | ||
1900 | */ | ||
1901 | struct PeerData *first; | ||
1902 | |||
1903 | /** | ||
1904 | * Number of conns per peer | ||
1905 | */ | ||
1906 | unsigned int num_to_add; | ||
1907 | }; | ||
1908 | |||
1909 | /** | ||
1910 | * Iterator for choosing random peers to connect. | ||
1911 | * | ||
1912 | * @param cls closure, a RandomContext | ||
1913 | * @param key the key the second Daemon was stored under | ||
1914 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
1915 | * | ||
1916 | * @return GNUNET_YES to continue iteration | ||
1917 | */ | ||
1918 | static int | ||
1919 | random_connect_iterator (void *cls, | ||
1920 | const GNUNET_HashCode * key, | ||
1921 | void *value) | ||
1922 | { | ||
1923 | struct RandomContext *random_ctx = cls; | ||
1924 | double random_number; | ||
1925 | uint32_t second_pos; | ||
1926 | GNUNET_HashCode first_hash; | ||
1927 | random_number = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK, | ||
1928 | (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL); | ||
1929 | if (random_number < random_ctx->percentage) | ||
1930 | { | ||
1931 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(random_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1932 | } | ||
1933 | /* Now we have considered this particular connection, remove it from the second peer so it's not double counted */ | ||
1934 | uid_from_hash(key, &second_pos); | ||
1935 | hash_from_uid(random_ctx->first_uid, &first_hash); | ||
1936 | GNUNET_assert(random_ctx->pg->total > second_pos); | ||
1937 | GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(random_ctx->pg->peers[second_pos].connect_peers, &first_hash, random_ctx->first->daemon)); | ||
1938 | |||
1939 | return GNUNET_YES; | ||
1940 | } | ||
1941 | |||
1942 | /** | ||
1943 | * Iterator for adding at least X peers to a peers connection set. | ||
1944 | * | ||
1945 | * @param cls closure, MinimumContext | ||
1946 | * @param key the key the second Daemon was stored under | ||
1947 | * @param value the GNUNET_TESTING_Daemon that the first is to connect to | ||
1948 | * | ||
1949 | * @return GNUNET_YES to continue iteration | ||
1950 | */ | ||
1951 | static int | ||
1952 | minimum_connect_iterator (void *cls, | ||
1953 | const GNUNET_HashCode * key, | ||
1954 | void *value) | ||
1955 | { | ||
1956 | struct MinimumContext *min_ctx = cls; | ||
1957 | uint32_t second_pos; | ||
1958 | GNUNET_HashCode first_hash; | ||
1959 | |||
1960 | if (GNUNET_CONTAINER_multihashmap_size(min_ctx->first->connect_peers_working_set) < min_ctx->num_to_add) | ||
1961 | { | ||
1962 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(min_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1963 | GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(min_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1964 | /* Now we have added this particular connection, remove it from the second peer's map so it's not double counted */ | ||
1965 | uid_from_hash(key, &second_pos); | ||
1966 | hash_from_uid(min_ctx->first_uid, &first_hash); | ||
1967 | GNUNET_assert(min_ctx->pg->total > second_pos); | ||
1968 | GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(min_ctx->pg->peers[second_pos].connect_peers, &first_hash, min_ctx->first->daemon)); | ||
1969 | return GNUNET_YES; | ||
1970 | } | ||
1971 | else | ||
1972 | return GNUNET_NO; /* We can stop iterating, we have enough peers! */ | ||
1973 | |||
1974 | |||
1975 | } | ||
1976 | |||
1977 | /** | ||
1978 | * From the set of connections possible, choose percentage percent of connections | ||
1979 | * to actually connect. | ||
1980 | * | ||
1981 | * @param pg the peergroup we are dealing with | ||
1982 | * @param percentage what percent of total connections to make | ||
1983 | */ | ||
1984 | void | ||
1985 | choose_random_connections(struct GNUNET_TESTING_PeerGroup *pg, double percentage) | ||
1986 | { | ||
1987 | struct RandomContext random_ctx; | ||
1988 | uint32_t pg_iter; | ||
1989 | |||
1990 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
1991 | { | ||
1992 | random_ctx.first_uid = pg_iter; | ||
1993 | random_ctx.first = &pg->peers[pg_iter]; | ||
1994 | random_ctx.percentage = percentage; | ||
1995 | pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(pg->total); | ||
1996 | GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &random_connect_iterator, &random_ctx); | ||
1997 | /* Now remove the old connections */ | ||
1998 | GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers); | ||
1999 | /* And replace with the random set */ | ||
2000 | pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set; | ||
2001 | } | ||
2002 | } | ||
2003 | |||
2004 | /** | ||
2005 | * From the set of connections possible, choose at least num connections per | ||
2006 | * peer. | ||
2007 | * | ||
2008 | * @param pg the peergroup we are dealing with | ||
2009 | * @param num how many connections at least should each peer have (if possible)? | ||
2010 | */ | ||
2011 | void | ||
2012 | choose_minimum(struct GNUNET_TESTING_PeerGroup *pg, unsigned int num) | ||
2013 | { | ||
2014 | struct MinimumContext minimum_ctx; | ||
2015 | uint32_t pg_iter; | ||
2016 | |||
2017 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
2018 | { | ||
2019 | pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(num); | ||
2020 | } | ||
2021 | |||
2022 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
2023 | { | ||
2024 | minimum_ctx.first_uid = pg_iter; | ||
2025 | minimum_ctx.first = &pg->peers[pg_iter]; | ||
2026 | minimum_ctx.num_to_add = num; | ||
2027 | pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(pg->total); | ||
2028 | GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &minimum_connect_iterator, &minimum_ctx); | ||
2029 | } | ||
2030 | |||
2031 | for (pg_iter = 0; pg_iter < pg->total; pg_iter++) | ||
2032 | { | ||
2033 | /* Remove the "old" connections */ | ||
2034 | GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers); | ||
2035 | /* And replace with the working set */ | ||
2036 | pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set; | ||
2037 | } | ||
2038 | |||
2039 | } | ||
2040 | |||
2041 | |||
2042 | /* | ||
2043 | * @param pg the peer group struct representing the running peers | ||
2044 | * @param topology which topology to connect the peers in | ||
2045 | * @param options options for connecting the topology | ||
2046 | * @param option_modifier modifier for options that take a parameter | ||
2047 | * | ||
2048 | * There are many ways to connect peers that are supported by this function. | ||
2049 | * To connect peers in the same topology that was created via the | ||
2050 | * GNUNET_TESTING_create_topology, the topology variable must be set to | ||
2051 | * GNUNET_TESTING_TOPOLOGY_NONE. If the topology variable is specified, | ||
2052 | * a new instance of that topology will be generated and attempted to be | ||
2053 | * connected. This could result in some connections being impossible, | ||
2054 | * because some topologies are non-deterministic. | ||
2055 | * | ||
2056 | */ | ||
2057 | int | ||
2058 | GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg, | ||
2059 | enum GNUNET_TESTING_Topology topology, | ||
2060 | enum GNUNET_TESTING_TopologyOption options, | ||
2061 | double option_modifier) | ||
2062 | { | ||
2063 | int num_connections; | ||
2064 | |||
2065 | switch (topology) | ||
2066 | { | ||
2067 | case GNUNET_TESTING_TOPOLOGY_CLIQUE: | ||
2068 | #if VERBOSE_TESTING | ||
2069 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2070 | _("Creating clique topology\n")); | ||
2071 | #endif | ||
2072 | num_connections = create_clique (pg, &add_actual_connections); | ||
2073 | break; | ||
2074 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING: | ||
2075 | #if VERBOSE_TESTING | ||
2076 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2077 | _("Creating small world (ring) topology\n")); | ||
2078 | #endif | ||
2079 | num_connections = create_small_world_ring (pg, &add_actual_connections); | ||
2080 | break; | ||
2081 | case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD: | ||
2082 | #if VERBOSE_TESTING | ||
2083 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2084 | _("Creating small world (2d-torus) topology\n")); | ||
2085 | #endif | ||
2086 | num_connections = create_small_world (pg, &add_actual_connections); | ||
2087 | break; | ||
2088 | case GNUNET_TESTING_TOPOLOGY_RING: | ||
2089 | #if VERBOSE_TESTING | ||
2090 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2091 | _("Creating ring topology\n")); | ||
2092 | #endif | ||
2093 | num_connections = create_ring (pg, &add_actual_connections); | ||
2094 | break; | ||
2095 | case GNUNET_TESTING_TOPOLOGY_2D_TORUS: | ||
2096 | #if VERBOSE_TESTING | ||
2097 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2098 | _("Creating 2d torus topology\n")); | ||
2099 | #endif | ||
2100 | num_connections = create_2d_torus (pg, &add_actual_connections); | ||
2101 | break; | ||
2102 | case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI: | ||
2103 | #if VERBOSE_TESTING | ||
2104 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2105 | _("Creating Erdos-Renyi topology\n")); | ||
2106 | #endif | ||
2107 | num_connections = create_erdos_renyi (pg, &add_actual_connections); | ||
2108 | break; | ||
2109 | case GNUNET_TESTING_TOPOLOGY_INTERNAT: | ||
2110 | #if VERBOSE_TESTING | ||
2111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2112 | _("Creating InterNAT topology\n")); | ||
2113 | #endif | ||
2114 | num_connections = create_nated_internet (pg, &add_actual_connections); | ||
2115 | break; | ||
2116 | case GNUNET_TESTING_TOPOLOGY_SCALE_FREE: | ||
2117 | #if VERBOSE_TESTING | ||
2118 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2119 | _("Creating Scale Free topology\n")); | ||
2120 | #endif | ||
2121 | num_connections = create_scale_free (pg, &add_actual_connections); | ||
2122 | break; | ||
2123 | case GNUNET_TESTING_TOPOLOGY_NONE: | ||
2124 | num_connections = copy_allowed_topology(pg); | ||
2125 | break; | ||
2126 | default: | ||
2127 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unknown topology specification, can't connect peers!\n"); | ||
2128 | return GNUNET_SYSERR; | ||
2129 | } | ||
2130 | |||
2131 | switch (options) | ||
2132 | { | ||
2133 | case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM: /* Create a random subset of total connections based on parameter */ | ||
2134 | choose_random_connections(pg, option_modifier); | ||
2135 | break; | ||
2136 | case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM: /* Create at least X connections per peer (if possible!) */ | ||
2137 | choose_minimum(pg, (unsigned int)option_modifier); | ||
2138 | break; | ||
2139 | case GNUNET_TESTING_TOPOLOGY_OPTION_DFS: /* Choose a random starting point, randomly walk graph, try to get each peer X connections */ | ||
2140 | //choose_dfs(pg, (int)option_modifier); | ||
2141 | break; | ||
2142 | case GNUNET_TESTING_TOPOLOGY_OPTION_NONE: | ||
2143 | /* Fall through */ | ||
2144 | case GNUNET_TESTING_TOPOLOGY_OPTION_ALL: | ||
2145 | /* Fall through */ | ||
2146 | default: | ||
2147 | break; | ||
2148 | } | ||
2149 | |||
2150 | return connect_topology(pg); | ||
2151 | } | ||
2152 | |||
2153 | /** | ||
2154 | * Function which continues a peer group starting up | ||
2155 | * after successfully generating hostkeys for each peer. | ||
2156 | * | ||
2157 | * @param pg the peer group to continue starting | ||
2158 | * | ||
2159 | */ | ||
2160 | void | ||
2161 | GNUNET_TESTING_daemons_continue_startup(struct GNUNET_TESTING_PeerGroup *pg) | ||
2162 | { | ||
2163 | unsigned int i; | ||
2164 | |||
2165 | for (i = 0; i < pg->total; i++) | ||
2166 | { | ||
2167 | GNUNET_TESTING_daemon_continue_startup(pg->peers[i].daemon); | ||
2168 | } | ||
2169 | } | ||
2170 | |||
1220 | /** | 2171 | /** |
1221 | * Start count gnunetd processes with the same set of transports and | 2172 | * Start count gnunetd processes with the same set of transports and |
1222 | * applications. The port numbers (any option called "PORT") will be | 2173 | * applications. The port numbers (any option called "PORT") will be |
@@ -1226,6 +2177,11 @@ GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg, enum GNUNET | |||
1226 | * @param sched scheduler to use | 2177 | * @param sched scheduler to use |
1227 | * @param cfg configuration template to use | 2178 | * @param cfg configuration template to use |
1228 | * @param total number of daemons to start | 2179 | * @param total number of daemons to start |
2180 | * @param hostkey_callback function to call on each peers hostkey generation | ||
2181 | * if NULL, peers will be started by this call, if non-null, | ||
2182 | * GNUNET_TESTING_daemons_continue_startup must be called after | ||
2183 | * successful hostkey generation | ||
2184 | * @param hostkey_cls closure for hostkey callback | ||
1229 | * @param cb function to call on each daemon that was started | 2185 | * @param cb function to call on each daemon that was started |
1230 | * @param cb_cls closure for cb | 2186 | * @param cb_cls closure for cb |
1231 | * @param connect_callback function to call each time two hosts are connected | 2187 | * @param connect_callback function to call each time two hosts are connected |
@@ -1238,6 +2194,8 @@ struct GNUNET_TESTING_PeerGroup * | |||
1238 | GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | 2194 | GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, |
1239 | const struct GNUNET_CONFIGURATION_Handle *cfg, | 2195 | const struct GNUNET_CONFIGURATION_Handle *cfg, |
1240 | unsigned int total, | 2196 | unsigned int total, |
2197 | GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback, | ||
2198 | void *hostkey_cls, | ||
1241 | GNUNET_TESTING_NotifyDaemonRunning cb, | 2199 | GNUNET_TESTING_NotifyDaemonRunning cb, |
1242 | void *cb_cls, | 2200 | void *cb_cls, |
1243 | GNUNET_TESTING_NotifyConnection | 2201 | GNUNET_TESTING_NotifyConnection |
@@ -1366,13 +2324,20 @@ GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched, | |||
1366 | "SERVICEHOME", newservicehome); | 2324 | "SERVICEHOME", newservicehome); |
1367 | GNUNET_free (newservicehome); | 2325 | GNUNET_free (newservicehome); |
1368 | pg->peers[off].cfg = pcfg; | 2326 | pg->peers[off].cfg = pcfg; |
2327 | pg->peers[off].allowed_peers = GNUNET_CONTAINER_multihashmap_create(total); | ||
2328 | pg->peers[off].connect_peers = GNUNET_CONTAINER_multihashmap_create(total); | ||
2329 | pg->peers[off].blacklisted_peers = GNUNET_CONTAINER_multihashmap_create(total); | ||
2330 | pg->peers[off].pg = pg; | ||
1369 | pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched, | 2331 | pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched, |
1370 | pcfg, | 2332 | pcfg, |
1371 | hostname, | 2333 | hostname, |
2334 | hostkey_callback, | ||
2335 | hostkey_cls, | ||
1372 | cb, cb_cls); | 2336 | cb, cb_cls); |
1373 | if (NULL == pg->peers[off].daemon) | 2337 | if (NULL == pg->peers[off].daemon) |
1374 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 2338 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
1375 | _("Could not start peer number %u!\n"), off); | 2339 | _("Could not start peer number %u!\n"), off); |
2340 | |||
1376 | } | 2341 | } |
1377 | return pg; | 2342 | return pg; |
1378 | } | 2343 | } |
@@ -1391,6 +2356,72 @@ GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int pos | |||
1391 | } | 2356 | } |
1392 | 2357 | ||
1393 | /** | 2358 | /** |
2359 | * Prototype of a function that will be called when a | ||
2360 | * particular operation was completed the testing library. | ||
2361 | * | ||
2362 | * @param cls closure | ||
2363 | * @param emsg NULL on success | ||
2364 | */ | ||
2365 | void restart_callback (void *cls, | ||
2366 | const struct GNUNET_PeerIdentity *id, | ||
2367 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
2368 | struct GNUNET_TESTING_Daemon *d, | ||
2369 | const char *emsg) | ||
2370 | { | ||
2371 | struct RestartContext *restart_context = cls; | ||
2372 | |||
2373 | if (emsg == NULL) | ||
2374 | { | ||
2375 | restart_context->peers_restarted++; | ||
2376 | } | ||
2377 | else | ||
2378 | { | ||
2379 | restart_context->peers_restart_failed++; | ||
2380 | } | ||
2381 | |||
2382 | if (restart_context->peers_restarted == restart_context->peer_group->total) | ||
2383 | { | ||
2384 | restart_context->callback(restart_context->callback_cls, NULL); | ||
2385 | GNUNET_free(restart_context); | ||
2386 | } | ||
2387 | else if (restart_context->peers_restart_failed + restart_context->peers_restarted == restart_context->peer_group->total) | ||
2388 | { | ||
2389 | restart_context->callback(restart_context->callback_cls, "Failed to restart peers!"); | ||
2390 | GNUNET_free(restart_context); | ||
2391 | } | ||
2392 | |||
2393 | } | ||
2394 | |||
2395 | /** | ||
2396 | * Restart all peers in the given group. | ||
2397 | * | ||
2398 | * @param pg the handle to the peer group | ||
2399 | * @param timeout how long to wait on failure | ||
2400 | * @param callback function to call on completion (or failure) | ||
2401 | * @param callback_cls closure for the callback function | ||
2402 | */ | ||
2403 | void | ||
2404 | GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_NotifyCompletion callback, void *callback_cls) | ||
2405 | { | ||
2406 | struct RestartContext *restart_context; | ||
2407 | unsigned int off; | ||
2408 | |||
2409 | if (pg->total > 0) | ||
2410 | { | ||
2411 | restart_context = GNUNET_malloc(sizeof(struct RestartContext)); | ||
2412 | restart_context->peer_group = pg; | ||
2413 | restart_context->peers_restarted = 0; | ||
2414 | restart_context->callback = callback; | ||
2415 | restart_context->callback_cls = callback_cls; | ||
2416 | |||
2417 | for (off = 0; off < pg->total; off++) | ||
2418 | { | ||
2419 | GNUNET_TESTING_daemon_restart (pg->peers[off].daemon, &restart_callback, restart_context); | ||
2420 | } | ||
2421 | } | ||
2422 | } | ||
2423 | |||
2424 | /** | ||
1394 | * Shutdown all peers started in the given group. | 2425 | * Shutdown all peers started in the given group. |
1395 | * | 2426 | * |
1396 | * @param pg handle to the peer group | 2427 | * @param pg handle to the peer group |
@@ -1399,8 +2430,6 @@ void | |||
1399 | GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) | 2430 | GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) |
1400 | { | 2431 | { |
1401 | unsigned int off; | 2432 | unsigned int off; |
1402 | struct PeerConnection *pos; | ||
1403 | struct PeerConnection *next; | ||
1404 | 2433 | ||
1405 | for (off = 0; off < pg->total; off++) | 2434 | for (off = 0; off < pg->total; off++) |
1406 | { | 2435 | { |
@@ -1410,17 +2439,13 @@ GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg) | |||
1410 | as well... */ | 2439 | as well... */ |
1411 | 2440 | ||
1412 | if (NULL != pg->peers[off].daemon) | 2441 | if (NULL != pg->peers[off].daemon) |
1413 | GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL); | 2442 | GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL, GNUNET_YES); |
1414 | if (NULL != pg->peers[off].cfg) | 2443 | if (NULL != pg->peers[off].cfg) |
1415 | GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); | 2444 | GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg); |
1416 | 2445 | ||
1417 | pos = pg->peers[off].connected_peers; | 2446 | GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].allowed_peers); |
1418 | while (pos != NULL) | 2447 | GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].connect_peers); |
1419 | { | 2448 | GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].blacklisted_peers); |
1420 | next = pos->next; | ||
1421 | GNUNET_free(pos); | ||
1422 | pos = next; | ||
1423 | } | ||
1424 | 2449 | ||
1425 | } | 2450 | } |
1426 | GNUNET_free (pg->peers); | 2451 | GNUNET_free (pg->peers); |