-consistently use struct GNUNET_HashCode
[oweals/gnunet.git] / src / core / gnunet-service-core_neighbours.c
index 12d002da805382c0e2a931b6872db1848c71a352..65b4ba41a218e1e6efe8b2c04d59e4c7c3bdffbe 100644 (file)
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
+#include "gnunet_statistics_service.h"
 #include "gnunet_transport_service.h"
-#include "gnunet_service_core.h"
-#include "gnunet_service_core-neighbours.h"
-#include "gnunet_service_core-kx.h"
+#include "gnunet-service-core.h"
+#include "gnunet-service-core_neighbours.h"
+#include "gnunet-service-core_kx.h"
+#include "gnunet-service-core_sessions.h"
+#include "gnunet_constants.h"
 
 
 /**
  * Message ready for transmission via transport service.  This struct
  * is followed by the actual content of the message.
  */
-struct MessageEntry
+struct NeighbourMessageEntry
 {
 
   /**
    * We keep messages in a doubly linked list.
    */
-  struct MessageEntry *next;
+  struct NeighbourMessageEntry *next;
 
   /**
    * We keep messages in a doubly linked list.
    */
-  struct MessageEntry *prev;
+  struct NeighbourMessageEntry *prev;
 
   /**
    * By when are we supposed to transmit this message?
@@ -73,13 +76,13 @@ struct Neighbour
    * Head of the batched message queue (already ordered, transmit
    * starting with the head).
    */
-  struct MessageEntry *message_head;
+  struct NeighbourMessageEntry *message_head;
 
   /**
    * Tail of the batched message queue (already ordered, append new
    * messages to tail).
    */
-  struct MessageEntry *message_tail;
+  struct NeighbourMessageEntry *message_tail;
 
   /**
    * Handle for pending requests for transmission to this peer
@@ -102,17 +105,6 @@ struct Neighbour
    */
   GNUNET_SCHEDULER_TaskIdentifier retry_plaintext_task;
 
-  /**
-   * Tracking bandwidth for sending to this peer.
-   */
-  struct GNUNET_BANDWIDTH_Tracker available_send_window;
-
-  /**
-   * Tracking bandwidth for sending to this peer.
-   */
-  struct GNUNET_BANDWIDTH_Tracker available_recv_window;
-
-
 };
 
 
@@ -127,7 +119,6 @@ static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
 static struct GNUNET_TRANSPORT_Handle *transport;
 
 
