-GCP_connect (struct CadetPeer *peer)
-{
- struct CadetTunnel *t;
- struct CadetPeerPath *path;
- struct CadetConnection *c;
- int rerun_search;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "peer_connect towards %s\n",
- GCP_2s (peer));
- /* If we have a current hello, try to connect using it. */
- GCP_try_connect (peer);
-
- t = peer->tunnel;
- c = NULL;
- rerun_search = GNUNET_NO;
-
- if (NULL != peer->path_head)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " some path exists\n");
- path = peer_get_best_path (peer);
- if (NULL != path)
- {
- char *s;
-
- s = path_2s (path);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " path to use: %s\n", s);
- GNUNET_free (s);
-
- c = GCT_use_path (t, path);
- if (NULL == c)
- {
- /* This case can happen when the path includes a first hop that is
- * not yet known to be connected.
- *
- * This happens quite often during testing when running cadet
- * under valgrind: core connect notifications come very late
- * and the DHT result has already come and created a valid
- * path. In this case, the peer->connections
- * hashmaps will be NULL and tunnel_use_path will not be able
- * to create a connection from that path.
- *
- * Re-running the DHT GET should give core time to callback.
- *
- * GCT_use_path -> GCC_new -> register_neighbors takes care of
- * updating statistics about this issue.
- */
- rerun_search = GNUNET_YES;
- }
- else
- {
- GCC_send_create (c);
- return;
- }
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " but is NULL, all paths are in use\n");
- }
- }
-
- if (GNUNET_YES == rerun_search)
- {
- struct GNUNET_TIME_Relative delay;
-
- GCP_stop_search (peer);
- delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
- peer->search_delayed = GNUNET_SCHEDULER_add_delayed (delay,
- &delayed_search,
- peer);
- GCC_check_connections ();
- return;
- }
-
- if (GNUNET_NO == is_searching (peer))
- GCP_start_search (peer);
- GCC_check_connections ();
-}
-
-
-/**
- * Chech whether there is a direct (core level) connection to peer.
- *
- * @param peer Peer to check.
- *
- * @return #GNUNET_YES if there is a direct connection.
- */
-int
-GCP_is_neighbor (const struct CadetPeer *peer)
-{
- struct CadetPeerPath *path;
-
- if (NULL == peer->connections)
- return GNUNET_NO;
-
- for (path = peer->path_head; NULL != path; path = path->next)
- {
- if (3 > path->length)
- return GNUNET_YES;
- }
-
- /* Is not a neighbor but connections is not NULL, probably disconnecting */
- return GNUNET_NO;
-}
-
-
-/**
- * Create and initialize a new tunnel towards a peer, in case it has none.
- * In case the peer already has a tunnel, nothing is done.
- *
- * Does not generate any traffic, just creates the local data structures.
- *
- * @param peer Peer towards which to create the tunnel.
- */
-void
-GCP_add_tunnel (struct CadetPeer *peer)
-{
- GCC_check_connections ();
- if (NULL != peer->tunnel)
- return;
- peer->tunnel = GCT_new (peer);
- GCC_check_connections ();
-}
-
-
-/**
- * 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)