- fix coverity
[oweals/gnunet.git] / src / transport / gnunet-service-transport_clients.c
index cea1dc14e5f134e935e8a4f25ab54ad835a2d75c..3df62011cbf270d07503639ae5d54b9e027cb743 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
+     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
@@ -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.
 */
 
 /**
@@ -171,6 +171,40 @@ struct MonitoringClient
 };
 
 
+/**
+ * Closure for #handle_send_transmit_continuation()
+ */
+struct SendTransmitContinuationContext
+{
+  /**
+   * Client that made the request.
+   */
+  struct GNUNET_SERVER_Client *client;
+
+  /**
+   * Peer that was the target.
+   */
+  struct GNUNET_PeerIdentity target;
+
+  /**
+   * At what time did we receive the message?
+   */
+  struct GNUNET_TIME_Absolute send_time;
+
+  /**
+   * Unique ID, for logging.
+   */
+  unsigned long long uuid;
+
+  /**
+   * Set to #GNUNET_YES if the connection for @e target goes
+   * down and we thus must no longer send the
+   * #GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK message.
+   */
+  int down;
+};
+
+
 /**
  * Head of linked list of all clients to this service.
  */
@@ -181,6 +215,14 @@ static struct TransportClient *clients_head;
  */
 static struct TransportClient *clients_tail;
 
+/**
+ * Map of peer identities to active send transmit continuation
+ * contexts. Used to flag contexts as 'dead' when a connection goes
+ * down. Values are of type `struct SendTransmitContinuationContext
+ * *`.
+ */
+static struct GNUNET_CONTAINER_MultiPeerMap *active_stccs;
+
 /**
  * Head of linked list of all pending address iterations
  */
@@ -201,16 +243,6 @@ static struct MonitoringClient *peer_monitoring_clients_head;
  */
 static struct MonitoringClient *peer_monitoring_clients_tail;
 
