From d22eacb13eb676b5c096b47c72a3fdbdb332d5a5 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Fri, 5 Jun 2020 16:37:10 +0200 Subject: Fixed bug #5822 by adding a monotonic time to the connection create message of a peer that want to start a KX, and the corresponding test #5823. Credits to dvn, lurchi and xrs for helpful discussions and coding. --- src/cadet/Makefile.am | 5 + src/cadet/cadet.h | 87 ++++++- src/cadet/cadet_api.c | 66 ----- src/cadet/cadet_protocol.h | 18 ++ src/cadet/gnunet-service-cadet.c | 112 +++++---- src/cadet/gnunet-service-cadet.h | 1 + src/cadet/gnunet-service-cadet_channel.c | 46 +++- src/cadet/gnunet-service-cadet_channel.h | 17 ++ src/cadet/gnunet-service-cadet_connection.c | 47 +++- src/cadet/gnunet-service-cadet_connection.h | 22 ++ src/cadet/gnunet-service-cadet_core.c | 15 +- src/cadet/gnunet-service-cadet_peer.c | 63 ++++- src/cadet/gnunet-service-cadet_peer.h | 9 + src/cadet/gnunet-service-cadet_tunnels.c | 43 +++- src/cadet/gnunet-service-cadet_tunnels.h | 21 +- src/cadet/test_cadet.c | 365 ++++++++++++++++++++++++---- src/cadet/test_cadet.conf | 7 +- src/include/gnunet_protocols.h | 10 +- src/include/gnunet_signatures.h | 4 + 19 files changed, 780 insertions(+), 178 deletions(-) diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am index d8d81bf20..2289a2d96 100644 --- a/src/cadet/Makefile.am +++ b/src/cadet/Makefile.am @@ -30,6 +30,7 @@ lib_LTLIBRARIES = \ 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 \ @@ -95,6 +96,7 @@ check_PROGRAMS = \ 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 \ @@ -211,6 +213,9 @@ test_cadet_5_reopen_SOURCES = \ 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; diff --git a/src/cadet/cadet.h b/src/cadet/cadet.h index 29400e39f..d17eab1d6 100644 --- a/src/cadet/cadet.h +++ b/src/cadet/cadet.h @@ -95,7 +95,6 @@ extern "C" { GNUNET_NETWORK_STRUCT_BEGIN - /** * Number uniquely identifying a channel of a client. */ @@ -111,6 +110,70 @@ struct GNUNET_CADET_ClientChannelNumber 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. @@ -252,7 +315,29 @@ struct GNUNET_CADET_LocalInfo 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. */ diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c index 3a75266b7..45cb66c1d 100644 --- a/src/cadet/cadet_api.c +++ b/src/cadet/cadet_api.c @@ -73,72 +73,6 @@ struct GNUNET_CADET_Handle 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. */ diff --git a/src/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h index e3417f8c4..08298e224 100644 --- a/src/cadet/cadet_protocol.h +++ b/src/cadet/cadet_protocol.h @@ -84,6 +84,24 @@ struct GNUNET_CADET_ConnectionCreateMessage */ 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 */ diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c index ba83fe0fc..03af3d5c0 100644 --- a/src/cadet/gnunet-service-cadet.c +++ b/src/cadet/gnunet-service-cadet.c @@ -580,6 +580,7 @@ handle_channel_create (void *cls, 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; @@ -589,6 +590,7 @@ handle_channel_create (void *cls, 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; @@ -1008,6 +1010,26 @@ handle_info_tunnels (void *cls, 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. @@ -1305,48 +1327,52 @@ run (void *cls, * 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 */ diff --git a/src/cadet/gnunet-service-cadet.h b/src/cadet/gnunet-service-cadet.h index 6da0950f1..ff216f8c3 100644 --- a/src/cadet/gnunet-service-cadet.h +++ b/src/cadet/gnunet-service-cadet.h @@ -325,4 +325,5 @@ const char * GSC_2s (struct CadetClient *c); + #endif diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c index 5c8103c5e..e6fce562f 100644 --- a/src/cadet/gnunet-service-cadet_channel.c +++ b/src/cadet/gnunet-service-cadet_channel.c @@ -380,8 +380,44 @@ struct CadetChannel * 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. @@ -594,7 +630,7 @@ send_channel_open (void *cls) 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); } @@ -818,7 +854,7 @@ send_channel_data_ack (struct CadetChannel *ch) 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); } @@ -845,7 +881,7 @@ send_open_ack (void *cls) 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); } @@ -1477,7 +1513,7 @@ retry_transmission (void *cls) "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); } @@ -1865,7 +1901,7 @@ GCCH_handle_local_data (struct CadetChannel *ch, 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; } diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h index 0a6c97329..7a072f128 100644 --- a/src/cadet/gnunet-service-cadet_channel.h +++ b/src/cadet/gnunet-service-cadet_channel.h @@ -57,6 +57,23 @@ GCCH_hash_port (struct GNUNET_HashCode *h_port, 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. diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index c07339ebc..1dac9eb1e 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c @@ -26,6 +26,7 @@ * @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" @@ -78,7 +79,6 @@ enum CadetConnectionState CADET_CONNECTION_READY }; - /** * Low-level connection to a destination. */ @@ -206,6 +206,14 @@ update_state (struct CadetConnection *cc, 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 = @@ -214,6 +222,13 @@ update_state (struct CadetConnection *cc, ((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); } @@ -392,7 +407,7 @@ send_keepalive (void *cls) 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); } @@ -580,6 +595,20 @@ GCC_handle_encrypted (struct CadetConnection *cc, } +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. @@ -593,6 +622,7 @@ send_create (void *cls) 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); @@ -603,6 +633,18 @@ send_create (void *cls) // 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++) @@ -792,6 +834,7 @@ connection_create (struct CadetPeer *destination, 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); diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h index b05c3b72c..a9ebef567 100644 --- a/src/cadet/gnunet-service-cadet_connection.h +++ b/src/cadet/gnunet-service-cadet_connection.h @@ -182,7 +182,29 @@ void 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. diff --git a/src/cadet/gnunet-service-cadet_core.c b/src/cadet/gnunet-service-cadet_core.c index d54022896..04847f906 100644 --- a/src/cadet/gnunet-service-cadet_core.c +++ b/src/cadet/gnunet-service-cadet_core.c @@ -227,7 +227,6 @@ static unsigned long long cur_buffers; */ static struct GNUNET_SCHEDULER_Task *timeout_task; - /** * Get the route corresponding to a hash. * @@ -724,6 +723,7 @@ handle_connection_create ( 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) @@ -822,8 +822,19 @@ handle_connection_create ( 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)) { diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c index 8258881d0..0ff4d1fb8 100644 --- a/src/cadet/gnunet-service-cadet_peer.c +++ b/src/cadet/gnunet-service-cadet_peer.c @@ -31,6 +31,7 @@ * 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" @@ -38,10 +39,10 @@ #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" @@ -66,7 +67,6 @@ */ #define MAX_OOO_QUEUE_SIZE 100 - /** * Data structure used to track whom we have to notify about changes * to our message queue. @@ -118,7 +118,7 @@ struct CadetPeer /** * 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 @@ -1552,5 +1552,60 @@ GCP_send_ooo (struct CadetPeer *cp, 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 */ diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h index bec0606a0..31bd23121 100644 --- a/src/cadet/gnunet-service-cadet_peer.h +++ b/src/cadet/gnunet-service-cadet_peer.h @@ -402,5 +402,14 @@ void 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 diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c index f1f2ec81f..66e7d5b1e 100644 --- a/src/cadet/gnunet-service-cadet_tunnels.c +++ b/src/cadet/gnunet-service-cadet_tunnels.c @@ -464,8 +464,8 @@ struct CadetTunnel * @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)) @@ -1345,7 +1345,7 @@ send_kx (struct CadetTunnel *t, 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)) @@ -1521,7 +1521,7 @@ update_ax_by_kx (struct CadetTunnelAxolotl *ax, 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; @@ -1726,7 +1726,7 @@ GCT_handle_kx (struct CadetTConnection *ct, 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); @@ -2123,9 +2123,10 @@ GCT_add_channel (struct CadetTunnel *t, 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: @@ -2429,12 +2430,21 @@ connection_ready_cb (void *cls, 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); @@ -3028,7 +3038,8 @@ GCT_send_channel_destroy (struct CadetTunnel *t, GCT_send (t, &msg.header, NULL, - NULL); + NULL, + &ctn); } @@ -3445,18 +3456,32 @@ GCT_handle_encrypted (struct CadetTConnection *ct, * @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) { diff --git a/src/cadet/gnunet-service-cadet_tunnels.h b/src/cadet/gnunet-service-cadet_tunnels.h index ef07badea..147f2e56f 100644 --- a/src/cadet/gnunet-service-cadet_tunnels.h +++ b/src/cadet/gnunet-service-cadet_tunnels.h @@ -80,6 +80,14 @@ enum CadetTunnelEState 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. @@ -226,7 +234,8 @@ 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); /** @@ -320,6 +329,16 @@ GCT_iterate_channels (struct CadetTunnel *t, 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. diff --git a/src/cadet/test_cadet.c b/src/cadet/test_cadet.c index 25713709c..779d3bc9f 100644 --- a/src/cadet/test_cadet.c +++ b/src/cadet/test_cadet.c @@ -25,6 +25,7 @@ */ #include #include "platform.h" +#include "cadet.h" #include "cadet_test_lib.h" #include "gnunet_cadet_service.h" #include "gnunet_statistics_service.h" @@ -74,6 +75,17 @@ struct CadetTestChannelWrapper #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? @@ -123,7 +135,12 @@ static struct GNUNET_TESTBED_Operation *t_op[2]; /** * 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 @@ -133,7 +150,7 @@ static struct GNUNET_HashCode port; /** * Peer ids counter. */ -static unsigned int p_ids; +static unsigned int peerinfo_task_cnt; /** * Is the setup initialized? @@ -195,16 +212,6 @@ static struct GNUNET_SCHEDULER_Task *test_task; */ 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 */ @@ -226,6 +233,9 @@ static struct GNUNET_TIME_Absolute start_time; */ static struct GNUNET_TESTBED_Peer **testbed_peers; + +struct GNUNET_CADET_Handle **cadets_running; + /** * Statistics operation handle. */ @@ -246,6 +256,17 @@ static unsigned int ka_received; */ 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); /******************************************************************************/ @@ -516,6 +537,49 @@ static void 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. @@ -534,6 +598,8 @@ reconnect_op (void *cls) }; 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, @@ -544,18 +610,128 @@ reconnect_op (void *cls) 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 @@ -575,9 +751,22 @@ disconnect_handler (void *cls, 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++; @@ -651,8 +840,8 @@ send_test_message (struct GNUNET_CADET_Channel *channel) 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) { @@ -699,6 +888,10 @@ send_test_message (struct GNUNET_CADET_Channel *channel) "Sending DATA %u [%d bytes]\n", data_sent, size); } + else if (DESTROY == test) + { + payload = data_sent; + } else { GNUNET_assert (0); @@ -826,7 +1019,7 @@ handle_data (void *cls, } GNUNET_log (GNUNET_ERROR_TYPE_INFO, - " ok: (%d/%d)\n", + "handle_data ok: (%d/%d)\n", ok, ok_goal); data = (uint32_t *) &message[1]; @@ -844,6 +1037,49 @@ handle_data (void *cls, 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; @@ -861,7 +1097,7 @@ handle_data (void *cls, 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); @@ -927,11 +1163,13 @@ connect_handler (void *cls, 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", @@ -947,7 +1185,7 @@ connect_handler (void *cls, (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, @@ -971,6 +1209,7 @@ connect_handler (void *cls, (void *) __LINE__); } + /* TODO: cannot return channel as-is, in order to unify the data handlers */ ch = GNUNET_new (struct CadetTestChannelWrapper); ch->ch = channel; @@ -998,6 +1237,8 @@ start_test (void *cls) 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); @@ -1012,20 +1253,25 @@ start_test (void *cls) 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. */ @@ -1054,7 +1300,7 @@ start_test (void *cls) /** * 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; @@ -1068,9 +1314,6 @@ pi_cb (void *cls, { long i = (long) cls; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "ID callback for %ld\n", - i); if ((NULL == pinfo) || (NULL != emsg)) { @@ -1080,15 +1323,40 @@ pi_cb (void *cls, 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); } @@ -1115,8 +1383,8 @@ tmain (void *cls, 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__); @@ -1130,6 +1398,14 @@ tmain (void *cls, 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"); } @@ -1272,6 +1548,13 @@ main (int argc, char *argv[]) // */ 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"); @@ -1286,7 +1569,7 @@ main (int argc, char *argv[]) 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", diff --git a/src/cadet/test_cadet.conf b/src/cadet/test_cadet.conf index 30e496aff..067dd5fb4 100644 --- a/src/cadet/test_cadet.conf +++ b/src/cadet/test_cadet.conf @@ -27,7 +27,8 @@ QUOTA = 1 MB DATABASE = heap [transport] -PLUGINS = udp +#PLUGINS = udp +PLUGINS = tcp NEIGHBOUR_LIMIT = 50 #MANIPULATE_DELAY_IN = 10 ms #MANIPULATE_DELAY_OUT = 10 ms @@ -102,3 +103,7 @@ START_ON_DEMAND = NO [rps] IMMEDIATE_START = NO START_ON_DEMAND = NO + +[rest] +IMMEDIATE_START = NO +START_ON_DEMAND = NO diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index a9cd7466a..0db6150aa 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -2734,9 +2734,8 @@ extern "C" { * 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 ********************************/ @@ -2932,6 +2931,11 @@ extern "C" { */ #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 *******************************/ diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h index a00e0372d..503113770 100644 --- a/src/include/gnunet_signatures.h +++ b/src/include/gnunet_signatures.h @@ -241,6 +241,10 @@ extern "C" */ #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 */ { -- cgit v1.2.3