diff options
author | Bart Polot <bart@net.in.tum.de> | 2011-09-16 15:23:32 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2011-09-16 15:23:32 +0000 |
commit | c8dce9e10f91f76095eb9620f9e85af6dcd2b1d3 (patch) | |
tree | f65c47b3aa2401543a6b21027f1f038ff9b95db8 /src | |
parent | c90957f078692b28d99b330a485a3f2becfa89bb (diff) | |
download | gnunet-c8dce9e10f91f76095eb9620f9e85af6dcd2b1d3.tar.gz gnunet-c8dce9e10f91f76095eb9620f9e85af6dcd2b1d3.zip |
Changed path management
- Peers now have a set of individual paths to reach them
- Tunnels have a tree of the paths in the tunnel to reach all peers in the tunnel in an efficent way, allowing to add peers efficiently taking in account existing paths and having each tunnel reach a peer on a different path.
- Adapted helper functions, periodic announcements, etc to new structure
Added initial support for link disconnection notification and readjustment
Diffstat (limited to 'src')
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 1259 |
1 files changed, 792 insertions, 467 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index d903e7584..edbad550a 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -90,65 +90,134 @@ mesh_debug (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
90 | GNUNET_TIME_UNIT_SECONDS,\ | 90 | GNUNET_TIME_UNIT_SECONDS,\ |
91 | 5) | 91 | 5) |
92 | 92 | ||
93 | |||
94 | |||
95 | /******************************************************************************/ | 93 | /******************************************************************************/ |
96 | /************************ DATA STRUCTURES ****************************/ | 94 | /************************ ENUMERATIONS ****************************/ |
97 | /******************************************************************************/ | 95 | /******************************************************************************/ |
98 | 96 | ||
99 | /** | 97 | /** |
100 | * Information regarding a path | 98 | * All the states a peer participating in a tunnel can be in. |
101 | */ | 99 | */ |
102 | struct MeshPath | 100 | enum MeshPeerState |
103 | { | 101 | { |
102 | /** | ||
103 | * Peer only retransmits traffic, is not a final destination | ||
104 | */ | ||
105 | MESH_PEER_RELAY, | ||
104 | 106 | ||
105 | /** | 107 | /** |
106 | * Linked list | 108 | * Path to the peer not known yet |
107 | */ | 109 | */ |
108 | struct MeshPath *next; | 110 | MESH_PEER_SEARCHING, |
109 | struct MeshPath *prev; | ||
110 | 111 | ||
111 | /** | 112 | /** |
112 | * Whether the path is serving traffic in a tunnel or is a backup | 113 | * Request sent, not yet answered. |
113 | */ | 114 | */ |
114 | int in_use; | 115 | MESH_PEER_WAITING, |
115 | 116 | ||
116 | /** | 117 | /** |
117 | * List of all the peers that form the path from origin to target | 118 | * Peer connected and ready to accept data |
118 | */ | 119 | */ |
119 | GNUNET_PEER_Id *peers; | 120 | MESH_PEER_READY, |
120 | 121 | ||
121 | /** | 122 | /** |
122 | * Number of peers (hops) in the path | 123 | * Peer connected previosly but not responding |
123 | */ | 124 | */ |
124 | unsigned int length; | 125 | MESH_PEER_RECONNECTING |
125 | }; | 126 | }; |
126 | 127 | ||
127 | 128 | ||
129 | /******************************************************************************/ | ||
130 | /************************ DATA STRUCTURES ****************************/ | ||
131 | /******************************************************************************/ | ||
132 | |||
128 | /** | 133 | /** |
129 | * All the states a peer participating in a tunnel can be in. | 134 | * Information regarding a possible path to reach a single peer |
130 | */ | 135 | */ |
131 | enum MeshPeerState | 136 | struct MeshPeerPath |
132 | { | 137 | { |
138 | |||
133 | /** | 139 | /** |
134 | * Path to the peer not known yet | 140 | * Linked list |
135 | */ | 141 | */ |
136 | MESH_PEER_SEARCHING, | 142 | struct MeshPeerPath *next; |
143 | struct MeshPeerPath *prev; | ||
137 | 144 | ||
138 | /** | 145 | /** |
139 | * Request sent, not yet answered. | 146 | * List of all the peers that form the path from origin to target. |
140 | */ | 147 | */ |
141 | MESH_PEER_WAITING, | 148 | GNUNET_PEER_Id *peers; |
142 | 149 | ||
143 | /** | 150 | /** |
144 | * Peer connected and ready to accept data | 151 | * Number of peers (hops) in the path |
145 | */ | 152 | */ |
146 | MESH_PEER_READY, | 153 | unsigned int length; |
154 | |||
155 | }; | ||
156 | |||
157 | |||
158 | /** | ||
159 | * Node of path tree for a tunnel | ||
160 | */ | ||
161 | struct MeshTunnelPathNode | ||
162 | { | ||
163 | /** | ||
164 | * Tunnel this node belongs to (and therefore tree) | ||
165 | */ | ||
166 | struct MeshTunnel *t; | ||
167 | |||
168 | /** | ||
169 | * Peer this node describes | ||
170 | */ | ||
171 | struct MeshPeerInfo *peer; | ||
172 | |||
173 | /** | ||
174 | * Parent node in the tree | ||
175 | */ | ||
176 | struct MeshTunnelPathNode *parent; | ||
177 | |||
178 | /** | ||
179 | * Array of children | ||
180 | */ | ||
181 | struct MeshTunnelPathNode *children; | ||
182 | |||
183 | /** | ||
184 | * Number of children | ||
185 | */ | ||
186 | unsigned int nchildren; | ||
147 | 187 | ||
148 | /** | 188 | /** |
149 | * Peer connected previosly but not responding | 189 | * Status of the peer in the tunnel |
150 | */ | 190 | */ |
151 | MESH_PEER_RECONNECTING | 191 | enum MeshPeerState status; |
192 | }; | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Tree to reach all peers in the tunnel | ||
197 | */ | ||
198 | struct MeshTunnelPath | ||
199 | { | ||
200 | /** | ||
201 | * Tunnel this path belongs to | ||
202 | */ | ||
203 | struct MeshTunnel *t; | ||
204 | |||
205 | /** | ||
206 | * Root node of peer tree | ||
207 | */ | ||
208 | struct MeshTunnelPathNode *root; | ||
209 | |||
210 | /** | ||
211 | * Node that represents our position in the tree (for non local tunnels) | ||
212 | */ | ||
213 | struct MeshTunnelPathNode *me; | ||
214 | |||
215 | /** | ||
216 | * Cache of all peers and the first hop to them. | ||
217 | * Indexed by Peer_Identity, contains a pointer to the PeerInfo of 1st hop. | ||
218 | */ | ||
219 | struct GNUNET_CONTAINER_MultiHashMap *first_hops; | ||
220 | |||
152 | }; | 221 | }; |
153 | 222 | ||
154 | 223 | ||
@@ -197,11 +266,6 @@ struct MeshPeerInfo | |||
197 | GNUNET_PEER_Id id; | 266 | GNUNET_PEER_Id id; |
198 | 267 | ||
199 | /** | 268 | /** |
200 | * Is the peer reachable? Is the peer even connected? | ||
201 | */ | ||
202 | enum MeshPeerState state; | ||
203 | |||
204 | /** | ||
205 | * Last time we heard from this peer | 269 | * Last time we heard from this peer |
206 | */ | 270 | */ |
207 | struct GNUNET_TIME_Absolute last_contact; | 271 | struct GNUNET_TIME_Absolute last_contact; |
@@ -212,10 +276,14 @@ struct MeshPeerInfo | |||
212 | int n_reconnect_attempts; | 276 | int n_reconnect_attempts; |
213 | 277 | ||
214 | /** | 278 | /** |
215 | * Paths to reach the peer | 279 | * Paths to reach the peer, ordered by ascending hop count |
216 | */ | 280 | */ |
217 | struct MeshPath *path; | 281 | struct MeshPeerPath *path_head; |
218 | struct MeshPath *path_tail; | 282 | |
283 | /** | ||
284 | * Paths to reach the peer, ordered by ascending hop count | ||
285 | */ | ||
286 | struct MeshPeerPath *path_tail; | ||
219 | 287 | ||
220 | /** | 288 | /** |
221 | * Handle to stop the DHT search for a path to this peer | 289 | * Handle to stop the DHT search for a path to this peer |
@@ -233,9 +301,17 @@ struct MeshPeerInfo | |||
233 | struct MeshDataDescriptor *infos[CORE_QUEUE_SIZE]; | 301 | struct MeshDataDescriptor *infos[CORE_QUEUE_SIZE]; |
234 | 302 | ||
235 | /** | 303 | /** |
236 | * Task to send keepalive packets over the current active path | 304 | * Array of tunnels this peer participates in |
305 | * (most probably a small amount, therefore not a hashmap) | ||
306 | * When the path to the peer changes, notify these tunnels to let them | ||
307 | * re-adjust their path trees. | ||
237 | */ | 308 | */ |
238 | GNUNET_SCHEDULER_TaskIdentifier path_refresh_task; | 309 | struct MeshTunnel **tunnels; |
310 | |||
311 | /** | ||
312 | * Number of tunnels above | ||
313 | */ | ||
314 | unsigned int ntunnels; | ||
239 | }; | 315 | }; |
240 | 316 | ||
241 | 317 | ||
@@ -336,7 +412,6 @@ struct MeshTunnel | |||
336 | */ | 412 | */ |
337 | unsigned int peers_total; | 413 | unsigned int peers_total; |
338 | 414 | ||
339 | |||
340 | /** | 415 | /** |
341 | * Client owner of the tunnel, if any | 416 | * Client owner of the tunnel, if any |
342 | */ | 417 | */ |
@@ -348,8 +423,40 @@ struct MeshTunnel | |||
348 | struct MeshQueue *queue_head; | 423 | struct MeshQueue *queue_head; |
349 | struct MeshQueue *queue_tail; | 424 | struct MeshQueue *queue_tail; |
350 | 425 | ||
426 | /** | ||
427 | * Tunnel paths | ||
428 | */ | ||
429 | struct MeshTunnelPath *paths; | ||
430 | |||
431 | /** | ||
432 | * Task to keep the used paths alive | ||
433 | */ | ||
434 | GNUNET_SCHEDULER_TaskIdentifier path_refresh_task; | ||
435 | }; | ||
436 | |||
437 | |||
438 | /** | ||
439 | * Info needed to work with tunnel paths and peers | ||
440 | */ | ||
441 | struct MeshPathInfo | ||
442 | { | ||
443 | /** | ||
444 | * Tunnel | ||
445 | */ | ||
446 | struct MeshTunnel *t; | ||
447 | |||
448 | /** | ||
449 | * Destination peer | ||
450 | */ | ||
451 | struct MeshPeerInfo *peer; | ||
452 | |||
453 | /** | ||
454 | * Path itself | ||
455 | */ | ||
456 | struct MeshPeerPath *path; | ||
351 | }; | 457 | }; |
352 | 458 | ||
459 | |||
353 | /** | 460 | /** |
354 | * Struct containing information about a client of the service | 461 | * Struct containing information about a client of the service |
355 | */ | 462 | */ |
@@ -382,7 +489,7 @@ struct MeshClient | |||
382 | struct GNUNET_CONTAINER_MultiHashMap *types; | 489 | struct GNUNET_CONTAINER_MultiHashMap *types; |
383 | 490 | ||
384 | /** | 491 | /** |
385 | * Used for seachching peers offering a service | 492 | * Used to search peers offering a service |
386 | */ | 493 | */ |
387 | struct GNUNET_DHT_GetHandle *dht_get_type; | 494 | struct GNUNET_DHT_GetHandle *dht_get_type; |
388 | 495 | ||
@@ -465,17 +572,151 @@ GNUNET_SCHEDULER_TaskIdentifier announce_id_task; | |||
465 | 572 | ||
466 | 573 | ||
467 | /******************************************************************************/ | 574 | /******************************************************************************/ |
575 | /************************ PERIODIC FUNCTIONS ****************************/ | ||
576 | /******************************************************************************/ | ||
577 | |||
578 | /** | ||
579 | * Announce iterator over for each application provided by the peer | ||
580 | * | ||
581 | * @param cls closure | ||
582 | * @param key current key code | ||
583 | * @param value value in the hash map | ||
584 | * @return GNUNET_YES if we should continue to | ||
585 | * iterate, | ||
586 | * GNUNET_NO if not. | ||
587 | */ | ||
588 | static int | ||
589 | announce_application (void *cls, const GNUNET_HashCode * key, void *value) | ||
590 | { | ||
591 | /* FIXME are hashes in multihash map equal on all aquitectures? */ | ||
592 | GNUNET_DHT_put (dht_handle, key, 10U, GNUNET_DHT_RO_RECORD_ROUTE, | ||
593 | GNUNET_BLOCK_TYPE_TEST, sizeof (struct GNUNET_PeerIdentity), | ||
594 | (const char *) &my_full_id, | ||
595 | #if MESH_DEBUG | ||
596 | GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL, | ||
597 | &mesh_debug, "DHT_put for app completed"); | ||
598 | #else | ||
599 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
600 | APP_ANNOUNCE_TIME), | ||
601 | APP_ANNOUNCE_TIME, | ||
602 | NULL, NULL); | ||
603 | #endif | ||
604 | return GNUNET_OK; | ||
605 | } | ||
606 | |||
607 | |||
608 | /** | ||
609 | * Periodically announce what applications are provided by local clients | ||
610 | * | ||
611 | * @param cls closure | ||
612 | * @param tc task context | ||
613 | */ | ||
614 | static void | ||
615 | announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
616 | { | ||
617 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
618 | { | ||
619 | announce_applications_task = GNUNET_SCHEDULER_NO_TASK; | ||
620 | return; | ||
621 | } | ||
622 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Starting PUT for apps\n"); | ||
623 | GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application, | ||
624 | NULL); | ||
625 | announce_applications_task = | ||
626 | GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME, &announce_applications, | ||
627 | cls); | ||
628 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Finished PUT for apps\n"); | ||
629 | return; | ||
630 | } | ||
631 | |||
632 | |||
633 | /** | ||
634 | * Periodically announce self id in the DHT | ||
635 | * | ||
636 | * @param cls closure | ||
637 | * @param tc task context | ||
638 | */ | ||
639 | static void | ||
640 | announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
641 | { | ||
642 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
643 | { | ||
644 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; | ||
645 | return; | ||
646 | } | ||
647 | /* TODO | ||
648 | * - Set data expiration in function of X | ||
649 | * - Adapt X to churn | ||
650 | */ | ||
651 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
652 | &my_full_id.hashPubKey, /* Key to use */ | ||
653 | 10U, /* Replication level */ | ||
654 | GNUNET_DHT_RO_RECORD_ROUTE, /* DHT options */ | ||
655 | GNUNET_BLOCK_TYPE_TEST, /* Block type */ | ||
656 | 0, /* Size of the data */ | ||
657 | NULL, /* Data itself */ | ||
658 | GNUNET_TIME_absolute_get_forever (), /* Data expiration */ | ||
659 | GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */ | ||
660 | #if MESH_DEBUG | ||
661 | &mesh_debug, "DHT_put for id completed"); | ||
662 | #else | ||
663 | NULL, /* Continuation */ | ||
664 | NULL); /* Continuation closure */ | ||
665 | #endif | ||
666 | announce_id_task = | ||
667 | GNUNET_SCHEDULER_add_delayed (ID_ANNOUNCE_TIME, &announce_id, cls); | ||
668 | } | ||
669 | |||
670 | |||
671 | /** | ||
672 | * Send keepalive packets for a peer | ||
673 | * | ||
674 | * @param cls unused | ||
675 | * @param tc unused | ||
676 | * | ||
677 | * FIXME path | ||
678 | */ | ||
679 | static void | ||
680 | path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
681 | { | ||
682 | struct MeshTunnel *t = cls; | ||
683 | // struct GNUNET_PeerIdentity id; | ||
684 | |||
685 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
686 | { | ||
687 | return; | ||
688 | } | ||
689 | /* FIXME implement multicast keepalive. Just an empty multicast packet? */ | ||
690 | // GNUNET_PEER_resolve (path_get_first_hop (path->t, path->peer)->id, &id); | ||
691 | // GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | ||
692 | // GNUNET_TIME_UNIT_FOREVER_REL, &id, | ||
693 | // sizeof (struct GNUNET_MESH_ManipulatePath) | ||
694 | // + | ||
695 | // (path->path->length * | ||
696 | // sizeof (struct GNUNET_PeerIdentity)), | ||
697 | // &send_core_create_path, | ||
698 | // t); | ||
699 | t->path_refresh_task = | ||
700 | GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, | ||
701 | t); | ||
702 | return; | ||
703 | } | ||
704 | |||
705 | |||
706 | /******************************************************************************/ | ||
468 | /****************** GENERAL HELPER FUNCTIONS ************************/ | 707 | /****************** GENERAL HELPER FUNCTIONS ************************/ |
469 | /******************************************************************************/ | 708 | /******************************************************************************/ |
470 | 709 | ||
471 | /** | 710 | /** |
472 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one | 711 | * Retrieve the MeshPeerInfo stucture associated with the peer, create one |
473 | * and insert it in the appropiate structures if the peer is not known yet. | 712 | * and insert it in the appropiate structures if the peer is not known yet. |
713 | * | ||
474 | * @param peer Identity of the peer | 714 | * @param peer Identity of the peer |
715 | * | ||
475 | * @return Existing or newly created peer info | 716 | * @return Existing or newly created peer info |
476 | */ | 717 | */ |
477 | static struct MeshPeerInfo * | 718 | static struct MeshPeerInfo * |
478 | get_peer_info (const struct GNUNET_PeerIdentity *peer) | 719 | peer_info_get (const struct GNUNET_PeerIdentity *peer) |
479 | { | 720 | { |
480 | struct MeshPeerInfo *peer_info; | 721 | struct MeshPeerInfo *peer_info; |
481 | 722 | ||
@@ -487,62 +728,84 @@ get_peer_info (const struct GNUNET_PeerIdentity *peer) | |||
487 | GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info, | 728 | GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info, |
488 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | 729 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); |
489 | peer_info->id = GNUNET_PEER_intern (peer); | 730 | peer_info->id = GNUNET_PEER_intern (peer); |
490 | peer_info->state = MESH_PEER_SEARCHING; | ||
491 | } | 731 | } |
492 | 732 | ||
493 | return peer_info; | 733 | return peer_info; |
494 | } | 734 | } |
495 | 735 | ||
736 | |||
737 | #if LATER | ||
496 | /** | 738 | /** |
497 | * Find the first peer whom to send a packet to go down this path | 739 | * Destroy the peer_info and free any allocated resources linked to it |
498 | * @param path The path to use | 740 | * @param t tunnel the path belongs to |
499 | * @return short id of the next peer, myid in case of local delivery, | 741 | * @param pi the peer_info to destroy |
500 | * or 0 in case of error | 742 | * @return GNUNET_OK on success |
501 | */ | 743 | */ |
502 | static GNUNET_PEER_Id | 744 | static int |
503 | get_first_hop (struct MeshPath *path) | 745 | peer_info_destroy (struct MeshPeerInfo *pi) |
504 | { | 746 | { |
505 | unsigned int i; | 747 | GNUNET_HashCode hash; |
748 | struct GNUNET_PeerIdentity id; | ||
506 | 749 | ||
507 | while (NULL != path) | 750 | GNUNET_PEER_resolve (pi->id, &id); |
508 | { | 751 | GNUNET_PEER_change_rc (pi->id, -1); |
509 | if (path->in_use) | 752 | GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &hash); |
510 | break; | ||
511 | path = path->next; | ||
512 | } | ||
513 | if (NULL == path) | ||
514 | { | ||
515 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
516 | "tried to get the next hop from an invalid path\n"); | ||
517 | return 0; | ||
518 | } | ||
519 | 753 | ||
520 | for (i = 0; i < path->length; i++) | 754 | GNUNET_CONTAINER_multihashmap_remove (peers, &hash, pi); |
521 | { | 755 | GNUNET_SCHEDULER_cancel (pi->path_refresh_task); |
522 | if (path->peers[i] == myid) | 756 | GNUNET_free (pi); |
523 | { | 757 | return GNUNET_OK; |
524 | if (i < path->length - 1) | ||
525 | { | ||
526 | return path->peers[i + 1]; | ||
527 | } | ||
528 | else | ||
529 | { | ||
530 | return myid; | ||
531 | } | ||
532 | } | ||
533 | } | ||
534 | return 0; | ||
535 | } | 758 | } |
759 | #endif | ||
536 | 760 | ||
537 | 761 | ||
538 | /** | 762 | /** |
539 | * Get the cost of the path. | 763 | * Destroy the path and free any allocated resources linked to it |
540 | * @param path The path to analyze | 764 | * |
541 | * @return Number of hops to reach destination, UINT_MAX in case the peer is not | 765 | * @param p the path to destroy |
542 | * in the path | 766 | * |
767 | * @return GNUNET_OK on success | ||
768 | */ | ||
769 | static int | ||
770 | path_destroy (struct MeshPeerPath *p) | ||
771 | { | ||
772 | GNUNET_PEER_decrement_rcs (p->peers, p->length); | ||
773 | GNUNET_free (p->peers); | ||
774 | GNUNET_free (p); | ||
775 | return GNUNET_OK; | ||
776 | } | ||
777 | |||
778 | |||
779 | /** | ||
780 | * Find the first peer whom to send a packet to go down this path | ||
781 | * | ||
782 | * @param t The tunnel to use | ||
783 | * @param peer The peerinfo of the peer we are trying to reach | ||
784 | * | ||
785 | * @return peerinfo of the peer who is the first hop in the tunnel | ||
786 | * NULL on error | ||
787 | */ | ||
788 | static struct MeshPeerInfo * | ||
789 | path_get_first_hop (struct MeshTunnel *t, struct MeshPeerInfo *peer) | ||
790 | { | ||
791 | struct GNUNET_PeerIdentity id; | ||
792 | |||
793 | GNUNET_PEER_resolve(peer->id, &id); | ||
794 | return GNUNET_CONTAINER_multihashmap_get(t->paths->first_hops, | ||
795 | &id.hashPubKey); | ||
796 | } | ||
797 | |||
798 | |||
799 | /** | ||
800 | * Get the length of a path | ||
801 | * | ||
802 | * @param path The path to measure, with the local peer at any point of it | ||
803 | * | ||
804 | * @return Number of hops to reach destination | ||
805 | * UINT_MAX in case the peer is not in the path | ||
543 | */ | 806 | */ |
544 | static unsigned int | 807 | static unsigned int |
545 | get_path_cost (struct MeshPath *path) | 808 | path_get_length (struct MeshPeerPath *path) |
546 | { | 809 | { |
547 | unsigned int i; | 810 | unsigned int i; |
548 | 811 | ||
@@ -560,61 +823,136 @@ get_path_cost (struct MeshPath *path) | |||
560 | 823 | ||
561 | 824 | ||
562 | /** | 825 | /** |
826 | * Get the cost of the path relative to the already built tunnel tree | ||
827 | * | ||
828 | * @param t The tunnel to which compare | ||
829 | * @param path The individual path to reach a peer | ||
830 | * | ||
831 | * @return Number of hops to reach destination, UINT_MAX in case the peer is not | ||
832 | * in the path | ||
833 | * | ||
834 | * TODO: remove dummy implementation, look into the tunnel tree | ||
835 | */ | ||
836 | static unsigned int | ||
837 | path_get_cost (struct MeshTunnel *t, struct MeshPeerPath *path) | ||
838 | { | ||
839 | return path_get_length(path); | ||
840 | } | ||
841 | |||
842 | |||
843 | /** | ||
563 | * Add the path to the peer and update the path used to reach it in case this | 844 | * Add the path to the peer and update the path used to reach it in case this |
564 | * is the shortest. | 845 | * is the shortest. |
846 | * | ||
565 | * @param peer_info Destination peer to add the path to. | 847 | * @param peer_info Destination peer to add the path to. |
566 | * @param path New path to add. Last peer must be the peer in arg 1. | 848 | * @param path New path to add. Last peer must be the peer in arg 1. |
849 | * | ||
850 | * TODO: trim the part from origin to us? Add it as path to origin? | ||
567 | */ | 851 | */ |
568 | static void | 852 | static void |
569 | add_path_to_peer (struct MeshPeerInfo *peer_info, struct MeshPath *path) | 853 | path_add_to_peer (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path) |
570 | { | 854 | { |
571 | unsigned int i; | 855 | unsigned int l; |
572 | unsigned int new_cost; | 856 | struct MeshPeerPath *aux; |
573 | unsigned int best_cost; | ||
574 | struct MeshPath *aux; | ||
575 | struct MeshPath *best; | ||
576 | 857 | ||
577 | if (NULL == peer_info || NULL == path) | 858 | if (NULL == peer_info || NULL == path) |
859 | { | ||
860 | GNUNET_break (0); | ||
578 | return; | 861 | return; |
862 | } | ||
579 | 863 | ||
580 | new_cost = get_path_cost (path); | 864 | l = path_get_length (path); |
581 | best_cost = UINT_MAX; | 865 | |
582 | best = NULL; | 866 | for (aux = peer_info->path_head; aux != NULL; aux = aux->next) |
583 | for (aux = peer_info->path; aux != NULL; aux = aux->next) | ||
584 | { | 867 | { |
585 | if ((i = get_path_cost (aux)) < best_cost) | 868 | if (path_get_length (aux) > l) |
586 | { | 869 | { |
587 | best = aux; | 870 | GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head, |
588 | best_cost = i; | 871 | peer_info->path_tail, |
872 | aux, | ||
873 | path); | ||
589 | } | 874 | } |
590 | } | 875 | } |
591 | if (best_cost < new_cost) | 876 | GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, |
877 | peer_info->path_tail, | ||
878 | path); | ||
879 | return; | ||
880 | } | ||
881 | |||
882 | |||
883 | /** | ||
884 | * Notify a tunnel that a connection has broken that affects at least | ||
885 | * some of its peers. | ||
886 | * | ||
887 | * @param t Tunnel affected | ||
888 | * @param peer Peer that (at least) has been affected by the disconnection | ||
889 | * @param p1 Peer that got disconnected from p2 | ||
890 | * @param p2 Peer that got disconnected from p1 | ||
891 | */ | ||
892 | static void | ||
893 | tunnel_notify_connection_broken(struct MeshTunnel *t, | ||
894 | struct MeshPeerInfo *peer, | ||
895 | GNUNET_PEER_Id p1, | ||
896 | GNUNET_PEER_Id p2); | ||
897 | |||
898 | |||
899 | /** | ||
900 | * Remove all paths that rely on a direct connection between p1 and p2 | ||
901 | * from the peer itself and notify all tunnels about it. | ||
902 | * | ||
903 | * @param pi PeerInfo of affected peer | ||
904 | * @param p1 GNUNET_PEER_Id of one peer. | ||
905 | * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and | ||
906 | * no longer is. | ||
907 | */ | ||
908 | static void | ||
909 | path_remove_from_peer (struct MeshPeerInfo *peer, | ||
910 | GNUNET_PEER_Id p1, | ||
911 | GNUNET_PEER_Id p2) | ||
912 | { | ||
913 | struct MeshPeerPath *p; | ||
914 | struct MeshPeerPath *aux; | ||
915 | unsigned int destroyed; | ||
916 | unsigned int i; | ||
917 | |||
918 | destroyed = 0; | ||
919 | p = peer->path_head; | ||
920 | while (NULL != p) | ||
592 | { | 921 | { |
593 | path->in_use = 0; | 922 | aux = p->next; |
594 | GNUNET_CONTAINER_DLL_insert_tail (peer_info->path, peer_info->path_tail, | 923 | for (i = 0; i < (p->length - 1); i++) |
595 | path); | 924 | { |
925 | if ((p->peers[i] == p1 && p->peers[i + 1] == p2) || | ||
926 | (p->peers[i] == p2 && p->peers[i + 1] == p1)) | ||
927 | { | ||
928 | path_destroy(p); | ||
929 | destroyed++; | ||
930 | break; | ||
931 | } | ||
932 | } | ||
933 | p = aux; | ||
596 | } | 934 | } |
597 | else | 935 | if (0 == destroyed) |
936 | return; | ||
937 | |||
938 | for (i = 0; i < peer->ntunnels; i++) | ||
598 | { | 939 | { |
599 | if (NULL != best) | 940 | tunnel_notify_connection_broken(peer->tunnels[i], peer, p1, p2); |
600 | best->in_use = 0; | ||
601 | path->in_use = 1; | ||
602 | GNUNET_CONTAINER_DLL_insert (peer_info->path, peer_info->path_tail, path); | ||
603 | } | 941 | } |
604 | return; | ||
605 | } | 942 | } |
606 | 943 | ||
607 | 944 | ||
608 | /** | 945 | /** |
609 | * Add the path to the peer and update the path used to reach it in case this | 946 | * Add the path to the origin peer and update the path used to reach it in case |
610 | * is the shortest. The path is given in reverse, the destination peer is | 947 | * this is the shortest. |
611 | * path[0]. The function modifies the path, inverting it to use the origin as | 948 | * The path is given in peer_info -> destination, therefore we turn the path |
612 | * destination. | 949 | * upside down first. |
613 | * @param peer_info Destination peer to add the path to. | 950 | * |
614 | * @param path New path to add. First peer must be the peer in arg 1. | 951 | * @param peer_info Peer to add the path to, being the origin of the path. |
952 | * @param path New path to add after being inversed. | ||
615 | */ | 953 | */ |
616 | static void | 954 | static void |
617 | add_path_to_origin (struct MeshPeerInfo *peer_info, struct MeshPath *path) | 955 | path_add_to_origin (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path) |
618 | { | 956 | { |
619 | GNUNET_PEER_Id aux; | 957 | GNUNET_PEER_Id aux; |
620 | unsigned int i; | 958 | unsigned int i; |
@@ -625,17 +963,138 @@ add_path_to_origin (struct MeshPeerInfo *peer_info, struct MeshPath *path) | |||
625 | path->peers[i] = path->peers[path->length - i - 1]; | 963 | path->peers[i] = path->peers[path->length - i - 1]; |
626 | path->peers[path->length - i - 1] = aux; | 964 | path->peers[path->length - i - 1] = aux; |
627 | } | 965 | } |
628 | add_path_to_peer (peer_info, path); | 966 | path_add_to_peer (peer_info, path); |
967 | } | ||
968 | |||
969 | /** | ||
970 | * Integrate a stand alone path into the tunnel tree. | ||
971 | * | ||
972 | * @param t Tunnel where to add the new path. | ||
973 | * @param p Path to be integrated. | ||
974 | * | ||
975 | * @return GNUNET_OK in case of success. | ||
976 | * GNUNET_SYSERR in case of error. | ||
977 | * | ||
978 | * FIXME path: remove old path to the same peer if needed | ||
979 | */ | ||
980 | static int | ||
981 | path_add_to_tunnel(struct MeshTunnel *t, struct MeshPeerPath *p) | ||
982 | { | ||
983 | struct MeshTunnelPathNode *parent; | ||
984 | struct MeshTunnelPathNode *n; | ||
985 | struct GNUNET_PeerIdentity id; | ||
986 | struct GNUNET_PeerIdentity hop; | ||
987 | int me; | ||
988 | unsigned int i; | ||
989 | unsigned int j; | ||
990 | |||
991 | n = t->paths->root; | ||
992 | if (n->peer->id != p->peers[0]) | ||
993 | { | ||
994 | GNUNET_break (0); | ||
995 | return GNUNET_SYSERR; | ||
996 | } | ||
997 | /* Assuming that the tree is somewhat balanced, O((log n * log N). | ||
998 | * - Length of the path is expected to be log N (size of whole network). | ||
999 | * - Each level of the tree is expected to have log n children (size of tree). | ||
1000 | */ | ||
1001 | for (i = 1, me = -1; i < p->length; i++) | ||
1002 | { | ||
1003 | parent = n; | ||
1004 | if (p->peers[i] == myid) | ||
1005 | me = i; | ||
1006 | for (j = 0; j < n->nchildren; j++) | ||
1007 | { | ||
1008 | if (n->children[j].peer->id == p->peers[i]) | ||
1009 | { | ||
1010 | n = &n->children[j]; | ||
1011 | break; | ||
1012 | } | ||
1013 | } | ||
1014 | /* If we couldn't find a child equal to path[i], we have reached the end | ||
1015 | * of the common path. */ | ||
1016 | if (parent == n) | ||
1017 | break; | ||
1018 | } | ||
1019 | if (-1 == me) | ||
1020 | { | ||
1021 | GNUNET_break (0); | ||
1022 | return GNUNET_SYSERR; | ||
1023 | } | ||
1024 | /* Add the rest of the path as a branch from parent. */ | ||
1025 | while (i < p->length) | ||
1026 | { | ||
1027 | parent->children = GNUNET_realloc(parent->children, parent->nchildren); | ||
1028 | parent->nchildren++; | ||
1029 | GNUNET_PEER_resolve(p->peers[i], &id); | ||
1030 | n->peer = peer_info_get(&id); | ||
1031 | n->parent = parent; | ||
1032 | n->t = t; | ||
1033 | i++; | ||
1034 | } | ||
1035 | /* Add info about first hop into hashmap. */ | ||
1036 | if (me < p->length - 1) | ||
1037 | { | ||
1038 | GNUNET_PEER_resolve(p->peers[p->length - 1], &id); | ||
1039 | GNUNET_PEER_resolve(p->peers[me + 1], &hop); | ||
1040 | GNUNET_CONTAINER_multihashmap_put( | ||
1041 | t->paths->first_hops, | ||
1042 | &id.hashPubKey, | ||
1043 | peer_info_get(&hop), | ||
1044 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1045 | } | ||
1046 | return GNUNET_OK; | ||
1047 | } | ||
1048 | |||
1049 | |||
1050 | /** | ||
1051 | * Build a PeerPath from the paths returned from the DHT, reversing the paths | ||
1052 | * to obtain a local peer -> destination path and interning the peer ids. | ||
1053 | * | ||
1054 | * @param get_path NULL-terminated array of pointers | ||
1055 | * to the peers on reverse GET path (or NULL if not recorded) | ||
1056 | * @param put_path NULL-terminated array of pointers | ||
1057 | * to the peers on the PUT path (or NULL if not recorded) | ||
1058 | * | ||
1059 | * @return Newly allocated and created path | ||
1060 | */ | ||
1061 | static struct MeshPeerPath * | ||
1062 | path_build_from_dht(const struct GNUNET_PeerIdentity *const *get_path, | ||
1063 | const struct GNUNET_PeerIdentity *const *put_path) | ||
1064 | { | ||
1065 | struct MeshPeerPath *p; | ||
1066 | int i; | ||
1067 | |||
1068 | p = GNUNET_malloc (sizeof (struct MeshPeerPath)); | ||
1069 | for (i = 0; get_path[i] != NULL; i++) ; | ||
1070 | for (i--; i >= 0; i--) | ||
1071 | { | ||
1072 | p->peers = | ||
1073 | GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1)); | ||
1074 | p->peers[p->length] = GNUNET_PEER_intern (get_path[i]); | ||
1075 | p->length++; | ||
1076 | } | ||
1077 | for (i = 0; put_path[i] != NULL; i++) ; | ||
1078 | for (i--; i >= 0; i--) | ||
1079 | { | ||
1080 | p->peers = | ||
1081 | GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1)); | ||
1082 | p->peers[p->length] = GNUNET_PEER_intern (put_path[i]); | ||
1083 | p->length++; | ||
1084 | } | ||
1085 | return p; | ||
629 | } | 1086 | } |
630 | 1087 | ||
631 | 1088 | ||
632 | /** | 1089 | /** |
633 | * Check if client has registered with the service and has not disconnected | 1090 | * Check if client has registered with the service and has not disconnected |
1091 | * | ||
634 | * @param client the client to check | 1092 | * @param client the client to check |
1093 | * | ||
635 | * @return non-NULL if client exists in the global DLL | 1094 | * @return non-NULL if client exists in the global DLL |
636 | */ | 1095 | */ |
637 | static struct MeshClient * | 1096 | static struct MeshClient * |
638 | retrieve_client (struct GNUNET_SERVER_Client *client) | 1097 | client_get (struct GNUNET_SERVER_Client *client) |
639 | { | 1098 | { |
640 | struct MeshClient *c; | 1099 | struct MeshClient *c; |
641 | 1100 | ||
@@ -652,12 +1111,16 @@ retrieve_client (struct GNUNET_SERVER_Client *client) | |||
652 | 1111 | ||
653 | /** | 1112 | /** |
654 | * Checks if a given client has subscribed to certain message type | 1113 | * Checks if a given client has subscribed to certain message type |
1114 | * | ||
655 | * @param message_type Type of message to check | 1115 | * @param message_type Type of message to check |
656 | * @param c Client to check | 1116 | * @param c Client to check |
1117 | * | ||
657 | * @return GNUNET_YES or GNUNET_NO, depending on subscription status | 1118 | * @return GNUNET_YES or GNUNET_NO, depending on subscription status |
1119 | * | ||
1120 | * TODO inline? | ||
658 | */ | 1121 | */ |
659 | static int /* FIXME inline? */ | 1122 | static int |
660 | is_client_subscribed (uint16_t message_type, struct MeshClient *c) | 1123 | client_is_subscribed (uint16_t message_type, struct MeshClient *c) |
661 | { | 1124 | { |
662 | GNUNET_HashCode hc; | 1125 | GNUNET_HashCode hc; |
663 | 1126 | ||
@@ -668,12 +1131,14 @@ is_client_subscribed (uint16_t message_type, struct MeshClient *c) | |||
668 | 1131 | ||
669 | /** | 1132 | /** |
670 | * Search for a tunnel among the tunnels for a client | 1133 | * Search for a tunnel among the tunnels for a client |
1134 | * | ||
671 | * @param c the client whose tunnels to search in | 1135 | * @param c the client whose tunnels to search in |
672 | * @param tid the local id of the tunnel | 1136 | * @param tid the local id of the tunnel |
1137 | * | ||
673 | * @return tunnel handler, NULL if doesn't exist | 1138 | * @return tunnel handler, NULL if doesn't exist |
674 | */ | 1139 | */ |
675 | static struct MeshTunnel * | 1140 | static struct MeshTunnel * |
676 | retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid) | 1141 | tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid) |
677 | { | 1142 | { |
678 | GNUNET_HashCode hash; | 1143 | GNUNET_HashCode hash; |
679 | 1144 | ||
@@ -681,14 +1146,17 @@ retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid) | |||
681 | return GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash); | 1146 | return GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash); |
682 | } | 1147 | } |
683 | 1148 | ||
1149 | |||
684 | /** | 1150 | /** |
685 | * Search for a tunnel by global ID using PEER_ID | 1151 | * Search for a tunnel by global ID using PEER_ID |
1152 | * | ||
686 | * @param pi owner of the tunnel | 1153 | * @param pi owner of the tunnel |
687 | * @param tid global tunnel number | 1154 | * @param tid global tunnel number |
1155 | * | ||
688 | * @return tunnel handler, NULL if doesn't exist | 1156 | * @return tunnel handler, NULL if doesn't exist |
689 | */ | 1157 | */ |
690 | static struct MeshTunnel * | 1158 | static struct MeshTunnel * |
691 | retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid) | 1159 | tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid) |
692 | { | 1160 | { |
693 | struct MESH_TunnelID id; | 1161 | struct MESH_TunnelID id; |
694 | GNUNET_HashCode hash; | 1162 | GNUNET_HashCode hash; |
@@ -704,63 +1172,84 @@ retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid) | |||
704 | 1172 | ||
705 | /** | 1173 | /** |
706 | * Search for a tunnel by global ID using full PeerIdentities | 1174 | * Search for a tunnel by global ID using full PeerIdentities |
1175 | * | ||
707 | * @param oid owner of the tunnel | 1176 | * @param oid owner of the tunnel |
708 | * @param tid global tunnel number | 1177 | * @param tid global tunnel number |
1178 | * | ||
709 | * @return tunnel handler, NULL if doesn't exist | 1179 | * @return tunnel handler, NULL if doesn't exist |
710 | */ | 1180 | */ |
711 | static struct MeshTunnel * | 1181 | static struct MeshTunnel * |
712 | retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) | 1182 | tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) |
713 | { | 1183 | { |
714 | return retrieve_tunnel_by_pi (GNUNET_PEER_search (oid), tid); | 1184 | return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid); |
715 | } | 1185 | } |
716 | 1186 | ||
717 | 1187 | ||
718 | /** | 1188 | /** |
719 | * Destroy the path and free any allocated resources linked to it | 1189 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all |
720 | * @param p the path to destroy | 1190 | * needed rescources. |
721 | * @return GNUNET_OK on success | 1191 | * |
1192 | * @param t Tunnel we want to add a new peer to | ||
1193 | * @param peer PeerInfo of the peer being added | ||
1194 | * | ||
722 | */ | 1195 | */ |
723 | static int | 1196 | static void |
724 | destroy_path (struct MeshPath *p) | 1197 | tunnel_add_peer(struct MeshTunnel *t, struct MeshPeerInfo *peer) |
725 | { | 1198 | { |
726 | GNUNET_PEER_decrement_rcs (p->peers, p->length); | 1199 | struct MeshPeerPath *p; |
727 | GNUNET_free (p->peers); | 1200 | struct MeshPeerPath *best_p; |
728 | GNUNET_free (p); | 1201 | unsigned int best_cost; |
729 | return GNUNET_OK; | 1202 | unsigned int cost; |
1203 | |||
1204 | GNUNET_array_append(peer->tunnels, peer->ntunnels, t); | ||
1205 | if (NULL == (p = peer->path_head)) | ||
1206 | return; | ||
1207 | |||
1208 | best_p = p; | ||
1209 | best_cost = UINT_MAX; | ||
1210 | while (NULL != p) | ||
1211 | { | ||
1212 | if ((cost = path_get_cost(t, p)) < best_cost) | ||
1213 | { | ||
1214 | best_cost = cost; | ||
1215 | best_p = p; | ||
1216 | } | ||
1217 | p = p->next; | ||
1218 | } | ||
1219 | path_add_to_tunnel(t, best_p); | ||
1220 | if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task) | ||
1221 | t->path_refresh_task = GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, | ||
1222 | &path_refresh, t); | ||
730 | } | 1223 | } |
731 | 1224 | ||
732 | #if LATER | 1225 | |
733 | /** | 1226 | /** |
734 | * Destroy the peer_info and free any allocated resources linked to it | 1227 | * Notify a tunnel that a connection has broken that affects at least |
735 | * @param t tunnel the path belongs to | 1228 | * some of its peers. |
736 | * @param pi the peer_info to destroy | 1229 | * |
737 | * @return GNUNET_OK on success | 1230 | * @param t Tunnel affected |
1231 | * @param peer Peer that (at least) has been affected by the disconnection | ||
1232 | * @param p1 Peer that got disconnected from p2 | ||
1233 | * @param p2 Peer that got disconnected from p1 | ||
738 | */ | 1234 | */ |
739 | static int | 1235 | static void |
740 | destroy_peer_info (struct MeshPeerInfo *pi) | 1236 | tunnel_notify_connection_broken(struct MeshTunnel *t, |
1237 | struct MeshPeerInfo *peer, | ||
1238 | GNUNET_PEER_Id p1, | ||
1239 | GNUNET_PEER_Id p2) | ||
741 | { | 1240 | { |
742 | GNUNET_HashCode hash; | ||
743 | struct GNUNET_PeerIdentity id; | ||
744 | |||
745 | GNUNET_PEER_resolve (pi->id, &id); | ||
746 | GNUNET_PEER_change_rc (pi->id, -1); | ||
747 | GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &hash); | ||
748 | |||
749 | GNUNET_CONTAINER_multihashmap_remove (peers, &hash, pi); | ||
750 | GNUNET_SCHEDULER_cancel (pi->path_refresh_task); | ||
751 | GNUNET_free (pi); | ||
752 | return GNUNET_OK; | ||
753 | } | 1241 | } |
754 | #endif | ||
755 | 1242 | ||
756 | 1243 | ||
757 | /** | 1244 | /** |
758 | * Destroy the tunnel and free any allocated resources linked to it | 1245 | * Destroy the tunnel and free any allocated resources linked to it |
1246 | * | ||
759 | * @param t the tunnel to destroy | 1247 | * @param t the tunnel to destroy |
1248 | * | ||
760 | * @return GNUNET_OK on success | 1249 | * @return GNUNET_OK on success |
761 | */ | 1250 | */ |
762 | static int | 1251 | static int |
763 | destroy_tunnel (struct MeshTunnel *t) | 1252 | tunnel_destroy (struct MeshTunnel *t) |
764 | { | 1253 | { |
765 | struct MeshClient *c; | 1254 | struct MeshClient *c; |
766 | struct MeshQueue *q; | 1255 | struct MeshQueue *q; |
@@ -799,106 +1288,12 @@ destroy_tunnel (struct MeshTunnel *t) | |||
799 | return r; | 1288 | return r; |
800 | } | 1289 | } |
801 | 1290 | ||
802 | /******************************************************************************/ | ||
803 | /************************ PERIODIC FUNCTIONS ****************************/ | ||
804 | /******************************************************************************/ | ||
805 | |||
806 | /** | ||
807 | * Announce iterator over for each application provided by the peer | ||
808 | * | ||
809 | * @param cls closure | ||
810 | * @param key current key code | ||
811 | * @param value value in the hash map | ||
812 | * @return GNUNET_YES if we should continue to | ||
813 | * iterate, | ||
814 | * GNUNET_NO if not. | ||
815 | */ | ||
816 | static int | ||
817 | announce_application (void *cls, const GNUNET_HashCode * key, void *value) | ||
818 | { | ||
819 | /* FIXME are hashes in multihash map equal on all aquitectures? */ | ||
820 | GNUNET_DHT_put (dht_handle, key, 10U, GNUNET_DHT_RO_RECORD_ROUTE, | ||
821 | GNUNET_BLOCK_TYPE_TEST, sizeof (struct GNUNET_PeerIdentity), | ||
822 | (const char *) &my_full_id, | ||
823 | // GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
824 | // APP_ANNOUNCE_TIME), FIXME | ||
825 | // APP_ANNOUNCE_TIME, | ||
826 | GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL, | ||
827 | #if MESH_DEBUG | ||
828 | &mesh_debug, "DHT_put for app completed"); | ||
829 | #else | ||
830 | NULL, NULL); | ||
831 | #endif | ||
832 | return GNUNET_OK; | ||
833 | } | ||
834 | |||
835 | |||
836 | /** | ||
837 | * Periodically announce what applications are provided by local clients | ||
838 | * | ||
839 | * @param cls closure | ||
840 | * @param tc task context | ||
841 | */ | ||
842 | static void | ||
843 | announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
844 | { | ||
845 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
846 | { | ||
847 | announce_applications_task = GNUNET_SCHEDULER_NO_TASK; | ||
848 | return; | ||
849 | } | ||
850 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Starting PUT for apps\n"); | ||
851 | GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application, | ||
852 | NULL); | ||
853 | announce_applications_task = | ||
854 | GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME, &announce_applications, | ||
855 | cls); | ||
856 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Finished PUT for apps\n"); | ||
857 | return; | ||
858 | } | ||
859 | |||
860 | |||
861 | /** | ||
862 | * Periodically announce self id in the DHT | ||
863 | * | ||
864 | * @param cls closure | ||
865 | * @param tc task context | ||
866 | */ | ||
867 | static void | ||
868 | announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
869 | { | ||
870 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
871 | { | ||
872 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; | ||
873 | return; | ||
874 | } | ||
875 | /* TODO | ||
876 | * - Set data expiration in function of X | ||
877 | * - Adapt X to churn | ||
878 | */ | ||
879 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
880 | &my_full_id.hashPubKey, /* Key to use */ | ||
881 | 10U, /* Replication level */ | ||
882 | GNUNET_DHT_RO_RECORD_ROUTE, /* DHT options */ | ||
883 | GNUNET_BLOCK_TYPE_TEST, /* Block type */ | ||
884 | 0, /* Size of the data */ | ||
885 | NULL, /* Data itself */ | ||
886 | GNUNET_TIME_absolute_get_forever (), /* Data expiration */ | ||
887 | GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */ | ||
888 | #if MESH_DEBUG | ||
889 | &mesh_debug, "DHT_put for id completed"); | ||
890 | #else | ||
891 | NULL, /* Continuation */ | ||
892 | NULL); /* Continuation closure */ | ||
893 | #endif | ||
894 | announce_id_task = | ||
895 | GNUNET_SCHEDULER_add_delayed (ID_ANNOUNCE_TIME, &announce_id, cls); | ||
896 | } | ||
897 | 1291 | ||
898 | /******************************************************************************/ | 1292 | /******************************************************************************/ |
899 | /**************** MESH NETWORK HANDLER HELPERS ***********************/ | 1293 | /**************** MESH NETWORK HANDLER HELPERS ***********************/ |
900 | /******************************************************************************/ | 1294 | /******************************************************************************/ |
901 | 1295 | ||
1296 | |||
902 | /** | 1297 | /** |
903 | * Function called to notify a client about the socket | 1298 | * Function called to notify a client about the socket |
904 | * being ready to queue more data. "buf" will be | 1299 | * being ready to queue more data. "buf" will be |
@@ -911,64 +1306,37 @@ announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
911 | * @return number of bytes written to buf | 1306 | * @return number of bytes written to buf |
912 | */ | 1307 | */ |
913 | static size_t | 1308 | static size_t |
914 | send_core_create_path_for_peer (void *cls, size_t size, void *buf) | 1309 | send_core_create_path (void *cls, size_t size, void *buf) |
915 | { | 1310 | { |
916 | struct MeshPeerInfo *peer_info = cls; | 1311 | struct MeshPathInfo *info = cls; |
917 | struct GNUNET_MESH_ManipulatePath *msg; | 1312 | struct GNUNET_MESH_ManipulatePath *msg; |
918 | struct MeshPath *p; | ||
919 | struct GNUNET_PeerIdentity *peer_ptr; | 1313 | struct GNUNET_PeerIdentity *peer_ptr; |
920 | struct GNUNET_PeerIdentity id; | 1314 | struct GNUNET_PeerIdentity id; |
1315 | struct MeshPeerInfo *peer = info->peer; | ||
1316 | struct MeshTunnel *t = info->t; | ||
1317 | struct MeshPeerPath *p = info->path; | ||
921 | size_t size_needed; | 1318 | size_t size_needed; |
922 | int i; | 1319 | int i; |
923 | 1320 | ||
924 | if (0 == size && NULL == buf) | ||
925 | { | ||
926 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n"); | ||
927 | GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id); | ||
928 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | ||
929 | GNUNET_TIME_UNIT_FOREVER_REL, &id, | ||
930 | sizeof (struct | ||
931 | GNUNET_MESH_ManipulatePath) + | ||
932 | (peer_info->path->length * | ||
933 | sizeof (struct GNUNET_PeerIdentity)), | ||
934 | &send_core_create_path_for_peer, | ||
935 | peer_info); | ||
936 | return 0; | ||
937 | } | ||
938 | p = peer_info->path; | ||
939 | while (NULL != p) | ||
940 | { | ||
941 | if (p->in_use) | ||
942 | { | ||
943 | break; | ||
944 | } | ||
945 | p = p->next; | ||
946 | } | ||
947 | if (p == NULL) | ||
948 | return 0; // TODO Notify ERROR Path not found | ||
949 | |||
950 | size_needed = | 1321 | size_needed = |
951 | sizeof (struct GNUNET_MESH_ManipulatePath) + | 1322 | sizeof (struct GNUNET_MESH_ManipulatePath) + |
952 | p->length * sizeof (struct GNUNET_PeerIdentity); | 1323 | p->length * sizeof (struct GNUNET_PeerIdentity); |
953 | if (size < size_needed) | 1324 | |
1325 | if (size < size_needed || NULL == buf) | ||
954 | { | 1326 | { |
955 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n"); | 1327 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n"); |
956 | GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id); | 1328 | GNUNET_PEER_resolve (path_get_first_hop (t, peer)->id, &id); |
957 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 1329 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
958 | GNUNET_TIME_UNIT_FOREVER_REL, &id, | 1330 | GNUNET_TIME_UNIT_FOREVER_REL, &id, |
959 | sizeof (struct | 1331 | size_needed, &send_core_create_path, |
960 | GNUNET_MESH_ManipulatePath) + | 1332 | info); |
961 | (peer_info->path->length * | ||
962 | sizeof (struct GNUNET_PeerIdentity)), | ||
963 | &send_core_create_path_for_peer, | ||
964 | peer_info); | ||
965 | return 0; | 1333 | return 0; |
966 | } | 1334 | } |
967 | 1335 | ||
968 | msg = (struct GNUNET_MESH_ManipulatePath *) buf; | 1336 | msg = (struct GNUNET_MESH_ManipulatePath *) buf; |
969 | msg->header.size = htons (size_needed); | 1337 | msg->header.size = htons (size_needed); |
970 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE); | 1338 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE); |
971 | msg->tid = 0; /* FIXME */ | 1339 | msg->tid = ntohl(t->id.tid); |
972 | 1340 | ||
973 | peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; | 1341 | peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; |
974 | for (i = 0; i < p->length; i++) | 1342 | for (i = 0; i < p->length; i++) |
@@ -976,7 +1344,8 @@ send_core_create_path_for_peer (void *cls, size_t size, void *buf) | |||
976 | GNUNET_PEER_resolve (p->peers[i], peer_ptr++); | 1344 | GNUNET_PEER_resolve (p->peers[i], peer_ptr++); |
977 | } | 1345 | } |
978 | 1346 | ||
979 | peer_info->state = MESH_PEER_WAITING; | 1347 | path_destroy(p); |
1348 | GNUNET_free (info); | ||
980 | 1349 | ||
981 | return size_needed; | 1350 | return size_needed; |
982 | } | 1351 | } |
@@ -1215,7 +1584,7 @@ send_p2p_tunnel_destroy (void *cls, size_t size, void *buf) | |||
1215 | htons (sizeof (struct GNUNET_MESH_TunnelMessage)); | 1584 | htons (sizeof (struct GNUNET_MESH_TunnelMessage)); |
1216 | msg->tunnel_id = htonl (t->id.tid); | 1585 | msg->tunnel_id = htonl (t->id.tid); |
1217 | 1586 | ||
1218 | destroy_tunnel (c, t); | 1587 | tunnel_destroy (c, t); |
1219 | return sizeof (struct GNUNET_MESH_TunnelMessage); | 1588 | return sizeof (struct GNUNET_MESH_TunnelMessage); |
1220 | } | 1589 | } |
1221 | #endif | 1590 | #endif |
@@ -1237,7 +1606,7 @@ send_subscribed_clients (struct GNUNET_MessageHeader *msg) | |||
1237 | type = ntohs (msg->type); | 1606 | type = ntohs (msg->type); |
1238 | for (count = 0, c = clients; c != NULL; c = c->next) | 1607 | for (count = 0, c = clients; c != NULL; c = c->next) |
1239 | { | 1608 | { |
1240 | if (is_client_subscribed (type, c)) | 1609 | if (client_is_subscribed (type, c)) |
1241 | { | 1610 | { |
1242 | count++; | 1611 | count++; |
1243 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, msg, | 1612 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, msg, |
@@ -1261,23 +1630,22 @@ static int | |||
1261 | iterate_collect_neighbors (void *cls, const GNUNET_HashCode * key, void *value) | 1630 | iterate_collect_neighbors (void *cls, const GNUNET_HashCode * key, void *value) |
1262 | { | 1631 | { |
1263 | struct MeshPeerInfo *peer_info = value; | 1632 | struct MeshPeerInfo *peer_info = value; |
1264 | GNUNET_PEER_Id **neighbors = cls; | 1633 | struct MeshPathInfo *neighbors = cls; |
1265 | GNUNET_PEER_Id id; | ||
1266 | unsigned int i; | 1634 | unsigned int i; |
1267 | 1635 | ||
1268 | if (peer_info->id == myid) | 1636 | if (peer_info->id == myid) |
1269 | { | 1637 | { |
1270 | return GNUNET_YES; | 1638 | return GNUNET_YES; |
1271 | } | 1639 | } |
1272 | id = get_first_hop (peer_info->path); | 1640 | peer_info = path_get_first_hop (neighbors->t, peer_info); |
1273 | for (i = 0; *neighbors[i] != 0; i++) | 1641 | for (i = 0; i < neighbors->path->length; i++) |
1274 | { | 1642 | { |
1275 | if (*neighbors[i] == id) | 1643 | if (neighbors->path->peers[i] == peer_info->id) |
1276 | return GNUNET_YES; | 1644 | return GNUNET_YES; |
1277 | } | 1645 | } |
1278 | *neighbors = GNUNET_realloc (*neighbors, (i + 2) * sizeof (GNUNET_PEER_Id)); | 1646 | GNUNET_array_append(neighbors->path->peers, |
1279 | *neighbors[i] = id; | 1647 | neighbors->path->length, |
1280 | *neighbors[i + 1] = 0; | 1648 | peer_info->id); |
1281 | 1649 | ||
1282 | return GNUNET_YES; | 1650 | return GNUNET_YES; |
1283 | } | 1651 | } |
@@ -1313,7 +1681,7 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1313 | struct GNUNET_PeerIdentity *pi; | 1681 | struct GNUNET_PeerIdentity *pi; |
1314 | struct GNUNET_PeerIdentity id; | 1682 | struct GNUNET_PeerIdentity id; |
1315 | GNUNET_HashCode hash; | 1683 | GNUNET_HashCode hash; |
1316 | struct MeshPath *path; | 1684 | struct MeshPeerPath *path; |
1317 | struct MeshPeerInfo *dest_peer_info; | 1685 | struct MeshPeerInfo *dest_peer_info; |
1318 | struct MeshPeerInfo *orig_peer_info; | 1686 | struct MeshPeerInfo *orig_peer_info; |
1319 | struct MeshTunnel *t; | 1687 | struct MeshTunnel *t; |
@@ -1323,30 +1691,27 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1323 | size = ntohs (message->size); | 1691 | size = ntohs (message->size); |
1324 | if (size < sizeof (struct GNUNET_MESH_ManipulatePath)) | 1692 | if (size < sizeof (struct GNUNET_MESH_ManipulatePath)) |
1325 | { | 1693 | { |
1326 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1694 | GNUNET_break_op (0); |
1327 | "received create path message too short\n"); | ||
1328 | return GNUNET_OK; | 1695 | return GNUNET_OK; |
1329 | } | 1696 | } |
1330 | 1697 | ||
1331 | size -= sizeof (struct GNUNET_MESH_ManipulatePath); | 1698 | size -= sizeof (struct GNUNET_MESH_ManipulatePath); |
1332 | if (size < 2 * sizeof (struct GNUNET_PeerIdentity)) | 1699 | if (size % sizeof (struct GNUNET_PeerIdentity)) |
1333 | { | 1700 | { |
1334 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1701 | GNUNET_break_op (0); |
1335 | "create path message lacks enough peers\n"); | ||
1336 | return GNUNET_OK; | 1702 | return GNUNET_OK; |
1337 | } | 1703 | } |
1338 | if (size % sizeof (struct GNUNET_PeerIdentity)) | 1704 | size /= sizeof (struct GNUNET_PeerIdentity); |
1705 | if (size < 2) | ||
1339 | { | 1706 | { |
1340 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1707 | GNUNET_break_op (0); |
1341 | "create path message of wrong size\n"); | ||
1342 | return GNUNET_OK; | 1708 | return GNUNET_OK; |
1343 | } | 1709 | } |
1344 | msg = (struct GNUNET_MESH_ManipulatePath *) message; | 1710 | msg = (struct GNUNET_MESH_ManipulatePath *) message; |
1345 | size /= sizeof (struct GNUNET_PeerIdentity); | ||
1346 | 1711 | ||
1347 | tid = ntohl (msg->tid); | 1712 | tid = ntohl (msg->tid); |
1348 | pi = (struct GNUNET_PeerIdentity *) &msg[1]; | 1713 | pi = (struct GNUNET_PeerIdentity *) &msg[1]; |
1349 | t = retrieve_tunnel (pi, tid); | 1714 | t = tunnel_get (pi, tid); |
1350 | 1715 | ||
1351 | if (NULL == t) | 1716 | if (NULL == t) |
1352 | { | 1717 | { |
@@ -1358,8 +1723,9 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1358 | 1723 | ||
1359 | GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash); | 1724 | GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash); |
1360 | if (GNUNET_OK != | 1725 | if (GNUNET_OK != |
1361 | GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t, | 1726 | GNUNET_CONTAINER_multihashmap_put ( |
1362 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | 1727 | tunnels, &hash, t, |
1728 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1363 | { | 1729 | { |
1364 | GNUNET_break (0); | 1730 | GNUNET_break (0); |
1365 | return GNUNET_OK; | 1731 | return GNUNET_OK; |
@@ -1372,23 +1738,25 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1372 | { | 1738 | { |
1373 | dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo)); | 1739 | dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo)); |
1374 | dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]); | 1740 | dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]); |
1375 | dest_peer_info->state = MESH_PEER_WAITING; | 1741 | GNUNET_CONTAINER_multihashmap_put ( |
1376 | GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey, | 1742 | peers, |
1377 | dest_peer_info, | 1743 | &pi[size - 1].hashPubKey, |
1378 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | 1744 | dest_peer_info, |
1745 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1379 | } | 1746 | } |
1380 | orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey); | 1747 | orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey); |
1381 | if (NULL == orig_peer_info) | 1748 | if (NULL == orig_peer_info) |
1382 | { | 1749 | { |
1383 | orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo)); | 1750 | orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo)); |
1384 | orig_peer_info->id = GNUNET_PEER_intern (pi); | 1751 | orig_peer_info->id = GNUNET_PEER_intern (pi); |
1385 | orig_peer_info->state = MESH_PEER_WAITING; | 1752 | GNUNET_CONTAINER_multihashmap_put ( |
1386 | GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info, | 1753 | peers, |
1387 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | 1754 | &pi->hashPubKey, |
1755 | orig_peer_info, | ||
1756 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1388 | } | 1757 | } |
1389 | 1758 | ||
1390 | 1759 | path = GNUNET_malloc (sizeof (struct MeshPeerPath)); | |
1391 | path = GNUNET_malloc (sizeof (struct MeshPath)); | ||
1392 | path->length = size; | 1760 | path->length = size; |
1393 | path->peers = GNUNET_malloc (size * sizeof (GNUNET_PEER_Id)); | 1761 | path->peers = GNUNET_malloc (size * sizeof (GNUNET_PEER_Id)); |
1394 | own_pos = 0; | 1762 | own_pos = 0; |
@@ -1402,17 +1770,17 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1402 | { /* cannot be self, must be 'not found' */ | 1770 | { /* cannot be self, must be 'not found' */ |
1403 | /* create path: self not found in path through self */ | 1771 | /* create path: self not found in path through self */ |
1404 | GNUNET_break_op (0); | 1772 | GNUNET_break_op (0); |
1405 | destroy_path (path); | 1773 | path_destroy (path); |
1406 | /* FIXME error. destroy tunnel? leave for timeout? */ | 1774 | /* FIXME error. destroy tunnel? leave for timeout? */ |
1407 | return 0; | 1775 | return 0; |
1408 | } | 1776 | } |
1409 | if (own_pos == size - 1) | 1777 | if (own_pos == size - 1) |
1410 | { /* it is for us! */ | 1778 | { |
1779 | /* It is for us! Send ack. */ | ||
1411 | struct MeshDataDescriptor *info; | 1780 | struct MeshDataDescriptor *info; |
1412 | unsigned int j; | 1781 | unsigned int j; |
1413 | 1782 | ||
1414 | add_path_to_origin (orig_peer_info, path); /* inverts path! */ | 1783 | path_add_to_origin (orig_peer_info, path); /* inverts path! */ |
1415 | GNUNET_PEER_resolve (get_first_hop (path), &id); /* path is inverted :) */ | ||
1416 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor)); | 1784 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor)); |
1417 | info->origin = &t->id; | 1785 | info->origin = &t->id; |
1418 | info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey); | 1786 | info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey); |
@@ -1428,19 +1796,27 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1428 | info->handler_n = j; | 1796 | info->handler_n = j; |
1429 | info->peer->core_transmit[j] = | 1797 | info->peer->core_transmit[j] = |
1430 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100, | 1798 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100, |
1431 | GNUNET_TIME_UNIT_FOREVER_REL, &id, | 1799 | GNUNET_TIME_UNIT_FOREVER_REL, peer, |
1432 | sizeof (struct GNUNET_MessageHeader), | 1800 | sizeof (struct GNUNET_MessageHeader), |
1433 | &send_core_path_ack, info); | 1801 | &send_core_path_ack, info); |
1434 | } | 1802 | } |
1435 | else | 1803 | else |
1436 | { | 1804 | { |
1437 | add_path_to_peer (dest_peer_info, path); | 1805 | /* It's for somebody else! Retransmit. */ |
1438 | GNUNET_PEER_resolve (get_first_hop (path), &id); | 1806 | struct MeshPathInfo *path_info; |
1807 | |||
1808 | path_info = GNUNET_malloc (sizeof(struct MeshPathInfo)); | ||
1809 | path_info->t = t; | ||
1810 | path_info->path = path; | ||
1811 | path_info->peer = dest_peer_info; | ||
1812 | |||
1813 | path_add_to_peer (dest_peer_info, path); | ||
1814 | GNUNET_PEER_resolve (path->peers[own_pos + 1], &id); | ||
1439 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 1815 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
1440 | GNUNET_TIME_UNIT_FOREVER_REL, &id, | 1816 | GNUNET_TIME_UNIT_FOREVER_REL, &id, |
1441 | sizeof (struct GNUNET_MessageHeader), | 1817 | sizeof (struct GNUNET_MessageHeader), |
1442 | &send_core_create_path_for_peer, | 1818 | &send_core_create_path, |
1443 | dest_peer_info); | 1819 | path_info); |
1444 | } | 1820 | } |
1445 | return GNUNET_OK; | 1821 | return GNUNET_OK; |
1446 | } | 1822 | } |
@@ -1476,7 +1852,7 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1476 | return GNUNET_OK; | 1852 | return GNUNET_OK; |
1477 | } | 1853 | } |
1478 | msg = (struct GNUNET_MESH_Unicast *) message; | 1854 | msg = (struct GNUNET_MESH_Unicast *) message; |
1479 | t = retrieve_tunnel (&msg->oid, ntohl (msg->tid)); | 1855 | t = tunnel_get (&msg->oid, ntohl (msg->tid)); |
1480 | if (NULL == t) | 1856 | if (NULL == t) |
1481 | { | 1857 | { |
1482 | /* TODO notify back: we don't know this tunnel */ | 1858 | /* TODO notify back: we don't know this tunnel */ |
@@ -1494,7 +1870,7 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1494 | send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]); | 1870 | send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]); |
1495 | return GNUNET_OK; | 1871 | return GNUNET_OK; |
1496 | } | 1872 | } |
1497 | GNUNET_PEER_resolve (get_first_hop (pi->path), &id); | 1873 | GNUNET_PEER_resolve (path_get_first_hop (t, pi)->id, &id); |
1498 | msg = GNUNET_malloc (size); | 1874 | msg = GNUNET_malloc (size); |
1499 | memcpy (msg, message, size); | 1875 | memcpy (msg, message, size); |
1500 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 1876 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
@@ -1521,9 +1897,9 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1521 | { | 1897 | { |
1522 | struct GNUNET_MESH_Multicast *msg; | 1898 | struct GNUNET_MESH_Multicast *msg; |
1523 | struct GNUNET_PeerIdentity id; | 1899 | struct GNUNET_PeerIdentity id; |
1524 | struct MeshTunnel *t; | ||
1525 | struct MeshDataDescriptor *info; | 1900 | struct MeshDataDescriptor *info; |
1526 | GNUNET_PEER_Id *neighbors; | 1901 | struct MeshPathInfo neighbors; |
1902 | struct MeshTunnel *t; | ||
1527 | size_t size; | 1903 | size_t size; |
1528 | uint16_t i; | 1904 | uint16_t i; |
1529 | uint16_t j; | 1905 | uint16_t j; |
@@ -1538,7 +1914,7 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1538 | return GNUNET_OK; | 1914 | return GNUNET_OK; |
1539 | } | 1915 | } |
1540 | msg = (struct GNUNET_MESH_Multicast *) message; | 1916 | msg = (struct GNUNET_MESH_Multicast *) message; |
1541 | t = retrieve_tunnel (&msg->oid, ntohl (msg->tid)); | 1917 | t = tunnel_get (&msg->oid, ntohl (msg->tid)); |
1542 | 1918 | ||
1543 | if (NULL == t) | 1919 | if (NULL == t) |
1544 | { | 1920 | { |
@@ -1552,29 +1928,30 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1552 | send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]); | 1928 | send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]); |
1553 | } | 1929 | } |
1554 | 1930 | ||
1555 | /* Retransmit to other peers */ | 1931 | /* Retransmit to other peers. |
1556 | neighbors = GNUNET_malloc (sizeof (GNUNET_PEER_Id)); | 1932 | * Using path here as just a collection of peers, not a path per se. |
1557 | neighbors[0] = 0; | 1933 | */ |
1934 | neighbors.t = t; | ||
1935 | neighbors.path = GNUNET_malloc (sizeof(struct MeshPeerPath)); | ||
1558 | GNUNET_CONTAINER_multihashmap_iterate (t->peers, &iterate_collect_neighbors, | 1936 | GNUNET_CONTAINER_multihashmap_iterate (t->peers, &iterate_collect_neighbors, |
1559 | &neighbors); | 1937 | &neighbors); |
1560 | if (!neighbors[0]) | 1938 | if (0 == neighbors.path->length) |
1561 | { | 1939 | { |
1940 | GNUNET_free(neighbors.path); | ||
1562 | return GNUNET_OK; | 1941 | return GNUNET_OK; |
1563 | } | 1942 | } |
1564 | size -= sizeof (struct GNUNET_MESH_Multicast); | 1943 | size -= sizeof (struct GNUNET_MESH_Multicast); |
1565 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + size); | 1944 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + size); |
1566 | info->origin = &t->id; | 1945 | info->origin = &t->id; |
1567 | info->copies = 0; | 1946 | info->copies = neighbors.path->length; |
1568 | for (i = 0; 0 != neighbors[i]; i++) | 1947 | for (i = 0; i < info->copies; i++) |
1569 | { | 1948 | { |
1570 | GNUNET_PEER_resolve (neighbors[i], &id); | 1949 | GNUNET_PEER_resolve (neighbors.path->peers[i], &id); |
1571 | info->copies++; | ||
1572 | info->destination = neighbors[i]; | ||
1573 | info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey); | 1950 | info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey); |
1574 | GNUNET_assert (info->peer); | 1951 | GNUNET_assert (NULL != info->peer); |
1575 | for (j = 0; info->peer->core_transmit[j]; j++) | 1952 | for (j = 0; 0 != info->peer->core_transmit[j]; j++) |
1576 | { | 1953 | { |
1577 | if (j == 9) | 1954 | if (j == (CORE_QUEUE_SIZE - 1)) |
1578 | { | 1955 | { |
1579 | GNUNET_break (0); | 1956 | GNUNET_break (0); |
1580 | return GNUNET_OK; | 1957 | return GNUNET_OK; |
@@ -1588,6 +1965,8 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1588 | ntohs (msg->header.size), | 1965 | ntohs (msg->header.size), |
1589 | &send_core_data_multicast, info); | 1966 | &send_core_data_multicast, info); |
1590 | } | 1967 | } |
1968 | GNUNET_free(neighbors.path->peers); | ||
1969 | GNUNET_free(neighbors.path); | ||
1591 | return GNUNET_OK; | 1970 | return GNUNET_OK; |
1592 | } | 1971 | } |
1593 | 1972 | ||
@@ -1601,12 +1980,14 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1601 | * @param atsi performance data | 1980 | * @param atsi performance data |
1602 | * @return GNUNET_OK to keep the connection open, | 1981 | * @return GNUNET_OK to keep the connection open, |
1603 | * GNUNET_SYSERR to close it (signal serious error) | 1982 | * GNUNET_SYSERR to close it (signal serious error) |
1983 | * | ||
1984 | * FIXME path | ||
1604 | */ | 1985 | */ |
1605 | static int | 1986 | static int |
1606 | handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | 1987 | handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, |
1607 | const struct GNUNET_MessageHeader *message, | 1988 | const struct GNUNET_MessageHeader *message, |
1608 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) | 1989 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) |
1609 | { | 1990 | { |
1610 | struct GNUNET_MESH_ToOrigin *msg; | 1991 | struct GNUNET_MESH_ToOrigin *msg; |
1611 | struct GNUNET_PeerIdentity id; | 1992 | struct GNUNET_PeerIdentity id; |
1612 | struct MeshTunnel *t; | 1993 | struct MeshTunnel *t; |
@@ -1622,7 +2003,7 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1622 | return GNUNET_OK; | 2003 | return GNUNET_OK; |
1623 | } | 2004 | } |
1624 | msg = (struct GNUNET_MESH_ToOrigin *) message; | 2005 | msg = (struct GNUNET_MESH_ToOrigin *) message; |
1625 | t = retrieve_tunnel (&msg->oid, ntohl (msg->tid)); | 2006 | t = tunnel_get (&msg->oid, ntohl (msg->tid)); |
1626 | 2007 | ||
1627 | if (NULL == t) | 2008 | if (NULL == t) |
1628 | { | 2009 | { |
@@ -1642,14 +2023,14 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1642 | GNUNET_YES); | 2023 | GNUNET_YES); |
1643 | return GNUNET_OK; | 2024 | return GNUNET_OK; |
1644 | } | 2025 | } |
1645 | peer_info = get_peer_info (&msg->oid); | 2026 | peer_info = peer_info_get (&msg->oid); |
1646 | if (NULL == peer_info) | 2027 | if (NULL == peer_info) |
1647 | { | 2028 | { |
1648 | /* unknown origin of tunnel */ | 2029 | /* unknown origin of tunnel */ |
1649 | GNUNET_break (0); | 2030 | GNUNET_break (0); |
1650 | return GNUNET_OK; | 2031 | return GNUNET_OK; |
1651 | } | 2032 | } |
1652 | GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id); | 2033 | GNUNET_PEER_resolve (path_get_first_hop (t, peer_info)->id, &id); |
1653 | msg = GNUNET_malloc (size); | 2034 | msg = GNUNET_malloc (size); |
1654 | memcpy (msg, message, size); | 2035 | memcpy (msg, message, size); |
1655 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 2036 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
@@ -1667,8 +2048,11 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1667 | * @param message message | 2048 | * @param message message |
1668 | * @param peer peer identity this notification is about | 2049 | * @param peer peer identity this notification is about |
1669 | * @param atsi performance data | 2050 | * @param atsi performance data |
2051 | * | ||
1670 | * @return GNUNET_OK to keep the connection open, | 2052 | * @return GNUNET_OK to keep the connection open, |
1671 | * GNUNET_SYSERR to close it (signal serious error) | 2053 | * GNUNET_SYSERR to close it (signal serious error) |
2054 | * | ||
2055 | * FIXME path change state | ||
1672 | */ | 2056 | */ |
1673 | static int | 2057 | static int |
1674 | handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | 2058 | handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, |
@@ -1681,7 +2065,7 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1681 | struct MeshPeerInfo *peer_info; | 2065 | struct MeshPeerInfo *peer_info; |
1682 | 2066 | ||
1683 | msg = (struct GNUNET_MESH_PathACK *) message; | 2067 | msg = (struct GNUNET_MESH_PathACK *) message; |
1684 | t = retrieve_tunnel (&msg->oid, msg->tid); | 2068 | t = tunnel_get (&msg->oid, msg->tid); |
1685 | if (NULL == t) | 2069 | if (NULL == t) |
1686 | { | 2070 | { |
1687 | /* TODO notify that we don't know the tunnel */ | 2071 | /* TODO notify that we don't know the tunnel */ |
@@ -1698,13 +2082,13 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1698 | GNUNET_break (0); | 2082 | GNUNET_break (0); |
1699 | return GNUNET_OK; | 2083 | return GNUNET_OK; |
1700 | } | 2084 | } |
1701 | peer_info = get_peer_info (&msg->peer_id); | 2085 | peer_info = peer_info_get (&msg->peer_id); |
1702 | if (NULL == peer_info) | 2086 | if (NULL == peer_info) |
1703 | { | 2087 | { |
1704 | GNUNET_break_op (0); | 2088 | GNUNET_break_op (0); |
1705 | return GNUNET_OK; | 2089 | return GNUNET_OK; |
1706 | } | 2090 | } |
1707 | peer_info->state = MESH_PEER_READY; | 2091 | /* FIXME change state of peer */ |
1708 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); | 2092 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); |
1709 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); | 2093 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); |
1710 | pc.tunnel_id = htonl (t->local_tid); | 2094 | pc.tunnel_id = htonl (t->local_tid); |
@@ -1714,14 +2098,14 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1714 | return GNUNET_OK; | 2098 | return GNUNET_OK; |
1715 | } | 2099 | } |
1716 | 2100 | ||
1717 | peer_info = get_peer_info (&msg->oid); | 2101 | peer_info = peer_info_get (&msg->oid); |
1718 | if (NULL == peer_info) | 2102 | if (NULL == peer_info) |
1719 | { | 2103 | { |
1720 | /* If we know the tunnel, we should DEFINITELY know the peer */ | 2104 | /* If we know the tunnel, we should DEFINITELY know the peer */ |
1721 | GNUNET_break (0); | 2105 | GNUNET_break (0); |
1722 | return GNUNET_OK; | 2106 | return GNUNET_OK; |
1723 | } | 2107 | } |
1724 | GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id); | 2108 | GNUNET_PEER_resolve (path_get_first_hop (t, peer_info)->id, &id); |
1725 | msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PathACK)); | 2109 | msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PathACK)); |
1726 | memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK)); | 2110 | memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK)); |
1727 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 2111 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
@@ -1764,7 +2148,7 @@ delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) | |||
1764 | { | 2148 | { |
1765 | int r; | 2149 | int r; |
1766 | 2150 | ||
1767 | r = destroy_tunnel ((struct MeshTunnel *) value); | 2151 | r = tunnel_destroy ((struct MeshTunnel *) value); |
1768 | return r; | 2152 | return r; |
1769 | } | 2153 | } |
1770 | 2154 | ||
@@ -1824,36 +2208,6 @@ notify_client_connection_failure (void *cls, size_t size, void *buf) | |||
1824 | 2208 | ||
1825 | 2209 | ||
1826 | /** | 2210 | /** |
1827 | * Send keepalive packets for a peer | ||
1828 | * | ||
1829 | * @param cls unused | ||
1830 | * @param tc unused | ||
1831 | */ | ||
1832 | static void | ||
1833 | path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1834 | { | ||
1835 | struct MeshPeerInfo *peer_info = cls; | ||
1836 | struct GNUNET_PeerIdentity id; | ||
1837 | |||
1838 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
1839 | return; | ||
1840 | GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id); | ||
1841 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | ||
1842 | GNUNET_TIME_UNIT_FOREVER_REL, &id, | ||
1843 | sizeof (struct GNUNET_MESH_ManipulatePath) | ||
1844 | + | ||
1845 | (peer_info->path->length * | ||
1846 | sizeof (struct GNUNET_PeerIdentity)), | ||
1847 | &send_core_create_path_for_peer, | ||
1848 | peer_info); | ||
1849 | peer_info->path_refresh_task = | ||
1850 | GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, | ||
1851 | peer_info); | ||
1852 | return; | ||
1853 | } | ||
1854 | |||
1855 | |||
1856 | /** | ||
1857 | * Function to process paths received for a new peer addition. The recorded | 2211 | * Function to process paths received for a new peer addition. The recorded |
1858 | * paths form the initial tunnel, which can be optimized later. | 2212 | * paths form the initial tunnel, which can be optimized later. |
1859 | * Called on each result obtained for the DHT search. | 2213 | * Called on each result obtained for the DHT search. |
@@ -1868,6 +2222,8 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1868 | * @param type type of the result | 2222 | * @param type type of the result |
1869 | * @param size number of bytes in data | 2223 | * @param size number of bytes in data |
1870 | * @param data pointer to the result data | 2224 | * @param data pointer to the result data |
2225 | * | ||
2226 | * FIXME path | ||
1871 | */ | 2227 | */ |
1872 | static void | 2228 | static void |
1873 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | 2229 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, |
@@ -1876,60 +2232,42 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
1876 | const struct GNUNET_PeerIdentity *const *put_path, | 2232 | const struct GNUNET_PeerIdentity *const *put_path, |
1877 | enum GNUNET_BLOCK_Type type, size_t size, const void *data) | 2233 | enum GNUNET_BLOCK_Type type, size_t size, const void *data) |
1878 | { | 2234 | { |
1879 | struct MeshPeerInfo *peer_info = cls; | 2235 | struct MeshPathInfo *path_info = cls; |
1880 | struct MeshPath *p; | 2236 | struct MeshPeerPath *p; |
1881 | struct GNUNET_PeerIdentity pi; | 2237 | struct GNUNET_PeerIdentity pi; |
1882 | int i; | 2238 | int i; |
1883 | 2239 | ||
1884 | if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) | 2240 | if (NULL == get_path || NULL == put_path) |
1885 | { | 2241 | { |
1886 | // Find ourselves some alternate initial path to the destination: retry | 2242 | if (NULL == path_info->peer->path_head) |
1887 | GNUNET_DHT_get_stop (peer_info->dhtget); | 2243 | { |
1888 | GNUNET_PEER_resolve (peer_info->id, &pi); | 2244 | // Find ourselves some alternate initial path to the destination: retry |
1889 | peer_info->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ | 2245 | GNUNET_DHT_get_stop (path_info->peer->dhtget); |
1890 | GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BLOCK_TYPE_TEST, /* type */ | 2246 | GNUNET_PEER_resolve (path_info->peer->id, &pi); |
1891 | &pi.hashPubKey, /*key to search */ | 2247 | path_info->peer->dhtget = GNUNET_DHT_get_start ( |
1892 | 4, /* replication level */ | 2248 | dht_handle, /* handle */ |
1893 | GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */ | 2249 | GNUNET_TIME_UNIT_FOREVER_REL, /* timeout */ |
1894 | 0, /* mutator */ | 2250 | GNUNET_BLOCK_TYPE_TEST, /* type */ |
1895 | NULL, /* xquery */ | 2251 | &pi.hashPubKey, /*key to search */ |
1896 | 0, /* xquery bits */ | 2252 | 4, /* replication level */ |
1897 | dht_get_id_handler, | 2253 | GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */ |
1898 | (void *) peer_info); | 2254 | 0, /* mutator */ |
2255 | NULL, /* xquery */ | ||
2256 | 0, /* xquery bits */ | ||
2257 | dht_get_id_handler, | ||
2258 | (void *) path_info); | ||
2259 | return; | ||
2260 | } | ||
1899 | } | 2261 | } |
1900 | 2262 | ||
1901 | p = GNUNET_malloc (sizeof (struct MeshPath)); | 2263 | p = path_build_from_dht(get_path, put_path); |
1902 | for (i = 0; get_path[i] != NULL; i++) ; | 2264 | path_add_to_peer (path_info->peer, p); |
1903 | for (i--; i >= 0; i--) | 2265 | for (i = 0; i < path_info->peer->ntunnels; i++) |
1904 | { | ||
1905 | p->peers = | ||
1906 | GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1)); | ||
1907 | p->peers[p->length] = GNUNET_PEER_intern (get_path[i]); | ||
1908 | p->length++; | ||
1909 | } | ||
1910 | for (i = 0; put_path[i] != NULL; i++) ; | ||
1911 | for (i--; i >= 0; i--) | ||
1912 | { | 2266 | { |
1913 | p->peers = | 2267 | tunnel_add_peer(path_info->peer->tunnels[i], path_info->peer); |
1914 | GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1)); | ||
1915 | p->peers[p->length] = GNUNET_PEER_intern (put_path[i]); | ||
1916 | p->length++; | ||
1917 | } | ||
1918 | add_path_to_peer (peer_info, p); | ||
1919 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | ||
1920 | GNUNET_TIME_UNIT_FOREVER_REL, get_path[1], | ||
1921 | sizeof (struct GNUNET_MESH_ManipulatePath) | ||
1922 | + | ||
1923 | (p->length * | ||
1924 | sizeof (struct GNUNET_PeerIdentity)), | ||
1925 | &send_core_create_path_for_peer, | ||
1926 | peer_info); | ||
1927 | if (0 == peer_info->path_refresh_task) | ||
1928 | { | ||
1929 | peer_info->path_refresh_task = | ||
1930 | GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, | ||
1931 | peer_info); | ||
1932 | } | 2268 | } |
2269 | GNUNET_free(path_info); | ||
2270 | |||
1933 | return; | 2271 | return; |
1934 | } | 2272 | } |
1935 | 2273 | ||
@@ -1962,7 +2300,7 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
1962 | struct GNUNET_PeerIdentity id; | 2300 | struct GNUNET_PeerIdentity id; |
1963 | struct MeshTunnel *t = cls; | 2301 | struct MeshTunnel *t = cls; |
1964 | struct MeshPeerInfo *peer_info; | 2302 | struct MeshPeerInfo *peer_info; |
1965 | struct MeshPath *p; | 2303 | struct MeshPeerPath *p; |
1966 | int i; | 2304 | int i; |
1967 | 2305 | ||
1968 | if (size != sizeof (struct GNUNET_PeerIdentity)) | 2306 | if (size != sizeof (struct GNUNET_PeerIdentity)) |
@@ -1973,12 +2311,12 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
1973 | GNUNET_assert (NULL != t->client); | 2311 | GNUNET_assert (NULL != t->client); |
1974 | GNUNET_DHT_get_stop (t->client->dht_get_type); | 2312 | GNUNET_DHT_get_stop (t->client->dht_get_type); |
1975 | t->client->dht_get_type = NULL; | 2313 | t->client->dht_get_type = NULL; |
1976 | peer_info = get_peer_info (pi); | 2314 | peer_info = peer_info_get (pi); |
1977 | GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, peer_info, | 2315 | GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, peer_info, |
1978 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | 2316 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); |
1979 | 2317 | ||
1980 | if ((NULL == get_path || NULL == put_path) && | 2318 | if ((NULL == get_path || NULL == put_path) && |
1981 | NULL == peer_info->path && | 2319 | NULL == peer_info->path_head && |
1982 | NULL == peer_info->dhtget) | 2320 | NULL == peer_info->dhtget) |
1983 | { | 2321 | { |
1984 | /* we don't have a route to the peer, let's try a direct lookup */ | 2322 | /* we don't have a route to the peer, let's try a direct lookup */ |
@@ -1997,24 +2335,8 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
1997 | peer_info); /* closure */ | 2335 | peer_info); /* closure */ |
1998 | } | 2336 | } |
1999 | 2337 | ||
2000 | p = GNUNET_malloc (sizeof (struct MeshPath)); | 2338 | p = path_build_from_dht(get_path, put_path); |
2001 | for (i = 0; get_path[i] != NULL; i++) ; | 2339 | path_add_to_peer (peer_info, p); |
2002 | for (i--; i >= 0; i--) | ||
2003 | { | ||
2004 | p->peers = | ||
2005 | GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1)); | ||
2006 | p->peers[p->length] = GNUNET_PEER_intern (get_path[i]); | ||
2007 | p->length++; | ||
2008 | } | ||
2009 | for (i = 0; put_path[i] != NULL; i++) ; | ||
2010 | for (i--; i >= 0; i--) | ||
2011 | { | ||
2012 | p->peers = | ||
2013 | GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1)); | ||
2014 | p->peers[p->length] = GNUNET_PEER_intern (put_path[i]); | ||
2015 | p->length++; | ||
2016 | } | ||
2017 | add_path_to_peer (peer_info, p); | ||
2018 | #if MESH_DEBUG | 2340 | #if MESH_DEBUG |
2019 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | 2341 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, |
2020 | "MESH: new route for tunnel 0x%x found, has %u hops\n", | 2342 | "MESH: new route for tunnel 0x%x found, has %u hops\n", |
@@ -2039,7 +2361,7 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
2039 | &id, /* target */ | 2361 | &id, /* target */ |
2040 | sizeof (struct GNUNET_MESH_ManipulatePath) + | 2362 | sizeof (struct GNUNET_MESH_ManipulatePath) + |
2041 | (p->length * sizeof (struct GNUNET_PeerIdentity)), /*size */ | 2363 | (p->length * sizeof (struct GNUNET_PeerIdentity)), /*size */ |
2042 | &send_core_create_path_for_peer, /* callback */ | 2364 | &send_core_create_path, /* callback */ |
2043 | peer_info); /* cls */ | 2365 | peer_info); /* cls */ |
2044 | } | 2366 | } |
2045 | 2367 | ||
@@ -2217,7 +2539,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, | |||
2217 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new tunnel requested\n"); | 2539 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new tunnel requested\n"); |
2218 | 2540 | ||
2219 | /* Sanity check for client registration */ | 2541 | /* Sanity check for client registration */ |
2220 | if (NULL == (c = retrieve_client (client))) | 2542 | if (NULL == (c = client_get (client))) |
2221 | { | 2543 | { |
2222 | GNUNET_break (0); | 2544 | GNUNET_break (0); |
2223 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2545 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2241,7 +2563,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, | |||
2241 | return; | 2563 | return; |
2242 | } | 2564 | } |
2243 | /* Sanity check for duplicate tunnel IDs */ | 2565 | /* Sanity check for duplicate tunnel IDs */ |
2244 | if (NULL != retrieve_tunnel_by_local_id (c, ntohl (t_msg->tunnel_id))) | 2566 | if (NULL != tunnel_get_by_local_id (c, ntohl (t_msg->tunnel_id))) |
2245 | { | 2567 | { |
2246 | GNUNET_break (0); | 2568 | GNUNET_break (0); |
2247 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2569 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2249,7 +2571,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, | |||
2249 | } | 2571 | } |
2250 | 2572 | ||
2251 | t = GNUNET_malloc (sizeof (struct MeshTunnel)); | 2573 | t = GNUNET_malloc (sizeof (struct MeshTunnel)); |
2252 | while (NULL != retrieve_tunnel_by_pi (myid, next_tid)) | 2574 | while (NULL != tunnel_get_by_pi (myid, next_tid)) |
2253 | next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; | 2575 | next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; |
2254 | t->id.tid = next_tid++; | 2576 | t->id.tid = next_tid++; |
2255 | t->id.oid = myid; | 2577 | t->id.oid = myid; |
@@ -2302,7 +2624,7 @@ handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client, | |||
2302 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: destroying tunnel\n"); | 2624 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: destroying tunnel\n"); |
2303 | 2625 | ||
2304 | /* Sanity check for client registration */ | 2626 | /* Sanity check for client registration */ |
2305 | if (NULL == (c = retrieve_client (client))) | 2627 | if (NULL == (c = client_get (client))) |
2306 | { | 2628 | { |
2307 | GNUNET_break (0); | 2629 | GNUNET_break (0); |
2308 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2630 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2342,6 +2664,8 @@ handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client, | |||
2342 | * @param cls closure | 2664 | * @param cls closure |
2343 | * @param client identification of the client | 2665 | * @param client identification of the client |
2344 | * @param message the actual message (PeerControl) | 2666 | * @param message the actual message (PeerControl) |
2667 | * | ||
2668 | * FIXME path | ||
2345 | */ | 2669 | */ |
2346 | static void | 2670 | static void |
2347 | handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client, | 2671 | handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client, |
@@ -2355,7 +2679,7 @@ handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client, | |||
2355 | 2679 | ||
2356 | 2680 | ||
2357 | /* Sanity check for client registration */ | 2681 | /* Sanity check for client registration */ |
2358 | if (NULL == (c = retrieve_client (client))) | 2682 | if (NULL == (c = client_get (client))) |
2359 | { | 2683 | { |
2360 | GNUNET_break (0); | 2684 | GNUNET_break (0); |
2361 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2685 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2373,7 +2697,7 @@ handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client, | |||
2373 | 2697 | ||
2374 | /* Tunnel exists? */ | 2698 | /* Tunnel exists? */ |
2375 | tid = ntohl (peer_msg->tunnel_id); | 2699 | tid = ntohl (peer_msg->tunnel_id); |
2376 | t = retrieve_tunnel_by_local_id (c, tid); | 2700 | t = tunnel_get_by_local_id (c, tid); |
2377 | if (NULL == t) | 2701 | if (NULL == t) |
2378 | { | 2702 | { |
2379 | GNUNET_break (0); | 2703 | GNUNET_break (0); |
@@ -2390,10 +2714,10 @@ handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client, | |||
2390 | } | 2714 | } |
2391 | 2715 | ||
2392 | t->peers_total++; | 2716 | t->peers_total++; |
2393 | peer_info = get_peer_info (&peer_msg->peer); | 2717 | peer_info = peer_info_get (&peer_msg->peer); |
2394 | 2718 | ||
2395 | /* Start DHT search if needed */ | 2719 | /* Start DHT search if needed FIXME: if not already connected */ |
2396 | if (MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) | 2720 | if (NULL == peer_info->dhtget) |
2397 | { | 2721 | { |
2398 | peer_info->dhtget = GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BLOCK_TYPE_TEST, &peer_msg->peer.hashPubKey, 4, /* replication level */ | 2722 | peer_info->dhtget = GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BLOCK_TYPE_TEST, &peer_msg->peer.hashPubKey, 4, /* replication level */ |
2399 | GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */ | 2723 | GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */ |
@@ -2426,7 +2750,7 @@ handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client, | |||
2426 | MESH_TunnelNumber tid; | 2750 | MESH_TunnelNumber tid; |
2427 | 2751 | ||
2428 | /* Sanity check for client registration */ | 2752 | /* Sanity check for client registration */ |
2429 | if (NULL == (c = retrieve_client (client))) | 2753 | if (NULL == (c = client_get (client))) |
2430 | { | 2754 | { |
2431 | GNUNET_break (0); | 2755 | GNUNET_break (0); |
2432 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2756 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2443,7 +2767,7 @@ handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client, | |||
2443 | 2767 | ||
2444 | /* Tunnel exists? */ | 2768 | /* Tunnel exists? */ |
2445 | tid = ntohl (peer_msg->tunnel_id); | 2769 | tid = ntohl (peer_msg->tunnel_id); |
2446 | t = retrieve_tunnel_by_local_id (c, tid); | 2770 | t = tunnel_get_by_local_id (c, tid); |
2447 | if (NULL == t) | 2771 | if (NULL == t) |
2448 | { | 2772 | { |
2449 | GNUNET_break (0); | 2773 | GNUNET_break (0); |
@@ -2488,7 +2812,7 @@ handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client, | |||
2488 | 2812 | ||
2489 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got connect by type request\n"); | 2813 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got connect by type request\n"); |
2490 | /* Sanity check for client registration */ | 2814 | /* Sanity check for client registration */ |
2491 | if (NULL == (c = retrieve_client (client))) | 2815 | if (NULL == (c = client_get (client))) |
2492 | { | 2816 | { |
2493 | GNUNET_break (0); | 2817 | GNUNET_break (0); |
2494 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2818 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2507,7 +2831,7 @@ handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client, | |||
2507 | 2831 | ||
2508 | /* Tunnel exists? */ | 2832 | /* Tunnel exists? */ |
2509 | tid = ntohl (connect_msg->tunnel_id); | 2833 | tid = ntohl (connect_msg->tunnel_id); |
2510 | t = retrieve_tunnel_by_local_id (c, tid); | 2834 | t = tunnel_get_by_local_id (c, tid); |
2511 | if (NULL == t) | 2835 | if (NULL == t) |
2512 | { | 2836 | { |
2513 | GNUNET_break (0); | 2837 | GNUNET_break (0); |
@@ -2538,7 +2862,7 @@ handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client, | |||
2538 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: available locally\n"); | 2862 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: available locally\n"); |
2539 | pc.peer = my_full_id; | 2863 | pc.peer = my_full_id; |
2540 | GNUNET_CONTAINER_multihashmap_put (t->peers, &pc.peer.hashPubKey, | 2864 | GNUNET_CONTAINER_multihashmap_put (t->peers, &pc.peer.hashPubKey, |
2541 | get_peer_info (&pc.peer), | 2865 | peer_info_get (&pc.peer), |
2542 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | 2866 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); |
2543 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); | 2867 | pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); |
2544 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); | 2868 | pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); |
@@ -2591,7 +2915,7 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, | |||
2591 | size_t data_size; | 2915 | size_t data_size; |
2592 | 2916 | ||
2593 | /* Sanity check for client registration */ | 2917 | /* Sanity check for client registration */ |
2594 | if (NULL == (c = retrieve_client (client))) | 2918 | if (NULL == (c = client_get (client))) |
2595 | { | 2919 | { |
2596 | GNUNET_break (0); | 2920 | GNUNET_break (0); |
2597 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2921 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2609,7 +2933,7 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, | |||
2609 | 2933 | ||
2610 | /* Tunnel exists? */ | 2934 | /* Tunnel exists? */ |
2611 | tid = ntohl (data_msg->tid); | 2935 | tid = ntohl (data_msg->tid); |
2612 | t = retrieve_tunnel_by_local_id (c, tid); | 2936 | t = tunnel_get_by_local_id (c, tid); |
2613 | if (NULL == t) | 2937 | if (NULL == t) |
2614 | { | 2938 | { |
2615 | GNUNET_break (0); | 2939 | GNUNET_break (0); |
@@ -2645,7 +2969,7 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, | |||
2645 | handle_mesh_data_unicast (NULL, &my_full_id, ©.header, NULL); | 2969 | handle_mesh_data_unicast (NULL, &my_full_id, ©.header, NULL); |
2646 | return; | 2970 | return; |
2647 | } | 2971 | } |
2648 | GNUNET_PEER_resolve (get_first_hop (pi->path), &next_hop); | 2972 | GNUNET_PEER_resolve (path_get_first_hop (t, pi)->id, &next_hop); |
2649 | data_size = ntohs (message->size) - sizeof (struct GNUNET_MESH_Unicast); | 2973 | data_size = ntohs (message->size) - sizeof (struct GNUNET_MESH_Unicast); |
2650 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + data_size); | 2974 | info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + data_size); |
2651 | memcpy (&info[1], &data_msg[1], data_size); | 2975 | memcpy (&info[1], &data_msg[1], data_size); |
@@ -2679,7 +3003,7 @@ handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client, | |||
2679 | MESH_TunnelNumber tid; | 3003 | MESH_TunnelNumber tid; |
2680 | 3004 | ||
2681 | /* Sanity check for client registration */ | 3005 | /* Sanity check for client registration */ |
2682 | if (NULL == (c = retrieve_client (client))) | 3006 | if (NULL == (c = client_get (client))) |
2683 | { | 3007 | { |
2684 | GNUNET_break (0); | 3008 | GNUNET_break (0); |
2685 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 3009 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
@@ -2696,7 +3020,7 @@ handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client, | |||
2696 | 3020 | ||
2697 | /* Tunnel exists? */ | 3021 | /* Tunnel exists? */ |
2698 | tid = ntohl (data_msg->tid); | 3022 | tid = ntohl (data_msg->tid); |
2699 | t = retrieve_tunnel_by_local_id (c, tid); | 3023 | t = tunnel_get_by_local_id (c, tid); |
2700 | if (NULL == t) | 3024 | if (NULL == t) |
2701 | { | 3025 | { |
2702 | GNUNET_break (0); | 3026 | GNUNET_break (0); |
@@ -2782,20 +3106,20 @@ core_connect (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
2782 | { | 3106 | { |
2783 | // GNUNET_PEER_Id pid; | 3107 | // GNUNET_PEER_Id pid; |
2784 | struct MeshPeerInfo *peer_info; | 3108 | struct MeshPeerInfo *peer_info; |
2785 | struct MeshPath *path; | 3109 | struct MeshPeerPath *path; |
2786 | 3110 | ||
2787 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer connected\n"); | 3111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer connected\n"); |
2788 | peer_info = get_peer_info (peer); | 3112 | peer_info = peer_info_get (peer); |
2789 | if (myid == peer_info->id) | 3113 | if (myid == peer_info->id) |
2790 | { | 3114 | { |
2791 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (self)\n"); | 3115 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (self)\n"); |
2792 | } | 3116 | } |
2793 | path = GNUNET_malloc (sizeof (struct MeshPath)); | 3117 | path = GNUNET_malloc (sizeof (struct MeshPeerPath)); |
2794 | path->length = 2; | 3118 | path->length = 2; |
2795 | path->peers = GNUNET_malloc (sizeof (GNUNET_PEER_Id) * 2); | 3119 | path->peers = GNUNET_malloc (sizeof (GNUNET_PEER_Id) * 2); |
2796 | path->peers[0] = myid; | 3120 | path->peers[0] = myid; |
2797 | path->peers[1] = peer_info->id; | 3121 | path->peers[1] = peer_info->id; |
2798 | add_path_to_peer (peer_info, path); | 3122 | path_add_to_peer (peer_info, path); |
2799 | return; | 3123 | return; |
2800 | } | 3124 | } |
2801 | 3125 | ||
@@ -2827,6 +3151,7 @@ core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) | |||
2827 | GNUNET_free (pi->infos[i]); | 3151 | GNUNET_free (pi->infos[i]); |
2828 | } | 3152 | } |
2829 | } | 3153 | } |
3154 | path_remove_from_peer (pi, pi->id, myid); | ||
2830 | if (myid == pi->id) | 3155 | if (myid == pi->id) |
2831 | { | 3156 | { |
2832 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (self)\n"); | 3157 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (self)\n"); |