- * @param peer Peer to check.
- *
- * @return #GNUNET_YES if peer is in use.
- */
-static int
-peer_is_used (struct CadetPeer *peer)
-{
- struct CadetPeerPath *p;
-
- if (NULL != peer->tunnel)
- return GNUNET_YES;
-
- for (p = peer->path_head; NULL != p; p = p->next)
- {
- if (p->length < 3)
- return GNUNET_YES;
- }
- return GNUNET_NO;
-}
-
-
-/**
- * Iterator over all the peers to get the oldest timestamp.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- */
-static int
-peer_get_oldest (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *value)
-{
- struct CadetPeer *p = value;
- struct GNUNET_TIME_Absolute *abs = cls;
-
- /* Don't count active peers */
- if (GNUNET_YES == peer_is_used (p))
- return GNUNET_YES;
-
- if (abs->abs_value_us < p->last_contact.abs_value_us)
- abs->abs_value_us = p->last_contact.abs_value_us;
-
- return GNUNET_YES;
-}
-
-
-/**
- * Iterator over all the peers to remove the oldest entry.
- *
- * @param cls Closure (unsued).
- * @param key ID of the peer.
- * @param value Peer_Info of the peer.
- */
-static int
-peer_timeout (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *value)
-{
- struct CadetPeer *p = value;
- struct GNUNET_TIME_Absolute *abs = cls;
-
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "peer %s timeout\n", GNUNET_i2s (key));
-
- if (p->last_contact.abs_value_us == abs->abs_value_us &&
- GNUNET_NO == peer_is_used (p))
- {
- peer_destroy (p);
- return GNUNET_NO;
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Delete oldest unused peer.
- */
-static void
-peer_delete_oldest (void)
-{
- struct GNUNET_TIME_Absolute abs;
-
- abs = GNUNET_TIME_UNIT_FOREVER_ABS;
-
- GNUNET_CONTAINER_multipeermap_iterate (peers,
- &peer_get_oldest,
- &abs);
- GNUNET_CONTAINER_multipeermap_iterate (peers,
- &peer_timeout,
- &abs);
-}
-
-
-/**
- * Choose the best (yet unused) path towards a peer,
- * considering the tunnel properties.
- *
- * @param peer The destination peer.
- *
- * @return Best current known path towards the peer, if any.
- */
-static struct CadetPeerPath *
-peer_get_best_path (const struct CadetPeer *peer)
-{
- struct CadetPeerPath *best_p;
- struct CadetPeerPath *p;
- unsigned int best_cost;
- unsigned int cost;
-
- best_cost = UINT_MAX;
- best_p = NULL;
- for (p = peer->path_head; NULL != p; p = p->next)
- {
- if (GNUNET_NO == path_is_valid (p))
- continue; /* Don't use invalid paths. */
- if (GNUNET_YES == GCT_is_path_used (peer->tunnel, p))
- continue; /* If path is already in use, skip it. */
-
- if ((cost = GCT_get_path_cost (peer->tunnel, p)) < best_cost)
- {
- best_cost = cost;
- best_p = p;
- }
- }
- return best_p;
-}
-
-
-/**
- * Is this queue element sendable?
- *
- * - All management traffic is always sendable.
- * - For payload traffic, check the connection flow control.
- *
- * @param q Queue element to inspect.
- *
- * @return #GNUNET_YES if it is sendable, #GNUNET_NO otherwise.
- */
-static int
-queue_is_sendable (struct CadetPeerQueue *q)
-{
- /* Is PID-independent? */
- switch (q->type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_POLL:
- case GNUNET_MESSAGE_TYPE_CADET_KX:
- case GNUNET_MESSAGE_TYPE_CADET_AX_KX:
- case GNUNET_MESSAGE_TYPE_CADET_AX:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
- return GNUNET_YES;
-
- case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
- break;
-
- default:
- GNUNET_break (0);
- }
-
- return GCC_is_sendable (q->c, q->fwd);
-}
-
-
-/**
- * Get first sendable message.
- *
- * @param peer The destination peer.
- *
- * @return First transmittable message, if any. Otherwise, NULL.
- */
-static struct CadetPeerQueue *
-peer_get_first_message (const struct CadetPeer *peer)
-{
- struct CadetPeerQueue *q;
-
- for (q = peer->queue_head; NULL != q; q = q->next)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking q:%p on c:%s\n", q, GCC_2s (q->c));
- if (queue_is_sendable (q))
- return q;
- }
-
- return NULL;
-}
-
-
-/**
- * Function to process paths received for a new peer addition. The recorded
- * paths form the initial tunnel, which can be optimized later.
- * Called on each result obtained for the DHT search.
- *
- * @param cls closure
- * @param path
- */
-static void
-search_handler (void *cls, const struct CadetPeerPath *path)
-{
- struct CadetPeer *peer = cls;
- unsigned int connection_count;
-
- GCP_add_path_to_all (path, GNUNET_NO);
-
- /* Count connections */
- connection_count = GCT_count_connections (peer->tunnel);
-
- /* If we already have our minimum (or more) connections, it's enough */
- if (CONNECTIONS_PER_TUNNEL <= connection_count)
- return;
-
- if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (peer->tunnel))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
- GCP_connect (peer);
- }
- return;
-}
-
-
-/**
- * Adjust core requested size to accomodate an ACK.
- *
- * @param message_size Requested size.
- *
- * @return Size enough to fit @c message_size and an ACK.
- */
-static size_t
-get_core_size (size_t message_size)
-{
- return message_size + sizeof (struct GNUNET_CADET_ACK);
-}
-
-
-/**
- * Fill a core buffer with the appropriate data for the queued message.
- *
- * @param queue Queue element for the message.
- * @param buf Core buffer to fill.
- * @param size Size remaining in @c buf.
- * @param[out] pid In case its an encrypted payload, set payload.
- *
- * @return Bytes written to @c buf.
- */
-static size_t
-fill_buf (struct CadetPeerQueue *queue, void *buf, size_t size, uint32_t *pid)
-{
- struct CadetConnection *c = queue->c;
- size_t msg_size;
-
- switch (queue->type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
- *pid = GCC_get_pid (queue->c, queue->fwd);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " payload ID %u\n", *pid);
- msg_size = send_core_data_raw (queue->cls, size, buf);
- ((struct GNUNET_CADET_Encrypted *) buf)->pid = htonl (*pid);
- break;
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
- case GNUNET_MESSAGE_TYPE_CADET_KX:
- case GNUNET_MESSAGE_TYPE_CADET_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_POLL:
- LOG (GNUNET_ERROR_TYPE_DEBUG, " raw %s\n", GC_m2s (queue->type));
- msg_size = send_core_data_raw (queue->cls, size, buf);
- break;
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
- LOG (GNUNET_ERROR_TYPE_DEBUG, " path create\n");
- if (GCC_is_origin (c, GNUNET_YES))
- msg_size = send_core_connection_create (c, size, buf);
- else
- msg_size = send_core_data_raw (queue->cls, size, buf);
- break;
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
- LOG (GNUNET_ERROR_TYPE_DEBUG, " path ack\n");
- if (GCC_is_origin (c, GNUNET_NO) ||
- GCC_is_origin (c, GNUNET_YES))
- {
- msg_size = send_core_connection_ack (c, size, buf);
- }
- else
- {
- msg_size = send_core_data_raw (queue->cls, size, buf);
- }
- break;
- case GNUNET_MESSAGE_TYPE_CADET_DATA:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
- /* This should be encapsulted */
- msg_size = 0;
- GNUNET_assert (0);
- break;
- default:
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_WARNING, " type unknown: %u\n", queue->type);
- msg_size = 0;
- }
-
- GNUNET_assert (size >= msg_size);
-
- return msg_size;
-}
-
-
-/**
- * Core callback to write a queued packet to core buffer
- *
- * @param cls Closure (peer info).
- * @param size Number of bytes available in buf.
- * @param buf Where the to write the message.
- *
- * @return number of bytes written to buf
- */
-static size_t
-queue_send (void *cls, size_t size, void *buf)
-{
- struct CadetPeer *peer = cls;
- struct CadetConnection *c;
- struct CadetPeerQueue *queue;
- struct GNUNET_TIME_Relative core_wait_time;
- const struct GNUNET_PeerIdentity *dst_id;
- size_t msg_size;
- size_t total_size;
- size_t rest;
- char *dst;
- uint32_t pid;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue send towards %s (max %u)\n",
- GCP_2s (peer), size);
-
- /* Sanity checking */
- if (NULL == buf || 0 == size)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Buffer size 0.\n");
- peer->tmt_time.abs_value_us = 0;
- peer->core_transmit = NULL;
- return 0;
- }
-
- /* Init */
- rest = size;
- total_size = 0;
- dst = (char *) buf;
- pid = 0;
- peer->core_transmit = NULL;
- queue = peer_get_first_message (peer);
- if (NULL == queue)
- {
- GNUNET_break (0); /* Core tmt_rdy should've been canceled */
- peer->tmt_time.abs_value_us = 0;
- return 0;
- }
- core_wait_time = GNUNET_TIME_absolute_get_duration (peer->tmt_time);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " core wait time %s\n",
- GNUNET_STRINGS_relative_time_to_string (core_wait_time, GNUNET_NO));
- peer->tmt_time.abs_value_us = 0;
-
- /* Copy all possible messages to the core buffer */
- while (NULL != queue && rest >= queue->size)
- {
- c = queue->c;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s %s\n",
- GCC_2s (c), GC_f2s(queue->fwd));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " size %u ok (%u/%u)\n",
- queue->size, total_size, size);
-
- msg_size = fill_buf (queue, (void *) dst, size, &pid);
-
- if (0 < drop_percent &&
- GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s (%s %u) on connection %s %s\n",
- GC_m2s (queue->type), GC_m2s (queue->payload_type),
- queue->payload_id, GCC_2s (c), GC_f2s (queue->fwd));
- msg_size = 0;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_INFO,
- "snd %s (%s %9u) on connection %s (%p) %s (size %u)\n",
- GC_m2s (queue->type), GC_m2s (queue->payload_type),
- queue->payload_id, GCC_2s (c), c, GC_f2s (queue->fwd), msg_size);
- }
- total_size += msg_size;
- rest -= msg_size;
- dst = &dst[msg_size];
- msg_size = 0;
-
- /* Free queue, but cls was freed by send_core_* in fill_buf. */
- (void) GCP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid);
-
- /* Next! */
- queue = peer_get_first_message (peer);
- }
-
- /* If more data in queue, send next */
- if (NULL != queue)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " more data! (%u)\n", queue->size);
- if (NULL == peer->core_transmit)
- {
- dst_id = GNUNET_PEER_resolve2 (peer->id);
- peer->core_transmit =
- GNUNET_CORE_notify_transmit_ready (core_handle,
- GNUNET_NO, get_priority (queue),
- GNUNET_TIME_UNIT_FOREVER_REL,
- dst_id,
- get_core_size (queue->size),
- &queue_send,
- peer);
- peer->tmt_time = GNUNET_TIME_absolute_get ();
- queue->start_waiting = GNUNET_TIME_absolute_get ();
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "* tmt rdy called somewhere else\n");
- }
-// GCC_start_poll (); FIXME needed?
- }
- else
- {
-// GCC_stop_poll(); FIXME needed?
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " return %d\n", total_size);
- queue_debug (peer, GNUNET_ERROR_TYPE_DEBUG);
-
- return total_size;
-}
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-
-/**
- * Free a transmission that was already queued with all resources
- * associated to the request.
- *
- * If connection was marked to be destroyed, and this was the last queued
- * message on it, the connection will be free'd as a result.
- *
- * @param queue Queue handler to cancel.
- * @param clear_cls Is it necessary to free associated cls?
- * @param sent Was it really sent? (Could have been canceled)
- * @param pid PID, if relevant (was sent and was a payload message).
- *
- * @return #GNUNET_YES if connection was destroyed as a result,
- * #GNUNET_NO otherwise.
- */
-int
-GCP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls,
- int sent, uint32_t pid)
-{
- struct CadetPeer *peer;
- int connection_destroyed;
-
- peer = queue->peer;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy %s\n", GC_m2s (queue->type));
- if (GNUNET_YES == clear_cls)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " free cls\n");
- switch (queue->type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
- LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n");
- /* fall through */
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
- case GNUNET_MESSAGE_TYPE_CADET_KX:
- case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
- case GNUNET_MESSAGE_TYPE_CADET_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_POLL:
- GNUNET_free_non_null (queue->cls);
- break;
-
- default:
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n",
- GC_m2s (queue->type));
- }
- }
- GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue);
-
- if (queue->type != GNUNET_MESSAGE_TYPE_CADET_ACK &&
- queue->type != GNUNET_MESSAGE_TYPE_CADET_POLL)
- {
- peer->queue_n--;
- }
-
- if (NULL != queue->callback)
- {
- struct GNUNET_TIME_Relative wait_time;
-
- wait_time = GNUNET_TIME_absolute_get_duration (queue->start_waiting);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback, time elapsed %s\n",
- GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO));
- connection_destroyed = queue->callback (queue->callback_cls,
- queue->c, sent, queue->type, pid,
- queue->fwd, queue->size,
- wait_time);
- }
- else
- {
- connection_destroyed = GNUNET_NO;
- }
-
- if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit)
- {
- GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
- peer->core_transmit = NULL;
- peer->tmt_time.abs_value_us = 0;
- }
-
- GNUNET_free (queue);
- return connection_destroyed;
-}
-
-
-/**
- * @brief Queue and pass message to core when possible.
- *
- * @param peer Peer towards which to queue the message.
- * @param cls Closure (@c type dependant). It will be used by queue_send to
- * build the message to be sent if not already prebuilt.
- * @param type Type of the message, 0 for a raw message.
- * @param size Size of the message.
- * @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 taken the message.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel the message before it is sent. Once cont is called
- * message has been sent and therefore the handle is no longer valid.
- */
-struct CadetPeerQueue *
-GCP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type,
- uint16_t payload_type, uint32_t payload_id, size_t size,
- struct CadetConnection *c, int fwd,
- GCP_sent cont, void *cont_cls)
-{
- struct CadetPeerQueue *q;
- int error_level;
- int priority;
- int call_core;
-
- if (NULL == c && GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN != type)
- error_level = GNUNET_ERROR_TYPE_ERROR;
- else
- error_level = GNUNET_ERROR_TYPE_INFO;
- LOG (error_level,
- "que %s (%s %9u) on connection %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 (error_level == GNUNET_ERROR_TYPE_ERROR)
- GNUNET_assert (0);
- if (NULL == peer->connections)
- {
- /* We are not connected to this peer, ignore request. */
- LOG (GNUNET_ERROR_TYPE_WARNING, "%s not a neighbor\n", GCP_2s (peer));
- GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1,
- GNUNET_NO);
- return NULL;
- }
-
- priority = 0;
-
- if (GNUNET_MESSAGE_TYPE_CADET_POLL == type ||
- GNUNET_MESSAGE_TYPE_CADET_ACK == type)
- {
- priority = 100;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority);
-
- call_core = (NULL == c || type == GNUNET_MESSAGE_TYPE_CADET_KX) ?
- GNUNET_YES : GCC_is_sendable (c, fwd);
- q = GNUNET_new (struct CadetPeerQueue);
- q->cls = cls;
- q->type = type;
- q->payload_type = payload_type;
- q->payload_id = payload_id;
- q->size = size;
- q->peer = peer;
- q->c = c;
- q->fwd = fwd;
- q->callback = cont;
- q->callback_cls = cont_cls;
- if (100 > priority)
- {
- GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, q);
- peer->queue_n++;
- }
- else
- {
- GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, q);
- call_core = GNUNET_YES;
- }
-
- q->start_waiting = GNUNET_TIME_absolute_get ();
- if (NULL == peer->core_transmit && GNUNET_YES == call_core)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "calling core tmt rdy towards %s for %u bytes\n",
- GCP_2s (peer), size);
- peer->core_transmit =
- GNUNET_CORE_notify_transmit_ready (core_handle,
- GNUNET_NO, get_priority (q),
- GNUNET_TIME_UNIT_FOREVER_REL,
- GNUNET_PEER_resolve2 (peer->id),
- get_core_size (size),
- &queue_send, peer);
- peer->tmt_time = GNUNET_TIME_absolute_get ();
- }
- else if (GNUNET_NO == call_core)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s not needed\n",
- GCP_2s (peer));
-
- }
- else
- {
- struct GNUNET_TIME_Relative elapsed;
- elapsed = GNUNET_TIME_absolute_get_duration (peer->tmt_time);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s already called %s\n",
- GCP_2s (peer),
- GNUNET_STRINGS_relative_time_to_string (elapsed, GNUNET_NO));
-
- }
- queue_debug (peer, GNUNET_ERROR_TYPE_DEBUG);
- return q;
-}
-
-
-/**
- * Cancel all queued messages to a peer that belong to a certain connection.
- *
- * @param peer Peer towards whom to cancel.
- * @param c Connection whose queued messages to cancel. Might be destroyed by
- * the sent continuation call.
- */
-void
-GCP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c)
-{
- struct CadetPeerQueue *q;
- struct CadetPeerQueue *next;
- struct CadetPeerQueue *prev;
- int connection_destroyed;
-
- connection_destroyed = GNUNET_NO;
- for (q = peer->queue_head; NULL != q; q = next)
- {
- prev = q->prev;
- if (q->c == c)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GC_m2s (q->type));
- GNUNET_break (GNUNET_NO == connection_destroyed);
- if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY == q->type)
- {
- q->c = NULL;
- }
- else
- {
- connection_destroyed = GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
- }
-
- /* Get next from prev, q->next might be already freed:
- * queue destroy -> callback -> GCC_destroy -> cancel_queues -> here
- */
- if (NULL == prev)
- next = peer->queue_head;
- else
- next = prev->next;
- }
- else
- {
- next = q->next;
- }
- }
-
- if (NULL == peer->queue_head && NULL != peer->core_transmit)
- {
- GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
- peer->core_transmit = NULL;
- peer->tmt_time.abs_value_us = 0;
- }
-}
-
-
-/**
- * Get the first transmittable message for a connection.
- *
- * @param peer Neighboring peer.
- * @param c Connection.
- *
- * @return First transmittable message.
- */
-static struct CadetPeerQueue *
-connection_get_first_message (struct CadetPeer *peer, struct CadetConnection *c)
-{
- struct CadetPeerQueue *q;
-
- for (q = peer->queue_head; NULL != q; q = q->next)
- {
- if (q->c != c)
- continue;
- if (queue_is_sendable (q))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable!!\n");
- return q;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n");
- }
-
- return NULL;
-}
-
-
-/**
- * Get the first message for a connection and unqueue it.
- *
- * Only tunnel (or higher) level messages are unqueued. Connection specific
- * messages are silently destroyed upon encounter.
- *
- * @param peer Neighboring peer.
- * @param c Connection.
- * @param destroyed[in/out] Was the connection destroyed (prev/as a result)?.
- * Can NOT be NULL.
- *
- * @return First message for this connection.
- */
-struct GNUNET_MessageHeader *
-GCP_connection_pop (struct CadetPeer *peer,
- struct CadetConnection *c,
- int *destroyed)
-{
- struct CadetPeerQueue *q;
- struct CadetPeerQueue *next;
- struct GNUNET_MessageHeader *msg;
- int dest;
-
- GNUNET_assert (NULL != destroyed);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "connection_pop on connection %p\n", c);
- for (q = peer->queue_head; NULL != q; q = next)
- {
- next = q->next;
- if (q->c != c)
- continue;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " - queued: %s (%s %u), callback: %p\n",
- GC_m2s (q->type), GC_m2s (q->payload_type), q->payload_id,
- q->callback);
- switch (q->type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
- case GNUNET_MESSAGE_TYPE_CADET_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_POLL:
- dest = GCP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0);
- if (GNUNET_YES == dest)
- {
- GNUNET_break (GNUNET_NO == *destroyed);
- *destroyed = GNUNET_YES;
- }
- continue;
-
- case GNUNET_MESSAGE_TYPE_CADET_KX:
- case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED:
- msg = (struct GNUNET_MessageHeader *) q->cls;
- dest = GCP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0);
- if (GNUNET_YES == dest)
- {
- GNUNET_break (GNUNET_NO == *destroyed);
- *destroyed = GNUNET_YES;
- }
- return msg;
-
- default:
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Unknown message %s\n", GC_m2s (q->type));
- }
- }
-
- return NULL;
-}
-
-/**
- * Unlock a possibly locked queue for a connection.
- *
- * If there is a message that can be sent on this connection, call core for it.
- * Otherwise (if core transmit is already called or there is no sendable
- * message) do nothing.
- *
- * @param peer Peer who keeps the queue.
- * @param c Connection whose messages to unlock.
- */
-void
-GCP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c)
-{
- struct CadetPeerQueue *q;
- size_t size;
-
- if (NULL != peer->core_transmit)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n");
- return; /* Already unlocked */
- }
-
- q = connection_get_first_message (peer, c);
- if (NULL == q)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n");
- return; /* Nothing to transmit */
- }
-
- size = q->size;
- peer->core_transmit =
- GNUNET_CORE_notify_transmit_ready (core_handle,
- GNUNET_NO, get_priority (q),
- GNUNET_TIME_UNIT_FOREVER_REL,
- GNUNET_PEER_resolve2 (peer->id),
- get_core_size (size),
- &queue_send,
- peer);
- peer->tmt_time = GNUNET_TIME_absolute_get ();
-}
-
-
-/**
- * Initialize the peer subsystem.
- *
- * @param c Configuration.
- */
-void
-GCP_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
- 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");
- }
-
- core_handle = GNUNET_CORE_connect (c, /* Main configuration */
- NULL, /* Closure passed to CADET functions */
- &core_init, /* Call core_init once connected */
- &core_connect, /* Handle connects */
- &core_disconnect, /* remove peers on disconnects */
- NULL, /* Don't notify about all incoming messages */
- GNUNET_NO, /* For header only in notification */
- NULL, /* Don't notify about all outbound messages */
- GNUNET_NO, /* For header-only out notification */
- core_handlers); /* Register these handlers */
- if (GNUNET_YES !=
- GNUNET_CONFIGURATION_get_value_yesno (c, "CADET", "DISABLE_TRY_CONNECT"))
- {
- transport_handle = GNUNET_TRANSPORT_connect (c, &my_full_id, NULL, /* cls */
- /* Notify callbacks */
- NULL, NULL, NULL);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "* DISABLE TRYING CONNECT in config *\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "* Use this only for test purposes. *\n");
- LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
- transport_handle = NULL;
- }
-
-
-
- if (NULL == core_handle)
- {
- GNUNET_break (0);
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
-}
-
-
-/**
- * Shut down the peer subsystem.