- add underlay api implementation
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_connection.c
index 10fcb7b115b419bf299d7e98ac5e57806e68778a..72f7a122c037e930df59c08afcdda6528cfd1e7f 100644 (file)
@@ -221,6 +221,11 @@ struct MeshConnectionQueue
    */
   struct MeshPeerQueue *q;
 
+  /**
+   * Was this a forced message? (Do not account for it)
+   */
+  int forced;
+
   /**
    * Continuation to call once sent.
    */
@@ -499,7 +504,8 @@ send_ack (struct MeshConnection *c, unsigned int buffer, int fwd, int force)
   msg.ack = htonl (ack);
   msg.cid = c->id;
 
-  prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header, c, !fwd,
+  prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header, c,
+                                                !fwd, GNUNET_YES,
                                                 &ack_sent, prev_fc);
 }
 
@@ -526,6 +532,7 @@ message_sent (void *cls,
   struct MeshFlowControl *fc;
   struct MeshConnectionQueue *q = cls;
   double usecsperbyte;
+  int forced;
 
   fc = fwd ? &c->fwd_fc : &c->bck_fc;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -535,6 +542,7 @@ message_sent (void *cls,
   LOG (GNUNET_ERROR_TYPE_DEBUG, "!  C_P- %p %u\n", c, c->pending_messages);
   if (NULL != q)
   {
+    forced = q->forced;
     if (NULL != q->cont)
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG, "!  calling cont\n");
@@ -542,6 +550,15 @@ message_sent (void *cls,
     }
     GNUNET_free (q);
   }
+  else if (type == GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED)
+  {
+    /* If NULL == q and ENCRYPTED == type, message must have been ch_mngmnt */
+    forced = GNUNET_YES;
+  }
+  else
+  {
+    forced = GNUNET_NO;
+  }
   c->pending_messages--;
   if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
   {
@@ -555,10 +572,19 @@ message_sent (void *cls,
     case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
       fc->last_pid_sent++;
       LOG (GNUNET_ERROR_TYPE_DEBUG, "!  Q_N- %p %u\n", fc, fc->queue_n);
-      fc->queue_n--;
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "!   accounting pid %u\n",
-           fc->last_pid_sent);
+      if (GNUNET_NO == forced)
+      {
+        fc->queue_n--;
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+            "!   accounting pid %u\n",
+            fc->last_pid_sent);
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG,
+             "!   forced, Q_N not accounting pid %u\n",
+             fc->last_pid_sent);
+      }
       GMC_send_ack (c, fwd, GNUNET_NO);
       break;
 
@@ -738,18 +764,15 @@ send_broken (struct MeshConnection *c,
   msg.cid = c->id;
   msg.peer1 = *id1;
   msg.peer2 = *id2;
-  GMC_send_prebuilt_message (&msg.header, c, fwd, NULL, NULL);
+  GMC_send_prebuilt_message (&msg.header, c, fwd, GNUNET_YES, NULL, NULL);
 }
 
 
-
 /**
  * Send keepalive packets for a connection.
  *
  * @param c Connection to keep alive..
  * @param fwd Is this a FWD keepalive? (owner -> dest).
- *
- * FIXME register in GMC_send_prebuilt_message()
  */
 static void
 connection_keepalive (struct MeshConnection *c, int fwd)
@@ -766,8 +789,9 @@ connection_keepalive (struct MeshConnection *c, int fwd)
   msg->header.size = htons (size);
   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE);
   msg->cid = c->id;
+  msg->reserved = htonl (0);
 
-  GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
+  GMC_send_prebuilt_message (&msg->header, c, fwd, GNUNET_YES, NULL, NULL);
 }
 
 
@@ -999,7 +1023,8 @@ connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   msg.header.size = htons (sizeof (msg));
   msg.pid = htonl (fc->last_pid_sent);
   LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", fc->last_pid_sent);
-  fc->poll_msg = GMC_send_prebuilt_message (&msg.header, c, fc == &c->fwd_fc,
+  fc->poll_msg = GMC_send_prebuilt_message (&msg.header, c,
+                                            fc == &c->fwd_fc, GNUNET_YES,
                                             &poll_sent, fc);
 }
 
@@ -1122,7 +1147,18 @@ register_neighbors (struct MeshConnection *c)
 
   if (GNUNET_NO == GMP_is_neighbor (next_peer)
       || GNUNET_NO == GMP_is_neighbor (prev_peer))
