From 4e8df946bc7fe30a4711a8ffd9b0a737f0b73515 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Tue, 26 Feb 2019 18:16:25 +0100 Subject: [PATCH] try fix #5597 --- src/cadet/gnunet-service-cadet_channel.c | 85 +++++++++++++++++++----- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c index 9b434ea68..031da9e4d 100644 --- a/src/cadet/gnunet-service-cadet_channel.c +++ b/src/cadet/gnunet-service-cadet_channel.c @@ -1306,23 +1306,35 @@ GCCH_handle_channel_plaintext_data (struct CadetChannel *ch, &msg[1], payload_size); ccc = (NULL != ch->owner) ? ch->owner : ch->dest; - if ( (GNUNET_YES == ccc->client_ready) && - ( (GNUNET_YES == ch->out_of_order) || - (msg->mid.mid == ch->mid_recv.mid) ) ) + if (GNUNET_YES == ccc->client_ready) { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Giving %u bytes of payload with MID %u from %s to client %s\n", - (unsigned int) payload_size, - ntohl (msg->mid.mid), - GCCH_2s (ch), - GSC_2s (ccc->c)); - ccc->client_ready = GNUNET_NO; - GSC_send_to_client (ccc->c, - env); - ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); - ch->mid_futures >>= 1; - send_channel_data_ack (ch); - return; + /* + * We ad-hoc send the message if + * - The channel is out-of-order + * - The channel is reliable and MID matches next expected MID + * - The channel is unreliable and MID is before lowest seen MID + */ + if ( (GNUNET_YES == ch->out_of_order) || + ((msg->mid.mid == ch->mid_recv.mid) && + (GNUNET_YES == ch->reliable)) || + ((GNUNET_NO == ch->reliable) && + ((NULL == ccc->head_recv) || + (msg->mid.mid < ccc->head_recv->mid.mid))) ) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Giving %u bytes of payload with MID %u from %s to client %s\n", + (unsigned int) payload_size, + ntohl (msg->mid.mid), + GCCH_2s (ch), + GSC_2s (ccc->c)); + ccc->client_ready = GNUNET_NO; + GSC_send_to_client (ccc->c, + env); + ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); + ch->mid_futures >>= 1; + send_channel_data_ack (ch); + return; + } } if (GNUNET_YES == ch->reliable) @@ -1379,6 +1391,45 @@ GCCH_handle_channel_plaintext_data (struct CadetChannel *ch, } else /* ! ch->reliable */ { + struct CadetOutOfOrderMessage *next_msg; + + /** + * We always send if possible in this case. + * It is guaranteed that the queued MID < received MID + **/ + if (GNUNET_YES == ccc->client_ready) + { + next_msg = ccc->head_recv; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Giving queued MID %u from %s to client %s\n", + ntohl (next_msg->mid.mid), + GCCH_2s (ch), + GSC_2s (ccc->c)); + ccc->client_ready = GNUNET_NO; + GSC_send_to_client (ccc->c, + next_msg->env); + ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); + ch->mid_futures >>= 1; + send_channel_data_ack (ch); + GNUNET_CONTAINER_DLL_remove (ccc->head_recv, + ccc->tail_recv, + next_msg); + ccc->num_recv--; + /* Do not process duplicate MID */ + if (msg->mid.mid == next_msg->mid.mid) + { + /* Duplicate within the queue, drop */ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Duplicate message on %s (mid %u) dropped\n", + GCCH_2s (ch), + ntohl (msg->mid.mid)); + GNUNET_free (next_msg); + GNUNET_MQ_discard (env); + return; + } + GNUNET_free (next_msg); + } + /* Channel is unreliable, so we do not ACK. But we also cannot allow buffering everything, so check if we have space... */ if (ccc->num_recv >= ch->max_pending_messages) @@ -1584,7 +1635,7 @@ GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, mid_mask = GNUNET_htonll (ack->futures); found = GNUNET_NO; for (crm = ch->head_sent; - NULL != crm; + NULL != crm; crm = crmn) { crmn = crm->next; -- 2.25.1