renaming libgnunetregexnew to libgnunetregex
[oweals/gnunet.git] / src / vpn / gnunet-service-vpn.c
index 1a46f0b5eb833c624b8dbb4263a4af73e7dc1864..bc2327e96a6441f6f70a4341c002ef5c46aafed5 100644 (file)
  *        IP traffic received on those IPs via the GNUnet mesh 
  * @author Philipp Toelke
  * @author Christian Grothoff
+ *
+ * TODO:
+ * - keep multiple peers/mesh tunnels ready as alternative exits /
+ *   recover from tunnel-to-exit failure gracefully
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -35,7 +39,7 @@
 #include "gnunet_statistics_service.h"
 #include "gnunet_constants.h"
 #include "gnunet_tun_lib.h"
-#include "gnunet_regex_lib.h"
+#include "gnunet_regex_service.h"
 #include "vpn.h"
 #include "exit.h"
 
@@ -171,6 +175,11 @@ struct TunnelState
    */
   struct GNUNET_MESH_Tunnel *tunnel;
 
+  /**
+   * Active query with REGEX to locate exit.
+   */
+  struct GNUNET_REGEX_Search *search;
+
   /**
    * Active transmission handle, NULL for none.
    */
@@ -520,11 +529,6 @@ free_tunnel_state (struct TunnelState *ts)
     GNUNET_free (tnq);
   }
   GNUNET_assert (0 == ts->tmq_length);
-  if (NULL != ts->client)
-  {
-    GNUNET_SERVER_client_drop (ts->client);
-    ts->client = NULL;
-  }
   if (NULL != ts->th)
   {
     GNUNET_MESH_notify_transmit_ready_cancel (ts->th);
@@ -536,6 +540,11 @@ free_tunnel_state (struct TunnelState *ts)
     ts->tunnel = NULL;
     GNUNET_MESH_tunnel_destroy (tunnel);
   }
+  if (NULL != ts->search)
+  {
+    GNUNET_REGEX_search_cancel (ts->search);
+    ts->search = NULL;
+  }
   if (GNUNET_SCHEDULER_NO_TASK != ts->destroy_task)
   {
     GNUNET_SCHEDULER_cancel (ts->destroy_task);
@@ -651,7 +660,6 @@ tunnel_peer_connect_handler (void *cls,
                     ts->request_id,
                     ts->af,
                     &ts->destination_ip);
-  GNUNET_SERVER_client_drop (ts->client);
   ts->client = NULL;
 }
 
@@ -750,6 +758,38 @@ send_to_tunnel (struct TunnelMessageQueueEntry *tnq,
 }
 
 
+/**
+ * Regex has found a potential exit peer for us; consider using it.
+ *
+ * @param cls the 'struct TunnelState'
+ * @param id Peer providing a regex that matches the string.
+ * @param get_path Path of the get request.
+ * @param get_path_length Lenght of get_path.
+ * @param put_path Path of the put request.
+ * @param put_path_length Length of the put_path.
+ */
+static void
+handle_regex_result (void *cls,
+                    const struct GNUNET_PeerIdentity *id,
+                    const struct GNUNET_PeerIdentity *get_path,
+                    unsigned int get_path_length,
+                    const struct GNUNET_PeerIdentity *put_path,
+                    unsigned int put_path_length)
+{
+  struct TunnelState *ts = cls;
+
+  GNUNET_REGEX_search_cancel (ts->search);
+  ts->search = NULL;
+  ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
+                                         ts,
+                                         &tunnel_peer_connect_handler,
+                                         &tunnel_peer_disconnect_handler,
+                                         ts);
+  GNUNET_MESH_peer_request_connect_add (ts->tunnel,
+                                       id);
+}
+
+
 /**
  * Initialize the given destination entry's mesh tunnel.
  *
@@ -777,28 +817,25 @@ create_tunnel_to_destination (struct DestinationEntry *de,
   {
     ts->request_id = request_id;
     ts->client = client;
-    GNUNET_SERVER_client_keep (client);
   }
   ts->destination = *de;
   ts->destination.heap_node = NULL; /* copy is NOT in destination heap */
   de->ts = ts;
   ts->destination_container = de; /* we are referenced from de */