-/**
- * Head of linked list of validation monitoring clients.
- */
-static struct MonitoringClient *val_monitoring_clients_head;
-
-/**
- * Tail of linked list of validation monitoring clients.
- */
-static struct MonitoringClient *val_monitoring_clients_tail;
-
 /**
  * Notification context, to send updates on changes to active addresses
  * of our neighbours.
@@ -344,47 +376,6 @@ setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client,
 }
 
 
-/**
- * Setup a new monitoring client using the given server client handle and
- * the peer identity.
- *
- * @param client server's client handle to create our internal handle for
- * @param peer identity of the peer to monitor the addresses of,
- *             zero to monitor all neighrours.
- * @return handle to the new monitoring client
- */
-static struct MonitoringClient *
-setup_val_monitoring_client (struct GNUNET_SERVER_Client *client,
-                             struct GNUNET_PeerIdentity *peer)
-{
-  struct MonitoringClient *mc;
-
-  GNUNET_assert (NULL ==
-                 lookup_monitoring_client (val_monitoring_clients_head,
-                                           client));
-  mc = GNUNET_new (struct MonitoringClient);
-  mc->client = client;
-  mc->peer = *peer;
-  GNUNET_CONTAINER_DLL_insert (val_monitoring_clients_head,
-                               val_monitoring_clients_tail,
-                               mc);
-  GNUNET_SERVER_notification_context_add (val_nc, client);
-
-  if (0 != memcmp (peer,
-                   &all_zeros,
-                   sizeof (struct GNUNET_PeerIdentity)))
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Client %p started monitoring of the peer `%s'\n",
-                mc,
-                GNUNET_i2s (peer));
-  else
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Client %p started monitoring all peers\n",
-                mc);
-  return mc;
-}
-
-
 /**
  * Function called to notify a client about the socket being ready to
  * queue more data.  @a buf will be NULL and @a size zero if the socket
@@ -526,15 +517,6 @@ client_disconnect_notification (void *cls,
                                  mc);
     GNUNET_free (mc);
   }
-  mc = lookup_monitoring_client (val_monitoring_clients_head,
-                                 client);
-  if (NULL != mc)
-  {
-    GNUNET_CONTAINER_DLL_remove (val_monitoring_clients_head,
-                                 val_monitoring_clients_tail,
-                                 mc);
-    GNUNET_free (mc);
-  }
   tc = lookup_client (client);
   if (NULL == tc)
     return;
@@ -646,22 +628,12 @@ clients_handle_start (void *cls,
   tc = setup_client (client);
   tc->send_payload = (0 != (2 & options));
   hello = GST_hello_get ();
-  if (NULL == hello)
-  {
-    /* We are during startup and should have no neighbours, hence
-       iteration with NULL must work.  The HELLO will be sent to
-       all clients once it has been created, so this should happen
-       next anyway, and certainly before we get neighbours. */
-    GST_neighbours_iterate (NULL, NULL);
-  }
-  else
-  {
+  if (NULL != hello)
     unicast (tc,
              hello,
              GNUNET_NO);
-    GST_neighbours_iterate (&notify_client_about_neighbour,
-                            tc);
-  }
+  GST_neighbours_iterate (&notify_client_about_neighbour,
+                          tc);
   GNUNET_SERVER_receive_done (client,
                               GNUNET_OK);
 }
@@ -684,23 +656,6 @@ clients_handle_hello (void *cls,
 }
 
 
-/**
- * Closure for #handle_send_transmit_continuation()
- */
-struct SendTransmitContinuationContext
-{
-  /**
-   * Client that made the request.
-   */
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Peer that was the target.
-   */
-  struct GNUNET_PeerIdentity target;
-};
-
-
 /**
  * Function called after the transmission is done.  Notify the client that it is
  * OK to send the next message.
@@ -718,17 +673,53 @@ handle_send_transmit_continuation (void *cls,
 {
   struct SendTransmitContinuationContext *stcc = cls;
   struct SendOkMessage send_ok_msg;
-
-  send_ok_msg.header.size = htons (sizeof (send_ok_msg));
-  send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
-  send_ok_msg.bytes_msg = htonl (bytes_payload);
-  send_ok_msg.bytes_physical = htonl (bytes_on_wire);
-  send_ok_msg.success = htonl (success);
-  send_ok_msg.peer = stcc->target;
-  GST_clients_unicast (stcc->client,
-                       &send_ok_msg.header,
-                       GNUNET_NO);
+  struct GNUNET_TIME_Relative delay;
+  const struct GNUNET_HELLO_Address *addr;
+
+  delay = GNUNET_TIME_absolute_get_duration (stcc->send_time);
+  addr = GST_neighbour_get_current_address (&stcc->target);
+  if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "It took us %s to send %u/%u bytes to %s (%d, %s)\n",
+                GNUNET_STRINGS_relative_time_to_string (delay,
+                                                        GNUNET_YES),
+                (unsigned int) bytes_payload,
+                (unsigned int) bytes_on_wire,
+                GNUNET_i2s (&stcc->target),
+                success,
+                (NULL != addr) ? addr->transport_name : "%");
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "It took us %s to send %u/%u bytes to %s (%d, %s)\n",
+                GNUNET_STRINGS_relative_time_to_string (delay,
+                                                        GNUNET_YES),
+                (unsigned int) bytes_payload,
+                (unsigned int) bytes_on_wire,
+                GNUNET_i2s (&stcc->target),
+                success,
+                (NULL != addr) ? addr->transport_name : "%");
+
+  if (GNUNET_NO == stcc->down)
+  {
+    /* Only send confirmation if we are still connected */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending SEND_OK for transmission request %llu\n",
+                stcc->uuid);
+    send_ok_msg.header.size = htons (sizeof (send_ok_msg));
+    send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK);
+    send_ok_msg.bytes_msg = htonl (bytes_payload);
+    send_ok_msg.bytes_physical = htonl (bytes_on_wire);
+    send_ok_msg.success = htonl (success);
+    send_ok_msg.peer = stcc->target;
+    GST_clients_unicast (stcc->client,
+                         &send_ok_msg.header,
+                         GNUNET_NO);
+  }
   GNUNET_SERVER_client_drop (stcc->client);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multipeermap_remove (active_stccs,
+                                                       &stcc->target,
+                                                       stcc));
   GNUNET_free (stcc);
 }
 
@@ -745,6 +736,7 @@ clients_handle_send (void *cls,
                      struct GNUNET_SERVER_Client *client,
                      const struct GNUNET_MessageHeader *message)
 {
+  static unsigned long long uuid_gen;
   const struct OutboundMessage *obm;
   const struct GNUNET_MessageHeader *obmm;
   struct SendTransmitContinuationContext *stcc;
@@ -757,7 +749,8 @@ clients_handle_send (void *cls,
   {
     /* client asked for transmission before 'START' */
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
 
@@ -766,7 +759,8 @@ clients_handle_send (void *cls,
       sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   obm = (const struct OutboundMessage *) message;
@@ -775,7 +769,8 @@ clients_handle_send (void *cls,
   if (msize < sizeof (struct GNUNET_MessageHeader))
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
 
@@ -789,95 +784,34 @@ clients_handle_send (void *cls,
                               gettext_noop
                               ("# bytes payload dropped (other peer was not connected)"),
                               msize, GNUNET_NO);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n",
-              "SEND",
+              "Received SEND request %llu for `%s' and first message of type %u and total size %u\n",
+              uuid_gen,
               GNUNET_i2s (&obm->peer),
               ntohs (obmm->type),
               msize);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
   stcc = GNUNET_new (struct SendTransmitContinuationContext);
   stcc->target = obm->peer;
   stcc->client = client;