+  {
+    if (GMC_is_origin (c, GNUNET_YES))
+      GNUNET_break (0);
+    else
+      GNUNET_break_op (0);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  register neighbors failed\n");
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  prev: %s, %d\n",
+         GMP_2s (prev_peer), GMP_is_neighbor (prev_peer));
+    LOG (GNUNET_ERROR_TYPE_DEBUG, "  next: %s, %d\n",
+         GMP_2s (next_peer), GMP_is_neighbor (next_peer));
     return GNUNET_SYSERR;
+  }
 
   GMP_add_connection (next_peer, c);
   GMP_add_connection (prev_peer, c);
@@ -1290,9 +1326,12 @@ GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
       connection_change_state (c, MESH_CONNECTION_ACK);
 
     /* Keep tunnel alive in direction dest->owner*/
-    c->bck_maintenance_task =
-      GNUNET_SCHEDULER_add_delayed (create_connection_time,
-                                    &connection_bck_keepalive, c);
+    if (GNUNET_SCHEDULER_NO_TASK == c->bck_maintenance_task)
+    {
+      c->bck_maintenance_task =
+        GNUNET_SCHEDULER_add_delayed (create_connection_time,
+                                      &connection_bck_keepalive, c);
+    }
   }
   else
   {
@@ -1300,7 +1339,7 @@ GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
     LOG (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
     GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
     GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO);
-    GMC_send_prebuilt_message (message, c, GNUNET_YES, NULL, NULL);
+    GMC_send_prebuilt_message (message, c, GNUNET_YES, GNUNET_YES, NULL, NULL);
   }
   path_destroy (path);
   return GNUNET_OK;
@@ -1424,7 +1463,7 @@ GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
   }
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
-  GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
+  GMC_send_prebuilt_message (message, c, fwd, GNUNET_YES, NULL, NULL);
   return GNUNET_OK;
 }
 
@@ -1463,7 +1502,6 @@ GMC_handle_broken (void* cls,
   }
 
   fwd = is_fwd (c, id);
-  connection_cancel_queues (c, !fwd);
   if (GMC_is_terminal (c, fwd))
   {
     if (0 < c->pending_messages)
@@ -1473,8 +1511,9 @@ GMC_handle_broken (void* cls,
   }
   else
   {
-    GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
+    GMC_send_prebuilt_message (message, c, fwd, GNUNET_YES, NULL, NULL);
     c->destroy = GNUNET_YES;
+    connection_cancel_queues (c, !fwd);
   }
 
   return GNUNET_OK;
@@ -1525,7 +1564,7 @@ GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
     GNUNET_break_op (0);
     return GNUNET_OK;
   }
-  GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
+  GMC_send_prebuilt_message (message, c, fwd, GNUNET_YES, NULL, NULL);
   c->destroy = GNUNET_YES;
   c->state = MESH_CONNECTION_DESTROYED;
 
@@ -1657,7 +1696,7 @@ handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
   }
 
   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
-  GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
+  GMC_send_prebuilt_message (&msg->header, c, fwd, GNUNET_NO, NULL, NULL);
 
   return GNUNET_OK;
 }
@@ -1754,7 +1793,7 @@ handle_mesh_kx (const struct GNUNET_PeerIdentity *peer,
   /* Message not for us: forward to next hop */
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  not for us, retransmitting...\n");
   GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
-  GMC_send_prebuilt_message (&msg->header, c, fwd, NULL, NULL);
+  GMC_send_prebuilt_message (&msg->header, c, fwd, GNUNET_NO, NULL, NULL);
 
   return GNUNET_OK;
 }
@@ -2006,7 +2045,7 @@ GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
     return GNUNET_OK;
 
   GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
-  GMC_send_prebuilt_message (message, c, fwd, NULL, NULL);
+  GMC_send_prebuilt_message (message, c, fwd, GNUNET_YES, NULL, NULL);
 
   return GNUNET_OK;
 }
@@ -2214,20 +2253,6 @@ GMC_destroy (struct MeshConnection *c)
        c->fwd_fc.poll_task, c->bck_fc.poll_task);
 
   /* Cancel maintainance task (keepalive/timeout) */
-  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
-    GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
-  if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
-    GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
-  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task)
-  {
-    GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n");
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task)
-  {
-    GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
-    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n");
-  }
   if (NULL != c->fwd_fc.poll_msg)
   {
     GMC_cancel (c->fwd_fc.poll_msg);
@@ -2249,6 +2274,20 @@ GMC_destroy (struct MeshConnection *c)
 
   if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES))
     path_destroy (c->path);
+  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
+    GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
+  if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
+    GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
+  if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task)
+  {
+    GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n");
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task)
+  {
+    GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task);
+    LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n");
+  }
 
   GNUNET_break (GNUNET_YES ==
                 GNUNET_CONTAINER_multihashmap_remove (connections, &c->id, c));