-
 /**
  * Find the entry for the given neighbour.
  *
@@ -138,6 +129,8 @@ static struct GNUNET_TRANSPORT_Handle *transport;
 static struct Neighbour *
 find_neighbour (const struct GNUNET_PeerIdentity *peer)
 {
+  if (NULL == neighbours)
+    return NULL;
   return GNUNET_CONTAINER_multihashmap_get (neighbours, &peer->hashPubKey);
 }
 
@@ -150,13 +143,11 @@ find_neighbour (const struct GNUNET_PeerIdentity *peer)
 static void
 free_neighbour (struct Neighbour *n)
 {
-  struct MessageEntry *m;
+  struct NeighbourMessageEntry *m;
 
-#if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Destroying neighbour entry for peer `%4s'\n",
               GNUNET_i2s (&n->peer));
-#endif
   while (NULL != (m = n->message_head))
   {
     GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
@@ -167,10 +158,15 @@ free_neighbour (struct Neighbour *n)
     GNUNET_TRANSPORT_notify_transmit_ready_cancel (n->th);
     n->th = NULL;
   }
-  if (NULL != n->kx)
+  GNUNET_STATISTICS_update (GSC_stats,
+                            gettext_noop
+                            ("# sessions terminated by transport disconnect"),
+                            1, GNUNET_NO);
+  GSC_SESSIONS_end (&n->peer);
+  if (NULL != n->kxinfo)
   {
-    GSC_KX_stop (n->kx);
-    n->kx = NULL;
+    GSC_KX_stop (n->kxinfo);
+    n->kxinfo = NULL;
   }
   if (n->retry_plaintext_task != GNUNET_SCHEDULER_NO_TASK)
   {
@@ -179,8 +175,9 @@ free_neighbour (struct Neighbour *n)
   }
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONTAINER_multihashmap_remove (neighbours,
-                                                      &n->peer.hashPubKey, n));
-  GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
+                                                       &n->peer.hashPubKey, n));
+  GNUNET_STATISTICS_set (GSC_stats,
+                         gettext_noop ("# neighbour entries allocated"),
                          GNUNET_CONTAINER_multihashmap_size (neighbours),
                          GNUNET_NO);
   GNUNET_free (n);
@@ -211,7 +208,7 @@ static size_t
 transmit_ready (void *cls, size_t size, void *buf)
 {
   struct Neighbour *n = cls;
-  struct MessageEntry *m;
+  struct NeighbourMessageEntry *m;
   size_t ret;
   char *cbuf;
 
@@ -219,40 +216,30 @@ transmit_ready (void *cls, size_t size, void *buf)
   m = n->message_head;
   if (m == NULL)
   {
-#if DEBUG_CORE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Encrypted message queue empty, no messages added to buffer for `%4s'\n",
-                GNUNET_i2s (&n->peer));
-#endif
+    GNUNET_break (0);
     return 0;
   }
-  GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, m);
+  GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
   if (buf == NULL)
   {
-#if DEBUG_CORE
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Transmission of message of type %u and size %u failed\n",
                 (unsigned int)
                 ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
                 (unsigned int) m->size);
-#endif
     GNUNET_free (m);
     process_queue (n);
     return 0;
   }
-  ret = 0;
   cbuf = buf;
   GNUNET_assert (size >= m->size);
   memcpy (cbuf, &m[1], m->size);
   ret = m->size;
-  GNUNET_BANDWIDTH_tracker_consume (&n->available_send_window, m->size);
-#if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Copied message of type %u and size %u into transport buffer for `%4s'\n",
-             (unsigned int)
-             ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
-             (unsigned int) ret, GNUNET_i2s (&n->peer));
-#endif
+              "Copied message of type %u and size %u into transport buffer for `%4s'\n",
+              (unsigned int)
+              ntohs (((struct GNUNET_MessageHeader *) &m[1])->type),
+              (unsigned int) ret, GNUNET_i2s (&n->peer));
   GNUNET_free (m);
   process_queue (n);
   GNUNET_STATISTICS_update (GSC_stats,
@@ -272,33 +259,34 @@ transmit_ready (void *cls, size_t size, void *buf)
 static void
 process_queue (struct Neighbour *n)
 {
-  struct MessageEntry *m;
+  struct NeighbourMessageEntry *m;
 
   if (n->th != NULL)
     return;                     /* request already pending */
   m = n->message_head;
   if (m == NULL)
