-allow caller ID to differ from zone used for resolution
[oweals/gnunet.git] / src / transport / transport_api_monitoring.c
index 8f67a24b7526f5789b6631732532d3114ede1717..31f3d4f90eec2d7187b8ca186e1fe064dfe59b98 100644 (file)
@@ -151,29 +151,24 @@ GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state)
 {
   switch (state)
   {
-  case S_NOT_CONNECTED:
-  case S_INIT_ATS:
-  case S_INIT_BLACKLIST:
-  case S_CONNECT_SENT:
-  case S_CONNECT_RECV_BLACKLIST_INBOUND:
-  case S_CONNECT_RECV_ATS:
-  case S_CONNECT_RECV_BLACKLIST:
-  case S_CONNECT_RECV_ACK:
+  case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
+  case GNUNET_TRANSPORT_PS_INIT_ATS:
+  case GNUNET_TRANSPORT_PS_CONNECT_SENT:
+  case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS:
+  case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK:
     return GNUNET_NO;
-  case S_CONNECTED:
-  case S_RECONNECT_ATS:
-  case S_RECONNECT_BLACKLIST:
-  case S_RECONNECT_SENT:
-  case S_CONNECTED_SWITCHING_BLACKLIST:
-  case S_CONNECTED_SWITCHING_CONNECT_SENT:
+  case GNUNET_TRANSPORT_PS_CONNECTED:
+  case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
+  case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
+  case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT:
     return GNUNET_YES;
-  case S_DISCONNECT:
-  case S_DISCONNECT_FINISHED:
+  case GNUNET_TRANSPORT_PS_DISCONNECT:
+  case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
     return GNUNET_NO;
   default:
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unhandled state `%s' \n",
-                GNUNET_TRANSPORT_p2s (state));
+                GNUNET_TRANSPORT_ps2s (state));
     GNUNET_break (0);
     break;
   }
@@ -181,47 +176,37 @@ GNUNET_TRANSPORT_is_connected (enum GNUNET_TRANSPORT_PeerState state)
 }
 
 /**
- * Convert state to human-readable string.
+ * Convert peer state to human-readable string.
  *
  * @param state the state value
  * @return corresponding string
  */
 const char *
-GNUNET_TRANSPORT_p2s (enum GNUNET_TRANSPORT_PeerState state)
+GNUNET_TRANSPORT_ps2s (enum GNUNET_TRANSPORT_PeerState state)
 {
   switch (state)
   {
-  case S_NOT_CONNECTED:
+  case GNUNET_TRANSPORT_PS_NOT_CONNECTED:
     return "S_NOT_CONNECTED";
-  case S_INIT_ATS:
+  case GNUNET_TRANSPORT_PS_INIT_ATS:
     return "S_INIT_ATS";
-  case S_INIT_BLACKLIST:
-    return "S_INIT_BLACKLIST";
-  case S_CONNECT_SENT:
+  case GNUNET_TRANSPORT_PS_CONNECT_SENT:
     return "S_CONNECT_SENT";
-  case S_CONNECT_RECV_BLACKLIST_INBOUND:
-    return "S_CONNECT_RECV_BLACKLIST_INBOUND";
-  case S_CONNECT_RECV_ATS:
+  case GNUNET_TRANSPORT_PS_CONNECT_RECV_ATS:
     return "S_CONNECT_RECV_ATS";
-  case S_CONNECT_RECV_BLACKLIST:
-    return "S_CONNECT_RECV_BLACKLIST";
-  case S_CONNECT_RECV_ACK:
+  case GNUNET_TRANSPORT_PS_CONNECT_RECV_ACK:
     return "S_CONNECT_RECV_ACK";
-  case S_CONNECTED:
+  case GNUNET_TRANSPORT_PS_CONNECTED:
     return "S_CONNECTED";
-  case S_RECONNECT_ATS:
+  case GNUNET_TRANSPORT_PS_RECONNECT_ATS:
     return "S_RECONNECT_ATS";
-  case S_RECONNECT_BLACKLIST:
-    return "S_RECONNECT_BLACKLIST";
-  case S_RECONNECT_SENT:
+  case GNUNET_TRANSPORT_PS_RECONNECT_SENT:
     return "S_RECONNECT_SENT";
-  case S_CONNECTED_SWITCHING_BLACKLIST:
-    return "S_CONNECTED_SWITCHING_BLACKLIST";
-  case S_CONNECTED_SWITCHING_CONNECT_SENT:
+  case GNUNET_TRANSPORT_PS_CONNECTED_SWITCHING_CONNECT_SENT:
     return "S_CONNECTED_SWITCHING_CONNECT_SENT";
-  case S_DISCONNECT:
+  case GNUNET_TRANSPORT_PS_DISCONNECT:
     return "S_DISCONNECT";
-  case S_DISCONNECT_FINISHED:
+  case GNUNET_TRANSPORT_PS_DISCONNECT_FINISHED:
     return "S_DISCONNECT_FINISHED";
   default:
     GNUNET_break (0);
@@ -229,6 +214,33 @@ GNUNET_TRANSPORT_p2s (enum GNUNET_TRANSPORT_PeerState state)
   }
 }
 
+/**
+ * Convert validation state to human-readable string.
+ *
+ * @param state the state value
+ * @return corresponding string
+ */
+const char *
+GNUNET_TRANSPORT_vs2s (enum GNUNET_TRANSPORT_ValidationState state)
+{
+  switch (state)
+  {
+  case GNUNET_TRANSPORT_VS_NONE:
+    return "NONE";
+  case GNUNET_TRANSPORT_VS_NEW:
+    return "NEW";
+  case GNUNET_TRANSPORT_VS_REMOVE:
+    return "REMOVE";
+  case GNUNET_TRANSPORT_VS_TIMEOUT:
+    return "TIMEOUT";
+  case GNUNET_TRANSPORT_VS_UPDATE:
+    return "UPDATE";
+  default:
+    GNUNET_break (0);
+    return "UNDEFINED";
+  }
+}
+
 
 /**
  * Function called with responses from the service.
@@ -238,32 +250,63 @@ GNUNET_TRANSPORT_p2s (enum GNUNET_TRANSPORT_PeerState state)
  *        message with the human-readable address
  */
 static void
-peer_response_processor (void *cls,
-                                 const struct GNUNET_MessageHeader *msg);
+peer_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
 
 
+/**
+ * Function called with responses from the service.
+ *
+ * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
+ * @param msg NULL on timeout or error, otherwise presumably a
+ *        message with the human-readable address
+ */
+static void
+val_response_processor (void *cls, const struct GNUNET_MessageHeader *msg);
+
 /**
  * Send our subscription request to the service.
  *
  * @param pal_ctx our context
  */
 static void
-send_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
+send_peer_mon_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
 {
   struct PeerMonitorMessage msg;
 
   msg.header.size = htons (sizeof (struct PeerMonitorMessage));
   msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_REQUEST);
   msg.one_shot = htonl (pal_ctx->one_shot);
-  msg.timeout = GNUNET_TIME_absolute_hton (pal_ctx->timeout);
   msg.peer = pal_ctx->peer;
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CLIENT_transmit_and_get_response (pal_ctx->client,
-                                                         &msg.header,
-                                                          GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
-                                                         GNUNET_YES,
-                                                          &peer_response_processor,
-                                                          pal_ctx));
+                    &msg.header,
+                    GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout),
+                    GNUNET_YES,
+                    &peer_response_processor,
+                    pal_ctx));
+}
+
+/**
+ * Send our subscription request to the service.
+ *
+ * @param val_ctx our context
+ */
+static void
+send_val_mon_request (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
+{
+  struct ValidationMonitorMessage msg;
+
+  msg.header.size = htons (sizeof (struct ValidationMonitorMessage));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_REQUEST);
+  msg.one_shot = htonl (val_ctx->one_shot);
+  msg.peer = val_ctx->peer;
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CLIENT_transmit_and_get_response (val_ctx->client,
+                    &msg.header,
+                    GNUNET_TIME_absolute_get_remaining (val_ctx->timeout),
+                    GNUNET_YES,
+                    &val_response_processor,
+                    val_ctx));
 }
 
 /**
@@ -273,15 +316,15 @@ send_request (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
  * @param tc scheduler context, unused
  */
 static void
-do_connect (void *cls,
-           const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_peer_connect (void *cls,
+           const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
 
   pal_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
   pal_ctx->client = GNUNET_CLIENT_connect ("transport", pal_ctx->cfg);
   GNUNET_assert (NULL != pal_ctx->client);
-  send_request (pal_ctx);
+  send_peer_mon_request (pal_ctx);
 }
 
 
@@ -291,28 +334,228 @@ do_connect (void *cls,
  * @param pal_ctx our context
  */
 static void
-reconnect (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
+reconnect_peer_ctx (struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx)
 {
   GNUNET_assert (GNUNET_NO == pal_ctx->one_shot);
   GNUNET_CLIENT_disconnect (pal_ctx->client);
   pal_ctx->client = NULL;
+  pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+               GNUNET_TRANSPORT_PS_NOT_CONNECTED,
+               GNUNET_TIME_UNIT_ZERO_ABS);
   pal_ctx->backoff = GNUNET_TIME_STD_BACKOFF (pal_ctx->backoff);
   pal_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (pal_ctx->backoff,
-                                                         &do_connect,
+                                                         &do_peer_connect,
                                                          pal_ctx);
 }
 
 
+/**
+ * Task run to re-establish the connection.
+ *
+ * @param cls our 'struct GNUNET_TRANSPORT_PeerAddressLookupContext*'
+ * @param tc scheduler context, unused
+ */
+static void
+do_val_connect (void *cls,
+           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
+
+  val_ctx->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  val_ctx->client = GNUNET_CLIENT_connect ("transport", val_ctx->cfg);
+  GNUNET_assert (NULL != val_ctx->client);
+  send_val_mon_request (val_ctx);
+}
+
+/**
+ * Cut the existing connection and reconnect.
+ *
+ * @param val_ctx our context
+ */
+static void
+reconnect_val_ctx (struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx)
+{
+  GNUNET_assert (GNUNET_NO == val_ctx->one_shot);
+  GNUNET_CLIENT_disconnect (val_ctx->client);
+  val_ctx->client = NULL;
+  /* notify clients about (re)connect */
+  val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+               GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+               GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
+  val_ctx->backoff = GNUNET_TIME_STD_BACKOFF (val_ctx->backoff);
+  val_ctx->reconnect_task = GNUNET_SCHEDULER_add_delayed (val_ctx->backoff,
+                                                          &do_val_connect,
+                                                          val_ctx);
+}
+
+
 /**
  * Function called with responses from the service.
  *
- * @param cls our 'struct GNUNET_TRANSPORT_PeerMonitoringContext*'
+ * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
+ * @param msg NULL on timeout or error, otherwise presumably a
+ *        message with the human-readable address
+ */
+static void
+val_response_processor (void *cls,
+                        const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx = cls;
+  struct ValidationIterateResponseMessage *vr_msg;
+  struct GNUNET_HELLO_Address *address;
+  const char *addr;
+  const char *transport_name;
+  size_t size;
+  size_t tlen;
+  size_t alen;
+
+  if (NULL == msg)
+  {
+    if (val_ctx->one_shot)
+    {
+      /* Disconnect */
+      val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_TIMEOUT);
+      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
+    }
+    else
+    {
+      reconnect_val_ctx (val_ctx);
+    }
+    return;
+  }
+  size = ntohs (msg->size);
+  GNUNET_break (ntohs (msg->type) ==
+      GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE);
+
+  if (size == sizeof (struct GNUNET_MessageHeader))
+  {
+    /* Done! */
+    if (val_ctx->one_shot)
+    {
+      val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
+      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
+    }
+    else
+    {
+      reconnect_val_ctx (val_ctx);
+    }
+    return;
+  }
+
+  if ((size < sizeof (struct ValidationIterateResponseMessage)) ||
+      (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_VALIDATION_RESPONSE))
+  {
+    GNUNET_break (0);
+    if (val_ctx->one_shot)
+    {
+      val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
+      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
+    }
+    else
+    {
+      reconnect_val_ctx (val_ctx);
+    }
+    return;
+  }
+
+  vr_msg = (struct ValidationIterateResponseMessage *) msg;
+  tlen = ntohl (vr_msg->pluginlen);
+  alen = ntohl (vr_msg->addrlen);
+
+  if (size != sizeof (struct ValidationIterateResponseMessage) + tlen + alen)
+  {
+    GNUNET_break (0);
+    if (val_ctx->one_shot)
+    {
+      val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
+      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
+    }
+    else
+    {
+      reconnect_val_ctx (val_ctx);
+    }
+    return;
+  }
+  if ( (0 == tlen) && (0 == alen) )
+  {
+    GNUNET_break (0);
+    if (val_ctx->one_shot)
+    {
+      val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+          GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
+      GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
+    }
+    else
+    {
+      reconnect_val_ctx (val_ctx);
+    }
+    return;
+  }
+  else
+  {
+    if (0 == tlen)
+    {
+      GNUNET_break (0); /* This must not happen: address without plugin */
+      return;
+    }
+    addr = (const char *) &vr_msg[1];
+    transport_name = &addr[alen];
+
+    if (transport_name[tlen - 1] != '\0')
+    {
+      /* Corrupt plugin name */
+      GNUNET_break (0);
+      if (val_ctx->one_shot)
+      {
+        val_ctx->cb (val_ctx->cb_cls, NULL, NULL,
+            GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TIME_UNIT_ZERO_ABS,
+            GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NONE);
+        GNUNET_TRANSPORT_monitor_validation_entries_cancel (val_ctx);
+      }
+      else
+      {
+        reconnect_val_ctx (val_ctx);
+      }
+      return;
+    }
+
+    /* notify client */
+    address = GNUNET_HELLO_address_allocate (&vr_msg->peer,
+        transport_name, addr, alen, ntohl(vr_msg->local_address_info));
+    val_ctx->cb (val_ctx->cb_cls, &vr_msg->peer, address,
+        GNUNET_TIME_absolute_ntoh(vr_msg->last_validation),
+        GNUNET_TIME_absolute_ntoh(vr_msg->valid_until),
+        GNUNET_TIME_absolute_ntoh(vr_msg->next_validation),
+        ntohl(vr_msg->state));
+    GNUNET_HELLO_address_free (address);
+  }
+  /* expect more replies */
+  GNUNET_CLIENT_receive (val_ctx->client,
+                         &val_response_processor,
+                         val_ctx,
+                         GNUNET_TIME_absolute_get_remaining (val_ctx->timeout));
+}
+
+
+/**
+ * Function called with responses from the service.
+ *
+ * @param cls our `struct GNUNET_TRANSPORT_PeerMonitoringContext *`
  * @param msg NULL on timeout or error, otherwise presumably a
  *        message with the human-readable address
  */
 static void
 peer_response_processor (void *cls,
-                                 const struct GNUNET_MessageHeader *msg)
+                         const struct GNUNET_MessageHeader *msg)
 {
   struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx = cls;
   struct PeerIterateResponseMessage *pir_msg;
@@ -323,17 +566,18 @@ peer_response_processor (void *cls,
   size_t alen;
   size_t tlen;
 
-  if (msg == NULL)
+  if (NULL == msg)
   {
     if (pal_ctx->one_shot)
     {
+      /* Disconnect */
       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
-          S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
     }
     else
     {
-      reconnect (pal_ctx);
+      reconnect_peer_ctx (pal_ctx);
     }
     return;
   }
@@ -342,34 +586,35 @@ peer_response_processor (void *cls,
       GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE);
   if (size == sizeof (struct GNUNET_MessageHeader))
   {
-    /* done! */
+    /* Done! */
     if (pal_ctx->one_shot)
     {
+      /* iteration finished */
       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
-          S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
     }
     else
     {
-      reconnect (pal_ctx);
+      reconnect_peer_ctx (pal_ctx);
     }
     return;
   }
 
   if ((size < sizeof (struct PeerIterateResponseMessage)) ||
-      (ntohs (msg->type) !=
-          GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE))
+      (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_TRANSPORT_MONITOR_PEER_RESPONSE))
   {
     GNUNET_break (0);
     if (pal_ctx->one_shot)
     {
+      /* iteration finished (with error) */
       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
-          S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
     }
     else
     {
-      reconnect (pal_ctx);
+      reconnect_peer_ctx (pal_ctx);
     }
     return;
   }
@@ -384,49 +629,58 @@ peer_response_processor (void *cls,
     if (pal_ctx->one_shot)
     {
       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
-          S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+          GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
     }
     else
     {
-      reconnect (pal_ctx);
+      reconnect_peer_ctx (pal_ctx);
     }
     return;
   }
 
-  if (alen == 0 && tlen == 0)
+  if ( (0 == tlen) && (0 == alen) )
   {
+    /* No address available */
     pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, NULL,
-        S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+        ntohl(pir_msg->state),
+        GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
   }
   else
   {
+    if (0 == tlen)
+    {
+      GNUNET_break (0); /* This must not happen: address without plugin */
+      return;
+    }
     addr = (const char *) &pir_msg[1];
     transport_name = &addr[alen];
 
     if (transport_name[tlen - 1] != '\0')
     {
+      /* Corrupt plugin name */
       GNUNET_break (0);
-      if (pal_ctx->one_shot)   
+      if (pal_ctx->one_shot)
       {
-       pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
-           S_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
-       GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
+        pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL,
+            GNUNET_TRANSPORT_PS_NOT_CONNECTED, GNUNET_TIME_UNIT_ZERO_ABS);
+        GNUNET_TRANSPORT_monitor_peers_cancel (pal_ctx);
       }
       else
       {
-       reconnect (pal_ctx);
+        reconnect_peer_ctx (pal_ctx);
       }
       return;
     }
 
     /* notify client */
     address = GNUNET_HELLO_address_allocate (&pir_msg->peer,
-        transport_name, addr, alen);
+        transport_name, addr, alen, ntohl(pir_msg->local_address_info));
     pal_ctx->cb (pal_ctx->cb_cls, &pir_msg->peer, address,
         ntohl(pir_msg->state),
         GNUNET_TIME_absolute_ntoh (pir_msg->state_timeout));
     GNUNET_HELLO_address_free (address);
+
   }
 
   /* expect more replies */
@@ -437,32 +691,39 @@ peer_response_processor (void *cls,
 
 
 /**
- * Return all the known addresses for a specific peer or all peers.
- * Returns continuously all address if one_shot is set to GNUNET_NO
+ * Return information about a specific peer or all peers currently known to
+ * transport service once or in monitoring mode. To obtain information about
+ * a specific peer, a peer identity can be passed. To obtain information about
+ * all peers currently known to transport service, NULL can be passed as peer
+ * identity.
+ *
+ * For each peer, the callback is called with information about the address used
+ * to communicate with this peer, the state this peer is currently in and the
+ * the current timeout for this state.
  *
- * CHANGE: Returns the address(es) that we are currently using for this
- * peer.  Upon completion, the 'AddressLookUpCallback' is called one more
- * time with 'NULL' for the address and the peer.  After this, the operation must no
- * longer be explicitly canceled.
+ * Upon completion, the 'GNUNET_TRANSPORT_PeerIterateCallback' is called one
+ * more time with 'NULL'. After this, the operation must no longer be
+ * explicitly canceled.
  *
  * The #GNUNET_TRANSPORT_monitor_peers_cancel call MUST not be called in the
  * the peer_callback!
  *
  * @param cfg configuration to use
- * @param peer peer identity to look up the addresses of, CHANGE: allow NULL for all (connected) peers
- * @param one_shot GNUNET_YES to return the current state and then end (with NULL+NULL),
- *                 GNUNET_NO to monitor the set of addresses used (continuously, must be explicitly canceled)
- * @param timeout how long is the lookup allowed to take at most (irrelevant if one_shot is set to GNUNET_NO)
+ * @param peer a specific peer identity to obtain information for,
+ *      NULL for all peers
+ * @param one_shot #GNUNET_YES to return the current state and then end (with NULL+NULL),
+ *                 #GNUNET_NO to monitor peers continuously
+ * @param timeout how long is the lookup allowed to take at most
  * @param peer_callback function to call with the results
- * @param peer_callback_cls closure for peer_address_callback
+ * @param peer_callback_cls closure for @a peer_address_callback
  */
 struct GNUNET_TRANSPORT_PeerMonitoringContext *
 GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
-    const struct GNUNET_PeerIdentity *peer,
-    int one_shot,
-    struct GNUNET_TIME_Relative timeout,
-    GNUNET_TRANSPORT_PeerIterateCallback peer_callback,
-    void *peer_callback_cls)
+                                const struct GNUNET_PeerIdentity *peer,
+                                int one_shot,
+                                struct GNUNET_TIME_Relative timeout,
+                                GNUNET_TRANSPORT_PeerIterateCallback peer_callback,
+                                void *peer_callback_cls)
 {
   struct GNUNET_TRANSPORT_PeerMonitoringContext *pal_ctx;
   struct GNUNET_CLIENT_Connection *client;
@@ -481,7 +742,7 @@ GNUNET_TRANSPORT_monitor_peers (const struct GNUNET_CONFIGURATION_Handle *cfg,
     pal_ctx->peer = *peer;
   pal_ctx->one_shot = one_shot;
   pal_ctx->client = client;
-  send_request (pal_ctx);
+  send_peer_mon_request (pal_ctx);
 
   return pal_ctx;
 }
@@ -531,8 +792,26 @@ GNUNET_TRANSPORT_monitor_validation_entries (const struct
                                 GNUNET_TRANSPORT_ValidationIterateCallback validation_callback,
                                 void *validation_callback_cls)
 {
-  /* Not implemented */
-  return NULL;
+  struct GNUNET_TRANSPORT_ValidationMonitoringContext *val_ctx;
+  struct GNUNET_CLIENT_Connection *client;
+
+  client = GNUNET_CLIENT_connect ("transport", cfg);
+  if (client == NULL)
+    return NULL;
+  if (GNUNET_YES != one_shot)
+    timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  val_ctx = GNUNET_new (struct GNUNET_TRANSPORT_ValidationMonitoringContext);
+  val_ctx->cb = validation_callback;
+  val_ctx->cb_cls = validation_callback_cls;
+  val_ctx->cfg = cfg;
+  val_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  if (NULL != peer)
+    val_ctx->peer = *peer;
+  val_ctx->one_shot = one_shot;
+  val_ctx->client = client;
+  send_val_mon_request (val_ctx);
+
+  return val_ctx;
 }
 
 
@@ -544,7 +823,17 @@ GNUNET_TRANSPORT_monitor_validation_entries (const struct
 void
 GNUNET_TRANSPORT_monitor_validation_entries_cancel (struct GNUNET_TRANSPORT_ValidationMonitoringContext *vic)
 {
-  /* Not implemented */
+  if (NULL != vic->client)
+  {
+    GNUNET_CLIENT_disconnect (vic->client);
+    vic->client = NULL;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != vic->reconnect_task)
+  {
+    GNUNET_SCHEDULER_cancel (vic->reconnect_task);
+    vic->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_free (vic);
 }