fixes
[oweals/gnunet.git] / src / dv / plugin_transport_dv.c
index 2c9881d30351526b7f05504fc06061a03875af87..697ca0c4cf211e3fa5cea15eaacdfc6efda51e57 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
 */
 
 /**
 */
 
 /**
- * @file transport/plugin_transport_dv.c
+ * @file dv/plugin_transport_dv.c
  * @brief DV transport service, takes incoming DV requests and deals with
  * the DV service
  * @brief DV transport service, takes incoming DV requests and deals with
  * the DV service
+ * @author Nathan Evans
  * @author Christian Grothoff
  */
 
  * @author Christian Grothoff
  */
 
-/**
- * TODO:
- *
- * As a start, the dv plugin needs to listen for information from the dv
- * service.  The plugin (?) will be notified by core (?) when a tcp/udp/whatever
- * message comes in that should be for dv.  The plugin will then hand off the message
- * to the dv service which will decrypt/validate the message (?) and then send the
- * result back to us (the transport) which will then send the message to the transport
- * service (yikes).
- *
- * Or, core will notify the dv service directly which will validate,
- * etc. and then just send a message to us.
- *
- * For starters, this plugin needs to have a client which will listen for messages from
- * the dv service that need to be sent up to the gnunet-transport-service.
- *
- * Messages sent from the dv transport get passed to the dv service which deals
- * with the actual sending (how much state does this transport need? should it know
- * which peers it is currently connected to and their distances, or just assume that
- * anything should be passed along to the dv service?).
- */
 #include "platform.h"
 #include "gnunet_protocols.h"
 #include "gnunet_connection_lib.h"
 #include "platform.h"
 #include "gnunet_protocols.h"
 #include "gnunet_connection_lib.h"
@@ -54,7 +34,7 @@
 #include "gnunet_statistics_service.h"
 #include "gnunet_dv_service.h"
 #include "gnunet_transport_service.h"
 #include "gnunet_statistics_service.h"
 #include "gnunet_dv_service.h"
 #include "gnunet_transport_service.h"
-#include "../transport/plugin_transport.h"
+#include "gnunet_transport_plugin.h"
 #include "dv.h"
 
 #define DEBUG_TEMPLATE GNUNET_NO
 #include "dv.h"
 
 #define DEBUG_TEMPLATE GNUNET_NO
@@ -138,11 +118,6 @@ struct Plugin
    */
   struct Session *sessions;
 
    */
   struct Session *sessions;
 
-  /**
-   * Handle for the statistics service.
-   */
-  struct GNUNET_STATISTICS_Handle *statistics;
-
   /**
    * Our server.
    */
   /**
    * Our server.
    */
@@ -166,20 +141,39 @@ struct Plugin
 
 };
 
 
 };
 