+  {
+    /* notify sessions that the queue is empty and more messages
+     * could thus be queued now */
+    GSC_SESSIONS_solicit (&n->peer);
     return;
-#if DEBUG_CORE > 1
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Asking transport for transmission of %u bytes to `%4s' in next %llu ms\n",
               (unsigned int) m->size, GNUNET_i2s (&n->peer),
               (unsigned long long)
               GNUNET_TIME_absolute_get_remaining (m->deadline).rel_value);
-#endif
   n->th =
-       GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size,
-                                              m->priority,
-                                              GNUNET_TIME_absolute_get_remaining
-                                              (m->deadline),
-                                              &transmit_ready,
-                                              n);
+      GNUNET_TRANSPORT_notify_transmit_ready (transport, &n->peer, m->size, 0,
+                                              GNUNET_TIME_absolute_get_remaining
+                                              (m->deadline), &transmit_ready,
+                                              n);
   if (n->th != NULL)
     return;
   /* message request too large or duplicate request */
   GNUNET_break (0);
   /* discard encrypted message */
-  GNUNET_CONTAINER_DLL_remove (n->encrypted_head, n->encrypted_tail, m);
+  GNUNET_CONTAINER_DLL_remove (n->message_head, n->message_tail, m);
   GNUNET_free (m);
   process_queue (n);
 }
@@ -311,18 +299,18 @@ process_queue (struct Neighbour *n)
  *
  * @param cls closure
  * @param peer the peer that connected
- * @param ats performance data
- * @param ats_count number of entries in ats (excluding 0-termination)
+ * @param atsi performance data
+ * @param atsi_count number of entries in ats (excluding 0-termination)
  */
 static void
 handle_transport_notify_connect (void *cls,
                                  const struct GNUNET_PeerIdentity *peer,
-                                 const struct GNUNET_TRANSPORT_ATS_Information
-                                 *ats, uint32_t ats_count)
+                                 const struct GNUNET_ATS_Information *atsi,
+                                 uint32_t atsi_count)
 {
   struct Neighbour *n;
 
-  if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
+  if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
   {
     GNUNET_break (0);
     return;
@@ -334,29 +322,19 @@ handle_transport_notify_connect (void *cls,
     GNUNET_break (0);
     return;
   }
-#if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received connection from `%4s'.\n",
               GNUNET_i2s (peer));
-#endif
   n = GNUNET_malloc (sizeof (struct Neighbour));
