-/**
- * Add a connection to a neighboring peer.
- *
- * Store that the peer is the first hop of the connection in one
- * direction and that on peer disconnect the connection must be
- * notified and destroyed, for it will no longer be valid.
- *
- * @param peer Peer to add connection to.
- * @param c Connection to add.
- * @param pred #GNUNET_YES if we are predecessor, #GNUNET_NO if we are successor
- */
-void
-GCP_add_connection (struct CadetPeer *peer,
- struct CadetConnection *c,
- int pred)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "adding connection %s\n",
- GCC_2s (c));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "to peer %s\n",
- GCP_2s (peer));
- GNUNET_assert (NULL != peer->connections);
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (peer->connections,
- GCC_get_h (c),
- c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Peer %s has now %u connections.\n",
- GCP_2s (peer),
- GNUNET_CONTAINER_multihashmap_size (peer->connections));
-}
-
-
-/**
- * Add the path to the peer and update the path used to reach it in case this
- * is the shortest.
- *
- * @param peer Destination peer to add the path to.
- * @param path New path to add. Last peer must be @c peer.
- * Path will be either used of freed if already known.
- * @param trusted Do we trust that this path is real?
- *
- * @return path if path was taken, pointer to existing duplicate if exists
- * NULL on error.
- */
-struct CadetPeerPath *
-GCP_add_path (struct CadetPeer *peer,
- struct CadetPeerPath *path,
- int trusted)
-{
- struct CadetPeerPath *aux;
- unsigned int l;
- unsigned int l2;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "adding path [%u] to peer %s\n",
- path->length, GCP_2s (peer));
-
- if (NULL == peer || NULL == path
- || path->peers[path->length - 1] != peer->id)
- {
- GNUNET_break (0);
- path_destroy (path);
- return NULL;
- }
-
- for (l = 1; l < path->length; l++)
- {
- if (path->peers[l] == myid)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " shortening path by %u\n", l);
- for (l2 = 0; l2 < path->length - l; l2++)
- {
- path->peers[l2] = path->peers[l + l2];
- }
- path->length -= l;
- l = 1;
- path->peers = GNUNET_realloc (path->peers,
- path->length * sizeof (GNUNET_PEER_Id));
- }
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length);
-
- if (2 >= path->length && GNUNET_NO == trusted)
- {
- /* Only allow CORE to tell us about direct paths */
- path_destroy (path);
- return NULL;
- }
-
- l = path_get_length (path);
- if (0 == l)
- {
- path_destroy (path);
- return NULL;
- }
-
- GNUNET_assert (peer->id == path->peers[path->length - 1]);
- for (aux = peer->path_head; aux != NULL; aux = aux->next)
- {
- l2 = path_get_length (aux);
- if (l2 > l)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " added\n");
- GNUNET_CONTAINER_DLL_insert_before (peer->path_head,
- peer->path_tail, aux, path);
- goto finish;
- }
- else
- {
- if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " already known\n");
- path_destroy (path);
- return aux;
- }
- }
- }
- GNUNET_CONTAINER_DLL_insert_tail (peer->path_head,
- peer->path_tail,
- path);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " added last\n");
-
-finish:
- if (NULL != peer->tunnel
- && CONNECTIONS_PER_TUNNEL > GCT_count_connections (peer->tunnel)
- && 2 < path->length) /* Direct paths are handled by core_connect */
- {
- GCP_connect (peer);
- }
- GCC_check_connections ();
- return path;
-}
-
-
-/**
- * Add the path to the origin peer and update the path used to reach it in case
- * this is the shortest.
- * The path is given in peer_info -> destination, therefore we turn the path
- * upside down first.
- *
- * @param peer Peer to add the path to, being the origin of the path.
- * @param path New path to add after being inversed.
- * Path will be either used or freed.
- * @param trusted Do we trust that this path is real?
- *
- * @return path if path was taken, pointer to existing duplicate if exists
- * NULL on error.
- */
-struct CadetPeerPath *
-GCP_add_path_to_origin (struct CadetPeer *peer,
- struct CadetPeerPath *path,
- int trusted)
-{
- if (NULL == path)
- return NULL;
- path_invert (path);
- return GCP_add_path (peer, path, trusted);
-}
-
-
-/**
- * Adds a path to the info of all the peers in the path
- *
- * @param p Path to process.
- * @param confirmed Whether we know if the path works or not.
- */
-void
-GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed)
-{
- unsigned int i;
-
- /* TODO: invert and add to origin */
- /* TODO: replace all "GCP_add_path" with this, make the other one static */
- GCC_check_connections ();
- for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
- for (i++; i < p->length; i++)
- {
- struct CadetPeer *peer;
- struct CadetPeerPath *copy;
-
- peer = GCP_get_short (p->peers[i], GNUNET_YES);
- copy = path_duplicate (p);
- copy->length = i + 1;
- GCP_add_path (peer, copy, 3 > p->length ? GNUNET_NO : confirmed);
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Remove any path to the peer that has the exact same peers as the one given.
- *
- * @param peer Peer to remove the path from.
- * @param path Path to remove. Is always destroyed .
- */
-void
-GCP_remove_path (struct CadetPeer *peer,
- struct CadetPeerPath *path)
-{
- struct CadetPeerPath *iter;
- struct CadetPeerPath *next;
-
- GCC_check_connections ();
- GNUNET_assert (myid == path->peers[0]);
- GNUNET_assert (peer->id == path->peers[path->length - 1]);
-
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Removing path %p (%u) from %s\n",
- path, path->length, GCP_2s (peer));
-
- for (iter = peer->path_head; NULL != iter; iter = next)
- {
- next = iter->next;
- if (0 == path_cmp (path, iter))
- {
- GNUNET_CONTAINER_DLL_remove (peer->path_head,
- peer->path_tail,
- iter);
- if (iter != path)
- path_destroy (iter);
- }
- }
- path_destroy (path);
- GCC_check_connections ();
-}
-
-
-/**
- * Check that we are aware of a connection from a neighboring peer.
- *
- * @param peer Peer to the connection is with
- * @param c Connection that should be in the map with this peer.
- */
-void
-GCP_check_connection (const struct CadetPeer *peer,
- const struct CadetConnection *c)
-{
- GNUNET_assert (NULL != peer);
- GNUNET_assert (NULL != peer->connections);
- return;
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_contains_value (peer->connections,
- GCC_get_h (c),
- c));
-}
-
-
-/**
- * Remove a connection from a neighboring peer.
- *
- * @param peer Peer to remove connection from.
- * @param c Connection to remove.
- */
-void
-GCP_remove_connection (struct CadetPeer *peer,
- const struct CadetConnection *c)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Removing connection %s\n",
- GCC_2s (c));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "from peer %s\n",
- GCP_2s (peer));
- if ( (NULL == peer) ||
- (NULL == peer->connections) )
- return;
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (peer->connections,
- GCC_get_h (c),
- c));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Peer %s remains with %u connections.\n",
- GCP_2s (peer),
- GNUNET_CONTAINER_multihashmap_size (peer->connections));
-}
-
-
-/**
- * Start the DHT search for new paths towards the peer: we don't have
- * enough good connections.
- *
- * @param peer Destination peer.
- */
-void
-GCP_start_search (struct CadetPeer *peer)
-{
- const struct GNUNET_PeerIdentity *id;
- struct CadetTunnel *t = peer->tunnel;
-
- GCC_check_connections ();
- if (NULL != peer->search_h)
- {
- GNUNET_break (0);
- return;
- }
-
- if (NULL != peer->search_delayed)
- GCP_stop_search (peer);
-
- id = GNUNET_PEER_resolve2 (peer->id);
- peer->search_h = GCD_search (id, &search_handler, peer);
-
- if (NULL == t)
- {
- /* Why would we search for a peer with no tunnel towards it? */
- GNUNET_break (0);
- return;
- }
-
- if (CADET_TUNNEL_NEW == GCT_get_cstate (t)
- || 0 == GCT_count_any_connections (t))
- {
- GCT_change_cstate (t, CADET_TUNNEL_SEARCHING);
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Stop the DHT search for new paths towards the peer: we already have
- * enough good connections.
- *
- * @param peer Destination peer.
- */
-void
-GCP_stop_search (struct CadetPeer *peer)
-{
- GCC_check_connections ();
- if (NULL != peer->search_h)
- {
- GCD_search_stop (peer->search_h);
- peer->search_h = NULL;
- }
- if (NULL != peer->search_delayed)
- {
- GNUNET_SCHEDULER_cancel (peer->search_delayed);
- peer->search_delayed = NULL;
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Get the Full ID of a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Full ID of peer.
- */
-const struct GNUNET_PeerIdentity *
-GCP_get_id (const struct CadetPeer *peer)
-{
- return GNUNET_PEER_resolve2 (peer->id);
-}
-
-
-/**
- * Get the Short ID of a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Short ID of peer.
- */
-GNUNET_PEER_Id
-GCP_get_short_id (const struct CadetPeer *peer)
-{
- return peer->id;
-}
-
-
-/**
- * Set tunnel.
- *
- * If tunnel is NULL and there was a search active, stop it, as it's useless.
- *
- * @param peer Peer.
- * @param t Tunnel.
- */
-void
-GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t)
-{
- peer->tunnel = t;
- if (NULL == t && GNUNET_YES == is_searching (peer))
- {
- GCP_stop_search (peer);
- }
-}
-
-
-/**
- * Get the tunnel towards a peer.
- *
- * @param peer Peer to get from.
- *
- * @return Tunnel towards peer.
- */
-struct CadetTunnel *
-GCP_get_tunnel (const struct CadetPeer *peer)
-{
- if (NULL == peer)
- return NULL;
- return peer->tunnel;
-}
-
-
-/**
- * Set the hello message.
- *
- * @param peer Peer whose message to set.
- * @param hello Hello message.
- */
-void
-GCP_set_hello (struct CadetPeer *peer,
- const struct GNUNET_HELLO_Message *hello)
-{
- struct GNUNET_HELLO_Message *old;
- size_t size;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GCP_2s (peer));
- if (NULL == hello)
- return;
-
- old = GCP_get_hello (peer);
- if (NULL == old)
- {
- size = GNUNET_HELLO_size (hello);
- peer->hello = GNUNET_malloc (size);
- GNUNET_memcpy (peer->hello, hello, size);
- }
- else
- {
- peer->hello = GNUNET_HELLO_merge (old, hello);
- GNUNET_free (old);
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Get the hello message.
- *
- * @param peer Peer whose message to get.
- *
- * @return Hello message.
- */
-struct GNUNET_HELLO_Message *
-GCP_get_hello (struct CadetPeer *peer)
-{
- struct GNUNET_TIME_Absolute expiration;
- struct GNUNET_TIME_Relative remaining;
-
- if (NULL == peer->hello)
- return NULL;
-
- expiration = GNUNET_HELLO_get_last_expiration (peer->hello);
- remaining = GNUNET_TIME_absolute_get_remaining (expiration);
- if (0 == remaining.rel_value_us)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n",
- GNUNET_STRINGS_absolute_time_to_string (expiration));
- GNUNET_free (peer->hello);
- peer->hello = NULL;
- }
- return peer->hello;
-}
-
-
-/**
- * Try to connect to a peer on TRANSPORT level.
- *
- * @param peer Peer to whom to connect.
- */
-void
-GCP_try_connect (struct CadetPeer *peer)
-{
- struct GNUNET_HELLO_Message *hello;
- struct GNUNET_MessageHeader *mh;
-
- if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (cfg,
- "CADET",
- "DISABLE_TRY_CONNECT"))
- return;
- GCC_check_connections ();
- if (GNUNET_YES == GCP_is_neighbor (peer))
- return;
- hello = GCP_get_hello (peer);
- if (NULL == hello)
- return;
-
- mh = GNUNET_HELLO_get_header (hello);
- if (NULL != peer->hello_offer)
- {
- GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer);
- peer->hello_offer = NULL;
- }
- peer->hello_offer = GNUNET_TRANSPORT_offer_hello (cfg,
- mh,
- &hello_offer_done,
- peer);
- if (NULL == peer->connectivity_suggestion)
- peer->connectivity_suggestion
- = GNUNET_ATS_connectivity_suggest (ats_ch,
- GNUNET_PEER_resolve2 (peer->id),
- 1 /* strength */);
- GCC_check_connections ();
-}
-
-
-/**
- * Notify a peer that a link between two other peers is broken. If any path
- * used that link, eliminate it.
- *
- * @param peer Peer affected by the change.
- * @param peer1 Peer whose link is broken.
- * @param peer2 Peer whose link is broken.
- */
-void
-GCP_notify_broken_link (struct CadetPeer *peer,
- const struct GNUNET_PeerIdentity *peer1,
- const struct GNUNET_PeerIdentity *peer2)
-{
- struct CadetPeerPath *iter;
- struct CadetPeerPath *next;
- unsigned int i;
- GNUNET_PEER_Id p1;
- GNUNET_PEER_Id p2;
-
- GCC_check_connections ();
- p1 = GNUNET_PEER_search (peer1);
- p2 = GNUNET_PEER_search (peer2);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2);
- if (0 == p1 || 0 == p2)
- {
- /* We don't even know them */
- return;
- }
-
- for (iter = peer->path_head; NULL != iter; iter = next)
- {
- next = iter->next;
- for (i = 0; i < iter->length - 1; i++)
- {
- if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2)
- || (iter->peers[i] == p2 && iter->peers[i + 1] == p1))
- {
- char *s;
-
- s = path_2s (iter);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s);
- GNUNET_free (s);
-
- path_invalidate (iter);
- }
- }
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Count the number of known paths toward the peer.
- *
- * @param peer Peer to get path info.
- *
- * @return Number of known paths.
- */
-unsigned int
-GCP_count_paths (const struct CadetPeer *peer)
-{
- struct CadetPeerPath *iter;
- unsigned int i;
-
- for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next)
- i++;
-
- return i;
-}
-
-
-/**
- * Iterate over the paths to a peer.
- *
- * @param peer Peer to get path info.
- * @param callback Function to call for every path.
- * @param cls Closure for @a callback.
- *
- * @return Number of iterated paths.
- */
-unsigned int
-GCP_iterate_paths (struct CadetPeer *peer,
- GCP_path_iterator callback,
- void *cls)
-{
- struct CadetPeerPath *iter;
- unsigned int i;
-
- for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next)
- {
- i++;
- if (GNUNET_YES != callback (cls, peer, iter))
- break;
- }
-
- return i;
-}
-
-
-/**
- * Iterate all known peers.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
- void *cls)
-{
- GCC_check_connections ();
- GNUNET_CONTAINER_multipeermap_iterate (peers,
- iter,
- cls);
- GCC_check_connections ();
-}
-
-
-/**
- * Get the static string for a peer ID.
- *
- * @param peer Peer.
- *
- * @return Static string for it's ID.
- */
-const char *
-GCP_2s (const struct CadetPeer *peer)
-{
- if (NULL == peer)
- return "(NULL)";
- return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
-}