fix
[oweals/gnunet.git] / src / dv / plugin_transport_dv.c
index 43bbfad33f890eee7aa04d8915ca2c8ef0c2b0ac..5e2a6bd6c072ee677f9b760d3a156241fdebb070 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 dv/plugin_transport_dv.c
  * @brief DV transport service, takes incoming DV requests and deals with
  * the DV service
  * @file dv/plugin_transport_dv.c
  * @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"
 #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"
 
 #include "dv.h"
 
-#define DEBUG_TEMPLATE GNUNET_NO
+#define DEBUG_TEMPLATE GNUNET_EXTRA_LOGGING
 
 /**
  * Encapsulation of all of the state of the plugin.
 
 /**
  * Encapsulation of all of the state of the plugin.
@@ -164,31 +144,35 @@ struct Plugin
 /**
  * Handler for messages received from the DV service.
  */
 /**
  * Handler for messages received from the DV service.
  */
-void handle_dv_message_received (void *cls,
-                                 struct GNUNET_PeerIdentity *sender,
-                                 char *msg,
-                                 size_t msg_len,
-                                 uint32_t distance,
-                                 char *sender_address,
-                                 size_t sender_address_len)
+void
+handle_dv_message_received (void *cls, struct GNUNET_PeerIdentity *sender,
+                            char *msg, size_t msg_len, uint32_t distance,
+                            char *sender_address, size_t sender_address_len)
 {
   struct Plugin *plugin = cls;
 {
   struct Plugin *plugin = cls;
+
 #if DEBUG_DV_MESSAGES
   char *my_id;
 #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);
+
+  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
 #endif
-  plugin->env->receive(plugin->env->cls,
-                       sender,
-                       (struct GNUNET_MessageHeader *)msg,
-                       distance,
-                      NULL,
-                       sender_address,
-                       sender_address_len);
+  struct GNUNET_ATS_Information ats[2];
+
+  ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
+  ats[0].value = htonl (distance);
+  ats[1].type = htonl (GNUNET_ATS_ARRAY_TERMINATOR);
+  ats[1].value = htonl (0);
+
+  plugin->env->receive (plugin->env->cls, sender,
+                        (struct GNUNET_MessageHeader *) msg,
+                        (const struct GNUNET_ATS_Information *) &ats,
+                        2, NULL, sender_address, sender_address_len);
 
 }
 
 
 }
 