-  n->peer = *pid;
-  GNUNET_BANDWIDTH_tracker_init (&n->available_send_window, 
-                                GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
-                                 MAX_WINDOW_TIME_S);
-  GNUNET_BANDWIDTH_tracker_init (&n->available_recv_window, 
-                                GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
-                                 MAX_WINDOW_TIME_S);
+  n->peer = *peer;
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONTAINER_multihashmap_put (neighbours,
                                                     &n->peer.hashPubKey, n,
                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  GNUNET_STATISTICS_set (stats, gettext_noop ("# neighbour entries allocated"),
+  GNUNET_STATISTICS_set (GSC_stats,
+                         gettext_noop ("# neighbour entries allocated"),
                          GNUNET_CONTAINER_multihashmap_size (neighbours),
                          GNUNET_NO);
-  GNUNET_TRANSPORT_set_quota (transport, peer, 
-                             GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, 
-                             GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT);
-  n->kx = GSC_KX_start (pid);
+  n->kxinfo = GSC_KX_start (peer);
 }
 
 
@@ -373,11 +351,9 @@ handle_transport_notify_disconnect (void *cls,
 {
   struct Neighbour *n;
 
-#if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Peer `%4s' disconnected from us; received notification from transport.\n",
               GNUNET_i2s (peer));
-#endif
   n = find_neighbour (peer);
   if (n == NULL)
   {
@@ -394,28 +370,22 @@ handle_transport_notify_disconnect (void *cls,
  * @param cls closure
  * @param peer (claimed) identity of the other peer
  * @param message the message
- * @param ats performance data
- * @param ats_count number of entries in ats (excluding 0-termination)
+ * @param atsi performance data
+ * @param atsi_count number of entries in ats (excluding 0-termination)
  */
 static void
 handle_transport_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
                           const struct GNUNET_MessageHeader *message,
-                          const struct GNUNET_TRANSPORT_ATS_Information *ats,
-                          uint32_t ats_count)
+                          const struct GNUNET_ATS_Information *atsi,
+                          uint32_t atsi_count)
 {
   struct Neighbour *n;
-  struct GNUNET_TIME_Absolute now;
-  int up;
   uint16_t type;
-  uint16_t size;
-  int changed;
 
-#if DEBUG_CORE > 1
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Received message of type %u from `%4s', demultiplexing.\n",
               (unsigned int) ntohs (message->type), GNUNET_i2s (peer));
-#endif
-  if (0 == memcmp (peer, &my_identity, sizeof (struct GNUNET_PeerIdentity)))
+  if (0 == memcmp (peer, &GSC_my_identity, sizeof (struct GNUNET_PeerIdentity)))
   {
     GNUNET_break (0);
     return;
@@ -427,132 +397,61 @@ handle_transport_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
     GNUNET_break (0);
     return;
   }
-
-
-  changed = GNUNET_NO;
-  up = (n->status == PEER_STATE_KEY_CONFIRMED);
   type = ntohs (message->type);
-  size = ntohs (message->size);
   switch (type)
   {
   case GNUNET_MESSAGE_TYPE_CORE_SET_KEY:
-    if (size != sizeof (struct SetKeyMessage))
-    {
-      GNUNET_break_op (0);
-      return;
-    }
-    GNUNET_STATISTICS_update (stats, gettext_noop ("# session keys received"),
-                              1, GNUNET_NO);
-    handle_set_key (n, (const struct SetKeyMessage *) message, ats, ats_count);
-    break;
-  case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
-    if (size <
-        sizeof (struct EncryptedMessage) + sizeof (struct GNUNET_MessageHeader))
-    {
-      GNUNET_break_op (0);
-      return;
-    }
-    if ((n->status != PEER_STATE_KEY_RECEIVED) &&
-        (n->status != PEER_STATE_KEY_CONFIRMED))
-    {
-      GNUNET_STATISTICS_update (stats,
-                                gettext_noop
-                                ("# failed to decrypt message (no session key)"),
-                                1, GNUNET_NO);
-      send_key (n);
-      return;
-    }
-    handle_encrypted_message (n, (const struct EncryptedMessage *) message, ats,
-                              ats_count);
+    GSC_KX_handle_set_key (n->kxinfo, message);
     break;
   case GNUNET_MESSAGE_TYPE_CORE_PING:
-    if (size != sizeof (struct PingMessage))
-    {
-      GNUNET_break_op (0);
-      return;
-    }
-    GNUNET_STATISTICS_update (stats, gettext_noop ("# PING messages received"),
-                              1, GNUNET_NO);
-    if ((n->status != PEER_STATE_KEY_RECEIVED) &&
-        (n->status != PEER_STATE_KEY_CONFIRMED))
-    {
-#if DEBUG_CORE > 1
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
-                  "PING", GNUNET_i2s (&n->peer));
-#endif
-      GNUNET_free_non_null (n->pending_ping);
-      n->pending_ping = GNUNET_malloc (sizeof (struct PingMessage));
-      memcpy (n->pending_ping, message, sizeof (struct PingMessage));
-      return;
-    }
-    handle_ping (n, (const struct PingMessage *) message, ats, ats_count);
+    GSC_KX_handle_ping (n->kxinfo, message);
     break;
   case GNUNET_MESSAGE_TYPE_CORE_PONG:
-    if (size != sizeof (struct PongMessage))
-    {
-      GNUNET_break_op (0);
-      return;
-    }
-    GNUNET_STATISTICS_update (stats, gettext_noop ("# PONG messages received"),
-                              1, GNUNET_NO);
-    if ((n->status != PEER_STATE_KEY_RECEIVED) &&
-        (n->status != PEER_STATE_KEY_CONFIRMED))
-    {
-#if DEBUG_CORE > 1
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Core service receives `%s' request from `%4s' but have not processed key; marking as pending.\n",
-                  "PONG", GNUNET_i2s (&n->peer));
-#endif
-      GNUNET_free_non_null (n->pending_pong);
-      n->pending_pong = GNUNET_malloc (sizeof (struct PongMessage));
-      memcpy (n->pending_pong, message, sizeof (struct PongMessage));
-      return;
-    }
-    handle_pong (n, (const struct PongMessage *) message, ats, ats_count);
+    GSC_KX_handle_pong (n->kxinfo, message);
+    break;
+  case GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE:
+    GSC_KX_handle_encrypted_message (n->kxinfo, message, atsi, atsi_count);
     break;
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("Unsupported message of type %u received.\n"),
-                (unsigned int) type);
+                _
+                ("Unsupported message of type %u (%u bytes) received from peer `%s'\n"),
+                (unsigned int) type, (unsigned int) ntohs (message->size),
+                GNUNET_i2s (peer));
     return;
   }
