tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / transport / gnunet-service-transport_neighbours.c
index d82112e033b507f538e182f75063506dc87394fc..3472e8ee086c70c117df3f711f1b6d805eee5542 100644 (file)
@@ -2,20 +2,20 @@
      This file is part of GNUnet.
      Copyright (C) 2010-2015 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
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
 
-     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., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 
 /**
@@ -181,7 +181,7 @@ struct GNUNET_ATS_SessionQuotaMessage
 
 
 /**
- * Message we send to the other peer to notify him that we intentionally
+ * Message we send to the other peer to notify it that we intentionally
  * are disconnecting (to reduce timeouts).  This is just a friendly
  * notification, peers must not rely on always receiving disconnect
  * messages.
@@ -573,7 +573,6 @@ neighbours_connect_notification (struct NeighbourMapEntry *n)
   connect_msg->header.size = htons (sizeof(buf));
   connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
   connect_msg->id = n->id;
-  connect_msg->quota_in = n->primary_address.bandwidth_in;
   connect_msg->quota_out = bandwidth_min;
   GST_clients_broadcast (&connect_msg->header,
                          GNUNET_NO);
@@ -616,6 +615,8 @@ neighbours_changed_notification (const struct GNUNET_PeerIdentity *peer,
                                  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
                                  struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
 {
+  (void) bandwidth_in;
+  (void) bandwidth_out;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Notifying about change for peer `%s' with address `%s' in state `%s' timing out at %s\n",
               GNUNET_i2s (peer),
@@ -712,7 +713,7 @@ set_state_and_timeout (struct NeighbourMapEntry *n,
                       struct GNUNET_TIME_Absolute timeout)
 {
   if (GNUNET_TRANSPORT_is_connected (s) &&
-      ! GNUNET_TRANSPORT_is_connected (n->state) )
+      (! GNUNET_TRANSPORT_is_connected (n->state)) )
   {
     neighbours_connect_notification (n);
     GNUNET_STATISTICS_set (GST_stats,
@@ -720,8 +721,8 @@ set_state_and_timeout (struct NeighbourMapEntry *n,
                           ++neighbours_connected,
                           GNUNET_NO);
   }
-  if (! GNUNET_TRANSPORT_is_connected (s) &&
-        GNUNET_TRANSPORT_is_connected (n->state) )
+  if ((! GNUNET_TRANSPORT_is_connected (s)) &&
+      GNUNET_TRANSPORT_is_connected (n->state) )
   {
     GNUNET_STATISTICS_set (GST_stats,
                           gettext_noop ("# peers connected"),
@@ -735,9 +736,9 @@ set_state_and_timeout (struct NeighbourMapEntry *n,
   {
     /* new timeout is earlier, reschedule master task */
     GNUNET_SCHEDULER_cancel (n->task);
-    n->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining (timeout),
-                                            &master_task,
-                                            n);
+    n->task = GNUNET_SCHEDULER_add_at (timeout,
+                                       &master_task,
+                                       n);
   }
   n->timeout = timeout;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -947,7 +948,8 @@ free_neighbour (struct NeighbourMapEntry *n)
   }
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CONTAINER_multipeermap_remove (neighbours,
-                                                       &n->id, n));
+                                                       &n->id,
+                                                      n));
 
   /* Cancel address requests for this peer */
   if (NULL != n->suggest_handle)
