call GNUNET_SERVER_receive_done() also on internal error paths
[oweals/gnunet.git] / src / transport / gnunet-service-transport_neighbours.c
index 729de12d39bad3f327bf3d655f6e8be2db493e44..17e30c0b790c087e1fa50710426f32b7d4b7175d 100644 (file)
@@ -826,6 +826,9 @@ set_alternative_address (struct NeighbourMapEntry *n,
   n->alternative_address.session = session;
   n->alternative_address.ats_active = GNUNET_NO;
   n->alternative_address.keep_alive_nonce = 0;
+  GNUNET_assert (GNUNET_YES ==
+                 GST_ats_is_known (n->alternative_address.address,
+                                   n->alternative_address.session));
 }
 
 
@@ -890,6 +893,9 @@ set_primary_address (struct NeighbourMapEntry *n,
   n->primary_address.bandwidth_out = bandwidth_out;
   n->primary_address.session = session;
   n->primary_address.keep_alive_nonce = 0;
+  GNUNET_assert (GNUNET_YES ==
+                 GST_ats_is_known (n->primary_address.address,
+                                   n->primary_address.session));
   /* subsystems about address use */
   GST_validation_set_address_use (n->primary_address.address,
                                   GNUNET_YES);
@@ -1224,13 +1230,20 @@ disconnect_neighbour (struct NeighbourMapEntry *n)
 static void
 transmit_send_continuation (void *cls,
                             const struct GNUNET_PeerIdentity *receiver,
-                            int success, size_t size_payload, size_t physical)
+                            int success,
+                            size_t size_payload,
+                            size_t physical)
 {
   struct MessageQueue *mq = cls;
   struct NeighbourMapEntry *n;
 
   if (NULL == (n = lookup_neighbour (receiver)))
   {
+    if (NULL != mq->cont)
+      mq->cont (mq->cont_cls,
+                GNUNET_SYSERR /* not connected */,
+                size_payload,
+                0);
     GNUNET_free (mq);
     return; /* disconnect or other error while transmitting, can happen */
   }
@@ -1255,7 +1268,6 @@ transmit_send_continuation (void *cls,
     GNUNET_break (0);
   }
 
-
   GNUNET_break (size_payload == mq->message_buf_size);
   bytes_in_send_queue -= mq->message_buf_size;
   GNUNET_STATISTICS_set (GST_stats,
@@ -1327,9 +1339,9 @@ try_transmission_to_peer (struct NeighbourMapEntry *n)
     if (timeout.rel_value_us > 0)
       break;
     GNUNET_STATISTICS_update (GST_stats,
-                             gettext_noop
-                             ("# messages timed out while in transport queue"),
-                             1, GNUNET_NO);
+                             gettext_noop ("# messages timed out while in transport queue"),
+                             1,
+                              GNUNET_NO);
     GNUNET_CONTAINER_DLL_remove (n->messages_head,
                                  n->messages_tail,
                                  mq);
@@ -1384,10 +1396,11 @@ send_keepalive (struct NeighbourMapEntry *n)
 
   nonce = 0; /* 0 indicates 'not set' */
   while (0 == nonce)
-    nonce = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX);
+    nonce = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                      UINT32_MAX);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending keep alive to peer `%s' with nonce %u\n",
+              "Sending KEEPALIVE to peer `%s' with nonce %u\n",
               GNUNET_i2s (&n->id),
               nonce);
   m.header.size = htons (sizeof (struct SessionKeepAliveMessage));
@@ -1402,7 +1415,7 @@ send_keepalive (struct NeighbourMapEntry *n)
                                GNUNET_YES,
                               NULL, NULL);
   GNUNET_STATISTICS_update (GST_stats,
-                            gettext_noop ("# keepalives sent"),
+                            gettext_noop ("# KEEPALIVES sent"),
                             1,
                            GNUNET_NO);
   n->primary_address.keep_alive_nonce = nonce;
@@ -1428,9 +1441,12 @@ GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour,
   struct SessionKeepAliveMessage msg;
 
   if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size))
+  {
+    GNUNET_break_op (0);
     return;
+  }
 
-  msg_in = (struct SessionKeepAliveMessage *) m;
+  msg_in = (const struct SessionKeepAliveMessage *) m;
   if (NULL == (n = lookup_neighbour (neighbour)))
   {
     GNUNET_STATISTICS_update (GST_stats,
@@ -1449,8 +1465,13 @@ GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour,
   }
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-      "Received keep alive request from peer `%s' with nonce %u\n",
-      GNUNET_i2s (&n->id), ntohl (msg_in->nonce));
+              "Received KEEPALIVE request from peer `%s' with nonce %u\n",
+              GNUNET_i2s (&n->id),
+              ntohl (msg_in->nonce));
+  GNUNET_STATISTICS_update (GST_stats,
+                            gettext_noop ("# KEEPALIVES received in good order"),
+                            1,
+                           GNUNET_NO);
 
   /* send reply to allow neighbour to measure latency */
   msg.header.size = htons (sizeof (struct SessionKeepAliveMessage));
