libgnunetcadet_la_SOURCES = \
cadet_api.c \
+ cadet_api_drop_message.c \
cadet_api_get_channel.c \
cadet_api_get_path.c \
cadet_api_list_peers.c \
test_cadet_2_speed_reliable \
test_cadet_2_speed_reliable_backwards \
test_cadet_2_reopen \
+ test_cadet_2_destroy \
test_cadet_5_forward \
test_cadet_5_signal \
test_cadet_5_keepalive \
test_cadet.c
test_cadet_5_reopen_LDADD = $(ld_cadet_test_lib)
+test_cadet_2_destroy_SOURCES = \
+ test_cadet.c
+test_cadet_2_destroy_LDADD = $(ld_cadet_test_lib)
if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
GNUNET_NETWORK_STRUCT_BEGIN
-
/**
* Number uniquely identifying a channel of a client.
*/
uint32_t channel_of_client GNUNET_PACKED;
};
+/**
+ * Opaque handle to a channel.
+ */
+struct GNUNET_CADET_Channel
+{
+
+ /**
+ * Other end of the channel.
+ */
+ struct GNUNET_PeerIdentity peer;
+
+ /**
+ * Handle to the cadet this channel belongs to
+ */
+ struct GNUNET_CADET_Handle *cadet;
+
+ /**
+ * Channel's port, if incoming.
+ */
+ struct GNUNET_CADET_Port *incoming_port;
+
+ /**
+ * Any data the caller wants to put in here, used for the
+ * various callbacks (@e disconnects, @e window_changes, handlers).
+ */
+ void *ctx;
+
+ /**
+ * Message Queue for the channel (which we are implementing).
+ */
+ struct GNUNET_MQ_Handle *mq;
+
+ /**
+ * Task to allow mq to send more traffic.
+ */
+ struct GNUNET_SCHEDULER_Task *mq_cont;
+
+ /**
+ * Pending envelope with a message to be transmitted to the
+ * service as soon as we are allowed to. Should only be
+ * non-NULL if @e allow_send is 0.
+ */
+ struct GNUNET_MQ_Envelope *pending_env;
+
+ /**
+ * Window change handler.
+ */
+ GNUNET_CADET_WindowSizeEventHandler window_changes;
+
+ /**
+ * Disconnect handler.
+ */
+ GNUNET_CADET_DisconnectEventHandler disconnects;
+
+ /**
+ * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound.
+ */
+ struct GNUNET_CADET_ClientChannelNumber ccn;
+
+ /**
+ * How many messages are we allowed to send to the service right now?
+ */
+ unsigned int allow_send;
+};
/**
* Message for a client to create and destroy channels.
struct GNUNET_PeerIdentity peer;
};
+/**
+ * Message to drop another message of specific type. Used in test context
+ */
+struct GNUNET_CADET_RequestDropCadetMessage
+{
+ /**
+ * Type: #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE
+ */
+ struct GNUNET_MessageHeader header;
+
+ /**
+ * Type of the message this handler covers, in host byte order.
+ */
+ uint16_t type;
+
+ /**
+ * ID of the channel we want to drop a message for.
+ */
+ struct GNUNET_CADET_ClientChannelNumber ccn;
+
+};
+
/**
* Message to inform the client about channels in the service.
*/
struct GNUNET_TIME_Relative reconnect_time;
};
-
-/**
- * Opaque handle to a channel.
- */
-struct GNUNET_CADET_Channel
-{
- /**
- * Other end of the channel.
- */
- struct GNUNET_PeerIdentity peer;
-
- /**
- * Handle to the cadet this channel belongs to
- */
- struct GNUNET_CADET_Handle *cadet;
-
- /**
- * Channel's port, if incoming.
- */
- struct GNUNET_CADET_Port *incoming_port;
-
- /**
- * Any data the caller wants to put in here, used for the
- * various callbacks (@e disconnects, @e window_changes, handlers).
- */
- void *ctx;
-
- /**
- * Message Queue for the channel (which we are implementing).
- */
- struct GNUNET_MQ_Handle *mq;
-
- /**
- * Task to allow mq to send more traffic.
- */
- struct GNUNET_SCHEDULER_Task *mq_cont;
-
- /**
- * Pending envelope with a message to be transmitted to the
- * service as soon as we are allowed to. Should only be
- * non-NULL if @e allow_send is 0.
- */
- struct GNUNET_MQ_Envelope *pending_env;
-
- /**
- * Window change handler.
- */
- GNUNET_CADET_WindowSizeEventHandler window_changes;
-
- /**
- * Disconnect handler.
- */
- GNUNET_CADET_DisconnectEventHandler disconnects;
-
- /**
- * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound.
- */
- struct GNUNET_CADET_ClientChannelNumber ccn;
-
- /**
- * How many messages are we allowed to send to the service right now?
- */
- unsigned int allow_send;
-};
-
-
/**
* Opaque handle to a port.
*/
*/
uint32_t options GNUNET_PACKED;
+ /**
+ * This flag indicates the peer sending the connection create
+ * meassage likes to trigger a KX handshake.
+ */
+ int has_monotime;
+
+ /**
+ * This monotonic time is set, if a peer likes to trigger a KX, but is not
+ * the peer that should start the KX. (xrs,t3ss)
+ */
+ struct GNUNET_TIME_AbsoluteNBO monotime;
+
+ /**
+ * We sign the monotime. The receiving peer can check the signature, to verify
+ * the sending peer.
+ */
+ struct GNUNET_CRYPTO_EddsaSignature monotime_sig;
+
/**
* ID of the connection
*/
if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
{
/* Channel ID not in allowed range. */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID not in allowed range.");
GNUNET_break (0);
GNUNET_SERVICE_client_drop (c->client);
return;
if (NULL != ch)
{
/* Channel ID already in use. Not allowed. */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,"Channel ID already in use. Not allowed.");
GNUNET_break (0);
GNUNET_SERVICE_client_drop (c->client);
return;
GNUNET_SERVICE_client_continue (c->client);
}
+/**
+ * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE request.
+ *
+ * @param cls client Identification of the client.
+ * @param message The actual message.
+ */
+static void
+handle_drop_message (void *cls,
+ const struct GNUNET_CADET_RequestDropCadetMessage *message)
+{
+ struct CadetClient *c = cls;
+ struct CadetChannel *ch;
+
+ ch = lookup_channel (c,
+ message->ccn);
+
+ GCCH_assign_type_to_drop(ch, message);
+
+ GNUNET_SERVICE_client_continue (c->client);
+}
/**
* Callback called when a client connects to the service.
* Define "main" method using service macro.
*/
GNUNET_SERVICE_MAIN
- ("cadet",
- GNUNET_SERVICE_OPTION_NONE,
- &run,
- &client_connect_cb,
- &client_disconnect_cb,
- NULL,
- GNUNET_MQ_hd_fixed_size (port_open,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
- struct GNUNET_CADET_PortMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (port_close,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
- struct GNUNET_CADET_PortMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (channel_create,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
- struct GNUNET_CADET_LocalChannelCreateMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (channel_destroy,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
- struct GNUNET_CADET_LocalChannelDestroyMessage,
- NULL),
- GNUNET_MQ_hd_var_size (local_data,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
- struct GNUNET_CADET_LocalData,
- NULL),
- GNUNET_MQ_hd_fixed_size (local_ack,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
- struct GNUNET_CADET_LocalAck,
- NULL),
- GNUNET_MQ_hd_fixed_size (get_peers,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
- struct GNUNET_MessageHeader,
- NULL),
- GNUNET_MQ_hd_fixed_size (show_path,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
- struct GNUNET_CADET_RequestPathInfoMessage,
- NULL),
- GNUNET_MQ_hd_fixed_size (info_tunnels,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
- struct GNUNET_MessageHeader,
- NULL),
- GNUNET_MQ_handler_end ());
+("cadet",
+ GNUNET_SERVICE_OPTION_NONE,
+ &run,
+ &client_connect_cb,
+ &client_disconnect_cb,
+ NULL,
+ GNUNET_MQ_hd_fixed_size (port_open,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN,
+ struct GNUNET_CADET_PortMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (port_close,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE,
+ struct GNUNET_CADET_PortMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (channel_create,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
+ struct GNUNET_CADET_LocalChannelCreateMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (channel_destroy,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
+ struct GNUNET_CADET_LocalChannelDestroyMessage,
+ NULL),
+ GNUNET_MQ_hd_var_size (local_data,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
+ struct GNUNET_CADET_LocalData,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (local_ack,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
+ struct GNUNET_CADET_LocalAck,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (get_peers,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PEERS,
+ struct GNUNET_MessageHeader,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (show_path,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_PATH,
+ struct GNUNET_CADET_RequestPathInfoMessage,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (info_tunnels,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_REQUEST_INFO_TUNNELS,
+ struct GNUNET_MessageHeader,
+ NULL),
+ GNUNET_MQ_hd_fixed_size (drop_message,
+ GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE,
+ struct GNUNET_CADET_RequestDropCadetMessage,
+ NULL),
+ GNUNET_MQ_handler_end ());
/* end of gnunet-service-cadet-new.c */
GSC_2s (struct CadetClient *c);
+
#endif
* empty.
*/
int destroy;
+
+ /**
+ * Type of message to be droped. See GCT_send.
+ */
+ uint16_t type GNUNET_PACKED;
+
};
+/**
+ * Assign type of message to drop.
+ * @param ch CadetChannel to assign type to drop.
+ * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from.
+ */
+void
+GCCH_assign_type_to_drop(struct CadetChannel *ch, const struct GNUNET_CADET_RequestDropCadetMessage *message)
+{
+
+ ch->type = message->type;
+
+}
+
+/**
+ * Check if type of message is the one to drop.
+ * @param ch CadetChannel to check for message type to drop.
+ * @param message GNUNET_MessageHeader to compare the type with.
+ */
+int
+GCCH_is_type_to_drop(struct CadetChannel *ch, const struct GNUNET_MessageHeader *message)
+{
+
+ if (ch->type == message->type)
+ {
+ ch->type = 0;
+ return GNUNET_YES;
+ }
+ else
+ return GNUNET_NO;
+}
/**
* Get the static string for identification of the channel.
if (NULL != ch->last_control_qe)
GCT_send_cancel (ch->last_control_qe);
ch->last_control_qe =
- GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch);
+ GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn);
GNUNET_assert (NULL == ch->retry_control_task);
}
GCCH_2s (ch));
if (NULL != ch->last_control_qe)
GCT_send_cancel (ch->last_control_qe);
- ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch);
+ ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, &msg.ctn);
}
msg.port = ch->port;
if (NULL != ch->last_control_qe)
GCT_send_cancel (ch->last_control_qe);
- ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch);
+ ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch, &msg.ctn);
}
"Retrying transmission on %s of message %u\n",
GCCH_2s (ch),
(unsigned int) ntohl (crm->data_message->mid.mid));
- crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm);
+ crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, &crm->data_message->ctn);
GNUNET_assert (NULL == ch->retry_data_task);
}
GNUNET_SCHEDULER_cancel (ch->retry_data_task);
ch->retry_data_task = NULL;
}
- crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm);
+ crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm, &crm->data_message->ctn);
GNUNET_assert (NULL == ch->retry_data_task);
return GNUNET_OK;
}
const struct GNUNET_HashCode *port,
const struct GNUNET_PeerIdentity *listener);
+/**
+ * Check if type of message is the one to drop.
+ * @param ch CadetChannel to check for message type to drop.
+ * @param message GNUNET_MessageHeader to compare the type with.
+ */
+int
+GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
+ GNUNET_MessageHeader *message);
+
+/**
+ * Check if type of message is the one to drop.
+ * @param ch CadetChannel to assign type to drop.
+ * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from.
+ */
+void
+GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
+ GNUNET_CADET_RequestDropCadetMessage *message);
/**
* Get the static string for identification of the channel.
* @author Christian Grothoff
*/
#include "platform.h"
+#include "gnunet_signatures.h"
#include "gnunet-service-cadet_connection.h"
#include "gnunet-service-cadet_channel.h"
#include "gnunet-service-cadet_paths.h"
CADET_CONNECTION_READY
};
-
/**
* Low-level connection to a destination.
*/
int old_ready;
int new_ready;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to update connection state for %s having old state %d to new %d and mqm_ready old %d to mqm_ready new %d\n",
+ GCT_2s (cc->ct->t),
+ cc->state,
+ new_state,
+ cc->mqm_ready,
+ new_mqm_ready);
+
if ((new_state == cc->state) && (new_mqm_ready == cc->mqm_ready))
return; /* no change, nothing to do */
old_ready =
((CADET_CONNECTION_READY == new_state) && (GNUNET_YES == new_mqm_ready));
cc->state = new_state;
cc->mqm_ready = new_mqm_ready;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Updating connection state for %s having old_ready %d and new_rady %d\n",
+ GCT_2s (cc->ct->t),
+ old_ready,
+ new_ready);
+
if (old_ready != new_ready)
cc->ready_cb (cc->ready_cb_cls, new_ready);
}
msg.size = htons (sizeof(msg));
msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE);
- cc->keepalive_qe = GCT_send (cc->ct->t, &msg, &keepalive_done, cc);
+ cc->keepalive_qe = GCT_send (cc->ct->t, &msg, &keepalive_done, cc, NULL);
}
}
+void
+set_monotime_sig (struct GNUNET_CADET_ConnectionCreateMessage *msg)
+{
+
+ struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
+ GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
+ .purpose.size = htonl (sizeof(cp)),
+ .monotonic_time = msg->monotime};
+
+ GNUNET_CRYPTO_eddsa_sign (my_private_key, &cp,
+ &msg->monotime_sig);
+
+}
+
/**
* Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the
* first hop.
struct GNUNET_CADET_ConnectionCreateMessage *create_msg;
struct GNUNET_PeerIdentity *pids;
struct GNUNET_MQ_Envelope *env;
+ struct CadetTunnel *t;
cc->task = NULL;
GNUNET_assert (GNUNET_YES == cc->mqm_ready);
// TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated 'reliable' bit here that was removed.
create_msg->options = 2;
create_msg->cid = cc->cid;
+
+ // check for tunnel state and set signed monotime (xrs,t3ss)
+ t = GCP_get_tunnel (cc->destination, GNUNET_YES);
+ if ((NULL != t)&& (GCT_get_estate (t) == CADET_TUNNEL_KEY_UNINITIALIZED) &&
+ (GCT_alice_or_betty (GCP_get_id (cc->destination)) == GNUNET_NO))
+ {
+ create_msg->has_monotime = GNUNET_YES;
+ create_msg->monotime = GNUNET_TIME_absolute_hton (
+ GNUNET_TIME_absolute_get_monotonic (cfg));
+ set_monotime_sig (create_msg);
+ }
+
pids = (struct GNUNET_PeerIdentity *) &create_msg[1];
pids[0] = my_full_id;
for (unsigned int i = 0; i <= cc->off; i++)
cc = GNUNET_new (struct CadetConnection);
cc->state = init_state;
cc->ct = ct;
+ cc->destination = destination; /* xrs,t3ss,lurchi*/
cc->cid = *cid;
cc->retry_delay =
GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, off);
GCC_handle_kx_auth (struct CadetConnection *cc,
const struct
GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg);
+struct CadetConnectionCreatePS
+{
+
+ /**
+ * Purpose is #GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR
+ */
+ struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+ /**
+ * Time at the initiator when generating the signature.
+ *
+ * Note that the receiver MUST IGNORE the absolute time, and only interpret
+ * the value as a mononic time and reject "older" values than the last one
+ * observed. This is necessary as we do not want to require synchronized
+ * clocks and may not have a bidirectional communication channel.
+ *
+ * Even with this, there is no real guarantee against replay achieved here,
+ * unless the latest timestamp is persisted. Persistence should be
+ * provided via PEERSTORE if possible.
+ */
+ struct GNUNET_TIME_AbsoluteNBO monotonic_time;
+
+};
/**
* Performance metrics for a connection.
*/
static struct GNUNET_SCHEDULER_Task *timeout_task;
-
/**
* Get the route corresponding to a hash.
*
uint16_t size = ntohs (msg->header.size) - sizeof(*msg);
unsigned int path_length;
unsigned int off;
+ struct CadetTunnel *t;
path_length = size / sizeof(struct GNUNET_PeerIdentity);
if (0 == path_length)
GCP_2s (origin),
GNUNET_sh2s (&msg->cid.connection_of_tunnel));
path = GCPP_get_path_from_route (path_length - 1, pids);
+ t = GCP_get_tunnel (sender, GNUNET_YES);
+
+ // Check for CADET state in case the other side has lost the tunnel (xrs,t3ss)
+ if ((GNUNET_YES == msg->has_monotime) &&
+ (GNUNET_YES == GCP_check_and_update_monotime(origin, msg->monotime)) &&
+ ( GNUNET_OK == GCP_check_monotime_sig(origin, msg)) &&
+ (CADET_TUNNEL_KEY_OK == GCT_get_estate(t)))
+ {
+ GCT_change_estate (t, CADET_TUNNEL_KEY_UNINITIALIZED);
+ }
+
if (GNUNET_OK !=
- GCT_add_inbound_connection (GCP_get_tunnel (origin, GNUNET_YES),
+ GCT_add_inbound_connection (t,
&msg->cid,
path))
{
* to take a break if we have some connections and have searched a lot (?))
*/
#include "platform.h"
+#include "gnunet_time_lib.h"
#include "gnunet_util_lib.h"
#include "gnunet_hello_lib.h"
#include "gnunet_signatures.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.h"
#include "gnunet-service-cadet_connection.h"
#include "gnunet-service-cadet_dht.h"
-#include "gnunet-service-cadet_peer.h"
#include "gnunet-service-cadet_paths.h"
#include "gnunet-service-cadet_tunnels.h"
*/
#define MAX_OOO_QUEUE_SIZE 100
-
/**
* Data structure used to track whom we have to notify about changes
* to our message queue.
/**
* Last time we heard from this peer (currently not used!)
*/
- struct GNUNET_TIME_Absolute last_contactXXX;
+ struct GNUNET_TIME_Absolute last_connection_create;
/**
* Array of DLLs of paths traversing the peer, organized by the
env);
}
+/*
+ * FIXME: comment
+ */
+void
+GCP_update_monotime (struct CadetPeer *peer)
+{
+ peer->last_connection_create = GNUNET_TIME_absolute_get_monotonic (cfg);
+}
+
+/*
+ * FIXME: comment
+ */
+int
+GCP_check_and_update_monotime (struct CadetPeer *peer,
+ struct GNUNET_TIME_AbsoluteNBO monotime)
+{
+
+ struct GNUNET_TIME_Absolute mt = GNUNET_TIME_absolute_ntoh (monotime);
+
+ if (mt.abs_value_us > *(&peer->last_connection_create.abs_value_us))
+ {
+ peer->last_connection_create = mt;
+ return GNUNET_YES;
+ }
+ return GNUNET_NO;
+}
+
+/*
+ * FIXME: documentation here
+ */
+int
+GCP_check_monotime_sig (struct CadetPeer *peer, const struct
+ GNUNET_CADET_ConnectionCreateMessage *msg)
+{
+ // struct CadetPeer *peer;
+ // const struct GNUNET_CADET_ConnectionCreateMessage *msg;
+
+ struct CadetConnectionCreatePS cp = { .purpose.purpose = htonl (
+ GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR),
+ .purpose.size = htonl (sizeof(cp)),
+ .monotonic_time = msg->monotime};
+
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (
+ GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR,
+ &cp,
+ &msg->monotime_sig,
+ &peer->pid.public_key))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
/* end of gnunet-service-cadet-new_peer.c */
GCP_set_mq (struct CadetPeer *cp,
struct GNUNET_MQ_Handle *mq);
+int
+GCP_check_monotime_sig (struct CadetPeer *peer, const struct GNUNET_CADET_ConnectionCreateMessage *msg);
+
+void
+GCP_update_monotime (struct CadetPeer *cp);
+
+int
+GCP_check_and_update_monotime (struct CadetPeer *peer,
+ struct GNUNET_TIME_AbsoluteNBO monotime);
#endif
* @param other the other peer
* @return #GNUNET_YES for Alice, #GNUNET_NO for Betty, #GNUNET_SYSERR if talking to myself
*/
-static int
-alice_or_betty (const struct GNUNET_PeerIdentity *other)
+int
+GCT_alice_or_betty (const struct GNUNET_PeerIdentity *other)
{
if (0 > GNUNET_memcmp (&my_full_id,
other))
struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
enum GNUNET_CADET_KX_Flags flags;
- if (GNUNET_YES != alice_or_betty (GCP_get_id (t->destination)))
+ if (GNUNET_YES != GCT_alice_or_betty (GCP_get_id (t->destination)))
return; /* only Alice may send KX */
if ((NULL == ct) ||
(GNUNET_NO == ct->is_ready))
const char salt[] = "CADET Axolotl salt";
int am_I_alice;
- if (GNUNET_SYSERR == (am_I_alice = alice_or_betty (pid)))
+ if (GNUNET_SYSERR == (am_I_alice = GCT_alice_or_betty (pid)))
{
GNUNET_break_op (0);
return GNUNET_SYSERR;
1,
GNUNET_NO);
if (GNUNET_YES ==
- alice_or_betty (GCP_get_id (t->destination)))
+ GCT_alice_or_betty (GCP_get_id (t->destination)))
{
/* Betty/Bob is not allowed to send KX! */
GNUNET_break_op (0);
ch,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Adding %s to %s\n",
+ "Adding %s to %s with state %d\n",
GCCH_2s (ch),
- GCT_2s (t));
+ GCT_2s (t),
+ t->estate);
switch (t->estate)
{
case CADET_TUNNEL_KEY_UNINITIALIZED:
switch (t->estate)
{
case CADET_TUNNEL_KEY_UNINITIALIZED:
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Do not begin KX for %s if WE have no channels waiting. Retrying after %d\n",
+ GCT_2s (t),
+ GNUNET_TIME_absolute_get_remaining (t->next_kx_attempt).rel_value_us);
/* Do not begin KX if WE have no channels waiting! */
if (0 != GNUNET_TIME_absolute_get_remaining (
t->next_kx_attempt).rel_value_us)
return; /* wait for timeout before retrying */
/* We are uninitialized, just transmit immediately,
without undue delay. */
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Why for %s \n",
+ GCT_2s (t));
+
if (NULL != t->kx_task)
{
GNUNET_SCHEDULER_cancel (t->kx_task);
GCT_send (t,
&msg.header,
NULL,
- NULL);
+ NULL,
+ &ctn);
}
* @param t Tunnel on which this message is transmitted.
* @param cont Continuation to call once message is really sent.
* @param cont_cls Closure for @c cont.
+ * @param The ID of the channel we are using for sending.
* @return Handle to cancel message
*/
struct CadetTunnelQueueEntry *
GCT_send (struct CadetTunnel *t,
const struct GNUNET_MessageHeader *message,
GCT_SendContinuation cont,
- void *cont_cls)
+ void *cont_cls,
+ struct GNUNET_CADET_ChannelTunnelNumber *ctn)
{
struct CadetTunnelQueueEntry *tq;
uint16_t payload_size;
struct GNUNET_MQ_Envelope *env;
struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg;
+ struct CadetChannel *ch;
+
+ if (NULL != ctn)
+ {
+ ch = lookup_channel (t,
+ *ctn);
+ if ((NULL != ch)&& GCCH_is_type_to_drop (ch, message))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ }
if (CADET_TUNNEL_KEY_OK != t->estate)
{
CADET_TUNNEL_KEY_OK
};
+/**
+ * Am I Alice or Betty (some call her Bob), or talking to myself?
+ *
+ * @param other the other peer
+ * @return #GNUNET_YES for Alice, #GNUNET_NO for Betty, #GNUNET_SYSERR if talking to myself
+ */
+int
+GCT_alice_or_betty (const struct GNUNET_PeerIdentity *other);
/**
* Get the static string for the peer this tunnel is directed.
GCT_send (struct CadetTunnel *t,
const struct GNUNET_MessageHeader *message,
GCT_SendContinuation cont,
- void *cont_cls);
+ void *cont_cls,
+ struct GNUNET_CADET_ChannelTunnelNumber *ctn);
/**
enum CadetTunnelEState
GCT_get_estate (struct CadetTunnel *t);
+/**
+ * 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);
/**
* Handle KX message.
*/
#include <stdio.h>
#include "platform.h"
+#include "cadet.h"
#include "cadet_test_lib.h"
#include "gnunet_cadet_service.h"
#include "gnunet_statistics_service.h"
#define SPEED_REL 8
#define P2P_SIGNAL 10
#define REOPEN 11
+#define DESTROY 12
+
+/**
+ * Active peer listing operation.
+ */
+static struct GNUNET_CADET_PeersLister *plo;
+
+/*
+ * Task called to check for existing tunnel and depending on that reopen channel
+ */
+static struct GNUNET_SCHEDULER_Task *get_peers_task;
/**
* Which test are we running?
/**
* Peer ids.
*/
-static struct GNUNET_PeerIdentity *p_id[2];
+static struct GNUNET_PeerIdentity *testpeer_id[2];
+
+/**
+ * Peer ids.
+ */
+static struct GNUNET_CONFIGURATION_Handle *p_cfg[2];
/**
* Port ID
/**
* Peer ids counter.
*/
-static unsigned int p_ids;
+static unsigned int peerinfo_task_cnt;
/**
* Is the setup initialized?
*/
static struct GNUNET_SCHEDULER_Task *send_next_msg_task;
-/**
- * Cadet handle for the root peer
- */
-static struct GNUNET_CADET_Handle *h1;
-
-/**
- * Cadet handle for the first leaf peer
- */
-static struct GNUNET_CADET_Handle *h2;
-
/**
* Channel handle for the root peer
*/
*/
static struct GNUNET_TESTBED_Peer **testbed_peers;
+
+struct GNUNET_CADET_Handle **cadets_running;
+
/**
* Statistics operation handle.
*/
*/
static unsigned int msg_dropped;
+/**
+ * Drop the next cadet message of a given type..
+ *
+ * @param mq message queue
+ * @param ccn client channel number.
+ * @param type of cadet message to be dropped.
+ */
+void
+GNUNET_CADET_drop_message (struct GNUNET_MQ_Handle *mq,
+ struct GNUNET_CADET_ClientChannelNumber ccn,
+ uint16_t type);
/******************************************************************************/
disconnect_handler (void *cls,
const struct GNUNET_CADET_Channel *channel);
+static struct GNUNET_PeerIdentity *
+get_from_p_ids ()
+{
+ if (0 < GNUNET_memcmp (testpeer_id[0], testpeer_id[1]))
+ {
+ return testpeer_id[1];
+ }
+ else
+ {
+ return testpeer_id[0];
+ }
+}
+
+static struct GNUNET_CADET_Handle *
+get_from_cadets ()
+{
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "1\n");
+ if (0 < GNUNET_memcmp (testpeer_id[0], testpeer_id[1]))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "standard peer\n");
+ return cadets_running[0];
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "the other peer\n");
+ return cadets_running[peers_running - 1];
+ }
+
+}
+
+static unsigned int
+get_peer_nr (int outgoing)
+{
+ if (0 < GNUNET_memcmp (testpeer_id[0], testpeer_id[1]))
+ {
+ return GNUNET_YES == outgoing ? 0 : peers_running - 1;
+ }
+ else
+ {
+ return GNUNET_YES == outgoing ? peers_running - 1 : 0;
+ }
+}
/**
* Task to reconnect to other peer.
};
long l = (long) cls;
struct CadetTestChannelWrapper *ch;
+ static struct GNUNET_PeerIdentity *p_id;
+ static struct GNUNET_CADET_Handle *h1;
reconnect_task = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
GNUNET_CADET_channel_destroy (outgoing_ch);
outgoing_ch = NULL;
}
+ ch = GNUNET_new (struct CadetTestChannelWrapper);
+
+ p_id = get_from_p_ids ();
+ h1 = get_from_cadets ();
+
+ outgoing_ch = GNUNET_CADET_channel_create (h1,
+ ch,
+ p_id,
+ &port,
+ NULL,
+ &disconnect_handler,
+ handlers);
+ ch->ch = outgoing_ch;
+ send_test_message (outgoing_ch);
+}
+
+void
+reopen_channel ()
+{
+ struct CadetTestChannelWrapper *ch;
+ static struct GNUNET_CADET_Handle *h1;
+ static struct GNUNET_PeerIdentity *p_id;
+ struct GNUNET_MQ_MessageHandler handlers[] = {
+ GNUNET_MQ_hd_var_size (data,
+ GNUNET_MESSAGE_TYPE_DUMMY,
+ struct GNUNET_MessageHeader,
+ NULL),
+ GNUNET_MQ_handler_end ()
+ };
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "creating channel again\n");
+ p_id = get_from_p_ids ();
+ h1 = get_from_cadets ();
+
ch = GNUNET_new (struct CadetTestChannelWrapper);
outgoing_ch = GNUNET_CADET_channel_create (h1,
ch,
- p_id[1],
+ p_id,
&port,
NULL,
&disconnect_handler,
handlers);
ch->ch = outgoing_ch;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Sending second test data (after destroying the channel) on channel %p...\n",
+ outgoing_ch);
send_test_message (outgoing_ch);
}
+static void
+peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple);
+
+/**
+ * We ask the monitoring api for all the peers.
+ */
+static void
+get_peers (void *cls)
+{
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "requesting peers info!\n");
+ plo = GNUNET_CADET_list_peers (p_cfg[get_peer_nr (GNUNET_YES)],
+ &peers_callback, NULL);
+
+}
+
+/**
+ * Method called to retrieve information about all peers in CADET, called
+ * once per peer.
+ *
+ * After last peer has been reported, an additional call with NULL is done.
+ *
+ * We check the peer we are interested in, if we have a tunnel. If not, we
+ * reopen the channel
+ *
+ * @param cls Closure.
+ * @param ple information about peer, or NULL on "EOF".
+ */
+static void
+peers_callback (void *cls, const struct GNUNET_CADET_PeerListEntry *ple)
+{
+
+ const struct GNUNET_PeerIdentity *p_id;
+ const struct GNUNET_PeerIdentity *peer;
+
+
+ peer = &ple->peer;
+
+ if (NULL == ple)
+ {
+ plo = NULL;
+ return;
+ }
+ p_id = get_from_p_ids ();
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "ple->peer %s\n",
+ GNUNET_i2s_full (&ple->peer));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "p_id %s\n",
+ GNUNET_i2s_full (p_id));
+
+ if ((0 == GNUNET_memcmp (&ple->peer, p_id))&& ple->have_tunnel)
+ {
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "schedule get_peers again?\n");
+ get_peers_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME,
+ &get_peers,
+ NULL);
+
+ }
+ else if (0 == GNUNET_memcmp (&ple->peer, p_id) )
+ {
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "reopen channel\n");
+
+ reopen_channel ();
+
+ }
+}
/**
* Function called whenever an MQ-channel is destroyed, unless the destruction
struct CadetTestChannelWrapper *ch_w = cls;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Channel disconnected at %d\n",
+ "Channel disconnected at ok=%d\n",
ok);
GNUNET_assert (ch_w->ch == channel);
+
+ if ((DESTROY == test) && (3 == ok))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Reopen channel task!\n");
+ if (NULL == get_peers_task)
+ {
+ get_peers_task = GNUNET_SCHEDULER_add_now (&get_peers,
+ NULL);
+ }
+ return;
+ }
+
if (channel == incoming_ch)
{
ok++;
int size;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending test message on channel %p\n",
- channel);
+ "Sending test message on channel %u\n",
+ channel->ccn.channel_of_client);
size = size_payload;
if (GNUNET_NO == initialized)
{
"Sending DATA %u [%d bytes]\n",
data_sent, size);
}
+ else if (DESTROY == test)
+ {
+ payload = data_sent;
+ }
else
{
GNUNET_assert (0);
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- " ok: (%d/%d)\n",
+ "handle_data ok: (%d/%d)\n",
ok,
ok_goal);
data = (uint32_t *) &message[1];
payload, *counter);
}
+ if (DESTROY == test)
+ {
+ if (2 == ok)
+ {
+ ok++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "dropping message ok: (%d/%d)\n",
+ ok,
+ ok_goal);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TEST ID 0: %s\n",
+ GNUNET_i2s (testpeer_id[0]));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TEST ID 1: %s\n",
+ GNUNET_i2s (testpeer_id[1]));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "dropping message\n");
+ GNUNET_CADET_drop_message (GNUNET_CADET_get_mq (outgoing_ch),
+ outgoing_ch->ccn,
+ GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY);
+ if (NULL != outgoing_ch)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Destroying channel %p...\n",
+ outgoing_ch);
+ GNUNET_CADET_channel_destroy (outgoing_ch);
+ outgoing_ch = NULL;
+ }
+ }
+ else if (5 == ok)
+ {
+ ok++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "destroy test finished ok: (%d/%d)\n",
+ ok,
+ ok_goal);
+ disconnect_task =
+ GNUNET_SCHEDULER_add_now (&gather_stats_and_exit,
+ (void *) __LINE__);
+ // End of DESTROY test.
+ }
+ }
+
if (GNUNET_NO == initialized)
{
initialized = GNUNET_YES;
if (get_target_channel () == channel) /* Got "data" */
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received);
- if ((SPEED != test) || ( (ok_goal - 2) == ok) )
+ if ((DESTROY != test) && ((SPEED != test) || ( (ok_goal - 2) == ok)) )
{
/* Send ACK */
send_test_message (channel);
channel);
ok++;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- " ok: %d\n",
- ok);
- if (peer == peers_requested - 1)
+ "connect_handler ok: (%d/%d)\n",
+ ok,
+ ok_goal);
+
+ if (peer == get_peer_nr (GNUNET_NO))
{
- if (NULL != incoming_ch)
+ if ((DESTROY != test)&&(NULL != incoming_ch))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Duplicate incoming channel for client %lu\n",
(long) cls);
GNUNET_assert (0);
}
- if ((NULL != disconnect_task) && (REOPEN != test))
+ if ((NULL != disconnect_task) && (REOPEN != test) && (DESTROY != test))
{
GNUNET_SCHEDULER_cancel (disconnect_task);
disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
(void *) __LINE__);
}
+
/* TODO: cannot return channel as-is, in order to unify the data handlers */
ch = GNUNET_new (struct CadetTestChannelWrapper);
ch->ch = channel;
GNUNET_MQ_handler_end ()
};
struct CadetTestChannelWrapper *ch;
+ static struct GNUNET_CADET_Handle *h1;
+ static struct GNUNET_PeerIdentity *p_id;
test_task = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test: %s\n", test_name);
test = SPEED;
}
+ p_id = get_from_p_ids ();
+ h1 = get_from_cadets ();
+
ch = GNUNET_new (struct CadetTestChannelWrapper);
outgoing_ch = GNUNET_CADET_channel_create (h1,
ch,
- p_id[1],
+ p_id,
&port,
NULL,
&disconnect_handler,
handlers);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "channel created\n");
ch->ch = outgoing_ch;
- disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
- &gather_stats_and_exit,
- (void *) __LINE__);
+ if (DESTROY != test)
+ disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
+ &gather_stats_and_exit,
+ (void *) __LINE__);
if (KEEPALIVE == test)
return; /* Don't send any data. */
/**
* Callback to be called when the requested peer information is available
*
- * @param cls the closure from GNUNET_TESTBED_peer_get_information()
+ * @param cls the closure from GNUNET_TESTBED_peer_getinformation()
* @param op the operation this callback corresponds to
* @param pinfo the result; will be NULL if the operation has failed
* @param emsg error message if the operation has failed;
{
long i = (long) cls;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "ID callback for %ld\n",
- i);
if ((NULL == pinfo) ||
(NULL != emsg))
{
abort_test (__LINE__);
return;
}
- p_id[i] = pinfo->result.id;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "id: %s\n",
- GNUNET_i2s (p_id[i]));
- p_ids++;
- if (p_ids < 2)
+
+ if (GNUNET_TESTBED_PIT_IDENTITY == pinfo->pit)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ID callback for %ld\n",
+ i);
+ testpeer_id[i] = pinfo->result.id;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "id: %s\n",
+ GNUNET_i2s (testpeer_id[i]));
+ }
+ else if (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "CFG callback for %ld\n",
+ i);
+ p_cfg[i] = pinfo->result.cfg;
+ }
+ else
+ {
+ GNUNET_break (0);
+ }
+
+ peerinfo_task_cnt++;
+ if (peerinfo_task_cnt < 4)
return;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Got all IDs, starting test\n");
+ "Got all peer information, starting test\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TEST ID 0: %s\n",
+ GNUNET_i2s (testpeer_id[0]));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "TEST ID 1: %s\n",
+ GNUNET_i2s (testpeer_id[1]));
test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL);
}
peers_running = num_peers;
GNUNET_assert (peers_running == peers_requested);
testbed_peers = peers;
- h1 = cadets[0];
- h2 = cadets[num_peers - 1];
+ cadets_running = cadets;
+
disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time,
&disconnect_cadet_peers,
(void *) __LINE__);
GNUNET_TESTBED_PIT_IDENTITY,
&pi_cb,
(void *) 1L);
+ t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0],
+ GNUNET_TESTBED_PIT_CONFIGURATION,
+ &pi_cb,
+ (void *) 0L);
+ t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1],
+ GNUNET_TESTBED_PIT_CONFIGURATION,
+ &pi_cb,
+ (void *) 1L);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n");
}
// */
ok_goal = 6;
}
+ else if (strstr (argv[0], "_destroy") != NULL)
+ {
+ test = DESTROY;
+ test_name = "destroy";
+ ok_goal = 6;
+ short_time = GNUNET_TIME_relative_multiply (short_time, 5);
+ }
else
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n");
GNUNET_asprintf (&test_name, "backwards %s", test_name);
}
- p_ids = 0;
+ peerinfo_task_cnt = 0;
ports[0] = &port;
ports[1] = NULL;
GNUNET_CADET_TEST_ruN ("test_cadet_small",
DATABASE = heap
[transport]
-PLUGINS = udp
+#PLUGINS = udp
+PLUGINS = tcp
NEIGHBOUR_LIMIT = 50
#MANIPULATE_DELAY_IN = 10 ms
#MANIPULATE_DELAY_OUT = 10 ms
[rps]
IMMEDIATE_START = NO
START_ON_DEMAND = NO
+
+[rest]
+IMMEDIATE_START = NO
+START_ON_DEMAND = NO
* 1000-1009 Connection-level Messages
* 1010-1019 Channel-level Messages
* 1020-1029 Local Client-Service
- * 1030-1039 Local Service Monitoring
- * 1040-1049 Application Data
- * 1050-1059 Reserved
+ * 1030-1049 Local Service Monitoring
+ * 1050-1059 Application Data
*/
/******************************** Connection ********************************/
*/
#define GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS_END 1041
+/**
+ * Request to drop a message of type X to peer y.
+ */
+#define GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE 1042
+
/******************************** Application *******************************/
*/
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_DV_INITIATOR 37
+/**
+ * Signature by a peer that like to create a connection.
+ */
+#define GNUNET_SIGNATURE_PURPOSE_CADET_CONNECTION_INITIATOR 38
#if 0 /* keep Emacsens' auto-indent happy */
{