-  if (n->status == PEER_STATE_KEY_CONFIRMED)
-  {
-    now = GNUNET_TIME_absolute_get ();
-    n->last_activity = now;
-    changed = GNUNET_YES;
-    if (!up)
-    {
-      GNUNET_STATISTICS_update (stats, gettext_noop ("# established sessions"),
-                                1, GNUNET_NO);
-      n->time_established = now;
-    }
-    if (n->keep_alive_task != GNUNET_SCHEDULER_NO_TASK)
-      GNUNET_SCHEDULER_cancel (n->keep_alive_task);
-    n->keep_alive_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
-                                      (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
-                                       2), &send_keep_alive, n);
-  }
-  if (changed)
-    handle_peer_status_change (n);
 }
 
 
 /**
  * Transmit the given message to the given target.
- * 
+ *
  * @param target peer that should receive the message (must be connected)
  * @param msg message to transmit
  * @param timeout by when should the transmission be done?
  */
 void
-GDS_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
-                        const struct GNUNET_MessageHeader *msg,
-                        struct GNUNET_TIME_Relative timeout)
+GSC_NEIGHBOURS_transmit (const struct GNUNET_PeerIdentity *target,
+                         const struct GNUNET_MessageHeader *msg,
+                         struct GNUNET_TIME_Relative timeout)
 {
-  
+  struct NeighbourMessageEntry *me;
+  struct Neighbour *n;
+  size_t msize;
+
+  n = find_neighbour (target);
+  if (NULL == n)
+  {
+    GNUNET_break (0);
+    return;
+  }
+  msize = ntohs (msg->size);
+  me = GNUNET_malloc (sizeof (struct NeighbourMessageEntry) + msize);
+  me->deadline = GNUNET_TIME_relative_to_absolute (timeout);
+  me->size = msize;
+  memcpy (&me[1], msg, msize);
+  GNUNET_CONTAINER_DLL_insert_tail (n->message_head, n->message_tail, me);
+  process_queue (n);
 }
 
 
@@ -564,8 +463,7 @@ GSC_NEIGHBOURS_init ()
 {
   neighbours = GNUNET_CONTAINER_multihashmap_create (128);
   transport =
-      GNUNET_TRANSPORT_connect (GSC_cfg, 
-                               &GSC_my_identity, NULL,
+      GNUNET_TRANSPORT_connect (GSC_cfg, &GSC_my_identity, NULL,
                                 &handle_transport_receive,
                                 &handle_transport_notify_connect,
                                 &handle_transport_notify_disconnect);
@@ -588,10 +486,12 @@ GSC_NEIGHBOURS_init ()
  * @return GNUNET_OK (continue to iterate)
  */
 static int
-free_neighbour_helper (void *cls, const GNUNET_HashCode * key, void *value)
+free_neighbour_helper (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   struct Neighbour *n = value;
 
+  /* transport should have 'disconnected' all neighbours... */
+  GNUNET_break (0);
   free_neighbour (n);
   return GNUNET_OK;
 }
@@ -605,13 +505,12 @@ GSC_NEIGHBOURS_done ()
 {
   if (NULL == transport)
     return;
-  GNUNET_CONTAINER_multihashmap_iterate (neighbours, &free_neighbour_helper,
-                                         NULL);
   GNUNET_TRANSPORT_disconnect (transport);
   transport = NULL;
+  GNUNET_CONTAINER_multihashmap_iterate (neighbours, &free_neighbour_helper,
+                                         NULL);
   GNUNET_CONTAINER_multihashmap_destroy (neighbours);
   neighbours = NULL;
 }
 
 /* end of gnunet-service-core_neighbours.c */
-