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.
*/
--- /dev/null
+/*
+ This file is part of GNUnet.
+ Copyright (C) 2011, 2017, 2019 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+*/
+/**
+ * @file cadet/cadet_api_drop_message.c
+ * @brief cadet api: client implementation of cadet service
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_constants.h"
+#include "gnunet_cadet_service.h"
+#include "cadet.h"
+#include "cadet_protocol.h"
+
+
+/**
+ * Operation handle.
+ */
+struct GNUNET_CADET_ChannelMonitor
+{
+
+ /**
+ * Channel callback.
+ */
+ GNUNET_CADET_ChannelCB channel_cb;
+
+ /**
+ * Info callback closure for @c channel_cb.
+ */
+ void *channel_cb_cls;
+
+ /**
+ * Configuration we use.
+ */
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+ /**
+ * Message queue to talk to CADET service.
+ */
+ struct GNUNET_MQ_Handle *mq;
+
+ /**
+ * Task to reconnect.
+ */
+ struct GNUNET_SCHEDULER_Task *reconnect_task;
+
+ /**
+ * Backoff for reconnect attempts.
+ */
+ struct GNUNET_TIME_Relative backoff;
+
+ /**
+ * Peer we want information about.
+ */
+ struct GNUNET_PeerIdentity peer;
+
+};
+
+
+/**
+ * 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);
+}
+
+/**
+ * Reconnect to the service and try again.
+ *
+ * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation
+ */
+static void
+reconnect (struct GNUNET_CADET_Handle *h);
+
+
+/**
+ * Function called on connection trouble. Reconnects.
+ *
+ * @param cls a `struct GNUNET_CADET_ChannelMonitor``
+ * @param error error code from MQ
+ */
+static void
+error_handler (void *cls,
+ enum GNUNET_MQ_Error error)
+{
+ struct GNUNET_CADET_ChannelMonitor *cm = cls;
+
+ GNUNET_MQ_destroy (cm->mq);
+ cm->mq = NULL;
+ cm->backoff = GNUNET_TIME_randomized_backoff (cm->backoff,
+ GNUNET_TIME_UNIT_MINUTES);
+ cm->reconnect_task = GNUNET_SCHEDULER_add_delayed (cm->backoff,
+ &reconnect,
+ cm);
+}
+
+
+/**
+ * Reconnect to the service and try again.
+ *
+ * @param cls a `struct GNUNET_CADET_ChannelMonitor` operation
+ */
+static void
+reconnect (void *clsstruct GNUNET_CADET_Handle *h)
+{
+
+ struct GNUNET_MQ_MessageHandler handlers[] = {
+ GNUNET_MQ_hd_fixed_size (drop_message,
+ GNUNET_MESSAGE_TYPE_CADET_DROP_CADET_MESSAGE,
+ struct GNUNET_CADET_RequestDropCadetMessage,
+ NULL),
+ GNUNET_MQ_handler_end ()
+ };
+ GNUNET_assert (NULL == h->mq);
+ h->mq =
+ GNUNET_CLIENT_connect (h->cfg, "cadet", handlers, &error_handler, h);
+}
+
+
+/**
+ * Request information about a specific channel of the running cadet peer.
+ *
+ * @param cfg configuration to use
+ * @param peer ID of the other end of the channel.
+ * @param callback Function to call with the requested data.
+ * @param callback_cls Closure for @c callback.
+ * @return NULL on error
+ */
+struct GNUNET_CADET_ChannelMonitor *
+GNUNET_CADET_get_channel (const struct GNUNET_CONFIGURATION_Handle *cfg,
+ struct GNUNET_PeerIdentity *peer,
+ GNUNET_CADET_ChannelCB callback,
+ void *callback_cls)
+{
+ struct GNUNET_CADET_ChannelMonitor *cm;
+
+ if (NULL == callback)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ cm = GNUNET_new (struct GNUNET_CADET_ChannelMonitor);
+ cm->channel_cb = callback;
+ cm->channel_cb_cls = callback_cls;
+ cm->cfg = cfg;
+ cm->peer = *peer;
+ reconnect (cm);
+ if (NULL == cm->mq)
+ {
+ GNUNET_free (cm);
+ return NULL;
+ }
+ return cm;
+}
+
+
+
+
+/* end of cadet_api_get_channel.c */
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.
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 */
-
/*
This file is part of GNUnet.
Copyright (C) 2001-2017 GNUnet e.V.
* empty.
*/
int destroy;
+
+ /**
+ * Type of message to be droped. See GCT_send.
+ */
+ uint16_t type GNUNET_PACKED;
+
};
+/**
+ * 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)
+{
+
+ 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;
}
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 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);
+/**
+ * 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);
/**
* Get the static string for identification of the channel.
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);
}
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ MERCHsendANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
struct GNUNET_CADET_TunnelKeyExchangeMessage *msg;
enum GNUNET_CADET_KX_Flags flags;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Will we ever send a KX message?\n");
+
if (GNUNET_YES != alice_or_betty (GCP_get_id (t->destination)))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Only Alice may send KX to %s!\n",
+ GCT_2s (t));
return; /* only Alice may send KX */
+ }
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "It is Alice!\n");
+
if ( (NULL == ct) ||
(GNUNET_NO == ct->is_ready) )
ct = get_ready_connection (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:
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);
}
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 (GCCH_is_type_to_drop(ch, message))
+ {
+ GNUNET_break(0);
+ return NULL;
+ }
+ }
+
if (CADET_TUNNEL_KEY_OK != t->estate)
{
GNUNET_break (0);
GCT_send (struct CadetTunnel *t,
const struct GNUNET_MessageHeader *message,
GCT_SendContinuation cont,
- void *cont_cls);
+ void *cont_cls,
+ struct GNUNET_CADET_ChannelTunnelNumber *ctn);
/**
#define SPEED_REL 8
#define P2P_SIGNAL 10
#define REOPEN 11
+#define DESTROY 12
/**
* Which test are we running?
if (KEEPALIVE == test)
return; /* Don't send any data. */
+ if (DESTROY == test)
+ {
+
+
+
+ }
+
data_received = 0;
data_sent = 0;
ack_received = 0;
* 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 *******************************/