AM_CLFAGS = -g
libexec_PROGRAMS = \
- gnunet-service-cadet \
gnunet-service-cadet-new \
$(EXP_LIBEXEC)
$(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
$(top_builddir)/src/hello/libgnunethello.la \
$(top_builddir)/src/block/libgnunetblock.la
-
-gnunet_service_cadet_SOURCES = \
- gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \
- gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \
- gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \
- gnunet-service-cadet_local.c gnunet-service-cadet_local.h \
- gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h \
- gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \
- gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \
- cadet_path.c cadet_path.h \
- cadet_common.c \
- gnunet-service-cadet.c
-gnunet_service_cadet_CFLAGS = $(AM_CFLAGS)
-gnunet_service_cadet_LDADD = \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/transport/libgnunettransport.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/ats/libgnunetats.la \
- $(top_builddir)/src/dht/libgnunetdht.la \
- $(top_builddir)/src/statistics/libgnunetstatistics.la \
- $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \
- $(top_builddir)/src/hello/libgnunethello.la \
- $(top_builddir)/src/block/libgnunetblock.la
if LINUX
- gnunet_service_cadet_LDFLAGS = -lrt
+ gnunet_service_cadet_new_LDFLAGS = -lrt
endif
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2001-2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet.c
- * @brief GNUnet CADET service with encryption
- * @author Bartlomiej Polot
- *
- * FIXME in progress:
- * - rekey - reliability interaction
- * - channel retransmit timing
- *
- * TODO:
- * - relay corking down to core
- * - set ttl relative to path length
- * TODO END
- *
- * Dictionary:
- * - peer: other cadet instance. If there is direct connection it's a neighbor.
- * - tunnel: encrypted connection to a peer, neighbor or not.
- * - channel: connection between two clients, on the same or different peers.
- * have properties like reliability.
- * - path: series of directly connected peer from one peer to another.
- * - connection: path which is being used in a tunnel.
- */
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "cadet.h"
-#include "gnunet_statistics_service.h"
-
-#include "gnunet-service-cadet_local.h"
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_dht.h"
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_hello.h"
-
-
-/******************************************************************************/
-/*********************** GLOBAL VARIABLES ****************************/
-/******************************************************************************/
-
-/****************************** Global variables ******************************/
-
-/**
- * Handle to the statistics service.
- */
-struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-struct GNUNET_PeerIdentity my_full_id;
-
-
-/**
- * Signal that shutdown is happening: prevent recover measures.
- */
-int shutting_down;
-
-/*************************** Static global variables **************************/
-
-/**
- * Own private key.
- */
-static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
-
-
-/******************************************************************************/
-/************************ MAIN FUNCTIONS ****************************/
-/******************************************************************************/
-
-/**
- * Task run during shutdown.
- *
- * @param cls unused
- */
-static void
-shutdown_task (void *cls)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
-
- shutting_down = GNUNET_YES;
-
- GML_shutdown ();
- GCH_shutdown ();
- GCC_shutdown ();
- GCT_shutdown ();
- GCD_shutdown ();
- GCP_shutdown ();
-
- GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
- stats = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
-}
-
-
-/**
- * Process cadet requests.
- *
- * @param cls closure
- * @param server the initialized server
- * @param c configuration to use
- */
-static void
-run (void *cls, struct GNUNET_SERVER_Handle *server,
- const struct GNUNET_CONFIGURATION_Handle *c)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
-
- stats = GNUNET_STATISTICS_create ("cadet", c);
-
- /* Scheduled the task to clean up when shutdown is called */
- GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
- NULL);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n");
- my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
- GNUNET_assert (NULL != my_private_key);
- GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_full_id.public_key);
- myid = GNUNET_PEER_intern (&my_full_id);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "STARTING SERVICE (cadet) for peer [%s]\n",
- GNUNET_i2s (&my_full_id));
-
- GML_init (server); /* Local clients */
- GCH_init (c); /* Hellos */
- GCC_init (c); /* Connections */
- GCP_init (c); /* Peers */
- GCD_init (c); /* DHT */
- GCT_init (c, my_private_key); /* Tunnels */
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cadet service running\n");
-}
-
-
-/**
- * The main function for the cadet service.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
- int r;
-
- shutting_down = GNUNET_NO;
- r = GNUNET_SERVICE_run (argc, argv, "cadet", GNUNET_SERVICE_OPTION_NONE, &run,
- NULL);
- GNUNET_free (my_private_key);
-
- if (GNUNET_OK != r)
- {
- FPRINTF (stderr, "GNUNET_SERVICE_run for CADET has failed!\n");
- return 1;
- }
-
- return 0;
-}
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_statistics_service.h"
-
-#include "cadet.h"
-#include "cadet_protocol.h"
-
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_local.h"
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-chn",__VA_ARGS__)
-#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
-
-#define CADET_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(\
- GNUNET_TIME_UNIT_MILLISECONDS, 250)
-#define CADET_RETRANSMIT_MARGIN 4
-
-
-/**
- * All the states a connection can be in.
- */
-enum CadetChannelState
-{
- /**
- * Uninitialized status, should never appear in operation.
- */
- CADET_CHANNEL_NEW,
-
- /**
- * Connection create message sent, waiting for ACK.
- */
- CADET_CHANNEL_SENT,
-
- /**
- * Connection confirmed, ready to carry traffic.
- */
- CADET_CHANNEL_READY
-};
-
-
-/**
- * Info holder for channel messages in queues.
- */
-struct CadetChannelQueue
-{
- /**
- * Tunnel Queue.
- */
- struct CadetTunnelQueue *tq;
-
- /**
- * Message type (DATA/DATA_ACK)
- */
- uint16_t type;
-
- /**
- * Message copy (for DATAs, to start retransmission timer)
- */
- struct CadetReliableMessage *copy;
-
- /**
- * Reliability (for DATA_ACKs, to access rel->ack_q)
- */
- struct CadetChannelReliability *rel;
-};
-
-
-/**
- * Info needed to retry a message in case it gets lost.
- */
-struct CadetReliableMessage
-{
- /**
- * Double linked list, FIFO style
- */
- struct CadetReliableMessage *next;
- struct CadetReliableMessage *prev;
-
- /**
- * Type of message (payload, channel management).
- */
- int16_t type;
-
- /**
- * Tunnel Reliability queue this message is in.
- */
- struct CadetChannelReliability *rel;
-
- /**
- * ID of the message (ACK needed to free)
- */
- uint32_t mid;
-
- /**
- * Tunnel Queue.
- */
- struct CadetChannelQueue *chq;
-
- /**
- * When was this message issued (to calculate ACK delay)
- */
- struct GNUNET_TIME_Absolute timestamp;
-
- /* struct GNUNET_CADET_ChannelAppDataMessage with payload */
-};
-
-
-/**
- * Info about the traffic state for a client in a channel.
- */
-struct CadetChannelReliability
-{
- /**
- * Channel this is about.
- */
- struct CadetChannel *ch;
-
- /**
- * DLL of messages sent and not yet ACK'd.
- */
- struct CadetReliableMessage *head_sent;
- struct CadetReliableMessage *tail_sent;
-
- /**
- * DLL of messages received out of order.
- */
- struct CadetReliableMessage *head_recv;
- struct CadetReliableMessage *tail_recv;
-
- /**
- * Messages received.
- */
- unsigned int n_recv;
-
- /**
- * Next MID to use for outgoing traffic.
- */
- uint32_t mid_send;
-
- /**
- * Next MID expected for incoming traffic.
- */
- uint32_t mid_recv;
-
- /**
- * Handle for queued unique data CREATE, DATA_ACK.
- */
- struct CadetChannelQueue *uniq;
-
- /**
- * Can we send data to the client?
- */
- int client_ready;
-
- /**
- * Can the client send data to us?
- */
- int client_allowed;
-
- /**
- * Task to resend/poll in case no ACK is received.
- */
- struct GNUNET_SCHEDULER_Task * retry_task;
-
- /**
- * Counter for exponential backoff.
- */
- struct GNUNET_TIME_Relative retry_timer;
-
- /**
- * How long does it usually take to get an ACK.
- */
- struct GNUNET_TIME_Relative expected_delay;
-};
-
-
-/**
- * Struct containing all information regarding a channel to a remote client.
- */
-struct CadetChannel
-{
- /**
- * Tunnel this channel is in.
- */
- struct CadetTunnel *t;
-
- /**
- * Destination port of the channel.
- */
- struct GNUNET_HashCode port;
-
- /**
- * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- */
- struct GNUNET_CADET_ChannelTunnelNumber gid;
-
- /**
- * Local tunnel number for root (owner) client.
- * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
- */
- struct GNUNET_CADET_ClientChannelNumber lid_root;
-
- /**
- * Local tunnel number for local destination clients (incoming number)
- * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0).
- */
- struct GNUNET_CADET_ClientChannelNumber lid_dest;
-
- /**
- * Channel state.
- */
- enum CadetChannelState state;
-
- /**
- * Is the tunnel bufferless (minimum latency)?
- */
- int nobuffer;
-
- /**
- * Is the tunnel reliable?
- */
- int reliable;
-
- /**
- * Last time the channel was used
- */
- struct GNUNET_TIME_Absolute timestamp;
-
- /**
- * Client owner of the tunnel, if any
- */
- struct CadetClient *root;
-
- /**
- * Client destination of the tunnel, if any.
- */
- struct CadetClient *dest;
-
- /**
- * Flag to signal the destruction of the channel.
- * If this is set to #GNUNET_YES the channel will be destroyed
- * when the queue is empty.
- */
- int destroy;
-
- /**
- * Total (reliable) messages pending ACK for this channel.
- */
- unsigned int pending_messages;
-
- /**
- * Reliability data.
- * Only present (non-NULL) at the owner of a tunnel.
- */
- struct CadetChannelReliability *root_rel;
-
- /**
- * Reliability data.
- * Only present (non-NULL) at the destination of a tunnel.
- */
- struct CadetChannelReliability *dest_rel;
-
-};
-
-
-/******************************************************************************/
-/******************************* GLOBALS ***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-
-/******************************************************************************/
-/******************************** STATIC ***********************************/
-/******************************************************************************/
-
-
-/**
- * Destroy a reliable message after it has been acknowledged, either by
- * direct mid ACK or bitfield. Updates the appropriate data structures and
- * timers and frees all memory.
- *
- * @param copy Message that is no longer needed: remote peer got it.
- * @param update_time Is the timing information relevant?
- * If this message is ACK in a batch the timing information
- * is skewed by the retransmission, count only for the
- * retransmitted message.
- *
- * @return #GNUNET_YES if channel was destroyed as a result of the call,
- * #GNUNET_NO otherwise.
- */
-static int
-rel_message_free (struct CadetReliableMessage *copy, int update_time);
-
-/**
- * send a channel create message.
- *
- * @param ch Channel for which to send.
- */
-static void
-send_create (struct CadetChannel *ch);
-
-/**
- * Confirm we got a channel create, FWD ack.
- *
- * @param ch The channel to confirm.
- * @param fwd Should we send a FWD ACK? (going dest->root)
- */
-static void
-send_ack (struct CadetChannel *ch, int fwd);
-
-
-
-/**
- * Test if the channel is loopback: both root and dest are on the local peer.
- *
- * @param ch Channel to test.
- *
- * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise.
- */
-static int
-is_loopback (const struct CadetChannel *ch)
-{
- if (NULL != ch->t)
- return GCT_is_loopback (ch->t);
-
- return (NULL != ch->root && NULL != ch->dest);
-}
-
-
-/**
- * Save a copy of the data message for later retransmission.
- *
- * @param msg Message to copy.
- * @param mid Message ID.
- * @param rel Reliability data for retransmission.
- */
-static struct CadetReliableMessage *
-copy_message (const struct GNUNET_CADET_ChannelAppDataMessage *msg, uint32_t mid,
- struct CadetChannelReliability *rel)
-{
- struct CadetReliableMessage *copy;
- uint16_t size;
-
- size = ntohs (msg->header.size);
- copy = GNUNET_malloc (sizeof (*copy) + size);
- copy->mid = mid;
- copy->rel = rel;
- copy->type = GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA;
- GNUNET_memcpy (©[1], msg, size);
-
- return copy;
-}
-
-/**
- * We have received a message out of order, or the client is not ready.
- * Buffer it until we receive an ACK from the client or the missing
- * message from the channel.
- *
- * @param msg Message to buffer (MUST be of type CADET_DATA).
- * @param rel Reliability data to the corresponding direction.
- */
-static void
-add_buffered_data (const struct GNUNET_CADET_ChannelAppDataMessage *msg,
- struct CadetChannelReliability *rel)
-{
- struct CadetReliableMessage *copy;
- struct CadetReliableMessage *prev;
- uint32_t mid;
-
- mid = ntohl (msg->mid);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data MID %u (%u)\n",
- mid, rel->n_recv);
-
- rel->n_recv++;
-
- // FIXME do something better than O(n), although n < 64...
- // FIXME start from the end (most messages are the latest ones)
- for (prev = rel->head_recv; NULL != prev; prev = prev->next)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid);
- if (prev->mid == mid)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n");
- rel->n_recv--;
- return;
- }
- else if (GC_is_pid_bigger (prev->mid, mid))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n");
- copy = copy_message (msg, mid, rel);
- GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv,
- prev, copy);
- return;
- }
- }
- copy = copy_message (msg, mid, rel);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail! (now: %u)\n", rel->n_recv);
- GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n");
-}
-
-
-/**
- * Add a destination client to a channel, initializing all data structures
- * in the channel and the client.
- *
- * @param ch Channel to which add the destination.
- * @param c Client which to add to the channel.
- */
-static void
-add_destination (struct CadetChannel *ch, struct CadetClient *c)
-{
- if (NULL != ch->dest)
- {
- GNUNET_break (0);
- return;
- }
-
- /* Assign local id as destination */
- ch->lid_dest = GML_get_next_ccn (c);
-
- /* Store in client's hashmap */
- GML_channel_add (c, ch->lid_dest, ch);
-
- GNUNET_break (NULL == ch->dest_rel);
- ch->dest_rel = GNUNET_new (struct CadetChannelReliability);
- ch->dest_rel->ch = ch;
- ch->dest_rel->expected_delay.rel_value_us = 0;
- ch->dest_rel->retry_timer = CADET_RETRANSMIT_TIME;
-
- ch->dest = c;
-}
-
-
-/**
- * Set options in a channel, extracted from a bit flag field.
- *
- * @param ch Channel to set options to.
- * @param options Bit array in host byte order.
- */
-static void
-channel_set_options (struct CadetChannel *ch, uint32_t options)
-{
- ch->nobuffer = (options & GNUNET_CADET_OPTION_NOBUFFER) != 0 ?
- GNUNET_YES : GNUNET_NO;
- ch->reliable = (options & GNUNET_CADET_OPTION_RELIABLE) != 0 ?
- GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Get a bit flag field with the options of a channel.
- *
- * @param ch Channel to get options from.
- *
- * @return Bit array in host byte order.
- */
-static uint32_t
-channel_get_options (struct CadetChannel *ch)
-{
- uint32_t options;
-
- options = 0;
- if (ch->nobuffer)
- options |= GNUNET_CADET_OPTION_NOBUFFER;
- if (ch->reliable)
- options |= GNUNET_CADET_OPTION_RELIABLE;
-
- return options;
-}
-
-
-/**
- * Notify a client that the channel is no longer valid.
- *
- * @param ch Channel that is destroyed.
- * @param local_only Should we avoid sending it to other peers?
- */
-static void
-send_destroy (struct CadetChannel *ch, int local_only)
-{
- struct GNUNET_CADET_ChannelManageMessage msg;
-
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
- msg.header.size = htons (sizeof (msg));
- msg.ctn = ch->gid;
-
- /* If root is not NULL, notify.
- * If it's NULL, check lid_root. When a local destroy comes in, root
- * is set to NULL but lid_root is left untouched. In this case, do nothing,
- * the client is the one who requested the channel to be destroyed.
- */
- if (NULL != ch->root)
- GML_send_channel_destroy (ch->root, ch->lid_root);
- else if (0 == ch->lid_root.channel_of_client && GNUNET_NO == local_only)
- GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
-
- if (NULL != ch->dest)
- GML_send_channel_destroy (ch->dest, ch->lid_dest);
- else if (0 == ch->lid_dest.channel_of_client && GNUNET_NO == local_only)
- GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL);
-}
-
-
-/**
- * Notify the destination client that a new incoming channel was created.
- *
- * @param ch Channel that was created.
- */
-static void
-send_client_create (struct CadetChannel *ch)
-{
- uint32_t opt;
-
- if (NULL == ch->dest)
- return;
-
- opt = 0;
- opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0;
- opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0;
- GML_send_channel_create (ch->dest,
- ch->lid_dest,
- &ch->port,
- opt,
- GCT_get_destination (ch->t));
-
-}
-
-
-/**
- * Send data to a client.
- *
- * If the client is ready, send directly, otherwise buffer while listening
- * for a local ACK.
- *
- * @param ch Channel
- * @param msg Message.
- * @param fwd Is this a fwd (root->dest) message?
- */
-static void
-send_client_data (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelAppDataMessage *msg,
- int fwd)
-{
- if (fwd)
- {
- if (ch->dest_rel->client_ready)
- {
- GML_send_data (ch->dest, msg, ch->lid_dest);
- ch->dest_rel->client_ready = GNUNET_NO;
- ch->dest_rel->mid_recv++;
- }
- else
- add_buffered_data (msg, ch->dest_rel);
- }
- else
- {
- if (ch->root_rel->client_ready)
- {
- GML_send_data (ch->root, msg, ch->lid_root);
- ch->root_rel->client_ready = GNUNET_NO;
- ch->root_rel->mid_recv++;
- }
- else
- add_buffered_data (msg, ch->root_rel);
- }
-}
-
-
-/**
- * Send a buffered message to the client, for in order delivery or
- * as result of client ACK.
- *
- * @param ch Channel on which to empty the message buffer.
- * @param c Client to send to.
- * @param fwd Is this to send FWD data?.
- */
-static void
-send_client_buffered_data (struct CadetChannel *ch,
- struct CadetClient *c,
- int fwd)
-{
- struct CadetReliableMessage *copy;
- struct CadetChannelReliability *rel;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n");
- rel = fwd ? ch->dest_rel : ch->root_rel;
- if (GNUNET_NO == rel->client_ready)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n");
- return;
- }
-
- copy = rel->head_recv;
- /* We never buffer channel management messages */
- if (NULL != copy)
- {
- if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable)
- {
- struct GNUNET_CADET_ChannelAppDataMessage *msg = (struct GNUNET_CADET_ChannelAppDataMessage *) ©[1];
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n",
- copy->mid, rel->mid_recv + 1);
- send_client_data (ch, msg, fwd);
- rel->n_recv--;
- GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " free copy recv MID %u (%p), %u left\n",
- copy->mid, copy, rel->n_recv);
- GNUNET_free (copy);
- GCCH_send_data_ack (ch, fwd);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " reliable && don't have %u, next is %u\n",
- rel->mid_recv, copy->mid);
- if (GNUNET_YES == ch->destroy)
- {
- /* We don't have the next data piece and the remote peer has closed the
- * channel. We won't receive it anymore, so just destroy the channel.
- * FIXME: wait some time to allow other connections to
- * deliver missing messages
- */
- send_destroy (ch, GNUNET_YES);
- GCCH_destroy (ch);
- }
- }
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n");
-}
-
-
-/**
- * Allow a client to send more data.
- *
- * In case the client was already allowed to send data, do nothing.
- *
- * @param ch Channel.
- * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root)
- */
-static void
-send_client_ack (struct CadetChannel *ch, int fwd)
-{
- struct CadetChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel;
- struct CadetClient *c = fwd ? ch->root : ch->dest;
-
- if (NULL == c)
- {
- GNUNET_break (GNUNET_NO != ch->destroy);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " sending %s ack to client on channel %s\n",
- GC_f2s (fwd), GCCH_2s (ch));
-
- if (NULL == rel)
- {
- GNUNET_break (0);
- return;
- }
-
- if (GNUNET_YES == rel->client_allowed)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " already allowed\n");
- return;
- }
- rel->client_allowed = GNUNET_YES;
-
- GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest);
-}
-
-
-/**
- * Notify the root that the destination rejected the channel.
- *
- * @param ch Rejected channel.
- */
-static void
-send_client_nack (struct CadetChannel *ch)
-{
- if (NULL == ch->root)
- {
- GNUNET_break (0);
- return;
- }
- GML_send_channel_nack (ch->root, ch->lid_root);
-}
-
-
-/**
- * We haven't received an ACK after a certain time: restransmit the message.
- *
- * @param cls Closure (CadetChannelReliability with the message to restransmit)
- */
-static void
-channel_retransmit_message (void *cls)
-{
- struct CadetChannelReliability *rel = cls;
- struct CadetReliableMessage *copy;
- struct CadetChannel *ch;
- struct GNUNET_CADET_ChannelAppDataMessage *payload;
- int fwd;
-
- rel->retry_task = NULL;
- ch = rel->ch;
- copy = rel->head_sent;
- if (NULL == copy)
- {
- GNUNET_break (0); // FIXME tripped in rps testcase
- return;
- }
-
- payload = (struct GNUNET_CADET_ChannelAppDataMessage *) ©[1];
- fwd = (rel == ch->root_rel);
-
- /* Message not found in the queue that we are going to use. */
- LOG (GNUNET_ERROR_TYPE_DEBUG, "RETRANSMIT MID %u\n", copy->mid);
-
- GCCH_send_prebuilt_message (&payload->header, ch, fwd, copy);
- GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO);
-}
-
-
-/**
- * We haven't received an Channel ACK after a certain time: resend the CREATE.
- *
- * @param cls Closure (CadetChannelReliability of the channel to recreate)
- */
-static void
-channel_recreate (void *cls)
-{
- struct CadetChannelReliability *rel = cls;
-
- rel->retry_task = NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "RE-CREATE\n");
- GNUNET_STATISTICS_update (stats,
- "# data retransmitted", 1, GNUNET_NO);
-
- if (rel == rel->ch->root_rel)
- {
- send_create (rel->ch);
- }
- else if (rel == rel->ch->dest_rel)
- {
- send_ack (rel->ch, GNUNET_YES);
- }
- else
- {
- GNUNET_break (0);
- }
-}
-
-
-/**
- * Message has been sent: start retransmission timer.
- *
- * @param cls Closure (queue structure).
- * @param t Tunnel.
- * @param q Queue handler (no longer valid).
- * @param type Type of message.
- * @param size Size of the message.
- */
-static void
-ch_message_sent (void *cls,
- struct CadetTunnel *t,
- struct CadetTunnelQueue *q,
- uint16_t type, size_t size)
-{
- struct CadetChannelQueue *chq = cls;
- struct CadetReliableMessage *copy = chq->copy;
- struct CadetChannelReliability *rel;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "channel_message_sent callback %s\n",
- GC_m2s (chq->type));
-
- switch (chq->type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
- LOG (GNUNET_ERROR_TYPE_DEBUG, "data MID %u sent\n", copy->mid);
- GNUNET_assert (chq == copy->chq);
- copy->timestamp = GNUNET_TIME_absolute_get ();
- rel = copy->rel;
- if (NULL == rel->retry_task)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " scheduling retry in %d * %s\n",
- CADET_RETRANSMIT_MARGIN,
- GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
- GNUNET_YES));
- if (0 != rel->expected_delay.rel_value_us)
- {
- rel->retry_timer =
- GNUNET_TIME_relative_saturating_multiply (rel->expected_delay,
- CADET_RETRANSMIT_MARGIN);
- }
- else
- {
- rel->retry_timer = CADET_RETRANSMIT_TIME;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " using delay %s\n",
- GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
- GNUNET_NO));
- rel->retry_task =
- GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
- &channel_retransmit_message, rel);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "retry running %p\n", rel->retry_task);
- }
- copy->chq = NULL;
- break;
-
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
- LOG (GNUNET_ERROR_TYPE_DEBUG, "sent %s\n", GC_m2s (chq->type));
- rel = chq->rel;
- GNUNET_assert (rel->uniq == chq);
- rel->uniq = NULL;
-
- if (CADET_CHANNEL_READY != rel->ch->state
- && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK != type
- && GNUNET_NO == rel->ch->destroy)
- {
- GNUNET_assert (NULL == rel->retry_task);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "STD BACKOFF %s\n",
- GNUNET_STRINGS_relative_time_to_string (rel->retry_timer,
- GNUNET_NO));
- rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer);
- rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer,
- &channel_recreate, rel);
- }
- break;
-
- default:
- GNUNET_break (0);
- }
-
- GNUNET_free (chq);
-}
-
-
-/**
- * send a channel create message.
- *
- * @param ch Channel for which to send.
- */
-static void
-send_create (struct CadetChannel *ch)
-{
- struct GNUNET_CADET_ChannelOpenMessage msgcc;
-
- msgcc.header.size = htons (sizeof (msgcc));
- msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
- msgcc.ctn = ch->gid;
- msgcc.port = ch->port;
- msgcc.opt = htonl (channel_get_options (ch));
-
- GCCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL);
-}
-
-
-/**
- * Confirm we got a channel create or FWD ack.
- *
- * @param ch The channel to confirm.
- * @param fwd Should we send a FWD ACK? (going dest->root)
- */
-static void
-send_ack (struct CadetChannel *ch, int fwd)
-{
- struct GNUNET_CADET_ChannelManageMessage msg;
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " sending channel %s ack for channel %s\n",
- GC_f2s (fwd), GCCH_2s (ch));
-
- msg.ctn =ch->gid;
- GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL);
-}
-
-
-/**
- * Send a message and don't keep any info about it: we won't need to cancel it
- * or resend it.
- *
- * @param msg Header of the message to fire away.
- * @param ch Channel on which the message should go.
- * @param force Is this a forced (undroppable) message?
- */
-static void
-fire_and_forget (const struct GNUNET_MessageHeader *msg,
- struct CadetChannel *ch,
- int force)
-{
- GNUNET_break (NULL ==
- GCT_send_prebuilt_message (msg, ch->t, NULL,
- force, NULL, NULL));
-}
-
-
-/**
- * Notify that a channel create didn't succeed.
- *
- * @param ch The channel to reject.
- */
-static void
-send_nack (struct CadetChannel *ch)
-{
- struct GNUNET_CADET_ChannelManageMessage msg;
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " sending channel NACK for channel %s\n",
- GCCH_2s (ch));
-
- msg.ctn = ch->gid;
- GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL);
-}
-
-
-/**
- * Destroy all reliable messages queued for a channel,
- * during a channel destruction.
- * Frees the reliability structure itself.
- *
- * @param rel Reliability data for a channel.
- */
-static void
-channel_rel_free_all (struct CadetChannelReliability *rel)
-{
- struct CadetReliableMessage *copy;
- struct CadetReliableMessage *next;
-
- if (NULL == rel)
- return;
-
- for (copy = rel->head_recv; NULL != copy; copy = next)
- {
- next = copy->next;
- GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE ALL RECV %p\n", copy);
- GNUNET_break (NULL == copy->chq);
- GNUNET_free (copy);
- }
- for (copy = rel->head_sent; NULL != copy; copy = next)
- {
- next = copy->next;
- GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE ALL SEND %p\n", copy);
- if (NULL != copy->chq)
- {
- if (NULL != copy->chq->tq)
- {
- GCT_cancel (copy->chq->tq);
- /* ch_message_sent will free copy->q */
- }
- else
- {
- GNUNET_free (copy->chq);
- GNUNET_break (0);
- }
- }
- GNUNET_free (copy);
- }
- if (NULL != rel->uniq && NULL != rel->uniq->tq)
- {
- GCT_cancel (rel->uniq->tq);
- /* ch_message_sent is called freeing uniq */
- }
- if (NULL != rel->retry_task)
- {
- GNUNET_SCHEDULER_cancel (rel->retry_task);
- rel->retry_task = NULL;
- }
- GNUNET_free (rel);
-}
-
-
-/**
- * Mark future messages as ACK'd.
- *
- * @param rel Reliability data.
- * @param msg DataACK message with a bitfield of future ACK'd messages.
- *
- * @return How many messages have been freed.
- */
-static unsigned int
-channel_rel_free_sent (struct CadetChannelReliability *rel,
- const struct GNUNET_CADET_ChannelDataAckMessage *msg)
-{
- struct CadetReliableMessage *copy;
- struct CadetReliableMessage *next;
- uint64_t bitfield;
- uint64_t mask;
- uint32_t mid;
- uint32_t target;
- unsigned int i;
- unsigned int r;
-
- bitfield = msg->futures;
- mid = ntohl (msg->mid);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable %u %lX\n", mid, bitfield);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " rel %p, head %p\n", rel, rel->head_sent);
- for (i = 0, r = 0, copy = rel->head_sent;
- i < 64 && NULL != copy && 0 != bitfield;
- i++)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " trying bit %u (mid %u)\n", i, mid + i + 1);
- mask = 0x1LL << i;
- if (0 == (bitfield & mask))
- continue;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n");
- /* Bit was set, clear the bit from the bitfield */
- bitfield &= ~mask;
-
- /* The i-th bit was set. Do we have that copy? */
- /* Skip copies with mid < target */
- target = mid + i + 1;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target);
- while (NULL != copy && GC_is_pid_bigger (target, copy->mid))
- copy = copy->next;
-
- /* Did we run out of copies? (previously freed, it's ok) */
- if (NULL == copy)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n");
- return r;
- }
-
- /* Did we overshoot the target? (previously freed, it's ok) */
- if (GC_is_pid_bigger (copy->mid, target))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid);
- i += copy->mid - target - 1; /* MID: 90, t = 85, i += 4 (i++ later) */
- mask = (0x1LL << (i + 1)) - 1; /* Mask = i-th bit and all before */
- bitfield &= ~mask; /* Clear all bits up to MID - 1 */
- continue;
- }
-
- /* Now copy->mid == target, free it */
- next = copy->next;
- GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES));
- r++;
- copy = next;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n");
- return r;
-}
-
-
-/**
- * Destroy a reliable message after it has been acknowledged, either by
- * direct mid ACK or bitfield. Updates the appropriate data structures and
- * timers and frees all memory.
- *
- * @param copy Message that is no longer needed: remote peer got it.
- * @param update_time Is the timing information relevant?
- * If this message is ACK in a batch the timing information
- * is skewed by the retransmission, count only for the
- * retransmitted message.
- *
- * @return #GNUNET_YES if channel was destroyed as a result of the call,
- * #GNUNET_NO otherwise.
- */
-static int
-rel_message_free (struct CadetReliableMessage *copy, int update_time)
-{
- struct CadetChannelReliability *rel;
- struct GNUNET_TIME_Relative time;
-
- rel = copy->rel;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing %u\n", copy->mid);
- if (GNUNET_YES == update_time)
- {
- time = GNUNET_TIME_absolute_get_duration (copy->timestamp);
- if (0 == rel->expected_delay.rel_value_us)
- rel->expected_delay = time;
- else
- {
- rel->expected_delay.rel_value_us *= 7;
- rel->expected_delay.rel_value_us += time.rel_value_us;
- rel->expected_delay.rel_value_us /= 8;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " message time %12s\n",
- GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " new delay %12s\n",
- GNUNET_STRINGS_relative_time_to_string (rel->expected_delay,
- GNUNET_NO));
- rel->retry_timer = rel->expected_delay;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "batch free, ignoring timing\n");
- }
- rel->ch->pending_messages--;
- if (NULL != copy->chq)
- {
- GCT_cancel (copy->chq->tq);
- /* copy->q is set to NULL by ch_message_sent */
- }
- GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " free send copy MID %u at %p\n",
- copy->mid, copy);
- GNUNET_free (copy);
-
- if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages)
- {
- GCCH_destroy (rel->ch);
- return GNUNET_YES;
- }
- return GNUNET_NO;
-}
-
-
-/**
- * Channel was ACK'd by remote peer, mark as ready and cancel retransmission.
- *
- * @param ch Channel to mark as ready.
- * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK)
- */
-static void
-channel_confirm (struct CadetChannel *ch, int fwd)
-{
- struct CadetChannelReliability *rel;
- enum CadetChannelState oldstate;
-
- rel = fwd ? ch->root_rel : ch->dest_rel;
- if (NULL == rel)
- {
- GNUNET_break (GNUNET_NO != ch->destroy);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " channel confirm %s %s\n",
- GC_f2s (fwd), GCCH_2s (ch));
- oldstate = ch->state;
- ch->state = CADET_CHANNEL_READY;
-
- if (CADET_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch))
- {
- rel->client_ready = GNUNET_YES;
- rel->expected_delay = rel->retry_timer;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " confirm retry timer %s\n",
- GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO));
- if (GCT_get_connections_buffer (ch->t) > 0 || GCT_is_loopback (ch->t))
- send_client_ack (ch, fwd);
-
- if (NULL != rel->retry_task)
- {
- GNUNET_SCHEDULER_cancel (rel->retry_task);
- rel->retry_task = NULL;
- }
- else if (NULL != rel->uniq)
- {
- GCT_cancel (rel->uniq->tq);
- /* ch_message_sent will free and NULL uniq */
- }
- else if (GNUNET_NO == is_loopback (ch))
- {
- /* We SHOULD have been trying to retransmit this! */
- GNUNET_break (0);
- }
- }
-
- /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */
- if (GNUNET_YES == fwd)
- send_ack (ch, GNUNET_NO);
-}
-
-
-/**
- * Save a copy to retransmit in case it gets lost.
- *
- * Initializes all needed callbacks and timers.
- *
- * @param ch Channel this message goes on.
- * @param msg Message to copy.
- * @param fwd Is this fwd traffic?
- */
-static struct CadetReliableMessage *
-channel_save_copy (struct CadetChannel *ch,
- const struct GNUNET_MessageHeader *msg,
- int fwd)
-{
- struct CadetChannelReliability *rel;
- struct CadetReliableMessage *copy;
- uint32_t mid;
- uint16_t type;
- uint16_t size;
-
- rel = fwd ? ch->root_rel : ch->dest_rel;
- mid = rel->mid_send - 1;
- type = ntohs (msg->type);
- size = ntohs (msg->size);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "save MID %u %s\n", mid, GC_m2s (type));
- copy = GNUNET_malloc (sizeof (struct CadetReliableMessage) + size);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", copy);
- copy->mid = mid;
- copy->rel = rel;
- copy->type = type;
- GNUNET_memcpy (©[1], msg, size);
- GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy);
- ch->pending_messages++;
-
- return copy;
-}
-
-
-/**
- * Create a new channel.
- *
- * @param t Tunnel this channel is in.
- * @param owner Client that owns the channel, NULL for foreign channels.
- * @param lid_root Local ID for root client.
- *
- * @return A new initialized channel. NULL on error.
- */
-static struct CadetChannel *
-channel_new (struct CadetTunnel *t,
- struct CadetClient *owner,
- struct GNUNET_CADET_ClientChannelNumber lid_root)
-{
- struct CadetChannel *ch;
-
- ch = GNUNET_new (struct CadetChannel);
- ch->root = owner;
- ch->lid_root = lid_root;
- ch->t = t;
-
- GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
-
- if (NULL != owner)
- {
- ch->gid = GCT_get_next_ctn (t);
- GML_channel_add (owner, lid_root, ch);
- }
- GCT_add_channel (t, ch);
-
- return ch;
-}
-
-
-/**
- * Handle a loopback message: call the appropriate handler for the message type.
- *
- * @param ch Channel this message is on.
- * @param msgh Message header.
- * @param fwd Is this FWD traffic?
- */
-void
-handle_loopback (struct CadetChannel *ch,
- const struct GNUNET_MessageHeader *msgh,
- int fwd)
-{
- uint16_t type;
-
- type = ntohs (msgh->type);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Loopback %s %s message!\n",
- GC_f2s (fwd), GC_m2s (type));
-
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
- /* Don't send hop ACK, wait for client to ACK */
- LOG (GNUNET_ERROR_TYPE_DEBUG, "SEND loopback %u (%u)\n",
- ntohl (((struct GNUNET_CADET_ChannelAppDataMessage *) msgh)->mid), ntohs (msgh->size));
- GCCH_handle_data (ch, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
- GCCH_handle_data_ack (ch,
- (const struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
- GCCH_handle_create (ch->t,
- (const struct GNUNET_CADET_ChannelOpenMessage *) msgh);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
- GCCH_handle_ack (ch,
- (const struct GNUNET_CADET_ChannelManageMessage *) msgh,
- fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
- GCCH_handle_nack (ch);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
- GCCH_handle_destroy (ch,
- (const struct GNUNET_CADET_ChannelManageMessage *) msgh,
- fwd);
- break;
-
- default:
- GNUNET_break_op (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "end-to-end message not known (%u)\n",
- ntohs (msgh->type));
- }
-}
-
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Destroy a channel and free all resources.
- *
- * @param ch Channel to destroy.
- */
-void
-GCCH_destroy (struct CadetChannel *ch)
-{
- struct CadetClient *c;
- struct CadetTunnel *t;
-
- if (NULL == ch)
- return;
- if (2 == ch->destroy)
- return; /* recursive call */
- ch->destroy = 2;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n",
- GCT_2s (ch->t), ch->gid);
- GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG);
-
- c = ch->root;
- if (NULL != c)
- {
- GML_channel_remove (c, ch->lid_root, ch);
- }
-
- c = ch->dest;
- if (NULL != c)
- {
- GML_channel_remove (c, ch->lid_dest, ch);
- }
-
- channel_rel_free_all (ch->root_rel);
- channel_rel_free_all (ch->dest_rel);
-
- t = ch->t;
- GCT_remove_channel (t, ch);
- GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO);
-
- GNUNET_free (ch);
- GCT_destroy_if_empty (t);
-}
-
-
-/**
- * Get the channel's public ID.
- *
- * @param ch Channel.
- *
- * @return ID used to identify the channel with the remote peer.
- */
-struct GNUNET_CADET_ChannelTunnelNumber
-GCCH_get_id (const struct CadetChannel *ch)
-{
- return ch->gid;
-}
-
-
-/**
- * Get the channel tunnel.
- *
- * @param ch Channel to get the tunnel from.
- *
- * @return tunnel of the channel.
- */
-struct CadetTunnel *
-GCCH_get_tunnel (const struct CadetChannel *ch)
-{
- return ch->t;
-}
-
-
-/**
- * Get free buffer space towards the client on a specific channel.
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - 64]
- */
-unsigned int
-GCCH_get_buffer (struct CadetChannel *ch, int fwd)
-{
- struct CadetChannelReliability *rel;
-
- rel = fwd ? ch->dest_rel : ch->root_rel;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " get buffer, channel %s\n", GCCH_2s (ch));
- GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG);
- /* If rel is NULL it means that the end is not yet created,
- * most probably is a loopback channel at the point of sending
- * the ChannelCreate to itself.
- */
- if (NULL == rel)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " rel is NULL: max\n");
- return 64;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " n_recv %d\n", rel->n_recv);
- return (64 - rel->n_recv);
-}
-
-
-/**
- * Get flow control status of end point: is client allow to send?
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic? (Request root status).
- *
- * @return #GNUNET_YES if client is allowed to send us data.
- */
-int
-GCCH_get_allowed (struct CadetChannel *ch, int fwd)
-{
- struct CadetChannelReliability *rel;
-
- rel = fwd ? ch->root_rel : ch->dest_rel;
-
- if (NULL == rel)
- {
- /* Probably shutting down: root/dest NULL'ed to mark disconnection */
- GNUNET_break (GNUNET_NO != ch->destroy);
- return 0;
- }
-
- return rel->client_allowed;
-}
-
-
-/**
- * Is the root client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GCCH_is_origin (struct CadetChannel *ch, int fwd)
-{
- struct CadetClient *c;
-
- c = fwd ? ch->root : ch->dest;
- return NULL != c;
-}
-
-
-/**
- * Is the destination client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GCCH_is_terminal (struct CadetChannel *ch, int fwd)
-{
- struct CadetClient *c;
-
- c = fwd ? ch->dest : ch->root;
- return NULL != c;
-}
-
-
-/**
- * Send an end-to-end ACK message for the most recent in-sequence payload.
- *
- * If channel is not reliable, do nothing.
- *
- * @param ch Channel this is about.
- * @param fwd Is for FWD traffic? (ACK dest->owner)
- */
-void
-GCCH_send_data_ack (struct CadetChannel *ch, int fwd)
-{
- struct GNUNET_CADET_ChannelDataAckMessage msg;
- struct CadetChannelReliability *rel;
- struct CadetReliableMessage *copy;
- unsigned int delta;
- uint64_t mask;
- uint32_t ack;
-
- if (GNUNET_NO == ch->reliable)
- return;
-
- rel = fwd ? ch->dest_rel : ch->root_rel;
- ack = rel->mid_recv - 1;
-
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
- msg.header.size = htons (sizeof (msg));
- msg.ctn = ch->gid;
- msg.mid = htonl (ack);
-
- msg.futures = 0LL;
- for (copy = rel->head_recv; NULL != copy; copy = copy->next)
- {
- if (copy->type != GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Type %s, expected DATA\n",
- GC_m2s (copy->type));
- continue;
- }
- GNUNET_assert (GC_is_pid_bigger(copy->mid, ack));
- delta = copy->mid - (ack + 1);
- if (63 < delta)
- break;
- mask = 0x1LL << delta;
- msg.futures |= mask;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " setting bit for %u (delta %u) (%lX) -> %lX\n",
- copy->mid, delta, mask, msg.futures);
- }
-
- GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n");
-}
-
-
-/**
- * Allow a client to send us more data, in case it was choked.
- *
- * @param ch Channel.
- * @param fwd Is this about FWD traffic? (Root client).
- */
-void
-GCCH_allow_client (struct CadetChannel *ch, int fwd)
-{
- struct CadetChannelReliability *rel;
- unsigned int buffer;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n");
-
- if (CADET_CHANNEL_READY != ch->state)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n");
- return;
- }
-
- if (GNUNET_YES == ch->reliable)
- {
- rel = fwd ? ch->root_rel : ch->dest_rel;
- if (NULL == rel)
- {
- GNUNET_break (GNUNET_NO != ch->destroy);
- return;
- }
- if (NULL != rel->head_sent)
- {
- if (64 <= rel->mid_send - rel->head_sent->mid)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n");
- return;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n",
- rel->head_sent->mid, rel->mid_send);
- struct CadetReliableMessage *aux;
- for (aux = rel->head_sent; NULL != aux; aux = aux->next)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " - sent mid %u\n", aux->mid);
- }
- }
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n");
- }
- }
-
- if (is_loopback (ch))
- buffer = GCCH_get_buffer (ch, fwd);
- else
- buffer = GCT_get_connections_buffer (ch->t);
-
- if (0 == buffer)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n");
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer);
- send_client_ack (ch, fwd);
-}
-
-
-/**
- * Log channel info.
- *
- * @param ch Channel.
- * @param level Debug level to use.
- */
-void
-GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
-{
- int do_log;
-
- do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
- "cadet-chn",
- __FILE__, __FUNCTION__, __LINE__);
- if (0 == do_log)
- return;
-
- if (NULL == ch)
- {
- LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
- return;
- }
- LOG2 (level, "CHN Channel %s:%X (%p)\n", GCT_2s (ch->t), ch->gid, ch);
- LOG2 (level, "CHN root %p/%p\n", ch->root, ch->root_rel);
- if (NULL != ch->root)
- {
- LOG2 (level, "CHN cli %s\n", GML_2s (ch->root));
- LOG2 (level, "CHN ready %s\n", ch->root_rel->client_ready ? "YES" : "NO");
- LOG2 (level, "CHN id %X\n", ch->lid_root.channel_of_client);
- LOG2 (level, "CHN recv %d\n", ch->root_rel->n_recv);
- LOG2 (level, "CHN MID r: %d, s: %d\n",
- ch->root_rel->mid_recv, ch->root_rel->mid_send);
- }
- LOG2 (level, "CHN dest %p/%p\n",
- ch->dest, ch->dest_rel);
- if (NULL != ch->dest)
- {
- LOG2 (level, "CHN cli %s\n", GML_2s (ch->dest));
- LOG2 (level, "CHN ready %s\n", ch->dest_rel->client_ready ? "YES" : "NO");
- LOG2 (level, "CHN id %X\n", ch->lid_dest);
- LOG2 (level, "CHN recv %d\n", ch->dest_rel->n_recv);
- LOG2 (level, "CHN MID r: %d, s: %d\n",
- ch->dest_rel->mid_recv, ch->dest_rel->mid_send);
-
- }
-}
-
-
-/**
- * Handle an ACK given by a client.
- *
- * Mark client as ready and send him any buffered data we could have for him.
- *
- * @param ch Channel.
- * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK)
- */
-void
-GCCH_handle_local_ack (struct CadetChannel *ch, int fwd)
-{
- struct CadetChannelReliability *rel;
- struct CadetClient *c;
-
- rel = fwd ? ch->dest_rel : ch->root_rel;
- c = fwd ? ch->dest : ch->root;
-
- rel->client_ready = GNUNET_YES;
- send_client_buffered_data (ch, c, fwd);
-
- if (GNUNET_YES == ch->destroy && 0 == rel->n_recv)
- {
- send_destroy (ch, GNUNET_YES);
- GCCH_destroy (ch);
- return;
- }
- /* if loopback is marked for destruction, no need to ACK to the other peer,
- * it requested the destruction and is already gone, therefore, else if.
- */
- else if (is_loopback (ch))
- {
- unsigned int buffer;
-
- buffer = GCCH_get_buffer (ch, fwd);
- if (0 < buffer)
- GCCH_allow_client (ch, fwd);
-
- return;
- }
- GCT_send_connection_acks (ch->t);
-}
-
-
-/**
- * Handle data given by a client.
- *
- * Check whether the client is allowed to send in this tunnel, save if channel
- * is reliable and send an ACK to the client if there is still buffer space
- * in the tunnel.
- *
- * @param ch Channel.
- * @param c Client which sent the data.
- * @param fwd Is this a FWD data?
- * @param message Data message.
- * @param size Size of data.
- *
- * @return #GNUNET_OK if everything goes well, #GNUNET_SYSERR in case of en error.
- */
-int
-GCCH_handle_local_data (struct CadetChannel *ch,
- struct CadetClient *c,
- int fwd,
- const struct GNUNET_MessageHeader *message,
- size_t size)
-{
- struct CadetChannelReliability *rel;
- struct GNUNET_CADET_ChannelAppDataMessage *payload;
- uint16_t p2p_size = sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + size;
- unsigned char cbuf[p2p_size];
- unsigned char buffer;
-
- /* Is the client in the channel? */
- if ( !( (fwd &&
- ch->root == c)
- ||
- (!fwd &&
- ch->dest == c) ) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- rel = fwd ? ch->root_rel : ch->dest_rel;
-
- if (GNUNET_NO == rel->client_allowed)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- rel->client_allowed = GNUNET_NO;
-
- /* Ok, everything is correct, send the message. */
- payload = (struct GNUNET_CADET_ChannelAppDataMessage *) cbuf;
- payload->mid = htonl (rel->mid_send);
- rel->mid_send++;
- GNUNET_memcpy (&payload[1], message, size);
- payload->header.size = htons (p2p_size);
- payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
- payload->ctn = ch->gid;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
- GCCH_send_prebuilt_message (&payload->header, ch, fwd, NULL);
-
- if (is_loopback (ch))
- buffer = GCCH_get_buffer (ch, fwd);
- else
- buffer = GCT_get_connections_buffer (ch->t);
-
- if (0 < buffer)
- GCCH_allow_client (ch, fwd);
-
- return GNUNET_OK;
-}
-
-
-/**
- * Handle a channel destroy requested by a client.
- *
- * TODO: add "reason" field
- *
- * Destroy the channel and the tunnel in case this was the last channel.
- *
- * @param ch Channel.
- * @param c Client that requested the destruction (to avoid notifying him).
- * @param is_root Is the request coming from root?
- */
-void
-GCCH_handle_local_destroy (struct CadetChannel *ch,
- struct CadetClient *c,
- int is_root)
-{
- ch->destroy = GNUNET_YES;
- /* Cleanup after the tunnel */
- if (GNUNET_NO == is_root && c == ch->dest)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c));
- GML_client_delete_channel (c, ch, ch->lid_dest);
- ch->dest = NULL;
- }
- if (GNUNET_YES == is_root && c == ch->root)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c));
- GML_client_delete_channel (c, ch, ch->lid_root);
- ch->root = NULL;
- }
-
- send_destroy (ch, GNUNET_NO);
- if (0 == ch->pending_messages)
- GCCH_destroy (ch);
-}
-
-
-/**
- * Handle a channel create requested by a client.
- *
- * Create the channel and the tunnel in case this was the first0 channel.
- *
- * @param c Client that requested the creation (will be the root).
- * @param msg Create Channel message.
- *
- * @return #GNUNET_OK if everything went fine, #GNUNET_SYSERR otherwise.
- */
-int
-GCCH_handle_local_create (struct CadetClient *c,
- struct GNUNET_CADET_LocalChannelCreateMessage *msg)
-{
- struct CadetChannel *ch;
- struct CadetTunnel *t;
- struct CadetPeer *peer;
- struct GNUNET_CADET_ClientChannelNumber ccn;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n",
- GNUNET_i2s (&msg->peer), GNUNET_h2s (&msg->port));
- ccn = msg->ccn;
-
- /* Sanity check for duplicate channel IDs */
- if (NULL != GML_channel_get (c, ccn))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
-
- peer = GCP_get (&msg->peer, GNUNET_YES);
- GCP_add_tunnel (peer);
- t = GCP_get_tunnel (peer);
-
- if (GCP_get_short_id (peer) == myid)
- {
- GCT_change_cstate (t, CADET_TUNNEL_READY);
- }
- else
- {
- /* FIXME change to a tunnel API, eliminate ch <-> peer connection */
- GCP_connect (peer);
- }
-
- /* Create channel */
- ch = channel_new (t, c, ccn);
- if (NULL == ch)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- ch->port = msg->port;
- channel_set_options (ch, ntohl (msg->opt));
-
- /* In unreliable channels, we'll use the DLL to buffer BCK data */
- ch->root_rel = GNUNET_new (struct CadetChannelReliability);
- ch->root_rel->ch = ch;
- ch->root_rel->retry_timer = CADET_RETRANSMIT_TIME;
- ch->root_rel->expected_delay.rel_value_us = 0;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GCCH_2s (ch));
-
- send_create (ch);
-
- return GNUNET_OK;
-}
-
-
-/**
- * Handler for cadet network payload traffic.
- *
- * @param ch Channel for the message.
- * @param msg Unencryted data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_data (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelAppDataMessage *msg,
- int fwd)
-{
- struct CadetChannelReliability *rel;
- struct CadetClient *c;
- struct GNUNET_MessageHeader *payload_msg;
- uint32_t mid;
- uint16_t payload_type;
- uint16_t payload_size;
-
- /* If this is a remote (non-loopback) channel, find 'fwd'. */
- if (GNUNET_SYSERR == fwd)
- {
- if (is_loopback (ch))
- {
- /* It is a loopback channel after all... */
- GNUNET_break (0);
- return;
- }
- fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
- }
-
- /* Initialize FWD/BCK data */
- c = fwd ? ch->dest : ch->root;
- rel = fwd ? ch->dest_rel : ch->root_rel;
-
- if (NULL == c)
- {
- GNUNET_break (GNUNET_NO != ch->destroy);
- return;
- }
-
- if (CADET_CHANNEL_READY != ch->state)
- {
- if (GNUNET_NO == fwd)
- {
- /* If we are the root, this means the other peer has sent traffic before
- * receiving our ACK. Even if the SYNACK goes missing, no traffic should
- * be sent before the ACK.
- */
- GNUNET_break_op (0);
- return;
- }
- /* If we are the dest, this means that the SYNACK got to the root but
- * the ACK went missing. Treat this as an ACK.
- */
- channel_confirm (ch, GNUNET_NO);
- }
-
- payload_msg = (struct GNUNET_MessageHeader *) &msg[1];
- payload_type = ntohs (payload_msg->type);
- payload_size = ntohs (payload_msg->size);
-
- GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
- GNUNET_STATISTICS_update (stats, "# bytes received", payload_size, GNUNET_NO);
-
- mid = ntohl (msg->mid);
- LOG (GNUNET_ERROR_TYPE_INFO, "<== %s (%s %4u) on chan %s (%p) %s [%5u]\n",
- GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA), GC_m2s (payload_type), mid,
- GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
-
- if ( (GNUNET_NO == ch->reliable) ||
- ( (! GC_is_pid_bigger (rel->mid_recv, mid)) &&
- GC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
- {
- if (GNUNET_YES == ch->reliable)
- {
- /* Is this the exact next expected messasge? */
- if (mid == rel->mid_recv)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "as expected, sending to client\n");
- send_client_data (ch, msg, fwd);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "save for later\n");
- add_buffered_data (msg, rel);
- }
- }
- else
- {
- /* Tunnel is unreliable: send to clients directly */
- /* FIXME: accept Out Of Order traffic */
- rel->mid_recv = mid + 1;
- send_client_data (ch, msg, fwd);
- }
- }
- else
- {
- GNUNET_STATISTICS_update (stats, "# duplicate MID", 1, GNUNET_NO);
- if (GC_is_pid_bigger (rel->mid_recv, mid))
- {
- GNUNET_break_op (0);
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "MID %u on channel %s not expected (window: %u - %u). Dropping!\n",
- mid, GCCH_2s (ch), rel->mid_recv, rel->mid_recv + 63);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Duplicate MID %u, channel %s (expecting MID %u). Re-sending ACK!\n",
- mid, GCCH_2s (ch), rel->mid_recv);
- if (NULL != rel->uniq)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "We are trying to send an ACK, but don't seem have the "
- "bandwidth. Have you set enough [ats] QUOTA in your config?\n");
- }
-
- }
- }
-
- GCCH_send_data_ack (ch, fwd);
-}
-
-
-/**
- * Handler for cadet network traffic end-to-end ACKs.
- *
- * @param ch Channel on which we got this message.
- * @param msg Data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_data_ack (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelDataAckMessage *msg,
- int fwd)
-{
- struct CadetChannelReliability *rel;
- struct CadetReliableMessage *copy;
- struct CadetReliableMessage *next;
- uint32_t ack;
- int work;
-
- /* If this is a remote (non-loopback) channel, find 'fwd'. */
- if (GNUNET_SYSERR == fwd)
- {
- if (is_loopback (ch))
- {
- /* It is a loopback channel after all... */
- GNUNET_break (0);
- return;
- }
- /* Inverted: if message came 'FWD' is a 'BCK ACK'. */
- fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES;
- }
-
- ack = ntohl (msg->mid);
- LOG (GNUNET_ERROR_TYPE_INFO,
- "<== %s (0x%010lX %4u) on chan %s (%p) %s [%5u]\n",
- GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK), msg->futures, ack,
- GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
-
- if (GNUNET_YES == fwd)
- rel = ch->root_rel;
- else
- rel = ch->dest_rel;
-
- if (NULL == rel)
- {
- GNUNET_break (GNUNET_NO != ch->destroy);
- return;
- }
-
- /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */
- for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next)
- {
- if (GC_is_pid_bigger (copy->mid, ack))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " head %u, out!\n", copy->mid);
- if (0 < channel_rel_free_sent (rel, msg))
- work = GNUNET_YES;
- break;
- }
- work = GNUNET_YES;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " id %u\n", copy->mid);
- next = copy->next;
- if (GNUNET_YES == rel_message_free (copy, GNUNET_YES))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " channel destoyed\n");
- return;
- }
- }
-
- /* ACK client if needed and possible */
- GCCH_allow_client (ch, fwd);
-
- /* If some message was free'd, update the retransmission delay */
- if (GNUNET_YES == work)
- {
- if (NULL != rel->retry_task)
- {
- GNUNET_SCHEDULER_cancel (rel->retry_task);
- rel->retry_task = NULL;
- if (NULL != rel->head_sent && NULL == rel->head_sent->chq)
- {
- struct GNUNET_TIME_Absolute new_target;
- struct GNUNET_TIME_Relative delay;
-
- delay = GNUNET_TIME_relative_saturating_multiply (rel->retry_timer,
- CADET_RETRANSMIT_MARGIN);
- new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp,
- delay);
- delay = GNUNET_TIME_absolute_get_remaining (new_target);
- rel->retry_task =
- GNUNET_SCHEDULER_add_delayed (delay,
- &channel_retransmit_message,
- rel);
- }
- }
- else
- {
- /* Work was done but no task was pending.
- * Task was cancelled by a retransmission that is sitting in the queue.
- */
- // FIXME add test to make sure this is the case, probably add return
- // value to GCCH_send_prebuilt_message
- }
- }
-}
-
-
-/**
- * Handler for channel create messages.
- *
- * Does not have fwd parameter because it's always 'FWD': channel is incoming.
- *
- * @param t Tunnel this channel will be in.
- * @param msg Channel crate message.
- */
-struct CadetChannel *
-GCCH_handle_create (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelOpenMessage *msg)
-{
- struct GNUNET_CADET_ClientChannelNumber ccn;
- struct GNUNET_CADET_ChannelTunnelNumber gid;
- struct CadetChannel *ch;
- struct CadetClient *c;
- int new_channel;
- const struct GNUNET_HashCode *port;
-
- gid = msg->ctn;
- ch = GCT_get_channel (t, gid);
- if (NULL == ch)
- {
- /* Create channel */
- ccn.channel_of_client = htonl (0);
- ch = channel_new (t, NULL, ccn);
- ch->gid = gid;
- channel_set_options (ch, ntohl (msg->opt));
- new_channel = GNUNET_YES;
- }
- else
- {
- new_channel = GNUNET_NO;
- }
- port = &msg->port;
-
- LOG (GNUNET_ERROR_TYPE_INFO,
- "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
- GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN), ccn, port,
- GCCH_2s (ch), ch, GC_f2s (GNUNET_YES), ntohs (msg->header.size));
-
- if (GNUNET_YES == new_channel || GCT_is_loopback (t))
- {
- /* Find a destination client */
- ch->port = *port;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " port %s\n", GNUNET_h2s (port));
- c = GML_client_get_by_port (port);
- if (NULL == c)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n");
- if (is_loopback (ch))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback: destroy on handler\n");
- send_nack (ch);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not loopback: destroy now\n");
- send_nack (ch);
- GCCH_destroy (ch);
- }
- return NULL;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " client %p has port registered\n", c);
- }
-
- add_destination (ch, c);
- if (GNUNET_YES == ch->reliable)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Reliable\n");
- else
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Not Reliable\n");
-
- send_client_create (ch);
- ch->state = CADET_CHANNEL_SENT;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate create channel\n");
- if (NULL != ch->dest_rel->retry_task)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " clearing retry task\n");
- /* we were waiting to re-send our 'SYNACK', wait no more! */
- GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task);
- ch->dest_rel->retry_task = NULL;
- }
- else if (NULL != ch->dest_rel->uniq)
- {
- /* we are waiting to for our 'SYNACK' to leave the queue, all done! */
- return ch;
- }
- }
- send_ack (ch, GNUNET_YES);
-
- return ch;
-}
-
-
-/**
- * Handler for channel NACK messages.
- *
- * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
- *
- * @param ch Channel.
- */
-void
-GCCH_handle_nack (struct CadetChannel *ch)
-{
- LOG (GNUNET_ERROR_TYPE_INFO,
- "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
- GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED), ch->gid, 0,
- GCCH_2s (ch), ch, "---", 0);
-
- send_client_nack (ch);
- GCCH_destroy (ch);
-}
-
-
-/**
- * Handler for channel ack messages.
- *
- * @param ch Channel.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_ack (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelManageMessage *msg,
- int fwd)
-{
- LOG (GNUNET_ERROR_TYPE_INFO,
- "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
- GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK), ch->gid, 0,
- GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
-
- /* If this is a remote (non-loopback) channel, find 'fwd'. */
- if (GNUNET_SYSERR == fwd)
- {
- if (is_loopback (ch))
- {
- /* It is a loopback channel after all... */
- GNUNET_break (0);
- return;
- }
- fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
- }
-
- channel_confirm (ch, !fwd);
-}
-
-
-/**
- * Handler for channel destroy messages.
- *
- * @param ch Channel to be destroyed of.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_destroy (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelManageMessage *msg,
- int fwd)
-{
- struct CadetChannelReliability *rel;
-
- LOG (GNUNET_ERROR_TYPE_INFO,
- "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n",
- GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY), ch->gid, 0,
- GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size));
-
- /* If this is a remote (non-loopback) channel, find 'fwd'. */
- if (GNUNET_SYSERR == fwd)
- {
- if (is_loopback (ch))
- {
- /* It is a loopback channel after all... */
- GNUNET_break (0);
- return;
- }
- fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO;
- }
-
- GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG);
- if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
- {
- /* Not for us (don't destroy twice a half-open loopback channel) */
- return;
- }
-
- rel = fwd ? ch->dest_rel : ch->root_rel;
- if (0 == rel->n_recv)
- {
- send_destroy (ch, GNUNET_YES);
- GCCH_destroy (ch);
- }
- else
- {
- ch->destroy = GNUNET_YES;
- }
-}
-
-
-/**
- * Sends an already built message on a channel.
- *
- * If the channel is on a loopback tunnel, notifies the appropriate destination
- * client locally.
- *
- * On a normal channel passes the message to the tunnel for encryption and
- * sending on a connection.
- *
- * This function DOES NOT save the message for retransmission.
- *
- * @param message Message to send. Function makes a copy of it.
- * @param ch Channel on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param existing_copy This is a retransmission, don't save a copy.
- */
-void
-GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- struct CadetChannel *ch, int fwd,
- void *existing_copy)
-{
- struct CadetChannelQueue *chq;
- uint32_t data_id;
- uint16_t type;
- uint16_t size;
- char info[32];
-
- type = ntohs (message->type);
- size = ntohs (message->size);
-
- data_id = 0;
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
- {
- struct GNUNET_CADET_ChannelAppDataMessage *data_msg;
- struct GNUNET_MessageHeader *payload_msg;
- uint16_t payload_type;
-
- data_msg = (struct GNUNET_CADET_ChannelAppDataMessage *) message;
- data_id = ntohl (data_msg->mid);
- payload_msg = (struct GNUNET_MessageHeader *) &data_msg[1];
- payload_type = ntohs (payload_msg->type);
- strncpy (info, GC_m2s (payload_type), 31);
- info[31] = '\0';
- break;
- }
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
- {
- struct GNUNET_CADET_ChannelDataAckMessage *ack_msg;
- ack_msg = (struct GNUNET_CADET_ChannelDataAckMessage *) message;
- data_id = ntohl (ack_msg->mid);
- SPRINTF (info, "0x%010lX",
- (unsigned long int) ack_msg->futures);
- break;
- }
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
- {
- struct GNUNET_CADET_ChannelOpenMessage *cc_msg;
- cc_msg = (struct GNUNET_CADET_ChannelOpenMessage *) message;
- SPRINTF (info, " 0x%08X", ntohl (cc_msg->ctn.cn));
- break;
- }
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
- {
- struct GNUNET_CADET_ChannelManageMessage *m_msg;
- m_msg = (struct GNUNET_CADET_ChannelManageMessage *) message;
- SPRINTF (info, " 0x%08X", ntohl (m_msg->ctn.cn));
- break;
- }
- default:
- info[0] = '\0';
- }
- LOG (GNUNET_ERROR_TYPE_INFO,
- "==> %s (%12s %4u) on chan %s (%p) %s [%5u]\n",
- GC_m2s (type), info, data_id,
- GCCH_2s (ch), ch, GC_f2s (fwd), size);
-
- if (GCT_is_loopback (ch->t))
- {
- handle_loopback (ch, message, fwd);
- return;
- }
-
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
- if (GNUNET_YES == ch->reliable)
- {
- chq = GNUNET_new (struct CadetChannelQueue);
- chq->type = type;
- if (NULL == existing_copy)
- chq->copy = channel_save_copy (ch, message, fwd);
- else
- {
- chq->copy = (struct CadetReliableMessage *) existing_copy;
- if (NULL != chq->copy->chq)
- {
- /* Last retransmission was queued but not yet sent!
- * This retransmission was scheduled by a ch_message_sent which
- * followed a very fast RTT, so the tiny delay made the
- * retransmission function to execute before the previous
- * retransmitted message even had a chance to leave the peer.
- * Cancel this message and wait until the pending
- * retransmission leaves the peer and ch_message_sent starts
- * the timer for the next one.
- */
- GNUNET_free (chq);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " exisitng copy not yet transmitted!\n");
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " using existing copy: %p {r:%p q:%p t:%u}\n",
- existing_copy,
- chq->copy->rel, chq->copy->chq, chq->copy->type);
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " new chq: %p\n", chq);
- chq->copy->chq = chq;
- chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL,
- GNUNET_YES,
- &ch_message_sent, chq);
- /* q itself is stored in copy */
- GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy);
- }
- else
- {
- fire_and_forget (message, ch, GNUNET_NO);
- }
- break;
-
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
- chq = GNUNET_new (struct CadetChannelQueue);
- chq->type = type;
- chq->rel = fwd ? ch->root_rel : ch->dest_rel;
- if (NULL != chq->rel->uniq)
- {
- if (NULL != chq->rel->uniq->tq)
- {
- GCT_cancel (chq->rel->uniq->tq);
- /* ch_message_sent is called, freeing and NULLing uniq */
- GNUNET_break (NULL == chq->rel->uniq);
- }
- else
- {
- GNUNET_break (0);
- GNUNET_free (chq->rel->uniq);
- }
- }
-
- chq->rel->uniq = chq;
- chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES,
- &ch_message_sent, chq);
- if (NULL == chq->tq)
- {
- GNUNET_break (0);
- chq->rel->uniq = NULL;
- GCT_debug (ch->t, GNUNET_ERROR_TYPE_ERROR);
- GNUNET_free (chq);
- chq = NULL;
- return;
- }
- break;
-
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
- fire_and_forget (message, ch, GNUNET_YES);
- break;
-
-
- default:
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_WARNING, "type %s unknown!\n", GC_m2s (type));
- fire_and_forget (message, ch, GNUNET_YES);
- }
-}
-
-
-/**
- * Get the static string for identification of the channel.
- *
- * @param ch Channel.
- *
- * @return Static string with the channel IDs.
- */
-const char *
-GCCH_2s (const struct CadetChannel *ch)
-{
- static char buf[64];
-
- if (NULL == ch)
- return "(NULL Channel)";
-
- SPRINTF (buf,
- "%s:%s gid:%X (%X / %X)",
- GCT_2s (ch->t),
- GNUNET_h2s (&ch->port),
- ntohl (ch->gid.cn),
- ntohl (ch->lid_root.channel_of_client),
- ntohl (ch->lid_dest.channel_of_client));
-
- return buf;
-}
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_channel.h
- * @brief cadet service; dealing with end-to-end channels
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMCH (Gnunet Cadet CHannel)
- */
-
-#ifndef GNUNET_SERVICE_CADET_CHANNEL_H
-#define GNUNET_SERVICE_CADET_CHANNEL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "cadet_protocol.h"
-#include "cadet.h"
-
-/**
- * Struct containing all information regarding a channel to a remote client.
- */
-struct CadetChannel;
-
-
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_local.h"
-
-
-/**
- * Destroy a channel and free all resources.
- *
- * @param ch Channel to destroy.
- */
-void
-GCCH_destroy (struct CadetChannel *ch);
-
-
-/**
- * Get the channel's public ID.
- *
- * @param ch Channel.
- *
- * @return ID used to identify the channel with the remote peer.
- */
-struct GNUNET_CADET_ChannelTunnelNumber
-GCCH_get_id (const struct CadetChannel *ch);
-
-
-/**
- * Get the channel tunnel.
- *
- * @param ch Channel to get the tunnel from.
- *
- * @return tunnel of the channel.
- */
-struct CadetTunnel *
-GCCH_get_tunnel (const struct CadetChannel *ch);
-
-
-/**
- * Get free buffer space towards the client on a specific channel.
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - 64]
- */
-unsigned int
-GCCH_get_buffer (struct CadetChannel *ch, int fwd);
-
-
-/**
- * Get flow control status of end point: is client allow to send?
- *
- * @param ch Channel.
- * @param fwd Is query about FWD traffic? (Request root status).
- *
- * @return #GNUNET_YES if client is allowed to send us data.
- */
-int
-GCCH_get_allowed (struct CadetChannel *ch, int fwd);
-
-
-/**
- * Is the root client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GCCH_is_origin (struct CadetChannel *ch, int fwd);
-
-/**
- * Is the destination client for this channel on this peer?
- *
- * @param ch Channel.
- * @param fwd Is this for fwd traffic?
- *
- * @return #GNUNET_YES in case it is.
- */
-int
-GCCH_is_terminal (struct CadetChannel *ch, int fwd);
-
-/**
- * Send an end-to-end ACK message for the most recent in-sequence payload.
- *
- * If channel is not reliable, do nothing.
- *
- * @param ch Channel this is about.
- * @param fwd Is for FWD traffic? (ACK dest->owner)
- */
-void
-GCCH_send_data_ack (struct CadetChannel *ch, int fwd);
-
-/**
- * Notify the destination client that a new incoming channel was created.
- *
- * @param ch Channel that was created.
- */
-void
-GCCH_send_create (struct CadetChannel *ch);
-
-/**
- * Allow a client to send us more data, in case it was choked.
- *
- * @param ch Channel.
- * @param fwd Is this about FWD traffic? (Root client).
- */
-void
-GCCH_allow_client (struct CadetChannel *ch, int fwd);
-
-/**
- * Log channel info.
- *
- * @param ch Channel.
- * @param level Debug level to use.
- */
-void
-GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level);
-
-/**
- * Handle an ACK given by a client.
- *
- * Mark client as ready and send him any buffered data we could have for him.
- *
- * @param ch Channel.
- * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK)
- */
-void
-GCCH_handle_local_ack (struct CadetChannel *ch, int fwd);
-
-/**
- * Handle data given by a client.
- *
- * Check whether the client is allowed to send in this tunnel, save if channel
- * is reliable and send an ACK to the client if there is still buffer space
- * in the tunnel.
- *
- * @param ch Channel.
- * @param c Client which sent the data.
- * @param fwd Is this a FWD data?
- * @param message Data message.
- * @param size Size of data.
- *
- * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error.
- */
-int
-GCCH_handle_local_data (struct CadetChannel *ch,
- struct CadetClient *c, int fwd,
- const struct GNUNET_MessageHeader *message,
- size_t size);
-
-/**
- * Handle a channel destroy requested by a client.
- *
- * Destroy the channel and the tunnel in case this was the last channel.
- *
- * @param ch Channel.
- * @param c Client that requested the destruction (to avoid notifying him).
- * @param is_root Is the request coming from root?
- */
-void
-GCCH_handle_local_destroy (struct CadetChannel *ch,
- struct CadetClient *c,
- int is_root);
-
-
-/**
- * Handle a channel create requested by a client.
- *
- * Create the channel and the tunnel in case this was the first0 channel.
- *
- * @param c Client that requested the creation (will be the root).
- * @param msg Create Channel message.
- *
- * @return #GNUNET_OK if everything went fine, #GNUNET_SYSERR otherwise.
- */
-int
-GCCH_handle_local_create (struct CadetClient *c,
- struct GNUNET_CADET_LocalChannelCreateMessage *msg);
-
-/**
- * Handler for cadet network payload traffic.
- *
- * @param ch Channel for the message.
- * @param msg Unencryted data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_data (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelAppDataMessage *msg,
- int fwd);
-
-
-/**
- * Handler for cadet network traffic end-to-end ACKs.
- *
- * @param ch Channel on which we got this message.
- * @param msg Data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_data_ack (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelDataAckMessage *msg,
- int fwd);
-
-
-/**
- * Handler for channel create messages.
- *
- * Does not have fwd parameter because it's always 'FWD': channel is incoming.
- *
- * @param t Tunnel this channel will be in.
- * @param msg Channel crate message.
- */
-struct CadetChannel *
-GCCH_handle_create (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelOpenMessage *msg);
-
-
-/**
- * Handler for channel NACK messages.
- *
- * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter.
- *
- * @param ch Channel.
- */
-void
-GCCH_handle_nack (struct CadetChannel *ch);
-
-
-/**
- * Handler for channel ack messages.
- *
- * @param ch Channel this channel is to be created in.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_ack (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelManageMessage *msg,
- int fwd);
-
-
-/**
- * Handler for channel destroy messages.
- *
- * @param ch Channel this channel is to be destroyed of.
- * @param msg Message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-void
-GCCH_handle_destroy (struct CadetChannel *ch,
- const struct GNUNET_CADET_ChannelManageMessage *msg,
- int fwd);
-
-
-/**
- * Sends an already built message on a channel.
- *
- * If the channel is on a loopback tunnel, notifies the appropriate destination
- * client locally.
- *
- * On a normal channel passes the message to the tunnel for encryption and
- * sending on a connection.
- *
- * This function DOES NOT save the message for retransmission.
- *
- * @param message Message to send. Function makes a copy of it.
- * @param ch Channel on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param existing_copy This is a retransmission, don't save a copy.
- */
-void
-GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- struct CadetChannel *ch, int fwd,
- void *existing_copy);
-
-
-/**
- * Get the static string for identification of the channel.
- *
- * @param ch Channel.i
- *
- * @return Static string with the channel IDs.
- */
-const char *
-GCCH_2s (const struct CadetChannel *ch);
-
-
-
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_SERVICE_CADET_CHANNEL_H */
-#endif
-/* end of gnunet-service-cadet_channel.h */
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2001-2015 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-/**
- * @file cadet/gnunet-service-cadet_connection.c
- * @brief GNUnet CADET service connection handling
- * @author Bartlomiej Polot
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_statistics_service.h"
-#include "cadet_path.h"
-#include "cadet_protocol.h"
-#include "cadet.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_tunnel.h"
-
-
-/**
- * Should we run somewhat expensive checks on our invariants?
- */
-#define CHECK_INVARIANTS 0
-
-
-#define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__)
-#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__)
-
-
-#define CADET_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
- GNUNET_TIME_UNIT_MINUTES,\
- 10)
-#define AVG_MSGS 32
-
-
-/******************************************************************************/
-/******************************** STRUCTS **********************************/
-/******************************************************************************/
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetConnectionQueue
-{
-
- struct CadetConnectionQueue *next;
- struct CadetConnectionQueue *prev;
-
- /**
- * Peer queue handle, to cancel if necessary.
- */
- struct CadetPeerQueue *peer_q;
-
- /**
- * Continuation to call once sent.
- */
- GCC_sent cont;
-
- /**
- * Closure for @e cont.
- */
- void *cont_cls;
-
- /**
- * Was this a forced message? (Do not account for it)
- */
- int forced;
-};
-
-
-/**
- * Struct to encapsulate all the Flow Control information to a peer to which
- * we are directly connected (on a core level).
- */
-struct CadetFlowControl
-{
- /**
- * Connection this controls.
- */
- struct CadetConnection *c;
-
- struct CadetConnectionQueue *q_head;
- struct CadetConnectionQueue *q_tail;
-
- /**
- * How many messages are in the queue on this connection.
- */
- unsigned int queue_n;
-
- /**
- * How many messages do we accept in the queue.
- * If 0, the connection is broken in this direction (next hop disconnected).
- */
- unsigned int queue_max;
-
- /**
- * ID of the next packet to send.
- */
- struct CadetEncryptedMessageIdentifier next_pid;
-
- /**
- * ID of the last packet sent towards the peer.
- */
- struct CadetEncryptedMessageIdentifier last_pid_sent;
-
- /**
- * ID of the last packet received from the peer.
- */
- struct CadetEncryptedMessageIdentifier last_pid_recv;
-
- /**
- * Bitmap of past 32 messages received:
- * - LSB being @c last_pid_recv.
- * - MSB being @c last_pid_recv - 31 (mod UINTMAX).
- */
- uint32_t recv_bitmap;
-
- /**
- * Last ACK sent to the peer (peer is not allowed to send
- * messages with PIDs higher than this value).
- */
- struct CadetEncryptedMessageIdentifier last_ack_sent;
-
- /**
- * Last ACK sent towards the origin (for traffic towards leaf node).
- */
- struct CadetEncryptedMessageIdentifier last_ack_recv;
-
- /**
- * Task to poll the peer in case of a lost ACK causes stall.
- */
- struct GNUNET_SCHEDULER_Task *poll_task;
-
- /**
- * How frequently to poll for ACKs.
- */
- struct GNUNET_TIME_Relative poll_time;
-
- /**
- * Queued poll message, to cancel if not necessary anymore (got ACK).
- */
- struct CadetConnectionQueue *poll_msg;
-
- /**
- * Queued poll message, to cancel if not necessary anymore (got ACK).
- */
- struct CadetConnectionQueue *ack_msg;
-};
-
-/**
- * Keep a record of the last messages sent on this connection.
- */
-struct CadetConnectionPerformance
-{
- /**
- * Circular buffer for storing measurements.
- */
- double usecsperbyte[AVG_MSGS];
-
- /**
- * Running average of @c usecsperbyte.
- */
- double avg;
-
- /**
- * How many values of @c usecsperbyte are valid.
- */
- uint16_t size;
-
- /**
- * Index of the next "free" position in @c usecsperbyte.
- */
- uint16_t idx;
-};
-
-
-/**
- * Struct containing all information regarding a connection to a peer.
- */
-struct CadetConnection
-{
- /**
- * Tunnel this connection is part of.
- */
- struct CadetTunnel *t;
-
- /**
- * Flow control information for traffic fwd.
- */
- struct CadetFlowControl fwd_fc;
-
- /**
- * Flow control information for traffic bck.
- */
- struct CadetFlowControl bck_fc;
-
- /**
- * Measure connection performance on the endpoint.
- */
- struct CadetConnectionPerformance *perf;
-
- /**
- * ID of the connection.
- */
- struct GNUNET_CADET_ConnectionTunnelIdentifier id;
-
- /**
- * Path being used for the tunnel. At the origin of the connection
- * it's a pointer to the destination's path pool, otherwise just a copy.
- */
- struct CadetPeerPath *path;
-
- /**
- * Task to keep the used paths alive at the owner,
- * time tunnel out on all the other peers.
- */
- struct GNUNET_SCHEDULER_Task *fwd_maintenance_task;
-
- /**
- * Task to keep the used paths alive at the destination,
- * time tunnel out on all the other peers.
- */
- struct GNUNET_SCHEDULER_Task *bck_maintenance_task;
-
- /**
- * Queue handle for maintainance traffic. One handle for FWD and BCK since
- * one peer never needs to maintain both directions (no loopback connections).
- */
- struct CadetPeerQueue *maintenance_q;
-
- /**
- * Should equal #get_next_hop(), or NULL if that peer disconnected.
- */
- struct CadetPeer *next_peer;
-
- /**
- * Should equal #get_prev_hop(), or NULL if that peer disconnected.
- */
- struct CadetPeer *prev_peer;
-
- /**
- * State of the connection.
- */
- enum CadetConnectionState state;
-
- /**
- * Position of the local peer in the path.
- */
- unsigned int own_pos;
-
- /**
- * Pending message count.
- */
- unsigned int pending_messages;
-
- /**
- * Destroy flag:
- * - if 0, connection in use.
- * - if 1, destroy on last message.
- * - if 2, connection is being destroyed don't re-enter.
- */
- int destroy;
-
- /**
- * In-connection-map flag. Sometimes, when @e destroy is set but
- * actual destruction is delayed to enable us to finish processing
- * queues (i.e. in the direction that is still working), we remove
- * the connection from the map to prevent it from still being
- * found (and used) by accident. This flag is set to #GNUNET_YES
- * for a connection that is not in the #connections map. Should
- * only be #GNUNET_YES if #destroy is also non-zero.
- */
- int was_removed;
-
- /**
- * Counter to do exponential backoff when creating a connection (max 64).
- */
- unsigned short create_retry;
-
- /**
- * Task to check if connection has duplicates.
- */
- struct GNUNET_SCHEDULER_Task *check_duplicates_task;
-};
-
-
-/******************************************************************************/
-/******************************* GLOBALS ***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Connections known, indexed by cid (CadetConnection).
- */
-static struct GNUNET_CONTAINER_MultiShortmap *connections;
-
-/**
- * How many connections are we willing to maintain.
- * Local connections are always allowed,
- * even if there are more connections than max.
- */
-static unsigned long long max_connections;
-
-/**
- * How many messages *in total* are we willing to queue, divide by number of
- * connections to get connection queue size.
- */
-static unsigned long long max_msgs_queue;
-
-/**
- * How often to send path keepalives. Paths timeout after 4 missed.
- */
-static struct GNUNET_TIME_Relative refresh_connection_time;
-
-/**
- * How often to send path create / ACKs.
- */
-static struct GNUNET_TIME_Relative create_connection_time;
-
-
-/******************************************************************************/
-/******************************** STATIC ***********************************/
-/******************************************************************************/
-
-
-
-#if 0 // avoid compiler warning for unused static function
-static void
-fc_debug (struct CadetFlowControl *fc)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
- ntohl (fc->last_pid_recv.pid),
- ntohl (fc->last_ack_sent.pid));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
- fc->last_pid_sent, fc->last_ack_recv);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
- fc->queue_n, fc->queue_max);
-}
-
-static void
-connection_debug (struct CadetConnection *c)
-{
- if (NULL == c)
- {
- LOG (GNUNET_ERROR_TYPE_INFO, "DEBUG NULL CONNECTION\n");
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
- peer2s (c->t->peer), GCC_2s (c));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
- c->state, c->pending_messages);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
- fc_debug (&c->fwd_fc);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
- fc_debug (&c->bck_fc);
-}
-#endif
-
-
-/**
- * Schedule next keepalive task, taking in consideration
- * the connection state and number of retries.
- *
- * @param c Connection for which to schedule the next keepalive.
- * @param fwd Direction for the next keepalive.
- */
-static void
-schedule_next_keepalive (struct CadetConnection *c, int fwd);
-
-
-/**
- * Resets the connection timeout task, some other message has done the
- * task's job.
- * - For the first peer on the direction this means to send
- * a keepalive or a path confirmation message (either create or ACK).
- * - For all other peers, this means to destroy the connection,
- * due to lack of activity.
- * Starts the timeout if no timeout was running (connection just created).
- *
- * @param c Connection whose timeout to reset.
- * @param fwd Is this forward?
- */
-static void
-connection_reset_timeout (struct CadetConnection *c, int fwd);
-
-
-/**
- * Get string description for tunnel state. Reentrant.
- *
- * @param s Tunnel state.
- *
- * @return String representation.
- */
-static const char *
-GCC_state2s (enum CadetConnectionState s)
-{
- switch (s)
- {
- case CADET_CONNECTION_NEW:
- return "CADET_CONNECTION_NEW";
- case CADET_CONNECTION_SENT:
- return "CADET_CONNECTION_SENT";
- case CADET_CONNECTION_ACK:
- return "CADET_CONNECTION_ACK";
- case CADET_CONNECTION_READY:
- return "CADET_CONNECTION_READY";
- case CADET_CONNECTION_DESTROYED:
- return "CADET_CONNECTION_DESTROYED";
- case CADET_CONNECTION_BROKEN:
- return "CADET_CONNECTION_BROKEN";
- default:
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_ERROR, " conn state %u unknown!\n", s);
- return "CADET_CONNECTION_STATE_ERROR";
- }
-}
-
-
-/**
- * Initialize a Flow Control structure to the initial state.
- *
- * @param fc Flow Control structure to initialize.
- */
-static void
-fc_init (struct CadetFlowControl *fc)
-{
- fc->next_pid.pid = 0;
- fc->last_pid_sent.pid = htonl (UINT32_MAX);
- fc->last_pid_recv.pid = htonl (UINT32_MAX);
- fc->last_ack_sent.pid = (uint32_t) 0;
- fc->last_ack_recv.pid = (uint32_t) 0;
- fc->poll_task = NULL;
- fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
- fc->queue_n = 0;
- fc->queue_max = (max_msgs_queue / max_connections) + 1;
-}
-
-
-/**
- * Find a connection.
- *
- * @param cid Connection ID.
- *
- * @return conntection with the given ID @cid or NULL if not found.
- */
-static struct CadetConnection *
-connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
-{
- return GNUNET_CONTAINER_multishortmap_get (connections,
- &cid->connection_of_tunnel);
-}
-
-
-/**
- * Change the connection state. Cannot change a connection marked as destroyed.
- *
- * @param c Connection to change.
- * @param state New state to set.
- */
-static void
-connection_change_state (struct CadetConnection* c,
- enum CadetConnectionState state)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Connection %s state %s -> %s\n",
- GCC_2s (c), GCC_state2s (c->state), GCC_state2s (state));
- if (CADET_CONNECTION_DESTROYED <= c->state) /* Destroyed or broken. */
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n");
- return;
- }
- c->state = state;
- if (CADET_CONNECTION_READY == state)
- c->create_retry = 1;
-}
-
-
-/**
- * Mark a connection as "destroyed", to send all pending traffic and freeing
- * all associated resources, without accepting new status changes on it.
- *
- * @param c Connection to mark as destroyed.
- */
-static void
-mark_destroyed (struct CadetConnection *c)
-{
- c->destroy = GNUNET_YES;
- connection_change_state (c, CADET_CONNECTION_DESTROYED);
-}
-
-
-/**
- * Function called if a connection has been stalled for a while,
- * possibly due to a missed ACK. Poll the neighbor about its ACK status.
- *
- * @param cls Closure (poll ctx).
- */
-static void
-send_poll (void *cls);
-
-
-/**
- * Send an ACK on the connection, informing the predecessor about
- * the available buffer space. Should not be called in case the peer
- * is origin (no predecessor) in the @c fwd direction.
- *
- * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
- * the ACK itself goes "back" (dest->root).
- *
- * @param c Connection on which to send the ACK.
- * @param buffer How much space free to advertise?
- * @param fwd Is this FWD ACK? (Going dest -> root)
- * @param force Don't optimize out.
- */
-static void
-send_ack (struct CadetConnection *c,
- unsigned int buffer,
- int fwd,
- int force)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct CadetFlowControl *next_fc;
- struct CadetFlowControl *prev_fc;
- struct GNUNET_CADET_ConnectionEncryptedAckMessage msg;
- struct CadetEncryptedMessageIdentifier ack_cemi;
- int delta;
-
- GCC_check_connections ();
- GNUNET_assert (GNUNET_NO == GCC_is_origin (c, fwd));
-
- next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
- prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "send %s ack on %s\n",
- GC_f2s (fwd), GCC_2s (c));
-
- /* Check if we need to transmit the ACK. */
- delta = ntohl (prev_fc->last_ack_sent.pid) - ntohl (prev_fc->last_pid_recv.pid);
- if (3 < delta && buffer < delta && GNUNET_NO == force)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, delta > 3\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " last pid recv: %u, last ack sent: %u\n",
- ntohl (prev_fc->last_pid_recv.pid),
- ntohl (prev_fc->last_ack_sent.pid));
- GCC_check_connections ();
- return;
- }
-
- /* Ok, ACK might be necessary, what PID to ACK? */
- ack_cemi.pid = htonl (ntohl (prev_fc->last_pid_recv.pid) + buffer);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " ACK %u, last PID %u, last ACK %u, qmax %u, q %u\n",
- ntohl (ack_cemi.pid),
- ntohl (prev_fc->last_pid_recv.pid),
- ntohl (prev_fc->last_ack_sent.pid),
- next_fc->queue_max, next_fc->queue_n);
- if ( (ack_cemi.pid == prev_fc->last_ack_sent.pid) &&
- (GNUNET_NO == force) )
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
- GCC_check_connections ();
- return;
- }
-
- /* Check if message is already in queue */
- if (NULL != prev_fc->ack_msg)
- {
- if (GC_is_pid_bigger (ntohl (ack_cemi.pid),
- ntohl (prev_fc->last_ack_sent.pid)))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n");
- GCC_cancel (prev_fc->ack_msg);
- /* GCC_cancel triggers ack_sent(), which clears fc->ack_msg */
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n");
- GCC_check_connections ();
- return;
- }
- }
- GNUNET_break (GC_is_pid_bigger (ntohl (ack_cemi.pid),
- ntohl (prev_fc->last_ack_sent.pid)));
- prev_fc->last_ack_sent = ack_cemi;
-
- /* Build ACK message and send on conn */
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK);
- msg.cemi_max = ack_cemi;
- msg.cid = c->id;
-
- prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header,
- UINT16_MAX,
- zero,
- c,
- !fwd,
- GNUNET_YES,
- NULL, NULL);
- GNUNET_assert (NULL != prev_fc->ack_msg);
- GCC_check_connections ();
-}
-
-
-/**
- * Update performance information if we are a connection's endpoint.
- *
- * @param c Connection to update.
- * @param wait How much time did we wait to send the last message.
- * @param size Size of the last message.
- */
-static void
-update_perf (struct CadetConnection *c,
- struct GNUNET_TIME_Relative wait,
- uint16_t size)
-{
- struct CadetConnectionPerformance *p;
- double usecsperbyte;
-
- if (NULL == c->perf)
- return; /* Only endpoints are interested in timing. */
-
- p = c->perf;
- usecsperbyte = ((double) wait.rel_value_us) / size;
- if (p->size == AVG_MSGS)
- {
- /* Array is full. Substract oldest value, add new one and store. */
- p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
- p->usecsperbyte[p->idx] = usecsperbyte;
- p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
- }
- else
- {
- /* Array not yet full. Add current value to avg and store. */
- p->usecsperbyte[p->idx] = usecsperbyte;
- p->avg *= p->size;
- p->avg += p->usecsperbyte[p->idx];
- p->size++;
- p->avg /= p->size;
- }
- p->idx = (p->idx + 1) % AVG_MSGS;
-}
-
-
-/**
- * Callback called when a connection queued message is sent.
- *
- * Calculates the average time and connection packet tracking.
- *
- * @param cls Closure (ConnectionQueue Handle), can be NULL.
- * @param c Connection this message was on.
- * @param fwd Was this a FWD going message?
- * @param sent Was it really sent? (Could have been canceled)
- * @param type Type of message sent.
- * @param payload_type Type of payload, if applicable.
- * @param pid Message ID, or 0 if not applicable (create, destroy, etc).
- * @param size Size of the message.
- * @param wait Time spent waiting for core (only the time for THIS message)
- */
-static void
-conn_message_sent (void *cls,
- struct CadetConnection *c,
- int fwd,
- int sent,
- uint16_t type,
- uint16_t payload_type,
- struct CadetEncryptedMessageIdentifier pid,
- size_t size,
- struct GNUNET_TIME_Relative wait)
-{
- struct CadetConnectionQueue *q = cls;
- struct CadetFlowControl *fc;
- int forced;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_INFO,
- ">>> %s (%s %4u) on conn %s (%p) %s [%5u] in queue %s\n",
- GC_m2s (type), GC_m2s (payload_type),
- ntohl (pid.pid),
- GCC_2s (c),
- c,
- GC_f2s (fwd), size,
- GNUNET_STRINGS_relative_time_to_string (wait, GNUNET_YES));
-
- /* If c is NULL, nothing to update. */
- if (NULL == c)
- {
- if (type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
- && type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n",
- GC_m2s (type));
- }
- GCC_check_connections ();
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s pid %u\n",
- sent ? "" : "not ", GC_f2s (fwd),
- GC_m2s (type), GC_m2s (payload_type),
- ntohl (pid.pid));
- GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
-
- /* Update flow control info. */
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
-
- if (NULL != q)
- {
- GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q);
- forced = q->forced;
- if (NULL != q->cont)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n");
- q->cont (q->cont_cls, c, q, type, fwd, size);
- }
- GNUNET_free (q);
- }
- else /* CONN_CREATE or CONN_ACK */
- {
- GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED != type);
- forced = GNUNET_YES;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages);
- c->pending_messages--;
- if ( (GNUNET_YES == c->destroy) &&
- (0 == c->pending_messages) )
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "! destroying connection!\n");
- GCC_destroy (c);
- GCC_check_connections ();
- return;
- }
-
- /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
- c->maintenance_q = NULL;
- /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */
- if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd)
- schedule_next_keepalive (c, fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
- if (GNUNET_YES == sent)
- {
- fc->last_pid_sent = pid;
- if (GC_is_pid_bigger (ntohl (fc->last_pid_sent.pid) + 1,
- ntohl (fc->last_ack_recv.pid)) )
- GCC_start_poll (c, fwd);
- GCC_send_ack (c, fwd, GNUNET_NO);
- connection_reset_timeout (c, fwd);
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n);
- if (GNUNET_NO == forced)
- {
- fc->queue_n--;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "! accounting pid %u\n",
- ntohl (fc->last_pid_sent.pid));
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "! forced, Q_N not accounting pid %u\n",
- ntohl (fc->last_pid_sent.pid));
- }
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
- if (GNUNET_YES == sent)
- connection_reset_timeout (c, fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
- fc->poll_msg = NULL;
- if (2 == c->destroy)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL canceled on shutdown\n");
- return;
- }
- if (0 == fc->queue_max)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL cancelled: neighbor disconnected\n");
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL sent for %s, scheduling new one!\n",
- GCC_2s (c));
- GNUNET_assert (NULL == fc->poll_task);
- fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
- fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
- &send_poll, fc);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
- fc->ack_msg = NULL;
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
- break;
-
- default:
- LOG (GNUNET_ERROR_TYPE_ERROR, "%s unknown\n", GC_m2s (type));
- GNUNET_break (0);
- break;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n");
-
- update_perf (c, wait, size);
- GCC_check_connections ();
-}
-
-
-/**
- * Get the previous hop in a connection
- *
- * @param c Connection.
- *
- * @return Previous peer in the connection.
- */
-static struct CadetPeer *
-get_prev_hop (const struct CadetConnection *c)
-{
- GNUNET_PEER_Id id;
-
- if (NULL == c->path)
- return NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " get prev hop %s [%u/%u]\n",
- GCC_2s (c), c->own_pos, c->path->length);
- if (0 == c->own_pos || c->path->length < 2)
- id = c->path->peers[0];
- else
- id = c->path->peers[c->own_pos - 1];
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n",
- GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
-
- return GCP_get_short (id, GNUNET_YES);
-}
-
-
-/**
- * Get the next hop in a connection
- *
- * @param c Connection.
- *
- * @return Next peer in the connection.
- */
-static struct CadetPeer *
-get_next_hop (const struct CadetConnection *c)
-{
- GNUNET_PEER_Id id;
-
- if (NULL == c->path)
- return NULL;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n",
- GCC_2s (c), c->own_pos, c->path->length);
- if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
- id = c->path->peers[c->path->length - 1];
- else
- id = c->path->peers[c->own_pos + 1];
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n",
- GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id);
-
- return GCP_get_short (id, GNUNET_YES);
-}
-
-
-/**
- * Check that the direct neighbours (previous and next hop)
- * are properly associated with this connection.
- *
- * @param c connection to check
- */
-static void
-check_neighbours (const struct CadetConnection *c)
-{
- if (NULL == c->path)
- return; /* nothing to check */
- GCP_check_connection (get_next_hop (c), c);
- GCP_check_connection (get_prev_hop (c), c);
-}
-
-
-/**
- * Helper for #GCC_check_connections(). Calls #check_neighbours().
- *
- * @param cls NULL
- * @param key ignored
- * @param value the `struct CadetConnection` to check
- * @return #GNUNET_OK (continue to iterate)
- */
-static int
-check_connection (void *cls,
- const struct GNUNET_ShortHashCode *key,
- void *value)
-{
- struct CadetConnection *c = value;
-
- check_neighbours (c);
- return GNUNET_OK;
-}
-
-
-/**
- * Check invariants for all connections using #check_neighbours().
- */
-void
-GCC_check_connections ()
-{
- if (0 == CHECK_INVARIANTS)
- return;
- if (NULL == connections)
- return;
- GNUNET_CONTAINER_multishortmap_iterate (connections,
- &check_connection,
- NULL);
-}
-
-
-/**
- * Get the hop in a connection.
- *
- * @param c Connection.
- * @param fwd Next in the FWD direction?
- *
- * @return Next peer in the connection.
- */
-static struct CadetPeer *
-get_hop (struct CadetConnection *c, int fwd)
-{
- return (fwd) ? get_next_hop (c) : get_prev_hop (c);
-}
-
-
-/**
- * Get a bit mask for a message received out-of-order.
- *
- * @param last_pid_recv Last PID we received prior to the out-of-order.
- * @param ooo_pid PID of the out-of-order message.
- */
-static uint32_t
-get_recv_bitmask (struct CadetEncryptedMessageIdentifier last_pid_recv,
- struct CadetEncryptedMessageIdentifier ooo_pid)
-{
- // FIXME: should assert that the delta is in range...
- return 1 << (ntohl (last_pid_recv.pid) - ntohl (ooo_pid.pid));
-}
-
-
-/**
- * Check is an out-of-order message is ok:
- * - at most 31 messages behind.
- * - not duplicate.
- *
- * @param last_pid_recv Last in-order PID received.
- */
-static int
-is_ooo_ok (struct CadetEncryptedMessageIdentifier last_pid_recv,
- struct CadetEncryptedMessageIdentifier ooo_pid,
- uint32_t ooo_bitmap)
-{
- uint32_t mask;
-
- if (GC_is_pid_bigger (ntohl (last_pid_recv.pid) - 31,
- ntohl (ooo_pid.pid)))
- return GNUNET_NO;
-
- mask = get_recv_bitmask (last_pid_recv,
- ooo_pid);
- if (0 != (ooo_bitmap & mask))
- return GNUNET_NO;
-
- return GNUNET_YES;
-}
-
-
-/**
- * Is traffic coming from this sender 'FWD' traffic?
- *
- * @param c Connection to check.
- * @param sender Short peer identity of neighbor.
- *
- * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore
- * the traffic is 'FWD'.
- * #GNUNET_NO for BCK.
- * #GNUNET_SYSERR for errors (sender isn't a hop in the connection).
- */
-static int
-is_fwd (const struct CadetConnection *c,
- const struct CadetPeer *sender)
-{
- GNUNET_PEER_Id id;
-
- id = GCP_get_short_id (sender);
- if (GCP_get_short_id (get_prev_hop (c)) == id)
- return GNUNET_YES;
-
- if (GCP_get_short_id (get_next_hop (c)) == id)
- return GNUNET_NO;
-
- return GNUNET_SYSERR;
-}
-
-
-/**
- * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
- * or a first CONNECTION_ACK directed to us.
- *
- * @param c Connection to confirm.
- * @param fwd Should we send it FWD? (root->dest)
- * (First (~SYNACK) goes BCK, second (~ACK) goes FWD)
- */
-static void
-send_connection_ack (struct CadetConnection *c, int fwd)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct GNUNET_CADET_ConnectionCreateAckMessage msg;
- struct CadetTunnel *t;
- const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionCreateAckMessage);
- const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK;
-
- GCC_check_connections ();
- t = c->t;
- LOG (GNUNET_ERROR_TYPE_INFO,
- "==> %s ({ C %s ACK} 0) on conn %s (%p) %s [%5u]\n",
- GC_m2s (type), GC_f2s (!fwd), GCC_2s (c), c, GC_f2s (fwd), size);
-
- msg.header.size = htons (size);
- msg.header.type = htons (type);
- msg.reserved = htonl (0);
- msg.cid = c->id;
-
- GNUNET_assert (NULL == c->maintenance_q);
- c->maintenance_q = GCP_send (get_hop (c, fwd),
- &msg.header,
- GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
- zero,
- c,
- fwd,
- &conn_message_sent, NULL);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (conn`ACK)\n",
- c, c->pending_messages);
- c->pending_messages++;
-
- if (CADET_TUNNEL_NEW == GCT_get_cstate (t))
- GCT_change_cstate (t, CADET_TUNNEL_WAITING);
- if (CADET_CONNECTION_READY != c->state)
- connection_change_state (c, CADET_CONNECTION_SENT);
- GCC_check_connections ();
-}
-
-
-/**
- * Send a notification that a connection is broken.
- *
- * @param c Connection that is broken.
- * @param id1 Peer that has disconnected.
- * @param id2 Peer that has disconnected.
- * @param fwd Direction towards which to send it.
- */
-static void
-send_broken (struct CadetConnection *c,
- const struct GNUNET_PeerIdentity *id1,
- const struct GNUNET_PeerIdentity *id2,
- int fwd)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct GNUNET_CADET_ConnectionBrokenMessage msg;
-
- GCC_check_connections ();
- msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
- msg.cid = c->id;
- msg.reserved = htonl (0);
- msg.peer1 = *id1;
- msg.peer2 = *id2;
- (void) GCC_send_prebuilt_message (&msg.header,
- UINT16_MAX,
- zero,
- c,
- fwd,
- GNUNET_YES,
- NULL, NULL);
- GCC_check_connections ();
-}
-
-
-/**
- * Send a notification that a connection is broken, when a connection
- * isn't even known to the local peer or soon to be destroyed.
- *
- * @param connection_id Connection ID.
- * @param id1 Peer that has disconnected, probably local peer.
- * @param id2 Peer that has disconnected can be NULL if unknown.
- * @param neighbor Peer to notify (neighbor who sent the connection).
- */
-static void
-send_broken_unknown (const struct GNUNET_CADET_ConnectionTunnelIdentifier *connection_id,
- const struct GNUNET_PeerIdentity *id1,
- const struct GNUNET_PeerIdentity *id2,
- struct CadetPeer *neighbor)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct GNUNET_CADET_ConnectionBrokenMessage msg;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_INFO, "--> BROKEN on unknown connection %s\n",
- GNUNET_sh2s (&connection_id->connection_of_tunnel));
-
- msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN);
- msg.cid = *connection_id;
- msg.reserved = htonl (0);
- msg.peer1 = *id1;
- if (NULL != id2)
- msg.peer2 = *id2;
- else
- memset (&msg.peer2, 0, sizeof (msg.peer2));
- GNUNET_assert (NULL != GCP_send (neighbor,
- &msg.header,
- UINT16_MAX,
- zero,
- NULL,
- GNUNET_SYSERR, /* connection, fwd */
- NULL, NULL)); /* continuation */
- GCC_check_connections ();
-}
-
-
-/**
- * Send keepalive packets for a connection.
- *
- * @param c Connection to keep alive..
- * @param fwd Is this a FWD keepalive? (owner -> dest).
- */
-static void
-send_connection_keepalive (struct CadetConnection *c, int fwd)
-{
- struct GNUNET_MessageHeader msg;
- struct CadetFlowControl *fc;
- int tunnel_ready;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_INFO,
- "keepalive %s for connection %s\n",
- GC_f2s (fwd), GCC_2s (c));
-
- GNUNET_assert (NULL != c->t);
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- tunnel_ready = GNUNET_YES == GCT_has_queued_traffic (c->t)
- && CADET_TUNNEL_KEY_OK <= GCT_get_estate (c->t);
- if (0 < fc->queue_n || tunnel_ready)
- {
- LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n");
- return;
- }
-
- GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO);
-
- GNUNET_assert (NULL != c->t);
- msg.size = htons (sizeof (msg));
- msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
-
- GNUNET_assert (NULL ==
- GCT_send_prebuilt_message (&msg, c->t, c,
- GNUNET_NO, NULL, NULL));
- GCC_check_connections ();
-}
-
-
-/**
- * Send CONNECTION_{CREATE/ACK} packets for a connection.
- *
- * @param c Connection for which to send the message.
- * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK.
- */
-static void
-connection_recreate (struct CadetConnection *c, int fwd)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "sending connection recreate\n");
- if (fwd)
- GCC_send_create (c);
- else
- send_connection_ack (c, GNUNET_NO);
-}
-
-
-/**
- * Generic connection timer management.
- * Depending on the role of the peer in the connection will send the
- * appropriate message (build or keepalive)
- *
- * @param c Conncetion to maintain.
- * @param fwd Is FWD?
- */
-static void
-connection_maintain (struct CadetConnection *c, int fwd)
-{
- if (GNUNET_NO != c->destroy)
- {
- LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, being destroyed\n");
- return;
- }
-
- if (NULL == c->t)
- {
- GNUNET_break (0);
- GCC_debug (c, GNUNET_ERROR_TYPE_ERROR);
- return;
- }
-
- if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (c->t))
- {
- /* If status is SEARCHING, why is there a connection? Should be WAITING */
- GNUNET_break (0);
- GCT_debug (c->t, GNUNET_ERROR_TYPE_ERROR);
- LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, tunnel SEARCHING\n");
- schedule_next_keepalive (c, fwd);
- return;
- }
- switch (c->state)
- {
- case CADET_CONNECTION_NEW:
- GNUNET_break (0);
- /* fall-through */
- case CADET_CONNECTION_SENT:
- connection_recreate (c, fwd);
- break;
- case CADET_CONNECTION_READY:
- send_connection_keepalive (c, fwd);
- break;
- default:
- break;
- }
-}
-
-
-/**
- * Keep the connection alive.
- *
- * @param c Connection to keep alive.
- * @param fwd Direction.
- */
-static void
-connection_keepalive (struct CadetConnection *c,
- int fwd)
-{
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "%s keepalive for %s\n",
- GC_f2s (fwd), GCC_2s (c));
-
- if (fwd)
- c->fwd_maintenance_task = NULL;
- else
- c->bck_maintenance_task = NULL;
- connection_maintain (c, fwd);
- GCC_check_connections ();
- /* Next execution will be scheduled by message_sent or _maintain*/
-}
-
-
-/**
- * Keep the connection alive in the FWD direction.
- *
- * @param cls Closure (connection to keepalive).
- */
-static void
-connection_fwd_keepalive (void *cls)
-{
- struct CadetConnection *c = cls;
-
- GCC_check_connections ();
- connection_keepalive (c,
- GNUNET_YES);
- GCC_check_connections ();
-}
-
-
-/**
- * Keep the connection alive in the BCK direction.
- *
- * @param cls Closure (connection to keepalive).
- */
-static void
-connection_bck_keepalive (void *cls)
-{
- struct CadetConnection *c = cls;
-
- GCC_check_connections ();
- connection_keepalive (c,
- GNUNET_NO);
- GCC_check_connections ();
-}
-
-
-/**
- * Schedule next keepalive task, taking in consideration
- * the connection state and number of retries.
- *
- * If the peer is not the origin, do nothing.
- *
- * @param c Connection for which to schedule the next keepalive.
- * @param fwd Direction for the next keepalive.
- */
-static void
-schedule_next_keepalive (struct CadetConnection *c, int fwd)
-{
- struct GNUNET_TIME_Relative delay;
- struct GNUNET_SCHEDULER_Task * *task_id;
- GNUNET_SCHEDULER_TaskCallback keepalive_task;
-
- GCC_check_connections ();
- if (GNUNET_NO == GCC_is_origin (c, fwd))
- return;
-
- /* Calculate delay to use, depending on the state of the connection */
- if (CADET_CONNECTION_READY == c->state)
- {
- delay = refresh_connection_time;
- }
- else
- {
- if (1 > c->create_retry)
- c->create_retry = 1;
- delay = GNUNET_TIME_relative_saturating_multiply (create_connection_time,
- c->create_retry);
- if (c->create_retry < 64) // TODO make configurable
- c->create_retry *= 2;
- }
-
- /* Select direction-dependent parameters */
- if (GNUNET_YES == fwd)
- {
- task_id = &c->fwd_maintenance_task;
- keepalive_task = &connection_fwd_keepalive;
- }
- else
- {
- task_id = &c->bck_maintenance_task;
- keepalive_task = &connection_bck_keepalive;
- }
-
- /* Check that no one scheduled it before us */
- if (NULL != *task_id)
- {
- /* No need for a _break. It can happen for instance when sending a SYNACK
- * for a duplicate SYN: the first SYNACK scheduled the task. */
- GNUNET_SCHEDULER_cancel (*task_id);
- }
-
- /* Schedule the task */
- *task_id = GNUNET_SCHEDULER_add_delayed (delay,
- keepalive_task,
- c);
- LOG (GNUNET_ERROR_TYPE_INFO,
- "next keepalive for %s in in %s\n",
- GCC_2s (c), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
- GCC_check_connections ();
-}
-
-
-/**
- * Cancel all transmissions that belong to a certain connection.
- *
- * If the connection is scheduled for destruction and no more messages are left,
- * the connection will be destroyed by the continuation call.
- *
- * @param c Connection which to cancel. Might be destroyed during this call.
- * @param fwd Cancel fwd traffic?
- */
-static void
-connection_cancel_queues (struct CadetConnection *c,
- int fwd)
-{
- struct CadetFlowControl *fc;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Cancel %s queues for connection %s\n",
- GC_f2s (fwd), GCC_2s (c));
- if (NULL == c)
- {
- GNUNET_break (0);
- return;
- }
-
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- if (NULL != fc->poll_task)
- {
- GNUNET_SCHEDULER_cancel (fc->poll_task);
- fc->poll_task = NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL task for fc %p\n", fc);
- }
- if (NULL != fc->poll_msg)
- {
- GCC_cancel (fc->poll_msg);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL msg for fc %p\n", fc);
- }
-
- while (NULL != fc->q_head)
- {
- GCC_cancel (fc->q_head);
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Function called if a connection has been stalled for a while,
- * possibly due to a missed ACK. Poll the neighbor about its ACK status.
- *
- * @param cls Closure (poll ctx).
- */
-static void
-send_poll (void *cls)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct CadetFlowControl *fc = cls;
- struct GNUNET_CADET_ConnectionHopByHopPollMessage msg;
- struct CadetConnection *c;
- int fwd;
-
- fc->poll_task = NULL;
- GCC_check_connections ();
- c = fc->c;
- fwd = fc == &c->fwd_fc;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Polling connection %s %s\n",
- GCC_2s (c), GC_f2s (fwd));
-
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL);
- msg.header.size = htons (sizeof (msg));
- msg.cid = c->id;
- msg.cemi = fc->last_pid_sent;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", ntohl (fc->last_pid_sent.pid));
- fc->poll_msg
- = GCC_send_prebuilt_message (&msg.header,
- UINT16_MAX,
- zero,
- c,
- fc == &c->fwd_fc,
- GNUNET_YES,
- NULL,
- NULL);
- GNUNET_assert (NULL != fc->poll_msg);
- GCC_check_connections ();
-}
-
-
-/**
- * Generic connection timeout implementation.
- *
- * Timeout function due to lack of keepalive/traffic from an endpoint.
- * Destroys connection if called.
- *
- * @param c Connection to destroy.
- * @param fwd Was the timeout from the origin? (FWD timeout)
- */
-static void
-connection_timeout (struct CadetConnection *c, int fwd)
-{
- GCC_check_connections ();
-
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Connection %s %s timed out. Destroying.\n",
- GCC_2s (c),
- GC_f2s (fwd));
- GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
-
- if (GCC_is_origin (c, fwd)) /* Loopback? Something is wrong! */
- {
- GNUNET_break (0);
- return;
- }
-
- /* If dest, send "broken" notification. */
- if (GCC_is_terminal (c, fwd))
- {
- struct CadetPeer *next_hop;
-
- next_hop = fwd ? get_prev_hop (c) : get_next_hop (c);
- send_broken_unknown (&c->id, &my_full_id, NULL, next_hop);
- }
-
- GCC_destroy (c);
- GCC_check_connections ();
-}
-
-
-/**
- * Timeout function due to lack of keepalive/traffic from the owner.
- * Destroys connection if called.
- *
- * @param cls Closure (connection to destroy).
- */
-static void
-connection_fwd_timeout (void *cls)
-{
- struct CadetConnection *c = cls;
-
- c->fwd_maintenance_task = NULL;
- GCC_check_connections ();
- connection_timeout (c, GNUNET_YES);
- GCC_check_connections ();
-}
-
-
-/**
- * Timeout function due to lack of keepalive/traffic from the destination.
- * Destroys connection if called.
- *
- * @param cls Closure (connection to destroy).
- */
-static void
-connection_bck_timeout (void *cls)
-{
- struct CadetConnection *c = cls;
-
- c->bck_maintenance_task = NULL;
- GCC_check_connections ();
- connection_timeout (c, GNUNET_NO);
- GCC_check_connections ();
-}
-
-
-/**
- * Resets the connection timeout task, some other message has done the
- * task's job.
- * - For the first peer on the direction this means to send
- * a keepalive or a path confirmation message (either create or ACK).
- * - For all other peers, this means to destroy the connection,
- * due to lack of activity.
- * Starts the timeout if no timeout was running (connection just created).
- *
- * @param c Connection whose timeout to reset.
- * @param fwd Is this forward?
- *
- * TODO use heap to improve efficiency of scheduler.
- */
-static void
-connection_reset_timeout (struct CadetConnection *c, int fwd)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GC_f2s (fwd));
- if (GCC_is_origin (c, fwd)) /* Startpoint */
- {
- schedule_next_keepalive (c, fwd);
- if (NULL != c->maintenance_q)
- {
- GCP_send_cancel (c->maintenance_q);
- c->maintenance_q = NULL; /* Is set to NULL by conn_message_sent anyway */
- }
- }
- else /* Relay, endpoint. */
- {
- struct GNUNET_TIME_Relative delay;
- struct GNUNET_SCHEDULER_Task * *ti;
- GNUNET_SCHEDULER_TaskCallback f;
-
- ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
-
- if (NULL != *ti)
- GNUNET_SCHEDULER_cancel (*ti);
- delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 4);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " timing out in %s\n",
- GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_NO));
- f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
- *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
- }
-}
-
-
-/**
- * Iterator to compare each connection's path with the path of a new connection.
- *
- * If the connection coincides, the c member of path is set to the connection
- * and the destroy flag of the connection is set.
- *
- * @param cls Closure (new path).
- * @param c Connection in the tunnel to check.
- */
-static void
-check_path (void *cls, struct CadetConnection *c)
-{
- struct CadetConnection *new_conn = cls;
- struct CadetPeerPath *path = new_conn->path;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " checking %s (%p), length %u\n",
- GCC_2s (c), c, c->path->length);
-
- if (c != new_conn
- && GNUNET_NO == c->destroy
- && CADET_CONNECTION_BROKEN != c->state
- && CADET_CONNECTION_DESTROYED != c->state
- && path_equivalent (path, c->path))
- {
- new_conn->destroy = GNUNET_YES; /* Do not mark_destroyed, */
- new_conn->path->c = c; /* this is only a flag for the Iterator. */
- LOG (GNUNET_ERROR_TYPE_DEBUG, " MATCH!\n");
- }
-}
-
-
-/**
- * Finds out if this path is already being used by an existing connection.
- *
- * Checks the tunnel towards the destination to see if it contains
- * any connection with the same path.
- *
- * If the existing connection is ready, it is kept.
- * Otherwise if the sender has a smaller ID that ours, we accept it (and
- * the peer will eventually reject our attempt).
- *
- * @param path Path to check.
- * @return #GNUNET_YES if the tunnel has a connection with the same path,
- * #GNUNET_NO otherwise.
- */
-static int
-does_connection_exist (struct CadetConnection *conn)
-{
- struct CadetPeer *p;
- struct CadetTunnel *t;
- struct CadetConnection *c;
-
- p = GCP_get_short (conn->path->peers[0], GNUNET_NO);
- if (NULL == p)
- return GNUNET_NO;
- t = GCP_get_tunnel (p);
- if (NULL == t)
- return GNUNET_NO;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking for duplicates\n");
-
- GCT_iterate_connections (t, &check_path, conn);
-
- if (GNUNET_YES == conn->destroy)
- {
- c = conn->path->c;
- conn->destroy = GNUNET_NO;
- conn->path->c = conn;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " found duplicate of %s\n", GCC_2s (conn));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate: %s\n", GCC_2s (c));
- GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
- if (CADET_CONNECTION_READY == c->state)
- {
- /* The other peer confirmed a live connection with this path,
- * why are they trying to duplicate it? */
- GNUNET_STATISTICS_update (stats, "# duplicate connections", 1, GNUNET_NO);
- return GNUNET_YES;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate not ready, connection unique\n");
- return GNUNET_NO;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " %s has no duplicates\n", GCC_2s (conn));
- return GNUNET_NO;
- }
-}
-
-
-/**
- * @brief Check if the tunnel this connection belongs to has any other
- * connection with the same path, and destroy one if so.
- *
- * @param cls Closure (connection to check).
- */
-static void
-check_duplicates (void *cls)
-{
- struct CadetConnection *c = cls;
-
- c->check_duplicates_task = NULL;
- if (GNUNET_YES == does_connection_exist (c))
- {
- GCT_debug (c->t, GNUNET_ERROR_TYPE_DEBUG);
- send_broken (c, &my_full_id, &my_full_id, GCC_is_origin (c, GNUNET_YES));
- GCC_destroy (c);
- }
-}
-
-
-/**
- * Wait for enough time to let any dead connections time out and check for
- * any remaining duplicates.
- *
- * @param c Connection that is a potential duplicate.
- */
-static void
-schedule_check_duplicates (struct CadetConnection *c)
-{
- struct GNUNET_TIME_Relative delay;
-
- if (NULL != c->check_duplicates_task)
- return;
- delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 5);
- c->check_duplicates_task = GNUNET_SCHEDULER_add_delayed (delay,
- &check_duplicates,
- c);
-}
-
-
-/**
- * Add the connection to the list of both neighbors.
- *
- * @param c Connection.
- *
- * @return #GNUNET_OK if everything went fine
- * #GNUNET_SYSERR if the was an error and @c c is malformed.
- */
-static int
-register_neighbors (struct CadetConnection *c)
-{
- c->next_peer = get_next_hop (c);
- c->prev_peer = get_prev_hop (c);
- GNUNET_assert (c->next_peer != c->prev_peer);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "register neighbors for connection %s\n",
- GCC_2s (c));
- path_debug (c->path);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "own pos %u\n", c->own_pos);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "putting connection %s to next peer %p\n",
- GCC_2s (c),
- c->next_peer);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n",
- c->next_peer,
- GCP_2s (c->next_peer));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "putting connection %s to prev peer %p\n",
- GCC_2s (c),
- c->prev_peer);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "prev peer %p %s\n",
- c->prev_peer,
- GCP_2s (c->prev_peer));
-
- if ( (GNUNET_NO == GCP_is_neighbor (c->next_peer)) ||
- (GNUNET_NO == GCP_is_neighbor (c->prev_peer)) )
- {
- if (GCC_is_origin (c, GNUNET_YES))
- GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO);
- GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " register neighbors failed\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " prev: %s, neighbor?: %d\n",
- GCP_2s (c->prev_peer),
- GCP_is_neighbor (c->prev_peer));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " next: %s, neighbor?: %d\n",
- GCP_2s (c->next_peer),
- GCP_is_neighbor (c->next_peer));
- return GNUNET_SYSERR;
- }
- GCP_add_connection (c->next_peer, c, GNUNET_NO);
- GCP_add_connection (c->prev_peer, c, GNUNET_YES);
-
- return GNUNET_OK;
-}
-
-
-/**
- * Remove the connection from the list of both neighbors.
- *
- * @param c Connection.
- */
-static void
-unregister_neighbors (struct CadetConnection *c)
-{
-// struct CadetPeer *peer; FIXME dont use next_peer, prev_peer
- /* Either already unregistered or never got registered, it's ok either way. */
- if (NULL == c->path)
- return;
- if (NULL != c->next_peer)
- {
- GCP_remove_connection (c->next_peer, c);
- c->next_peer = NULL;
- }
- if (NULL != c->prev_peer)
- {
- GCP_remove_connection (c->prev_peer, c);
- c->prev_peer = NULL;
- }
-}
-
-
-/**
- * Invalidates all paths towards all peers that comprise the connection which
- * rely on the disconnected peer.
- *
- * ~O(n^3) (peers in connection * paths/peer * links/path)
- *
- * @param c Connection whose peers' paths to clean.
- * @param disconnected Peer that disconnected.
- */
-static void
-invalidate_paths (struct CadetConnection *c,
- struct CadetPeer *disconnected)
-{
- struct CadetPeer *peer;
- unsigned int i;
-
- for (i = 0; i < c->path->length; i++)
- {
- peer = GCP_get_short (c->path->peers[i], GNUNET_NO);
- if (NULL != peer)
- GCP_notify_broken_link (peer, &my_full_id, GCP_get_id (disconnected));
- }
-}
-
-
-/**
- * Bind the connection to the peer and the tunnel to that peer.
- *
- * If the peer has no tunnel, create one. Update tunnel and connection
- * data structres to reflect new status.
- *
- * @param c Connection.
- * @param peer Peer.
- */
-static void
-add_to_peer (struct CadetConnection *c,
- struct CadetPeer *peer)
-{
- GCP_add_tunnel (peer);
- c->t = GCP_get_tunnel (peer);
- GCT_add_connection (c->t, c);
-}
-
-
-/**
- * Log receipt of message on stderr (INFO level).
- *
- * @param message Message received.
- * @param peer Peer who sent the message.
- * @param conn_id Connection ID of the message.
- */
-static void
-log_message (const struct GNUNET_MessageHeader *message,
- const struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionTunnelIdentifier *conn_id)
-{
- uint16_t size;
- uint16_t type;
- char *arrow;
-
- size = ntohs (message->size);
- type = ntohs (message->type);
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
- arrow = "==";
- break;
- default:
- arrow = "--";
- }
- LOG (GNUNET_ERROR_TYPE_INFO,
- "<%s %s on conn %s from %s, %6u bytes\n",
- arrow,
- GC_m2s (type),
- GNUNET_sh2s (&conn_id->connection_of_tunnel),
- GCP_2s(peer),
- (unsigned int) size);
-}
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Handler for connection creation.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_create (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionCreateMessage *msg)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid;
- struct GNUNET_PeerIdentity *id;
- struct CadetPeerPath *path;
- struct CadetPeer *dest_peer;
- struct CadetPeer *orig_peer;
- struct CadetConnection *c;
- unsigned int own_pos;
- uint16_t size;
-
- GCC_check_connections ();
- size = ntohs (msg->header.size);
-
- /* Calculate hops */
- size -= sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
- if (0 != size % sizeof (struct GNUNET_PeerIdentity))
- {
- GNUNET_break_op (0);
- return;
- }
- size /= sizeof (struct GNUNET_PeerIdentity);
- if (1 > size)
- {
- GNUNET_break_op (0);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
-
- /* Get parameters */
- cid = &msg->cid;
- log_message (&msg->header, peer, cid);
- id = (struct GNUNET_PeerIdentity *) &msg[1];
- LOG (GNUNET_ERROR_TYPE_DEBUG, " origin: %s\n", GNUNET_i2s (id));
-
- /* Create connection */
- c = connection_get (cid);
- if (NULL == c)
- {
- path = path_build_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1],
- size, myid, &own_pos);
- if (NULL == path)
- {
- /* Path was malformed, probably our own ID was not in it. */
- GNUNET_STATISTICS_update (stats, "# malformed paths", 1, GNUNET_NO);
- GNUNET_break_op (0);
- return;
- }
- if (0 == own_pos)
- {
- /* We received this request from a neighbor, we cannot be origin */
- GNUNET_STATISTICS_update (stats, "# fake paths", 1, GNUNET_NO);
- GNUNET_break_op (0);
- path_destroy (path);
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
- c = GCC_new (cid, NULL, path, own_pos);
- if (NULL == c)
- {
- if (path->length - 1 == own_pos)
- {
- /* If we are destination, why did the creation fail? */
- GNUNET_break (0);
- path_destroy (path);
- GCC_check_connections ();
- return;
- }
- send_broken_unknown (cid, &my_full_id,
- GNUNET_PEER_resolve2 (path->peers[own_pos + 1]),
- peer);
- path_destroy (path);
- GCC_check_connections ();
- return;
- }
- GCP_add_path_to_all (path, GNUNET_NO);
- connection_reset_timeout (c, GNUNET_YES);
- }
- else
- {
- path = path_duplicate (c->path);
- }
- if (CADET_CONNECTION_NEW == c->state)
- connection_change_state (c, CADET_CONNECTION_SENT);
-
- /* Remember peers */
- dest_peer = GCP_get (&id[size - 1], GNUNET_YES);
- orig_peer = GCP_get (&id[0], GNUNET_YES);
-
- /* Is it a connection to us? */
- if (c->own_pos == path->length - 1)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
- GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES);
-
- add_to_peer (c, orig_peer);
- if (GNUNET_YES == does_connection_exist (c))
- {
- /* Peer created a connection equal to one we think exists
- * and is fine.
- * Solution: Keep both and postpone disambiguation. In the meantime
- * the connection will time out or peer will inform us it is broken.
- *
- * Other options:
- * - Use explicit duplicate.
- * - Accept new conn and destroy the old. (interruption in higher level)
- * - Keep the one with higher ID / created by peer with higher ID. */
- schedule_check_duplicates (c);
- }
-
- if (CADET_TUNNEL_NEW == GCT_get_cstate (c->t))
- GCT_change_cstate (c->t, CADET_TUNNEL_WAITING);
- if (NULL == c->maintenance_q)
- send_connection_ack (c, GNUNET_NO);
- if (CADET_CONNECTION_SENT == c->state)
- connection_change_state (c, CADET_CONNECTION_ACK);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
- GCP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
- GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
- (void) GCC_send_prebuilt_message (&msg->header,
- 0,
- zero,
- c,
- GNUNET_YES, GNUNET_YES,
- NULL, NULL);
- }
- path_destroy (path);
- GCC_check_connections ();
-}
-
-
-/**
- * Handler for connection confirmations.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_confirm (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct CadetConnection *c;
- enum CadetConnectionState oldstate;
- int fwd;
-
- GCC_check_connections ();
- log_message (&msg->header, peer, &msg->cid);
- c = connection_get (&msg->cid);
- if (NULL == c)
- {
- GNUNET_STATISTICS_update (stats, "# control on unknown connection",
- 1, GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " don't know the connection!\n");
- send_broken_unknown (&msg->cid, &my_full_id, NULL, peer);
- GCC_check_connections ();
- return;
- }
- if (GNUNET_NO != c->destroy)
- {
- GNUNET_assert (CADET_CONNECTION_DESTROYED == c->state);
- GNUNET_STATISTICS_update (stats, "# control on dying connection",
- 1, GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "connection %s being destroyed, ignoring confirm\n",
- GCC_2s (c));
- GCC_check_connections ();
- return;
- }
-
- oldstate = c->state;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GCP_2s (peer));
- if (get_next_hop (c) == peer)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
- fwd = GNUNET_NO;
- if (CADET_CONNECTION_SENT == oldstate)
- connection_change_state (c, CADET_CONNECTION_ACK);
- }
- else if (get_prev_hop (c) == peer)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " FINAL ACK\n");
- fwd = GNUNET_YES;
- connection_change_state (c, CADET_CONNECTION_READY);
- }
- else
- {
- GNUNET_STATISTICS_update (stats, "# control on connection from wrong peer",
- 1, GNUNET_NO);
- GNUNET_break_op (0);
- return;
- }
-
- connection_reset_timeout (c, fwd);
-
- GNUNET_assert (NULL != c->path);
- GCP_add_path_to_all (c->path, GNUNET_YES);
-
- /* Message for us as creator? */
- if (GNUNET_YES == GCC_is_origin (c, GNUNET_YES))
- {
- if (GNUNET_NO != fwd)
- {
- GNUNET_break (0);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
-
- /* If just created, cancel the short timeout and start a long one */
- if (CADET_CONNECTION_SENT == oldstate)
- {
- c->create_retry = 1;
- connection_reset_timeout (c, GNUNET_YES);
- }
-
- /* Change connection state, send ACK */
- connection_change_state (c, CADET_CONNECTION_READY);
- send_connection_ack (c, GNUNET_YES);
-
- /* Change tunnel state, trigger KX */
- if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t))
- GCT_change_cstate (c->t, CADET_TUNNEL_READY);
- GCC_check_connections ();
- return;
- }
-
- /* Message for us as destination? */
- if (GCC_is_terminal (c, GNUNET_YES))
- {
- if (GNUNET_YES != fwd)
- {
- GNUNET_break (0);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
-
- /* If just created, cancel the short timeout and start a long one */
- if (CADET_CONNECTION_ACK == oldstate)
- connection_reset_timeout (c, GNUNET_NO);
-
- /* Change tunnel state */
- if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t))
- GCT_change_cstate (c->t, CADET_TUNNEL_READY);
- GCC_check_connections ();
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
- (void) GCC_send_prebuilt_message (&msg->header, 0,
- zero,
- c,
- fwd,
- GNUNET_YES, NULL, NULL);
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Handler for notifications of broken connections.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_broken (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct CadetConnection *c;
- struct CadetTunnel *t;
- int fwd;
-
- GCC_check_connections ();
- log_message (&msg->header, peer, &msg->cid);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer1));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer2));
- c = connection_get (&msg->cid);
- if (NULL == c)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate CONNECTION_BROKEN\n");
- GNUNET_STATISTICS_update (stats, "# duplicate CONNECTION_BROKEN",
- 1, GNUNET_NO);
- GCC_check_connections ();
- return;
- }
-
- t = c->t;
-
- fwd = is_fwd (c, peer);
- if (GNUNET_SYSERR == fwd)
- {
- GNUNET_break_op (0);
- GCC_check_connections ();
- return;
- }
- mark_destroyed (c);
- if (GCC_is_terminal (c, fwd))
- {
- struct CadetPeer *endpoint;
-
- if (NULL == t)
- {
- /* A terminal connection should not have 't' set to NULL. */
- GNUNET_break (0);
- GCC_debug (c, GNUNET_ERROR_TYPE_ERROR);
- return;
- }
- endpoint = GCP_get_short (c->path->peers[c->path->length - 1], GNUNET_YES);
- if (2 < c->path->length)
- path_invalidate (c->path);
- GCP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2);
-
- connection_change_state (c, CADET_CONNECTION_BROKEN);
- GCT_remove_connection (t, c);
- c->t = NULL;
-
- GCC_destroy (c);
- }
- else
- {
- (void) GCC_send_prebuilt_message (&msg->header, 0,
- zero, c, fwd,
- GNUNET_YES, NULL, NULL);
- connection_cancel_queues (c, !fwd);
- }
- GCC_check_connections ();
- return;
-}
-
-
-/**
- * Handler for notifications of destroyed connections.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_destroy (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct CadetConnection *c;
- int fwd;
-
- GCC_check_connections ();
- log_message (&msg->header, peer, &msg->cid);
- c = connection_get (&msg->cid);
- if (NULL == c)
- {
- /* Probably already got the message from another path,
- * destroyed the tunnel and retransmitted to children.
- * Safe to ignore.
- */
- GNUNET_STATISTICS_update (stats,
- "# control on unknown connection",
- 1, GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " connection unknown destroyed: previously destroyed?\n");
- GCC_check_connections ();
- return;
- }
-
- fwd = is_fwd (c, peer);
- if (GNUNET_SYSERR == fwd)
- {
- GNUNET_break_op (0);
- GCC_check_connections ();
- return;
- }
-
- if (GNUNET_NO == GCC_is_terminal (c, fwd))
- {
- (void) GCC_send_prebuilt_message (&msg->header, 0,
- zero, c, fwd,
- GNUNET_YES, NULL, NULL);
- }
- else if (0 == c->pending_messages)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n");
- GCC_destroy (c);
- GCC_check_connections ();
- return;
- }
- mark_destroyed (c);
- if (NULL != c->t)
- {
- GCT_remove_connection (c->t, c);
- c->t = NULL;
- }
- GCC_check_connections ();
- return;
-}
-
-
-/**
- * Handler for cadet network traffic hop-by-hop acks.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_ack (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
-{
- struct CadetConnection *c;
- struct CadetFlowControl *fc;
- struct CadetEncryptedMessageIdentifier ack;
- int fwd;
-
- GCC_check_connections ();
- log_message (&msg->header, peer, &msg->cid);
- c = connection_get (&msg->cid);
- if (NULL == c)
- {
- GNUNET_STATISTICS_update (stats,
- "# ack on unknown connection",
- 1,
- GNUNET_NO);
- send_broken_unknown (&msg->cid,
- &my_full_id,
- NULL,
- peer);
- GCC_check_connections ();
- return;
- }
-
- /* Is this a forward or backward ACK? */
- if (get_next_hop (c) == peer)
- {
- fc = &c->fwd_fc;
- fwd = GNUNET_YES;
- }
- else if (get_prev_hop (c) == peer)
- {
- fc = &c->bck_fc;
- fwd = GNUNET_NO;
- }
- else
- {
- GNUNET_break_op (0);
- return;
- }
-
- ack = msg->cemi_max;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n",
- GC_f2s (fwd),
- ntohl (ack.pid),
- ntohl (fc->last_ack_recv.pid));
- if (GC_is_pid_bigger (ntohl (ack.pid),
- ntohl (fc->last_ack_recv.pid)))
- fc->last_ack_recv = ack;
-
- /* Cancel polling if the ACK is big enough. */
- if ( (NULL != fc->poll_task) &
- GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
- ntohl (fc->last_pid_sent.pid)))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
- GNUNET_SCHEDULER_cancel (fc->poll_task);
- fc->poll_task = NULL;
- fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
- }
-
- GCC_check_connections ();
-}
-
-
-/**
- * Handler for cadet network traffic hop-by-hop data counter polls.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_poll (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
-{
- struct CadetConnection *c;
- struct CadetFlowControl *fc;
- struct CadetEncryptedMessageIdentifier pid;
- int fwd;
-
- GCC_check_connections ();
- log_message (&msg->header, peer, &msg->cid);
- c = connection_get (&msg->cid);
- if (NULL == c)
- {
- GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
- GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "POLL message on unknown connection %s!\n",
- GNUNET_sh2s (&msg->cid.connection_of_tunnel));
- send_broken_unknown (&msg->cid,
- &my_full_id,
- NULL,
- peer);
- GCC_check_connections ();
- return;
- }
-
- /* Is this a forward or backward ACK?
- * Note: a poll should never be needed in a loopback case,
- * since there is no possiblility of packet loss there, so
- * this way of discerining FWD/BCK should not be a problem.
- */
- if (get_next_hop (c) == peer)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
- fc = &c->fwd_fc;
- }
- else if (get_prev_hop (c) == peer)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
- fc = &c->bck_fc;
- }
- else
- {
- GNUNET_break_op (0);
- return;
- }
-
- pid = msg->cemi;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " PID %u, OLD %u\n",
- ntohl (pid.pid),
- ntohl (fc->last_pid_recv.pid));
- fc->last_pid_recv = pid;
- fwd = fc == &c->bck_fc;
- GCC_send_ack (c, fwd, GNUNET_YES);
- GCC_check_connections ();
-}
-
-
-/**
- * Check the message against internal state and test if it goes FWD or BCK.
- *
- * Updates the PID, state and timeout values for the connection.
- *
- * @param message Message to check. It must belong to an existing connection.
- * @param cid Connection ID (even if @a c is NULL, the ID is still needed).
- * @param c Connection this message should belong. If NULL, check fails.
- * @param sender Neighbor that sent the message.
- *
- * @return #GNUNET_YES if the message goes FWD.
- * #GNUNET_NO if it goes BCK.
- * #GNUNET_SYSERR if there is an error (unauthorized sender, ...).
- */
-static int
-check_message (const struct GNUNET_MessageHeader *message,
- const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid,
- struct CadetConnection *c,
- struct CadetPeer *sender,
- struct CadetEncryptedMessageIdentifier pid)
-{
- struct CadetFlowControl *fc;
- struct CadetPeer *hop;
- int fwd;
- uint16_t type;
-
- /* Check connection */
- if (NULL == c)
- {
- GNUNET_STATISTICS_update (stats,
- "# unknown connection",
- 1, GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "%s on unknown connection %s\n",
- GC_m2s (ntohs (message->type)),
- GNUNET_sh2s (&cid->connection_of_tunnel));
- GNUNET_break_op (0);
- send_broken_unknown (cid,
- &my_full_id,
- NULL,
- sender);
- return GNUNET_SYSERR;
- }
-
- /* Check if origin is as expected */
- hop = get_prev_hop (c);
- if (sender == hop)
- {
- fwd = GNUNET_YES;
- }
- else
- {
- hop = get_next_hop (c);
- GNUNET_break (hop == c->next_peer);
- if (sender == hop)
- {
- fwd = GNUNET_NO;
- }
- else
- {
- /* Unexpected peer sending traffic on a connection. */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
-
- /* Check PID for payload messages */
- type = ntohs (message->type);
- if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
- {
- fc = fwd ? &c->bck_fc : &c->fwd_fc;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected in interval [%u,%u])\n",
- ntohl (pid.pid),
- ntohl (fc->last_pid_recv.pid) + 1,
- ntohl (fc->last_ack_sent.pid));
- if (GC_is_pid_bigger (ntohl (pid.pid),
- ntohl (fc->last_ack_sent.pid)))
- {
- GNUNET_STATISTICS_update (stats,
- "# unsolicited message",
- 1,
- GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "Received PID %u, (prev %u), ACK %u\n",
- pid, fc->last_pid_recv, fc->last_ack_sent);
- return GNUNET_SYSERR;
- }
- if (GC_is_pid_bigger (ntohl (pid.pid),
- ntohl (fc->last_pid_recv.pid)))
- {
- unsigned int delta;
-
- delta = ntohl (pid.pid) - ntohl (fc->last_pid_recv.pid);
- fc->last_pid_recv = pid;
- fc->recv_bitmap <<= delta;
- fc->recv_bitmap |= 1;
- }
- else
- {
- GNUNET_STATISTICS_update (stats,
- "# out of order PID",
- 1,
- GNUNET_NO);
- if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv,
- pid,
- fc->recv_bitmap))
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "PID %u unexpected (%u+), dropping!\n",
- ntohl (pid.pid),
- ntohl (fc->last_pid_recv.pid) - 31);
- return GNUNET_SYSERR;
- }
- fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv,
- pid);
- }
- }
-
- /* Count as connection confirmation. */
- if ( (CADET_CONNECTION_SENT == c->state) ||
- (CADET_CONNECTION_ACK == c->state) )
- {
- connection_change_state (c, CADET_CONNECTION_READY);
- if (NULL != c->t)
- {
- if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t))
- GCT_change_cstate (c->t, CADET_TUNNEL_READY);
- }
- }
- connection_reset_timeout (c, fwd);
-
- return fwd;
-}
-
-
-/**
- * Handler for key exchange traffic (Axolotl KX).
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_kx (struct CadetPeer *peer,
- const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
- struct CadetConnection *c;
- int fwd;
-
- GCC_check_connections ();
- cid = &msg->cid;
- log_message (&msg->header, peer, cid);
-
- c = connection_get (cid);
- fwd = check_message (&msg->header,
- cid,
- c,
- peer,
- zero);
-
- /* If something went wrong, discard message. */
- if (GNUNET_SYSERR == fwd)
- {
- GNUNET_break_op (0);
- GCC_check_connections ();
- return;
- }
-
- /* Is this message for us? */
- if (GCC_is_terminal (c, fwd))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n");
- GNUNET_STATISTICS_update (stats, "# received KX", 1, GNUNET_NO);
- if (NULL == c->t)
- {
- GNUNET_break (0);
- return;
- }
- GCT_handle_kx (c->t, msg);
- GCC_check_connections ();
- return;
- }
-
- /* Message not for us: forward to next hop */
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
- GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
- (void) GCC_send_prebuilt_message (&msg->header, 0,
- zero, c, fwd,
- GNUNET_NO, NULL, NULL);
- GCC_check_connections ();
-}
-
-
-/**
- * Handler for encrypted cadet network traffic (channel mgmt, data).
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_encrypted (struct CadetPeer *peer,
- const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid;
- struct CadetConnection *c;
- struct CadetEncryptedMessageIdentifier pid;
- int fwd;
-
- GCC_check_connections ();
- cid = &msg->cid;
- pid = msg->cemi;
- log_message (&msg->header, peer, cid);
-
- c = connection_get (cid);
- fwd = check_message (&msg->header,
- cid,
- c,
- peer,
- pid);
-
- /* If something went wrong, discard message. */
- if (GNUNET_SYSERR == fwd)
- {
- GCC_check_connections ();
- return;
- }
-
- /* Is this message for us? */
- if (GCC_is_terminal (c, fwd))
- {
- GNUNET_STATISTICS_update (stats, "# received encrypted", 1, GNUNET_NO);
-
- if (NULL == c->t)
- {
- GNUNET_break (GNUNET_NO != c->destroy);
- return;
- }
- GCT_handle_encrypted (c->t, msg);
- GCC_send_ack (c, fwd, GNUNET_NO);
- GCC_check_connections ();
- return;
- }
-
- /* Message not for us: forward to next hop */
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
- GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
- (void) GCC_send_prebuilt_message (&msg->header, 0,
- zero, c, fwd,
- GNUNET_NO, NULL, NULL);
- GCC_check_connections ();
-}
-
-
-/**
- * Initialize the connections subsystem
- *
- * @param c Configuration handle.
- */
-void
-GCC_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE",
- &max_msgs_queue))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- "CADET", "MAX_MSGS_QUEUE", "MISSING");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS",
- &max_connections))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- "CADET", "MAX_CONNECTIONS", "MISSING");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REFRESH_CONNECTION_TIME",
- &refresh_connection_time))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- "CADET", "REFRESH_CONNECTION_TIME", "MISSING");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
- create_connection_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
- refresh_connection_time);
- connections = GNUNET_CONTAINER_multishortmap_create (1024,
- GNUNET_YES);
-}
-
-
-/**
- * Destroy each connection on shutdown.
- *
- * @param cls Closure (unused).
- * @param key Current key code (CID, unused).
- * @param value Value in the hash map (`struct CadetConnection`)
- *
- * @return #GNUNET_YES, because we should continue to iterate
- */
-static int
-shutdown_iterator (void *cls,
- const struct GNUNET_ShortHashCode *key,
- void *value)
-{
- struct CadetConnection *c = value;
-
- c->state = CADET_CONNECTION_DESTROYED;
- GCC_destroy (c);
- return GNUNET_YES;
-}
-
-
-/**
- * Shut down the connections subsystem.
- */
-void
-GCC_shutdown (void)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connections\n");
- GCC_check_connections ();
- GNUNET_CONTAINER_multishortmap_iterate (connections,
- &shutdown_iterator,
- NULL);
- GNUNET_CONTAINER_multishortmap_destroy (connections);
- connections = NULL;
-}
-
-
-/**
- * Create a connection.
- *
- * @param cid Connection ID (either created locally or imposed remotely).
- * @param t Tunnel this connection belongs to (or NULL for transit connections);
- * @param path Path this connection has to use (copy is made).
- * @param own_pos Own position in the @c path path.
- *
- * @return Newly created connection.
- * NULL in case of error: own id not in path, wrong neighbors, ...
-*/
-struct CadetConnection *
-GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
- struct CadetTunnel *t,
- struct CadetPeerPath *path,
- unsigned int own_pos)
-{
- struct CadetConnection *c;
- struct CadetPeerPath *cpath;
-
- GCC_check_connections ();
- cpath = path_duplicate (path);
- GNUNET_assert (NULL != cpath);
- c = GNUNET_new (struct CadetConnection);
- c->id = *cid;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CONTAINER_multishortmap_put (connections,
- &c->id.connection_of_tunnel,
- c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- fc_init (&c->fwd_fc);
- fc_init (&c->bck_fc);
- c->fwd_fc.c = c;
- c->bck_fc.c = c;
-
- c->t = t;
- GNUNET_assert (own_pos <= cpath->length - 1);
- c->own_pos = own_pos;
- c->path = cpath;
- cpath->c = c;
- if (GNUNET_OK != register_neighbors (c))
- {
- if (0 == own_pos)
- {
- /* We were the origin of this request, this means we have invalid
- * info about the paths to reach the destination. We must invalidate
- * the *original* path to avoid trying it again in the next minute.
- */
- if (2 < path->length)
- path_invalidate (path);
- else
- {
- GNUNET_break (0);
- GCT_debug(t, GNUNET_ERROR_TYPE_WARNING);
- }
- c->t = NULL;
- }
- path_destroy (c->path);
- c->path = NULL;
- GCC_destroy (c);
- return NULL;
- }
- LOG (GNUNET_ERROR_TYPE_INFO, "New connection %s\n", GCC_2s (c));
- GCC_check_connections ();
- return c;
-}
-
-
-/**
- * Connection is no longer needed: destroy it.
- *
- * Cancels all pending traffic (including possible DESTROY messages), all
- * maintenance tasks and removes the connection from neighbor peers and tunnel.
- *
- * @param c Connection to destroy.
- */
-void
-GCC_destroy (struct CadetConnection *c)
-{
- GCC_check_connections ();
- if (NULL == c)
- {
- GNUNET_break (0);
- return;
- }
-
- if (2 == c->destroy) /* cancel queues -> GCP_queue_cancel -> q_destroy -> */
- return; /* -> message_sent -> GCC_destroy. Don't loop. */
- c->destroy = 2;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "destroying connection %s\n",
- GCC_2s (c));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " fc's f: %p, b: %p\n",
- &c->fwd_fc, &c->bck_fc);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " fc tasks f: %u, b: %u\n",
- c->fwd_fc.poll_task,
- c->bck_fc.poll_task);
-
- /* Cancel all traffic */
- if (NULL != c->path)
- {
- connection_cancel_queues (c, GNUNET_YES);
- connection_cancel_queues (c, GNUNET_NO);
- if (NULL != c->maintenance_q)
- {
- GCP_send_cancel (c->maintenance_q);
- c->maintenance_q = NULL;
- }
- }
- unregister_neighbors (c);
- path_destroy (c->path);
- c->path = NULL;
-
- /* Delete from tunnel */
- if (NULL != c->t)
- GCT_remove_connection (c->t, c);
-
- if (NULL != c->check_duplicates_task)
- GNUNET_SCHEDULER_cancel (c->check_duplicates_task);
- if (NULL != c->fwd_maintenance_task)
- GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
- if (NULL != c->bck_maintenance_task)
- GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
-
- if (GNUNET_NO == c->was_removed)
- {
- GNUNET_break (GNUNET_YES ==
- GNUNET_CONTAINER_multishortmap_remove (connections,
- &c->id.connection_of_tunnel,
- c));
- }
- GNUNET_STATISTICS_update (stats,
- "# connections",
- -1,
- GNUNET_NO);
- GNUNET_free (c);
- GCC_check_connections ();
-}
-
-
-/**
- * Get the connection ID.
- *
- * @param c Connection to get the ID from.
- *
- * @return ID of the connection.
- */
-const struct GNUNET_CADET_ConnectionTunnelIdentifier *
-GCC_get_id (const struct CadetConnection *c)
-{
- return &c->id;
-}
-
-
-/**
- * Get the connection path.
- *
- * @param c Connection to get the path from.
- *
- * @return path used by the connection.
- */
-const struct CadetPeerPath *
-GCC_get_path (const struct CadetConnection *c)
-{
- if (GNUNET_NO == c->destroy)
- return c->path;
- return NULL;
-}
-
-
-/**
- * Get the connection state.
- *
- * @param c Connection to get the state from.
- *
- * @return state of the connection.
- */
-enum CadetConnectionState
-GCC_get_state (const struct CadetConnection *c)
-{
- return c->state;
-}
-
-/**
- * Get the connection tunnel.
- *
- * @param c Connection to get the tunnel from.
- *
- * @return tunnel of the connection.
- */
-struct CadetTunnel *
-GCC_get_tunnel (const struct CadetConnection *c)
-{
- return c->t;
-}
-
-
-/**
- * Get free buffer space in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - max_msgs_queue/max_connections]
- */
-unsigned int
-GCC_get_buffer (struct CadetConnection *c, int fwd)
-{
- struct CadetFlowControl *fc;
-
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Get %s buffer on %s: %u - %u\n",
- GC_f2s (fwd), GCC_2s (c), fc->queue_max, fc->queue_n);
- GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG);
-
- return (fc->queue_max - fc->queue_n);
-}
-
-
-/**
- * Get how many messages have we allowed to send to us from a direction.
- *
- * @param c Connection.
- * @param fwd Are we asking about traffic from FWD (BCK messages)?
- *
- * @return last_ack_sent - last_pid_recv
- */
-unsigned int
-GCC_get_allowed (struct CadetConnection *c, int fwd)
-{
- struct CadetFlowControl *fc;
-
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- if ( (CADET_CONNECTION_READY != c->state) ||
- GC_is_pid_bigger (ntohl (fc->last_pid_recv.pid),
- ntohl (fc->last_ack_sent.pid)) )
- {
- return 0;
- }
- return (ntohl (fc->last_ack_sent.pid) - ntohl (fc->last_pid_recv.pid));
-}
-
-
-/**
- * Get messages queued in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Number of messages queued.
- */
-unsigned int
-GCC_get_qn (struct CadetConnection *c, int fwd)
-{
- struct CadetFlowControl *fc;
-
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
-
- return fc->queue_n;
-}
-
-
-/**
- * Get next PID to use.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- * @return Next PID to use.
- */
-struct CadetEncryptedMessageIdentifier
-GCC_get_pid (struct CadetConnection *c, int fwd)
-{
- struct CadetFlowControl *fc;
- struct CadetEncryptedMessageIdentifier pid;
-
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- pid = fc->next_pid;
- fc->next_pid.pid = htonl (1 + ntohl (pid.pid));
- return pid;
-}
-
-
-/**
- * Allow the connection to advertise a buffer of the given size.
- *
- * The connection will send an @c fwd ACK message (so: in direction !fwd)
- * allowing up to last_pid_recv + buffer.
- *
- * @param c Connection.
- * @param buffer How many more messages the connection can accept.
- * @param fwd Is this about FWD traffic? (The ack will go dest->root).
- */
-void
-GCC_allow (struct CadetConnection *c, unsigned int buffer, int fwd)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, " allowing %s %u messages %s\n",
- GCC_2s (c), buffer, GC_f2s (fwd));
- send_ack (c, buffer, fwd, GNUNET_NO);
-}
-
-
-/**
- * Notify other peers on a connection of a broken link. Mark connections
- * to destroy after all traffic has been sent.
- *
- * @param c Connection on which there has been a disconnection.
- * @param peer Peer that disconnected.
- */
-void
-GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer)
-{
- struct CadetFlowControl *fc;
- char peer_name[16];
- int fwd;
-
- GCC_check_connections ();
- strncpy (peer_name, GCP_2s (peer), 16);
- peer_name[15] = '\0';
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "shutting down %s, %s disconnected\n",
- GCC_2s (c), peer_name);
-
- invalidate_paths (c, peer);
-
- fwd = is_fwd (c, peer);
- if (GNUNET_SYSERR == fwd)
- {
- GNUNET_break (0);
- return;
- }
- if ( (GNUNET_YES == GCC_is_terminal (c, fwd)) ||
- (GNUNET_NO != c->destroy) )
- {
- /* Local shutdown, or other peer already down (hence 'c->destroy');
- so there is no one to notify about this, just clean up. */
- GCC_destroy (c);
- GCC_check_connections ();
- return;
- }
- /* Mark FlowControl towards the peer as unavaliable. */
- fc = fwd ? &c->bck_fc : &c->fwd_fc;
- fc->queue_max = 0;
-
- send_broken (c, &my_full_id, GCP_get_id (peer), fwd);
-
- /* Connection will have at least one pending message
- * (the one we just scheduled), so delay destruction
- * and remove from map so we don't use accidentally. */
- mark_destroyed (c);
- GNUNET_assert (GNUNET_NO == c->was_removed);
- c->was_removed = GNUNET_YES;
- GNUNET_break (GNUNET_YES ==
- GNUNET_CONTAINER_multishortmap_remove (connections,
- &c->id.connection_of_tunnel,
- c));
- /* Cancel queue in the direction that just died. */
- connection_cancel_queues (c, ! fwd);
- GCC_stop_poll (c, ! fwd);
- unregister_neighbors (c);
- GCC_check_connections ();
-}
-
-
-/**
- * Is this peer the first one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
- */
-int
-GCC_is_origin (struct CadetConnection *c, int fwd)
-{
- if (!fwd && c->path->length - 1 == c->own_pos )
- return GNUNET_YES;
- if (fwd && 0 == c->own_pos)
- return GNUNET_YES;
- return GNUNET_NO;
-}
-
-
-/**
- * Is this peer the last one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- * Note that the ROOT is the terminal for BCK traffic!
- *
- * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
- */
-int
-GCC_is_terminal (struct CadetConnection *c, int fwd)
-{
- return GCC_is_origin (c, ! fwd);
-}
-
-
-/**
- * See if we are allowed to send by the next hop in the given direction.
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES in case it's OK to send.
- */
-int
-GCC_is_sendable (struct CadetConnection *c, int fwd)
-{
- struct CadetFlowControl *fc;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " checking sendability of %s traffic on %s\n",
- GC_f2s (fwd), GCC_2s (c));
- if (NULL == c)
- {
- GNUNET_break (0);
- return GNUNET_YES;
- }
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " last ack recv: %u, last pid sent: %u\n",
- ntohl (fc->last_ack_recv.pid),
- ntohl (fc->last_pid_sent.pid));
- if (GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid),
- ntohl (fc->last_pid_sent.pid)))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n");
- return GNUNET_YES;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n");
- return GNUNET_NO;
-}
-
-
-/**
- * Check if this connection is a direct one (never trim a direct connection).
- *
- * @param c Connection.
- *
- * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
- */
-int
-GCC_is_direct (struct CadetConnection *c)
-{
- return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Sends a completely built message on a connection, properly registering
- * all used resources.
- *
- * @param message Message to send.
- * @param payload_type Type of payload, in case the message is encrypted.
- * 0 for restransmissions (when type is no longer known)
- * UINT16_MAX when not applicable.
- * @param payload_id ID of the payload (PID, ACK, ...).
- * @param c Connection on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param force Force the connection to accept the message (buffer overfill).
- * @param cont Continuation called once message is sent. Can be NULL.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel the message before it's sent.
- * NULL on error.
- * Invalid on @c cont call.
- */
-struct CadetConnectionQueue *
-GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- uint16_t payload_type,
- struct CadetEncryptedMessageIdentifier payload_id,
- struct CadetConnection *c, int fwd, int force,
- GCC_sent cont, void *cont_cls)
-{
- struct CadetFlowControl *fc;
- struct CadetConnectionQueue *q;
- uint16_t size;
- uint16_t type;
-
- size = ntohs (message->size);
- type = ntohs (message->type);
-
- GCC_check_connections ();
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- if (0 == fc->queue_max)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- LOG (GNUNET_ERROR_TYPE_INFO,
- "--> %s (%s %4u) on conn %s (%p) %s [%5u]\n",
- GC_m2s (type), GC_m2s (payload_type), payload_id, GCC_2s (c), c,
- GC_f2s(fwd), size);
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED:
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u, PIDsnt: %u, ACKrcv: %u\n",
- fc,
- fc->queue_n,
- ntohl (fc->last_pid_sent.pid),
- ntohl (fc->last_ack_recv.pid));
- if (GNUNET_NO == force)
- {
- fc->queue_n++;
- }
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX:
- /* nothing to do here */
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK:
- /* Should've only be used for restransmissions. */
- GNUNET_break (0 == payload_type);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK:
- case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY:
- case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN:
- GNUNET_assert (GNUNET_YES == force);
- break;
-
- default:
- GNUNET_break (0);
- return NULL;
- }
-
- if (fc->queue_n > fc->queue_max && GNUNET_NO == force)
- {
- GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
- 1, GNUNET_NO);
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n",
- fc->queue_n, fc->queue_max);
- if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type)
- {
- fc->queue_n--;
- }
- return NULL; /* Drop this message */
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %s %u\n",
- GCC_2s (c), c->pending_messages);
- c->pending_messages++;
-
- q = GNUNET_new (struct CadetConnectionQueue);
- q->cont = cont;
- q->cont_cls = cont_cls;
- q->forced = force;
- GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q);
- q->peer_q = GCP_send (get_hop (c, fwd),
- message,
- payload_type,
- payload_id,
- c,
- fwd,
- &conn_message_sent, q);
- if (NULL == q->peer_q)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "dropping msg on %s, NULL q\n", GCC_2s (c));
- GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q);
- GNUNET_free (q);
- GCC_check_connections ();
- return NULL;
- }
- GCC_check_connections ();
- return q;
-}
-
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GCC_cancel (struct CadetConnectionQueue *q)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "! GCC cancel message\n");
-
- /* send_cancel calls message_sent, which calls q->cont and frees q */
- GCP_send_cancel (q->peer_q);
- GCC_check_connections ();
-}
-
-
-/**
- * Sends a CREATE CONNECTION message for a path to a peer.
- * Changes the connection and tunnel states if necessary.
- *
- * @param c Connection to create.
- */
-void
-GCC_send_create (struct CadetConnection *c)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- enum CadetTunnelCState state;
- size_t size;
-
- GCC_check_connections ();
- size = sizeof (struct GNUNET_CADET_ConnectionCreateMessage);
- size += c->path->length * sizeof (struct GNUNET_PeerIdentity);
- {
- /* Allocate message on the stack */
- unsigned char cbuf[size];
- struct GNUNET_CADET_ConnectionCreateMessage *msg;
- struct GNUNET_PeerIdentity *peers;
-
-
- msg = (struct GNUNET_CADET_ConnectionCreateMessage *) cbuf;
- msg->header.size = htons (size);
- msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE);
- msg->options = htonl (0);
- msg->cid = *GCC_get_id (c);
- peers = (struct GNUNET_PeerIdentity *) &msg[1];
- for (int i = 0; i < c->path->length; i++)
- {
- GNUNET_PEER_resolve (c->path->peers[i], peers++);
- }
- GNUNET_assert (NULL == c->maintenance_q);
- c->maintenance_q = GCP_send (get_next_hop (c),
- &msg->header,
- GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
- zero,
- c, GNUNET_YES,
- &conn_message_sent, NULL);
- }
-
- LOG (GNUNET_ERROR_TYPE_INFO, "==> %s %19s on conn %s (%p) FWD [%5u]\n",
- GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE), "",
- GCC_2s (c), c, size);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n",
- c, c->pending_messages);
- c->pending_messages++;
-
- state = GCT_get_cstate (c->t);
- if (CADET_TUNNEL_SEARCHING == state || CADET_TUNNEL_NEW == state)
- GCT_change_cstate (c->t, CADET_TUNNEL_WAITING);
- if (CADET_CONNECTION_NEW == c->state)
- connection_change_state (c, CADET_CONNECTION_SENT);
- GCC_check_connections ();
-}
-
-
-/**
- * Send an ACK on the appropriate connection/channel, depending on
- * the direction and the position of the peer.
- *
- * @param c Which connection to send the hop-by-hop ACK.
- * @param fwd Is this a fwd ACK? (will go dest->root).
- * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
- */
-void
-GCC_send_ack (struct CadetConnection *c, int fwd, int force)
-{
- unsigned int buffer;
-
- GCC_check_connections ();
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GCC send %s ACK on %s\n",
- GC_f2s (fwd), GCC_2s (c));
-
- if (NULL == c)
- {
- GNUNET_break (0);
- return;
- }
-
- if (GNUNET_NO != c->destroy)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother...\n");
- GCC_check_connections ();
- return;
- }
-
- /* Get available buffer space */
- if (GCC_is_terminal (c, fwd))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n");
- buffer = GCT_get_channels_buffer (c->t);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
- buffer = GCC_get_buffer (c, fwd);
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
- if (0 == buffer && GNUNET_NO == force)
- {
- GCC_check_connections ();
- return;
- }
-
- /* Send available buffer space */
- if (GNUNET_YES == GCC_is_origin (c, fwd))
- {
- GNUNET_assert (NULL != c->t);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n");
- GCT_unchoke_channels (c->t);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
- send_ack (c, buffer, fwd, force);
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Send a message to all peers in this connection that the connection
- * is no longer valid.
- *
- * If some peer should not receive the message, it should be zero'ed out
- * before calling this function.
- *
- * @param c The connection whose peers to notify.
- */
-void
-GCC_send_destroy (struct CadetConnection *c)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct GNUNET_CADET_ConnectionDestroyMessage msg;
-
- if (GNUNET_YES == c->destroy)
- return;
- GCC_check_connections ();
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);
- msg.cid = c->id;
- msg.reserved = htonl (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " sending connection destroy for connection %s\n",
- GCC_2s (c));
-
- if (GNUNET_NO == GCC_is_terminal (c, GNUNET_YES))
- (void) GCC_send_prebuilt_message (&msg.header,
- UINT16_MAX,
- zero,
- c,
- GNUNET_YES, GNUNET_YES, NULL, NULL);
- if (GNUNET_NO == GCC_is_terminal (c, GNUNET_NO))
- (void) GCC_send_prebuilt_message (&msg.header,
- UINT16_MAX,
- zero,
- c,
- GNUNET_NO, GNUNET_YES, NULL, NULL);
- mark_destroyed (c);
- GCC_check_connections ();
-}
-
-
-/**
- * @brief Start a polling timer for the connection.
- *
- * When a neighbor does not accept more traffic on the connection it could be
- * caused by a simple congestion or by a lost ACK. Polling enables to check
- * for the lastest ACK status for a connection.
- *
- * @param c Connection.
- * @param fwd Should we poll in the FWD direction?
- */
-void
-GCC_start_poll (struct CadetConnection *c, int fwd)
-{
- struct CadetFlowControl *fc;
-
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL %s requested\n",
- GC_f2s (fwd));
- if (NULL != fc->poll_task || NULL != fc->poll_msg)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL already in progress (t: %p, m: %p)\n",
- fc->poll_task, fc->poll_msg);
- return;
- }
- if (0 == fc->queue_max)
- {
- /* Should not be needed, traffic should've been cancelled. */
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL not possible, peer disconnected\n");
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL started on request\n");
- fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, &send_poll, fc);
-}
-
-
-/**
- * @brief Stop polling a connection for ACKs.
- *
- * Once we have enough ACKs for future traffic, polls are no longer necessary.
- *
- * @param c Connection.
- * @param fwd Should we stop the poll in the FWD direction?
- */
-void
-GCC_stop_poll (struct CadetConnection *c, int fwd)
-{
- struct CadetFlowControl *fc;
-
- fc = fwd ? &c->fwd_fc : &c->bck_fc;
- if (NULL != fc->poll_task)
- {
- GNUNET_SCHEDULER_cancel (fc->poll_task);
- fc->poll_task = NULL;
- }
- if (NULL != fc->poll_msg)
- {
- GCC_cancel (fc->poll_msg);
- fc->poll_msg = NULL;
- }
-}
-
-
-/**
- * Get a (static) string for a connection.
- *
- * @param c Connection.
- */
-const char *
-GCC_2s (const struct CadetConnection *c)
-{
- if (NULL == c)
- return "NULL";
-
- if (NULL != c->t)
- {
- static char buf[128];
-
- SPRINTF (buf, "%s (->%s)",
- GNUNET_sh2s (&GCC_get_id (c)->connection_of_tunnel),
- GCT_2s (c->t));
- return buf;
- }
- return GNUNET_sh2s (&c->id.connection_of_tunnel);
-}
-
-
-/**
- * Log all possible info about the connection state.
- *
- * @param c Connection to debug.
- * @param level Debug level to use.
- */
-void
-GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level)
-{
- int do_log;
- char *s;
-
- do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
- "cadet-con",
- __FILE__, __FUNCTION__, __LINE__);
- if (0 == do_log)
- return;
-
- if (NULL == c)
- {
- LOG2 (level, "CCC DEBUG NULL CONNECTION\n");
- return;
- }
-
- LOG2 (level, "CCC DEBUG CONNECTION %s\n", GCC_2s (c));
- s = path_2s (c->path);
- LOG2 (level, "CCC path %s, own pos: %u\n", s, c->own_pos);
- GNUNET_free (s);
- LOG2 (level, "CCC state: %s, destroy: %u\n",
- GCC_state2s (c->state), c->destroy);
- LOG2 (level, "CCC pending messages: %u\n", c->pending_messages);
- if (NULL != c->perf)
- LOG2 (level, "CCC us/byte: %f\n", c->perf->avg);
-
- LOG2 (level, "CCC FWD flow control:\n");
- LOG2 (level, "CCC queue: %u/%u\n", c->fwd_fc.queue_n, c->fwd_fc.queue_max);
- LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n",
- ntohl (c->fwd_fc.last_pid_sent.pid),
- ntohl (c->fwd_fc.last_pid_recv.pid));
- LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n",
- ntohl (c->fwd_fc.last_ack_sent.pid),
- ntohl (c->fwd_fc.last_ack_recv.pid));
- LOG2 (level, "CCC recv PID bitmap: %X\n", c->fwd_fc.recv_bitmap);
- LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n",
- c->fwd_fc.poll_task, c->fwd_fc.poll_msg, c->fwd_fc.ack_msg);
-
- LOG2 (level, "CCC BCK flow control:\n");
- LOG2 (level, "CCC queue: %u/%u\n", c->bck_fc.queue_n, c->bck_fc.queue_max);
- LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n",
- ntohl (c->bck_fc.last_pid_sent.pid),
- ntohl (c->bck_fc.last_pid_recv.pid));
- LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n",
- ntohl (c->bck_fc.last_ack_sent.pid),
- ntohl (c->bck_fc.last_ack_recv.pid));
- LOG2 (level, "CCC recv PID bitmap: %X\n", c->bck_fc.recv_bitmap);
- LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n",
- c->bck_fc.poll_task, c->bck_fc.poll_msg, c->bck_fc.ack_msg);
-
- LOG2 (level, "CCC DEBUG CONNECTION END\n");
-}
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_connection.h
- * @brief cadet service; dealing with connections
- * @author Bartlomiej Polot
- *
- * All functions in this file use the prefix GCC (GNUnet Cadet Connection)
- */
-
-#ifndef GNUNET_SERVICE_CADET_CONNECTION_H
-#define GNUNET_SERVICE_CADET_CONNECTION_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "gnunet_util_lib.h"
-
-
-/**
- * All the states a connection can be in.
- */
-enum CadetConnectionState
-{
- /**
- * Uninitialized status, should never appear in operation.
- */
- CADET_CONNECTION_NEW,
-
- /**
- * Connection create message sent, waiting for ACK.
- */
- CADET_CONNECTION_SENT,
-
- /**
- * Connection ACK sent, waiting for ACK.
- */
- CADET_CONNECTION_ACK,
-
- /**
- * Connection confirmed, ready to carry traffic.
- */
- CADET_CONNECTION_READY,
-
- /**
- * Connection to be destroyed, just waiting to empty queues.
- */
- CADET_CONNECTION_DESTROYED,
-
- /**
- * Connection to be destroyed because of a distant peer, same as DESTROYED.
- */
- CADET_CONNECTION_BROKEN,
-};
-
-
-/**
- * Struct containing all information regarding a connection to a peer.
- */
-struct CadetConnection;
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetConnectionQueue;
-
-#include "cadet_path.h"
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_peer.h"
-
-
-/**
- * Check invariants for all connections using #check_neighbours().
- */
-void
-GCC_check_connections (void);
-
-
-/**
- * Callback called when a queued message is sent.
- *
- * @param cls Closure.
- * @param c Connection this message was on.
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-typedef void
-(*GCC_sent) (void *cls,
- struct CadetConnection *c,
- struct CadetConnectionQueue *q,
- uint16_t type,
- int fwd,
- size_t size);
-
-
-/**
- * Handler for connection creation.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_create (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionCreateMessage *msg);
-
-
-/**
- * Handler for connection confirmations.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_confirm (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionCreateAckMessage *msg);
-
-
-/**
- * Handler for notifications of broken connections.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_broken (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionBrokenMessage *msg);
-
-/**
- * Handler for notifications of destroyed connections.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_destroy (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionDestroyMessage *msg);
-
-/**
- * Handler for cadet network traffic hop-by-hop acks.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_ack (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg);
-
-/**
- * Handler for cadet network traffic hop-by-hop data counter polls.
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_poll (struct CadetPeer *peer,
- const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg);
-
-/**
- * Handler for key exchange traffic (Axolotl KX).
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_kx (struct CadetPeer *peer,
- const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
-
-/**
- * Handler for encrypted cadet network traffic (channel mgmt, data).
- *
- * @param peer Message sender (neighbor).
- * @param msg Message itself.
- */
-void
-GCC_handle_encrypted (struct CadetPeer *peer,
- const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
-
-/**
- * Core handler for axolotl key exchange traffic.
- *
- * @param cls Closure (unused).
- * @param message Message received.
- * @param peer Neighbor who sent the message.
- *
- * @return GNUNET_OK, to keep the connection open.
- */
-int
-GCC_handle_ax_kx (void *cls, const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for axolotl encrypted cadet network traffic.
- *
- * @param cls Closure (unused).
- * @param message Message received.
- * @param peer Neighbor who sent the message.
- *
- * @return GNUNET_OK, to keep the connection open.
- */
-int
-GCC_handle_ax (void *cls, const struct GNUNET_PeerIdentity *peer,
- struct GNUNET_MessageHeader *message);
-
-/**
- * Core handler for cadet keepalives.
- *
- * @param cls closure
- * @param message message
- * @param peer peer identity this notification is about
- * @return GNUNET_OK to keep the connection open,
- * GNUNET_SYSERR to close it (signal serious error)
- *
- * TODO: Check who we got this from, to validate route.
- */
-int
-GCC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_MessageHeader *message);
-
-/**
- * Send an ACK on the appropriate connection/channel, depending on
- * the direction and the position of the peer.
- *
- * @param c Which connection to send the hop-by-hop ACK.
- * @param fwd Is this a fwd ACK? (will go dest->root).
- * @param force Send the ACK even if suboptimal (e.g. requested by POLL).
- */
-void
-GCC_send_ack (struct CadetConnection *c, int fwd, int force);
-
-/**
- * Initialize the connections subsystem
- *
- * @param c Configuration handle.
- */
-void
-GCC_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-/**
- * Shut down the connections subsystem.
- */
-void
-GCC_shutdown (void);
-
-/**
- * Create a connection.
- *
- * @param cid Connection ID (either created locally or imposed remotely).
- * @param t Tunnel this connection belongs to (or NULL for transit connections);
- * @param path Path this connection has to use (copy is made).
- * @param own_pos Own position in the @c path path.
- *
- * @return Newly created connection.
- * NULL in case of error: own id not in path, wrong neighbors, ...
- */
-struct CadetConnection *
-GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid,
- struct CadetTunnel *t,
- struct CadetPeerPath *path,
- unsigned int own_pos);
-
-/**
- * Connection is no longer needed: destroy it.
- *
- * Cancels all pending traffic (including possible DESTROY messages), all
- * maintenance tasks and removes the connection from neighbor peers and tunnel.
- *
- * @param c Connection to destroy.
- */
-void
-GCC_destroy (struct CadetConnection *c);
-
-/**
- * Get the connection ID.
- *
- * @param c Connection to get the ID from.
- *
- * @return ID of the connection.
- */
-const struct GNUNET_CADET_ConnectionTunnelIdentifier *
-GCC_get_id (const struct CadetConnection *c);
-
-
-/**
- * Get the connection path.
- *
- * @param c Connection to get the path from.
- *
- * @return path used by the connection.
- */
-const struct CadetPeerPath *
-GCC_get_path (const struct CadetConnection *c);
-
-/**
- * Get the connection state.
- *
- * @param c Connection to get the state from.
- *
- * @return state of the connection.
- */
-enum CadetConnectionState
-GCC_get_state (const struct CadetConnection *c);
-
-/**
- * Get the connection tunnel.
- *
- * @param c Connection to get the tunnel from.
- *
- * @return tunnel of the connection.
- */
-struct CadetTunnel *
-GCC_get_tunnel (const struct CadetConnection *c);
-
-/**
- * Get free buffer space in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Free buffer space [0 - max_msgs_queue/max_connections]
- */
-unsigned int
-GCC_get_buffer (struct CadetConnection *c, int fwd);
-
-/**
- * Get how many messages have we allowed to send to us from a direction.
- *
- * @param c Connection.
- * @param fwd Are we asking about traffic from FWD (BCK messages)?
- *
- * @return last_ack_sent - last_pid_recv
- */
-unsigned int
-GCC_get_allowed (struct CadetConnection *c, int fwd);
-
-/**
- * Get messages queued in a connection.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- *
- * @return Number of messages queued.
- */
-unsigned int
-GCC_get_qn (struct CadetConnection *c, int fwd);
-
-/**
- * Get next PID to use.
- *
- * @param c Connection.
- * @param fwd Is query about FWD traffic?
- * @return Next PID to use.
- */
-struct CadetEncryptedMessageIdentifier
-GCC_get_pid (struct CadetConnection *c, int fwd);
-
-/**
- * Allow the connection to advertise a buffer of the given size.
- *
- * The connection will send an @c fwd ACK message (so: in direction !fwd)
- * allowing up to last_pid_recv + buffer.
- *
- * @param c Connection.
- * @param buffer How many more messages the connection can accept.
- * @param fwd Is this about FWD traffic? (The ack will go dest->root).
- */
-void
-GCC_allow (struct CadetConnection *c, unsigned int buffer, int fwd);
-
-/**
- * Send FWD keepalive packets for a connection.
- *
- * @param cls Closure (connection for which to send the keepalive).
- * @param tc Notification context.
- */
-void
-GCC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
- * Send BCK keepalive packets for a connection.
- *
- * @param cls Closure (connection for which to send the keepalive).
- * @param tc Notification context.
- */
-void
-GCC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Notify other peers on a connection of a broken link. Mark connections
- * to destroy after all traffic has been sent.
- *
- * @param c Connection on which there has been a disconnection.
- * @param peer Peer that disconnected.
- */
-void
-GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer);
-
-/**
- * Is this peer the first one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal.
- */
-int
-GCC_is_origin (struct CadetConnection *c, int fwd);
-
-/**
- * Is this peer the last one on the connection?
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- * Note that the ROOT is the terminal for BCK traffic!
- *
- * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin.
- */
-int
-GCC_is_terminal (struct CadetConnection *c, int fwd);
-
-/**
- * See if we are allowed to send by the next hop in the given direction.
- *
- * @param c Connection.
- * @param fwd Is this about fwd traffic?
- *
- * @return #GNUNET_YES in case it's OK to send.
- */
-int
-GCC_is_sendable (struct CadetConnection *c, int fwd);
-
-/**
- * Check if this connection is a direct one (never trim a direct connection).
- *
- * @param c Connection.
- *
- * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise.
- */
-int
-GCC_is_direct (struct CadetConnection *c);
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GCC_cancel (struct CadetConnectionQueue *q);
-
-/**
- * Sends an already built message on a connection, properly registering
- * all used resources.
- *
- * @param message Message to send.
- * @param payload_type Type of payload, in case the message is encrypted.
- * 0 for restransmissions (when type is no longer known)
- * UINT16_MAX when not applicable.
- * @param payload_id ID of the payload (PID, ACK, ...).
- * @param c Connection on which this message is transmitted.
- * @param fwd Is this a fwd message?
- * @param force Force the connection to accept the message (buffer overfill).
- * @param cont Continuation called once message is sent. Can be NULL.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel the message before it's sent.
- * NULL on error.
- * Invalid on @c cont call.
- */
-struct CadetConnectionQueue *
-GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- uint16_t payload_type,
- struct CadetEncryptedMessageIdentifier payload_id,
- struct CadetConnection *c, int fwd, int force,
- GCC_sent cont, void *cont_cls);
-
-/**
- * Sends a CREATE CONNECTION message for a path to a peer.
- * Changes the connection and tunnel states if necessary.
- *
- * @param connection Connection to create.
- */
-void
-GCC_send_create (struct CadetConnection *connection);
-
-/**
- * Send a message to all peers in this connection that the connection
- * is no longer valid.
- *
- * If some peer should not receive the message, it should be zero'ed out
- * before calling this function.
- *
- * @param c The connection whose peers to notify.
- */
-void
-GCC_send_destroy (struct CadetConnection *c);
-
-/**
- * @brief Start a polling timer for the connection.
- *
- * When a neighbor does not accept more traffic on the connection it could be
- * caused by a simple congestion or by a lost ACK. Polling enables to check
- * for the lastest ACK status for a connection.
- *
- * @param c Connection.
- * @param fwd Should we poll in the FWD direction?
- */
-void
-GCC_start_poll (struct CadetConnection *c, int fwd);
-
-
-/**
- * @brief Stop polling a connection for ACKs.
- *
- * Once we have enough ACKs for future traffic, polls are no longer necessary.
- *
- * @param c Connection.
- * @param fwd Should we stop the poll in the FWD direction?
- */
-void
-GCC_stop_poll (struct CadetConnection *c, int fwd);
-
-/**
- * Get a (static) string for a connection.
- *
- * @param c Connection.
- */
-const char *
-GCC_2s (const struct CadetConnection *c);
-
-/**
- * Log all possible info about the connection state.
- *
- * @param c Connection to debug.
- * @param level Debug level to use.
- */
-void
-GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level);
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_SERVICE_CADET_CONNECTION_H */
-#endif
-/* end of gnunet-service-cadet_connection.h */
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_dht_service.h"
-#include "gnunet_statistics_service.h"
-
-#include "cadet_path.h"
-#include "gnunet-service-cadet_dht.h"
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_hello.h"
-
-#define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__)
-
-
-/******************************************************************************/
-/******************************** STRUCTS **********************************/
-/******************************************************************************/
-
-/**
- * Handle for DHT searches.
- */
-struct GCD_search_handle
-{
- /**
- * DHT_GET handle.
- */
- struct GNUNET_DHT_GetHandle *dhtget;
-
- /**
- * Provided callback to call when a path is found.
- */
- GCD_search_callback callback;
-
- /**
- * Provided closure.
- */
- void *cls;
-
- /**
- * Peer ID searched for
- */
- GNUNET_PEER_Id peer_id;
-};
-
-
-/******************************************************************************/
-/******************************* GLOBALS ***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Own ID (short value).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Handle to use DHT.
- */
-static struct GNUNET_DHT_Handle *dht_handle;
-
-/**
- * How often to PUT own ID in the DHT.
- */
-static struct GNUNET_TIME_Relative id_announce_time;
-
-/**
- * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
- */
-static unsigned long long dht_replication_level;
-
-/**
- * Task to periodically announce itself in the network.
- */
-static struct GNUNET_SCHEDULER_Task * announce_id_task;
-
-/**
- * Delay for the next ID announce.
- */
-static struct GNUNET_TIME_Relative announce_delay;
-
-/**
- * GET requests to stop on shutdown.
- */
-static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests;
-
-/******************************************************************************/
-/******************************** STATIC ***********************************/
-/******************************************************************************/
-
-
-/**
- * Build a PeerPath from the paths returned from the DHT, reversing the paths
- * to obtain a local peer -> destination path and interning the peer ids.
- *
- * @return Newly allocated and created path
- *
- * FIXME refactor and use build_path_from_peer_ids
- */
-static struct CadetPeerPath *
-path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int put_path_length)
-{
- size_t size = get_path_length + put_path_length + 1;
- struct GNUNET_PeerIdentity peers[size];
- const struct GNUNET_PeerIdentity *peer;
- struct CadetPeerPath *p;
- unsigned int own_pos;
- int i;
-
- peers[0] = my_full_id;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", get_path_length);
- for (i = 0 ; i < get_path_length; i++)
- {
- peer = &get_path[get_path_length - i - 1];
- LOG (GNUNET_ERROR_TYPE_DEBUG, " From GET: %s\n", GNUNET_i2s (peer));
- peers[i + 1] = *peer;
- }
- for (i = 0 ; i < put_path_length; i++)
- {
- peer = &put_path[put_path_length - i - 1];
- LOG (GNUNET_ERROR_TYPE_DEBUG, " From PUT: %s\n", GNUNET_i2s (peer));
- peers[i + get_path_length + 1] = *peer;
- }
- p = path_build_from_peer_ids (peers, size, myid, &own_pos);
- return p;
-}
-
-
-/**
- * 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 exp when will this value expire
- * @param key key of the result
- * @param get_path path of the get request
- * @param get_path_length lenght of @a get_path
- * @param put_path path of the put request
- * @param put_path_length length of the @a put_path
- * @param type type of the result
- * @param size number of bytes in data
- * @param data pointer to the result data
- */
-static void
-dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
- const struct GNUNET_HashCode * key,
- const struct GNUNET_PeerIdentity *get_path,
- unsigned int get_path_length,
- const struct GNUNET_PeerIdentity *put_path,
- unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
- size_t size, const void *data)
-{
- struct GCD_search_handle *h = cls;
- struct GNUNET_HELLO_Message *hello;
- struct CadetPeerPath *p;
- struct CadetPeer *peer;
- char *s;
-
- p = path_build_from_dht (get_path, get_path_length,
- put_path, put_path_length);
- if (NULL == p)
- {
- GNUNET_break_op (0);
- return;
- }
-
- s = path_2s (p);
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Got path from DHT: %s\n",
- s);
- GNUNET_free_non_null (s);
-
- peer = GCP_get_short (p->peers[p->length - 1], GNUNET_YES);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Got HELLO for %s\n",
- GCP_2s (peer));
- h->callback (h->cls, p);
- path_destroy (p);
- hello = (struct GNUNET_HELLO_Message *) data;
- GCP_set_hello (peer, hello);
- GCP_try_connect (peer);
-}
-
-
-/**
- * Periodically announce self id in the DHT
- *
- * @param cls closure
- */
-static void
-announce_id (void *cls)
-{
- struct GNUNET_HashCode phash;
- const struct GNUNET_HELLO_Message *hello;
- size_t size;
- struct GNUNET_TIME_Absolute expiration;
- struct GNUNET_TIME_Relative next_put;
-
- announce_id_task = NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n");
- hello = GCH_get_mine ();
- size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0;
- if ( (NULL == hello) || (0 == size) )
- {
- /* Peerinfo gave us no hello yet, try again soon. */
- LOG (GNUNET_ERROR_TYPE_INFO,
- " no hello, waiting!\n");
- GNUNET_STATISTICS_update (stats,
- "# DHT announce skipped (no hello)",
- 1,
- GNUNET_NO);
- expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
- announce_delay);
- announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay);
- }
- else
- {
- expiration = GNUNET_HELLO_get_last_expiration (hello);
- announce_delay = GNUNET_TIME_UNIT_SECONDS;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Hello %p size: %u\n",
- hello,
- size);
- if (NULL != hello)
- {
- GNUNET_STATISTICS_update (stats,
- "# DHT announce",
- 1, GNUNET_NO);
- memset (&phash,
- 0,
- sizeof (phash));
- GNUNET_memcpy (&phash,
- &my_full_id,
- sizeof (my_full_id));
- GNUNET_DHT_put (dht_handle, /* DHT handle */
- &phash, /* Key to use */
- dht_replication_level, /* Replication level */
- GNUNET_DHT_RO_RECORD_ROUTE
- | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
- GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */
- size, /* Size of the data */
- (const char *) hello, /* Data itself */
- expiration, /* Data expiration */
- NULL, /* Continuation */
- NULL); /* Continuation closure */
- }
- /* Call again in id_announce_time, unless HELLO expires first,
- * but wait at least 1s. */
- next_put = GNUNET_TIME_absolute_get_remaining (expiration);
- next_put = GNUNET_TIME_relative_min (next_put,
- id_announce_time);
- next_put = GNUNET_TIME_relative_max (next_put,
- GNUNET_TIME_UNIT_SECONDS);
- announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put,
- &announce_id,
- cls);
-}
-
-/**
- * Iterator over hash map entries and stop GET requests before disconnecting
- * from the DHT.
- *
- * @param cls Closure (unused)
- * @param key Current peer ID.
- * @param value Value in the hash map (GCD_search_handle).
- *
- * @return #GNUNET_YES, we should continue to iterate,
- */
-int
-stop_get (void *cls,
- uint32_t key,
- void *value)
-{
- struct GCD_search_handle *h = value;
-
- GCD_search_stop (h);
- return GNUNET_YES;
-}
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Initialize the DHT subsystem.
- *
- * @param c Configuration.
- */
-void
-GCD_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c, "CADET",
- "DHT_REPLICATION_LEVEL",
- &dht_replication_level))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "CADET",
- "DHT_REPLICATION_LEVEL", "USING DEFAULT");
- dht_replication_level = 3;
- }
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME",
- &id_announce_time))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "CADET",
- "ID_ANNOUNCE_TIME", "MISSING");
- GNUNET_SCHEDULER_shutdown ();
- return;
- }
-
- dht_handle = GNUNET_DHT_connect (c, 64);
- if (NULL == dht_handle)
- {
- GNUNET_break (0);
- }
-
- announce_delay = GNUNET_TIME_UNIT_SECONDS;
- announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL);
- get_requests = GNUNET_CONTAINER_multihashmap32_create (32);
-}
-
-
-/**
- * Shut down the DHT subsystem.
- */
-void
-GCD_shutdown (void)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down DHT\n");
- GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL);
- GNUNET_CONTAINER_multihashmap32_destroy (get_requests);
- if (dht_handle != NULL)
- {
- GNUNET_DHT_disconnect (dht_handle);
- dht_handle = NULL;
- }
- if (NULL != announce_id_task)
- {
- GNUNET_SCHEDULER_cancel (announce_id_task);
- announce_id_task = NULL;
- }
-}
-
-struct GCD_search_handle *
-GCD_search (const struct GNUNET_PeerIdentity *peer_id,
- GCD_search_callback callback, void *cls)
-{
- struct GNUNET_HashCode phash;
- struct GCD_search_handle *h;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting DHT GET for peer %s\n",
- GNUNET_i2s (peer_id));
- GNUNET_STATISTICS_update (stats, "# DHT search", 1, GNUNET_NO);
- memset (&phash, 0, sizeof (phash));
- GNUNET_memcpy (&phash, peer_id, sizeof (*peer_id));
- h = GNUNET_new (struct GCD_search_handle);
- h->peer_id = GNUNET_PEER_intern (peer_id);
- h->callback = callback;
- h->cls = cls;
- h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
- GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */
- &phash, /* key to search */
- dht_replication_level, /* replication level */
- GNUNET_DHT_RO_RECORD_ROUTE |
- GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
- NULL, /* xquery */
- 0, /* xquery bits */
- &dht_get_id_handler,
- h);
- GNUNET_CONTAINER_multihashmap32_put (get_requests,
- h->peer_id,
- h,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
- return h;
-}
-
-
-void
-GCD_search_stop (struct GCD_search_handle *h)
-{
- GNUNET_break (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap32_remove (get_requests,
- h->peer_id, h));
- GNUNET_DHT_get_stop (h->dhtget);
- GNUNET_free (h);
-}
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_dht.h
- * @brief cadet service; dealing with DHT requests and results
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMD (Gnunet Cadet Dht)
- */
-
-#ifndef GNUNET_SERVICE_CADET_DHT_H
-#define GNUNET_SERVICE_CADET_DHT_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-struct GCD_search_handle;
-
-
-/**
- * Callback called on each path found over the DHT.
- *
- * @param cls Closure.
- * @param path An unchecked, unoptimized path to the target node.
- * After callback will no longer be valid!
- */
-typedef void
-(*GCD_search_callback) (void *cls,
- const struct CadetPeerPath *path);
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Initialize the DHT subsystem.
- *
- * @param c Configuration.
- */
-void
-GCD_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-/**
- * Shut down the DHT subsystem.
- */
-void
-GCD_shutdown (void);
-
-
-struct GCD_search_handle *
-GCD_search (const struct GNUNET_PeerIdentity *peer_id,
- GCD_search_callback callback, void *cls);
-
-
-void
-GCD_search_stop (struct GCD_search_handle *h);
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */
-#endif
-/* end of gnunet-cadet-service_LOCAL.h */
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2014 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_statistics_service.h"
-#include "gnunet_peerinfo_service.h"
-
-#include "cadet_protocol.h"
-#include "cadet_path.h"
-
-#include "gnunet-service-cadet_hello.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__)
-
-
-/******************************************************************************/
-/******************************** STRUCTS **********************************/
-/******************************************************************************/
-
-
-
-/******************************************************************************/
-/******************************* GLOBALS ***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-
-/**
- * Don't try to recover tunnels if shutting down.
- */
-extern int shutting_down;
-
-
-/**
- * Hello message of local peer.
- */
-const struct GNUNET_HELLO_Message *mine;
-
-/**
- * Handle to peerinfo service.
- */
-static struct GNUNET_PEERINFO_Handle *peerinfo;
-
-/**
- * Iterator context.
- */
-struct GNUNET_PEERINFO_NotifyContext* nc;
-
-
-/******************************************************************************/
-/******************************** STATIC ***********************************/
-/******************************************************************************/
-
-/**
- * Process each hello message received from peerinfo.
- *
- * @param cls Closure (unused).
- * @param peer Identity of the peer.
- * @param hello Hello of the peer.
- * @param err_msg Error message.
- */
-static void
-got_hello (void *cls, const struct GNUNET_PeerIdentity *id,
- const struct GNUNET_HELLO_Message *hello,
- const char *err_msg)
-{
- struct CadetPeer *peer;
-
- if (NULL == id || NULL == hello)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " hello with id %p and msg %p\n", id, hello);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " hello for %s (%d bytes), expires on %s\n",
- GNUNET_i2s (id), GNUNET_HELLO_size (hello),
- GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration(hello)));
- peer = GCP_get (id, GNUNET_YES);
- GCP_set_hello (peer, hello);
-
- if (GCP_get_short_id (peer) == myid)
- mine = GCP_get_hello (peer);
-}
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Initialize the hello subsystem.
- *
- * @param c Configuration.
- */
-void
-GCH_init (const struct GNUNET_CONFIGURATION_Handle *c)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
- GNUNET_assert (NULL == nc);
- peerinfo = GNUNET_PEERINFO_connect (c);
- nc = GNUNET_PEERINFO_notify (c, GNUNET_NO, &got_hello, NULL);
-}
-
-
-/**
- * Shut down the hello subsystem.
- */
-void
-GCH_shutdown ()
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down channels\n");
- if (NULL != nc)
- {
- GNUNET_PEERINFO_notify_cancel (nc);
- nc = NULL;
- }
- if (NULL != peerinfo)
- {
- GNUNET_PEERINFO_disconnect (peerinfo);
- peerinfo = NULL;
- }
-}
-
-
-/**
- * Get own hello message.
- *
- * @return Own hello message.
- */
-const struct GNUNET_HELLO_Message *
-GCH_get_mine (void)
-{
- return mine;
-}
-
-
-/**
- * Get another peer's hello message.
- *
- * @param id ID of the peer whose hello message is requested.
- *
- * @return Hello message, if any (NULL possible).
- */
-const struct GNUNET_HELLO_Message *
-GCH_get (const struct GNUNET_PeerIdentity *id)
-{
- struct CadetPeer *p;
-
- p = GCP_get (id, GNUNET_NO);
- if (NULL == p)
- return NULL;
- return GCP_get_hello (p);
-}
-
-
-/**
- * Convert a hello message to a string.
- *
- * @param h Hello message.
- */
-char *
-GCH_2s (const struct GNUNET_HELLO_Message *h)
-{
- return "hello (TODO)";
-}
-
-
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2014 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_hello.h
- * @brief cadet service; dealing with hello messages
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMH (Gnunet Cadet Hello)
- */
-
-#ifndef GNUNET_SERVICE_CADET_HELLO_H
-#define GNUNET_SERVICE_CADET_HELLO_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_hello_lib.h"
-
-
-/**
- * Initialize the hello subsystem.
- *
- * @param c Configuration.
- */
-void
-GCH_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-
-/**
- * Shut down the hello subsystem.
- */
-void
-GCH_shutdown (void);
-
-
-/**
- * Get own hello message.
- *
- * @return Own hello message.
- */
-const struct GNUNET_HELLO_Message *
-GCH_get_mine (void);
-
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_HELLO_H */
-#endif
-/* end of gnunet-cadet-service_hello.h */
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#include "gnunet_statistics_service.h"
-
-#include "cadet.h"
-#include "cadet_protocol.h" /* GNUNET_CADET_Data is shared */
-
-#include "gnunet-service-cadet_local.h"
-#include "gnunet-service-cadet_channel.h"
-
-/* INFO DEBUG */
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-loc",__VA_ARGS__)
-
-/******************************************************************************/
-/******************************** STRUCTS **********************************/
-/******************************************************************************/
-
-/**
- * Struct containing information about a client of the service
- *
- * TODO: add a list of 'waiting' ports
- */
-struct CadetClient
-{
- /**
- * Linked list next
- */
- struct CadetClient *next;
-
- /**
- * Linked list prev
- */
- struct CadetClient *prev;
-
- /**
- * Tunnels that belong to this client, indexed by local id
- */
- struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
-
- /**
- * Tunnels this client has accepted, indexed by incoming local id
- */
- struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
-
- /**
- * Channel ID for the next incoming channel.
- */
- struct GNUNET_CADET_ClientChannelNumber next_ccn;
-
- /**
- * Handle to communicate with the client
- */
- struct GNUNET_SERVER_Client *handle;
-
- /**
- * Ports that this client has declared interest in.
- * Indexed by port, contains *Client.
- */
- struct GNUNET_CONTAINER_MultiHashMap *ports;
-
- /**
- * Whether the client is active or shutting down (don't send confirmations
- * to a client that is shutting down.
- */
- int shutting_down;
-
- /**
- * ID of the client, mainly for debug messages
- */
- unsigned int id;
-};
-
-/******************************************************************************/
-/******************************* GLOBALS ***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Handle to server lib.
- */
-static struct GNUNET_SERVER_Handle *server_handle;
-
-/**
- * DLL with all the clients, head.
- */
-static struct CadetClient *clients_head;
-
-/**
- * DLL with all the clients, tail.
- */
-static struct CadetClient *clients_tail;
-
-/**
- * Next ID to assign to a client.
- */
-unsigned int next_client_id;
-
-/**
- * All ports clients of this peer have opened.
- */
-static struct GNUNET_CONTAINER_MultiHashMap *ports;
-
-/**
- * Notification context, to send messages to local clients.
- */
-static struct GNUNET_SERVER_NotificationContext *nc;
-
-
-/******************************************************************************/
-/******************************** STATIC ***********************************/
-/******************************************************************************/
-
-/**
- * Remove client's ports from the global hashmap on disconnect.
- *
- * @param cls Closure (unused).
- * @param key Port.
- * @param value Client structure.
- *
- * @return #GNUNET_OK, keep iterating.
- */
-static int
-client_release_ports (void *cls,
- const struct GNUNET_HashCode *key,
- void *value)
-{
- int res;
-
- res = GNUNET_CONTAINER_multihashmap_remove (ports, key, value);
- if (GNUNET_YES != res)
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "Port %s by client %p was not registered.\n",
- GNUNET_h2s (key), value);
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Iterator for deleting each channel whose client endpoint disconnected.
- *
- * @param cls Closure (client that has disconnected).
- * @param key The local channel id (used to access the hashmap).
- * @param value The value stored at the key (channel to destroy).
- *
- * @return #GNUNET_OK, keep iterating.
- */
-static int
-channel_destroy_iterator (void *cls,
- uint32_t key,
- void *value)
-{
- struct CadetChannel *ch = value;
- struct CadetClient *c = cls;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " Channel %s destroy, due to client %s shutdown.\n",
- GCCH_2s (ch), GML_2s (c));
-
- GCCH_handle_local_destroy (ch,
- c,
- key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
- return GNUNET_OK;
-}
-
-
-/**
- * Unregister data and free memory for a client.
- *
- * @param c Client to destroy. No longer valid after call.
- */
-static void
-client_destroy (struct CadetClient *c)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, " client destroy: %p/%u\n", c, c->id);
- GNUNET_SERVER_client_drop (c->handle);
- c->shutting_down = GNUNET_YES;
-
- if (NULL != c->own_channels)
- {
- GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
- &channel_destroy_iterator, c);
- GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
- }
- if (NULL != c->incoming_channels)
- {
- GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
- &channel_destroy_iterator, c);
- GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
- }
- if (NULL != c->ports)
- {
- GNUNET_CONTAINER_multihashmap_iterate (c->ports,
- &client_release_ports, c);
- GNUNET_CONTAINER_multihashmap_destroy (c->ports);
- }
-
- GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
- GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
- GNUNET_SERVER_client_set_user_context (c->handle, NULL);
- GNUNET_free (c);
-}
-
-
-/**
- * Create a client record, register data and initialize memory.
- *
- * @param client Client's handle.
- */
-static struct CadetClient *
-client_new (struct GNUNET_SERVER_Client *client)
-{
- struct CadetClient *c;
-
- GNUNET_SERVER_client_keep (client);
- GNUNET_SERVER_notification_context_add (nc, client);
-
- c = GNUNET_new (struct CadetClient);
- c->handle = client;
- c->id = next_client_id++; /* overflow not important: just for debug */
-
- c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
- c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
-
- GNUNET_SERVER_client_set_user_context (client, c);
- GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
- GNUNET_STATISTICS_update (stats, "# clients", +1, GNUNET_NO);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " client created: %p/%u\n", c, c->id);
-
- return c;
-}
-
-
-/******************************************************************************/
-/******************************** HANDLES ***********************************/
-/******************************************************************************/
-
-/**
- * Handler for client connection.
- *
- * @param cls Closure (unused).
- * @param client Client handler.
- */
-static void
-handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client);
- if (NULL == client)
- return;
-
- (void) client_new (client);
-}
-
-
-/**
- * Handler for client disconnection
- *
- * @param cls closure
- * @param client identification of the client; NULL
- * for the last call when the server is destroyed
- */
-static void
-handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
-{
- struct CadetClient *c;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected: %p\n", client);
-
- c = GML_client_get (client);
- if (NULL != c)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n",
- c->id, c);
- client_destroy (c);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " disconnecting client's context NULL\n");
- }
- return;
-}
-
-
-/**
- * Handler for port open requests.
- *
- * @param cls Closure.
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_port_open (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct CadetClient *c;
- struct GNUNET_CADET_PortMessage *pmsg;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "open port requested\n");
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
-
- /* Message size sanity check */
- if (sizeof (struct GNUNET_CADET_PortMessage) != ntohs (message->size))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- pmsg = (struct GNUNET_CADET_PortMessage *) message;
- if (NULL == c->ports)
- {
- c->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO);
- }
- /* store in client's hashmap */
- if (GNUNET_OK !=
- GNUNET_CONTAINER_multihashmap_put (c->ports, &pmsg->port, c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- /* store in global hashmap */
- /* FIXME only allow one client to have the port open,
- * have a backup hashmap with waiting clients */
- GNUNET_CONTAINER_multihashmap_put (ports, &pmsg->port, c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for port close requests.
- *
- * @param cls Closure.
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_port_close (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct CadetClient *c;
- struct GNUNET_CADET_PortMessage *pmsg;
- int removed;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "close port requested\n");
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
-
- /* Message size sanity check */
- if (sizeof (struct GNUNET_CADET_PortMessage) != ntohs (message->size))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- pmsg = (struct GNUNET_CADET_PortMessage *) message;
- removed = GNUNET_CONTAINER_multihashmap_remove (c->ports, &pmsg->port, c);
- GNUNET_break_op (GNUNET_YES == removed);
- removed = GNUNET_CONTAINER_multihashmap_remove (ports, &pmsg->port, c);
- GNUNET_break_op (GNUNET_YES == removed);
-
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for requests of new channels.
- *
- * @param cls Closure.
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct CadetClient *c;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
-
- /* Message size sanity check */
- if (sizeof (struct GNUNET_CADET_LocalChannelCreateMessage)
- != ntohs (message->size))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- if (GNUNET_OK !=
- GCCH_handle_local_create (c,
- (struct GNUNET_CADET_LocalChannelCreateMessage *)
- message))
- {
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for requests of deleting tunnels
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
- struct CadetClient *c;
- struct CadetChannel *ch;
- struct GNUNET_CADET_ClientChannelNumber ccn;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n");
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
-
- /* Message sanity check */
- if (sizeof (struct GNUNET_CADET_LocalChannelDestroyMessage)
- != ntohs (message->size))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- msg = (const struct GNUNET_CADET_LocalChannelDestroyMessage *) message;
-
- /* Retrieve tunnel */
- ccn = msg->ccn;
- ch = GML_channel_get (c, ccn);
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Client %u is destroying channel %X\n",
- c->id, ccn);
-
- if (NULL == ch)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, " channel %X not found\n", ccn);
- GNUNET_STATISTICS_update (stats,
- "# client destroy messages on unknown channel",
- 1, GNUNET_NO);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
- }
-
- GCCH_handle_local_destroy (ch,
- c,
- ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
-
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for client traffic
- *
- * @param cls closure
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_data (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct GNUNET_MessageHeader *payload;
- struct GNUNET_CADET_LocalData *msg;
- struct CadetClient *c;
- struct CadetChannel *ch;
- struct GNUNET_CADET_ClientChannelNumber ccn;
- size_t message_size;
- size_t payload_size;
- size_t payload_claimed_size;
- int fwd;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client\n");
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- /* Sanity check for message size */
- message_size = ntohs (message->size);
- if (sizeof (struct GNUNET_CADET_LocalData)
- + sizeof (struct GNUNET_MessageHeader) > message_size
- || GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < message_size)
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- /* Sanity check for payload size */
- payload_size = message_size - sizeof (struct GNUNET_CADET_LocalData);
- msg = (struct GNUNET_CADET_LocalData *) message;
- payload = (struct GNUNET_MessageHeader *) &msg[1];
- payload_claimed_size = ntohs (payload->size);
- if (sizeof (struct GNUNET_MessageHeader) > payload_claimed_size
- || GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size
- || payload_claimed_size > payload_size)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "client claims to send %u bytes in %u payload\n",
- payload_claimed_size, payload_size);
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- ccn = msg->ccn;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes (%u payload) by client %u\n",
- payload_size, payload_claimed_size, c->id);
-
- /* Channel exists? */
- fwd = ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
- ch = GML_channel_get (c, ccn);
- if (NULL == ch)
- {
- GNUNET_STATISTICS_update (stats,
- "# client data messages on unknown channel",
- 1, GNUNET_NO);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
- }
-
- if (GNUNET_OK != GCCH_handle_local_data (ch, c, fwd, payload, payload_size))
- {
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-
- return;
-}
-
-
-/**
- * Handler for client's ACKs for payload traffic.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct GNUNET_CADET_LocalAck *msg;
- struct CadetChannel *ch;
- struct CadetClient *c;
- struct GNUNET_CADET_ClientChannelNumber ccn;
- int fwd;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
-
- msg = (struct GNUNET_CADET_LocalAck *) message;
-
- /* Channel exists? */
- ccn = msg->ccn;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n",
- ntohl (ccn.channel_of_client));
- ch = GML_channel_get (c, ccn);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch);
- if (NULL == ch)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Channel %X unknown.\n",
- ntohl (ccn.channel_of_client));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id);
- GNUNET_STATISTICS_update (stats,
- "# client ack messages on unknown channel",
- 1, GNUNET_NO);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
- }
-
- /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */
- /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */
- fwd = ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
-
- GCCH_handle_local_ack (ch, fwd);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Iterator over all peers to send a monitoring client info about each peer.
- *
- * @param cls Closure ().
- * @param peer Peer ID (tunnel remote peer).
- * @param value Peer info.
- *
- * @return #GNUNET_YES, to keep iterating.
- */
-static int
-get_all_peers_iterator (void *cls,
- const struct GNUNET_PeerIdentity * peer,
- void *value)
-{
- struct GNUNET_SERVER_Client *client = cls;
- struct CadetPeer *p = value;
- struct GNUNET_CADET_LocalInfoPeer msg;
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
- msg.destination = *peer;
- msg.paths = htons (GCP_count_paths (p));
- msg.tunnel = htons (NULL != GCP_get_tunnel (p));
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n",
- GNUNET_i2s (peer));
-
- GNUNET_SERVER_notification_context_unicast (nc, client,
- &msg.header, GNUNET_NO);
- return GNUNET_YES;
-}
-
-
-/**
- * Iterator over all peers to dump info for each peer.
- *
- * @param cls Closure (unused).
- * @param peer Peer ID (tunnel remote peer).
- * @param value Peer info.
- *
- * @return #GNUNET_YES, to keep iterating.
- */
-static int
-show_peer_iterator (void *cls,
- const struct GNUNET_PeerIdentity * peer,
- void *value)
-{
- struct CadetPeer *p = value;
- struct CadetTunnel *t;
-
- t = GCP_get_tunnel (p);
- if (NULL != t)
- GCT_debug (t, GNUNET_ERROR_TYPE_ERROR);
-
- LOG (GNUNET_ERROR_TYPE_ERROR, "\n");
-
- return GNUNET_YES;
-}
-
-
-/**
- * Iterator over all paths of a peer to build an InfoPeer message.
- *
- * Message contains blocks of peers, first not included.
- *
- * @param cls Closure (message to build).
- * @param peer Peer this path is towards.
- * @param path Path itself
- * @return #GNUNET_YES if should keep iterating.
- * #GNUNET_NO otherwise.
- */
-static int
-path_info_iterator (void *cls,
- struct CadetPeer *peer,
- struct CadetPeerPath *path)
-{
- struct GNUNET_CADET_LocalInfoPeer *resp = cls;
- struct GNUNET_PeerIdentity *id;
- uint16_t msg_size;
- uint16_t path_size;
- unsigned int i;
-
- msg_size = ntohs (resp->header.size);
- path_size = sizeof (struct GNUNET_PeerIdentity) * (path->length - 1);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Info Path %u\n", path->length);
- if (msg_size + path_size > UINT16_MAX)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, "path too long for info message\n");
- return GNUNET_NO;
- }
-
- i = msg_size - sizeof (struct GNUNET_CADET_LocalInfoPeer);
- i = i / sizeof (struct GNUNET_PeerIdentity);
-
- /* Set id to the address of the first free peer slot. */
- id = (struct GNUNET_PeerIdentity *) &resp[1];
- id = &id[i];
-
- /* Don't copy first peers.
- * First peer is always the local one.
- * Last peer is always the destination (leave as 0, EOL).
- */
- for (i = 0; i < path->length - 1; i++)
- {
- GNUNET_PEER_resolve (path->peers[i + 1], &id[i]);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&id[i]));
- }
-
- resp->header.size = htons (msg_size + path_size);
-
- return GNUNET_YES;
-}
-
-
-/**
- * Handler for client's INFO PEERS request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_get_peers (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct CadetClient *c;
- struct GNUNET_MessageHeader reply;
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received get peers request from client %u (%p)\n",
- c->id, client);
-
- GCP_iterate_all (get_all_peers_iterator, client);
- reply.size = htons (sizeof (reply));
- reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
- GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Get peers request from client %u completed\n", c->id);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for client's SHOW_PEER request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-void
-handle_show_peer (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct GNUNET_CADET_LocalInfo *msg;
- struct GNUNET_CADET_LocalInfoPeer *resp;
- struct CadetPeer *p;
- struct CadetClient *c;
- unsigned char cbuf[64 * 1024];
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- msg = (struct GNUNET_CADET_LocalInfo *) message;
- resp = (struct GNUNET_CADET_LocalInfoPeer *) cbuf;
- LOG (GNUNET_ERROR_TYPE_INFO,
- "Received peer info request from client %u for peer %s\n",
- c->id, GNUNET_i2s_full (&msg->peer));
-
- resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
- resp->header.size = htons (sizeof (struct GNUNET_CADET_LocalInfoPeer));
- resp->destination = msg->peer;
- p = GCP_get (&msg->peer, GNUNET_NO);
- if (NULL == p)
- {
- /* We don't know the peer */
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Peer %s unknown\n",
- GNUNET_i2s_full (&msg->peer));
- resp->paths = htons (0);
- resp->tunnel = htons (NULL != GCP_get_tunnel (p));
-
- GNUNET_SERVER_notification_context_unicast (nc, client,
- &resp->header,
- GNUNET_NO);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
- }
-
- resp->paths = htons (GCP_count_paths (p));
- resp->tunnel = htons (NULL != GCP_get_tunnel (p));
- GCP_iterate_paths (p, &path_info_iterator, resp);
-
- GNUNET_SERVER_notification_context_unicast (nc, c->handle,
- &resp->header, GNUNET_NO);
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Show peer from client %u completed.\n", c->id);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Iterator over all tunnels to send a monitoring client info about each tunnel.
- *
- * @param cls Closure ().
- * @param peer Peer ID (tunnel remote peer).
- * @param value Tunnel info.
- *
- * @return #GNUNET_YES, to keep iterating.
- */
-static int
-get_all_tunnels_iterator (void *cls,
- const struct GNUNET_PeerIdentity * peer,
- void *value)
-{
- struct GNUNET_SERVER_Client *client = cls;
- struct CadetTunnel *t = value;
- struct GNUNET_CADET_LocalInfoTunnel msg;
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
- msg.destination = *peer;
- msg.channels = htonl (GCT_count_channels (t));
- msg.connections = htonl (GCT_count_any_connections (t));
- msg.cstate = htons ((uint16_t) GCT_get_cstate (t));
- msg.estate = htons ((uint16_t) GCT_get_estate (t));
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n",
- GNUNET_i2s (peer));
-
- GNUNET_SERVER_notification_context_unicast (nc, client,
- &msg.header, GNUNET_NO);
- return GNUNET_YES;
-}
-
-
-/**
- * Handler for client's INFO TUNNELS request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-static void
-handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct CadetClient *c;
- struct GNUNET_MessageHeader reply;
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received get tunnels request from client %u (%p)\n",
- c->id, client);
-
- GCT_iterate_all (get_all_tunnels_iterator, client);
- reply.size = htons (sizeof (reply));
- reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
- GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Get tunnels request from client %u completed\n", c->id);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-static void
-iter_connection (void *cls, struct CadetConnection *c)
-{
- struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
- struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
-
- h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
- h[msg->connections] = *(GCC_get_id (c));
- msg->connections++;
-}
-
-static void
-iter_channel (void *cls, struct CadetChannel *ch)
-{
- struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
- struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
- struct GNUNET_CADET_ChannelTunnelNumber *chn = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections];
-
- chn[msg->channels] = GCCH_get_id (ch);
- msg->channels++;
-}
-
-
-/**
- * Handler for client's SHOW_TUNNEL request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-void
-handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- const struct GNUNET_CADET_LocalInfo *msg;
- struct GNUNET_CADET_LocalInfoTunnel *resp;
- struct CadetClient *c;
- struct CadetTunnel *t;
- unsigned int ch_n;
- unsigned int c_n;
- size_t size;
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- msg = (struct GNUNET_CADET_LocalInfo *) message;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received tunnel info request from client %u for tunnel %s\n",
- c->id, GNUNET_i2s_full(&msg->peer));
-
- t = GCP_get_tunnel (GCP_get (&msg->peer, GNUNET_NO));
- if (NULL == t)
- {
- /* We don't know the tunnel */
- struct GNUNET_CADET_LocalInfoTunnel warn;
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n",
- GNUNET_i2s_full(&msg->peer), sizeof (warn));
- warn.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
- warn.header.size = htons (sizeof (warn));
- warn.destination = msg->peer;
- warn.channels = htonl (0);
- warn.connections = htonl (0);
- warn.cstate = htons (0);
- warn.estate = htons (0);
-
- GNUNET_SERVER_notification_context_unicast (nc, client,
- &warn.header,
- GNUNET_NO);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
- return;
- }
-
- /* Initialize context */
- ch_n = GCT_count_channels (t);
- c_n = GCT_count_any_connections (t);
-
- size = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
- size += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
- size += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
-
- resp = GNUNET_malloc (size);
- resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
- resp->header.size = htons (size);
- resp->destination = msg->peer;
- /* Do not interleave with iterators, iter_channel needs conn in HBO */
- GCT_iterate_connections (t, &iter_connection, resp);
- GCT_iterate_channels (t, &iter_channel, resp);
- resp->connections = htonl (resp->connections);
- resp->channels = htonl (resp->channels);
- /* Do not interleave end */
- resp->cstate = htons (GCT_get_cstate (t));
- resp->estate = htons (GCT_get_estate (t));
- GNUNET_SERVER_notification_context_unicast (nc, c->handle,
- &resp->header, GNUNET_NO);
- GNUNET_free (resp);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Show tunnel request from client %u completed. %u conn, %u ch\n",
- c->id, c_n, ch_n);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handler for client's INFO_DUMP request.
- *
- * @param cls Closure (unused).
- * @param client Identification of the client.
- * @param message The actual message.
- */
-void
-handle_info_dump (void *cls, struct GNUNET_SERVER_Client *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct CadetClient *c;
-
- /* Sanity check for client registration */
- if (NULL == (c = GML_client_get (client)))
- {
- GNUNET_break (0);
- GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Received dump info request from client %u\n",
- c->id);
- LOG (GNUNET_ERROR_TYPE_ERROR,
- "*************************** DUMP START ***************************\n");
-
- for (c = clients_head; NULL != c; c = c->next)
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, "Client %u (%p), handle: %p\n",
- c->id, c, c->handle);
- if (NULL != c->ports)
- LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u ports registered\n",
- GNUNET_CONTAINER_multihashmap_size (c->ports));
- else
- LOG (GNUNET_ERROR_TYPE_ERROR, "\t no ports registered\n");
- LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u own channles\n",
- GNUNET_CONTAINER_multihashmap32_size (c->own_channels));
- LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u incoming channles\n",
- GNUNET_CONTAINER_multihashmap32_size (c->incoming_channels));
- }
- LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n");
- GCP_iterate_all (&show_peer_iterator, NULL);
-
- LOG (GNUNET_ERROR_TYPE_ERROR,
- "**************************** DUMP END ****************************\n");
-
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Functions to handle messages from clients
- */
-static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
- {&handle_port_open, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
- sizeof (struct GNUNET_CADET_PortMessage)},
- {&handle_port_close, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
- sizeof (struct GNUNET_CADET_PortMessage)},
- {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
- sizeof (struct GNUNET_CADET_LocalChannelCreateMessage)},
- {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
- sizeof (struct GNUNET_CADET_LocalChannelDestroyMessage)},
- {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0},
- {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
- sizeof (struct GNUNET_CADET_LocalAck)},
- {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
- sizeof (struct GNUNET_MessageHeader)},
- {&handle_show_peer, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
- sizeof (struct GNUNET_CADET_LocalInfo)},
- {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
- sizeof (struct GNUNET_MessageHeader)},
- {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
- sizeof (struct GNUNET_CADET_LocalInfo)},
- {&handle_info_dump, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP,
- sizeof (struct GNUNET_MessageHeader)},
- {NULL, NULL, 0, 0}
-};
-
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Initialize server subsystem.
- *
- * @param handle Server handle.
- */
-void
-GML_init (struct GNUNET_SERVER_Handle *handle)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
- server_handle = handle;
- GNUNET_SERVER_suspend (server_handle);
- ports = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO);
-}
-
-
-/**
- * Install server (service) handlers and start listening to clients.
- */
-void
-GML_start (void)
-{
- GNUNET_SERVER_add_handlers (server_handle, client_handlers);
- GNUNET_SERVER_connect_notify (server_handle, &handle_client_connect, NULL);
- GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
- NULL);
- nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
-
- clients_head = NULL;
- clients_tail = NULL;
- next_client_id = 0;
- GNUNET_SERVER_resume (server_handle);
-}
-
-
-/**
- * Shutdown server.
- */
-void
-GML_shutdown (void)
-{
- struct CadetClient *c;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down local\n");
-
- for (c = clients_head; NULL != clients_head; c = clients_head)
- client_destroy (c);
-
- if (nc != NULL)
- {
- GNUNET_SERVER_notification_context_destroy (nc);
- nc = NULL;
- }
-
-}
-
-
-/**
- * Get a channel from a client.
- *
- * @param c Client to check.
- * @param ccn Channel ID, must be local (> 0x800...).
- *
- * @return non-NULL if channel exists in the clients lists
- */
-struct CadetChannel *
-GML_channel_get (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn)
-{
- struct GNUNET_CONTAINER_MultiHashMap32 *map;
-
- if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- map = c->own_channels;
- else
- map = c->incoming_channels;
-
- if (NULL == map)
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Client %s does no t have a valid map for CCN %X\n",
- GML_2s (c), ccn);
- return NULL;
- }
- return GNUNET_CONTAINER_multihashmap32_get (map,
- ccn.channel_of_client);
-}
-
-
-/**
- * Add a channel to a client
- *
- * @param client Client.
- * @param ccn Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_add (struct CadetClient *client,
- struct GNUNET_CADET_ClientChannelNumber ccn,
- struct CadetChannel *ch)
-{
- if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- GNUNET_CONTAINER_multihashmap32_put (client->own_channels,
- ccn.channel_of_client,
- ch,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
- else
- GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels,
- ccn.channel_of_client,
- ch,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
-}
-
-
-/**
- * Remove a channel from a client.
- *
- * @param client Client.
- * @param ccn Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_remove (struct CadetClient *client,
- struct GNUNET_CADET_ClientChannelNumber ccn,
- struct CadetChannel *ch)
-{
- if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- GNUNET_CONTAINER_multihashmap32_remove (client->own_channels,
- ccn.channel_of_client,
- ch);
- else
- GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels,
- ccn.channel_of_client,
- ch);
-}
-
-
-/**
- * Get the tunnel's next free local channel ID.
- *
- * @param c Client.
- *
- * @return LID of a channel free to use.
- */
-struct GNUNET_CADET_ClientChannelNumber
-GML_get_next_ccn (struct CadetClient *c)
-{
- struct GNUNET_CADET_ClientChannelNumber ccn;
-
- while (NULL != GML_channel_get (c,
- c->next_ccn))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Channel %u exists...\n",
- c->next_ccn);
- c->next_ccn.channel_of_client
- = htonl (1 + (ntohl (c->next_ccn.channel_of_client)));
- if (ntohl (c->next_ccn.channel_of_client) >=
- GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- c->next_ccn.channel_of_client = htonl (0);
- }
- ccn = c->next_ccn;
- c->next_ccn.channel_of_client
- = htonl (1 + (ntohl (c->next_ccn.channel_of_client)));
-
- return ccn;
-}
-
-
-/**
- * Check if client has registered with the service and has not disconnected
- *
- * @param client the client to check
- *
- * @return non-NULL if client exists in the global DLL
- */
-struct CadetClient *
-GML_client_get (struct GNUNET_SERVER_Client *client)
-{
- if (NULL == client)
- return NULL;
- return GNUNET_SERVER_client_get_user_context (client,
- struct CadetClient);
-}
-
-
-/**
- * Find a client that has opened a port
- *
- * @param port Port to check.
- *
- * @return non-NULL if a client has the port.
- */
-struct CadetClient *
-GML_client_get_by_port (const struct GNUNET_HashCode *port)
-{
- return GNUNET_CONTAINER_multihashmap_get (ports, port);
-}
-
-
-/**
- * Deletes a channel from a client (either owner or destination).
- *
- * @param c Client whose tunnel to delete.
- * @param ch Channel which should be deleted.
- * @param id Channel ID.
- */
-void
-GML_client_delete_channel (struct CadetClient *c,
- struct CadetChannel *ch,
- struct GNUNET_CADET_ClientChannelNumber id)
-{
- int res;
-
- if (ntohl (id.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- {
- res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
- id.channel_of_client,
- ch);
- if (GNUNET_YES != res)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
- }
- else
- {
- res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
- id.channel_of_client,
- ch);
- if (GNUNET_YES != res)
- LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
- }
-}
-
-/**
- * Build a local ACK message and send it to a local client, if needed.
- *
- * If the client was already allowed to send data, do nothing.
- *
- * @param c Client to whom send the ACK.
- * @param ccn Channel ID to use
- */
-void
-GML_send_ack (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn)
-{
- struct GNUNET_CADET_LocalAck msg;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "send local %s ack on %X towards %p\n",
- ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI
- ? "FWD" : "BCK",
- ntohl (ccn.channel_of_client),
- c);
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
- msg.ccn = ccn;
- GNUNET_SERVER_notification_context_unicast (nc,
- c->handle,
- &msg.header,
- GNUNET_NO);
-
-}
-
-
-
-/**
- * Notify the client that a new incoming channel was created.
- *
- * @param c Client to notify.
- * @param ccn Channel ID.
- * @param port Channel's destination port.
- * @param opt Options (bit array).
- * @param peer Origin peer.
- */
-void
-GML_send_channel_create (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn,
- const struct GNUNET_HashCode *port,
- uint32_t opt,
- const struct GNUNET_PeerIdentity *peer)
-{
- struct GNUNET_CADET_LocalChannelCreateMessage msg;
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
- msg.ccn = ccn;
- msg.port = *port;
- msg.opt = htonl (opt);
- msg.peer = *peer;
- GNUNET_SERVER_notification_context_unicast (nc, c->handle,
- &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Build a local channel NACK message and send it to a local client.
- *
- * @param c Client to whom send the NACK.
- * @param ccn Channel ID to use
- */
-void
-GML_send_channel_nack (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn)
-{
- struct GNUNET_CADET_LocalAck msg;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "send local nack on %X towards %p\n",
- ntohl (ccn.channel_of_client),
- c);
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED);
- msg.ccn = ccn;
- GNUNET_SERVER_notification_context_unicast (nc,
- c->handle,
- &msg.header,
- GNUNET_NO);
-
-}
-
-/**
- * Notify a client that a channel is no longer valid.
- *
- * @param c Client.
- * @param ccn ID of the channel that is destroyed.
- */
-void
-GML_send_channel_destroy (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn)
-{
- struct GNUNET_CADET_LocalChannelDestroyMessage msg;
-
- if (NULL == c)
- {
- GNUNET_break (0);
- return;
- }
- if (GNUNET_YES == c->shutting_down)
- return;
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
- msg.ccn = ccn;
- GNUNET_SERVER_notification_context_unicast (nc, c->handle,
- &msg.header, GNUNET_NO);
-}
-
-
-/**
- * Modify the cadet message ID from global to local and send to client.
- *
- * @param c Client to send to.
- * @param msg Message to modify and send.
- * @param ccn Channel ID to use (c can be both owner and client).
- */
-void
-GML_send_data (struct CadetClient *c,
- const struct GNUNET_CADET_ChannelAppDataMessage *msg,
- struct GNUNET_CADET_ClientChannelNumber ccn)
-{
- struct GNUNET_CADET_LocalData *copy;
- uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
- char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)];
-
- if (size < sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break_op (0);
- return;
- }
- if (NULL == c)
- {
- GNUNET_break (0);
- return;
- }
- copy = (struct GNUNET_CADET_LocalData *) cbuf;
- GNUNET_memcpy (©[1], &msg[1], size);
- copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size);
- copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
- copy->ccn = ccn;
- GNUNET_SERVER_notification_context_unicast (nc, c->handle,
- ©->header, GNUNET_NO);
-}
-
-
-/**
- * Get the static string to represent a client.
- *
- * @param c Client.
- *
- * @return Static string for the client.
- */
-const char *
-GML_2s (const struct CadetClient *c)
-{
- static char buf[32];
-
- SPRINTF (buf, "%u", c->id);
- return buf;
-}
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_local.h
- * @brief cadet service; dealing with local clients
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GML (Gnunet Cadet Local)
- */
-
-#ifndef GNUNET_SERVICE_CADET_LOCAL_H
-#define GNUNET_SERVICE_CADET_LOCAL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-/**
- * Struct containing information about a client of the service
- */
-struct CadetClient;
-
-#include "gnunet-service-cadet_channel.h"
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Initialize server subsystem.
- *
- * @param handle Server handle.
- */
-void
-GML_init (struct GNUNET_SERVER_Handle *handle);
-
-/**
- * Install server (service) handlers and start listening to clients.
- */
-void
-GML_start (void);
-
-/**
- * Shutdown server.
- */
-void
-GML_shutdown (void);
-
-/**
- * Get a channel from a client.
- *
- * @param c Client to check.
- * @param ccn Channel ID, must be local (> 0x800...).
- *
- * @return non-NULL if channel exists in the clients lists
- */
-struct CadetChannel *
-GML_channel_get (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber ccn);
-
-/**
- * Add a channel to a client
- *
- * @param client Client.
- * @param ccn Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_add (struct CadetClient *client,
- struct GNUNET_CADET_ClientChannelNumber ccn,
- struct CadetChannel *ch);
-
-/**
- * Remove a channel from a client
- *
- * @param client Client.
- * @param ccn Channel ID.
- * @param ch Channel.
- */
-void
-GML_channel_remove (struct CadetClient *client,
- struct GNUNET_CADET_ClientChannelNumber ccn,
- struct CadetChannel *ch);
-
-/**
- * Get the tunnel's next free local channel ID.
- *
- * @param c Client.
- *
- * @return LID of a channel free to use.
- */
-struct GNUNET_CADET_ClientChannelNumber
-GML_get_next_ccn (struct CadetClient *c);
-
-/**
- * Check if client has registered with the service and has not disconnected
- *
- * @param client the client to check
- *
- * @return non-NULL if client exists in the global DLL
- */
-struct CadetClient *
-GML_client_get (struct GNUNET_SERVER_Client *client);
-
-/**
- * Find a client that has opened a port
- *
- * @param port Port to check.
- *
- * @return non-NULL if a client has the port.
- */
-struct CadetClient *
-GML_client_get_by_port (const struct GNUNET_HashCode *port);
-
-/**
- * Deletes a tunnel from a client (either owner or destination).
- *
- * @param c Client whose tunnel to delete.
- * @param ch Channel which should be deleted.
- * @param id Channel ID.
- */
-void
-GML_client_delete_channel (struct CadetClient *c,
- struct CadetChannel *ch,
- struct GNUNET_CADET_ClientChannelNumber id);
-
-/**
- * Build a local ACK message and send it to a local client, if needed.
- *
- * If the client was already allowed to send data, do nothing.
- *
- * @param c Client to whom send the ACK.
- * @param id Channel ID to use
- */
-void
-GML_send_ack (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber id);
-
-/**
- * Notify the appropriate client that a new incoming channel was created.
- *
- * @param c Client to notify.
- * @param id Channel ID.
- * @param port Channel's destination port.
- * @param opt Options (bit array).
- * @param peer Origin peer.
- */
-void
-GML_send_channel_create (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber id,
- const struct GNUNET_HashCode *port,
- uint32_t opt,
- const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Build a local channel NACK message and send it to a local client.
- *
- * @param c Client to whom send the NACK.
- * @param id Channel ID to use
- */
-void
-GML_send_channel_nack (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber id);
-
-
-/**
- * Notify a client that a channel is no longer valid.
- *
- * @param c Client.
- * @param id ID of the channel that is destroyed.
- */
-void
-GML_send_channel_destroy (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber id);
-
-
-/**
- * Modify the cadet message ID from global to local and send to client.
- *
- * @param c Client to send to.
- * @param msg Message to modify and send.
- * @param id Channel ID to use (c can be both owner and client).
- */
-void
-GML_send_data (struct CadetClient *c,
- const struct GNUNET_CADET_ChannelAppDataMessage *msg,
- struct GNUNET_CADET_ClientChannelNumber id);
-
-/**
- * Get the static string to represent a client.
- *
- * @param c Client.
- *
- * @return Static string for the client.
- */
-const char *
-GML_2s (const struct CadetClient *c);
-
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_LOCAL_H */
-#endif
-/* end of gnunet-cadet-service_LOCAL.h */
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013, 2015 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-/**
- * @file cadet/gnunet-service-cadet_peer.c
- * @brief GNUnet CADET service connection handling
- * @author Bartlomiej Polot
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_transport_service.h"
-#include "gnunet_ats_service.h"
-#include "gnunet_core_service.h"
-#include "gnunet_statistics_service.h"
-#include "cadet_protocol.h"
-#include "gnunet-service-cadet_peer.h"
-#include "gnunet-service-cadet_dht.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_tunnel.h"
-#include "cadet_path.h"
-
-#define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__)
-#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-p2p",__VA_ARGS__)
-
-
-/******************************************************************************/
-/******************************** STRUCTS **********************************/
-/******************************************************************************/
-
-/**
- * Information about a queued message on the peer level.
- */
-struct CadetPeerQueue {
-
- struct CadetPeerQueue *next;
- struct CadetPeerQueue *prev;
-
- /**
- * Envelope to cancel message before MQ sends it.
- */
- struct GNUNET_MQ_Envelope *env;
-
- /**
- * Peer (neighbor) this message is being sent to.
- */
- struct CadetPeer *peer;
-
- /**
- * Continuation to call to notify higher layers about message sent.
- */
- GCP_sent cont;
-
- /**
- * Closure for @a cont.
- */
- void *cont_cls;
-
- /**
- * Task to asynchronously run the drop continuation.
- */
- struct GNUNET_SCHEDULER_Task *drop_task;
-
- /**
- * Time when message was queued for sending.
- */
- struct GNUNET_TIME_Absolute queue_timestamp;
-
- /**
- * #GNUNET_YES if message was management traffic (POLL, ACK, ...).
- */
- int management_traffic;
-
- /**
- * Message type.
- */
- uint16_t type;
-
- /**
- * Message size.
- */
- uint16_t size;
-
- /**
- * Type of the message's payload, if it was encrypted data.
- */
- uint16_t payload_type;
-
- /**
- * ID of the payload (PID, ACK #, ...).
- */
- struct CadetEncryptedMessageIdentifier payload_id;
-
- /**
- * Connection this message was sent on.
- */
- struct CadetConnection *c;
-
- /**
- * Direction in @a c this message was send on (#GNUNET_YES = FWD).
- */
- int c_fwd;
-};
-
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct CadetPeer
-{
- /**
- * ID of the peer
- */
- GNUNET_PEER_Id id;
-
- struct CadetPeerQueue *q_head;
- struct CadetPeerQueue *q_tail;
-
- /**
- * Last time we heard from this peer
- */
- struct GNUNET_TIME_Absolute last_contact;
-
- /**
- * Paths to reach the peer, ordered by ascending hop count
- */
- struct CadetPeerPath *path_head;
-
- /**
- * Paths to reach the peer, ordered by ascending hop count
- */
- struct CadetPeerPath *path_tail;
-
- /**
- * Handle to stop the DHT search for paths to this peer
- */
- struct GCD_search_handle *search_h;
-
- /**
- * Handle to stop the DHT search for paths to this peer
- */
- struct GNUNET_SCHEDULER_Task *search_delayed;
-
- /**
- * Tunnel to this peer, if any.
- */
- struct CadetTunnel *tunnel;
-
- /**
- * Connections that go through this peer; indexed by tid.
- */
- struct GNUNET_CONTAINER_MultiShortmap *connections;
-
- /**
- * Handle for core transmissions.
- */
- struct GNUNET_MQ_Handle *core_mq;
-
- /**
- * How many messages are in the queue to this peer.
- */
- unsigned int queue_n;
-
- /**
- * Hello message.
- */
- struct GNUNET_HELLO_Message* hello;
-
- /**
- * Handle to us offering the HELLO to the transport.
- */
- struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer;
-
- /**
- * Handle to our ATS request asking ATS to suggest an address
- * to TRANSPORT for this peer (to establish a direct link).
- */
- struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion;
-
-};
-
-
-/******************************************************************************/
-/******************************* GLOBALS ***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-/**
- * Local peer own ID (short)
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Peers known, indexed by PeerIdentity, values of type `struct CadetPeer`.
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *peers;
-
-/**
- * How many peers do we want to remember?
- */
-static unsigned long long max_peers;
-
-/**
- * Percentage of messages that will be dropped (for test purposes only).
- */
-static unsigned long long drop_percent;
-
-/**
- * Handle to communicate with CORE.
- */
-static struct GNUNET_CORE_Handle *core_handle;
-
-/**
- * Our configuration;
- */
-static const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-/**
- * Handle to communicate with ATS.
- */
-static struct GNUNET_ATS_ConnectivityHandle *ats_ch;
-
-/**
- * Shutdown falg.
- */
-static int in_shutdown;
-
-
-/******************************************************************************/
-/***************************** CORE HELPERS *********************************/
-/******************************************************************************/
-
-
-/**
- * Iterator to notify all connections of a broken link. Mark connections
- * to destroy after all traffic has been sent.
- *
- * @param cls Closure (disconnected peer).
- * @param key Current key code (peer id).
- * @param value Value in the hash map (connection).
- *
- * @return #GNUNET_YES to continue to iterate.
- */
-static int
-notify_broken (void *cls,
- const struct GNUNET_ShortHashCode *key,
- void *value)
-{
- struct CadetPeer *peer = cls;
- struct CadetConnection *c = value;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Notifying %s due to %s disconnect\n",
- GCC_2s (c), GCP_2s (peer));
- GCC_neighbor_disconnected (c, peer);
- return GNUNET_YES;
-}
-
-
-/**
- * Remove the direct path to the peer.
- *
- * @param peer Peer to remove the direct path from.
- */
-static struct CadetPeerPath *
-pop_direct_path (struct CadetPeer *peer)
-{
- struct CadetPeerPath *iter;
-
- for (iter = peer->path_head; NULL != iter; iter = iter->next)
- {
- if (2 >= iter->length)
- {
- GNUNET_CONTAINER_DLL_remove (peer->path_head,
- peer->path_tail,
- iter);
- return iter;
- }
- }
- return NULL;
-}
-
-/**
- * Call the continuation after a message has been sent or dropped.
- *
- * 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);
-
-
-/******************************************************************************/
-/***************************** CORE CALLBACKS *********************************/
-/******************************************************************************/
-
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls Core closure (unused).
- * @param peer Peer identity this notification is about
- * @param mq Message Queue to this peer.
- *
- * @return Internal closure for handlers (CadetPeer struct).
- */
-static void *
-core_connect_handler (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- struct GNUNET_MQ_Handle *mq)
-{
- struct CadetPeer *neighbor;
- struct CadetPeerPath *path;
- char own_id[16];
-
- GCC_check_connections ();
- GNUNET_snprintf (own_id,
- sizeof (own_id),
- "%s",
- GNUNET_i2s (&my_full_id));
-
- /* Save a path to the neighbor */
- neighbor = GCP_get (peer, GNUNET_YES);
- if (myid == neighbor->id)
- {
- LOG (GNUNET_ERROR_TYPE_INFO,
- "CONNECTED %s (self)\n",
- own_id);
- path = path_new (1);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_INFO,
- "CONNECTED %s <= %s\n",
- own_id,
- GNUNET_i2s (peer));
- path = path_new (2);
- path->peers[1] = neighbor->id;
- GNUNET_PEER_change_rc (neighbor->id, 1);
- GNUNET_assert (NULL == neighbor->core_mq);
- neighbor->core_mq = mq;
- }
- path->peers[0] = myid;
- GNUNET_PEER_change_rc (myid, 1);
- GCP_add_path (neighbor, path, GNUNET_YES);
-
- /* Create the connections hashmap */
- GNUNET_assert (NULL == neighbor->connections);
- neighbor->connections = GNUNET_CONTAINER_multishortmap_create (16,
- GNUNET_YES);
- GNUNET_STATISTICS_update (stats,
- "# peers",
- 1,
- GNUNET_NO);
-
- if ( (NULL != GCP_get_tunnel (neighbor)) &&
- (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer)) )
- {
- GCP_connect (neighbor);
- }
- GCC_check_connections ();
-
- return neighbor;
-}
-
-
-/**
- * Method called whenever a peer disconnects.
- *
- * @param cls Core closure (unused).
- * @param peer Peer identity this notification is about.
- * @param internal_cls Internal closure (CadetPeer struct).
- */
-static void
-core_disconnect_handler (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- void *internal_cls)
-{
- struct CadetPeer *p = internal_cls;
- struct CadetPeerPath *direct_path;
- char own_id[16];
-
- GCC_check_connections ();
- strncpy (own_id, GNUNET_i2s (&my_full_id), 16);
- own_id[15] = '\0';
- if (myid == p->id)
- {
- LOG (GNUNET_ERROR_TYPE_INFO,
- "DISCONNECTED %s (self)\n",
- own_id);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_INFO,
- "DISCONNECTED %s <= %s\n",
- own_id, GNUNET_i2s (peer));
- p->core_mq = NULL;
- }
- direct_path = pop_direct_path (p);
- if (NULL != p->connections)
- {
- GNUNET_CONTAINER_multishortmap_iterate (p->connections,
- ¬ify_broken,
- p);
- GNUNET_CONTAINER_multishortmap_destroy (p->connections);
- p->connections = NULL;
- }
- GNUNET_STATISTICS_update (stats,
- "# peers",
- -1,
- GNUNET_NO);
- path_destroy (direct_path);
- GCC_check_connections ();
-}
-
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-/**
- * Check if the create_connection message has the appropriate size.
- *
- * @param cls Closure (unused).
- * @param msg Message to check.
- *
- * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
- */
-static int
-check_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
-{
- uint16_t size;
-
- size = ntohs (msg->header.size);
- if (size < sizeof (*msg))
- {
- GNUNET_break_op (0);
- return GNUNET_NO;
- }
- return GNUNET_YES;
-}
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_create (peer, msg);
-}
-
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionCreateAckMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_confirm (peer, msg);
-}
-
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBrokenMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_broken (peer, msg);
-}
-
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroyMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_destroy (peer, msg);
-}
-
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_ack (void *cls, const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_ack (peer, msg);
-}
-
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_poll (void *cls, const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_poll (peer, msg);
-}
-
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_kx (void *cls, const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_kx (peer, msg);
-}
-
-
-/**
- * Check if the encrypted message has the appropriate size.
- *
- * @param cls Closure (unused).
- * @param msg Message to check.
- *
- * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise.
- */
-static int
-check_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
-{
- uint16_t size;
- uint16_t minimum_size;
-
- size = ntohs (msg->header.size);
- minimum_size = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)
- + sizeof (struct GNUNET_MessageHeader);
-
- if (size < minimum_size)
- {
- GNUNET_break_op (0);
- return GNUNET_NO;
- }
- return GNUNET_YES;
-}
-
-/**
- * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED.
- *
- * @param cls Closure (CadetPeer for neighbor that sent the message).
- * @param msg Message itself.
- */
-static void
-handle_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
-{
- struct CadetPeer *peer = cls;
- GCC_handle_encrypted (peer, msg);
-}
-
-
-/**
- * To be called on core init/fail.
- *
- * @param cls Closure (config)
- * @param identity The public identity of this peer.
- */
-static void
-core_init_notify (void *cls,
- const struct GNUNET_PeerIdentity *identity);
-
-
-static void
-connect_to_core (const struct GNUNET_CONFIGURATION_Handle *c)
-{
- struct GNUNET_MQ_MessageHandler core_handlers[] = {
- GNUNET_MQ_hd_var_size (create,
- GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE,
- struct GNUNET_CADET_ConnectionCreateMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (confirm,
- GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK,
- struct GNUNET_CADET_ConnectionCreateAckMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (broken,
- GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN,
- struct GNUNET_CADET_ConnectionBrokenMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (destroy,
- GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY,
- struct GNUNET_CADET_ConnectionDestroyMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (ack,
- GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK,
- struct GNUNET_CADET_ConnectionEncryptedAckMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (poll,
- GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL,
- struct GNUNET_CADET_ConnectionHopByHopPollMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (kx,
- GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX,
- struct GNUNET_CADET_TunnelKeyExchangeMessage,
- NULL),
- GNUNET_MQ_hd_var_size (encrypted,
- GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED,
- struct GNUNET_CADET_TunnelEncryptedMessage,
- NULL),
- GNUNET_MQ_handler_end ()
- };
- core_handle = GNUNET_CORE_connect (c, NULL,
- &core_init_notify,
- &core_connect_handler,
- &core_disconnect_handler,
- core_handlers);
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-/**
- * To be called on core init/fail.
- *
- * @param cls Closure (config)
- * @param identity The public identity of this peer.
- */
-static void
-core_init_notify (void *cls,
- const struct GNUNET_PeerIdentity *core_identity)
-{
- const struct GNUNET_CONFIGURATION_Handle *c = cls;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
- if (0 != memcmp (core_identity, &my_full_id, sizeof (my_full_id)))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
- LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (core_identity));
- LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id));
- GNUNET_CORE_disconnect (core_handle);
- connect_to_core (c);
- return;
- }
- GML_start ();
-}
-
-
-/******************************************************************************/
-/******************************** STATIC ***********************************/
-/******************************************************************************/
-
-
-/**
- * Get priority for a queued message.
- *
- * @param q Queued message
- *
- * @return CORE priority to use.
- *
- * FIXME make static
- * FIXME use when sending
- */
-enum GNUNET_CORE_Priority
-get_priority (struct CadetPeerQueue *q)
-{
- enum GNUNET_CORE_Priority low;
- enum GNUNET_CORE_Priority high;
-
- if (NULL == q)
- {
- GNUNET_break (0);
- return GNUNET_CORE_PRIO_BACKGROUND;
- }
-
- /* Relayed traffic has lower priority, our own traffic has higher */
- if (NULL == q->c || GNUNET_NO == GCC_is_origin (q->c, q->c_fwd))
- {
- low = GNUNET_CORE_PRIO_BEST_EFFORT;
- high = GNUNET_CORE_PRIO_URGENT;
- }
- else
- {
- low = GNUNET_CORE_PRIO_URGENT;
- high = GNUNET_CORE_PRIO_CRITICAL_CONTROL;
- }
-
- /* Bulky payload has lower priority, control traffic has higher. */
- if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == q->type)
- return low;
- return high;
-}
-
-
-/**
- * Cancel all messages queued to CORE MQ towards this peer.
- *
- * @param peer Peer towards which to cancel all messages.
- */
-static void
-cancel_queued_messages (struct CadetPeer *peer)
-{
- while (NULL != peer->q_head)
- {
- struct CadetPeerQueue *q;
-
- q = peer->q_head;
- call_peer_cont (q, GNUNET_NO);
- GNUNET_free (q);
- }
-}
-
-
-/**
- * Destroy the peer_info and free any allocated resources linked to it
- *
- * @param peer The peer_info to destroy.
- * @return #GNUNET_OK on success
- */
-static int
-peer_destroy (struct CadetPeer *peer)
-{
- struct GNUNET_PeerIdentity id;
- struct CadetPeerPath *p;
- struct CadetPeerPath *nextp;
-
- GNUNET_PEER_resolve (peer->id, &id);
- GNUNET_PEER_change_rc (peer->id, -1);
-
- LOG (GNUNET_ERROR_TYPE_INFO,
- "destroying peer %s\n",
- GNUNET_i2s (&id));
-
- if (GNUNET_YES !=
- GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_WARNING, " peer not in peermap!!\n");
- }
- GCP_stop_search (peer);
- p = peer->path_head;
- while (NULL != p)
- {
- nextp = p->next;
- GNUNET_CONTAINER_DLL_remove (peer->path_head,
- peer->path_tail,
- p);
- path_destroy (p);
- p = nextp;
- }
- if (NULL != peer->tunnel)
- GCT_destroy_empty (peer->tunnel);
- if (NULL != peer->connections)
- {
- GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (peer->connections));
- GNUNET_CONTAINER_multishortmap_destroy (peer->connections);
- peer->connections = NULL;
- }
- if (NULL != peer->hello_offer)
- {
- GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer);
- peer->hello_offer = NULL;
- }
- if (NULL != peer->connectivity_suggestion)
- {
- GNUNET_ATS_connectivity_suggest_cancel (peer->connectivity_suggestion);
- peer->connectivity_suggestion = NULL;
- }
- cancel_queued_messages (peer);
-
- GNUNET_free_non_null (peer->hello);
- GNUNET_free (peer);
- return GNUNET_OK;
-}
-
-
-/**
- * Iterator over peer hash map entries to destroy the peer during in_shutdown.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return #GNUNET_YES if we should continue to iterate,
- * #GNUNET_NO if not.
- */
-static int
-shutdown_peer (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *value)
-{
- struct CadetPeer *p = value;
- struct CadetTunnel *t = p->tunnel;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, " shutting down %s\n", GCP_2s (p));
- if (NULL != t)
- GCT_destroy (t);
- p->tunnel = NULL;
- peer_destroy (p);
- return GNUNET_YES;
-}
-
-
-/**
- * Check if peer is searching for a path (either active or delayed search).
- *
- * @param peer Peer to check
- * @return #GNUNET_YES if there is a search active.
- * #GNUNET_NO otherwise.
- */
-static int
-is_searching (const struct CadetPeer *peer)
-{
- return ( (NULL == peer->search_h) &&
- (NULL == peer->search_delayed) ) ?
- GNUNET_NO : GNUNET_YES;
-}
-
-
-/**
- * @brief Start a search for a peer.
- *
- * @param cls Closure (Peer to search for).
- */
-static void
-delayed_search (void *cls)
-{
- struct CadetPeer *peer = cls;
-
- peer->search_delayed = NULL;
- GCC_check_connections ();
- GCP_start_search (peer);
- GCC_check_connections ();
-}
-
-
-/**
- * Returns if peer is used (has a tunnel or is neighbor).
- *
- * @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;
-}
-
-
-/**
- * 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 (peer towards a path has been found).
- * @param path Path created from the DHT query. Will be freed afterwards.
- */
-static void
-search_handler (void *cls, const struct CadetPeerPath *path)
-{
- struct CadetPeer *peer = cls;
- unsigned int connection_count;
-
- GCC_check_connections ();
- 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)
- {
- GCC_check_connections ();
- return;
- }
-
- if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (peer->tunnel))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
- GCP_connect (peer);
- }
- GCC_check_connections ();
-}
-
-
-/**
- * Test if a message type is connection management traffic
- * or regular payload traffic.
- *
- * @param type Message type.
- *
- * @return #GNUNET_YES if connection management, #GNUNET_NO otherwise.
- */
-static int
-is_connection_management (uint16_t type)
-{
- return type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK ||
- type == GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL;
-}
-
-
-/**
- * Debug function should NEVER return true in production code, useful to
- * simulate losses for testcases.
- *
- * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
- */
-static int
-should_I_drop (void)
-{
- if (0 == drop_percent)
- return GNUNET_NO;
-
- if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
- return GNUNET_YES;
-
- return GNUNET_NO;
-}
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Call the continuation after a message has been sent or dropped.
- *
- * 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);
-}
-
-
-/**
- * Finish the drop operation.
- *
- * @param cls queue entry to finish drop for
- */
-static void
-drop_cb (void *cls)
-{
- struct CadetPeerQueue *q = cls;
-
- GNUNET_MQ_discard (q->env);
- 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,
- struct CadetEncryptedMessageIdentifier 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),
- ntohl (payload_id.pid),
- 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 (random drop for testing)\n",
- GC_m2s (q->type),
- GC_m2s (q->payload_type),
- ntohl (q->payload_id.pid),
- GCC_2s (c),
- GC_f2s (q->c_fwd));
- q->drop_task = GNUNET_SCHEDULER_add_now (&drop_cb,
- q);
- return q;
- }
- 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)
-{
- if (NULL != q->drop_task)
- {
- GNUNET_SCHEDULER_cancel (q->drop_task);
- q->drop_task = NULL;
- GNUNET_MQ_discard (q->env);
- }
- else
- {
- GNUNET_MQ_send_cancel (q->env);
- }
- call_peer_cont (q, GNUNET_NO);
- 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.
- */
-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_multishortmap_put (peer->connections,
- &GCC_get_id (c)->connection_of_tunnel,
- c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Peer %s has now %u connections.\n",
- GCP_2s (peer),
- GNUNET_CONTAINER_multishortmap_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_multishortmap_contains_value (peer->connections,
- &GCC_get_id (c)->connection_of_tunnel,
- 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_multishortmap_remove (peer->connections,
- &GCC_get_id (c)->connection_of_tunnel,
- c));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Peer %s remains with %u connections.\n",
- GCP_2s (peer),
- GNUNET_CONTAINER_multishortmap_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,
- GCP_get_id (peer),
- 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));
-}
-
-
-/* end of gnunet-service-cadet_peer.c */
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_peer.h
- * @brief cadet service; dealing with remote peers
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMP (Gnunet Cadet Peer)
- */
-
-#ifndef GNUNET_SERVICE_CADET_PEER_H
-#define GNUNET_SERVICE_CADET_PEER_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "cadet_path.h"
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct CadetPeer;
-
-/**
- * Handle to queued messages on a peer level.
- */
-struct CadetPeerQueue;
-
-#include "gnunet-service-cadet_connection.h"
-
-
-/**
- * Callback called when a queued message is sent.
- *
- * @param cls Closure.
- * @param c Connection this message was on.
- * @param fwd Was this a FWD going message?
- * @param sent Was it really sent? (Could have been canceled)
- * @param type Type of message sent.
- * @param payload_type Type of payload, if applicable.
- * @param pid Message ID, or 0 if not applicable (create, destroy, etc).
- * @param size Size of the message.
- * @param wait Time spent waiting for core (only the time for THIS message)
- */
-typedef void
-(*GCP_sent) (void *cls,
- struct CadetConnection *c,
- int fwd,
- int sent,
- uint16_t type,
- uint16_t payload_type,
- struct CadetEncryptedMessageIdentifier pid,
- size_t size,
- struct GNUNET_TIME_Relative wait);
-
-/**
- * Peer path iterator.
- *
- * @param cls Closure.
- * @param peer Peer this path is towards.
- * @param path Path itself
- * @return #GNUNET_YES if should keep iterating.
- * #GNUNET_NO otherwise.
- */
-typedef int
-(*GCP_path_iterator) (void *cls,
- struct CadetPeer *peer,
- struct CadetPeerPath *path);
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Initialize peer subsystem.
- *
- * @param c Configuration.
- */
-void
-GCP_init (const struct GNUNET_CONFIGURATION_Handle *c);
-
-/**
- * Shut down the peer subsystem.
- */
-void
-GCP_shutdown (void);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-/**
- * @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.
- */
-struct CadetPeerQueue *
-GCP_send (struct CadetPeer *peer,
- const struct GNUNET_MessageHeader *message,
- uint16_t payload_type,
- struct CadetEncryptedMessageIdentifier payload_id,
- struct CadetConnection *c,
- int fwd,
- GCP_sent cont,
- void *cont_cls);
-
-/**
- * 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 NOT call the continuation given to #GCP_send.
- *
- * @param q Queue handle to cancel
- */
-void
-GCP_send_cancel (struct CadetPeerQueue *q);
-
-/**
- * Set tunnel.
- *
- * @param peer Peer.
- * @param t Tunnel.
- */
-void
-GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t);
-
-
-/**
- * Check 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);
-
-
-/**
- * Create and initialize a new tunnel towards a peer, in case it has none.
- *
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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 the peer in arg 1.
- * 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 *p,
- int trusted);
-
-
-/**
- * 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);
-
-/**
- * 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);
-
-
-/**
- * Remove any path to the peer that has the extact 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-
-/**
- * Get the hello message.
- *
- * @param peer Peer whose message to get.
- *
- * @return Hello message.
- */
-struct GNUNET_HELLO_Message *
-GCP_get_hello (struct CadetPeer *peer);
-
-
-/**
- * Try to connect to a peer on TRANSPORT level.
- *
- * @param peer Peer to whom to connect.
- */
-void
-GCP_try_connect (struct CadetPeer *peer);
-
-/**
- * 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);
-
-
-/**
- * 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);
-
-/**
- * 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);
-
-
-/**
- * Iterate all known peers.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter,
- void *cls);
-
-
-/**
- * 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);
-
-
-/**
- * Log all kinds of info about a peer.
- *
- * @param peer Peer.
- */
-void
-GCP_debug (const struct CadetPeer *p,
- enum GNUNET_ErrorType level);
-
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_PEER_H */
-#endif
-/* end of gnunet-cadet-service_peer.h */
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013, 2017 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-/**
- * @file cadet/gnunet-service-cadet_tunnel.c
- * @brief logical links between CADET clients
- * @author Bartlomiej Polot
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_signatures.h"
-#include "gnunet_statistics_service.h"
-#include "cadet_protocol.h"
-#include "cadet_path.h"
-#include "gnunet-service-cadet_tunnel.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_peer.h"
-
-#define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__)
-#define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-tun",__VA_ARGS__)
-
-#define REKEY_WAIT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5)
-
-#if !defined(GNUNET_CULL_LOGGING)
- #define DUMP_KEYS_TO_STDERR GNUNET_YES
-#else
- #define DUMP_KEYS_TO_STDERR GNUNET_NO
-#endif
-
-#define MIN_TUNNEL_BUFFER 8
-#define MAX_TUNNEL_BUFFER 64
-#define MAX_SKIPPED_KEYS 64
-#define MAX_KEY_GAP 256
-#define AX_HEADER_SIZE (sizeof (uint32_t) * 2\
- + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey))
-
-/******************************************************************************/
-/******************************** STRUCTS **********************************/
-/******************************************************************************/
-
-struct CadetTChannel
-{
- struct CadetTChannel *next;
- struct CadetTChannel *prev;
- struct CadetChannel *ch;
-};
-
-
-/**
- * Entry in list of connections used by tunnel, with metadata.
- */
-struct CadetTConnection
-{
- /**
- * Next in DLL.
- */
- struct CadetTConnection *next;
-
- /**
- * Prev in DLL.
- */
- struct CadetTConnection *prev;
-
- /**
- * Connection handle.
- */
- struct CadetConnection *c;
-
- /**
- * Creation time, to keep oldest connection alive.
- */
- struct GNUNET_TIME_Absolute created;
-
- /**
- * Connection throughput, to keep fastest connection alive.
- */
- uint32_t throughput;
-};
-
-
-/**
- * Struct to old keys for skipped messages while advancing the Axolotl ratchet.
- */
-struct CadetTunnelSkippedKey
-{
- /**
- * DLL next.
- */
- struct CadetTunnelSkippedKey *next;
-
- /**
- * DLL prev.
- */
- struct CadetTunnelSkippedKey *prev;
-
- /**
- * When was this key stored (for timeout).
- */
- struct GNUNET_TIME_Absolute timestamp;
-
- /**
- * Header key.
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey HK;
-
- /**
- * Message key.
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey MK;
-
- /**
- * Key number for a given HK.
- */
- unsigned int Kn;
-};
-
-
-/**
- * Axolotl data, according to https://github.com/trevp/axolotl/wiki .
- */
-struct CadetTunnelAxolotl
-{
- /**
- * A (double linked) list of stored message keys and associated header keys
- * for "skipped" messages, i.e. messages that have not been
- * received despite the reception of more recent messages, (head).
- */
- struct CadetTunnelSkippedKey *skipped_head;
-
- /**
- * Skipped messages' keys DLL, tail.
- */
- struct CadetTunnelSkippedKey *skipped_tail;
-
- /**
- * Elements in @a skipped_head <-> @a skipped_tail.
- */
- unsigned int skipped;
-
- /**
- * 32-byte root key which gets updated by DH ratchet.
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey RK;
-
- /**
- * 32-byte header key (send).
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey HKs;
-
- /**
- * 32-byte header key (recv)
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey HKr;
-
- /**
- * 32-byte next header key (send).
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey NHKs;
-
- /**
- * 32-byte next header key (recv).
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey NHKr;
-
- /**
- * 32-byte chain keys (used for forward-secrecy updating, send).
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey CKs;
-
- /**
- * 32-byte chain keys (used for forward-secrecy updating, recv).
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey CKr;
-
- /**
- * ECDH for key exchange (A0 / B0).
- */
- struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0;
-
- /**
- * ECDH Ratchet key (send).
- */
- struct GNUNET_CRYPTO_EcdhePrivateKey *DHRs;
-
- /**
- * ECDH Ratchet key (recv).
- */
- struct GNUNET_CRYPTO_EcdhePublicKey DHRr;
-
- /**
- * Message number (reset to 0 with each new ratchet, next message to send).
- */
- uint32_t Ns;
-
- /**
- * Message number (reset to 0 with each new ratchet, next message to recv).
- */
- uint32_t Nr;
-
- /**
- * Previous message numbers (# of msgs sent under prev ratchet)
- */
- uint32_t PNs;
-
- /**
- * True (#GNUNET_YES) if we have to send a new ratchet key in next msg.
- */
- int ratchet_flag;
-
- /**
- * Number of messages recieved since our last ratchet advance.
- * - If this counter = 0, we cannot send a new ratchet key in next msg.
- * - If this counter > 0, we can (but don't yet have to) send a new key.
- */
- unsigned int ratchet_allowed;
-
- /**
- * Number of messages recieved since our last ratchet advance.
- * - If this counter = 0, we cannot send a new ratchet key in next msg.
- * - If this counter > 0, we can (but don't yet have to) send a new key.
- */
- unsigned int ratchet_counter;
-
- /**
- * When does this ratchet expire and a new one is triggered.
- */
- struct GNUNET_TIME_Absolute ratchet_expiration;
-};
-
-
-/**
- * Struct containing all information regarding a tunnel to a peer.
- */
-struct CadetTunnel
-{
- /**
- * Endpoint of the tunnel.
- */
- struct CadetPeer *peer;
-
- /**
- * Axolotl info.
- */
- struct CadetTunnelAxolotl *ax;
-
- /**
- * State of the tunnel connectivity.
- */
- enum CadetTunnelCState cstate;
-
- /**
- * State of the tunnel encryption.
- */
- enum CadetTunnelEState estate;
-
- /**
- * Peer's ephemeral key, to recreate @c e_key and @c d_key when own ephemeral
- * key changes.
- */
- struct GNUNET_CRYPTO_EcdhePublicKey peers_ephemeral_key;
-
- /**
- * Encryption ("our") key. It is only "confirmed" if kx_ctx is NULL.
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
-
- /**
- * Decryption ("their") key. It is only "confirmed" if kx_ctx is NULL.
- */
- struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
-
- /**
- * Task to start the rekey process.
- */
- struct GNUNET_SCHEDULER_Task *rekey_task;
-
- /**
- * Paths that are actively used to reach the destination peer.
- */
- struct CadetTConnection *connection_head;
- struct CadetTConnection *connection_tail;
-
- /**
- * Next connection number.
- */
- uint32_t next_cid;
-
- /**
- * Channels inside this tunnel.
- */
- struct CadetTChannel *channel_head;
- struct CadetTChannel *channel_tail;
-
- /**
- * Channel ID for the next created channel.
- */
- struct GNUNET_CADET_ChannelTunnelNumber next_ctn;
-
- /**
- * Destroy flag: if true, destroy on last message.
- */
- struct GNUNET_SCHEDULER_Task * destroy_task;
-
- /**
- * Queued messages, to transmit once tunnel gets connected.
- */
- struct CadetTunnelDelayed *tq_head;
- struct CadetTunnelDelayed *tq_tail;
-
- /**
- * Task to trim connections if too many are present.
- */
- struct GNUNET_SCHEDULER_Task * trim_connections_task;
-
- /**
- * Ephemeral message in the queue (to avoid queueing more than one).
- */
- struct CadetConnectionQueue *ephm_h;
-
- /**
- * Pong message in the queue.
- */
- struct CadetConnectionQueue *pong_h;
-};
-
-
-/**
- * Struct used to save messages in a non-ready tunnel to send once connected.
- */
-struct CadetTunnelDelayed
-{
- /**
- * DLL
- */
- struct CadetTunnelDelayed *next;
- struct CadetTunnelDelayed *prev;
-
- /**
- * Tunnel.
- */
- struct CadetTunnel *t;
-
- /**
- * Tunnel queue given to the channel to cancel request. Update on send_queued.
- */
- struct CadetTunnelQueue *tq;
-
- /**
- * Message to send.
- */
- /* struct GNUNET_MessageHeader *msg; */
-};
-
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetTunnelQueue
-{
- /**
- * Connection queue handle, to cancel if necessary.
- */
- struct CadetConnectionQueue *cq;
-
- /**
- * Handle in case message hasn't been given to a connection yet.
- */
- struct CadetTunnelDelayed *tqd;
-
- /**
- * Continuation to call once sent.
- */
- GCT_sent cont;
-
- /**
- * Closure for @c cont.
- */
- void *cont_cls;
-};
-
-
-/******************************************************************************/
-/******************************* GLOBALS ***********************************/
-/******************************************************************************/
-
-/**
- * Global handle to the statistics service.
- */
-extern struct GNUNET_STATISTICS_Handle *stats;
-
-/**
- * Local peer own ID (memory efficient handle).
- */
-extern GNUNET_PEER_Id myid;
-
-/**
- * Local peer own ID (full value).
- */
-extern struct GNUNET_PeerIdentity my_full_id;
-
-
-/**
- * Don't try to recover tunnels if shutting down.
- */
-extern int shutting_down;
-
-
-/**
- * Set of all tunnels, in order to trigger a new exchange on rekey.
- * Indexed by peer's ID.
- */
-static struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
-
-/**
- * Own Peer ID private key.
- */
-const static struct GNUNET_CRYPTO_EddsaPrivateKey *id_key;
-
-
-/******************************** AXOLOTL ************************************/
-
-/**
- * How many messages are needed to trigger a ratchet advance.
- */
-static unsigned long long ratchet_messages;
-
-/**
- * How long until we trigger a ratched advance.
- */
-static struct GNUNET_TIME_Relative ratchet_time;
-
-
-/******************************************************************************/
-/******************************** STATIC ***********************************/
-/******************************************************************************/
-
-/**
- * Get string description for tunnel connectivity state.
- *
- * @param cs Tunnel state.
- *
- * @return String representation.
- */
-static const char *
-cstate2s (enum CadetTunnelCState cs)
-{
- static char buf[32];
-
- switch (cs)
- {
- case CADET_TUNNEL_NEW:
- return "CADET_TUNNEL_NEW";
- case CADET_TUNNEL_SEARCHING:
- return "CADET_TUNNEL_SEARCHING";
- case CADET_TUNNEL_WAITING:
- return "CADET_TUNNEL_WAITING";
- case CADET_TUNNEL_READY:
- return "CADET_TUNNEL_READY";
- case CADET_TUNNEL_SHUTDOWN:
- return "CADET_TUNNEL_SHUTDOWN";
- default:
- SPRINTF (buf, "%u (UNKNOWN STATE)", cs);
- return buf;
- }
- return "";
-}
-
-
-/**
- * Get string description for tunnel encryption state.
- *
- * @param es Tunnel state.
- *
- * @return String representation.
- */
-static const char *
-estate2s (enum CadetTunnelEState es)
-{
- static char buf[32];
-
- switch (es)
- {
- case CADET_TUNNEL_KEY_UNINITIALIZED:
- return "CADET_TUNNEL_KEY_UNINITIALIZED";
- case CADET_TUNNEL_KEY_AX_SENT:
- return "CADET_TUNNEL_KEY_AX_SENT";
- case CADET_TUNNEL_KEY_AX_AUTH_SENT:
- return "CADET_TUNNEL_KEY_AX_AUTH_SENT";
- case CADET_TUNNEL_KEY_OK:
- return "CADET_TUNNEL_KEY_OK";
- case CADET_TUNNEL_KEY_REKEY:
- return "CADET_TUNNEL_KEY_REKEY";
- default:
- SPRINTF (buf, "%u (UNKNOWN STATE)", es);
- return buf;
- }
- return "";
-}
-
-
-/**
- * @brief Check if tunnel is ready to send traffic.
- *
- * Tunnel must be connected and with encryption correctly set up.
- *
- * @param t Tunnel to check.
- *
- * @return #GNUNET_YES if ready, #GNUNET_NO otherwise
- */
-static int
-is_ready (struct CadetTunnel *t)
-{
- int ready;
- int conn_ok;
- int enc_ok;
-
- conn_ok = CADET_TUNNEL_READY == t->cstate;
- enc_ok = CADET_TUNNEL_KEY_OK == t->estate
- || CADET_TUNNEL_KEY_REKEY == t->estate
- || CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate;
- ready = conn_ok && enc_ok;
- ready = ready || GCT_is_loopback (t);
- return ready;
-}
-
-
-/**
- * Get the channel's buffer. ONLY FOR NON-LOOPBACK CHANNELS!!
- *
- * @param tch Tunnel's channel handle.
- *
- * @return Amount of messages the channel can still buffer towards the client.
- */
-static unsigned int
-get_channel_buffer (const struct CadetTChannel *tch)
-{
- int fwd;
-
- /* If channel is incoming, is terminal in the FWD direction and fwd is YES */
- fwd = GCCH_is_terminal (tch->ch, GNUNET_YES);
-
- return GCCH_get_buffer (tch->ch, fwd);
-}
-
-
-/**
- * Get the channel's allowance status.
- *
- * @param tch Tunnel's channel handle.
- *
- * @return #GNUNET_YES if we allowed the client to send data to us.
- */
-static int
-get_channel_allowed (const struct CadetTChannel *tch)
-{
- int fwd;
-
- /* If channel is outgoing, is origin in the FWD direction and fwd is YES */
- fwd = GCCH_is_origin (tch->ch, GNUNET_YES);
-
- return GCCH_get_allowed (tch->ch, fwd);
-}
-
-
-/**
- * Get the connection's buffer.
- *
- * @param tc Tunnel's connection handle.
- *
- * @return Amount of messages the connection can still buffer.
- */
-static unsigned int
-get_connection_buffer (const struct CadetTConnection *tc)
-{
- int fwd;
-
- /* If connection is outgoing, is origin in the FWD direction and fwd is YES */
- fwd = GCC_is_origin (tc->c, GNUNET_YES);
-
- return GCC_get_buffer (tc->c, fwd);
-}
-
-
-/**
- * Get the connection's allowance.
- *
- * @param tc Tunnel's connection handle.
- *
- * @return Amount of messages we have allowed the next peer to send us.
- */
-static unsigned int
-get_connection_allowed (const struct CadetTConnection *tc)
-{
- int fwd;
-
- /* If connection is outgoing, is origin in the FWD direction and fwd is YES */
- fwd = GCC_is_origin (tc->c, GNUNET_YES);
-
- return GCC_get_allowed (tc->c, fwd);
-}
-
-
-/**
- * Create a new Axolotl ephemeral (ratchet) key.
- *
- * @param t Tunnel.
- */
-static void
-new_ephemeral (struct CadetTunnel *t)
-{
- GNUNET_free_non_null (t->ax->DHRs);
- t->ax->DHRs = GNUNET_CRYPTO_ecdhe_key_create();
- #if DUMP_KEYS_TO_STDERR
- {
- struct GNUNET_CRYPTO_EcdhePublicKey pub;
- GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &pub);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " new DHRs generated: pub %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &pub));
- }
- #endif
-}
-
-
-/**
- * Calculate HMAC.
- *
- * @param plaintext Content to HMAC.
- * @param size Size of @c plaintext.
- * @param iv Initialization vector for the message.
- * @param key Key to use.
- * @param hmac[out] Destination to store the HMAC.
- */
-static void
-t_hmac (const void *plaintext, size_t size,
- uint32_t iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *key,
- struct GNUNET_ShortHashCode *hmac)
-{
- static const char ctx[] = "cadet authentication key";
- struct GNUNET_CRYPTO_AuthKey auth_key;
- struct GNUNET_HashCode hash;
-
-#if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_INFO, " HMAC %u bytes with key %s\n", size,
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) key));
-#endif
- GNUNET_CRYPTO_hmac_derive_key (&auth_key, key,
- &iv, sizeof (iv),
- key, sizeof (*key),
- ctx, sizeof (ctx),
- NULL);
- /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */
- GNUNET_CRYPTO_hmac (&auth_key, plaintext, size, &hash);
- GNUNET_memcpy (hmac, &hash, sizeof (*hmac));
-}
-
-
-/**
- * Perform a HMAC.
- *
- * @param key Key to use.
- * @param hash[out] Resulting HMAC.
- * @param source Source key material (data to HMAC).
- * @param len Length of @a source.
- */
-static void
-t_ax_hmac_hash (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
- struct GNUNET_HashCode *hash,
- void *source, unsigned int len)
-{
- static const char ctx[] = "axolotl HMAC-HASH";
- struct GNUNET_CRYPTO_AuthKey auth_key;
-
- GNUNET_CRYPTO_hmac_derive_key (&auth_key, key,
- ctx, sizeof (ctx),
- NULL);
- GNUNET_CRYPTO_hmac (&auth_key, source, len, hash);
-}
-
-
-/**
- * Derive a key from a HMAC-HASH.
- *
- * @param key Key to use for the HMAC.
- * @param out Key to generate.
- * @param source Source key material (data to HMAC).
- * @param len Length of @a source.
- */
-static void
-t_hmac_derive_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key,
- struct GNUNET_CRYPTO_SymmetricSessionKey *out,
- void *source, unsigned int len)
-{
- static const char ctx[] = "axolotl derive key";
- struct GNUNET_HashCode h;
-
- t_ax_hmac_hash (key, &h, source, len);
- GNUNET_CRYPTO_kdf (out, sizeof (*out), ctx, sizeof (ctx),
- &h, sizeof (h), NULL);
-}
-
-
-/**
- * Encrypt data with the axolotl tunnel key.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the encrypted data.
- * @param src Source of the plaintext. Can overlap with @c dst.
- * @param size Size of the plaintext.
- *
- * @return Size of the encrypted data.
- */
-static int
-t_ax_encrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size)
-{
- struct GNUNET_CRYPTO_SymmetricSessionKey MK;
- struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
- struct CadetTunnelAxolotl *ax;
- size_t out_size;
-
- CADET_TIMING_START;
-
- ax = t->ax;
- ax->ratchet_counter++;
- if (GNUNET_YES == ax->ratchet_allowed
- && (ratchet_messages <= ax->ratchet_counter
- || 0 == GNUNET_TIME_absolute_get_remaining (ax->ratchet_expiration).rel_value_us))
- {
- ax->ratchet_flag = GNUNET_YES;
- }
-
- if (GNUNET_YES == ax->ratchet_flag)
- {
- /* Advance ratchet */
- struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
- struct GNUNET_HashCode dh;
- struct GNUNET_HashCode hmac;
- static const char ctx[] = "axolotl ratchet";
-
- new_ephemeral (t);
- ax->HKs = ax->NHKs;
-
- /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
- GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, &ax->DHRr, &dh);
- t_ax_hmac_hash (&ax->RK, &hmac, &dh, sizeof (dh));
- GNUNET_CRYPTO_kdf (keys, sizeof (keys), ctx, sizeof (ctx),
- &hmac, sizeof (hmac), NULL);
- ax->RK = keys[0];
- ax->NHKs = keys[1];
- ax->CKs = keys[2];
-
- ax->PNs = ax->Ns;
- ax->Ns = 0;
- ax->ratchet_flag = GNUNET_NO;
- ax->ratchet_allowed = GNUNET_NO;
- ax->ratchet_counter = 0;
- ax->ratchet_expiration =
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), ratchet_time);
- }
-
- t_hmac_derive_key (&ax->CKs, &MK, "0", 1);
- GNUNET_CRYPTO_symmetric_derive_iv (&iv, &MK, NULL, 0, NULL);
-
- #if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_DEBUG, " CKs: %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKs));
- LOG (GNUNET_ERROR_TYPE_INFO, " AX_ENC with key %u: %s\n", ax->Ns,
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &MK));
- #endif
-
- out_size = GNUNET_CRYPTO_symmetric_encrypt (src, size, &MK, &iv, dst);
- t_hmac_derive_key (&ax->CKs, &ax->CKs, "1", 1);
-
- CADET_TIMING_END;
-
- return out_size;
-}
-
-
-/**
- * Decrypt data with the axolotl tunnel key.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the decrypted data.
- * @param src Source of the ciphertext. Can overlap with @c dst.
- * @param size Size of the ciphertext.
- *
- * @return Size of the decrypted data.
- */
-static int
-t_ax_decrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size)
-{
- struct GNUNET_CRYPTO_SymmetricSessionKey MK;
- struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
- struct CadetTunnelAxolotl *ax;
- size_t out_size;
-
- CADET_TIMING_START;
-
- ax = t->ax;
-
- t_hmac_derive_key (&ax->CKr, &MK, "0", 1);
- GNUNET_CRYPTO_symmetric_derive_iv (&iv, &MK, NULL, 0, NULL);
-
- #if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_DEBUG, " CKr: %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKr));
- LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with key %u: %s\n", ax->Nr,
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &MK));
- #endif
-
- GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
- out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, &MK, &iv, dst);
- GNUNET_assert (out_size == size);
-
- t_hmac_derive_key (&ax->CKr, &ax->CKr, "1", 1);
-
- CADET_TIMING_END;
-
- return out_size;
-}
-
-
-/**
- * Encrypt header with the axolotl header key.
- *
- * @param t Tunnel whose key to use.
- * @param msg Message whose header to encrypt.
- */
-static void
-t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_TunnelEncryptedMessage *msg)
-{
- struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
- struct CadetTunnelAxolotl *ax;
- size_t out_size;
-
- CADET_TIMING_START;
- ax = t->ax;
- GNUNET_CRYPTO_symmetric_derive_iv (&iv, &ax->HKs, NULL, 0, NULL);
-
- #if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_INFO, " AX_ENC_H with key %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKs));
- #endif
-
- out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns, AX_HEADER_SIZE,
- &ax->HKs, &iv, &msg->Ns);
-
- GNUNET_assert (AX_HEADER_SIZE == out_size);
- CADET_TIMING_END;
-}
-
-
-/**
- * Decrypt header with the current axolotl header key.
- *
- * @param t Tunnel whose current ax HK to use.
- * @param src Message whose header to decrypt.
- * @param dst Where to decrypt header to.
- */
-static void
-t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_TunnelEncryptedMessage *src,
- struct GNUNET_CADET_TunnelEncryptedMessage *dst)
-{
- struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
- struct CadetTunnelAxolotl *ax;
- size_t out_size;
-
- CADET_TIMING_START;
-
- ax = t->ax;
- GNUNET_CRYPTO_symmetric_derive_iv (&iv, &ax->HKr, NULL, 0, NULL);
-
- #if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC_H with key %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKr));
- #endif
-
- out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE,
- &ax->HKr, &iv, &dst->Ns);
-
- GNUNET_assert (AX_HEADER_SIZE == out_size);
-
- CADET_TIMING_END;
-}
-
-
-/**
- * Decrypt and verify data with the appropriate tunnel key and verify that the
- * data has not been altered since it was sent by the remote peer.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the plaintext.
- * @param src Source of the message. Can overlap with @c dst.
- * @param size Size of the message.
- *
- * @return Size of the decrypted data, -1 if an error was encountered.
- */
-static int
-try_old_ax_keys (struct CadetTunnel *t, void *dst,
- const struct GNUNET_CADET_TunnelEncryptedMessage *src, size_t size)
-{
- struct CadetTunnelSkippedKey *key;
- struct GNUNET_ShortHashCode *hmac;
- struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
- struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
- struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK;
- size_t esize;
- size_t res;
- size_t len;
- unsigned int N;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying old keys\n");
- hmac = &plaintext_header.hmac;
- esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
-
- /* Find a correct Header Key */
- for (key = t->ax->skipped_head; NULL != key; key = key->next)
- {
- #if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Trying hmac with key %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->HK));
- #endif
- t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &key->HK, hmac);
- if (0 == memcmp (hmac, &src->hmac, sizeof (*hmac)))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " hmac correct\n");
- valid_HK = &key->HK;
- break;
- }
- }
- if (NULL == key)
- return -1;
-
- /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */
- GNUNET_assert (size > sizeof (struct GNUNET_CADET_TunnelEncryptedMessage));
- len = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
- GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader));
-
- /* Decrypt header */
- GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->HK, NULL, 0, NULL);
- res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE,
- &key->HK, &iv, &plaintext_header.Ns);
- GNUNET_assert (AX_HEADER_SIZE == res);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " Message %u, previous: %u\n",
- ntohl (plaintext_header.Ns), ntohl (plaintext_header.PNs));
-
- /* Find the correct Message Key */
- N = ntohl (plaintext_header.Ns);
- while (NULL != key && N != key->Kn)
- key = key->next;
- if (NULL == key || 0 != memcmp (&key->HK, valid_HK, sizeof (*valid_HK)))
- return -1;
-
- #if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC_H with skipped key %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->HK));
- LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with skipped key %u: %s\n",
- key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK));
- #endif
-
- /* Decrypt payload */
- GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->MK, NULL, 0, NULL);
- res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], len, &key->MK, &iv, dst);
-
- /* Remove key */
- GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key);
- t->ax->skipped--;
- GNUNET_free (key); /* GNUNET_free overwrites memory with 0xbaadf00d */
-
- return res;
-}
-
-
-/**
- * Delete a key from the list of skipped keys.
- *
- * @param t Tunnel to delete from.
- * @param HKr Header Key to use.
- */
-static void
-store_skipped_key (struct CadetTunnel *t,
- const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr)
-{
- struct CadetTunnelSkippedKey *key;
-
- key = GNUNET_new (struct CadetTunnelSkippedKey);
- key->timestamp = GNUNET_TIME_absolute_get ();
- key->Kn = t->ax->Nr;
- key->HK = t->ax->HKr;
- t_hmac_derive_key (&t->ax->CKr, &key->MK, "0", 1);
- #if DUMP_KEYS_TO_STDERR
- LOG (GNUNET_ERROR_TYPE_DEBUG, " storing MK for Nr %u: %s\n",
- key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " for CKr: %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &t->ax->CKr));
- #endif
- t_hmac_derive_key (&t->ax->CKr, &t->ax->CKr, "1", 1);
- GNUNET_CONTAINER_DLL_insert (t->ax->skipped_head, t->ax->skipped_tail, key);
- t->ax->Nr++;
- t->ax->skipped++;
-}
-
-
-/**
- * Delete a key from the list of skipped keys.
- *
- * @param t Tunnel to delete from.
- * @param key Key to delete.
- */
-static void
-delete_skipped_key (struct CadetTunnel *t, struct CadetTunnelSkippedKey *key)
-{
- GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key);
- GNUNET_free (key);
- t->ax->skipped--;
-}
-
-
-/**
- * Stage skipped AX keys and calculate the message key.
- *
- * Stores each HK and MK for skipped messages.
- *
- * @param t Tunnel where to stage the keys.
- * @param HKr Header key.
- * @param Np Received meesage number.
- *
- * @return GNUNET_OK if keys were stored.
- * GNUNET_SYSERR if an error ocurred (Np not expected).
- */
-static int
-store_ax_keys (struct CadetTunnel *t,
- const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr,
- uint32_t Np)
-{
- int gap;
-
-
- gap = Np - t->ax->Nr;
- LOG (GNUNET_ERROR_TYPE_INFO, "Storing keys [%u, %u)\n", t->ax->Nr, Np);
- if (MAX_KEY_GAP < gap)
- {
- /* Avoid DoS (forcing peer to do 2*33 chain HMAC operations) */
- /* TODO: start new key exchange on return */
- GNUNET_break_op (0);
- LOG (GNUNET_ERROR_TYPE_WARNING, "Got message %u, expected %u+\n",
- Np, t->ax->Nr);
- return GNUNET_SYSERR;
- }
- if (0 > gap)
- {
- /* Delayed message: don't store keys, flag to try old keys. */
- return GNUNET_SYSERR;
- }
-
- while (t->ax->Nr < Np)
- store_skipped_key (t, HKr);
-
- while (t->ax->skipped > MAX_SKIPPED_KEYS)
- delete_skipped_key (t, t->ax->skipped_tail);
-
- return GNUNET_OK;
-}
-
-
-/**
- * Decrypt and verify data with the appropriate tunnel key and verify that the
- * data has not been altered since it was sent by the remote peer.
- *
- * @param t Tunnel whose key to use.
- * @param dst Destination for the plaintext.
- * @param src Source of the message. Can overlap with @c dst.
- * @param size Size of the message.
- *
- * @return Size of the decrypted data, -1 if an error was encountered.
- */
-static int
-t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst,
- const struct GNUNET_CADET_TunnelEncryptedMessage *src,
- size_t size)
-{
- struct CadetTunnelAxolotl *ax;
- struct GNUNET_ShortHashCode msg_hmac;
- struct GNUNET_HashCode hmac;
- struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header;
- uint32_t Np;
- uint32_t PNp;
- size_t esize; /* Size of encryped payload */
- size_t osize; /* Size of output (decrypted payload) */
-
- esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
- ax = t->ax;
- if (NULL == ax)
- return -1;
-
- /* Try current HK */
- t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &ax->HKr, &msg_hmac);
- if (0 != memcmp (&msg_hmac, &src->hmac, sizeof (msg_hmac)))
- {
- static const char ctx[] = "axolotl ratchet";
- struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
- struct GNUNET_CRYPTO_SymmetricSessionKey HK;
- struct GNUNET_HashCode dh;
- struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;
-
- /* Try Next HK */
- LOG (GNUNET_ERROR_TYPE_DEBUG, " trying next HK\n");
- t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &ax->NHKr, &msg_hmac);
- if (0 != memcmp (&msg_hmac, &src->hmac, sizeof (msg_hmac)))
- {
- /* Try the skipped keys, if that fails, we're out of luck. */
- return try_old_ax_keys (t, dst, src, size);
- }
- LOG (GNUNET_ERROR_TYPE_INFO, "next HK worked\n");
-
- HK = ax->HKr;
- ax->HKr = ax->NHKr;
- t_h_decrypt (t, src, &plaintext_header);
- Np = ntohl (plaintext_header.Ns);
- PNp = ntohl (plaintext_header.PNs);
- DHRp = &plaintext_header.DHRs;
- store_ax_keys (t, &HK, PNp);
-
- /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
- GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, DHRp, &dh);
- t_ax_hmac_hash (&ax->RK, &hmac, &dh, sizeof (dh));
- GNUNET_CRYPTO_kdf (keys, sizeof (keys), ctx, sizeof (ctx),
- &hmac, sizeof (hmac), NULL);
-
- /* Commit "purported" keys */
- ax->RK = keys[0];
- ax->NHKr = keys[1];
- ax->CKr = keys[2];
- ax->DHRr = *DHRp;
- ax->Nr = 0;
- ax->ratchet_allowed = GNUNET_YES;
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "current HK\n");
- t_h_decrypt (t, src, &plaintext_header);
- Np = ntohl (plaintext_header.Ns);
- PNp = ntohl (plaintext_header.PNs);
- }
- LOG (GNUNET_ERROR_TYPE_INFO, " got AX Nr %u\n", Np);
- if (Np != ax->Nr)
- if (GNUNET_OK != store_ax_keys (t, &ax->HKr, Np))
- /* Try the skipped keys, if that fails, we're out of luck. */
- return try_old_ax_keys (t, dst, src, size);
-
- osize = t_ax_decrypt (t, dst, &src[1], esize);
- ax->Nr = Np + 1;
-
- if (osize != esize)
- {
- GNUNET_break_op (0);
- return -1;
- }
-
- return osize;
-}
-
-
-/**
- * Pick a connection on which send the next data message.
- *
- * @param t Tunnel on which to send the message.
- *
- * @return The connection on which to send the next message.
- */
-static struct CadetConnection *
-tunnel_get_connection (struct CadetTunnel *t)
-{
- struct CadetTConnection *iter;
- struct CadetConnection *best;
- unsigned int qn;
- unsigned int lowest_q;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n", GCT_2s (t));
- best = NULL;
- lowest_q = UINT_MAX;
- for (iter = t->connection_head; NULL != iter; iter = iter->next)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n",
- GCC_2s (iter->c), GCC_get_state (iter->c));
- if (CADET_CONNECTION_READY == GCC_get_state (iter->c))
- {
- qn = GCC_get_qn (iter->c, GCC_is_origin (iter->c, GNUNET_YES));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " q_n %u, \n", qn);
- if (qn < lowest_q)
- {
- best = iter->c;
- lowest_q = qn;
- }
- }
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GCC_2s (best));
- return best;
-}
-
-
-/**
- * Callback called when a queued message is sent.
- *
- * Calculates the average time and connection packet tracking.
- *
- * @param cls Closure (TunnelQueue handle).
- * @param c Connection this message was on.
- * @param q Connection queue handle (unused).
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-static void
-tun_message_sent (void *cls,
- struct CadetConnection *c,
- struct CadetConnectionQueue *q,
- uint16_t type, int fwd, size_t size)
-{
- struct CadetTunnelQueue *qt = cls;
- struct CadetTunnel *t;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "tun_message_sent\n");
-
- GNUNET_assert (NULL != qt->cont);
- t = NULL == c ? NULL : GCC_get_tunnel (c);
- qt->cont (qt->cont_cls, t, qt, type, size);
- GNUNET_free (qt);
-}
-
-
-static unsigned int
-count_queued_data (const struct CadetTunnel *t)
-{
- struct CadetTunnelDelayed *iter;
- unsigned int count;
-
- for (count = 0, iter = t->tq_head; iter != NULL; iter = iter->next)
- count++;
-
- return count;
-}
-
-/**
- * Delete a queued message: either was sent or the channel was destroyed
- * before the tunnel's key exchange had a chance to finish.
- *
- * @param tqd Delayed queue handle.
- */
-static void
-unqueue_data (struct CadetTunnelDelayed *tqd)
-{
- GNUNET_CONTAINER_DLL_remove (tqd->t->tq_head, tqd->t->tq_tail, tqd);
- GNUNET_free (tqd);
-}
-
-
-/**
- * Cache a message to be sent once tunnel is online.
- *
- * @param t Tunnel to hold the message.
- * @param msg Message itself (copy will be made).
- */
-static struct CadetTunnelDelayed *
-queue_data (struct CadetTunnel *t, const struct GNUNET_MessageHeader *msg)
-{
- struct CadetTunnelDelayed *tqd;
- uint16_t size = ntohs (msg->size);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GCT_2s (t));
-
- GNUNET_assert (GNUNET_NO == is_ready (t));
-
- tqd = GNUNET_malloc (sizeof (struct CadetTunnelDelayed) + size);
-
- tqd->t = t;
- GNUNET_memcpy (&tqd[1], msg, size);
- GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd);
- return tqd;
-}
-
-
-/**
- * Sends an already built message on a tunnel, encrypting it and
- * choosing the best connection.
- *
- * @param message Message to send. Function modifies it.
- * @param t Tunnel on which this message is transmitted.
- * @param c Connection to use (autoselect if NULL).
- * @param force Force the tunnel to take the message (buffer overfill).
- * @param cont Continuation to call once message is really sent.
- * @param cont_cls Closure for @c cont.
- * @param existing_q In case this a transmission of previously queued data,
- * this should be TunnelQueue given to the client.
- * Otherwise, NULL.
- * @return Handle to cancel message.
- * NULL if @c cont is NULL or an error happens and message is dropped.
- */
-static struct CadetTunnelQueue *
-send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- struct CadetTunnel *t,
- struct CadetConnection *c,
- int force,
- GCT_sent cont,
- void *cont_cls,
- struct CadetTunnelQueue *existing_q)
-{
- struct GNUNET_MessageHeader *msg;
- struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
- struct CadetTunnelQueue *tq;
- size_t size = ntohs (message->size);
- char cbuf[sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size] GNUNET_ALIGN;
- size_t esize;
- uint16_t type;
- int fwd;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GCT_2s (t));
-
- if (GNUNET_NO == is_ready (t))
- {
- struct CadetTunnelDelayed *tqd;
- /* A non null existing_q indicates sending of queued data.
- * Should only happen after tunnel becomes ready.
- */
- GNUNET_assert (NULL == existing_q);
- tqd = queue_data (t, message);
- if (NULL == cont)
- return NULL;
- tq = GNUNET_new (struct CadetTunnelQueue);
- tq->tqd = tqd;
- tqd->tq = tq;
- tq->cont = cont;
- tq->cont_cls = cont_cls;
- return tq;
- }
-
- GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
-
- ax_msg = (struct GNUNET_CADET_TunnelEncryptedMessage *) cbuf;
- msg = &ax_msg->header;
- msg->size = htons (sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size);
- msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED);
- esize = t_ax_encrypt (t, &ax_msg[1], message, size);
- ax_msg->Ns = htonl (t->ax->Ns++);
- ax_msg->PNs = htonl (t->ax->PNs);
- GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &ax_msg->DHRs);
- t_h_encrypt (t, ax_msg);
- t_hmac (&ax_msg->Ns, AX_HEADER_SIZE + esize, 0, &t->ax->HKs, &ax_msg->hmac);
- GNUNET_assert (esize == size);
-
- if (NULL == c)
- c = tunnel_get_connection (t);
- if (NULL == c)
- {
- /* Why is tunnel 'ready'? Should have been queued! */
- if (NULL != t->destroy_task)
- {
- GNUNET_break (0);
- GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
- }
- return NULL; /* Drop... */
- }
- fwd = GCC_is_origin (c, GNUNET_YES);
- ax_msg->cid = *GCC_get_id (c);
- ax_msg->cemi = GCC_get_pid (c, fwd);
-
- type = htons (message->type);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Sending message of type %s with CEMI %u and CID %s\n",
- GC_m2s (type),
- htonl (ax_msg->cemi.pid),
- GNUNET_sh2s (&ax_msg->cid.connection_of_tunnel));
-
- if (NULL == cont)
- {
- (void) GCC_send_prebuilt_message (msg,
- type,
- ax_msg->cemi,
- c,
- fwd,
- force, NULL, NULL);
- return NULL;
- }
- if (NULL == existing_q)
- {
- tq = GNUNET_new (struct CadetTunnelQueue); /* FIXME valgrind: leak*/
- }
- else
- {
- tq = existing_q;
- tq->tqd = NULL;
- }
- tq->cont = cont;
- tq->cont_cls = cont_cls;
- tq->cq = GCC_send_prebuilt_message (msg,
- type,
- ax_msg->cemi,
- c,
- fwd,
- force,
- &tun_message_sent, tq);
- GNUNET_assert (NULL != tq->cq);
-
- return tq;
-}
-
-
-/**
- * Send all cached messages that we can, tunnel is online.
- *
- * @param t Tunnel that holds the messages. Cannot be loopback.
- */
-static void
-send_queued_data (struct CadetTunnel *t)
-{
- struct CadetTunnelDelayed *tqd;
- struct CadetTunnelDelayed *next;
- unsigned int room;
-
- LOG (GNUNET_ERROR_TYPE_INFO, "Send queued data, tunnel %s\n", GCT_2s (t));
-
- if (GCT_is_loopback (t))
- {
- GNUNET_break (0);
- return;
- }
-
- if (GNUNET_NO == is_ready (t))
- {
- LOG (GNUNET_ERROR_TYPE_WARNING, " not ready yet: %s/%s\n",
- estate2s (t->estate), cstate2s (t->cstate));
- return;
- }
-
- room = GCT_get_connections_buffer (t);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " tq head: %p\n", t->tq_head);
- for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n");
- next = tqd->next;
- room--;
- send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1],
- tqd->t, NULL, GNUNET_YES,
- NULL != tqd->tq ? tqd->tq->cont : NULL,
- NULL != tqd->tq ? tqd->tq->cont_cls : NULL,
- tqd->tq);
- unqueue_data (tqd);
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GCT_send_queued_data end\n", GCP_2s (t->peer));
-}
-
-
-/**
- * @brief Resend the KX until we complete the handshake.
- *
- * @param cls Closure (tunnel).
- */
-static void
-kx_resend (void *cls)
-{
- struct CadetTunnel *t = cls;
-
- t->rekey_task = NULL;
- if (CADET_TUNNEL_KEY_OK == t->estate)
- {
- /* Should have been canceled on estate change */
- GNUNET_break (0);
- return;
- }
-
- GCT_send_kx (t, CADET_TUNNEL_KEY_AX_SENT >= t->estate);
-}
-
-
-/**
- * Callback called when a queued message is sent.
- *
- * @param cls Closure.
- * @param c Connection this message was on.
- * @param type Type of message sent.
- * @param fwd Was this a FWD going message?
- * @param size Size of the message.
- */
-static void
-ephm_sent (void *cls,
- struct CadetConnection *c,
- struct CadetConnectionQueue *q,
- uint16_t type, int fwd, size_t size)
-{
- struct CadetTunnel *t = cls;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "ephemeral sent %s\n", GC_m2s (type));
-
- t->ephm_h = NULL;
-
- if (CADET_TUNNEL_KEY_OK == t->estate)
- return;
-
- if (NULL != t->rekey_task)
- {
- GNUNET_break (0);
- GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
- GNUNET_SCHEDULER_cancel (t->rekey_task);
- }
- t->rekey_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
- &kx_resend, t);
-
-}
-
-
-/**
- * Called only on shutdown, destroy every tunnel.
- *
- * @param cls Closure (unused).
- * @param key Current public key.
- * @param value Value in the hash map (tunnel).
- *
- * @return #GNUNET_YES, so we should continue to iterate,
- */
-static int
-destroy_iterator (void *cls,
- const struct GNUNET_PeerIdentity *key,
- void *value)
-{
- struct CadetTunnel *t = value;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "GCT_shutdown destroying tunnel at %p\n", t);
- GCT_destroy (t);
- return GNUNET_YES;
-}
-
-
-/**
- * Notify remote peer that we don't know a channel he is talking about,
- * probably CHANNEL_DESTROY was missed.
- *
- * @param t Tunnel on which to notify.
- * @param gid ID of the channel.
- */
-static void
-send_channel_destroy (struct CadetTunnel *t,
- struct GNUNET_CADET_ChannelTunnelNumber gid)
-{
- struct GNUNET_CADET_ChannelManageMessage msg;
-
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
- msg.header.size = htons (sizeof (msg));
- msg.ctn = gid;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "WARNING destroying unknown channel %u on tunnel %s\n",
- ntohl (gid.cn),
- GCT_2s (t));
- send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL);
-}
-
-
-/**
- * Demultiplex data per channel and call appropriate channel handler.
- *
- * @param t Tunnel on which the data came.
- * @param msg Data message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_data (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelAppDataMessage *msg,
- int fwd)
-{
- struct CadetChannel *ch;
- char buf[128];
- size_t size;
- uint16_t type;
-
- /* Check size */
- size = ntohs (msg->header.size);
- if (size <
- sizeof (struct GNUNET_CADET_ChannelAppDataMessage) +
- sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break (0);
- return;
- }
- type = ntohs (msg[1].header.type);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n", GC_m2s (type));
- SPRINTF (buf, "# received payload of type %hu", type);
- GNUNET_STATISTICS_update (stats, buf, 1, GNUNET_NO);
-
-
- /* Check channel */
- ch = GCT_get_channel (t, msg->ctn);
- if (NULL == ch)
- {
- GNUNET_STATISTICS_update (stats,
- "# data on unknown channel",
- 1,
- GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "channel 0x%X unknown\n",
- ntohl (msg->ctn.cn));
- send_channel_destroy (t, msg->ctn);
- return;
- }
-
- GCCH_handle_data (ch, msg, fwd);
-}
-
-
-/**
- * Demultiplex data ACKs per channel and update appropriate channel buffer info.
- *
- * @param t Tunnel on which the DATA ACK came.
- * @param msg DATA ACK message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_data_ack (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelDataAckMessage *msg,
- int fwd)
-{
- struct CadetChannel *ch;
- size_t size;
-
- /* Check size */
- size = ntohs (msg->header.size);
- if (size != sizeof (struct GNUNET_CADET_ChannelDataAckMessage))
- {
- GNUNET_break (0);
- return;
- }
-
- /* Check channel */
- ch = GCT_get_channel (t, msg->ctn);
- if (NULL == ch)
- {
- GNUNET_STATISTICS_update (stats, "# data ack on unknown channel",
- 1, GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
- ntohl (msg->ctn.cn));
- return;
- }
-
- GCCH_handle_data_ack (ch, msg, fwd);
-}
-
-
-/**
- * Handle channel create.
- *
- * @param t Tunnel on which the message came.
- * @param msg ChannelCreate message.
- */
-static void
-handle_ch_create (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelOpenMessage *msg)
-{
- struct CadetChannel *ch;
- size_t size;
-
- /* Check size */
- size = ntohs (msg->header.size);
- if (size != sizeof (struct GNUNET_CADET_ChannelOpenMessage))
- {
- GNUNET_break_op (0);
- return;
- }
-
- /* Check channel */
- ch = GCT_get_channel (t, msg->ctn);
- if (NULL != ch && ! GCT_is_loopback (t))
- {
- /* Probably a retransmission, safe to ignore */
- LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists...\n");
- }
- ch = GCCH_handle_create (t, msg);
- if (NULL != ch)
- GCT_add_channel (t, ch);
-}
-
-
-
-/**
- * Handle channel NACK: check correctness and call channel handler for NACKs.
- *
- * @param t Tunnel on which the NACK came.
- * @param msg NACK message.
- */
-static void
-handle_ch_nack (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelManageMessage *msg)
-{
- struct CadetChannel *ch;
- size_t size;
-
- /* Check size */
- size = ntohs (msg->header.size);
- if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
- {
- GNUNET_break (0);
- return;
- }
-
- /* Check channel */
- ch = GCT_get_channel (t, msg->ctn);
- if (NULL == ch)
- {
- GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel",
- 1, GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "WARNING channel %u unknown\n",
- ntohl (msg->ctn.cn));
- return;
- }
-
- GCCH_handle_nack (ch);
-}
-
-
-/**
- * Handle a CHANNEL ACK (SYNACK/ACK).
- *
- * @param t Tunnel on which the CHANNEL ACK came.
- * @param msg CHANNEL ACK message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_ch_ack (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelManageMessage *msg,
- int fwd)
-{
- struct CadetChannel *ch;
- size_t size;
-
- /* Check size */
- size = ntohs (msg->header.size);
- if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
- {
- GNUNET_break (0);
- return;
- }
-
- /* Check channel */
- ch = GCT_get_channel (t, msg->ctn);
- if (NULL == ch)
- {
- GNUNET_STATISTICS_update (stats,
- "# channel ack on unknown channel",
- 1,
- GNUNET_NO);
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "WARNING channel %u unknown\n",
- ntohl (msg->ctn.cn));
- return;
- }
-
- GCCH_handle_ack (ch, msg, fwd);
-}
-
-
-/**
- * Handle a channel destruction message.
- *
- * @param t Tunnel on which the message came.
- * @param msg Channel destroy message.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_ch_destroy (struct CadetTunnel *t,
- const struct GNUNET_CADET_ChannelManageMessage *msg,
- int fwd)
-{
- struct CadetChannel *ch;
- size_t size;
-
- /* Check size */
- size = ntohs (msg->header.size);
- if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage))
- {
- GNUNET_break (0);
- return;
- }
-
- /* Check channel */
- ch = GCT_get_channel (t, msg->ctn);
- if (NULL == ch)
- {
- /* Probably a retransmission, safe to ignore */
- return;
- }
-
- GCCH_handle_destroy (ch, msg, fwd);
-}
-
-
-/**
- * Free Axolotl data.
- *
- * @param t Tunnel.
- */
-static void
-destroy_ax (struct CadetTunnel *t)
-{
- if (NULL == t->ax)
- return;
-
- GNUNET_free_non_null (t->ax->DHRs);
- GNUNET_free_non_null (t->ax->kx_0);
- while (NULL != t->ax->skipped_head)
- delete_skipped_key (t, t->ax->skipped_head);
- GNUNET_assert (0 == t->ax->skipped);
-
- GNUNET_free (t->ax);
- t->ax = NULL;
-
- if (NULL != t->rekey_task)
- {
- GNUNET_SCHEDULER_cancel (t->rekey_task);
- t->rekey_task = NULL;
- }
- if (NULL != t->ephm_h)
- {
- GCC_cancel (t->ephm_h);
- t->ephm_h = NULL;
- }
-}
-
-
-/**
- * Demultiplex by message type and call appropriate handler for a message
- * towards a channel of a local tunnel.
- *
- * @param t Tunnel this message came on.
- * @param msgh Message header.
- * @param fwd Is this message fwd? This only is meaningful in loopback channels.
- * #GNUNET_YES if message is FWD on the respective channel (loopback)
- * #GNUNET_NO if message is BCK on the respective channel (loopback)
- * #GNUNET_SYSERR if message on a one-ended channel (remote)
- */
-static void
-handle_decrypted (struct CadetTunnel *t,
- const struct GNUNET_MessageHeader *msgh,
- int fwd)
-{
- uint16_t type;
- char buf[256];
-
- type = ntohs (msgh->type);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "<-- %s on %s\n", GC_m2s (type), GCT_2s (t));
- SPRINTF (buf, "# received encrypted of type %hu (%s)", type, GC_m2s (type));
- GNUNET_STATISTICS_update (stats, buf, 1, GNUNET_NO);
-
- switch (type)
- {
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE:
- /* Do nothing, connection aleady got updated. */
- GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA:
- /* Don't send hop ACK, wait for client to ACK */
- handle_data (t, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK:
- handle_data_ack (t, (struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
- handle_ch_create (t, (struct GNUNET_CADET_ChannelOpenMessage *) msgh);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED:
- handle_ch_nack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK:
- handle_ch_ack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
- break;
-
- case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
- handle_ch_destroy (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd);
- break;
-
- default:
- GNUNET_break_op (0);
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "end-to-end message not known (%u)\n",
- ntohs (msgh->type));
- GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
- }
-}
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Decrypt and process an encrypted message.
- *
- * Calls the appropriate handler for a message in a channel of a local tunnel.
- *
- * @param t Tunnel this message came on.
- * @param msg Message header.
- */
-void
-GCT_handle_encrypted (struct CadetTunnel *t,
- const struct GNUNET_CADET_TunnelEncryptedMessage *msg)
-{
- uint16_t size = ntohs (msg->header.size);
- char cbuf [size];
- int decrypted_size;
- const struct GNUNET_MessageHeader *msgh;
- unsigned int off;
-
- GNUNET_STATISTICS_update (stats, "# received encrypted", 1, GNUNET_NO);
-
- decrypted_size = t_ax_decrypt_and_validate (t, cbuf, msg, size);
-
- if (-1 == decrypted_size)
- {
- GNUNET_STATISTICS_update (stats, "# unable to decrypt", 1, GNUNET_NO);
- if (CADET_TUNNEL_KEY_AX_AUTH_SENT <= t->estate)
- {
- GNUNET_break_op (0);
- LOG (GNUNET_ERROR_TYPE_WARNING, "Wrong crypto, tunnel %s\n", GCT_2s (t));
- GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
- }
- return;
- }
- GCT_change_estate (t, CADET_TUNNEL_KEY_OK);
-
- /* FIXME: this is bad, as the structs returned from
- this loop may be unaligned, see util's MST for
- how to do this right. */
- off = 0;
- while (off + sizeof (struct GNUNET_MessageHeader) <= decrypted_size)
- {
- uint16_t msize;
-
- msgh = (const struct GNUNET_MessageHeader *) &cbuf[off];
- msize = ntohs (msgh->size);
- if (msize < sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break_op (0);
- return;
- }
- if (off + msize < decrypted_size)
- {
- GNUNET_break_op (0);
- return;
- }
- handle_decrypted (t, msgh, GNUNET_SYSERR);
- off += msize;
- }
-}
-
-
-/**
- * Handle a Key eXchange message.
- *
- * @param t Tunnel on which the message came.
- * @param msg KX message itself.
- */
-void
-GCT_handle_kx (struct CadetTunnel *t,
- const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg)
-{
- struct CadetTunnelAxolotl *ax;
- struct GNUNET_HashCode key_material[3];
- struct GNUNET_CRYPTO_SymmetricSessionKey keys[5];
- const char salt[] = "CADET Axolotl salt";
- const struct GNUNET_PeerIdentity *pid;
- int am_I_alice;
-
- CADET_TIMING_START;
-
- LOG (GNUNET_ERROR_TYPE_INFO, "<== { KX} on %s\n", GCT_2s (t));
-
- if (NULL == t->ax)
- {
- /* Something is wrong if ax is NULL. Whose fault it is? */
- return;
- }
- ax = t->ax;
-
- pid = GCT_get_destination (t);
- if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, pid))
- am_I_alice = GNUNET_YES;
- else if (0 < GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, pid))
- am_I_alice = GNUNET_NO;
- else
- {
- GNUNET_break_op (0);
- return;
- }
-
- if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->flags)))
- {
- if (NULL != t->rekey_task)
- {
- GNUNET_SCHEDULER_cancel (t->rekey_task);
- t->rekey_task = NULL;
- }
- GCT_send_kx (t, GNUNET_NO);
- }
-
- if (0 == memcmp (&ax->DHRr, &msg->ratchet_key, sizeof(msg->ratchet_key)))
- {
- LOG (GNUNET_ERROR_TYPE_INFO, " known ratchet key, exit\n");
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_INFO, " is Alice? %s\n", am_I_alice ? "YES" : "NO");
-
- ax->DHRr = msg->ratchet_key;
-
- /* ECDH A B0 */
- if (GNUNET_YES == am_I_alice)
- {
- GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */
- &msg->ephemeral_key, /* B0 */
- &key_material[0]);
- }
- else
- {
- GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* B0 */
- &pid->public_key, /* A */
- &key_material[0]);
- }
-
- /* ECDH A0 B */
- if (GNUNET_YES == am_I_alice)
- {
- GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* A0 */
- &pid->public_key, /* B */
- &key_material[1]);
- }
- else
- {
- GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */
- &msg->ephemeral_key, /* B0 */
- &key_material[1]);
-
-
- }
-
- /* ECDH A0 B0 */
- /* (This is the triple-DH, we could probably safely skip this,
- as A0/B0 are already in the key material.) */
- GNUNET_CRYPTO_ecc_ecdh (ax->kx_0, /* A0 or B0 */
- &msg->ephemeral_key, /* B0 or A0 */
- &key_material[2]);
-
- #if DUMP_KEYS_TO_STDERR
- {
- unsigned int i;
- for (i = 0; i < 3; i++)
- LOG (GNUNET_ERROR_TYPE_INFO, "km[%u]: %s\n",
- i, GNUNET_h2s (&key_material[i]));
- }
- #endif
-
- /* KDF */
- GNUNET_CRYPTO_kdf (keys, sizeof (keys),
- salt, sizeof (salt),
- &key_material, sizeof (key_material), NULL);
-
- if (0 == memcmp (&ax->RK, &keys[0], sizeof(ax->RK)))
- {
- LOG (GNUNET_ERROR_TYPE_INFO, " known handshake key, exit\n");
- return;
- }
- ax->RK = keys[0];
- if (GNUNET_YES == am_I_alice)
- {
- ax->HKr = keys[1];
- ax->NHKs = keys[2];
- ax->NHKr = keys[3];
- ax->CKr = keys[4];
- ax->ratchet_flag = GNUNET_YES;
- }
- else
- {
- ax->HKs = keys[1];
- ax->NHKr = keys[2];
- ax->NHKs = keys[3];
- ax->CKs = keys[4];
- ax->ratchet_flag = GNUNET_NO;
- ax->ratchet_allowed = GNUNET_NO;
- ax->ratchet_counter = 0;
- ax->ratchet_expiration =
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), ratchet_time);
- }
- ax->PNs = 0;
- ax->Nr = 0;
- ax->Ns = 0;
-
- GCT_change_estate (t, CADET_TUNNEL_KEY_AX_AUTH_SENT);
- send_queued_data (t);
-
- CADET_TIMING_END;
-}
-
-/**
- * Initialize the tunnel subsystem.
- *
- * @param c Configuration handle.
- * @param key ECC private key, to derive all other keys and do crypto.
- */
-void
-GCT_init (const struct GNUNET_CONFIGURATION_Handle *c,
- const struct GNUNET_CRYPTO_EddsaPrivateKey *key)
-{
- unsigned int expected_overhead;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n");
-
- expected_overhead = 0;
- expected_overhead += sizeof (struct GNUNET_CADET_TunnelEncryptedMessage);
- expected_overhead += sizeof (struct GNUNET_CADET_ChannelAppDataMessage);
- expected_overhead += sizeof (struct GNUNET_CADET_ConnectionEncryptedAckMessage);
- GNUNET_assert (GNUNET_CONSTANTS_CADET_P2P_OVERHEAD == expected_overhead);
-
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_number (c,
- "CADET",
- "RATCHET_MESSAGES",
- &ratchet_messages))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
- "CADET",
- "RATCHET_MESSAGES",
- "USING DEFAULT");
- ratchet_messages = 64;
- }
- if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_time (c,
- "CADET",
- "RATCHET_TIME",
- &ratchet_time))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
- "CADET", "RATCHET_TIME", "USING DEFAULT");
- ratchet_time = GNUNET_TIME_UNIT_HOURS;
- }
-
-
- id_key = key;
- tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
-}
-
-
-/**
- * Shut down the tunnel subsystem.
- */
-void
-GCT_shutdown (void)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down tunnels\n");
- GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL);
- GNUNET_CONTAINER_multipeermap_destroy (tunnels);
-}
-
-
-/**
- * Create a tunnel.
- *
- * @param destination Peer this tunnel is towards.
- */
-struct CadetTunnel *
-GCT_new (struct CadetPeer *destination)
-{
- struct CadetTunnel *t;
-
- t = GNUNET_new (struct CadetTunnel);
- t->next_ctn.cn = 0;
- t->peer = destination;
-
- if (GNUNET_OK !=
- GNUNET_CONTAINER_multipeermap_put (tunnels, GCP_get_id (destination), t,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
- {
- GNUNET_break (0);
- GNUNET_free (t);
- return NULL;
- }
- t->ax = GNUNET_new (struct CadetTunnelAxolotl);
- new_ephemeral (t);
- t->ax->kx_0 = GNUNET_CRYPTO_ecdhe_key_create ();
- return t;
-}
-
-
-/**
- * Change the tunnel's connection state.
- *
- * @param t Tunnel whose connection state to change.
- * @param cstate New connection state.
- */
-void
-GCT_change_cstate (struct CadetTunnel* t, enum CadetTunnelCState cstate)
-{
- if (NULL == t)
- return;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s cstate %s => %s\n",
- GCP_2s (t->peer), cstate2s (t->cstate), cstate2s (cstate));
- if (myid != GCP_get_short_id (t->peer) &&
- CADET_TUNNEL_READY != t->cstate &&
- CADET_TUNNEL_READY == cstate)
- {
- t->cstate = cstate;
- if (CADET_TUNNEL_KEY_OK == t->estate)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered send queued data\n");
- send_queued_data (t);
- }
- else if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered KX\n");
- GCT_send_kx (t, GNUNET_NO);
- }
- else
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "estate %s\n", estate2s (t->estate));
- }
- }
- t->cstate = cstate;
-
- if (CADET_TUNNEL_READY == cstate
- && CONNECTIONS_PER_TUNNEL <= GCT_count_connections (t))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered stop dht\n");
- GCP_stop_search (t->peer);
- }
-}
-
-
-/**
- * Change the tunnel encryption state.
- *
- * If the encryption state changes to OK, stop the rekey task.
- *
- * @param t Tunnel whose encryption state to change, or NULL.
- * @param state New encryption state.
- */
-void
-GCT_change_estate (struct CadetTunnel* t, enum CadetTunnelEState state)
-{
- enum CadetTunnelEState old;
-
- if (NULL == t)
- return;
-
- old = t->estate;
- t->estate = state;
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate was %s\n",
- GCP_2s (t->peer), estate2s (old));
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate is now %s\n",
- GCP_2s (t->peer), estate2s (t->estate));
-
- if (CADET_TUNNEL_KEY_OK != old && CADET_TUNNEL_KEY_OK == t->estate)
- {
- if (NULL != t->rekey_task)
- {
- GNUNET_SCHEDULER_cancel (t->rekey_task);
- t->rekey_task = NULL;
- }
- /* Send queued data if tunnel is not loopback */
- if (myid != GCP_get_short_id (t->peer))
- send_queued_data (t);
- }
-}
-
-
-/**
- * @brief Check if tunnel has too many connections, and remove one if necessary.
- *
- * Currently this means the newest connection, unless it is a direct one.
- * Implemented as a task to avoid freeing a connection that is in the middle
- * of being created/processed.
- *
- * @param cls Closure (Tunnel to check).
- */
-static void
-trim_connections (void *cls)
-{
- struct CadetTunnel *t = cls;
-
- t->trim_connections_task = NULL;
- if (GCT_count_connections (t) > 2 * CONNECTIONS_PER_TUNNEL)
- {
- struct CadetTConnection *iter;
- struct CadetTConnection *c;
-
- for (c = iter = t->connection_head; NULL != iter; iter = iter->next)
- {
- if ((iter->created.abs_value_us > c->created.abs_value_us)
- && GNUNET_NO == GCC_is_direct (iter->c))
- {
- c = iter;
- }
- }
- if (NULL != c)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Too many connections on tunnel %s\n",
- GCT_2s (t));
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying connection %s\n",
- GCC_2s (c->c));
- GCC_destroy (c->c);
- }
- else
- {
- GNUNET_break (0);
- }
- }
-}
-
-
-/**
- * Add a connection to a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GCT_add_connection (struct CadetTunnel *t, struct CadetConnection *c)
-{
- struct CadetTConnection *aux;
-
- GNUNET_assert (NULL != c);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "add connection %s\n", GCC_2s (c));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " to tunnel %s\n", GCT_2s (t));
- for (aux = t->connection_head; aux != NULL; aux = aux->next)
- if (aux->c == c)
- return;
-
- aux = GNUNET_new (struct CadetTConnection);
- aux->c = c;
- aux->created = GNUNET_TIME_absolute_get ();
-
- GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, aux);
-
- if (CADET_TUNNEL_SEARCHING == t->cstate)
- GCT_change_cstate (t, CADET_TUNNEL_WAITING);
-
- if (NULL != t->trim_connections_task)
- t->trim_connections_task = GNUNET_SCHEDULER_add_now (&trim_connections, t);
-}
-
-
-/**
- * Remove a connection from a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GCT_remove_connection (struct CadetTunnel *t,
- struct CadetConnection *c)
-{
- struct CadetTConnection *aux;
- struct CadetTConnection *next;
- unsigned int conns;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n",
- GCC_2s (c), GCT_2s (t));
- for (aux = t->connection_head; aux != NULL; aux = next)
- {
- next = aux->next;
- if (aux->c == c)
- {
- GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, aux);
- GNUNET_free (aux);
- }
- }
-
- conns = GCT_count_connections (t);
- if (0 == conns
- && NULL == t->destroy_task
- && CADET_TUNNEL_SHUTDOWN != t->cstate
- && GNUNET_NO == shutting_down)
- {
- if (0 == GCT_count_any_connections (t))
- GCT_change_cstate (t, CADET_TUNNEL_SEARCHING);
- else
- GCT_change_cstate (t, CADET_TUNNEL_WAITING);
- }
-
- /* Start new connections if needed */
- if (CONNECTIONS_PER_TUNNEL > conns
- && CADET_TUNNEL_SHUTDOWN != t->cstate
- && GNUNET_NO == shutting_down)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " too few connections, getting new ones\n");
- GCP_connect (t->peer); /* Will change cstate to WAITING when possible */
- return;
- }
-
- /* If not marked as ready, no change is needed */
- if (CADET_TUNNEL_READY != t->cstate)
- return;
-
- /* Check if any connection is ready to maintain cstate */
- for (aux = t->connection_head; aux != NULL; aux = aux->next)
- if (CADET_CONNECTION_READY == GCC_get_state (aux->c))
- return;
-}
-
-
-/**
- * Add a channel to a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GCT_add_channel (struct CadetTunnel *t,
- struct CadetChannel *ch)
-{
- struct CadetTChannel *aux;
-
- GNUNET_assert (NULL != ch);
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding channel %p to tunnel %p\n", ch, t);
-
- for (aux = t->channel_head; aux != NULL; aux = aux->next)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " already there %p\n", aux->ch);
- if (aux->ch == ch)
- return;
- }
-
- aux = GNUNET_new (struct CadetTChannel);
- aux->ch = ch;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- " adding %p to %p\n", aux, t->channel_head);
- GNUNET_CONTAINER_DLL_insert_tail (t->channel_head,
- t->channel_tail,
- aux);
-
- if (NULL != t->destroy_task)
- {
- GNUNET_SCHEDULER_cancel (t->destroy_task);
- t->destroy_task = NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n");
- }
-}
-
-
-/**
- * Remove a channel from a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch)
-{
- struct CadetTChannel *aux;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing channel %p from tunnel %p\n", ch, t);
- for (aux = t->channel_head; aux != NULL; aux = aux->next)
- {
- if (aux->ch == ch)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, " found! %s\n", GCCH_2s (ch));
- GNUNET_CONTAINER_DLL_remove (t->channel_head,
- t->channel_tail,
- aux);
- GNUNET_free (aux);
- return;
- }
- }
-}
-
-
-/**
- * Search for a channel by global ID.
- *
- * @param t Tunnel containing the channel.
- * @param ctn Public channel number.
- *
- * @return channel handler, NULL if doesn't exist
- */
-struct CadetChannel *
-GCT_get_channel (struct CadetTunnel *t,
- struct GNUNET_CADET_ChannelTunnelNumber ctn)
-{
- struct CadetTChannel *iter;
-
- if (NULL == t)
- return NULL;
-
- for (iter = t->channel_head; NULL != iter; iter = iter->next)
- {
- if (GCCH_get_id (iter->ch).cn == ctn.cn)
- break;
- }
-
- return NULL == iter ? NULL : iter->ch;
-}
-
-
-/**
- * @brief Destroy a tunnel and free all resources.
- *
- * Should only be called a while after the tunnel has been marked as destroyed,
- * in case there is a new channel added to the same peer shortly after marking
- * the tunnel. This way we avoid a new public key handshake.
- *
- * @param cls Closure (tunnel to destroy).
- */
-static void
-delayed_destroy (void *cls)
-{
- struct CadetTunnel *t = cls;
- struct CadetTConnection *iter;
-
- t->destroy_task = NULL;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "delayed destroying tunnel %p\n",
- t);
- t->cstate = CADET_TUNNEL_SHUTDOWN;
- for (iter = t->connection_head; NULL != iter; iter = iter->next)
- {
- GCC_send_destroy (iter->c);
- }
- GCT_destroy (t);
-}
-
-
-/**
- * Tunnel is empty: destroy it.
- *
- * Notifies all connections about the destruction.
- *
- * @param t Tunnel to destroy.
- */
-void
-GCT_destroy_empty (struct CadetTunnel *t)
-{
- if (GNUNET_YES == shutting_down)
- return; /* Will be destroyed immediately anyway */
-
- if (NULL != t->destroy_task)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "Tunnel %s is already scheduled for destruction. Tunnel debug dump:\n",
- GCT_2s (t));
- GCT_debug (t, GNUNET_ERROR_TYPE_WARNING);
- GNUNET_break (0);
- /* should never happen, tunnel can only become empty once, and the
- * task identifier should be NO_TASK (cleaned when the tunnel was created
- * or became un-empty)
- */
- return;
- }
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s empty: scheduling destruction\n",
- GCT_2s (t));
-
- // FIXME make delay a config option
- t->destroy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
- &delayed_destroy, t);
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled destroy of %p as %p\n",
- t, t->destroy_task);
-}
-
-
-/**
- * Destroy tunnel if empty (no more channels).
- *
- * @param t Tunnel to destroy if empty.
- */
-void
-GCT_destroy_if_empty (struct CadetTunnel *t)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s destroy if empty\n", GCT_2s (t));
- if (0 < GCT_count_channels (t))
- return;
-
- GCT_destroy_empty (t);
-}
-
-
-/**
- * Destroy the tunnel.
- *
- * This function does not generate any warning traffic to clients or peers.
- *
- * Tasks:
- * Cancel messages belonging to this tunnel queued to neighbors.
- * Free any allocated resources linked to the tunnel.
- *
- * @param t The tunnel to destroy.
- */
-void
-GCT_destroy (struct CadetTunnel *t)
-{
- struct CadetTConnection *iter_c;
- struct CadetTConnection *next_c;
- struct CadetTChannel *iter_ch;
- struct CadetTChannel *next_ch;
- unsigned int keepalives_queued;
-
- if (NULL == t)
- return;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "destroying tunnel %s\n",
- GCP_2s (t->peer));
- GNUNET_break (GNUNET_YES ==
- GNUNET_CONTAINER_multipeermap_remove (tunnels,
- GCP_get_id (t->peer), t));
-
- for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c)
- {
- next_c = iter_c->next;
- GCC_destroy (iter_c->c);
- }
- for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = next_ch)
- {
- next_ch = iter_ch->next;
- GCCH_destroy (iter_ch->ch);
- /* Should only happen on shutdown, but it's ok. */
- }
- keepalives_queued = 0;
- while (NULL != t->tq_head)
- {
- /* Should have been cleaned by destuction of channel. */
- struct GNUNET_MessageHeader *mh;
- uint16_t type;
-
- mh = (struct GNUNET_MessageHeader *) &t->tq_head[1];
- type = ntohs (mh->type);
- if (0 == keepalives_queued && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE == type)
- {
- keepalives_queued = 1;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "one keepalive left behind on tunnel shutdown\n");
- }
- else if (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY == type)
- {
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "tunnel destroyed before a CHANNEL_DESTROY was sent to peer\n");
- }
- else
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_ERROR,
- "message left behind on tunnel shutdown: %s\n",
- GC_m2s (type));
- }
- unqueue_data (t->tq_head);
- }
-
-
- if (NULL != t->destroy_task)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "cancelling dest: %p\n",
- t->destroy_task);
- GNUNET_SCHEDULER_cancel (t->destroy_task);
- t->destroy_task = NULL;
- }
-
- if (NULL != t->trim_connections_task)
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG, "cancelling trim: %p\n",
- t->trim_connections_task);
- GNUNET_SCHEDULER_cancel (t->trim_connections_task);
- t->trim_connections_task = NULL;
- }
-
- GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
- GCP_set_tunnel (t->peer, NULL);
-
- if (NULL != t->rekey_task)
- {
- GNUNET_SCHEDULER_cancel (t->rekey_task);
- t->rekey_task = NULL;
- }
- if (NULL != t->ax)
- destroy_ax (t);
-
- GNUNET_free (t);
-}
-
-
-/**
- * @brief Use the given path for the tunnel.
- * Update the next and prev hops (and RCs).
- * (Re)start the path refresh in case the tunnel is locally owned.
- *
- * @param t Tunnel to update.
- * @param p Path to use.
- *
- * @return Connection created.
- */
-struct CadetConnection *
-GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *path)
-{
- struct CadetConnection *c;
- struct GNUNET_CADET_ConnectionTunnelIdentifier cid;
- unsigned int own_pos;
-
- if (NULL == t || NULL == path)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- if (CADET_TUNNEL_SHUTDOWN == t->cstate)
- {
- GNUNET_break (0);
- return NULL;
- }
-
- for (own_pos = 0; own_pos < path->length; own_pos++)
- {
- if (path->peers[own_pos] == myid)
- break;
- }
- if (own_pos >= path->length)
- {
- GNUNET_break_op (0);
- return NULL;
- }
-
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid));
- c = GCC_new (&cid, t, path, own_pos);
- if (NULL == c)
- {
- /* Path was flawed */
- return NULL;
- }
- GCT_add_connection (t, c);
- return c;
-}
-
-
-/**
- * Count all created connections of a tunnel. Not necessarily ready connections!
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of connections created, either being established or ready.
- */
-unsigned int
-GCT_count_any_connections (struct CadetTunnel *t)
-{
- struct CadetTConnection *iter;
- unsigned int count;
-
- if (NULL == t)
- return 0;
-
- for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
- count++;
-
- return count;
-}
-
-
-/**
- * Count established (ready) connections of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of connections.
- */
-unsigned int
-GCT_count_connections (struct CadetTunnel *t)
-{
- struct CadetTConnection *iter;
- unsigned int count;
-
- if (NULL == t)
- return 0;
-
- for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
- if (CADET_CONNECTION_READY == GCC_get_state (iter->c))
- count++;
-
- return count;
-}
-
-
-/**
- * Count channels of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of channels.
- */
-unsigned int
-GCT_count_channels (struct CadetTunnel *t)
-{
- struct CadetTChannel *iter;
- unsigned int count;
-
- for (count = 0, iter = t->channel_head;
- NULL != iter;
- iter = iter->next, count++) /* skip */;
-
- return count;
-}
-
-
-/**
- * Get the connectivity state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's connectivity state.
- */
-enum CadetTunnelCState
-GCT_get_cstate (struct CadetTunnel *t)
-{
- if (NULL == t)
- {
- GNUNET_assert (0);
- return (enum CadetTunnelCState) -1;
- }
- return t->cstate;
-}
-
-
-/**
- * Get the encryption state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's encryption state.
- */
-enum CadetTunnelEState
-GCT_get_estate (struct CadetTunnel *t)
-{
- if (NULL == t)
- {
- GNUNET_break (0);
- return (enum CadetTunnelEState) -1;
- }
- return t->estate;
-}
-
-/**
- * Get the maximum buffer space for a tunnel towards a local client.
- *
- * @param t Tunnel.
- *
- * @return Biggest buffer space offered by any channel in the tunnel.
- */
-unsigned int
-GCT_get_channels_buffer (struct CadetTunnel *t)
-{
- struct CadetTChannel *iter;
- unsigned int buffer;
- unsigned int ch_buf;
-
- if (NULL == t->channel_head)
- {
- /* Probably getting buffer for a channel create/handshake. */
- LOG (GNUNET_ERROR_TYPE_DEBUG, " no channels, allow max\n");
- return MIN_TUNNEL_BUFFER;
- }
-
- buffer = 0;
- for (iter = t->channel_head; NULL != iter; iter = iter->next)
- {
- ch_buf = get_channel_buffer (iter);
- if (ch_buf > buffer)
- buffer = ch_buf;
- }
- if (MIN_TUNNEL_BUFFER > buffer)
- return MIN_TUNNEL_BUFFER;
-
- if (MAX_TUNNEL_BUFFER < buffer)
- {
- GNUNET_break (0);
- return MAX_TUNNEL_BUFFER;
- }
- return buffer;
-}
-
-
-/**
- * Get the total buffer space for a tunnel for P2P traffic.
- *
- * @param t Tunnel.
- *
- * @return Buffer space offered by all connections in the tunnel.
- */
-unsigned int
-GCT_get_connections_buffer (struct CadetTunnel *t)
-{
- struct CadetTConnection *iter;
- unsigned int buffer;
-
- if (GNUNET_NO == is_ready (t))
- {
- if (count_queued_data (t) >= 3)
- return 0;
- else
- return 1;
- }
-
- buffer = 0;
- for (iter = t->connection_head; NULL != iter; iter = iter->next)
- {
- if (GCC_get_state (iter->c) != CADET_CONNECTION_READY)
- {
- continue;
- }
- buffer += get_connection_buffer (iter);
- }
-
- return buffer;
-}
-
-
-/**
- * Get the tunnel's destination.
- *
- * @param t Tunnel.
- *
- * @return ID of the destination peer.
- */
-const struct GNUNET_PeerIdentity *
-GCT_get_destination (struct CadetTunnel *t)
-{
- return GCP_get_id (t->peer);
-}
-
-
-/**
- * Get the tunnel's next free global channel ID.
- *
- * @param t Tunnel.
- *
- * @return GID of a channel free to use.
- */
-struct GNUNET_CADET_ChannelTunnelNumber
-GCT_get_next_ctn (struct CadetTunnel *t)
-{
- struct GNUNET_CADET_ChannelTunnelNumber ctn;
- struct GNUNET_CADET_ChannelTunnelNumber mask;
- int result;
-
- /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID.
- * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0
- * If peer's ID is bigger, start at 0x4... bit 30 = 1
- */
- result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GCP_get_id (t->peer));
- if (0 > result)
- mask.cn = htonl (0x40000000);
- else
- mask.cn = 0x0;
- t->next_ctn.cn |= mask.cn;
-
- while (NULL != GCT_get_channel (t, t->next_ctn))
- {
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Channel %u exists...\n",
- t->next_ctn.cn);
- t->next_ctn.cn = htonl ((ntohl (t->next_ctn.cn) + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
- t->next_ctn.cn |= mask.cn;
- }
- ctn = t->next_ctn;
- t->next_ctn.cn = (t->next_ctn.cn + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
- t->next_ctn.cn |= mask.cn;
-
- return ctn;
-}
-
-
-/**
- * Send ACK on one or more channels due to buffer in connections.
- *
- * @param t Channel which has some free buffer space.
- */
-void
-GCT_unchoke_channels (struct CadetTunnel *t)
-{
- struct CadetTChannel *iter;
- unsigned int buffer;
- unsigned int channels = GCT_count_channels (t);
- unsigned int choked_n;
- struct CadetChannel *choked[channels];
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "GCT_unchoke_channels on %s\n", GCT_2s (t));
- LOG (GNUNET_ERROR_TYPE_DEBUG, " head: %p\n", t->channel_head);
- if (NULL != t->channel_head)
- LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch);
-
- if (NULL != t->tq_head)
- send_queued_data (t);
-
- /* Get buffer space */
- buffer = GCT_get_connections_buffer (t);
- if (0 == buffer)
- {
- return;
- }
-
- /* Count and remember choked channels */
- choked_n = 0;
- for (iter = t->channel_head; NULL != iter; iter = iter->next)
- {
- if (GNUNET_NO == get_channel_allowed (iter))
- {
- choked[choked_n++] = iter->ch;
- }
- }
-
- /* Unchoke random channels */
- while (0 < buffer && 0 < choked_n)
- {
- unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- choked_n);
- GCCH_allow_client (choked[r], GCCH_is_origin (choked[r], GNUNET_YES));
- choked_n--;
- buffer--;
- choked[r] = choked[choked_n];
- }
-}
-
-
-/**
- * Send ACK on one or more connections due to buffer space to the client.
- *
- * Iterates all connections of the tunnel and sends ACKs appropriately.
- *
- * @param t Tunnel.
- */
-void
-GCT_send_connection_acks (struct CadetTunnel *t)
-{
- struct CadetTConnection *iter;
- uint32_t allowed;
- uint32_t to_allow;
- uint32_t allow_per_connection;
- unsigned int cs;
- unsigned int buffer;
-
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel send connection ACKs on %s\n",
- GCT_2s (t));
-
- if (NULL == t)
- {
- GNUNET_break (0);
- return;
- }
-
- if (CADET_TUNNEL_READY != t->cstate)
- return;
-
- buffer = GCT_get_channels_buffer (t);
- LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer %u\n", buffer);
-
- /* Count connections, how many messages are already allowed */
- cs = GCT_count_connections (t);
- for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
- {
- allowed += get_connection_allowed (iter);
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG, " allowed %u\n", allowed);
-
- /* Make sure there is no overflow */
- if (allowed > buffer)
- return;
-
- /* Authorize connections to send more data */
- to_allow = buffer - allowed;
-
- for (iter = t->connection_head;
- NULL != iter && to_allow > 0;
- iter = iter->next)
- {
- if (CADET_CONNECTION_READY != GCC_get_state (iter->c)
- || get_connection_allowed (iter) > 64 / 3)
- {
- continue;
- }
- GNUNET_assert(cs != 0);
- allow_per_connection = to_allow/cs;
- to_allow -= allow_per_connection;
- cs--;
- GCC_allow (iter->c, allow_per_connection,
- GCC_is_origin (iter->c, GNUNET_NO));
- }
-
- if (0 != to_allow)
- {
- /* Since we don't allow if it's allowed to send 64/3, this can happen. */
- LOG (GNUNET_ERROR_TYPE_DEBUG, " reminding to_allow: %u\n", to_allow);
- }
-}
-
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GCT_cancel (struct CadetTunnelQueue *q)
-{
- if (NULL != q->cq)
- {
- GNUNET_assert (NULL == q->tqd);
- GCC_cancel (q->cq);
- /* tun_message_sent() will be called and free q */
- }
- else if (NULL != q->tqd)
- {
- unqueue_data (q->tqd);
- q->tqd = NULL;
- if (NULL != q->cont)
- q->cont (q->cont_cls, NULL, q, 0, 0);
- GNUNET_free (q);
- }
- else
- {
- GNUNET_break (0);
- }
-}
-
-
-/**
- * Check if the tunnel has queued traffic.
- *
- * @param t Tunnel to check.
- *
- * @return #GNUNET_YES if there is queued traffic
- * #GNUNET_NO otherwise
- */
-int
-GCT_has_queued_traffic (struct CadetTunnel *t)
-{
- return (NULL != t->tq_head) ? GNUNET_YES : GNUNET_NO;
-}
-
-
-/**
- * Sends an already built message on a tunnel, encrypting it and
- * choosing the best connection if not provided.
- *
- * @param message Message to send. Function modifies it.
- * @param t Tunnel on which this message is transmitted.
- * @param c Connection to use (autoselect if NULL).
- * @param force Force the tunnel to take the message (buffer overfill).
- * @param cont Continuation to call once message is really sent.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel message. NULL if @c cont is NULL.
- */
-struct CadetTunnelQueue *
-GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- struct CadetTunnel *t,
- struct CadetConnection *c,
- int force, GCT_sent cont, void *cont_cls)
-{
- return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL);
-}
-
-
-/**
- * Send a KX message.
- *
- * @param t Tunnel on which to send it.
- * @param force_reply Force the other peer to reply with a KX message.
- */
-void
-GCT_send_kx (struct CadetTunnel *t, int force_reply)
-{
- static struct CadetEncryptedMessageIdentifier zero;
- struct CadetConnection *c;
- struct GNUNET_CADET_TunnelKeyExchangeMessage msg;
- enum GNUNET_CADET_KX_Flags flags;
-
- LOG (GNUNET_ERROR_TYPE_INFO, "==> { KX} on %s\n", GCT_2s (t));
- if (NULL != t->ephm_h)
- {
- LOG (GNUNET_ERROR_TYPE_INFO, " already queued, nop\n");
- return;
- }
- GNUNET_assert (GNUNET_NO == GCT_is_loopback (t));
-
- c = tunnel_get_connection (t);
- if (NULL == c)
- {
- if (NULL == t->destroy_task && CADET_TUNNEL_READY == t->cstate)
- {
- GNUNET_break (0);
- GCT_debug (t, GNUNET_ERROR_TYPE_ERROR);
- }
- return;
- }
-
- msg.header.size = htons (sizeof (msg));
- msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX);
- flags = GNUNET_CADET_KX_FLAG_NONE;
- if (GNUNET_YES == force_reply)
- flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY;
- msg.flags = htonl (flags);
- msg.cid = *GCC_get_id (c);
- GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->kx_0, &msg.ephemeral_key);
- GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &msg.ratchet_key);
-
- t->ephm_h = GCC_send_prebuilt_message (&msg.header,
- UINT16_MAX,
- zero,
- c,
- GCC_is_origin (c, GNUNET_YES),
- GNUNET_YES, &ephm_sent, t);
- if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
- GCT_change_estate (t, CADET_TUNNEL_KEY_AX_SENT);
-}
-
-
-/**
- * Is the tunnel directed towards the local peer?
- *
- * @param t Tunnel.
- *
- * @return #GNUNET_YES if it is loopback.
- */
-int
-GCT_is_loopback (const struct CadetTunnel *t)
-{
- return (myid == GCP_get_short_id (t->peer));
-}
-
-
-/**
- * Is the tunnel this path already?
- *
- * @param t Tunnel.
- * @param p Path.
- *
- * @return #GNUNET_YES a connection uses this path.
- */
-int
-GCT_is_path_used (const struct CadetTunnel *t, const struct CadetPeerPath *p)
-{
- struct CadetTConnection *iter;
-
- for (iter = t->connection_head; NULL != iter; iter = iter->next)
- if (path_equivalent (GCC_get_path (iter->c), p))
- return GNUNET_YES;
-
- return GNUNET_NO;
-}
-
-
-/**
- * Get a cost of a path for a tunnel considering existing connections.
- *
- * @param t Tunnel.
- * @param path Candidate path.
- *
- * @return Cost of the path (path length + number of overlapping nodes)
- */
-unsigned int
-GCT_get_path_cost (const struct CadetTunnel *t,
- const struct CadetPeerPath *path)
-{
- struct CadetTConnection *iter;
- const struct CadetPeerPath *aux;
- unsigned int overlap;
- unsigned int i;
- unsigned int j;
-
- if (NULL == path)
- return 0;
-
- overlap = 0;
- GNUNET_assert (NULL != t);
-
- for (i = 0; i < path->length; i++)
- {
- for (iter = t->connection_head; NULL != iter; iter = iter->next)
- {
- aux = GCC_get_path (iter->c);
- if (NULL == aux)
- continue;
-
- for (j = 0; j < aux->length; j++)
- {
- if (path->peers[i] == aux->peers[j])
- {
- overlap++;
- break;
- }
- }
- }
- }
- return path->length + overlap;
-}
-
-
-/**
- * Get the static string for the peer this tunnel is directed.
- *
- * @param t Tunnel.
- *
- * @return Static string the destination peer's ID.
- */
-const char *
-GCT_2s (const struct CadetTunnel *t)
-{
- if (NULL == t)
- return "(NULL)";
-
- return GCP_2s (t->peer);
-}
-
-
-/******************************************************************************/
-/***************************** INFO/DEBUG *******************************/
-/******************************************************************************/
-
-static void
-ax_debug (const struct CadetTunnelAxolotl *ax, enum GNUNET_ErrorType level)
-{
- struct GNUNET_CRYPTO_EcdhePublicKey pub;
- struct CadetTunnelSkippedKey *iter;
-
- LOG2 (level, "TTT RK \t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->RK));
-
- LOG2 (level, "TTT HKs \t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKs));
- LOG2 (level, "TTT HKr \t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKr));
- LOG2 (level, "TTT NHKs\t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->NHKs));
- LOG2 (level, "TTT NHKr\t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->NHKr));
-
- LOG2 (level, "TTT CKs \t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKs));
- LOG2 (level, "TTT CKr \t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKr));
-
- GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs, &pub);
- LOG2 (level, "TTT DHRs\t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &pub));
- LOG2 (level, "TTT DHRr\t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->DHRr));
-
- LOG2 (level, "TTT Nr\t %u\tNs\t%u\n", ax->Nr, ax->Ns);
- LOG2 (level, "TTT PNs\t %u\tSkipped\t%u\n", ax->PNs, ax->skipped);
- LOG2 (level, "TTT Ratchet\t%u\n", ax->ratchet_flag);
-
- for (iter = ax->skipped_head; NULL != iter; iter = iter->next)
- {
- LOG2 (level, "TTT HK\t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &iter->HK));
- LOG2 (level, "TTT MK\t %s\n",
- GNUNET_i2s ((struct GNUNET_PeerIdentity *) &iter->MK));
- }
-}
-
-/**
- * Log all possible info about the tunnel state.
- *
- * @param t Tunnel to debug.
- * @param level Debug level to use.
- */
-void
-GCT_debug (const struct CadetTunnel *t, enum GNUNET_ErrorType level)
-{
- struct CadetTChannel *iter_ch;
- struct CadetTConnection *iter_c;
- int do_log;
-
- do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
- "cadet-tun",
- __FILE__, __FUNCTION__, __LINE__);
- if (0 == do_log)
- return;
-
- LOG2 (level, "TTT DEBUG TUNNEL TOWARDS %s\n", GCT_2s (t));
- LOG2 (level, "TTT cstate %s, estate %s\n",
- cstate2s (t->cstate), estate2s (t->estate));
-#if DUMP_KEYS_TO_STDERR
- ax_debug (t->ax, level);
-#endif
- LOG2 (level, "TTT tq_head %p, tq_tail %p\n", t->tq_head, t->tq_tail);
- LOG2 (level, "TTT destroy %p\n", t->destroy_task);
- LOG2 (level, "TTT channels:\n");
- for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = iter_ch->next)
- {
- GCCH_debug (iter_ch->ch, level);
- }
-
- LOG2 (level, "TTT connections:\n");
- for (iter_c = t->connection_head; NULL != iter_c; iter_c = iter_c->next)
- {
- GCC_debug (iter_c->c, level);
- }
-
- LOG2 (level, "TTT DEBUG TUNNEL END\n");
-}
-
-
-/**
- * Iterate all tunnels.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls)
-{
- GNUNET_CONTAINER_multipeermap_iterate (tunnels, iter, cls);
-}
-
-
-/**
- * Count all tunnels.
- *
- * @return Number of tunnels to remote peers kept by this peer.
- */
-unsigned int
-GCT_count_all (void)
-{
- return GNUNET_CONTAINER_multipeermap_size (tunnels);
-}
-
-
-/**
- * Iterate all connections of a tunnel.
- *
- * @param t Tunnel whose connections to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCT_iterate_connections (struct CadetTunnel *t, GCT_conn_iter iter, void *cls)
-{
- struct CadetTConnection *ct;
-
- for (ct = t->connection_head; NULL != ct; ct = ct->next)
- iter (cls, ct->c);
-}
-
-
-/**
- * Iterate all channels of a tunnel.
- *
- * @param t Tunnel whose channels to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCT_iterate_channels (struct CadetTunnel *t, GCT_chan_iter iter, void *cls)
-{
- struct CadetTChannel *cht;
-
- for (cht = t->channel_head; NULL != cht; cht = cht->next)
- iter (cls, cht->ch);
-}
+++ /dev/null
-/*
- This file is part of GNUnet.
- Copyright (C) 2013 GNUnet e.V.
-
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-/**
- * @file cadet/gnunet-service-cadet_tunnel.h
- * @brief cadet service; dealing with tunnels and crypto
- * @author Bartlomiej Polot
- *
- * All functions in this file should use the prefix GMT (Gnunet Cadet Tunnel)
- */
-
-#ifndef GNUNET_SERVICE_CADET_TUNNEL_H
-#define GNUNET_SERVICE_CADET_TUNNEL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#if 0 /* keep Emacsens' auto-indent happy */
-}
-#endif
-#endif
-
-#include "platform.h"
-#include "gnunet_util_lib.h"
-
-#define CONNECTIONS_PER_TUNNEL 3
-
-/**
- * All the connectivity states a tunnel can be in.
- */
-enum CadetTunnelCState
-{
- /**
- * Uninitialized status, should never appear in operation.
- */
- CADET_TUNNEL_NEW,
-
- /**
- * No path to the peer known yet.
- */
- CADET_TUNNEL_SEARCHING,
-
- /**
- * Request sent, not yet answered.
- */
- CADET_TUNNEL_WAITING,
-
- /**
- * Peer connected and ready to accept data.
- */
- CADET_TUNNEL_READY,
-
- /**
- * Tunnel being shut down, don't try to keep it alive.
- */
- CADET_TUNNEL_SHUTDOWN
-};
-
-
-/**
- * All the encryption states a tunnel can be in.
- */
-enum CadetTunnelEState
-{
- /**
- * Uninitialized status, should never appear in operation.
- */
- CADET_TUNNEL_KEY_UNINITIALIZED,
-
- /**
- * Ephemeral key sent, waiting for peer's key.
- */
- CADET_TUNNEL_KEY_AX_SENT,
-
- /**
- * In OTR: New ephemeral key and ping sent, waiting for pong.
- *
- * This means that we DO have the peer's ephemeral key, otherwise the
- * state would be KEY_SENT. We DO NOT have a valid session key (either no
- * previous key or previous key expired).
- *
- *
- * In Axolotl: Key sent and received but no deciphered traffic yet.
- *
- * This means that we can send traffic (otherwise we would never complete
- * the handshake), but we don't have complete confirmation. Since the first
- * traffic MUST be a complete channel creation 3-way handshake, no payload
- * will be sent before confirmation.
- */
- CADET_TUNNEL_KEY_AX_AUTH_SENT,
-
- /**
- * Handshake completed: session key available.
- */
- CADET_TUNNEL_KEY_OK,
-
- /**
- * New ephemeral key and ping sent, waiting for pong. Unlike KEY_PING,
- * we still have a valid session key and therefore we *can* still send
- * traffic on the tunnel.
- */
- CADET_TUNNEL_KEY_REKEY
-};
-
-/**
- * Struct containing all information regarding a given peer
- */
-struct CadetTunnel;
-
-
-#include "gnunet-service-cadet_channel.h"
-#include "gnunet-service-cadet_connection.h"
-#include "gnunet-service-cadet_peer.h"
-
-/**
- * Handle for messages queued but not yet sent.
- */
-struct CadetTunnelQueue;
-
-/**
- * Callback called when a queued message is sent.
- *
- * @param cls Closure.
- * @param t Tunnel this message was on.
- * @param type Type of message sent.
- * @param size Size of the message.
- */
-typedef void
-(*GCT_sent) (void *cls,
- struct CadetTunnel *t,
- struct CadetTunnelQueue *q,
- uint16_t type, size_t size);
-
-typedef void
-(*GCT_conn_iter) (void *cls, struct CadetConnection *c);
-
-
-typedef void
-(*GCT_chan_iter) (void *cls, struct CadetChannel *ch);
-
-
-/******************************************************************************/
-/******************************** API ***********************************/
-/******************************************************************************/
-
-/**
- * Initialize tunnel subsystem.
- *
- * @param c Configuration handle.
- * @param key ECC private key, to derive all other keys and do crypto.
- */
-void
-GCT_init (const struct GNUNET_CONFIGURATION_Handle *c,
- const struct GNUNET_CRYPTO_EddsaPrivateKey *key);
-
-
-/**
- * Shut down the tunnel subsystem.
- */
-void
-GCT_shutdown (void);
-
-
-/**
- * Create a tunnel.
- *
- * @param destination Peer this tunnel is towards.
- */
-struct CadetTunnel *
-GCT_new (struct CadetPeer *destination);
-
-
-/**
- * Tunnel is empty: destroy it.
- *
- * Notifies all connections about the destruction.
- *
- * @param t Tunnel to destroy.
- */
-void
-GCT_destroy_empty (struct CadetTunnel *t);
-
-
-/**
- * Destroy tunnel if empty (no more channels).
- *
- * @param t Tunnel to destroy if empty.
- */
-void
-GCT_destroy_if_empty (struct CadetTunnel *t);
-
-
-/**
- * Destroy the tunnel.
- *
- * This function does not generate any warning traffic to clients or peers.
- *
- * Tasks:
- * Cancel messages belonging to this tunnel queued to neighbors.
- * Free any allocated resources linked to the tunnel.
- *
- * @param t The tunnel to destroy.
- */
-void
-GCT_destroy (struct CadetTunnel *t);
-
-
-/**
- * Change the tunnel's connection state.
- *
- * @param t Tunnel whose connection state to change.
- * @param cstate New connection state.
- */
-void
-GCT_change_cstate (struct CadetTunnel* t, enum CadetTunnelCState cstate);
-
-
-/**
- * Change the tunnel encryption state.
- *
- * @param t Tunnel whose encryption state to change.
- * @param state New encryption state.
- */
-void
-GCT_change_estate (struct CadetTunnel* t, enum CadetTunnelEState state);
-
-
-/**
- * Add a connection to a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GCT_add_connection (struct CadetTunnel *t, struct CadetConnection *c);
-
-
-/**
- * Remove a connection from a tunnel.
- *
- * @param t Tunnel.
- * @param c Connection.
- */
-void
-GCT_remove_connection (struct CadetTunnel *t, struct CadetConnection *c);
-
-
-/**
- * Add a channel to a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GCT_add_channel (struct CadetTunnel *t, struct CadetChannel *ch);
-
-
-/**
- * Remove a channel from a tunnel.
- *
- * @param t Tunnel.
- * @param ch Channel.
- */
-void
-GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch);
-
-
-/**
- * Search for a channel by global ID.
- *
- * @param t Tunnel containing the channel.
- * @param ctn Public channel number.
- *
- * @return channel handler, NULL if doesn't exist
- */
-struct CadetChannel *
-GCT_get_channel (struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber ctn);
-
-
-/**
- * Decrypt and process an encrypted message.
- *
- * Calls the appropriate handler for a message in a channel of a local tunnel.
- *
- * @param t Tunnel this message came on.
- * @param msg Message header.
- */
-void
-GCT_handle_encrypted (struct CadetTunnel *t,
- const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
-
-
-/**
- * Handle a Key eXchange message.
- *
- * @param t Tunnel on which the message came.
- * @param msg KX message itself.
- */
-void
-GCT_handle_kx (struct CadetTunnel *t,
- const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg);
-
-
-/**
- * @brief Use the given path for the tunnel.
- * Update the next and prev hops (and RCs).
- * (Re)start the path refresh in case the tunnel is locally owned.
- *
- * @param t Tunnel to update.
- * @param p Path to use.
- *
- * @return Connection created.
- */
-struct CadetConnection *
-GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *p);
-
-
-/**
- * Count all created connections of a tunnel. Not necessarily ready connections!
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of connections created, either being established or ready.
- */
-unsigned int
-GCT_count_any_connections (struct CadetTunnel *t);
-
-
-/**
- * Count established (ready) connections of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of connections.
- */
-unsigned int
-GCT_count_connections (struct CadetTunnel *t);
-
-
-/**
- * Count channels of a tunnel.
- *
- * @param t Tunnel on which to count.
- *
- * @return Number of channels.
- */
-unsigned int
-GCT_count_channels (struct CadetTunnel *t);
-
-
-/**
- * Get the connectivity state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's connectivity state.
- */
-enum CadetTunnelCState
-GCT_get_cstate (struct CadetTunnel *t);
-
-
-/**
- * Get the encryption state of a tunnel.
- *
- * @param t Tunnel.
- *
- * @return Tunnel's encryption state.
- */
-enum CadetTunnelEState
-GCT_get_estate (struct CadetTunnel *t);
-
-
-/**
- * Get the maximum buffer space for a tunnel towards a local client.
- *
- * @param t Tunnel.
- *
- * @return Biggest buffer space offered by any channel in the tunnel.
- */
-unsigned int
-GCT_get_channels_buffer (struct CadetTunnel *t);
-
-
-/**
- * Get the total buffer space for a tunnel for P2P traffic.
- *
- * @param t Tunnel.
- *
- * @return Buffer space offered by all connections in the tunnel.
- */
-unsigned int
-GCT_get_connections_buffer (struct CadetTunnel *t);
-
-
-/**
- * Get the tunnel's destination.
- *
- * @param t Tunnel.
- *
- * @return ID of the destination peer.
- */
-const struct GNUNET_PeerIdentity *
-GCT_get_destination (struct CadetTunnel *t);
-
-
-/**
- * Get the tunnel's next free Channel ID.
- *
- * @param t Tunnel.
- *
- * @return ID of a channel free to use.
- */
-struct GNUNET_CADET_ChannelTunnelNumber
-GCT_get_next_ctn (struct CadetTunnel *t);
-
-
-/**
- * Send ACK on one or more channels due to buffer in connections.
- *
- * @param t Channel which has some free buffer space.
- */
-void
-GCT_unchoke_channels (struct CadetTunnel *t);
-
-
-/**
- * Send ACK on one or more connections due to buffer space to the client.
- *
- * Iterates all connections of the tunnel and sends ACKs appropriately.
- *
- * @param t Tunnel which has some free buffer space.
- */
-void
-GCT_send_connection_acks (struct CadetTunnel *t);
-
-
-/**
- * Cancel a previously sent message while it's in the queue.
- *
- * ONLY can be called before the continuation given to the send function
- * is called. Once the continuation is called, the message is no longer in the
- * queue.
- *
- * @param q Handle to the queue.
- */
-void
-GCT_cancel (struct CadetTunnelQueue *q);
-
-
-/**
- * Check if the tunnel has queued traffic.
- *
- * @param t Tunnel to check.
- *
- * @return #GNUNET_YES if there is queued traffic
- * #GNUNET_NO otherwise
- */
-int
-GCT_has_queued_traffic (struct CadetTunnel *t);
-
-/**
- * Sends an already built message on a tunnel, encrypting it and
- * choosing the best connection.
- *
- * @param message Message to send. Function modifies it.
- * @param t Tunnel on which this message is transmitted.
- * @param c Connection to use (autoselect if NULL).
- * @param force Force the tunnel to take the message (buffer overfill).
- * @param cont Continuation to call once message is really sent.
- * @param cont_cls Closure for @c cont.
- *
- * @return Handle to cancel message. NULL if @c cont is NULL.
- */
-struct CadetTunnelQueue *
-GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
- struct CadetTunnel *t, struct CadetConnection *c,
- int force, GCT_sent cont, void *cont_cls);
-
-
-/**
- * Send a KX message.
- *
- * @param t Tunnel on which to send it.
- * @param force_reply Force the other peer to reply with a KX message.
- */
-void
-GCT_send_kx (struct CadetTunnel *t, int force_reply);
-
-
-/**
- * Is the tunnel directed towards the local peer?
- *
- * @param t Tunnel.
- *
- * @return #GNUNET_YES if it is loopback.
- */
-int
-GCT_is_loopback (const struct CadetTunnel *t);
-
-
-/**
- * Is the tunnel using this path already?
- *
- * @param t Tunnel.
- * @param p Path.
- *
- * @return #GNUNET_YES a connection uses this path.
- */
-int
-GCT_is_path_used (const struct CadetTunnel *t, const struct CadetPeerPath *p);
-
-
-/**
- * Get a cost of a path for a tunnel considering existing connections.
- *
- * @param t Tunnel.
- * @param path Candidate path.
- *
- * @return Cost of the path (path length + number of overlapping nodes)
- */
-unsigned int
-GCT_get_path_cost (const struct CadetTunnel *t,
- const struct CadetPeerPath *path);
-
-
-/**
- * Get the static string for the peer this tunnel is directed.
- *
- * @param t Tunnel.
- *
- * @return Static string the destination peer's ID.
- */
-const char *
-GCT_2s (const struct CadetTunnel *t);
-
-
-/**
- * Log all possible info about the tunnel state.
- *
- * @param t Tunnel to debug.
- * @param level Debug level to use.
- */
-void
-GCT_debug (const struct CadetTunnel *t, enum GNUNET_ErrorType level);
-
-
-/**
- * Iterate all tunnels.
- *
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls);
-
-
-/**
- * Count all tunnels.
- *
- * @return Number of tunnels to remote peers kept by this peer.
- */
-unsigned int
-GCT_count_all (void);
-
-
-/**
- * Iterate all connections of a tunnel.
- *
- * @param t Tunnel whose connections to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCT_iterate_connections (struct CadetTunnel *t, GCT_conn_iter iter, void *cls);
-
-
-/**
- * Iterate all channels of a tunnel.
- *
- * @param t Tunnel whose channels to iterate.
- * @param iter Iterator.
- * @param cls Closure for @c iter.
- */
-void
-GCT_iterate_channels (struct CadetTunnel *t,
- GCT_chan_iter iter,
- void *cls);
-
-
-#if 0 /* keep Emacsens' auto-indent happy */
-{
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-/* ifndef GNUNET_CADET_SERVICE_TUNNEL_H */
-#endif
-/* end of gnunet-cadet-service_tunnel.h */