@@ -1484,50 +1505,56 @@ GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour,
   struct GNUNET_TIME_Relative latency;
 
   if (sizeof (struct SessionKeepAliveMessage) != ntohs (m->size))
+  {
+    GNUNET_break_op (0);
     return;
+  }
 
   msg = (const struct SessionKeepAliveMessage *) m;
   if (NULL == (n = lookup_neighbour (neighbour)))
   {
     GNUNET_STATISTICS_update (GST_stats,
-                              gettext_noop
-                              ("# KEEPALIVE_RESPONSE messages discarded (not connected)"),
-                              1, GNUNET_NO);
+                              gettext_noop ("# KEEPALIVE_RESPONSEs discarded (not connected)"),
+                              1,
+                              GNUNET_NO);
     return;
   }
   if ( (GNUNET_TRANSPORT_PS_CONNECTED != n->state) ||
        (GNUNET_YES != n->expect_latency_response) )
   {
     GNUNET_STATISTICS_update (GST_stats,
-                              gettext_noop
-                              ("# KEEPALIVE_RESPONSE messages discarded (not expected)"),
-                              1, GNUNET_NO);
+                              gettext_noop ("# KEEPALIVE_RESPONSEs discarded (not expected)"),
+                              1,
+                              GNUNET_NO);
     return;
   }
   if (NULL == n->primary_address.address)
   {
     GNUNET_STATISTICS_update (GST_stats,
-                              gettext_noop
-                              ("# KEEPALIVE_RESPONSE messages discarded (address changed)"),
-                              1, GNUNET_NO);
+                              gettext_noop ("# KEEPALIVE_RESPONSEs discarded (address changed)"),
+                              1,
+                              GNUNET_NO);
     return;
   }
   if (n->primary_address.keep_alive_nonce != ntohl (msg->nonce))
   {
-    GNUNET_STATISTICS_update (GST_stats,
-                              gettext_noop
-                              ("# KEEPALIVE_RESPONSE messages discarded (wrong nonce)"),
-                              1, GNUNET_NO);
+    if (0 == n->primary_address.keep_alive_nonce)
+      GNUNET_STATISTICS_update (GST_stats,
+                                gettext_noop ("# KEEPALIVE_RESPONSEs discarded (no nonce)"),
+                                1,
+                                GNUNET_NO);
+    else
+      GNUNET_STATISTICS_update (GST_stats,
+                                gettext_noop ("# KEEPALIVE_RESPONSEs discarded (bad nonce)"),
+                                1,
+                                GNUNET_NO);
     return;
   }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received keep alive response from peer `%s' for session %p\n",
-                GNUNET_i2s (&n->id),
-                n->primary_address.session);
+  GNUNET_STATISTICS_update (GST_stats,
+                            gettext_noop ("# KEEPALIVE_RESPONSEs received (OK)"),
+                            1,
+                            GNUNET_NO);
 
-  }
 
   /* Update session timeout here */
   if (NULL != (papi = GST_plugins_find (n->primary_address.address->transport_name)))
@@ -1553,12 +1580,13 @@ GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour,
 
   latency = GNUNET_TIME_absolute_get_duration (n->last_keep_alive_time);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Latency for peer `%s' is %s\n",
+              "Received KEEPALIVE_RESPONSE from peer `%s', latency is %s\n",
               GNUNET_i2s (&n->id),
              GNUNET_STRINGS_relative_time_to_string (latency,
                                                      GNUNET_YES));
   GST_ats_update_delay (n->primary_address.address,
-                        GNUNET_TIME_relative_divide (latency, 2));
+                        GNUNET_TIME_relative_divide (latency,
+                                                     2));
 }
 
 
@@ -2119,16 +2147,6 @@ struct BlacklistCheckSwitchContext
    */
   struct GST_BlacklistCheck *blc;
 
-  /**
-   * Address we are asking the blacklist subsystem about.
-   */
-  struct GNUNET_HELLO_Address *address;
-
-  /**
-   * Session we should use in conjunction with @e address, can be NULL.
-   */
-  struct Session *session;
-
   /**
    * Inbound bandwidth that was assigned to @e address.
    */
