struct CadetClient *prev;
/**
- * Tunnels that belong to this client, indexed by local id
+ * Tunnels that belong to this client, indexed by local id,
+ * value is a `struct CadetChannel`.
*/
- 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_chid;
+ struct GNUNET_CONTAINER_MultiHashMap32 *channels;
/**
* Handle to communicate with the 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).
+ * Channel ID to use for the next incoming channel for this client.
+ * Wraps around (in theory).
*/
- int shutting_down;
+ struct GNUNET_CADET_ClientChannelNumber next_ccn;
/**
- * ID of the client, mainly for debug messages
+ * ID of the client, mainly for debug messages. Purely internal to this file.
*/
unsigned int id;
};
/****************************** Global variables ******************************/
+/**
+ * Handle to our configuration.
+ */
+const struct GNUNET_CONFIGURATION_Handle *cfg;
+
/**
* Handle to the statistics service.
*/
struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
/**
- * Signal that shutdown is happening: prevent recover measures.
+ * Signal that shutdown is happening: prevent recovery measures.
*/
int shutting_down;
struct GNUNET_CONTAINER_MultiPeerMap *peers;
/**
- * Map from expanded connection hash codes to `struct CadetConnection` objects.
+ * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier`
+ * hash codes to `struct CadetConnection` objects.
*/
-struct GNUNET_CONTAINER_MultiHashMap *connections;
+struct GNUNET_CONTAINER_MultiShortmap *connections;
/**
* How many messages are needed to trigger an AXOLOTL ratchet advance.
*/
struct GNUNET_TIME_Relative ratchet_time;
+/**
+ * How frequently do we send KEEPALIVE messages on idle connections?
+ */
+struct GNUNET_TIME_Relative keepalive_period;
+
+/**
+ * Set to non-zero values to create random drops to test retransmissions.
+ */
+unsigned long long drop_percent;
/**
{
static char buf[32];
- if (NULL == c)
- return "Client(NULL)";
GNUNET_snprintf (buf,
sizeof (buf),
"Client(%u)",
}
+/**
+ * Lookup channel of client @a c by @a ccn.
+ *
+ * @param c client to look in
+ * @param ccn channel ID to look up
+ * @return NULL if no such channel exists
+ */
+static struct CadetChannel *
+lookup_channel (struct CadetClient *c,
+ struct GNUNET_CADET_ClientChannelNumber ccn)
+{
+ return GNUNET_CONTAINER_multihashmap32_get (c->channels,
+ ntohl (ccn.channel_of_client));
+}
+
+
/**
* Obtain the next LID to use for incoming connections to
* the given client.
* @param c client handle
*/
static struct GNUNET_CADET_ClientChannelNumber
-client_get_next_lid (struct CadetClient *c)
+client_get_next_ccn (struct CadetClient *c)
{
- struct GNUNET_CADET_ClientChannelNumber ccn = c->next_chid;
+ struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn;
/* increment until we have a free one... */
while (NULL !=
- GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels,
- ntohl (ccn.channel_of_client)))
+ lookup_channel (c,
+ ccn))
{
ccn.channel_of_client
= htonl (1 + (ntohl (ccn.channel_of_client)));
GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
ccn.channel_of_client = htonl (0);
}
- c->next_chid.channel_of_client
+ c->next_ccn.channel_of_client
= htonl (1 + (ntohl (ccn.channel_of_client)));
return ccn;
}
/**
- * Bind incoming channel to this client, and notify client
- * about incoming connection.
+ * Bind incoming channel to this client, and notify client about
+ * incoming connection. Caller is responsible for notifying the other
+ * peer about our acceptance of the channel.
*
* @param c client to bind to
* @param ch channel to be bound
uint32_t options)
{
struct GNUNET_MQ_Envelope *env;
- struct GNUNET_CADET_ChannelCreateMessage *msg;
- struct GNUNET_CADET_ClientChannelNumber lid;
+ struct GNUNET_CADET_LocalChannelCreateMessage *cm;
+ struct GNUNET_CADET_ClientChannelNumber ccn;
- lid = client_get_next_lid (c);
+ ccn = client_get_next_ccn (c);
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_put (c->incoming_channels,
- ntohl (lid.channel_of_client),
+ GNUNET_CONTAINER_multihashmap32_put (c->channels,
+ ntohl (ccn.channel_of_client),
ch,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n",
+ GCCH_2s (ch),
+ GCP_2s (dest),
+ GNUNET_h2s (port),
+ ntohl (options),
+ ntohl (ccn.channel_of_client));
/* notify local client about incoming connection! */
- env = GNUNET_MQ_msg (msg,
- GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE);
- msg->channel_id = lid;
- msg->port = *port;
- msg->opt = htonl (options);
- msg->peer = *GCP_get_id (dest);
+ env = GNUNET_MQ_msg (cm,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
+ cm->ccn = ccn;
+ cm->port = *port;
+ cm->opt = htonl (options);
+ cm->peer = *GCP_get_id (dest);
GSC_send_to_client (c,
env);
- return lid;
+ return ccn;
}
-/******************************************************************************/
-/************************ MAIN FUNCTIONS ****************************/
-/******************************************************************************/
+/**
+ * Callback invoked on all peers to destroy all tunnels
+ * that may still exist.
+ *
+ * @param cls NULL
+ * @param pid identify of a peer
+ * @param value a `struct CadetPeer` that may still have a tunnel
+ * @return #GNUNET_OK (iterate over all entries)
+ */
+static int
+destroy_tunnels_now (void *cls,
+ const struct GNUNET_PeerIdentity *pid,
+ void *value)
+{
+ struct CadetPeer *cp = value;
+ struct CadetTunnel *t = GCP_get_tunnel (cp,
+ GNUNET_NO);
+
+ if (NULL != t)
+ GCT_destroy_tunnel_now (t);
+ return GNUNET_OK;
+}
+
/**
- * Task run during shutdown.
+ * Callback invoked on all peers to destroy all tunnels
+ * that may still exist.
*
- * @param cls unused
+ * @param cls NULL
+ * @param pid identify of a peer
+ * @param value a `struct CadetPeer` that may still have a tunnel
+ * @return #GNUNET_OK (iterate over all entries)
+ */
+static int
+destroy_paths_now (void *cls,
+ const struct GNUNET_PeerIdentity *pid,
+ void *value)
+{
+ struct CadetPeer *cp = value;
+
+ GCP_drop_owned_paths (cp);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Shutdown everything once the clients have disconnected.
*/
static void
-shutdown_task (void *cls)
+shutdown_rest ()
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "shutting down\n");
- shutting_down = GNUNET_YES;
- GCO_shutdown ();
if (NULL != stats)
{
GNUNET_STATISTICS_destroy (stats,
GNUNET_CONTAINER_multihashmap_destroy (loose_channels);
loose_channels = NULL;
}
- /* All channels, connections and CORE must be down before this point. */
+ /* Destroy tunnels. Note that all channels must be destroyed first! */
+ GCP_iterate_all (&destroy_tunnels_now,
+ NULL);
+ /* All tunnels, channels, connections and CORE must be down before this point. */
+ GCP_iterate_all (&destroy_paths_now,
+ NULL);
+ /* All paths, tunnels, channels, connections and CORE must be down before this point. */
GCP_destroy_all_peers ();
if (NULL != peers)
{
}
if (NULL != connections)
{
- GNUNET_CONTAINER_multihashmap_destroy (connections);
+ GNUNET_CONTAINER_multishortmap_destroy (connections);
connections = NULL;
}
if (NULL != ats_ch)
}
+/**
+ * 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;
+ GCO_shutdown ();
+ if (NULL == clients_head)
+ shutdown_rest ();
+}
+
+
/**
* We had a remote connection @a value to port @a port before
* client @a cls opened port @a port. Bind them now.
/**
- * Handler for port open requests.
+ * Handle port open request. Creates a mapping from the
+ * port to the respective client and checks whether we have
+ * loose channels trying to bind to the port. If so, those
+ * are bound.
*
* @param cls Identification of the client.
* @param pmsg The actual message.
struct CadetClient *c = cls;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Open port %s requested by client %u\n",
+ "Open port %s requested by %s\n",
GNUNET_h2s (&pmsg->port),
- c->id);
+ GSC_2s (c));
if (NULL == c->ports)
c->ports = GNUNET_CONTAINER_multihashmap_create (4,
- GNUNET_NO);
+ GNUNET_NO);
if (GNUNET_OK !=
GNUNET_CONTAINER_multihashmap_put (c->ports,
&pmsg->port,
GNUNET_SERVICE_client_drop (c->client);
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 (open_ports,
- &pmsg->port,
- c,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ (void) GNUNET_CONTAINER_multihashmap_put (open_ports,
+ &pmsg->port,
+ c,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels,
&pmsg->port,
&bind_loose_channel,
/**
- * Handler for port close requests.
+ * Handler for port close requests. Marks this port as closed
+ * (unless of course we have another client with the same port
+ * open). Note that existing channels accepted on the port are
+ * not affected.
*
* @param cls Identification of the client.
* @param pmsg The actual message.
struct CadetClient *c = cls;
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Open port %s requested by client %u\n",
+ "Closing port %s as requested by %s\n",
GNUNET_h2s (&pmsg->port),
- c->id);
+ GSC_2s (c));
if (GNUNET_YES !=
GNUNET_CONTAINER_multihashmap_remove (c->ports,
&pmsg->port,
GNUNET_CONTAINER_multihashmap_remove (open_ports,
&pmsg->port,
c));
-
GNUNET_SERVICE_client_continue (c->client);
}
/**
- * Handler for requests of new channels.
+ * Handler for requests for us creating a new channel to another peer and port.
*
* @param cls Identification of the client.
- * @param ccm The actual message.
+ * @param tcm The actual message.
*/
static void
handle_channel_create (void *cls,
- const struct GNUNET_CADET_ChannelCreateMessage *ccm)
+ const struct GNUNET_CADET_LocalChannelCreateMessage *tcm)
{
struct CadetClient *c = cls;
struct CadetChannel *ch;
- struct GNUNET_CADET_ClientChannelNumber chid;
- struct CadetPeer *dst;
- chid = ccm->channel_id;
- if (ntohl (chid.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
+ if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
{
/* Channel ID not in allowed range. */
GNUNET_break (0);
GNUNET_SERVICE_client_drop (c->client);
return;
}
- ch = GNUNET_CONTAINER_multihashmap32_get (c->own_channels,
- ntohl (chid.channel_of_client));
+ ch = lookup_channel (c,
+ tcm->ccn);
if (NULL != ch)
{
/* Channel ID already in use. Not allowed. */
GNUNET_SERVICE_client_drop (c->client);
return;
}
-
- dst = GCP_get (&ccm->peer,
- GNUNET_YES);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "New channel to %s at port %s requested by %s\n",
+ GNUNET_i2s (&tcm->peer),
+ GNUNET_h2s (&tcm->port),
+ GSC_2s (c));
/* Create channel */
ch = GCCH_channel_local_new (c,
- chid,
- dst,
- &ccm->port,
- ntohl (ccm->opt));
+ tcm->ccn,
+ GCP_get (&tcm->peer,
+ GNUNET_YES),
+ &tcm->port,
+ ntohl (tcm->opt));
if (NULL == ch)
{
GNUNET_break (0);
return;
}
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_put (c->own_channels,
- ntohl (chid.channel_of_client),
+ GNUNET_CONTAINER_multihashmap32_put (c->channels,
+ ntohl (tcm->ccn.channel_of_client),
ch,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "New channel %s to %s at port %s requested by client %u\n",
- GCCH_2s (ch),
- GNUNET_i2s (&ccm->peer),
- GNUNET_h2s (&ccm->port),
- c->id);
GNUNET_SERVICE_client_continue (c->client);
}
/**
- * Return the map which we use for client @a c for a channel ID of @a chid
- *
- * @param c client to find map for
- * @param chid chid to find map for
- * @return applicable map we use
- */
-static struct GNUNET_CONTAINER_MultiHashMap32 *
-get_map_by_chid (struct CadetClient *c,
- struct GNUNET_CADET_ClientChannelNumber chid)
-{
- return (ntohl (chid.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- ? c->own_channels
- : c->incoming_channels;
-}
-
-
-/**
- * Handler for requests of deleting tunnels
+ * Handler for requests of destroying an existing channel.
*
* @param cls client identification of the client
* @param msg the actual message
*/
static void
handle_channel_destroy (void *cls,
- const struct GNUNET_CADET_ChannelDestroyMessage *msg)
+ const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
{
struct CadetClient *c = cls;
- struct GNUNET_CADET_ClientChannelNumber chid;
- struct GNUNET_CONTAINER_MultiHashMap32 *map;
struct CadetChannel *ch;
- /* Retrieve tunnel */
- chid = msg->channel_id;
- map = get_map_by_chid (c,
- chid);
- ch = GNUNET_CONTAINER_multihashmap32_get (map,
- ntohl (chid.channel_of_client));
+ ch = lookup_channel (c,
+ msg->ccn);
if (NULL == ch)
{
/* Client attempted to destroy unknown channel */
return;
}
LOG (GNUNET_ERROR_TYPE_INFO,
- "Client %u is destroying channel %s\n",
- c->id,
+ "%s is destroying %s\n",
+ GSC_2s(c),
GCCH_2s (ch));
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_remove (map,
- ntohl (chid.channel_of_client),
+ GNUNET_CONTAINER_multihashmap32_remove (c->channels,
+ ntohl (msg->ccn.channel_of_client),
ch));
- GCCH_channel_local_destroy (ch);
+ GCCH_channel_local_destroy (ch,
+ c,
+ msg->ccn);
GNUNET_SERVICE_client_continue (c->client);
}
/**
- * Check for client traffic data message is well-formed
+ * Check for client traffic data message is well-formed.
*
* @param cls identification of the client
* @param msg the actual message
* @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not
*/
static int
-check_data (void *cls,
- const struct GNUNET_CADET_LocalData *msg)
+check_local_data (void *cls,
+ const struct GNUNET_CADET_LocalData *msg)
{
- const struct GNUNET_MessageHeader *payload;
size_t payload_size;
size_t payload_claimed_size;
-
+ const char *buf;
+ struct GNUNET_MessageHeader pa;
+
+ /* FIXME: what is the format we shall allow for @a msg?
+ ONE payload item or multiple? Seems current cadet_api
+ at least in theory allows more than one. Next-gen
+ cadet_api will likely no more, so we could then
+ simplify this mess again. */
/* Sanity check for message size */
payload_size = ntohs (msg->header.size) - sizeof (*msg);
- if ( (payload_size < sizeof (struct GNUNET_MessageHeader)) ||
- (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_size) )
+ buf = (const char *) &msg[1];
+ while (payload_size >= sizeof (struct GNUNET_MessageHeader))
{
- GNUNET_break (0);
- return GNUNET_SYSERR;
+ /* need to memcpy() for alignment */
+ GNUNET_memcpy (&pa,
+ buf,
+ sizeof (pa));
+ payload_claimed_size = ntohs (pa.size);
+ if ( (payload_size < payload_claimed_size) ||
+ (payload_claimed_size < sizeof (struct GNUNET_MessageHeader)) ||
+ (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size) )
+ {
+ GNUNET_break (0);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Local data of %u total size had sub-message %u at %u with %u bytes\n",
+ ntohs (msg->header.size),
+ ntohs (pa.type),
+ (unsigned int) (buf - (const char *) &msg[1]),
+ (unsigned int) payload_claimed_size);
+ return GNUNET_SYSERR;
+ }
+ payload_size -= payload_claimed_size;
+ buf += payload_claimed_size;
}
- payload = (struct GNUNET_MessageHeader *) &msg[1];
- payload_claimed_size = ntohs (payload->size);
- if (payload_size != payload_claimed_size)
+ if (0 != payload_size)
{
- GNUNET_break (0);
+ GNUNET_break_op (0);
return GNUNET_SYSERR;
}
return GNUNET_OK;
/**
- * Handler for client traffic
+ * Handler for client payload traffic to be send on a channel to
+ * another peer.
*
* @param cls identification of the client
* @param msg the actual message
*/
static void
-handle_data (void *cls,
- const struct GNUNET_CADET_LocalData *msg)
+handle_local_data (void *cls,
+ const struct GNUNET_CADET_LocalData *msg)
{
struct CadetClient *c = cls;
- struct GNUNET_CONTAINER_MultiHashMap32 *map;
- struct GNUNET_CADET_ClientChannelNumber chid;
struct CadetChannel *ch;
- const struct GNUNET_MessageHeader *payload;
+ size_t payload_size;
+ const char *buf;
- chid = msg->id;
- map = get_map_by_chid (c,
- chid);
- ch = GNUNET_CONTAINER_multihashmap32_get (map,
- ntohl (chid.channel_of_client));
+ ch = lookup_channel (c,
+ msg->ccn);
if (NULL == ch)
{
/* Channel does not exist! */
GNUNET_SERVICE_client_drop (c->client);
return;
}
-
- payload = (const struct GNUNET_MessageHeader *) &msg[1];
+ payload_size = ntohs (msg->header.size) - sizeof (*msg);
+ buf = (const char *) &msg[1];
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received %u bytes payload from client %u for channel %s\n",
- ntohs (payload->size),
- c->id,
+ "Received %u bytes payload from %s for %s\n",
+ (unsigned int) payload_size,
+ GSC_2s (c),
GCCH_2s (ch));
if (GNUNET_OK !=
GCCH_handle_local_data (ch,
- payload))
+ msg->ccn,
+ buf,
+ payload_size))
{
GNUNET_SERVICE_client_drop (c->client);
return;
* @param msg The actual message.
*/
static void
-handle_ack (void *cls,
- const struct GNUNET_CADET_LocalAck *msg)
+handle_local_ack (void *cls,
+ const struct GNUNET_CADET_LocalAck *msg)
{
struct CadetClient *c = cls;
- struct GNUNET_CONTAINER_MultiHashMap32 *map;
- struct GNUNET_CADET_ClientChannelNumber chid;
struct CadetChannel *ch;
- chid = msg->channel_id;
- map = get_map_by_chid (c,
- chid);
- ch = GNUNET_CONTAINER_multihashmap32_get (map,
- ntohl (chid.channel_of_client));
+ ch = lookup_channel (c,
+ msg->ccn);
if (NULL == ch)
{
/* Channel does not exist! */
return;
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Got a local ACK from client %u for channel %s\n",
- c->id,
+ "Got a local ACK from %s for %s\n",
+ GSC_2s(c),
GCCH_2s (ch));
- GCCH_handle_local_ack (ch);
+ GCCH_handle_local_ack (ch,
+ msg->ccn);
GNUNET_SERVICE_client_continue (c->client);
}
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->cstate = htons (0);
msg->estate = htons ((uint16_t) GCT_get_estate (t));
GNUNET_MQ_send (c->mq,
env);
/**
- * Handler for client's INFO TUNNELS request.
+ * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS request.
*
* @param cls client Identification of the client.
* @param message The actual message.
*/
static void
-handle_get_tunnels (void *cls,
- const struct GNUNET_MessageHeader *message)
+handle_info_tunnels (void *cls,
+ const struct GNUNET_MessageHeader *message)
{
struct CadetClient *c = cls;
struct GNUNET_MQ_Envelope *env;
/**
- * FIXME.
+ * Update the message with information about the connection.
+ *
+ * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update
+ * @param c a connection about which we should store information in @a cls
*/
static void
iter_connection (void *cls,
/**
- * FIXME.
+ * Update the message with information about the channel.
+ *
+ * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update
+ * @param ch a channel about which we should store information in @a cls
*/
static void
iter_channel (void *cls,
struct CadetChannel *ch)
{
struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
- struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1];
- struct GCT_ChannelTunnelNumber *chn
- = (struct GCT_ChannelTunnelNumber *) &h[msg->connections];
+ 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);
}
/**
- * Handler for client's SHOW_TUNNEL request.
+ * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL request.
*
* @param cls Identification of the client.
* @param msg The actual message.
*/
static void
-handle_show_tunnel (void *cls,
+handle_info_tunnel (void *cls,
const struct GNUNET_CADET_LocalInfo *msg)
{
struct CadetClient *c = cls;
ch_n = GCT_count_channels (t);
c_n = GCT_count_any_connections (t);
env = GNUNET_MQ_msg_extra (resp,
- c_n * sizeof (struct GNUNET_CADET_Hash) +
- ch_n * sizeof (struct GCT_ChannelTunnelNumber),
+ c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) +
+ ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber),
GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
resp->destination = msg->peer;
/* Do not reorder! #iter_channel needs counters in HBO! */
resp);
resp->connections = htonl (resp->connections);
resp->channels = htonl (resp->channels);
- resp->cstate = htons (GCT_get_cstate (t));
+ resp->cstate = htons (0);
resp->estate = htons (GCT_get_estate (t));
GNUNET_MQ_send (c->mq,
env);
LOG (GNUNET_ERROR_TYPE_ERROR,
"*************************** DUMP START ***************************\n");
- for (struct CadetClient *ci = clients_head; NULL != ci; ci = ci->next)
+ for (struct CadetClient *ci = clients_head;
+ NULL != ci;
+ ci = ci->next)
{
LOG (GNUNET_ERROR_TYPE_ERROR,
- "Client %u (%p), handle: %p, ports: %u, own channels: %u, incoming channels: %u\n",
+ "Client %u (%p), handle: %p, ports: %u, channels: %u\n",
ci->id,
ci,
ci->client,
(NULL != c->ports)
? GNUNET_CONTAINER_multihashmap_size (ci->ports)
: 0,
- GNUNET_CONTAINER_multihashmap32_size (ci->own_channels),
- GNUNET_CONTAINER_multihashmap32_size (ci->incoming_channels));
+ GNUNET_CONTAINER_multihashmap32_size (ci->channels));
}
LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n");
GCP_iterate_all (&show_peer_iterator,
c->client = client;
c->mq = mq;
c->id = next_client_id++; /* overflow not important: just for debug */
- c->own_channels
- = GNUNET_CONTAINER_multihashmap32_create (32);
- c->incoming_channels
+ c->channels
= GNUNET_CONTAINER_multihashmap32_create (32);
GNUNET_CONTAINER_DLL_insert (clients_head,
clients_tail,
"# clients",
+1,
GNUNET_NO);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "%s connected\n",
+ GSC_2s (c));
return c;
}
/**
- * Iterator for deleting each channel whose client endpoint disconnected.
+ * A channel was destroyed by the other peer. Tell our client.
*
- * @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.
+ * @param c client that lost a channel
+ * @param ccn channel identification number for the client
+ * @param ch the channel object
*/
-static int
-own_channel_destroy_iterator (void *cls,
- uint32_t key,
- void *value)
+void
+GSC_handle_remote_channel_destroy (struct CadetClient *c,
+ struct GNUNET_CADET_ClientChannelNumber ccn,
+ struct CadetChannel *ch)
{
- struct CadetClient *c = cls;
- struct CadetChannel *ch = value;
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
+ env = GNUNET_MQ_msg (tdm,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
+ tdm->ccn = ccn;
+ GSC_send_to_client (c,
+ env);
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
- key,
+ GNUNET_CONTAINER_multihashmap32_remove (c->channels,
+ ntohl (ccn.channel_of_client),
ch));
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Destroying own channel %s, due to client %u shutdown.\n",
- GCCH_2s (ch),
- c->id);
- GCCH_channel_local_destroy (ch);
- 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 key The local channel id in host byte order
* @param value The value stored at the key (channel to destroy).
* @return #GNUNET_OK, keep iterating.
*/
static int
-incoming_channel_destroy_iterator (void *cls,
- uint32_t key,
- void *value)
+channel_destroy_iterator (void *cls,
+ uint32_t key,
+ void *value)
{
- struct CadetChannel *ch = value;
struct CadetClient *c = cls;
+ struct GNUNET_CADET_ClientChannelNumber ccn;
+ struct CadetChannel *ch = value;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Destroying %s, due to %s disconnecting.\n",
+ GCCH_2s (ch),
+ GSC_2s (c));
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
+ GNUNET_CONTAINER_multihashmap32_remove (c->channels,
key,
ch));
-
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Destroying incoming channel %s due to client %u shutdown.\n",
- GCCH_2s (ch),
- c->id);
- GCCH_channel_incoming_destroy (ch);
+ ccn.channel_of_client = htonl (key);
+ GCCH_channel_local_destroy (ch,
+ c,
+ ccn);
return GNUNET_OK;
}
* Remove client's ports from the global hashmap on disconnect.
*
* @param cls Closure (unused).
- * @param key Port.
+ * @param key the port.
* @param value the `struct CadetClient` to remove
* @return #GNUNET_OK, keep iterating.
*/
{
struct CadetClient *c = value;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Closing port %s due to %s disconnect.\n",
+ GNUNET_h2s (key),
+ GSC_2s (c));
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (open_ports,
key,
struct CadetClient *c = internal_cls;
GNUNET_assert (c->client == client);
- c->shutting_down = GNUNET_YES;
- if (NULL != c->own_channels)
- {
- GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
- &own_channel_destroy_iterator,
- c);
- GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
- }
- if (NULL != c->incoming_channels)
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "%s is disconnecting.\n",
+ GSC_2s (c));
+ if (NULL != c->channels)
{
- GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
- &incoming_channel_destroy_iterator,
+ GNUNET_CONTAINER_multihashmap32_iterate (c->channels,
+ &channel_destroy_iterator,
c);
- GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
+ GNUNET_CONTAINER_multihashmap32_destroy (c->channels);
}
if (NULL != c->ports)
{
-1,
GNUNET_NO);
GNUNET_free (c);
+ if ( (NULL == clients_head) &&
+ (GNUNET_YES == shutting_down) )
+ shutdown_rest ();
}
const struct GNUNET_CONFIGURATION_Handle *c,
struct GNUNET_SERVICE_Handle *service)
{
+ cfg = c;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (c,
"CADET",
"need delay value");
ratchet_time = GNUNET_TIME_UNIT_HOURS;
}
-
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_time (c,
+ "CADET",
+ "REFRESH_CONNECTION_TIME",
+ &keepalive_period))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
+ "CADET",
+ "REFRESH_CONNECTION_TIME",
+ "need delay value");
+ keepalive_period = GNUNET_TIME_UNIT_MINUTES;
+ }
+ 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");
+ }
my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
if (NULL == my_private_key)
{
GNUNET_NO);
peers = GNUNET_CONTAINER_multipeermap_create (16,
GNUNET_YES);
- connections = GNUNET_CONTAINER_multihashmap_create (256,
- GNUNET_YES);
+ connections = GNUNET_CONTAINER_multishortmap_create (256,
+ GNUNET_YES);
GCH_init (c);
GCD_init (c);
GCO_init (c);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "CADET starting at peer %s\n",
+ "CADET started for peer %s\n",
GNUNET_i2s (&my_full_id));
}
struct GNUNET_CADET_PortMessage,
NULL),
GNUNET_MQ_hd_fixed_size (channel_create,
- GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE,
- struct GNUNET_CADET_ChannelCreateMessage,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
+ struct GNUNET_CADET_LocalChannelCreateMessage,
NULL),
GNUNET_MQ_hd_fixed_size (channel_destroy,
- GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY,
- struct GNUNET_CADET_ChannelDestroyMessage,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
+ struct GNUNET_CADET_LocalChannelDestroyMessage,
NULL),
- GNUNET_MQ_hd_var_size (data,
+ GNUNET_MQ_hd_var_size (local_data,
GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
struct GNUNET_CADET_LocalData,
NULL),
- GNUNET_MQ_hd_fixed_size (ack,
+ GNUNET_MQ_hd_fixed_size (local_ack,
GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
struct GNUNET_CADET_LocalAck,
NULL),
GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
struct GNUNET_CADET_LocalInfo,
NULL),
- GNUNET_MQ_hd_fixed_size (get_tunnels,
+ GNUNET_MQ_hd_fixed_size (info_tunnels,
GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
struct GNUNET_MessageHeader,
NULL),
- GNUNET_MQ_hd_fixed_size (show_tunnel,
+ GNUNET_MQ_hd_fixed_size (info_tunnel,
GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
struct GNUNET_CADET_LocalInfo,
NULL),