-
+/**
+ * Handler for messages received from the DV service.
+ */
 void handle_dv_message_received (void *cls,
                                  struct GNUNET_PeerIdentity *sender,
 void handle_dv_message_received (void *cls,
                                  struct GNUNET_PeerIdentity *sender,
-                                 struct GNUNET_MessageHeader *msg,
-                                 unsigned int distance,
+                                 char *msg,
+                                 size_t msg_len,
+                                 uint32_t distance,
                                  char *sender_address,
                                  size_t sender_address_len)
 {
   struct Plugin *plugin = cls;
                                  char *sender_address,
                                  size_t sender_address_len)
 {
   struct Plugin *plugin = cls;
-
-  plugin->env->receive(plugin,
+#if DEBUG_DV_MESSAGES
+  char *my_id;
+  my_id = GNUNET_strdup(GNUNET_i2s(plugin->env->my_identity));
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+                   "plugin_transport_dv",
+                   _("%s Received message from %s of type %d, distance %u!\n"),
+                   my_id, GNUNET_i2s(sender), ntohs(((struct GNUNET_MessageHeader *)msg)->type), distance);
+  GNUNET_free_non_null(my_id);
+#endif
+  struct GNUNET_TRANSPORT_ATS_Information ats[2];
+  ats[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+  ats[0].value = htonl (distance);
+  ats[1].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+  ats[1].value = htonl (0);
+
+  plugin->env->receive(plugin->env->cls,
                        sender,
                        sender,
-                       msg,
-                       distance,
+                       (struct GNUNET_MessageHeader *)msg,
+                       (const struct GNUNET_TRANSPORT_ATS_Information *) &ats,
+                       2,
+                       NULL,
                        sender_address,
                        sender_address_len);
 
                        sender_address,
                        sender_address_len);
 
@@ -201,6 +195,7 @@ void handle_dv_message_received (void *cls,
  * @param msgbuf the message to transmit
  * @param msgbuf_size number of bytes in 'msgbuf'
  * @param timeout when should we time out
  * @param msgbuf the message to transmit
  * @param msgbuf_size number of bytes in 'msgbuf'
  * @param timeout when should we time out
+ * @param session the session used
  * @param addr the address to use (can be NULL if the plugin
  *                is "on its own" (i.e. re-use existing TCP connection))
  * @param addrlen length of the address in bytes
  * @param addr the address to use (can be NULL if the plugin
  *                is "on its own" (i.e. re-use existing TCP connection))
  * @param addrlen length of the address in bytes
@@ -223,6 +218,7 @@ dv_plugin_send (void *cls,
                 size_t msgbuf_size,
                 unsigned int priority,
                 struct GNUNET_TIME_Relative timeout,
                 size_t msgbuf_size,
                 unsigned int priority,
                 struct GNUNET_TIME_Relative timeout,
+               struct Session *session,
                 const void *addr,
                 size_t addrlen,
                 int force_address,
                 const void *addr,
                 size_t addrlen,
                 int force_address,
@@ -232,9 +228,6 @@ dv_plugin_send (void *cls,
   int ret = 0;
   struct Plugin *plugin = cls;
 
   int ret = 0;
   struct Plugin *plugin = cls;
 
-  /* FIXME: do we want the dv plugin to remember sent messages to call continuation once message actually goes out?
-   * Or do we just call the continuation once we've notified the plugin?
-   */
   ret = GNUNET_DV_send(plugin->dv_handle,
                        target,
                        msgbuf,
   ret = GNUNET_DV_send(plugin->dv_handle,
                        target,
                        msgbuf,
@@ -242,14 +235,9 @@ dv_plugin_send (void *cls,
                        priority,
                        timeout,
                        addr,
                        priority,
                        timeout,
                        addr,
-                       addrlen);
-  /*, cont, cont_cls);*/
-
-  if (ret == 0)
-    cont(cls, target, GNUNET_OK);
-  else
-    cont(cls, target, GNUNET_SYSERR);
-
+                       addrlen,
+                       cont,
+                       cont_cls);
   return ret;
 }
 
   return ret;
 }
 
@@ -265,7 +253,7 @@ dv_plugin_send (void *cls,
  */
 static void
 dv_plugin_disconnect (void *cls,
  */
 static void
 dv_plugin_disconnect (void *cls,
-                            const struct GNUNET_PeerIdentity *target)
+                      const struct GNUNET_PeerIdentity *target)
 {
   // struct Plugin *plugin = cls;
   // TODO: Add message type to send to dv service to "disconnect" a peer
 {
   // struct Plugin *plugin = cls;
   // TODO: Add message type to send to dv service to "disconnect" a peer
@@ -296,34 +284,102 @@ dv_plugin_address_pretty_printer (void *cls,
                                   GNUNET_TRANSPORT_AddressStringCallback
                                   asc, void *asc_cls)
 {
                                   GNUNET_TRANSPORT_AddressStringCallback
                                   asc, void *asc_cls)
 {
-  asc (asc_cls, NULL);
+  char *dest_peer;
+  char *via_peer;
+  char *print_string;
+  char *addr_buf = (char *)addr;
+
+  if (addrlen != sizeof(struct GNUNET_PeerIdentity) * 2)
+    {
+      asc (asc_cls, NULL);
+    }
+  else
+    {
+      dest_peer = GNUNET_strdup(GNUNET_i2s((struct GNUNET_PeerIdentity *)addr));
+      via_peer = GNUNET_strdup(GNUNET_i2s((struct GNUNET_PeerIdentity *)&addr_buf[sizeof(struct GNUNET_PeerIdentity)]));
+      GNUNET_asprintf(&print_string, "DV Peer `%s' via peer`%s'", dest_peer, via_peer);
+      asc (asc_cls, print_string);
+      asc (asc_cls, NULL);
+      GNUNET_free(via_peer);
+      GNUNET_free(dest_peer);
+      GNUNET_free(print_string);
+    }
 }
 
 }
 
+/**
+ * Convert the DV address to a pretty string.
+ *
+ * @param cls closure
+ * @param addr the (hopefully) DV address
+ * @param addrlen the length of the address
+ *
+ * @return string representing the DV address
+ */
+static const char *address_to_string (void *cls,
+                                       const void *addr,
+                                       size_t addrlen)
+{
+  static char return_buffer[2 * 4 + 2]; // Two four character peer identity prefixes a ':' and '\0'
+
+  struct GNUNET_CRYPTO_HashAsciiEncoded peer_hash;
+  struct GNUNET_CRYPTO_HashAsciiEncoded via_hash;
+  struct GNUNET_PeerIdentity *peer;
+  struct GNUNET_PeerIdentity *via;
+  char *addr_buf = (char *)addr;
+
+  if (addrlen == (2 * sizeof(struct GNUNET_PeerIdentity)))
+    {
+      peer = (struct GNUNET_PeerIdentity *)addr_buf;
+      via = (struct GNUNET_PeerIdentity *)&addr_buf[sizeof(struct GNUNET_PeerIdentity)];
+
+      GNUNET_CRYPTO_hash_to_enc (&peer->hashPubKey, &peer_hash);
+      peer_hash.encoding[4] = '\0';
+      GNUNET_CRYPTO_hash_to_enc (&via->hashPubKey, &via_hash);
+      via_hash.encoding[4] = '\0';
+      GNUNET_snprintf (return_buffer,
+                       sizeof (return_buffer),
+                       "%s:%s",
+                       &peer_hash,
+                       &via_hash);
+    }
+  else
+    return NULL;
 
 
+  return return_buffer;
+}
 
 /**
 
 /**
- * Another peer has suggested an address for this
- * peer and transport plugin.  Check that this could be a valid
- * address.  If so, consider adding it to the list
- * of addresses.
+ * Another peer has suggested an address for this peer and transport
+ * plugin.  Check that this could be a valid address.  This function
+ * is not expected to 'validate' the address in the sense of trying to
+ * connect to it but simply to see if the binary format is technically
+ * legal for establishing a connection to this peer (and make sure that
+ * the address really corresponds to our network connection/settings
+ * and not some potential man-in-the-middle).
  *
  * @param cls closure
  * @param addr pointer to the address
  * @param addrlen length of addr
  * @return GNUNET_OK if this is a plausible address for this peer
  *
  * @param cls closure
  * @param addr pointer to the address
  * @param addrlen length of addr
  * @return GNUNET_OK if this is a plausible address for this peer
- *         and transport
+ *         and transport, GNUNET_SYSERR if not
  *
  *
- * FIXME: does this mean anything for the DV plugin?
  */
 static int
  */
 static int
-dv_plugin_address_suggested (void *cls,
-                                  void *addr, size_t addrlen)
+dv_plugin_check_address (void *cls,
+                         const void *addr, size_t addrlen)
 {
 {
-  /* struct Plugin *plugin = cls; */
-
-  /* check if the address is plausible; if so,
-     add it to our list! */
-  return GNUNET_NO;
+  struct Plugin *plugin = cls;
+  /* Verify that the first peer of this address matches our peer id! */
+  if ((addrlen != (2 * sizeof(struct GNUNET_PeerIdentity))) || (0 != memcmp(addr, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity))))
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Address not correct size or identity doesn't match ours!\n", GNUNET_i2s(plugin->env->my_identity));
+    if (addrlen == (2 * sizeof(struct GNUNET_PeerIdentity)))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peer in address is %s\n", GNUNET_i2s(addr));
+    }
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
 }
 
 
 }
 
 
@@ -336,52 +392,11 @@ libgnunet_plugin_transport_dv_init (void *cls)
   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
   struct GNUNET_TRANSPORT_PluginFunctions *api;
   struct Plugin *plugin;
   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
   struct GNUNET_TRANSPORT_PluginFunctions *api;
   struct Plugin *plugin;
-  struct GNUNET_SERVICE_Context *service;
-
-  /**
-   * Do we not even need a service for this thing?  That's peculiar.
-   */
-  /*
-  service = GNUNET_SERVICE_start ("transport-dv", env->sched, env->cfg);
-  if (service == NULL)
-    {
-      GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
-                       "dv",
-                       _
-                       ("Failed to start service for `%s' transport plugin.\n"),
-                       "dv");
-      return NULL;
-    }
-   */
-  /**
-   * I don't think we need a port, the only way we get stuff is being directly
-   * called by service transport or by responses from the dv-service via our
-   * client handle
-   */
-  /*
-  if ((GNUNET_OK !=
-       GNUNET_CONFIGURATION_get_value_number (env->cfg,
-                                              "transport-dv",
-                                              "PORT",
-                                              &port)))
-    {
-      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
-                       "dv",
-                       _
-                       ("Require valid port number for service `%s' in configuration!\n"),
-                       "transport-dv");
-      GNUNET_SERVICE_stop (service);
-      return NULL;
-    }
-    */
 
   plugin = GNUNET_malloc (sizeof (struct Plugin));
   plugin->env = env;
 
   plugin = GNUNET_malloc (sizeof (struct Plugin));
   plugin->env = env;
-  plugin->statistics = NULL;
-  //plugin->service = service;
-  //plugin->server = GNUNET_SERVICE_get_server (service);
 
 
-  plugin->dv_handle = GNUNET_DV_connect(env->sched, env->cfg, &handle_dv_message_received, plugin);
+  plugin->dv_handle = GNUNET_DV_connect(env->cfg, &handle_dv_message_received, plugin);
 
   if (plugin->dv_handle == NULL)
   {
 
   if (plugin->dv_handle == NULL)
   {
@@ -394,7 +409,8 @@ libgnunet_plugin_transport_dv_init (void *cls)
   api->send = &dv_plugin_send;
   api->disconnect = &dv_plugin_disconnect;
   api->address_pretty_printer = &dv_plugin_address_pretty_printer;
   api->send = &dv_plugin_send;
   api->disconnect = &dv_plugin_disconnect;
   api->address_pretty_printer = &dv_plugin_address_pretty_printer;
-  api->check_address = &dv_plugin_address_suggested;
+  api->check_address = &dv_plugin_check_address;
+  api->address_to_string = &address_to_string;
   return api;
 }
 
   return api;
 }
 
@@ -408,6 +424,9 @@ libgnunet_plugin_transport_dv_done (void *cls)
   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
 
   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
 
+  if (plugin->dv_handle != NULL)
+    GNUNET_DV_disconnect(plugin->dv_handle);
+
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;