@@ -2147,11 +2165,17 @@ struct BlacklistCheckSwitchContext
  *
  * @param cls blc_ctx bl context
  * @param peer the peer
- * @param result the result
+ * @param address address associated with the request
+ * @param session session associated with the request
+ * @param result #GNUNET_OK if the connection is allowed,
+ *               #GNUNET_NO if not,
+ *               #GNUNET_SYSERR if operation was aborted
  */
 static void
 try_connect_bl_check_cont (void *cls,
                            const struct GNUNET_PeerIdentity *peer,
+                          const struct GNUNET_HELLO_Address *address,
+                          struct Session *session,
                            int result)
 {
   struct BlacklistCheckSwitchContext *blc_ctx = cls;
@@ -2259,7 +2283,9 @@ GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
       (blc = GST_blacklist_test_allowed (target,
                                          NULL,
                                          &try_connect_bl_check_cont,
-                                         blc_ctx)))
+                                         blc_ctx,
+                                        NULL,
+                                        NULL)))
   {
     blc_ctx->blc = blc;
   }
@@ -2435,6 +2461,9 @@ try_run_fast_ats_update (const struct GNUNET_HELLO_Address *address,
     /* switch to a different session, but keeping same address; could
        happen if there is a 2nd inbound connection */
     n->primary_address.session = session;
+    GNUNET_assert (GNUNET_YES ==
+                   GST_ats_is_known (n->primary_address.address,
+                                     n->primary_address.session));
   }
   n->primary_address.bandwidth_in = bandwidth_in;
   n->primary_address.bandwidth_out = bandwidth_out;
@@ -2453,54 +2482,66 @@ try_run_fast_ats_update (const struct GNUNET_HELLO_Address *address,
  * @param cls the `struct BlacklistCheckSwitchContext` with
  *        the information about the future address
  * @param peer the peer we may switch addresses on
- * @param result #GNUNET_NO if we are not allowed to use the new
- *        address
+ * @param address address associated with the request
+ * @param session session associated with the request
+ * @param result #GNUNET_OK if the connection is allowed,
+ *               #GNUNET_NO if not,
+ *               #GNUNET_SYSERR if operation was aborted
  */
 static void
 switch_address_bl_check_cont (void *cls,
                               const struct GNUNET_PeerIdentity *peer,
+                             const struct GNUNET_HELLO_Address *address,
+                             struct Session *session,
                               int result)
 {
   struct BlacklistCheckSwitchContext *blc_ctx = cls;
   struct GNUNET_TRANSPORT_PluginFunctions *papi;
   struct NeighbourMapEntry *n;
 
-  if (result == GNUNET_NO)
+  if (GNUNET_SYSERR == result)
+    goto cleanup;
+
+  papi = GST_plugins_find (address->transport_name);
+  GNUNET_assert (NULL != papi);
+
+  if (GNUNET_NO == result)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Blacklist denied to switch to suggested address `%s' session %p for peer `%s'\n",
-                GST_plugins_a2s (blc_ctx->address),
-                blc_ctx->session,
-                GNUNET_i2s (&blc_ctx->address->peer));
+                GST_plugins_a2s (address),
+               session,
+                GNUNET_i2s (peer));
     GNUNET_STATISTICS_update (GST_stats,
                               "# ATS suggestions ignored (blacklist denied)",
                               1,
                               GNUNET_NO);
-    /* FIXME: tell plugin to force killing session here and now
-       (note: _proper_ plugin API for this does not yet exist) */
-    GST_ats_block_address (blc_ctx->address,
-                           blc_ctx->session);
+    papi->disconnect_session (papi->cls,
+                             session);
+    if (GNUNET_YES !=
+       GNUNET_HELLO_address_check_option (address,
+                                          GNUNET_HELLO_ADDRESS_INFO_INBOUND))
+      GST_ats_block_address (address,
+                            NULL);
     goto cleanup;
   }
 
-  papi = GST_plugins_find (blc_ctx->address->transport_name);
-  GNUNET_assert (NULL != papi);
 
