-do not leave PPT timeout tasks behind
[oweals/gnunet.git] / src / transport / gnunet-service-transport_neighbours.c
index a2aaa19ec166e5c3bb72528d43282357f8334f08..01546ded4d059e1a58fa928012b364ae55419fe2 100644 (file)
@@ -14,8 +14,8 @@
 
      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., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
@@ -391,7 +391,7 @@ struct NeighbourMapEntry
   /**
    * Time where we should cut the connection (timeout) if we don't
    * make progress in the state machine (or get a KEEPALIVE_RESPONSE
-   * if we are in #S_CONNECTED).
+   * if we are in #GNUNET_TRANSPORT_PS_CONNECTED).
    */
   struct GNUNET_TIME_Absolute timeout;
 
@@ -2500,14 +2500,20 @@ try_run_fast_ats_update (const struct GNUNET_HELLO_Address *address,
                    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;
-  GST_neighbours_set_incoming_quota (&address->peer,
-                                     bandwidth_in);
-  bandwidth_min = GNUNET_BANDWIDTH_value_min (bandwidth_out,
-                                              n->neighbour_receive_quota);
-  send_outbound_quota_to_clients (&address->peer,
-                                  bandwidth_min);
+  if (n->primary_address.bandwidth_in.value__ != bandwidth_in.value__)
+  {
+    n->primary_address.bandwidth_in = bandwidth_in;
+    GST_neighbours_set_incoming_quota (&address->peer,
+                                       bandwidth_in);
+  }
+  if (n->primary_address.bandwidth_out.value__ != bandwidth_out.value__)
+  {
+    n->primary_address.bandwidth_out = bandwidth_out;
+    bandwidth_min = GNUNET_BANDWIDTH_value_min (bandwidth_out,
+                                                n->neighbour_receive_quota);
+    send_outbound_quota_to_clients (&address->peer,
+                                    bandwidth_min);
+  }
   return GNUNET_OK;
 }
 
@@ -3522,8 +3528,9 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
      now wait for the ACK to finally be connected
      - If we sent a SYN_ACK to this peer before */
 
-  if ( (GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) &&
-       (ACK_SEND_ACK != n->ack_state))
+  if ( ( (GNUNET_TRANSPORT_PS_SYN_RECV_ACK != n->state) &&
+        (ACK_SEND_ACK != n->ack_state) ) ||
+       (NULL == n->primary_address.address) ) 
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "Received unexpected ACK message from peer `%s' in state %s/%s\n",
@@ -3548,6 +3555,18 @@ GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
                          GNUNET_TRANSPORT_PS_CONNECTED,
                          GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT));
 
+  if (NULL == n->primary_address.address) {
+    /* See issue #3693.
+     * We are in state = PSY_SYN_RECV_ACK or ack_state = ACK_SEND_ACK, which
+     * really means we did try (and succeed) to send a SYN and are waiting for
+     * an ACK.
+     * That suggests that the primary_address used to be non-NULL, but maybe it
+     * got reset to NULL without the state being changed appropriately?
+     */
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+
   /* Reset backoff for primary address */
   GST_ats_block_reset (n->primary_address.address,
                        n->primary_address.session);
@@ -3569,7 +3588,9 @@ GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target)
 
 
 /**
- * Change the incoming quota for the given peer.
+ * Change the incoming quota for the given peer.  Updates
+ * our own receive rate and informs the neighbour about
+ * the new quota.
  *
  * @param neighbour identity of peer to change qutoa for
  * @param quota new quota
@@ -3593,7 +3614,21 @@ GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour,
               ntohl (quota.value__), GNUNET_i2s (&n->id));
   GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, quota);
   if (0 != ntohl (quota.value__))
+  {
+    struct SessionQuotaMessage sqm;
+
+    sqm.header.size = htons (sizeof (struct 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;
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Disconnecting peer `%4s' due to SET_QUOTA\n",
               GNUNET_i2s (&n->id));
@@ -3748,7 +3783,11 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity *peer
     GNUNET_break_op (0);
     return;
   }
-  n->delayed_disconnect_task = GNUNET_SCHEDULER_add_now (&delayed_disconnect, n);
+  if (NULL == n->delayed_disconnect_task)
+  {
+    n->delayed_disconnect_task = GNUNET_SCHEDULER_add_now (&delayed_disconnect,
+                                                           n);
+  }
 }