+  stcc->send_time = GNUNET_TIME_absolute_get ();
+  stcc->uuid = uuid_gen++;
+  (void) GNUNET_CONTAINER_multipeermap_put (active_stccs,
+                                            &stcc->target,
+                                            stcc,
+                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
   GNUNET_SERVER_client_keep (client);
-  GST_manipulation_send (&obm->peer, obmm, msize,
+  GST_manipulation_send (&obm->peer,
+                         obmm,
+                         msize,
                          GNUNET_TIME_relative_ntoh (obm->timeout),
-                         &handle_send_transmit_continuation, stcc);
-}
-
-
-/**
- * Handle request connect message
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-clients_handle_request_connect (void *cls,
-                                struct GNUNET_SERVER_Client *client,
-                                const struct GNUNET_MessageHeader *message)
-{
-  const struct TransportRequestConnectMessage *trcm;
-
-  trcm = (const struct TransportRequestConnectMessage *) message;
-  GNUNET_break (0 == ntohl (trcm->reserved));
-  GNUNET_STATISTICS_update (GST_stats,
-                            gettext_noop
-                            ("# REQUEST CONNECT messages received"), 1,
-                            GNUNET_NO);
-  if (0 == memcmp (&trcm->peer,
-                   &GST_my_identity,
-                   sizeof (struct GNUNET_PeerIdentity)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a request connect message for peer `%s'\n",
-              GNUNET_i2s (&trcm->peer));
-  GST_neighbours_try_connect (&trcm->peer);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Handle request disconnect message
- *
- * @param cls closure (always NULL)
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-clients_handle_request_disconnect (void *cls,
-                                   struct GNUNET_SERVER_Client *client,
-                                   const struct GNUNET_MessageHeader *message)
-{
-  const struct TransportRequestDisconnectMessage *trdm;
-
-  trdm = (const struct TransportRequestDisconnectMessage *) message;
-  GNUNET_break (0 == ntohl (trdm->reserved));
-  GNUNET_STATISTICS_update (GST_stats,
-                            gettext_noop
-                            ("# REQUEST DISCONNECT messages received"), 1,
-                            GNUNET_NO);
-  if (0 == memcmp (&trdm->peer,
-                   &GST_my_identity,
-                   sizeof (struct GNUNET_PeerIdentity)))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received a request disconnect message for peer `%s'\n",
-              GNUNET_i2s (&trdm->peer));
-  (void) GST_neighbours_force_disconnect (&trdm->peer);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+                         &handle_send_transmit_continuation,
+                         stcc);
 }
 
 
@@ -1011,6 +945,9 @@ clients_handle_address_to_string (void *cls,
   papi = GST_plugins_printer_find (plugin_name);
   if (NULL == papi)
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to find plugin `%s'\n",
+                plugin_name);
     atsm.header.size = ntohs (sizeof (struct AddressToStringResultMessage));
     atsm.header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
     atsm.res = htonl (GNUNET_SYSERR);
@@ -1030,6 +967,10 @@ clients_handle_address_to_string (void *cls,
   actx->tc = tc;
   GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx);
   GNUNET_SERVER_disable_receive_done_warning (client);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Pretty-printing address of %u bytes using plugin `%s'\n",
+              address_len,
+              plugin_name);
   papi->address_pretty_printer (papi->cls,
                                 plugin_name,
                                 address, address_len,
@@ -1089,55 +1030,6 @@ compose_address_iterate_response_message (const struct GNUNET_PeerIdentity *peer
 }
 
 
-/**
- * Compose #PeerIterateResponseMessage using the given peer and address.
- *
- * @param peer identity of the peer
- * @param address the address, NULL on disconnect
- * @return composed message
- */
-static struct ValidationIterateResponseMessage *
-compose_validation_iterate_response_message (const struct GNUNET_PeerIdentity *peer,
-                                             const struct GNUNET_HELLO_Address *address)
-{
-  struct ValidationIterateResponseMessage *msg;
-  size_t size;
-  size_t tlen;
-  size_t alen;
-  char *addr;
-
-  GNUNET_assert (NULL != peer);
-  if (NULL != address)
-  {
-    tlen = strlen (address->transport_name) + 1;
-    alen = address->address_length;
-  }
-  else
-  {
-    tlen = 0;
-    alen = 0;
-  }
-  size = (sizeof (struct ValidationIterateResponseMessage) + alen + tlen);
-  msg = GNUNET_malloc (size);
-  msg->header.size = htons (size);
-  msg->header.type =
-      htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
-  msg->reserved = htonl (0);
-  msg->peer = *peer;
-  msg->addrlen = htonl (alen);
-  msg->pluginlen = htonl (tlen);
-
-  if (NULL != address)
-  {
-    msg->local_address_info = htonl((uint32_t) address->local_info);
-    addr = (char *) &msg[1];
-    memcpy (addr, address->address, alen);
-    memcpy (&addr[alen], address->transport_name, tlen);
-  }
-  return msg;
-}
-
-
 /**
  * Context for #send_validation_information() and
  * #send_peer_information().
@@ -1161,44 +1053,6 @@ struct IterationContext
 };
 
 
-/**
- * Output information of validation entries to the given client.
- *
- * @param cls the `struct IterationContext *`
- * @param address the address
- * @param last_validation point in time when last validation was performed
- * @param valid_until point in time how long address is valid
- * @param next_validation point in time when next validation will be performed
- * @param state state of validation notification
- */
-static void
-send_validation_information (void *cls,
-                             const struct GNUNET_HELLO_Address *address,
-                             struct GNUNET_TIME_Absolute last_validation,
-                             struct GNUNET_TIME_Absolute valid_until,
-                             struct GNUNET_TIME_Absolute next_validation,
-                             enum GNUNET_TRANSPORT_ValidationState state)
-{
-  struct IterationContext *pc = cls;
-  struct ValidationIterateResponseMessage *msg;
-
-  if ( (GNUNET_YES != pc->all) &&
-       (0 != memcmp (&address->peer, &pc->id, sizeof (pc->id))) )
-    return;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending information about for validation entry for peer `%s' using address `%s'\n",
-              GNUNET_i2s (&address->peer),
-              (NULL != address) ? GST_plugins_a2s (address) : "<none>");
-  msg = compose_validation_iterate_response_message (&address->peer, address);
-  msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
-  msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
-  msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
-  msg->state = htonl ((uint32_t) state);
-  GNUNET_SERVER_transmit_context_append_message (pc->tc, &msg->header);
-  GNUNET_free (msg);
-}
-
-
 /**
  * Output information of neighbours to the given client.
  *
@@ -1261,79 +1115,8 @@ clients_handle_monitor_peers (void *cls,
                                           client)) )
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  GNUNET_SERVER_disable_receive_done_warning (client);
-  GNUNET_SERVER_client_mark_monitor (client);
-  pc.tc = tc = GNUNET_SERVER_transmit_context_create (client);
-
-  /* Send initial list */
-  if (0 == memcmp (&msg->peer,
-                   &all_zeros,
-                   sizeof (struct GNUNET_PeerIdentity)))
-  {
-    /* iterate over all neighbours */
-    pc.all = GNUNET_YES;
-    pc.id = msg->peer;
-  }
-  else
-  {
-    /* just return one neighbour */
-    pc.all = GNUNET_NO;
-    pc.id = msg->peer;
-  }
-  GST_neighbours_iterate (&send_peer_information, &pc);
-
-  if (GNUNET_YES != ntohl (msg->one_shot))
-  {
-    setup_peer_monitoring_client (client, &msg->peer);
-  }
-  else
-  {
-    GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-        GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
-  }
-
-  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
-}
-
-
-/**
- * Client asked to obtain information about a specific or all validation
- * processes
- *
- * @param cls unused
- * @param client the client
- * @param message the peer address information request
- */
-static void
-clients_handle_monitor_validation (void *cls,
-                                  struct GNUNET_SERVER_Client *client,
-                                  const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_SERVER_TransmitContext *tc;
-  struct PeerMonitorMessage *msg;
-  struct IterationContext pc;
-
-  if (ntohs (message->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  if (ntohs (message->size) != sizeof (struct ValidationMonitorMessage))
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  msg = (struct PeerMonitorMessage *) message;
-  if ( (GNUNET_YES != ntohl (msg->one_shot)) &&
-       (NULL != lookup_monitoring_client (val_monitoring_clients_head, client)) )
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   GNUNET_SERVER_disable_receive_done_warning (client);
@@ -1355,19 +1138,23 @@ clients_handle_monitor_validation (void *cls,
     pc.all = GNUNET_NO;
     pc.id = msg->peer;
   }
-  GST_validation_iterate (&send_validation_information,
+  GST_neighbours_iterate (&send_peer_information,
                           &pc);
 
   if (GNUNET_YES != ntohl (msg->one_shot))
   {
-    setup_val_monitoring_client (client, &msg->peer);
+    setup_peer_monitoring_client (client,
+                                  &msg->peer);
   }
   else
   {
-    GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
-                                                GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
+    GNUNET_SERVER_transmit_context_append_data (tc,
+                                                NULL,
+                                                0,
+                                                GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE_END);
   }
-  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
+  GNUNET_SERVER_transmit_context_run (tc,
+                                      GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
 
@@ -1385,7 +1172,7 @@ clients_handle_monitor_validation (void *cls,
  */
 static void
 plugin_session_info_cb (void *cls,
-                       struct Session *session,
+                       struct GNUNET_ATS_Session *session,
                        const struct GNUNET_TRANSPORT_SessionInfo *info)
 {
   struct TransportPluginMonitorMessage *msg;
@@ -1398,8 +1185,8 @@ plugin_session_info_cb (void *cls,
 
   if (0 == GNUNET_SERVER_notification_context_get_size (plugin_nc))
   {
-    fprintf (stderr, "UNSUB!\n");
-    GST_plugins_monitor_subscribe (NULL, NULL);
+    GST_plugins_monitor_subscribe (NULL,
+                                   NULL);
     return;
   }
   if ( (NULL == info) &&
@@ -1445,9 +1232,13 @@ plugin_session_info_cb (void *cls,
   msg->plugin_name_len = htons (slen);
   msg->plugin_address_len = htons (alen);
   name = (char *) &msg[1];
-  memcpy (name, info->address->transport_name, slen);
+  memcpy (name,
+          info->address->transport_name,
+          slen);
   addr = &name[slen];
-  memcpy (addr, info->address->address, alen);
+  memcpy (addr,
+          info->address->address,
+          alen);
   if (NULL != sync_client)
     GNUNET_SERVER_notification_context_unicast (plugin_nc,
                                                 sync_client,
@@ -1475,9 +1266,12 @@ clients_handle_monitor_plugins (void *cls,
 {
   GNUNET_SERVER_client_mark_monitor (client);
   GNUNET_SERVER_disable_receive_done_warning (client);
-  GNUNET_SERVER_notification_context_add (plugin_nc, client);
+  GNUNET_SERVER_notification_context_add (plugin_nc,
+                                          client);
+  GNUNET_assert (NULL == sync_client);
   sync_client = client;
-  GST_plugins_monitor_subscribe (&plugin_session_info_cb, NULL);
+  GST_plugins_monitor_subscribe (&plugin_session_info_cb,
+                                 NULL);
 }
 
 
@@ -1496,20 +1290,11 @@ GST_clients_start (struct GNUNET_SERVER_Handle *server)
      GNUNET_MESSAGE_TYPE_HELLO, 0},
     {&clients_handle_send, NULL,
      GNUNET_MESSAGE_TYPE_TRANSPORT_SEND, 0},
-    {&clients_handle_request_connect, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT,
-     sizeof (struct TransportRequestConnectMessage)},
-    {&clients_handle_request_disconnect, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_DISCONNECT,
-     sizeof (struct TransportRequestDisconnectMessage)},
     {&clients_handle_address_to_string, NULL,
      GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING, 0},
     {&clients_handle_monitor_peers, NULL,
      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST,
      sizeof (struct PeerMonitorMessage)},
-    {&clients_handle_monitor_validation, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST,
-     sizeof (struct ValidationMonitorMessage)},
     {&GST_blacklist_handle_init, NULL,
      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_INIT,
      sizeof (struct GNUNET_MessageHeader)},
@@ -1517,12 +1302,15 @@ GST_clients_start (struct GNUNET_SERVER_Handle *server)
      GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_REPLY,
      sizeof (struct BlacklistMessage)},
     {&GST_manipulation_set_metric, NULL,
-     GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC, 0},
+     GNUNET_MESSAGE_TYPE_TRANSPORT_TRAFFIC_METRIC,
+     sizeof (struct TrafficMetricMessage) },
     {&clients_handle_monitor_plugins, NULL,
      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PLUGIN_START,
      sizeof (struct GNUNET_MessageHeader) },
     {NULL, NULL, 0, 0}
   };
+  active_stccs = GNUNET_CONTAINER_multipeermap_create (128,
+                                                       GNUNET_YES);
   peer_nc = GNUNET_SERVER_notification_context_create (server, 0);
   val_nc = GNUNET_SERVER_notification_context_create (server, 0);
   plugin_nc = GNUNET_SERVER_notification_context_create (server, 0);
@@ -1562,6 +1350,8 @@ GST_clients_stop ()
     GNUNET_SERVER_notification_context_destroy (plugin_nc);
     plugin_nc = NULL;
   }
+  GNUNET_CONTAINER_multipeermap_destroy (active_stccs);
+  active_stccs = NULL;
 }
 
 
@@ -1646,45 +1436,48 @@ GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
 
 
 /**
- * Broadcast the new validation changes to all clients monitoring the peer.
+ * Mark the peer as down so we don't call the continuation
+ * context in the future.
  *
- * @param peer peer this update is about (never NULL)
- * @param address address, NULL on disconnect
- * @param last_validation point in time when last validation was performed
- * @param valid_until point in time how long address is valid
- * @param next_validation point in time when next validation will be performed
- * @param state state of validation notification
+ * @param cls NULL
+ * @param peer peer that got disconnected
+ * @param value a `struct SendTransmitContinuationContext` to mark
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+mark_peer_down (void *cls,
+                const struct GNUNET_PeerIdentity *peer,
+                void *value)
+{
+  struct SendTransmitContinuationContext *stcc = value;
+
+  stcc->down = GNUNET_YES;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Notify all clients about a disconnect, and cancel
+ * pending SEND_OK messages for this peer.
+ *
+ * @param peer peer that disconnected
  */
 void
-GST_clients_broadcast_validation_notification (const struct GNUNET_PeerIdentity *peer,
-                                               const struct GNUNET_HELLO_Address *address,
-                                               struct GNUNET_TIME_Absolute last_validation,
-                                               struct GNUNET_TIME_Absolute valid_until,
-                                               struct GNUNET_TIME_Absolute next_validation,
-                                               enum GNUNET_TRANSPORT_ValidationState state)
+GST_clients_broadcast_disconnect (const struct GNUNET_PeerIdentity *peer)
 {
-  struct ValidationIterateResponseMessage *msg;
-  struct MonitoringClient *mc;
+  struct DisconnectInfoMessage disconnect_msg;
+
+  GNUNET_CONTAINER_multipeermap_get_multiple (active_stccs,
+                                              peer,
+                                              &mark_peer_down,
+                                              NULL);
+  disconnect_msg.header.size = htons (sizeof(struct DisconnectInfoMessage));
+  disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
+  disconnect_msg.reserved = htonl (0);
+  disconnect_msg.peer = *peer;
+  GST_clients_broadcast (&disconnect_msg.header,
+                         GNUNET_NO);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Sending information about for validation entry for peer `%s' using address `%s'\n",
-              GNUNET_i2s(peer),
-              (address != NULL) ? GST_plugins_a2s (address) : "<none>");
-  msg = compose_validation_iterate_response_message (peer, address);
-  msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);
-  msg->valid_until = GNUNET_TIME_absolute_hton(valid_until);
-  msg->next_validation = GNUNET_TIME_absolute_hton(next_validation);
-  msg->state = htonl ((uint32_t) state);
-  for (mc = val_monitoring_clients_head; NULL != mc; mc = mc->next)
-    if ((0 == memcmp (&mc->peer, &all_zeros,
-                      sizeof (struct GNUNET_PeerIdentity))) ||
-        (0 == memcmp (&mc->peer, peer,
-                      sizeof (struct GNUNET_PeerIdentity))))
-      GNUNET_SERVER_notification_context_unicast (val_nc,
-                                                  mc->client,
-                                                  &msg->header,
-                                                  GNUNET_NO);
-  GNUNET_free (msg);
 }