gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r34870 - gnunet/src/cadet


From: gnunet
Subject: [GNUnet-SVN] r34870 - gnunet/src/cadet
Date: Fri, 9 Jan 2015 19:04:40 +0100

Author: bartpolot
Date: 2015-01-09 19:04:40 +0100 (Fri, 09 Jan 2015)
New Revision: 34870

Modified:
   gnunet/src/cadet/gnunet-service-cadet_connection.c
Log:
Accept Out-of-Order connection messages

Modified: gnunet/src/cadet/gnunet-service-cadet_connection.c
===================================================================
--- gnunet/src/cadet/gnunet-service-cadet_connection.c  2015-01-09 18:04:39 UTC 
(rev 34869)
+++ gnunet/src/cadet/gnunet-service-cadet_connection.c  2015-01-09 18:04:40 UTC 
(rev 34870)
@@ -83,6 +83,13 @@
   uint32_t last_pid_recv;
 
   /**
+   * Bitmap of past 32 messages received:
+   * - LSB being @c last_pid_recv.
+   * - MSB being @c last_pid_recv - 31 (mod UINTMAX).
+   */
+  uint32_t recv_bitmap;
+
+  /**
    * Last ACK sent to the peer (peer can't send more than this PID).
    */
   uint32_t last_ack_sent;
@@ -757,7 +764,7 @@
  * Get the hop in a connection.
  *
  * @param c Connection.
- * @param fwd Next hop?
+ * @param fwd Next in the FWD direction?
  *
  * @return Next peer in the connection.
  */
@@ -771,6 +778,42 @@
 
 
 /**
+ * Get a bit mask for a message received out-of-order.
+ *
+ * @param last_pid_recv Last PID we received prior to the out-of-order.
+ * @param ooo_pid PID of the out-of-order message.
+ */
+static uint32_t
+get_recv_bitmask (uint32_t last_pid_recv, uint32_t ooo_pid)
+{
+  return 1 << (last_pid_recv - ooo_pid);
+}
+
+
+/**
+ * Check is an out-of-order message is ok:
+ * - at most 31 messages behind.
+ * - not duplicate.
+ *
+ * @param last_pid_recv Last in-order PID received.
+ */
+static int
+is_ooo_ok (uint32_t last_pid_recv, uint32_t ooo_pid, uint32_t ooo_bitmap)
+{
+  uint32_t mask;
+
+  if (GC_is_pid_bigger (last_pid_recv - 31, ooo_pid))
+    return GNUNET_NO;
+
+  mask = get_recv_bitmask (last_pid_recv, ooo_pid);
+  if (0 != (ooo_bitmap & mask))
+    return GNUNET_NO;
+
+  return GNUNET_YES;
+}
+
+
+/**
  * Is traffic coming from this sender 'FWD' traffic?
  *
  * @param c Connection to check.
@@ -2054,6 +2097,7 @@
   return GNUNET_OK;
 }
 
+
 /**
  * Generic handler for cadet network encrypted traffic.
  *
@@ -2126,29 +2170,41 @@
   /* Check PID */
   fc = fwd ? &c->bck_fc : &c->fwd_fc;
   pid = ntohl (msg->pid);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u+)\n",
-       pid, fc->last_pid_recv + 1);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u - %u)\n",
+       pid, fc->last_pid_recv + 1, fc->last_ack_sent);
   if (GC_is_pid_bigger (pid, fc->last_ack_sent))
   {
     GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
     GNUNET_break_op (0);
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Received PID %u, (prev %u), ACK %u\n",
+    LOG (GNUNET_ERROR_TYPE_WARNING, "Received PID %u, (prev %u), ACK %u\n",
          pid, fc->last_pid_recv, fc->last_ack_sent);
     return GNUNET_OK;
   }
-  if (GNUNET_NO == GC_is_pid_bigger (pid, fc->last_pid_recv))
+  if (GC_is_pid_bigger (pid, fc->last_pid_recv))
   {
-    GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-                " PID %u not expected (%u+), dropping!\n",
-                pid, fc->last_pid_recv + 1);
-    return GNUNET_OK;
+    unsigned int delta;
+
+    delta = pid - fc->last_pid_recv;
+    fc->last_pid_recv = pid;
+    fc->recv_bitmap <<= delta;
+    fc->recv_bitmap |= 1;
+    LOG (GNUNET_ERROR_TYPE_WARNING, " OK bitmap %X\n", fc->recv_bitmap);
   }
+  else
+  {
+    GNUNET_STATISTICS_update (stats, "# out of order PID", 1, GNUNET_NO);
+    if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv, pid, fc->recv_bitmap))
+    {
+      LOG (GNUNET_ERROR_TYPE_WARNING, "PID %u not expected (%u+), dropping!\n",
+          pid, fc->last_pid_recv - 31);
+      return GNUNET_OK;
+    }
+    fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv, pid);
+    LOG (GNUNET_ERROR_TYPE_WARNING, " KO bitmap %X\n", fc->recv_bitmap);
+  }
   if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state)
     connection_change_state (c, CADET_CONNECTION_READY);
   connection_reset_timeout (c, fwd);
-  fc->last_pid_recv = pid;
 
   /* Is this message for us? */
   if (GCC_is_terminal (c, fwd))
@@ -2161,7 +2217,6 @@
       GNUNET_break (GNUNET_NO != c->destroy);
       return GNUNET_OK;
     }
-    fc->last_pid_recv = pid;
     GCT_handle_encrypted (c->t, msg);
     GCC_send_ack (c, fwd, GNUNET_NO);
     return GNUNET_OK;
@@ -2361,13 +2416,11 @@
   id = GNUNET_PEER_search (peer);
   if (GCP_get_short_id (get_next_hop (c)) == id)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  FWD ACK\n");
     fc = &c->fwd_fc;
     fwd = GNUNET_YES;
   }
   else if (GCP_get_short_id (get_prev_hop (c)) == id)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "  BCK ACK\n");
     fc = &c->bck_fc;
     fwd = GNUNET_NO;
   }
@@ -2378,8 +2431,8 @@
   }
 
   ack = ntohl (msg->ack);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "  ACK %u (was %u)\n",
-              ack, fc->last_ack_recv);
+  LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n",
+       GC_f2s (fwd), ack, fc->last_ack_recv);
   if (GC_is_pid_bigger (ack, fc->last_ack_recv))
     fc->last_ack_recv = ack;
 
@@ -2478,8 +2531,7 @@
 {
   unsigned int buffer;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "GMC send %s ACK on %s\n",
+  LOG (GNUNET_ERROR_TYPE_DEBUG, "GMC send %s ACK on %s\n",
        GC_f2s (fwd), GCC_2s (c));
 
   if (NULL == c)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]