-  ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
-                                         ts,
-                                         &tunnel_peer_connect_handler,
-                                         &tunnel_peer_disconnect_handler,
-                                         ts);
-  if (NULL == ts->tunnel)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Failed to setup mesh tunnel!\n"));
-    if (NULL != client)
-      GNUNET_SERVER_client_drop (client);
-    GNUNET_free (ts);
-    return NULL;
-  }
   if (de->is_service)
   {
+    ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle,
+                                           ts,
+                                           &tunnel_peer_connect_handler,
+                                           &tunnel_peer_disconnect_handler,
+                                           ts);
+    if (NULL == ts->tunnel)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Failed to setup mesh tunnel!\n"));
+      GNUNET_free (ts);
+      return NULL;
+    }
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                "Creating tunnel to peer %s offering service %s\n",
                GNUNET_i2s (&de->details.service_destination.target),
@@ -814,9 +851,10 @@ create_tunnel_to_destination (struct DestinationEntry *de,
     {
     case AF_INET:
     {
-      char address[GNUNET_REGEX_IPV4_REGEXLEN];
-      GNUNET_REGEX_ipv4toregex (&de->details.exit_destination.ip.v4,
-                                "255.255.255.255", address);
+      char address[GNUNET_TUN_IPV4_REGEXLEN];
+
+      GNUNET_TUN_ipv4toregex (&de->details.exit_destination.ip.v4,
+                  "255.255.255.255", address);
       GNUNET_asprintf (&policy, "%s%s%s",
                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
                        "4",
@@ -825,9 +863,10 @@ create_tunnel_to_destination (struct DestinationEntry *de,
     }
     case AF_INET6:
     {
-      char address[GNUNET_REGEX_IPV6_REGEXLEN];
-      GNUNET_REGEX_ipv6toregex (&de->details.exit_destination.ip.v6,
-                                128, address);
+      char address[GNUNET_TUN_IPV6_REGEXLEN];
+      
+      GNUNET_TUN_ipv6toregex (&de->details.exit_destination.ip.v6,
+                  128, address);
       GNUNET_asprintf (&policy, "%s%s%s",
                        GNUNET_APPLICATION_TYPE_EXIT_REGEX_PREFIX,
                        "6",
@@ -839,12 +878,13 @@ create_tunnel_to_destination (struct DestinationEntry *de,
       break;
     }
 
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting connect by string: %s\n", policy);
-
-    GNUNET_MESH_peer_request_connect_by_string (ts->tunnel, policy);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating tunnel to exit peer for policy `%s'\n",
-                policy);
+               "Requesting connect by string: %s\n",
+               policy);
+    ts->search = GNUNET_REGEX_search (cfg,
+                                     policy,
+                                     &handle_regex_result,
+                                     ts);
     GNUNET_free (policy);
   }
   return ts;
@@ -2928,8 +2968,8 @@ cleanup (void *cls GNUNET_UNUSED,
     mesh_handle = NULL;
   }
   if (NULL != helper_handle)
-    {
-    GNUNET_HELPER_stop (helper_handle);
+  {
+    GNUNET_HELPER_stop (helper_handle, GNUNET_NO);
     helper_handle = NULL;
   }
   if (NULL != nc)
@@ -2964,10 +3004,7 @@ cleanup_tunnel_client (void *cls,
   struct TunnelState *ts = value;
 
   if (client == ts->client)
-  {
-    GNUNET_SERVER_client_drop (ts->client);
     ts->client = NULL;
-  }
   return GNUNET_OK;
 }
 
@@ -2992,10 +3029,7 @@ cleanup_destination_client (void *cls,
   if (NULL == (ts = de->ts))
     return GNUNET_OK;
   if (client == ts->client)
-  {
-    GNUNET_SERVER_client_drop (ts->client);
     ts->client = NULL;
-  }
   return GNUNET_OK;
 }
 
@@ -3062,7 +3096,7 @@ run (void *cls,
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-vpn");
 
   if (GNUNET_YES !=
-      GNUNET_OS_check_helper_binary (binary))
+      GNUNET_OS_check_helper_binary (binary, GNUNET_YES, "-d gnunet-vpn - - 169.1.3.3.7 255.255.255.0")) //ipv4 only please!
   {
     fprintf (stderr,
             "`%s' is not SUID, refusing to run.\n",