-  if (NULL == blc_ctx->session)
+  if (NULL == session)
   {
     /* need to create a session, ATS only gave us an address */
-    blc_ctx->session = papi->get_session (papi->cls,
-                                          blc_ctx->address);
+    session = papi->get_session (papi->cls,
+                                address);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Obtained new session for peer `%s' and  address '%s': %p\n",
-                GNUNET_i2s (&blc_ctx->address->peer),
-                GST_plugins_a2s (blc_ctx->address),
-                blc_ctx->session);
-    if (NULL != blc_ctx->session)
-      GST_ats_new_session (blc_ctx->address,
-                           blc_ctx->session);
+                GNUNET_i2s (&address->peer),
+                GST_plugins_a2s (address),
+                session);
+    if (NULL != session)
+      GST_ats_new_session (address,
+                           session);
   }
-  if (NULL == blc_ctx->session)
+  if (NULL == session)
   {
     /* session creation failed, bad!, fail! */
     GNUNET_STATISTICS_update (GST_stats,
@@ -2510,10 +2551,10 @@ switch_address_bl_check_cont (void *cls,
     /* No session could be obtained, remove blacklist check and clean up */
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Failed to obtain new session for peer `%s' and address '%s'\n",
-                GNUNET_i2s (&blc_ctx->address->peer),
-                GST_plugins_a2s (blc_ctx->address));
-    GST_ats_block_address (blc_ctx->address,
-                           blc_ctx->session);
+                GNUNET_i2s (&address->peer),
+                GST_plugins_a2s (address));
+    GST_ats_block_address (address,
+                           session);
     goto cleanup;
   }
 