@@ -993,6 +995,10 @@ send_disconnect_cont (void *cls,
 {
   struct NeighbourMapEntry *n;
 
+  (void) cls;
+  (void) result;
+  (void) payload;
+  (void) physical;
   n = lookup_neighbour (target);
   if (NULL == n)
     return; /* already gone */
@@ -1131,10 +1137,12 @@ disconnect_neighbour (struct NeighbourMapEntry *n)
  * our own receive rate and informs the neighbour about
  * the new quota.
  *
- * @param n neighbour entry to change qutoa for
+ * @param n neighbour entry to change quota for
  * @param quota new quota
+ * @return #GNUNET_YES if @a n is still valid, #GNUNET_NO if
+ *   @a n was freed
  */
-static void
+static int
 set_incoming_quota (struct NeighbourMapEntry *n,
                     struct GNUNET_BANDWIDTH_Value32NBO quota)
 {
@@ -1150,23 +1158,25 @@ set_incoming_quota (struct NeighbourMapEntry *n,
     sqm.header.size = htons (sizeof (struct GNUNET_ATS_SessionQuotaMessage));
     sqm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_QUOTA);
     sqm.quota = quota.value__;
-    (void) send_with_session (n,
-                              &sqm,
-                              sizeof (sqm),
-                              UINT32_MAX - 1,
-                              GNUNET_TIME_UNIT_FOREVER_REL,
-                              GNUNET_NO,
-                              NULL, NULL);
-    return;
+    if (NULL != n->primary_address.session)
+      (void) send_with_session (n,
+                                &sqm,
+                                sizeof (sqm),
+                                UINT32_MAX - 1,
+                                GNUNET_TIME_UNIT_FOREVER_REL,
+                                GNUNET_NO,
+                                NULL, NULL);
+    return GNUNET_YES;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Disconnecting peer `%4s' due to SET_QUOTA\n",
+              "Disconnecting peer `%s' due to SET_QUOTA\n",
               GNUNET_i2s (&n->id));
   if (GNUNET_YES == test_connected (n))
     GNUNET_STATISTICS_update (GST_stats,
                               gettext_noop ("# disconnects due to quota of 0"),
                               1, GNUNET_NO);
   disconnect_neighbour (n);
+  return GNUNET_NO;
 }
 
 
@@ -1195,8 +1205,10 @@ set_primary_address (struct NeighbourMapEntry *n,
     if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
     {
       n->primary_address.bandwidth_in = bandwidth_in;
-      set_incoming_quota (n,
-                          bandwidth_in);
+      if (GNUNET_YES !=
+         set_incoming_quota (n,
+                             bandwidth_in))
+       return;
     }
     if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
     {
@@ -1236,8 +1248,10 @@ set_primary_address (struct NeighbourMapEntry *n,
   /* subsystems about address use */
   GST_validation_set_address_use (n->primary_address.address,
                                   GNUNET_YES);
-  set_incoming_quota (n,
-                      bandwidth_in);
+  if (GNUNET_YES !=
+      set_incoming_quota (n,
+                         bandwidth_in))
+    return;
   send_outbound_quota_to_clients (n);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Neighbour `%s' switched to address `%s'\n",
@@ -1393,6 +1407,14 @@ try_transmission_to_peer (struct NeighbourMapEntry *n)
   }
   if (NULL == mq)
     return;                     /* no more messages */
+  if (NULL == n->primary_address.address)
+  {
+    /* transmit_send_continuation() caused us to drop session,
+       can't try transmission anymore. */
+    return;
+  }
+
+
   GNUNET_CONTAINER_DLL_remove (n->messages_head,
                                n->messages_tail,
                                mq);
@@ -1804,6 +1826,9 @@ send_session_syn_cont (void *cls,
 {
   struct NeighbourMapEntry *n;
 
+  (void) cls;
+  (void) size_payload;
+  (void) size_on_wire;
   n = lookup_neighbour (target);
   if (NULL == n)
   {
@@ -1977,6 +2002,9 @@ send_session_syn_ack_cont (void *cls,
 {
   struct NeighbourMapEntry *n;
 
+  (void) cls;
+  (void) size_payload;
+  (void) size_on_wire;
   n = lookup_neighbour (target);
   if (NULL == n)
   {
@@ -2117,6 +2145,8 @@ inbound_bw_tracker_update (void *cls)
               "New inbound delay for peer `%s' is %llu ms\n",
               GNUNET_i2s (&n->id),
               (unsigned long long) delay.rel_value_us / 1000LL);
+  if (NULL == n->primary_address.session)
+    return;
   papi->update_inbound_delay (papi->cls,
                               &n->id,
                               n->primary_address.session,
@@ -2135,13 +2165,18 @@ setup_neighbour (const struct GNUNET_PeerIdentity *peer)
 {
   struct NeighbourMapEntry *n;
 
+  if (0 ==
+      memcmp (&GST_my_identity,
+              peer,
+              sizeof (struct GNUNET_PeerIdentity)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Cowardly refusing to consider myself my neighbour!\n");
+    return NULL;
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Creating new neighbour entry for `%s'\n",
              GNUNET_i2s (peer));
-  GNUNET_assert (0 !=
-                 memcmp (&GST_my_identity,
-                         peer,
-                         sizeof (struct GNUNET_PeerIdentity)));
   n = GNUNET_new (struct NeighbourMapEntry);
   n->id = *peer;
   n->ack_state = ACK_UNDEFINED;
@@ -2236,11 +2271,20 @@ GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message,
   scm = (const struct TransportSynMessage *) message;
   GNUNET_break_op (0 == ntohl (scm->reserved));
   ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
+  if (0 ==
+      memcmp (&GST_my_identity,
+              peer,
+              sizeof (struct GNUNET_PeerIdentity)))
+  {
+    /* loopback connection-to-self, ignore */
+    return GNUNET_SYSERR;
+  }
   n = lookup_neighbour (peer);
   if (NULL == n)
   {
     /* This is a new neighbour and set to not connected */
     n = setup_neighbour (peer);
+    GNUNET_assert (NULL != n);
   }
 
   /* Remember this SYN message in neighbour */
@@ -2310,6 +2354,7 @@ GST_neighbours_handle_session_syn (const struct GNUNET_MessageHeader *message,
     /* Get rid of remains and re-try */
     free_neighbour (n);
     n = setup_neighbour (peer);
+    GNUNET_assert (NULL != n);
     /* Remember the SYN time stamp for ACK message */
     n->ack_state = ACK_SEND_SYN_ACK;
     n->connect_ack_timestamp = ts;
@@ -2377,8 +2422,10 @@ try_run_fast_ats_update (const struct GNUNET_HELLO_Address *address,
   if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
   {
     n->primary_address.bandwidth_in = bandwidth_in;
-    set_incoming_quota (n,
-                        bandwidth_in);
+    if (GNUNET_YES !=
+       set_incoming_quota (n,
+                           bandwidth_in))
+      return GNUNET_NO;
   }
   if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
   {
@@ -2417,7 +2464,10 @@ switch_address_bl_check_cont (void *cls,
     goto cleanup;
 
   papi = GST_plugins_find (address->transport_name);
-  GNUNET_assert (NULL != papi);
+  if (NULL == papi) {
+    /* This can happen during shutdown. */
+    goto cleanup;
+  }
 
   if (GNUNET_NO == result)
   {
@@ -2487,6 +2537,12 @@ switch_address_bl_check_cont (void *cls,
   if (NULL == (n = lookup_neighbour (peer)))
   {
     n = setup_neighbour (peer);
+    if (NULL == n)
+    {
+      /* not sure how this can happen... */
+      GNUNET_break (0);
+      goto cleanup;
+    }
     n->state = GNUNET_TRANSPORT_PS_INIT_ATS;
   }
 
@@ -2780,6 +2836,7 @@ send_utilization_data (void *cls,
   uint32_t bps_out;
   struct GNUNET_TIME_Relative delta;
 
+  (void) cls;
   if ( (GNUNET_YES != test_connected (n)) ||
        (NULL == n->primary_address.address) )
     return GNUNET_OK;
@@ -2810,11 +2867,12 @@ send_utilization_data (void *cls,
 /**
  * Task transmitting utilization in a regular interval
  *
- * @param cls the 'struct NeighbourMapEntry' for which we are running
+ * @param cls the `struct NeighbourMapEntry` for which we are running
  */
 static void
 utilization_transmission (void *cls)
 {
+  (void) cls;
   util_transmission_tk = NULL;
   GNUNET_CONTAINER_multipeermap_iterate (neighbours,
                                          &send_utilization_data,
@@ -3025,7 +3083,7 @@ master_task (void *cls)
 
 /**
  * Send a ACK message to the neighbour to confirm that we
- * got his SYN_ACK.
+ * got its SYN_ACK.
  *
  * @param n neighbour to send the ACK to
  */
@@ -3070,6 +3128,7 @@ GST_neighbours_handle_session_syn_ack (const struct GNUNET_MessageHeader *messag
   struct GNUNET_TIME_Absolute ts;
   struct NeighbourMapEntry *n;
 
+  (void) session;
   if (ntohs (message->size) != sizeof (struct TransportSynMessage))
   {
     GNUNET_break_op (0);
@@ -3343,6 +3402,7 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
 {
   struct NeighbourMapEntry *n;
 
+  (void) session;
   if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader))
   {
     GNUNET_break_op (0);
@@ -3616,6 +3676,7 @@ neighbours_iterate (void *cls,
   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
 
+  (void) key;
   if (NULL != n->primary_address.address)
   {
     bandwidth_in = n->primary_address.bandwidth_in;
@@ -3708,6 +3769,7 @@ GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer)
 void
 GST_neighbours_start (unsigned int max_fds)
 {
+  (void) max_fds;
   neighbours = GNUNET_CONTAINER_multipeermap_create (NEIGHBOUR_TABLE_SIZE,
                                                      GNUNET_NO);
   util_transmission_tk = GNUNET_SCHEDULER_add_delayed (UTIL_TRANSMISSION_INTERVAL,
@@ -3731,6 +3793,8 @@ disconnect_all_neighbours (void *cls,
 {
   struct NeighbourMapEntry *n = value;
 
+  (void) cls;
+  (void) key;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Disconnecting peer `%4s' during shutdown\n",
               GNUNET_i2s (&n->id));