-ensure stats queues do not grow too big
[oweals/gnunet.git] / src / fragmentation / defragmentation.c
index 5c4a68416d6cd00cdc04b8de8f7824ef9f829950..5433ffb5a2b06b85369b2cac1da5f4ab8eed698d 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2009, 2011 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2009, 2011 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 /**
  * @file src/fragmentation/defragmentation.c
@@ -109,13 +109,13 @@ struct MessageContext
 
   /**
    * For the current ACK round, which is the first relevant
-   * offset in 'frag_times'?
+   * offset in @e frag_times?
    */
   unsigned int frag_times_start_offset;
 
   /**
    * Which offset whould we write the next frag value into
-   * in the 'frag_times' array? All smaller entries are valid.
+   * in the @e frag_times array? All smaller entries are valid.
    */
   unsigned int frag_times_write_offset;
 
@@ -124,6 +124,11 @@ struct MessageContext
    */
   uint16_t total_size;
 
+  /**
+   * Was the last fragment we got a duplicate?
+   */
+  int16_t last_duplicate;
+
 };
 
 
@@ -185,6 +190,7 @@ struct GNUNET_DEFRAGMENT_Context
    * Maximum message size for each fragment.
    */
   uint16_t mtu;
+
 };
 
 
@@ -252,11 +258,9 @@ GNUNET_DEFRAGMENT_context_destroy (struct GNUNET_DEFRAGMENT_Context *dc)
  * Send acknowledgement to the other peer now.
  *
  * @param cls the message context
- * @param tc the scheduler context
  */
 static void
-send_ack (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+send_ack (void *cls)
 {
   struct MessageContext *mc = cls;
   struct GNUNET_DEFRAGMENT_Context *dc = mc->dc;
@@ -271,6 +275,7 @@ send_ack (void *cls,
                             _("# acknowledgements sent for fragment"),
                             1,
                             GNUNET_NO);
+  mc->last_duplicate = GNUNET_NO; /* clear flag */
   dc->ackp (dc->cls,
             mc->fragment_id,
             &fa.header);
@@ -535,11 +540,13 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
                               GNUNET_NO);
   }
 
-  /* count number of missing fragments */
+  /* count number of missing fragments after the current one */
   bc = 0;
-  for (b = 0; b < 64; b++)
+  for (b = bit; b < 64; b++)
     if (0 != (mc->bits & (1LL << b)))
       bc++;
+    else
+      bc = 0;
 
   /* notify about complete message */
   if ( (GNUNET_NO == duplicate) &&
@@ -560,23 +567,23 @@ GNUNET_DEFRAGMENT_process_fragment (struct GNUNET_DEFRAGMENT_Context *dc,
   delay = GNUNET_TIME_relative_multiply (dc->latency,
                                          bc + 1);
   if ( (last + fid == num_fragments) ||
-       ( (0 == mc->bits) &&
-         (GNUNET_YES != duplicate)) )
+       (0 == mc->bits) ||
+       (GNUNET_YES == duplicate) )
   {
     /* message complete or duplicate or last missing fragment in
        linear sequence; ACK now! */
     delay = GNUNET_TIME_UNIT_ZERO;
   }
-  if (GNUNET_YES == duplicate)
-    delay = GNUNET_TIME_relative_multiply (delay,
-                                           2);
   if (NULL != mc->ack_task)
     GNUNET_SCHEDULER_cancel (mc->ack_task);
   mc->ack_task = GNUNET_SCHEDULER_add_delayed (delay,
                                                &send_ack,
                                                mc);
   if (GNUNET_YES == duplicate)
+  {
+    mc->last_duplicate = GNUNET_YES;
     return GNUNET_NO;
+  }
   return GNUNET_YES;
 }