@@ -2521,8 +2562,8 @@ switch_address_bl_check_cont (void *cls,
      it is theoretically possible that the situation changed in
      the meantime, hence we check again here */
   if (GNUNET_OK ==
-      try_run_fast_ats_update (blc_ctx->address,
-                               blc_ctx->session,
+      try_run_fast_ats_update (address,
+                               session,
                                blc_ctx->bandwidth_in,
                                blc_ctx->bandwidth_out))
     goto cleanup; /* was just a minor update, we're done */
@@ -2536,23 +2577,23 @@ switch_address_bl_check_cont (void *cls,
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Peer `%s' switches to address `%s'\n",
-              GNUNET_i2s (&blc_ctx->address->peer),
-              GST_plugins_a2s (blc_ctx->address));
+              GNUNET_i2s (&address->peer),
+              GST_plugins_a2s (address));
 
   switch (n->state)
   {
   case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
     GNUNET_break (0);
-    GST_ats_block_address (blc_ctx->address,
-                           blc_ctx->session);
+    GST_ats_block_address (address,
+                           session);
     free_neighbour (n);
     return;
   case GNUNET_TRANSPORT_PS_INIT_ATS:
     /* We requested an address and ATS suggests one:
      * set primary address and send SYN message*/
     set_primary_address (n,
-                         blc_ctx->address,
-                         blc_ctx->session,
+                         address,
+                         session,
                          blc_ctx->bandwidth_in,
                          blc_ctx->bandwidth_out);
     if (ACK_SEND_SYN_ACK == n->ack_state)
@@ -2572,8 +2613,8 @@ switch_address_bl_check_cont (void *cls,
      * Switch and send new SYN */
     /* ATS suggests a different address, switch again */
     set_primary_address (n,
-                         blc_ctx->address,
-                         blc_ctx->session,
+                         address,
+                         session,
                          blc_ctx->bandwidth_in,
                          blc_ctx->bandwidth_out);
     if (ACK_SEND_SYN_ACK == n->ack_state)
@@ -2592,8 +2633,8 @@ switch_address_bl_check_cont (void *cls,
     /* We requested an address and ATS suggests one:
      * set primary address and send SYN_ACK message*/
     set_primary_address (n,
-                         blc_ctx->address,
-                         blc_ctx->session,
+                         address,
+                         session,
                          blc_ctx->bandwidth_in,
                          blc_ctx->bandwidth_out);
     /* Send an ACK message as a response to the SYN msg */
@@ -2616,8 +2657,8 @@ switch_address_bl_check_cont (void *cls,
                             n->connect_ack_timestamp);
     }
     set_primary_address (n,
-                         blc_ctx->address,
-                         blc_ctx->session,
+                        address,
+                         session,
                          blc_ctx->bandwidth_in,
                          blc_ctx->bandwidth_out);
     set_state_and_timeout (n,
@@ -2627,12 +2668,12 @@ switch_address_bl_check_cont (void *cls,
   case GNUNET_TRANSPORT_PS_CONNECTED:
     GNUNET_assert (NULL != n->primary_address.address);
     GNUNET_assert (NULL != n->primary_address.session);
-    GNUNET_break (n->primary_address.session != blc_ctx->session);
+    GNUNET_break (n->primary_address.session != session);
     /* ATS asks us to switch a life connection; see if we can get
        a SYN_ACK on it before we actually do this! */
     set_alternative_address (n,
-                             blc_ctx->address,
-                             blc_ctx->session,
+                             address,
+                             session,
                              blc_ctx->bandwidth_in,
                              blc_ctx->bandwidth_out);
     set_state_and_timeout (n,
@@ -2646,8 +2687,8 @@ switch_address_bl_check_cont (void *cls,
     break;
   case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
     set_primary_address (n,
-                         blc_ctx->address,
-                         blc_ctx->session,
+                         address,
+                         session,
                          blc_ctx->bandwidth_in,
                          blc_ctx->bandwidth_out);
     if (ACK_SEND_SYN_ACK == n->ack_state)
@@ -2666,8 +2707,8 @@ switch_address_bl_check_cont (void *cls,
     /* ATS asks us to switch while we were trying to reconnect; switch to new
        address and send SYN again */
     set_primary_address (n,
-                         blc_ctx->address,
-                         blc_ctx->session,
+                         address,
+                         session,
                          blc_ctx->bandwidth_in,
                          blc_ctx->bandwidth_out);
     set_state_and_timeout (n,
@@ -2677,8 +2718,8 @@ switch_address_bl_check_cont (void *cls,
     break;
   case GNUNET_TRANSPORT_PS_SWITCH_SYN_SENT:
     if ( (0 == GNUNET_HELLO_address_cmp (n->primary_address.address,
-                                         blc_ctx->address)) &&
-         (n->primary_address.session == blc_ctx->session) )
+                                         address)) &&
+         (n->primary_address.session == session) )
     {
       /* ATS switches back to still-active session */
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2691,8 +2732,8 @@ switch_address_bl_check_cont (void *cls,
     }
     /* ATS asks us to switch a life connection, send */
     set_alternative_address (n,
-                             blc_ctx->address,
-                             blc_ctx->session,
+                            address,
+                             session,
                              blc_ctx->bandwidth_in,
                              blc_ctx->bandwidth_out);
     set_state_and_timeout (n,
@@ -2721,7 +2762,6 @@ switch_address_bl_check_cont (void *cls,
   GNUNET_CONTAINER_DLL_remove (pending_bc_head,
                                pending_bc_tail,
                                blc_ctx);
-  GNUNET_HELLO_address_free (blc_ctx->address);
   GNUNET_free (blc_ctx);
 }
 
@@ -2789,8 +2829,6 @@ GST_neighbours_switch_to_address (const struct GNUNET_HELLO_Address *address,
 
   /* Perform blacklist check */
   blc_ctx = GNUNET_new (struct BlacklistCheckSwitchContext);
-  blc_ctx->address = GNUNET_HELLO_address_copy (address);
-  blc_ctx->session = session;
   blc_ctx->bandwidth_in = bandwidth_in;
   blc_ctx->bandwidth_out = bandwidth_out;
   GNUNET_CONTAINER_DLL_insert (pending_bc_head,
@@ -2799,7 +2837,9 @@ GST_neighbours_switch_to_address (const struct GNUNET_HELLO_Address *address,
   if (NULL != (blc = GST_blacklist_test_allowed (&address->peer,
                                                  address->transport_name,
                                                  &switch_address_bl_check_cont,
-                                                 blc_ctx)))
+                                                 blc_ctx,
+                                                address,
+                                                session)))
   {
     blc_ctx->blc = blc;
   }
@@ -3367,6 +3407,9 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
     /* Destroy the inbound address since it cannot be used */
     free_address (&n->primary_address);
     n->primary_address = n->alternative_address;
+    GNUNET_assert (GNUNET_YES ==
+                   GST_ats_is_known (n->primary_address.address,
+                                     n->primary_address.session));
     memset (&n->alternative_address,
             0,
             sizeof (struct NeighbourAddress));
@@ -3452,7 +3495,8 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
                 print_ack_state (n->ack_state));
 
     GNUNET_STATISTICS_update (GST_stats,
-                              gettext_noop ("# unexpected ACK messages"), 1,
+                              gettext_noop ("# unexpected ACK messages"),
+                              1,
                               GNUNET_NO);
     return GNUNET_OK;
   }
@@ -3467,7 +3511,7 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
                          GNUNET_TRANSPORT_PS_CONNECTED,
                          GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
 
-  /* Reset backoff for primary address  */
+  /* Reset backoff for primary address */
   GST_ats_block_reset (n->primary_address.address,
                        n->primary_address.session);
   return GNUNET_OK;
@@ -3813,8 +3857,6 @@ GST_neighbours_stop ()
       GST_blacklist_test_cancel (cur->blc);
       cur->blc = NULL;
     }
-    if (NULL != cur->address)
-      GNUNET_HELLO_address_free (cur->address);
     GNUNET_free (cur);
   }
 }