@@ -225,53 +209,18 @@ void handle_dv_message_received (void *cls,
  *         and does NOT mean that the message was not transmitted (DV)
  */
 static ssize_t
  *         and does NOT mean that the message was not transmitted (DV)
  */
 static ssize_t
-dv_plugin_send (void *cls,
-                const struct GNUNET_PeerIdentity *target,
-                const char *msgbuf,
-                size_t msgbuf_size,
-                unsigned int priority,
-                struct GNUNET_TIME_Relative timeout,
-               struct Session *session,
-                const void *addr,
-                size_t addrlen,
-                int force_address,
-                GNUNET_TRANSPORT_TransmitContinuation
-                cont, void *cont_cls)
+dv_plugin_send (void *cls, const struct GNUNET_PeerIdentity *target,
+                const char *msgbuf, size_t msgbuf_size, unsigned int priority,
+                struct GNUNET_TIME_Relative timeout, struct Session *session,
+                const void *addr, size_t addrlen, int force_address,
+                GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
 {
   int ret = 0;
   struct Plugin *plugin = cls;
 {
   int ret = 0;
   struct Plugin *plugin = cls;
-  const char *tempbuf;
-  int temp_size;
-#if DEBUG_DV
-  char *my_identity;
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "DV API: Received send request from transport, calling GNUNET_DV_send\n");
-  my_identity = GNUNET_strdup(GNUNET_i2s(plugin->env->my_identity));
-#endif
-  temp_size = htons(((struct GNUNET_MessageHeader *)msgbuf)->size);
-  if (msgbuf_size > temp_size)
-    {
-      tempbuf = &msgbuf[temp_size];
-#if DEBUG_DV
-      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s DV PLUGIN SEND SPECIAL type %d to %s\n", my_identity, ntohs(((struct GNUNET_MessageHeader *)tempbuf)->type), GNUNET_i2s(target));
-#endif
-    }
-#if DEBUG_DV
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s DV PLUGIN SEND type %d to %s\n", my_identity, ntohs(((struct GNUNET_MessageHeader *)msgbuf)->type), GNUNET_i2s(target));
-#endif
-  ret = GNUNET_DV_send(plugin->dv_handle,
-                       target,
-                       msgbuf,
-                       msgbuf_size,
-                       priority,
-                       timeout,
-                       addr,
-                       addrlen,
-                       cont,
-                       cont_cls);
-#if DEBUG_DV
-  GNUNET_free_non_null(my_identity);
-#endif
 
 
+  ret =
+      GNUNET_DV_send (plugin->dv_handle, target, msgbuf, msgbuf_size, priority,
+                      timeout, addr, addrlen, cont, cont_cls);
   return ret;
 }
 
   return ret;
 }
 
@@ -286,8 +235,7 @@ dv_plugin_send (void *cls,
  * @param target peer from which to disconnect
  */
 static void
  * @param target peer from which to disconnect
  */
 static void
-dv_plugin_disconnect (void *cls,
-                            const struct GNUNET_PeerIdentity *target)
+dv_plugin_disconnect (void *cls, 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
@@ -309,16 +257,37 @@ dv_plugin_disconnect (void *cls,
  * @param asc_cls closure for asc
  */
 static void
  * @param asc_cls closure for asc
  */
 static void
-dv_plugin_address_pretty_printer (void *cls,
-                                  const char *type,
-                                  const void *addr,
-                                  size_t addrlen,
-                                  int numeric,
+dv_plugin_address_pretty_printer (void *cls, const char *type, const void *addr,
+                                  size_t addrlen, int numeric,
                                   struct GNUNET_TIME_Relative timeout,
                                   struct GNUNET_TIME_Relative timeout,
-                                  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);
+  }
 }
 
 /**
 }
 
 /**
@@ -330,9 +299,8 @@ dv_plugin_address_pretty_printer (void *cls,
  *
  * @return string representing the DV address
  */
  *
  * @return string representing the DV address
  */
-static const char *address_to_string (void *cls,
-                                       const void *addr,
-                                       size_t addrlen)
+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'
 
 {
   static char return_buffer[2 * 4 + 2]; // Two four character peer identity prefixes a ':' and '\0'
 
@@ -340,23 +308,22 @@ static const char *address_to_string (void *cls,
   struct GNUNET_CRYPTO_HashAsciiEncoded via_hash;
   struct GNUNET_PeerIdentity *peer;
   struct GNUNET_PeerIdentity *via;
   struct GNUNET_CRYPTO_HashAsciiEncoded via_hash;
   struct GNUNET_PeerIdentity *peer;
   struct GNUNET_PeerIdentity *via;
-  char *addr_buf = (char *)addr;
+  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);
-    }
+  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;
 
   else
     return NULL;
 
@@ -364,28 +331,43 @@ static const char *address_to_string (void *cls,
 }
 
 /**
 }
 
 /**
- * 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; */
+  struct Plugin *plugin = cls;
 
 
-  /* check if the address is plausible; if so,
-     add it to our list! */
-  return GNUNET_NO;
+  /* 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;
 }
 
 
 }
 
 
@@ -401,14 +383,13 @@ libgnunet_plugin_transport_dv_init (void *cls)
 
   plugin = GNUNET_malloc (sizeof (struct Plugin));
   plugin->env = env;
 
   plugin = GNUNET_malloc (sizeof (struct Plugin));
   plugin->env = env;
-  //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)
   {
-    GNUNET_free(plugin);
+    GNUNET_free (plugin);
     return NULL;
   }
 
     return NULL;
   }
 
@@ -417,7 +398,7 @@ 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;
 }
   api->address_to_string = &address_to_string;
   return api;
 }
@@ -432,6 +413,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;