*
* TODO:
* - Optimize ACKs by using 'mid_futures' properly!
+ * - calculate current RTT if possible, use that for initial retransmissions
+ * (NOTE: needs us to learn which connection the tunnel uses for the message!)
* - introduce shutdown so we can have half-closed channels, modify
* destroy to include MID to have FIN-ACK equivalents, etc.
* - estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
+ * (and figure out how/where to use this!)
* - check that '0xFFULL' really is sufficient for flow control!
+ * (this is right now a big HACK!)
* - revisit handling of 'unreliable' traffic!
+ * (has not seen enough review)
+ * - revisit handling of 'unbuffered' traffic!
+ * (has not seen enough review)
* - revisit handling of 'out-of-order' option, especially in combination with/without 'reliable'.
* - figure out flow control without ACKs (unreliable traffic!)
*/
struct GNUNET_CADET_LocalAck *ack;
struct CadetChannelClient *ccc;
+ ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
+ if (NULL == ccc)
+ {
+ /* This can happen if we are just getting ACKs after
+ our local client already disconnected. */
+ GNUNET_assert (GNUNET_YES == ch->destroy);
+ return;
+ }
env = GNUNET_MQ_msg (ack,
GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
- ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
ack->ccn = ccc->ccn;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
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;
return GNUNET_NO;
}
+
/**
* Function called once the tunnel has sent one of our messages.
* If the message is unreliable, simply frees the `crm`. If the
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),