- * This funcion removes the message from the queue.
- *
- * @param q Queue handle.
- * @param sent #GNUNET_YES if was sent to CORE, #GNUNET_NO if dropped.
- */
-static void
-call_peer_cont (struct CadetPeerQueue *q, int sent)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, " core mq just sent %s\n", GC_m2s (q->type));
- if (NULL != q->cont)
- {
- struct GNUNET_TIME_Relative wait_time;
-
- wait_time = GNUNET_TIME_absolute_get_duration (q->queue_timestamp);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " calling callback on %s after %s\n",
- GCC_2s (q->c),
- GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO));
- q->cont (q->cont_cls,
- q->c, q->c_fwd, sent,
- q->type, q->payload_type, q->payload_id,
- q->size, wait_time);
- q->cont = NULL;
- }
- GNUNET_CONTAINER_DLL_remove (q->peer->q_head, q->peer->q_tail, q);
-}
-
-
-/**
- * Function called by MQ when a message is sent to CORE.
- *
- * @param cls Closure (queue handle).
- */
-static void
-mq_sent (void *cls)
-{
- struct CadetPeerQueue *q = cls;
-
- if (GNUNET_NO == q->management_traffic)
- {
- q->peer->queue_n--;
- }
- call_peer_cont (q, GNUNET_YES);
- GNUNET_free (q);
-}
-
-
-/**
- * @brief Send a message to another peer (using CORE).
- *
- * @param peer Peer towards which to queue the message.
- * @param message Message to send.
- * @param payload_type Type of the message's payload, for debug messages.
- * 0 if the message is a retransmission (unknown payload).
- * UINT16_MAX if the message does not have payload.
- * @param payload_id ID of the payload (MID, ACK #, etc)
- * @param c Connection this message belongs to (can be NULL).
- * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
- * @param cont Continuation to be called once CORE has sent the message.
- * @param cont_cls Closure for @c cont.
- *
- * @return A handle to the message in the queue or NULL (if dropped).
- */
-struct CadetPeerQueue *
-GCP_send (struct CadetPeer *peer,
- const struct GNUNET_MessageHeader *message,
- uint16_t payload_type,
- uint32_t payload_id,
- struct CadetConnection *c,
- int fwd,
- GCP_sent cont,
- void *cont_cls)
-{
- struct CadetPeerQueue *q;
- uint16_t type;
- uint16_t size;
-
- GCC_check_connections ();
- type = ntohs (message->type);
- size = ntohs (message->size);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "que %s (%s %4u) on conn %s (%p) %s towards %s (size %u)\n",
- GC_m2s (type), GC_m2s (payload_type), payload_id,
- GCC_2s (c), c, GC_f2s (fwd), GCP_2s (peer), size);
-
- if (NULL == peer->connections)
- {
- /* We are not connected to this peer, ignore request. */
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_INFO, "%s not a neighbor\n", GCP_2s (peer));
- GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1,
- GNUNET_NO);
- return NULL;
- }
-
- q = GNUNET_new (struct CadetPeerQueue);
- q->env = GNUNET_MQ_msg_copy (message);
- q->peer = peer;
- q->cont = cont;
- q->cont_cls = cont_cls;
- q->queue_timestamp = GNUNET_TIME_absolute_get ();
- q->management_traffic = is_connection_management (type);
- q->type = type;
- q->size = size;
- q->payload_type = payload_type;
- q->payload_id = payload_id;
- q->c = c;
- q->c_fwd = fwd;
- GNUNET_MQ_notify_sent (q->env, &mq_sent, q);
- GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q);
-
- if (GNUNET_YES == q->management_traffic)
- {
- GNUNET_MQ_send (peer->core_mq, q->env); // FIXME implement "_urgent", use
- }
- else
- {
- if (GNUNET_YES == should_I_drop ())
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s (%s %u) on conn %s %s\n",
- GC_m2s (q->type), GC_m2s (q->payload_type),
- q->payload_id, GCC_2s (c), GC_f2s (q->c_fwd));
- GNUNET_MQ_discard (q->env);
- call_peer_cont (q, GNUNET_YES);
- GNUNET_CONTAINER_DLL_remove (peer->q_head, peer->q_tail, q);
- GNUNET_free (q);
- return NULL;
- }
- GNUNET_MQ_send (peer->core_mq, q->env);
- peer->queue_n++;
- }
-
- GCC_check_connections ();
- return q;
-}
-
-
-/**
- * Cancel sending a message. Message must have been sent with
- * #GCP_send before. May not be called after the notify sent
- * callback has been called.
- *
- * It DOES call the continuation given to #GCP_send.
- *
- * @param q Queue handle to cancel
- */
-void
-GCP_send_cancel (struct CadetPeerQueue *q)
-{
- call_peer_cont (q, GNUNET_NO);
- GNUNET_MQ_send_cancel (q->env);
- GNUNET_free (q);
-}
-
-
-/**
- * Initialize the peer subsystem.
- *
- * @param c Configuration.
- */
-void
-GCP_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
- cfg = c;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "GCP_init\n");
- in_shutdown = GNUNET_NO;
- peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS",
- &max_peers))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
- "CADET", "MAX_PEERS", "USING DEFAULT");
- max_peers = 1000;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT",
- &drop_percent))
- {
- drop_percent = 0;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
- }
- ats_ch = GNUNET_ATS_connectivity_init (c);
- connect_to_core (c);
- if (NULL == core_handle)
- {
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- }
-}
-
-
-/**
- * Shut down the peer subsystem.
- */
-void
-GCP_shutdown (void)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Shutting down peer subsystem\n");
- in_shutdown = GNUNET_YES;
- if (NULL != core_handle)
- {
- GNUNET_CORE_disconnecT (core_handle);
- core_handle = NULL;
- }
- GNUNET_PEER_change_rc (myid, -1);
- /* With MQ API, CORE calls the disconnect handler for every peer
- * after calling GNUNET_CORE_disconnecT, shutdown must occur *after* that.
- */
- GNUNET_CONTAINER_multipeermap_iterate (peers,
- &shutdown_peer,
- NULL);
- if (NULL != ats_ch)
- {
- GNUNET_ATS_connectivity_done (ats_ch);
- ats_ch = NULL;
- }
- GNUNET_CONTAINER_multipeermap_destroy (peers);
- peers = NULL;
-}
-
-
-/**
- * Retrieve the CadetPeer stucture associated with the peer. Optionally create
- * one and insert it in the appropriate structures if the peer is not known yet.
- *
- * @param peer_id Full identity of the peer.
- * @param create #GNUNET_YES if a new peer should be created if unknown.
- * #GNUNET_NO otherwise.
- *
- * @return Existing or newly created peer structure.
- * NULL if unknown and not requested @a create
- */
-struct CadetPeer *
-GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create)
-{
- struct CadetPeer *peer;
-
- peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
- if (NULL == peer)
- {
- peer = GNUNET_new (struct CadetPeer);
- if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
- {
- peer_delete_oldest ();
- }
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multipeermap_put (peers,
- peer_id,
- peer,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- peer->id = GNUNET_PEER_intern (peer_id);
- }
- peer->last_contact = GNUNET_TIME_absolute_get ();
-
- return peer;
-}
-
-
-/**
- * Retrieve the CadetPeer stucture associated with the
- * peer. Optionally create one and insert it in the appropriate
- * structures if the peer is not known yet.
- *
- * @param peer Short identity of the peer.
- * @param create #GNUNET_YES if a new peer should be created if unknown.
- * #GNUNET_NO otherwise.
- *
- * @return Existing or newly created peer structure.
- * NULL if unknown and not requested @a create
- */
-struct CadetPeer *
-GCP_get_short (const GNUNET_PEER_Id peer, int create)
-{
- return GCP_get (GNUNET_PEER_resolve2 (peer), create);
-}
-
-
-/**
- * Function called once #GNUNET_TRANSPORT_offer_hello() is done.
- * Marks the operation as finished.
- *
- * @param cls Closure (our `struct CadetPeer`).
- */
-static void
-hello_offer_done (void *cls)
-{
- struct CadetPeer *peer = cls;
-
- peer->hello_offer = NULL;
-}
-
-
-/**
- * Try to establish a new connection to this peer (in its tunnel).
- * If the peer doesn't have any path to it yet, try to get one.
- * If the peer already has some path, send a CREATE CONNECTION towards it.
- *
- * @param peer Peer to connect to.
- */
-void
-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.