-changing exit helper code to automatically do the network configuration for an exit...
[oweals/gnunet.git] / src / transport / transport_api_address_lookup.c
index 689e553b38b3e02f0d68a3ed5bc10239038bce77..9ae9b403103e99091c15063a53ace8687093fcc5 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
 */
      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      Boston, MA 02111-1307, USA.
 */
+
+/**
+ * @file transport/transport_api_peer_address_lookup.c
+ * @brief given a peer id, get all known addresses from transport service
+ *
+ * This api provides the ability to query the transport service about
+ * the status of connections to a specific peer.  Calls back with a
+ * pretty printed string of the address, as formatted by the appropriate
+ * transport plugin, and whether or not the address given is currently
+ * in the 'connected' state (according to the transport service).
+ */
+
 #include "platform.h"
 #include "gnunet_client_lib.h"
 #include "gnunet_arm_service.h"
 #include "platform.h"
 #include "gnunet_client_lib.h"
 #include "gnunet_arm_service.h"
 
 /**
  * Context for the address lookup.
 
 /**
  * Context for the address lookup.
- */ 
-struct AddressLookupCtx
+ */
+struct GNUNET_TRANSPORT_PeerIterateContext
 {
   /**
 {
   /**
-   * Function to call with the human-readable address.
+   * Function to call with the binary address.
    */
    */
-  GNUNET_TRANSPORT_AddressLookUpCallback cb;
+  GNUNET_TRANSPORT_PeerIterateCallback cb;
 
   /**
    * Closure for cb.
 
   /**
    * Closure for cb.
@@ -57,124 +69,166 @@ struct AddressLookupCtx
 /**
  * Function called with responses from the service.
  *
 /**
  * Function called with responses from the service.
  *
- * @param cls our 'struct AddressLookupCtx*'
+ * @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
  * @param msg NULL on timeout or error, otherwise presumably a
  *        message with the human-readable address
  */
 static void
-address_response_processor (void *cls, 
-                           const struct GNUNET_MessageHeader *msg)
+peer_address_response_processor (void *cls,
+                                 const struct GNUNET_MessageHeader *msg)
 {
 {
-  struct AddressLookupCtx *alucb = cls;
-  const char *address;
+  struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx = cls;
+  struct AddressIterateResponseMessage *air_msg;
+  struct GNUNET_HELLO_Address *address;
+  const char *addr;
+  const char *transport_name;
   uint16_t size;
   uint16_t size;
+  size_t alen;
+  size_t tlen;
 
   if (msg == NULL)
 
   if (msg == NULL)
-    {
-      alucb->cb (alucb->cb_cls, NULL);
-      GNUNET_CLIENT_disconnect (alucb->client, GNUNET_NO);
-      GNUNET_free (alucb);
-      return;
-    }
-  GNUNET_break (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_REPLY);
+  {
+    pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
+    GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
+    return;
+  }
   size = ntohs (msg->size);
   size = ntohs (msg->size);
+  GNUNET_break (ntohs (msg->type) ==
+                GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE);
   if (size == sizeof (struct GNUNET_MessageHeader))
   if (size == sizeof (struct GNUNET_MessageHeader))
-    {
-      /* done! */
-      alucb->cb (alucb->cb_cls, NULL);
-      GNUNET_CLIENT_disconnect (alucb->client, GNUNET_NO);
-      GNUNET_free (alucb);
-      return;
-    }
-  address = (const char *) &msg[1];
-  if (address[size - sizeof (struct GNUNET_MessageHeader) - 1] != '\0')
-    {
-      /* invalid reply */
-      GNUNET_break (0);
-      alucb->cb (alucb->cb_cls, NULL);
-      GNUNET_CLIENT_disconnect (alucb->client, GNUNET_NO);
-      GNUNET_free (alucb);
-      return;
-    }
+  {
+    /* done! */
+    pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
+    GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
+    return;
+  }
+
+  if ((size <
+       sizeof (struct GNUNET_MessageHeader) +
+       sizeof (struct AddressIterateResponseMessage)) ||
+      (ntohs (msg->type) !=
+       GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE_RESPONSE))
+  {
+    GNUNET_break (0);
+    pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
+    GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
+    return;
+  }
+
+  air_msg = (struct AddressIterateResponseMessage *) msg;
+  tlen = ntohl (air_msg->pluginlen);
+  alen = ntohl (air_msg->addrlen);
+
+  if (size != sizeof (struct AddressIterateResponseMessage) + tlen + alen)
+  {
+    GNUNET_break (0);
+    pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
+    GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
+    return;
+  }
+
+  addr = (const char *) &air_msg[1];
+  transport_name = &addr[alen];
+
+  if (transport_name[tlen - 1] != '\0')
+  {
+    GNUNET_break_op (0);
+    pal_ctx->cb (pal_ctx->cb_cls, NULL, NULL);
+    GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pal_ctx);
+    return;
+  }
+
   /* expect more replies */
   /* expect more replies */
-  GNUNET_CLIENT_receive (alucb->client,
-                        &address_response_processor, alucb,
-                        GNUNET_TIME_absolute_get_remaining
-                        (alucb->timeout));    
-  alucb->cb (alucb->cb_cls, address);
+  GNUNET_CLIENT_receive (pal_ctx->client, &peer_address_response_processor,
+                         pal_ctx,
+                         GNUNET_TIME_absolute_get_remaining (pal_ctx->timeout));
+
+  /* notify client */
+  address =
+      GNUNET_HELLO_address_allocate (&air_msg->peer, transport_name, addr,
+                                     alen);
+  pal_ctx->cb (pal_ctx->cb_cls, &air_msg->peer, address);
+  GNUNET_HELLO_address_free (address);
 }
 
 
 /**
 }
 
 
 /**
- * Convert a binary address into a human readable address.
+ * Return all the known addresses for a specific peer or all peers.
+ * Returns continously all address if one_shot is set to GNUNET_NO
+ *
+ * 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 cancelled.
  *
  *
- * @param sched scheduler to use
  * @param cfg configuration to use
  * @param cfg configuration to use
- * @param address address to convert (binary format)
- * @param addressLen number of bytes in address
- * @param numeric should (IP) addresses be displayed in numeric form 
- *                (otherwise do reverse DNS lookup)
- * @param nameTrans name of the transport to which the address belongs
+ * @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 cancelled)
  * @param timeout how long is the lookup allowed to take at most
  * @param timeout how long is the lookup allowed to take at most
- * @param aluc function to call with the results
- * @param aluc_cls closure for aluc
+ * @param peer_address_callback function to call with the results
+ * @param peer_address_callback_cls closure for peer_address_callback
  */
  */
-void
-GNUNET_TRANSPORT_address_lookup (struct GNUNET_SCHEDULER_Handle *sched,
-                                 const struct GNUNET_CONFIGURATION_Handle  *cfg, 
-                                const char *address, 
-                                size_t addressLen,
-                                int numeric,
-                                 const char *nameTrans,
-                                 struct GNUNET_TIME_Relative timeout,
-                                 GNUNET_TRANSPORT_AddressLookUpCallback aluc,
-                                 void *aluc_cls)
+struct GNUNET_TRANSPORT_PeerIterateContext *
+GNUNET_TRANSPORT_peer_get_active_addresses (const struct
+                                            GNUNET_CONFIGURATION_Handle *cfg,
+                                            const struct GNUNET_PeerIdentity
+                                            *peer, int one_shot,
+                                            struct GNUNET_TIME_Relative timeout,
+                                            GNUNET_TRANSPORT_PeerIterateCallback
+                                            peer_address_callback,
+                                            void *peer_address_callback_cls)
 {
 {
-  size_t slen;
-  size_t len;
-  struct AddressLookupMessage *msg;
-  struct GNUNET_TIME_Absolute abs_timeout;
-  struct AddressLookupCtx *aluCB;
+  struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx;
+  struct AddressIterateMessage msg;
   struct GNUNET_CLIENT_Connection *client;
   struct GNUNET_CLIENT_Connection *client;
-  char *addrbuf;
-
-  slen = strlen (nameTrans) + 1;
-  len = sizeof (struct AddressLookupMessage) + addressLen + slen;
-  if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
-    {
-      GNUNET_break (0);
-      aluc (aluc_cls, NULL);
-      return;
-    }
-  client = GNUNET_CLIENT_connect (sched, "transport", cfg);
+  struct GNUNET_TIME_Absolute abs_timeout;
+
+  if (GNUNET_YES != one_shot)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Address monitoring not implemented\n");
+    return NULL;
+  }
+  client = GNUNET_CLIENT_connect ("transport", cfg);
   if (client == NULL)
   if (client == NULL)
-    {
-      aluc (aluc_cls, NULL);
-      return;
-    }
+    return NULL;
   abs_timeout = GNUNET_TIME_relative_to_absolute (timeout);
   abs_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  msg = GNUNET_malloc (len);
-  msg->header.size = htons (len);
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP);
-  msg->numeric_only = htonl (numeric);
-  msg->timeout = GNUNET_TIME_absolute_hton (abs_timeout);
-  msg->addrlen = htonl (addressLen);
-  addrbuf = (char *) &msg[1];
-  memcpy (addrbuf, address, addressLen);
-  memcpy (&addrbuf[addressLen], nameTrans, slen);
-  aluCB = GNUNET_malloc (sizeof (struct AddressLookupCtx));
-  aluCB->cb = aluc;
-  aluCB->cb_cls = aluc_cls;
-  aluCB->timeout = abs_timeout;
-  aluCB->client = client;
+  msg.header.size = htons (sizeof (struct AddressIterateMessage));
+  msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_ITERATE);
+  msg.one_shot = htonl (one_shot);
+  msg.timeout = GNUNET_TIME_absolute_hton (abs_timeout);
+  if (peer == NULL)
+    memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity));
+  else
+    msg.peer = *peer;
+  pal_ctx = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PeerIterateContext));
+  pal_ctx->cb = peer_address_callback;
+  pal_ctx->cb_cls = peer_address_callback_cls;
+  pal_ctx->timeout = abs_timeout;
+  pal_ctx->client = client;
   GNUNET_assert (GNUNET_OK ==
   GNUNET_assert (GNUNET_OK ==
-                GNUNET_CLIENT_transmit_and_get_response (client, 
-                                                         &msg->header, 
-                                                         timeout,
-                                                         GNUNET_YES,
-                                                         &address_response_processor,
-                                                         aluCB));
-  GNUNET_free (msg);
+                 GNUNET_CLIENT_transmit_and_get_response (client, &msg.header,
+                                                          timeout, GNUNET_YES,
+                                                          &peer_address_response_processor,
+                                                          pal_ctx));
+  return pal_ctx;
 }
 
 }
 
-/* end of transport_api_address_lookup.c */
+
+/**
+ * Cancel request for address conversion.
+ *
+ * @param alc handle for the request to cancel
+ */
+void
+GNUNET_TRANSPORT_peer_get_active_addresses_cancel (struct
+                                                   GNUNET_TRANSPORT_PeerIterateContext
+                                                   *alc)
+{
+  GNUNET_CLIENT_disconnect (alc->client, GNUNET_NO);
+  GNUNET_free (alc);
+}
+
+
+/* end of transport_api_peer_address_lookup.c */