uncrustify as demanded.
[oweals/gnunet.git] / src / ats / plugin_ats2_simple.c
index 14bd2b99d546831d62076a59c7f1fb2290e42967..90566c56117f4eef212a817a4d8b7e133de59281 100644 (file)
@@ -1,19 +1,19 @@
 /*
- This file is part of GNUnet.
- Copyright (C) 2011-2015, 2018 GNUnet e.V.
  This file is part of GNUnet.
  Copyright (C) 2011-2015, 2018 GNUnet e.V.
 
- 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 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
- Affero General Public License for more details.
  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
  Affero General Public License for more details.
 
- 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/>.
  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
  */
@@ -31,7 +31,7 @@
 #include "gnunet_hello_lib.h"
 #include "gnunet_peerstore_service.h"
 
-#define LOG(kind, ...) GNUNET_log_from (kind, "ats-simple", __VA_ARGS__)
+#define LOG(kind, ...) GNUNET_log_from(kind, "ats-simple", __VA_ARGS__)
 
 
 /**
@@ -68,9 +68,7 @@ struct Peer;
 /**
  * Entry in list of addresses we could try per peer.
  */
-struct Hello
-{
-
+struct Hello {
   /**
    * Kept in a DLL.
    */
@@ -123,9 +121,7 @@ struct Hello
  * Internal representation of a session by the plugin.
  * (If desired, plugin may just use NULL.)
  */
-struct GNUNET_ATS_SessionHandle
-{
-
+struct GNUNET_ATS_SessionHandle {
   /**
    * Kept in DLL per peer.
    */
@@ -193,9 +189,7 @@ struct GNUNET_ATS_SessionHandle
  * Information about preferences and sessions we track
  * per peer.
  */
-struct Peer
-{
-
+struct Peer {
   /**
    * Kept in DLL per peer.
    */
@@ -253,9 +247,7 @@ struct Peer
 /**
  * Representation of a network (to be expanded...)
  */
-struct Network
-{
-
+struct Network {
   /**
    * Total inbound quota
    */
@@ -276,9 +268,7 @@ struct Network
 /**
  * A handle for the proportional solver
  */
-struct SimpleHandle
-{
-
+struct SimpleHandle {
   /**
    * Our execution environment.
    */
@@ -316,9 +306,9 @@ struct SimpleHandle
  * @return NULL for not found
  */
 struct Peer *
-lookup_peer (struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
+lookup_peer(struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
 {
-  return GNUNET_CONTAINER_multipeermap_get (h->peers, pid);
+  return GNUNET_CONTAINER_multipeermap_get(h->peers, pid);
 }
 
 
@@ -330,7 +320,7 @@ lookup_peer (struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
  * @return #GNUNET_YES if no information is left in @a p
  */
 static int
-peer_test_dead (struct Peer *p)
+peer_test_dead(struct Peer *p)
 {
   for (enum GNUNET_MQ_PreferenceKind pk = 0; pk < GNUNET_MQ_PREFERENCE_COUNT;
        pk++)
@@ -350,17 +340,17 @@ peer_test_dead (struct Peer *p)
  * @param hello[in,out] address suggestion to make
  */
 static void
-suggest_hello (struct Hello *hello)
+suggest_hello(struct Hello *hello)
 {
   struct Peer *p = hello->peer;
   struct SimpleHandle *h = p->h;
 
-  p->last_suggestion = hello->last_attempt = GNUNET_TIME_absolute_get ();
+  p->last_suggestion = hello->last_attempt = GNUNET_TIME_absolute_get();
   hello->backoff =
-    GNUNET_TIME_randomized_backoff (hello->backoff,
-                                    GNUNET_TIME_absolute_get_remaining (
-                                      hello->expiration));
-  h->env->suggest_cb (h->env->cls, &p->pid, hello->address);
+    GNUNET_TIME_randomized_backoff(hello->backoff,
+                                   GNUNET_TIME_absolute_get_remaining(
+                                     hello->expiration));
+  h->env->suggest_cb(h->env->cls, &p->pid, hello->address);
 }
 
 
@@ -379,7 +369,7 @@ suggest_hello (struct Hello *hello)
  * @param cls a `struct Peer`
  */
 static void
-suggest_start_cb (void *cls)
+suggest_start_cb(void *cls)
 {
   struct Peer *p = cls;
   struct GNUNET_TIME_Relative delay = GNUNET_TIME_UNIT_ZERO;
@@ -397,63 +387,63 @@ suggest_start_cb (void *cls)
   /* calculate square of number of sessions */
   num_sessions++; /* start with 1, even if we have zero sessions */
   if (num_sessions < UINT16_MAX)
-    sq = num_sessions * (uint32_t) num_sessions;
+    sq = num_sessions * (uint32_t)num_sessions;
   else
     sq = UINT32_MAX;
   xdelay =
-    GNUNET_TIME_randomized_backoff (GNUNET_TIME_relative_multiply (SUGGEST_FREQ,
-                                                                   sq),
-                                    GNUNET_TIME_UNIT_FOREVER_REL);
-  xnext = GNUNET_TIME_relative_to_absolute (xdelay);
+    GNUNET_TIME_randomized_backoff(GNUNET_TIME_relative_multiply(SUGGEST_FREQ,
+                                                                 sq),
+                                   GNUNET_TIME_UNIT_FOREVER_REL);
+  xnext = GNUNET_TIME_relative_to_absolute(xdelay);
 
   p->task = NULL;
   while (0 == delay.rel_value_us)
-  {
-    struct Hello *next;
-    struct GNUNET_TIME_Absolute xmax;
-
-    if (NULL != hello)
-    {
-      /* We went through the loop already once and found
-         a HELLO that is due *now*, so make a suggestion! */
-      GNUNET_break (NULL == hello->sh);
-      suggest_hello (hello);
-      hello = NULL;
-      hpt = GNUNET_TIME_UNIT_FOREVER_ABS;
-    }
-    for (struct Hello *pos = p->h_head; NULL != pos; pos = next)
     {
-      struct GNUNET_TIME_Absolute pt;
-
-      next = pos->next;
-      if (NULL != pos->sh)
-        continue;
-      if (0 ==
-          GNUNET_TIME_absolute_get_remaining (pos->expiration).rel_value_us)
-      {
-        /* expired, remove! */
-        GNUNET_CONTAINER_DLL_remove (p->h_head, p->h_tail, pos);
-        GNUNET_free (pos);
-        continue;
-      }
-      pt = GNUNET_TIME_absolute_add (pos->last_attempt, pos->backoff);
-      if ((NULL == hello) || (pt.abs_value_us < hpt.abs_value_us))
-      {
-        hello = pos;
-        hpt = pt;
-      }
+      struct Hello *next;
+      struct GNUNET_TIME_Absolute xmax;
+
+      if (NULL != hello)
+        {
+          /* We went through the loop already once and found
+             a HELLO that is due *now*, so make a suggestion! */
+          GNUNET_break(NULL == hello->sh);
+          suggest_hello(hello);
+          hello = NULL;
+          hpt = GNUNET_TIME_UNIT_FOREVER_ABS;
+        }
+      for (struct Hello *pos = p->h_head; NULL != pos; pos = next)
+        {
+          struct GNUNET_TIME_Absolute pt;
+
+          next = pos->next;
+          if (NULL != pos->sh)
+            continue;
+          if (0 ==
+              GNUNET_TIME_absolute_get_remaining(pos->expiration).rel_value_us)
+            {
+              /* expired, remove! */
+              GNUNET_CONTAINER_DLL_remove(p->h_head, p->h_tail, pos);
+              GNUNET_free(pos);
+              continue;
+            }
+          pt = GNUNET_TIME_absolute_add(pos->last_attempt, pos->backoff);
+          if ((NULL == hello) || (pt.abs_value_us < hpt.abs_value_us))
+            {
+              hello = pos;
+              hpt = pt;
+            }
+        }
+      if (NULL == hello)
+        return; /* no HELLOs that could still be tried */
+
+      /* hpt is now the *earliest* possible time for any HELLO
+         but we might not want to go for as early as possible for
+         this peer. So the actual time is the max of the earliest
+         HELLO and the 'xnext' */
+      xmax = GNUNET_TIME_absolute_max(hpt, xnext);
+      delay = GNUNET_TIME_absolute_get_remaining(xmax);
     }
-    if (NULL == hello)
-      return; /* no HELLOs that could still be tried */
-
-    /* hpt is now the *earliest* possible time for any HELLO
-       but we might not want to go for as early as possible for
-       this peer. So the actual time is the max of the earliest
-       HELLO and the 'xnext' */
-    xmax = GNUNET_TIME_absolute_max (hpt, xnext);
-    delay = GNUNET_TIME_absolute_get_remaining (xmax);
-  }
-  p->task = GNUNET_SCHEDULER_add_delayed (delay, &suggest_start_cb, p);
+  p->task = GNUNET_SCHEDULER_add_delayed(delay, &suggest_start_cb, p);
 }
 
 
@@ -465,9 +455,9 @@ suggest_start_cb (void *cls)
  * @param emsg error message, or NULL if no errors
  */
 static void
-watch_cb (void *cls,
-          const struct GNUNET_PEERSTORE_Record *record,
-          const char *emsg)
+watch_cb(void *cls,
+         const struct GNUNET_PEERSTORE_Record *record,
+         const char *emsg)
 {
   struct Peer *p = cls;
   char *addr;
@@ -476,65 +466,65 @@ watch_cb (void *cls,
   struct GNUNET_TIME_Absolute expiration;
   struct Hello *hello;
 
-  if (0 != GNUNET_memcmp (&p->pid, &record->peer))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  if (0 != strcmp (record->key, GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY))
-  {
-    GNUNET_break (0);
-    return;
-  }
-  addr = GNUNET_HELLO_extract_address (record->value,
-                                       record->value_size,
-                                       &p->pid,
-                                       &nt,
-                                       &expiration);
+  if (0 != GNUNET_memcmp(&p->pid, &record->peer))
+    {
+      GNUNET_break(0);
+      return;
+    }
+  if (0 != strcmp(record->key, GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY))
+    {
+      GNUNET_break(0);
+      return;
+    }
+  addr = GNUNET_HELLO_extract_address(record->value,
+                                      record->value_size,
+                                      &p->pid,
+                                      &nt,
+                                      &expiration);
   if (NULL == addr)
     return; /* invalid hello, bad signature, other problem */
-  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
-  {
-    /* expired, ignore */
-    GNUNET_free (addr);
-    return;
-  }
+  if (0 == GNUNET_TIME_absolute_get_remaining(expiration).rel_value_us)
+    {
+      /* expired, ignore */
+      GNUNET_free(addr);
+      return;
+    }
   /* check if addr is already known */
   for (struct Hello *he = p->h_head; NULL != he; he = he->next)
-  {
-    if (0 != strcmp (he->address, addr))
-      continue;
-    if (he->expiration.abs_value_us < expiration.abs_value_us)
     {
-      he->expiration = expiration;
-      he->nt = nt;
+      if (0 != strcmp(he->address, addr))
+        continue;
+      if (he->expiration.abs_value_us < expiration.abs_value_us)
+        {
+          he->expiration = expiration;
+          he->nt = nt;
+        }
+      GNUNET_free(addr);
+      return;
     }
-    GNUNET_free (addr);
-    return;
-  }
   /* create new HELLO */
-  alen = strlen (addr) + 1;
-  hello = GNUNET_malloc (sizeof (struct Hello) + alen);
-  hello->address = (const char *) &hello[1];
+  alen = strlen(addr) + 1;
+  hello = GNUNET_malloc(sizeof(struct Hello) + alen);
+  hello->address = (const char *)&hello[1];
   hello->expiration = expiration;
   hello->nt = nt;
   hello->peer = p;
-  memcpy (&hello[1], addr, alen);
-  GNUNET_CONTAINER_DLL_insert (p->h_head, p->h_tail, hello);
+  memcpy(&hello[1], addr, alen);
+  GNUNET_CONTAINER_DLL_insert(p->h_head, p->h_tail, hello);
   /* check if sh for this HELLO already exists */
   for (struct GNUNET_ATS_SessionHandle *sh = p->sh_head; NULL != sh;
        sh = sh->next)
-  {
-    if ((NULL == sh->address) || (0 != strcmp (sh->address, addr)))
-      continue;
-    GNUNET_assert (NULL == sh->hello);
-    sh->hello = hello;
-    hello->sh = sh;
-    break;
-  }
-  GNUNET_free (addr);
+    {
+      if ((NULL == sh->address) || (0 != strcmp(sh->address, addr)))
+        continue;
+      GNUNET_assert(NULL == sh->hello);
+      sh->hello = hello;
+      hello->sh = sh;
+      break;
+    }
+  GNUNET_free(addr);
   if (NULL == p->task)
-    p->task = GNUNET_SCHEDULER_add_now (&suggest_start_cb, p);
+    p->task = GNUNET_SCHEDULER_add_now(&suggest_start_cb, p);
 }
 
 
@@ -546,27 +536,27 @@ watch_cb (void *cls,
  * @return a peer handle
  */
 static struct Peer *
-peer_add (struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
+peer_add(struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
 {
-  struct Peer *p = lookup_peer (h, pid);
+  struct Peer *p = lookup_peer(h, pid);
 
   if (NULL != p)
     return p;
-  p = GNUNET_new (struct Peer);
+  p = GNUNET_new(struct Peer);
   p->h = h;
   p->pid = *pid;
-  p->wc = GNUNET_PEERSTORE_watch (h->ps,
-                                  "transport",
-                                  &p->pid,
-                                  GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
-                                  &watch_cb,
-                                  p);
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_put (
-                   h->peers,
-                   &p->pid,
-                   p,
-                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  p->wc = GNUNET_PEERSTORE_watch(h->ps,
+                                 "transport",
+                                 &p->pid,
+                                 GNUNET_PEERSTORE_TRANSPORT_URLADDRESS_KEY,
+                                 &watch_cb,
+                                 p);
+  GNUNET_assert(GNUNET_YES ==
+                GNUNET_CONTAINER_multipeermap_put(
+                  h->peers,
+                  &p->pid,
+                  p,
+                  GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 
   return p;
 }
@@ -579,31 +569,31 @@ peer_add (struct SimpleHandle *h, const struct GNUNET_PeerIdentity *pid)
  * @param p the peer to free
  */
 static void
-peer_free (struct Peer *p)
+peer_free(struct Peer *p)
 {
   struct SimpleHandle *h = p->h;
   struct Hello *hello;
 
-  GNUNET_assert (NULL == p->sh_head);
+  GNUNET_assert(NULL == p->sh_head);
   while (NULL != (hello = p->h_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (p->h_head, p->h_tail, hello);
-    GNUNET_assert (NULL == hello->sh);
-    GNUNET_free (hello);
-  }
+    {
+      GNUNET_CONTAINER_DLL_remove(p->h_head, p->h_tail, hello);
+      GNUNET_assert(NULL == hello->sh);
+      GNUNET_free(hello);
+    }
   if (NULL != p->task)
-  {
-    GNUNET_SCHEDULER_cancel (p->task);
-    p->task = NULL;
-  }
+    {
+      GNUNET_SCHEDULER_cancel(p->task);
+      p->task = NULL;
+    }
   if (NULL != p->wc)
-  {
-    GNUNET_PEERSTORE_watch_cancel (p->wc);
-    p->wc = NULL;
-  }
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multipeermap_remove (h->peers, &p->pid, p));
-  GNUNET_free (p);
+    {
+      GNUNET_PEERSTORE_watch_cancel(p->wc);
+      p->wc = NULL;
+    }
+  GNUNET_assert(GNUNET_YES ==
+                GNUNET_CONTAINER_multipeermap_remove(h->peers, &p->pid, p));
+  GNUNET_free(p);
 }
 
 
@@ -614,7 +604,7 @@ peer_free (struct Peer *p)
  * @param sh session handle to consider updating transport for
  */
 static void
-consider_notify_transport (struct GNUNET_ATS_SessionHandle *sh)
+consider_notify_transport(struct GNUNET_ATS_SessionHandle *sh)
 {
   struct Peer *peer = sh->peer;
   struct SimpleHandle *h = peer->h;
@@ -625,15 +615,15 @@ consider_notify_transport (struct GNUNET_ATS_SessionHandle *sh)
   int64_t delta_in;
   int64_t delta_out;
 
-  delay = GNUNET_TIME_absolute_get_duration (sh->last_allocation);
+  delay = GNUNET_TIME_absolute_get_duration(sh->last_allocation);
   /* A significant change is more than 10% of the quota,
      which is given in bytes/second */
   sig_in = h->networks[nt].total_quota_in * (delay.rel_value_us / 1000LL) /
            1000LL / 10;
   sig_out = h->networks[nt].total_quota_out * (delay.rel_value_us / 1000LL) /
             1000LL / 10;
-  delta_in = ((int64_t) ntohl (sh->bw_in.value__)) - ((int64_t) sh->target_in);
-  delta_out = ((int64_t) ntohl (sh->bw_in.value__)) - ((int64_t) sh->target_in);
+  delta_in = ((int64_t)ntohl(sh->bw_in.value__)) - ((int64_t)sh->target_in);
+  delta_out = ((int64_t)ntohl(sh->bw_in.value__)) - ((int64_t)sh->target_in);
   /* we want the absolute values */
   if (delta_in < 0)
     delta_in = -delta_in;
@@ -648,24 +638,23 @@ consider_notify_transport (struct GNUNET_ATS_SessionHandle *sh)
   /* change is significant, tell transport! */
   if (sh->target_in > UINT32_MAX)
     sh->target_in = UINT32_MAX;
-  sh->bw_in.value__ = htonl ((uint32_t) sh->target_in);
+  sh->bw_in.value__ = htonl((uint32_t)sh->target_in);
   if (sh->target_out > UINT32_MAX)
     sh->target_out = UINT32_MAX;
-  sh->bw_out.value__ = htonl ((uint32_t) sh->target_out);
-  sh->last_allocation = GNUNET_TIME_absolute_get ();
-  h->env->allocate_cb (h->env->cls,
-                       sh->session,
-                       &peer->pid,
-                       sh->bw_in,
-                       sh->bw_out);
+  sh->bw_out.value__ = htonl((uint32_t)sh->target_out);
+  sh->last_allocation = GNUNET_TIME_absolute_get();
+  h->env->allocate_cb(h->env->cls,
+                      sh->session,
+                      &peer->pid,
+                      sh->bw_in,
+                      sh->bw_out);
 }
 
 
 /**
  * Closure for #update_counters and #update_allocation.
  */
-struct Counters
-{
+struct Counters {
   /**
    * Plugin's state.
    */
@@ -709,100 +698,103 @@ struct Counters
  * @return #GNUNET_YES (continue to iterate)
  */
 static int
-update_counters (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
+update_counters(void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
 {
   struct Counters *c = cls;
   struct Peer *peer = value;
   struct GNUNET_ATS_SessionHandle *best[GNUNET_MQ_PREFERENCE_COUNT];
 
-  (void) pid;
+  (void)pid;
   if (NULL == peer->sh_head)
     return GNUNET_YES; /* no available session, cannot allocate bandwidth */
-  memset (best, 0, sizeof (best));
+  memset(best, 0, sizeof(best));
   for (struct GNUNET_ATS_SessionHandle *sh = peer->sh_head; NULL != sh;
        sh = sh->next)
-  {
-    enum GNUNET_NetworkType nt = sh->data->prop.nt;
-
-    sh->target_out = MIN_BANDWIDTH_PER_SESSION;
-    c->bw_out_by_nt[nt] += MIN_BANDWIDTH_PER_SESSION;
-    c->bw_in_by_nt[nt] +=
-      GNUNET_MAX (MIN_BANDWIDTH_PER_SESSION, sh->data->prop.goodput_in);
-    for (enum GNUNET_MQ_PreferenceKind pk = 0; pk < GNUNET_MQ_PREFERENCE_COUNT;
-         pk++)
     {
-      /* General rule: always prefer smaller distance if possible,
-         otherwise decide by pk: */
-      switch (pk)
-      {
-      case GNUNET_MQ_PREFERENCE_NONE:
-        break;
-      case GNUNET_MQ_PREFERENCE_BANDWIDTH:
-        /* For bandwidth, we compare the sum of transmitted bytes and
-           confirmed transmitted bytes, so confirmed data counts twice */
-        if ((NULL == best[pk]) ||
-            (sh->data->prop.distance < best[pk]->data->prop.distance) ||
-            (sh->data->prop.utilization_out + sh->data->prop.goodput_out >
-             best[pk]->data->prop.utilization_out +
-               best[pk]->data->prop.goodput_out))
-          best[pk] = sh;
-        /* If both are equal (i.e. usually this happens if there is a zero), use
-           latency as a yardstick */
-        if ((sh->data->prop.utilization_out + sh->data->prop.goodput_out ==
-             best[pk]->data->prop.utilization_out +
-               best[pk]->data->prop.goodput_out) &&
-            (sh->data->prop.distance == best[pk]->data->prop.distance) &&
-            (sh->data->prop.delay.rel_value_us <
-             best[pk]->data->prop.delay.rel_value_us))
-          best[pk] = sh;
-        break;
-      case GNUNET_MQ_PREFERENCE_LATENCY:
-        if ((NULL == best[pk]) ||
-            (sh->data->prop.distance < best[pk]->data->prop.distance) ||
-            ((sh->data->prop.distance == best[pk]->data->prop.distance) &&
-             (sh->data->prop.delay.rel_value_us <
-              best[pk]->data->prop.delay.rel_value_us)))
-          best[pk] = sh;
-        break;
-      case GNUNET_MQ_PREFERENCE_RELIABILITY:
-        /* For reliability, we consider the ratio of goodput to utilization
-           (but use multiplicative formultations to avoid division by zero) */
-        if ((NULL == best[pk]) || (1ULL * sh->data->prop.goodput_out *
-                                     best[pk]->data->prop.utilization_out >
-                                   1ULL * sh->data->prop.utilization_out *
-                                     best[pk]->data->prop.goodput_out))
-          best[pk] = sh;
-        /* If both are equal (i.e. usually this happens if there is a zero), use
-           latency as a yardstick */
-        if ((1ULL * sh->data->prop.goodput_out *
-               best[pk]->data->prop.utilization_out ==
-             1ULL * sh->data->prop.utilization_out *
-               best[pk]->data->prop.goodput_out) &&
-            (sh->data->prop.distance == best[pk]->data->prop.distance) &&
-            (sh->data->prop.delay.rel_value_us <
-             best[pk]->data->prop.delay.rel_value_us))
-          best[pk] = sh;
-        break;
-      }
+      enum GNUNET_NetworkType nt = sh->data->prop.nt;
+
+      sh->target_out = MIN_BANDWIDTH_PER_SESSION;
+      c->bw_out_by_nt[nt] += MIN_BANDWIDTH_PER_SESSION;
+      c->bw_in_by_nt[nt] +=
+        GNUNET_MAX(MIN_BANDWIDTH_PER_SESSION, sh->data->prop.goodput_in);
+      for (enum GNUNET_MQ_PreferenceKind pk = 0; pk < GNUNET_MQ_PREFERENCE_COUNT;
+           pk++)
+        {
+          /* General rule: always prefer smaller distance if possible,
+             otherwise decide by pk: */
+          switch (pk)
+            {
+            case GNUNET_MQ_PREFERENCE_NONE:
+              break;
+
+            case GNUNET_MQ_PREFERENCE_BANDWIDTH:
+              /* For bandwidth, we compare the sum of transmitted bytes and
+                 confirmed transmitted bytes, so confirmed data counts twice */
+              if ((NULL == best[pk]) ||
+                  (sh->data->prop.distance < best[pk]->data->prop.distance) ||
+                  (sh->data->prop.utilization_out + sh->data->prop.goodput_out >
+                   best[pk]->data->prop.utilization_out +
+                   best[pk]->data->prop.goodput_out))
+                best[pk] = sh;
+              /* If both are equal (i.e. usually this happens if there is a zero), use
+                 latency as a yardstick */
+              if ((sh->data->prop.utilization_out + sh->data->prop.goodput_out ==
+                   best[pk]->data->prop.utilization_out +
+                   best[pk]->data->prop.goodput_out) &&
+                  (sh->data->prop.distance == best[pk]->data->prop.distance) &&
+                  (sh->data->prop.delay.rel_value_us <
+                   best[pk]->data->prop.delay.rel_value_us))
+                best[pk] = sh;
+              break;
+
+            case GNUNET_MQ_PREFERENCE_LATENCY:
+              if ((NULL == best[pk]) ||
+                  (sh->data->prop.distance < best[pk]->data->prop.distance) ||
+                  ((sh->data->prop.distance == best[pk]->data->prop.distance) &&
+                   (sh->data->prop.delay.rel_value_us <
+                    best[pk]->data->prop.delay.rel_value_us)))
+                best[pk] = sh;
+              break;
+
+            case GNUNET_MQ_PREFERENCE_RELIABILITY:
+              /* For reliability, we consider the ratio of goodput to utilization
+                 (but use multiplicative formultations to avoid division by zero) */
+              if ((NULL == best[pk]) || (1ULL * sh->data->prop.goodput_out *
+                                         best[pk]->data->prop.utilization_out >
+                                         1ULL * sh->data->prop.utilization_out *
+                                         best[pk]->data->prop.goodput_out))
+                best[pk] = sh;
+              /* If both are equal (i.e. usually this happens if there is a zero), use
+                 latency as a yardstick */
+              if ((1ULL * sh->data->prop.goodput_out *
+                   best[pk]->data->prop.utilization_out ==
+                   1ULL * sh->data->prop.utilization_out *
+                   best[pk]->data->prop.goodput_out) &&
+                  (sh->data->prop.distance == best[pk]->data->prop.distance) &&
+                  (sh->data->prop.delay.rel_value_us <
+                   best[pk]->data->prop.delay.rel_value_us))
+                best[pk] = sh;
+              break;
+            }
+        }
     }
-  }
   /* for first round, assign target bandwidth simply to sum of
      requested bandwidth */
   for (enum GNUNET_MQ_PreferenceKind pk =
          1 /* skip GNUNET_MQ_PREFERENCE_NONE */;
        pk < GNUNET_MQ_PREFERENCE_COUNT;
        pk++)
-  {
-    const struct GNUNET_ATS_SessionData *data = best[pk]->data;
-    enum GNUNET_NetworkType nt;
-
-    GNUNET_assert (NULL != data);
-    nt = data->prop.nt;
-    best[pk]->target_out =
-      GNUNET_MIN (peer->bw_by_pk[pk], MIN_BANDWIDTH_PER_SESSION);
-    c->bw_out_by_nt[nt] +=
-      (uint64_t) (best[pk]->target_out - MIN_BANDWIDTH_PER_SESSION);
-  }
+    {
+      const struct GNUNET_ATS_SessionData *data = best[pk]->data;
+      enum GNUNET_NetworkType nt;
+
+      GNUNET_assert(NULL != data);
+      nt = data->prop.nt;
+      best[pk]->target_out =
+        GNUNET_MIN(peer->bw_by_pk[pk], MIN_BANDWIDTH_PER_SESSION);
+      c->bw_out_by_nt[nt] +=
+        (uint64_t)(best[pk]->target_out - MIN_BANDWIDTH_PER_SESSION);
+    }
   return GNUNET_YES;
 }
 
@@ -817,23 +809,23 @@ update_counters (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
  * @return #GNUNET_YES (continue to iterate)
  */
 static int
-update_allocation (void *cls,
-                   const struct GNUNET_PeerIdentity *pid,
-                   void *value)
+update_allocation(void *cls,
+                  const struct GNUNET_PeerIdentity *pid,
+                  void *value)
 {
   struct Counters *c = cls;
   struct Peer *peer = value;
 
-  (void) pid;
+  (void)pid;
   for (struct GNUNET_ATS_SessionHandle *sh = peer->sh_head; NULL != sh;
        sh = sh->next)
-  {
-    enum GNUNET_NetworkType nt = sh->data->prop.nt;
+    {
+      enum GNUNET_NetworkType nt = sh->data->prop.nt;
 
-    sh->target_out = (uint64_t) (c->scale_out[nt] * sh->target_out);
-    sh->target_in = (uint64_t) (c->scale_in[nt] * sh->target_in);
-    consider_notify_transport (sh);
-  }
+      sh->target_out = (uint64_t)(c->scale_out[nt] * sh->target_out);
+      sh->target_in = (uint64_t)(c->scale_in[nt] * sh->target_in);
+      consider_notify_transport(sh);
+    }
   return GNUNET_YES;
 }
 
@@ -842,23 +834,23 @@ update_allocation (void *cls,
  * The world changed, recalculate our allocations.
  */
 static void
-update (struct SimpleHandle *h)
+update(struct SimpleHandle *h)
 {
-  struct Counters cnt = {.h = h};
+  struct Counters cnt = { .h = h };
 
-  GNUNET_CONTAINER_multipeermap_iterate (h->peers, &update_counters, &cnt);
+  GNUNET_CONTAINER_multipeermap_iterate(h->peers, &update_counters, &cnt);
   /* calculate how badly the missmatch between requested
      allocations and available bandwidth is per network type */
   for (enum GNUNET_NetworkType nt = 0; nt < GNUNET_NT_COUNT; nt++)
-  {
-    cnt.scale_out[nt] =
-      1.0 * cnt.bw_out_by_nt[nt] / h->networks[nt].total_quota_out;
-    cnt.scale_in[nt] =
-      1.0 * cnt.bw_in_by_nt[nt] / h->networks[nt].total_quota_in;
-  }
+    {
+      cnt.scale_out[nt] =
+        1.0 * cnt.bw_out_by_nt[nt] / h->networks[nt].total_quota_out;
+      cnt.scale_in[nt] =
+        1.0 * cnt.bw_in_by_nt[nt] / h->networks[nt].total_quota_in;
+    }
   /* recalculate allocations, considering scaling factor, and
      update transport if the change is significant */
-  GNUNET_CONTAINER_multipeermap_iterate (h->peers, &update_allocation, &cnt);
+  GNUNET_CONTAINER_multipeermap_iterate(h->peers, &update_allocation, &cnt);
 }
 
 
@@ -870,15 +862,15 @@ update (struct SimpleHandle *h)
  * @return plugin's internal representation, or NULL
  */
 static struct GNUNET_ATS_PreferenceHandle *
-simple_preference_add (void *cls, const struct GNUNET_ATS_Preference *pref)
+simple_preference_add(void *cls, const struct GNUNET_ATS_Preference *pref)
 {
   struct SimpleHandle *h = cls;
-  struct Peer *p = peer_add (h, &pref->peer);
+  struct Peer *p = peer_add(h, &pref->peer);
 
-  GNUNET_assert (pref->pk < GNUNET_MQ_PREFERENCE_COUNT);
-  p->bw_by_pk[pref->pk] += ntohl (pref->bw.value__);
-  h->bw_by_pk[pref->pk] += ntohl (pref->bw.value__);
-  update (h);
+  GNUNET_assert(pref->pk < GNUNET_MQ_PREFERENCE_COUNT);
+  p->bw_by_pk[pref->pk] += ntohl(pref->bw.value__);
+  h->bw_by_pk[pref->pk] += ntohl(pref->bw.value__);
+  update(h);
   return NULL;
 }
 
@@ -892,20 +884,20 @@ simple_preference_add (void *cls, const struct GNUNET_ATS_Preference *pref)
  * @return plugin's internal representation, or NULL
  */
 static void
-simple_preference_del (void *cls,
-                       struct GNUNET_ATS_PreferenceHandle *ph,
-                       const struct GNUNET_ATS_Preference *pref)
+simple_preference_del(void *cls,
+                      struct GNUNET_ATS_PreferenceHandle *ph,
+                      const struct GNUNET_ATS_Preference *pref)
 {
   struct SimpleHandle *h = cls;
-  struct Peer *p = lookup_peer (h, &pref->peer);
-
-  GNUNET_assert (NULL != p);
-  GNUNET_assert (pref->pk < GNUNET_MQ_PREFERENCE_COUNT);
-  p->bw_by_pk[pref->pk] -= ntohl (pref->bw.value__);
-  h->bw_by_pk[pref->pk] -= ntohl (pref->bw.value__);
-  if ((0 == p->bw_by_pk[pref->pk]) && (GNUNET_YES == peer_test_dead (p)))
-    peer_free (p);
-  update (h);
+  struct Peer *p = lookup_peer(h, &pref->peer);
+
+  GNUNET_assert(NULL != p);
+  GNUNET_assert(pref->pk < GNUNET_MQ_PREFERENCE_COUNT);
+  p->bw_by_pk[pref->pk] -= ntohl(pref->bw.value__);
+  h->bw_by_pk[pref->pk] -= ntohl(pref->bw.value__);
+  if ((0 == p->bw_by_pk[pref->pk]) && (GNUNET_YES == peer_test_dead(p)))
+    peer_free(p);
+  update(h);
 }
 
 
@@ -919,50 +911,50 @@ simple_preference_del (void *cls,
  * @return handle by which the plugin will identify this session
  */
 static struct GNUNET_ATS_SessionHandle *
-simple_session_add (void *cls,
-                    const struct GNUNET_ATS_SessionData *data,
-                    const char *address)
+simple_session_add(void *cls,
+                   const struct GNUNET_ATS_SessionData *data,
+                   const char *address)
 {
   struct SimpleHandle *h = cls;
-  struct Peer *p = peer_add (h, &data->peer);
+  struct Peer *p = peer_add(h, &data->peer);
   struct Hello *hello;
   size_t alen;
   struct GNUNET_ATS_SessionHandle *sh;
 
   /* setup session handle */
-  GNUNET_assert (NULL != data);
+  GNUNET_assert(NULL != data);
   if (NULL == address)
     alen = 0;
   else
-    alen = strlen (address) + 1;
-  sh = GNUNET_malloc (sizeof (struct GNUNET_ATS_SessionHandle) + alen);
+    alen = strlen(address) + 1;
+  sh = GNUNET_malloc(sizeof(struct GNUNET_ATS_SessionHandle) + alen);
   sh->peer = p;
   sh->session = data->session;
   sh->data = data;
   if (NULL == address)
-  {
-    sh->address = NULL;
-  }
+    {
+      sh->address = NULL;
+    }
   else
-  {
-    memcpy (&sh[1], address, alen);
-    sh->address = (const char *) &sh[1];
-  }
-  GNUNET_CONTAINER_DLL_insert (p->sh_head, p->sh_tail, sh);
+    {
+      memcpy(&sh[1], address, alen);
+      sh->address = (const char *)&sh[1];
+    }
+  GNUNET_CONTAINER_DLL_insert(p->sh_head, p->sh_tail, sh);
   if (NULL != address)
-  {
-    /* match HELLO */
-    hello = p->h_head;
-    while ((NULL != hello) && (0 != strcmp (address, hello->address)))
-      hello = hello->next;
-    if (NULL != hello)
     {
-      hello->sh = sh;
-      hello->backoff = GNUNET_TIME_UNIT_ZERO;
-      sh->hello = hello;
+      /* match HELLO */
+      hello = p->h_head;
+      while ((NULL != hello) && (0 != strcmp(address, hello->address)))
+        hello = hello->next;
+      if (NULL != hello)
+        {
+          hello->sh = sh;
+          hello->backoff = GNUNET_TIME_UNIT_ZERO;
+          sh->hello = hello;
+        }
     }
-  }
-  update (h);
+  update(h);
   return sh;
 }
 
@@ -976,15 +968,15 @@ simple_session_add (void *cls,
  * @param data performance characteristics of @a sh
  */
 static void
-simple_session_update (void *cls,
-                       struct GNUNET_ATS_SessionHandle *sh,
-                       const struct GNUNET_ATS_SessionData *data)
+simple_session_update(void *cls,
+                      struct GNUNET_ATS_SessionHandle *sh,
+                      const struct GNUNET_ATS_SessionData *data)
 {
   struct SimpleHandle *h = cls;
 
-  GNUNET_assert (NULL != data);
+  GNUNET_assert(NULL != data);
   sh->data = data; /* this statement should not really do anything... */
-  update (h);
+  update(h);
 }
 
 
@@ -996,30 +988,30 @@ simple_session_update (void *cls,
  * @param data (last) performance characteristics of @a sh
  */
 static void
-simple_session_del (void *cls,
-                    struct GNUNET_ATS_SessionHandle *sh,
-                    const struct GNUNET_ATS_SessionData *data)
+simple_session_del(void *cls,
+                   struct GNUNET_ATS_SessionHandle *sh,
+                   const struct GNUNET_ATS_SessionData *data)
 {
   struct SimpleHandle *h = cls;
   struct Peer *p = sh->peer;
   struct Hello *hello = sh->hello;
 
   /* clean up sh */
-  GNUNET_CONTAINER_DLL_remove (p->sh_head, p->sh_tail, sh);
+  GNUNET_CONTAINER_DLL_remove(p->sh_head, p->sh_tail, sh);
   if (NULL != hello)
-  {
-    GNUNET_assert (sh == hello->sh);
-    hello->sh = NULL;
-    /* session went down, if necessary restart suggesting
-       addresses */
-    if (NULL == p->task)
-      p->task = GNUNET_SCHEDULER_add_now (&suggest_start_cb, p);
-  }
-  GNUNET_free (sh);
+    {
+      GNUNET_assert(sh == hello->sh);
+      hello->sh = NULL;
+      /* session went down, if necessary restart suggesting
+         addresses */
+      if (NULL == p->task)
+        p->task = GNUNET_SCHEDULER_add_now(&suggest_start_cb, p);
+    }
+  GNUNET_free(sh);
   /* del peer if otherwise dead */
-  if ((NULL == p->sh_head) && (GNUNET_YES == peer_test_dead (p)))
-    peer_free (p);
-  update (h);
+  if ((NULL == p->sh_head) && (GNUNET_YES == peer_test_dead(p)))
+    peer_free(p);
+  update(h);
 }
 
 
@@ -1034,16 +1026,16 @@ simple_session_del (void *cls,
  * @return the `struct SimpleHandle` to pass as a closure
  */
 void *
-libgnunet_plugin_ats2_simple_init (void *cls)
+libgnunet_plugin_ats2_simple_init(void *cls)
 {
   static struct GNUNET_ATS_SolverFunctions sf;
   struct GNUNET_ATS_PluginEnvironment *env = cls;
   struct SimpleHandle *s;
 
-  s = GNUNET_new (struct SimpleHandle);
+  s = GNUNET_new(struct SimpleHandle);
   s->env = env;
-  s->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
-  s->ps = GNUNET_PEERSTORE_connect (env->cfg);
+  s->peers = GNUNET_CONTAINER_multipeermap_create(128, GNUNET_YES);
+  s->ps = GNUNET_PEERSTORE_connect(env->cfg);
   sf.cls = s;
   sf.preference_add = &simple_preference_add;
   sf.preference_del = &simple_preference_del;
@@ -1051,18 +1043,18 @@ libgnunet_plugin_ats2_simple_init (void *cls)
   sf.session_update = &simple_session_update;
   sf.session_del = &simple_session_del;
   for (enum GNUNET_NetworkType nt = 0; nt < GNUNET_NT_COUNT; nt++)
-  {
-    const char *name = GNUNET_NT_to_string (nt);
-
-    if (NULL == name)
     {
-      GNUNET_break (0);
-      break;
+      const char *name = GNUNET_NT_to_string(nt);
+
+      if (NULL == name)
+        {
+          GNUNET_break(0);
+          break;
+        }
+      get_quota(env->cfg, name, "IN", &s->networks[nt].total_quota_in);
+      get_quota(env->cfg, name, "OUT", &s->networks[nt].total_quota_out);
+      s->networks[nt].type = nt;
     }
-    get_quota (env->cfg, name, "IN", &s->networks[nt].total_quota_in);
-    get_quota (env->cfg, name, "OUT", &s->networks[nt].total_quota_out);
-    s->networks[nt].type = nt;
-  }
   return &sf;
 }
 
@@ -1073,15 +1065,15 @@ libgnunet_plugin_ats2_simple_init (void *cls)
  * @param cls return value from #libgnunet_plugin_ats_proportional_init()
  */
 void *
-libgnunet_plugin_ats2_simple_done (void *cls)
+libgnunet_plugin_ats2_simple_done(void *cls)
 {
   struct GNUNET_ATS_SolverFunctions *sf = cls;
   struct SimpleHandle *s = sf->cls;
 
-  GNUNET_break (0 == GNUNET_CONTAINER_multipeermap_size (s->peers));
-  GNUNET_CONTAINER_multipeermap_destroy (s->peers);
-  GNUNET_PEERSTORE_disconnect (s->ps, GNUNET_NO);
-  GNUNET_free (s);
+  GNUNET_break(0 == GNUNET_CONTAINER_multipeermap_size(s->peers));
+  GNUNET_CONTAINER_multipeermap_destroy(s->peers);
+  GNUNET_PEERSTORE_disconnect(s->ps, GNUNET_NO);
+  GNUNET_free(s);
   return NULL;
 }