*/
struct GNUNET_TIME_Relative keepalive_period;
+/**
+ * Set to non-zero values to create random drops to test retransmissions.
+ */
+unsigned long long drop_percent;
+
/**
* Send a message to a client.
"need delay value");
keepalive_period = GNUNET_TIME_UNIT_MINUTES;
}
-
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_number (c,
+ "CADET",
+ "DROP_PERCENT",
+ &drop_percent))
+ {
+ drop_percent = 0;
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
+ LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n");
+ LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n");
+ LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n");
+ LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n");
+ }
my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c);
if (NULL == my_private_key)
{
*/
extern int shutting_down;
+/**
+ * Set to non-zero values to create random drops to test retransmissions.
+ */
+extern unsigned long long drop_percent;
+
/**
* Send a message to a client.
1,
GNUNET_NO);
GNUNET_MQ_discard (env);
+ if (GNUNET_YES == ch->reliable)
+ send_channel_data_ack (ch);
return;
}
crmn = crm->next;
if (ack->mid.mid == crm->data_message->mid.mid)
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Got DATA_ACK with base %u matching message %u on %s\n",
+ (unsigned int) mid_base,
+ ntohl (crm->data_message->mid.mid),
+ GCCH_2s (ch));
handle_matching_ack (ch,
crm);
found = GNUNET_YES;
continue;
}
delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base) - 1;
+ if (delta >= UINT_MAX - ch->max_pending_messages)
+ {
+ /* overflow, means crm was way in the past, so this ACK counts for it. */
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Got DATA_ACK with base %u past %u on %s\n",
+ (unsigned int) mid_base,
+ ntohl (crm->data_message->mid.mid),
+ GCCH_2s (ch));
+ handle_matching_ack (ch,
+ crm);
+ found = GNUNET_YES;
+ continue;
+ }
if (delta >= 64)
continue;
if (0 != (mid_mask & (1LLU << delta)))
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Got DATA_ACK with mask for %u on %s\n",
+ ntohl (crm->data_message->mid.mid),
+ GCCH_2s (ch));
handle_matching_ack (ch,
crm);
found = GNUNET_YES;
GCCH_2s (ch),
GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (ch->head_sent->next_retry),
GNUNET_YES));
- if (crm == ch->head_sent)
+ if (NULL == ch->head_sent->qe)
{
- /* We are the new head, need to reschedule retry task */
if (NULL != ch->retry_data_task)
GNUNET_SCHEDULER_cancel (ch->retry_data_task);
ch->retry_data_task
}
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Got LOCAL ACK, passing payload message %u to %s-%X on %s\n",
+ "Got LOCAL_ACK, passing payload message %u to %s-%X on %s\n",
ntohl (com->mid.mid),
GSC_2s (ccc->c),
ntohl (ccc->ccn.channel_of_client),
}
+/**
+ * Debug function should NEVER return true in production code, useful to
+ * simulate losses for testcases.
+ *
+ * @return #GNUNET_YES or #GNUNET_NO with the decision to drop.
+ */
+static int
+should_I_drop (void)
+{
+ if (0 == drop_percent)
+ return GNUNET_NO;
+ if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ 101) < drop_percent)
+ return GNUNET_YES;
+ return GNUNET_NO;
+}
+
+
+/**
+ * Function called when CORE took one of the messages from
+ * a message queue manager and transmitted it.
+ *
+ * @param cls the `struct CadetPeeer` where we made progress
+ */
+static void
+mqm_send_done (void *cls);
+
+
/**
* Transmit current envelope from this @a mqm.
*
{
struct CadetPeer *cp = mqm->cp;
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Sending to peer %s from MQM %p\n",
- GCP_2s (cp),
- mqm);
/* Move entry to the end of the DLL, to be fair. */
if (mqm != cp->mqm_tail)
{
cp->mqm_tail,
mqm);
}
- GNUNET_MQ_send (cp->core_mq,
- mqm->env);
- mqm->env = NULL;
cp->mqm_ready_counter--;
+ if (GNUNET_YES == should_I_drop ())
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "DROPPING message to peer %s from MQM %p\n",
+ GCP_2s (cp),
+ mqm);
+ GNUNET_MQ_discard (mqm->env);
+ mqm->env = NULL;
+ mqm_send_done (cp);
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending to peer %s from MQM %p\n",
+ GCP_2s (cp),
+ mqm);
+ GNUNET_MQ_send (cp->core_mq,
+ mqm->env);
+ mqm->env = NULL;
+ }
mqm->cb (mqm->cb_cls,
GNUNET_YES);
}
*/
struct CadetTunnelQueueEntry *tq_tail;
-
- /**
- * Ephemeral message in the queue (to avoid queueing more than one).
- */
- struct CadetConnectionQueue *ephm_hKILL;
-
- /**
- * Pong message in the queue.
- */
- struct CadetConnectionQueue *pong_hKILL;
-
/**
* How long do we wait until we retry the KX?
*/