@@ -2493,6 +2532,7 @@ GMC_is_sendable (struct MeshConnection *c, int fwd)
  *                If message is not hop-by-hop, decrements TTL of copy.
  * @param c Connection on which this message is transmitted.
  * @param fwd Is this a fwd message?
+ * @param force Force the connection to accept the message (buffer overfill).
  * @param cont Continuation called once message is sent. Can be NULL.
  * @param cont_cls Closure for @c cont.
  *
@@ -2502,7 +2542,7 @@ GMC_is_sendable (struct MeshConnection *c, int fwd)
  */
 struct MeshConnectionQueue *
 GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
-                           struct MeshConnection *c, int fwd,
+                           struct MeshConnection *c, int fwd, int force,
                            GMC_sent cont, void *cont_cls)
 {
   struct MeshFlowControl *fc;
@@ -2520,7 +2560,7 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
               GM_m2s (type), size, GMC_2s (c));
 
   fc = fwd ? &c->fwd_fc : &c->bck_fc;
-  droppable = GNUNET_YES;
+  droppable = GNUNET_NO == force;
   switch (type)
   {
     struct GNUNET_MESH_Encrypted *emsg;
@@ -2544,10 +2584,17 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
       emsg->ttl = htonl (ttl - 1);
       emsg->pid = htonl (fc->next_pid++);
       LOG (GNUNET_ERROR_TYPE_DEBUG, "  Q_N+ %p %u\n", fc, fc->queue_n);
-      fc->queue_n++;
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "pid %u\n", ntohl (emsg->pid));
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "     ack recv %u\n", fc->last_ack_recv);
+      if (GNUNET_YES == droppable)
+      {
+        fc->queue_n++;
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "pid %u\n", ntohl (emsg->pid));
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent);
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "     ack recv %u\n", fc->last_ack_recv);
+      }
+      else
+      {
+        LOG (GNUNET_ERROR_TYPE_DEBUG, "  not droppable, Q_N stays the same\n");
+      }
       if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
       {
         GMC_start_poll (c, fwd);
@@ -2587,6 +2634,7 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
 
     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
     case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
+    case GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE:
       break;
 
     default:
@@ -2615,14 +2663,8 @@ GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u\n", c, c->pending_messages);
   c->pending_messages++;
 
-  if (NULL == cont)
-  {
-    (void) GMP_queue_add (get_hop (c, fwd), data, type, size, c, fwd,
-                          &message_sent, NULL);
-    return NULL;
-  }
-
   q = GNUNET_new (struct MeshConnectionQueue);
+  q->forced = !droppable;
   q->q = GMP_queue_add (get_hop (c, fwd), data, type, size, c, fwd,
                         &message_sent, q);
   if (NULL == q->q)
@@ -2671,13 +2713,16 @@ GMC_send_create (struct MeshConnection *connection)
 
   size = sizeof (struct GNUNET_MESH_ConnectionCreate);
   size += connection->path->length * sizeof (struct GNUNET_PeerIdentity);
+
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
-  GMP_queue_add (get_next_hop (connection), NULL,
-                 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
-                 size, connection, GNUNET_YES, &message_sent, NULL);
   LOG (GNUNET_ERROR_TYPE_DEBUG, "  C_P+ %p %u (create)\n",
        connection, connection->pending_messages);
   connection->pending_messages++;
+
+  GMP_queue_add (get_next_hop (connection), NULL,
+                 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
+                 size, connection, GNUNET_YES, &message_sent, NULL);
+
   state = GMT_get_cstate (connection->t);
   if (MESH_TUNNEL3_SEARCHING == state || MESH_TUNNEL3_NEW == state)
     GMT_change_cstate (connection->t, MESH_TUNNEL3_WAITING);
@@ -2711,9 +2756,11 @@ GMC_send_destroy (struct MeshConnection *c)
               GMC_2s (c));
 
   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
-    GMC_send_prebuilt_message (&msg.header, c, GNUNET_YES, NULL, NULL);
+    GMC_send_prebuilt_message (&msg.header, c,
+                               GNUNET_YES, GNUNET_YES, NULL, NULL);
   if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
-    GMC_send_prebuilt_message (&msg.header, c, GNUNET_NO, NULL, NULL);
+    GMC_send_prebuilt_message (&msg.header, c,
+                               GNUNET_NO, GNUNET_YES, NULL, NULL);
   c->destroy = GNUNET_YES;
   c->state = MESH_CONNECTION_DESTROYED;
 }