added reolver
authort3sserakt <t3ss@posteo.de>
Thu, 23 Apr 2020 13:03:41 +0000 (15:03 +0200)
committert3sserakt <t3ss@posteo.de>
Thu, 23 Apr 2020 13:03:41 +0000 (15:03 +0200)
src/transport/Makefile.am
src/transport/gnunet-communicator-tcp.c

index 3028b29b4d0666823579cbc9d733dc0ac46bc5c7..15f3f564725c718611a430e607e0ddf2c866ee53 100644 (file)
@@ -673,13 +673,13 @@ TESTS += \
   test_transport_api_timeout_udp \
   test_transport_api_udp_nat \
   test_transport_api_reliability_udp \
-test_quota_compliance_udp \
-test_communicator_basic-unix \
-test_communicator_basic-tcp \
-test_communicator_basic-udp \
-test_communicator_rekey-tcp \
-test_communicator_rekey-udp \
-test_communicator_backchannel-udp
+  test_quota_compliance_udp \
+  test_communicator_basic-unix \
+  test_communicator_basic-tcp \
+  test_communicator_basic-udp \
+  test_communicator_rekey-tcp \
+  test_communicator_rekey-udp \
+  test_communicator_backchannel-udp
 endif
 endif
 
index 045a57d0feca4b2b0382e44b2f3e112094c5c154..b9d023e54bb363c911588c7c9d07c790c7b1a9c6 100644 (file)
@@ -40,6 +40,8 @@
 #include "gnunet_nt_lib.h"
 #include "gnunet_nat_service.h"
 #include "gnunet_statistics_service.h"
+#include "gnunet_ats_transport_service.h"
+#include "transport.h"
 #include "gnunet_transport_communication_service.h"
 
 /**
@@ -485,7 +487,6 @@ struct ProtoQueue
   size_t ibuf_off;
 };
 
-
 /**
  * ID of listen task
  */
@@ -556,6 +557,11 @@ static struct ProtoQueue *proto_head;
  */
 static struct ProtoQueue *proto_tail;
 
+/**
+ * Handle for DNS lookup of bindto address
+ */
+struct GNUNET_RESOLVER_RequestHandle *resolve_request_handle;
+
 
 /**
  * We have been notified that our listen socket has something to
@@ -1096,26 +1102,13 @@ queue_read (void *cls)
   queue_finish (queue);
 }
 
-
-/**
- * Convert TCP bind specification to a `struct sockaddr *`
- *
- * @param bindto bind specification to convert
- * @param[out] sock_len set to the length of the address
- * @return converted bindto specification
- */
 static struct sockaddr *
-tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
+tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int port, socklen_t *sock_len)
 {
+
   struct sockaddr *in;
-  unsigned int port;
-  char dummy[2];
-  char *colon;
-  char *cp;
 
-  if (1 == sscanf (bindto, "%u%1s", &port, dummy))
-  {
-    /* interpreting value as just a PORT number */
+  /* interpreting value as just a PORT number */
     if (port > UINT16_MAX)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1154,46 +1147,80 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
       in = (struct sockaddr *) i6;
     }
     return in;
+}
+
+static char *
+extract_ipv6_address (char *cp)
+{
+
+  const char *start;
+
+  start = cp;
+  if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
+  {
+    start++;   /* skip over '[' */
+    cp[strlen (cp) - 1] = '\0';  /* eat ']' */
   }
-  cp = GNUNET_strdup (bindto);
-  colon = strrchr (cp, ':');
+
+  return start;
+}
+
+static unsigned int
+extract_port(char *colon)
+{
+  unsigned int port;
+  char dummy[2];
   if (NULL != colon)
-  {
-    /* interpet value after colon as port */
-    *colon = '\0';
-    colon++;
-    if (1 == sscanf (colon, "%u%1s", &port, dummy))
     {
-      /* interpreting value as just a PORT number */
-      if (port > UINT16_MAX)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    "BINDTO specification `%s' invalid: value too large for port\n",
-                    bindto);
-        GNUNET_free (cp);
-        return NULL;
-      }
+      /* interpet value after colon as port */
+      *colon = '\0';
+      colon++;
+      if (1 == sscanf (colon, "%u%1s", &port, dummy))
+        {
+          /* interpreting value as just a PORT number */
+          if (port > UINT16_MAX)
+            {
+              GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                          "Port `%s' invalid: value too large for port\n",
+                          port);
+              //GNUNET_free (cp);
+              return NULL;
+            }
+        }
+      else
+        {
+          GNUNET_log (
+                      GNUNET_ERROR_TYPE_ERROR,
+                      "BINDTO specification invalid: last ':' not followed by number\n");
+          //GNUNET_free (cp);
+          return NULL;
+        }
     }
-    else
+  else
     {
-      GNUNET_log (
-        GNUNET_ERROR_TYPE_ERROR,
-        "BINDTO specification `%s' invalid: last ':' not followed by number\n",
-        bindto);
-      GNUNET_free (cp);
-      return NULL;
+      /* interpret missing port as 0, aka pick any free one */
+      port = 0;
     }
-  }
-  else
-  {
-    /* interpret missing port as 0, aka pick any free one */
-    port = 0;
-  }
+
+  return port;
+}
+
+static struct sockaddr *
+tcp_address_to_sockaddr_numeric (socklen_t *sock_len, struct sockaddr_in v4, struct sockaddr_in6 v6, char *colon)
+{
+
+  unsigned int port;
+  struct sockaddr *in;
+
+  port = extract_port(colon);
+
+  if (NULL == port)
+    return NULL;
+
   {
     /* try IPv4 */
-    struct sockaddr_in v4;
 
-    if (1 == inet_pton (AF_INET, cp, &v4.sin_addr))
+    if (NULL != &v4.sin_addr)
     {
       v4.sin_family = AF_INET;
       v4.sin_port = htons ((uint16_t) port);
@@ -1202,22 +1229,14 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
 #endif
       in = GNUNET_memdup (&v4, sizeof(v4));
       *sock_len = sizeof(v4);
-      GNUNET_free (cp);
+      //GNUNET_free (cp);
       return in;
     }
   }
   {
     /* try IPv6 */
-    struct sockaddr_in6 v6;
-    const char *start;
 
-    start = cp;
-    if (('[' == *cp) && (']' == cp[strlen (cp) - 1]))
-    {
-      start++;   /* skip over '[' */
-      cp[strlen (cp) - 1] = '\0';  /* eat ']' */
-    }
-    if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
+    if (NULL != &v6.sin6_addr)
     {
       v6.sin6_family = AF_INET6;
       v6.sin6_port = htons ((uint16_t) port);
@@ -1226,15 +1245,48 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
 #endif
       in = GNUNET_memdup (&v6, sizeof(v6));
       *sock_len = sizeof(v6);
-      GNUNET_free (cp);
+      //GNUNET_free (cp);
       return in;
     }
   }
-  /* #5528 FIXME (feature!): maybe also try getnameinfo()? */
-  GNUNET_free (cp);
+  //GNUNET_free (cp);
   return NULL;
 }
 
+/**
+ * Convert TCP bind specification to a `struct sockaddr *`
+ *
+ * @param bindto bind specification to convert
+ * @param[out] sock_len set to the length of the address
+ * @return converted bindto specification
+ */
+static struct sockaddr *
+tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len)
+{
+  struct sockaddr *in;
+  unsigned int port;
+  char dummy[2];
+  char *colon;
+  char *cp;
+  struct sockaddr_in v4;
+  struct sockaddr_in6 v6;
+  const char *start;
+  socklen_t in_len;
+
+  cp = GNUNET_strdup (bindto);
+  start = extract_ipv6_address (cp);
+
+  if (1 == sscanf (bindto, "%u%1s", &port, dummy))
+  {
+    in = tcp_address_to_sockaddr_port_only (bindto, port, sock_len);
+  }
+  else if (1 == inet_pton (AF_INET, cp, &v4.sin_addr) || 1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
+  {
+    colon = strrchr (cp, ':');
+    in = tcp_address_to_sockaddr_numeric (&in_len, v4, v6, colon);
+  }
+}
+
 
 /**
  * Setup cipher for outgoing data stream based on target and
@@ -1885,7 +1937,6 @@ queue_read_kx (void *cls)
     queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue);
 }
 
-
 /**
  * Function called by the transport service to initialize a
  * message queue given address information about another peer.
@@ -1905,24 +1956,27 @@ queue_read_kx (void *cls)
  * invalid
  */
 static int
-mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
+mq_init (void *cls, const struct GNUNET_PeerIdentity *peer,
+         struct GNUNET_TRANSPORT_CommunicatorHandle *ch,
+         const struct GNUNET_TRANSPORT_CreateQueue *cq)
 {
   struct Queue *queue;
   const char *path;
   struct sockaddr *in;
   socklen_t in_len;
   struct GNUNET_NETWORK_Handle *sock;
+  const char *addr = (const char *) &cq[1];
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting to %s\n", address);
-  if (0 != strncmp (address,
+              "Connecting to %s\n", addr);
+  if (0 != strncmp (addr,
                     COMMUNICATOR_ADDRESS_PREFIX "-",
                     strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
   {
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
+  path = &addr[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
   in = tcp_address_to_sockaddr (path, &in_len);
 
   sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP);
@@ -1940,7 +1994,7 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "connect to `%s' failed: %s",
-                address,
+                addr,
                 strerror (errno));
     GNUNET_NETWORK_socket_close (sock);
     GNUNET_free (in);
@@ -1968,7 +2022,6 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address)
   return GNUNET_OK;
 }
 
-
 /**
  * Iterator over all message queues to clean up.
  *
@@ -2113,78 +2166,74 @@ nat_address_cb (void *cls,
   }
 }
 
-
-/**
- * Setup communicator and launch network interactions.
- *
- * @param cls NULL (always)
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param c configuration
- */
 static void
-run (void *cls,
-     char *const *args,
-     const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *c)
+init_own_socket (void *cls, struct sockaddr *resolved_in, socklen_t in_len)
 {
-  char *bindto;
+
   struct sockaddr *in;
-  socklen_t in_len;
   struct sockaddr_storage in_sto;
   socklen_t sto_len;
+  struct sockaddr_in *v4;
+  struct sockaddr_in6 *v6;
+  char ipstr[INET6_ADDRSTRLEN];
 
-  (void) cls;
-  cfg = c;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             COMMUNICATOR_CONFIG_SECTION,
-                                             "BINDTO",
-                                             &bindto))
-  {
-    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                               COMMUNICATOR_CONFIG_SECTION,
-                               "BINDTO");
-    return;
-  }
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg,
-                                             COMMUNICATOR_CONFIG_SECTION,
-                                             "MAX_QUEUE_LENGTH",
-                                             &max_queue_length))
-    max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg,
-                                             COMMUNICATOR_CONFIG_SECTION,
-                                             "REKEY_INTERVAL",
-                                             &rekey_interval))
-    rekey_interval = DEFAULT_REKEY_INTERVAL;
-
-  in = tcp_address_to_sockaddr (bindto, &in_len);
-  if (NULL == in)
+  unsigned int port = cls;
+  if (NULL == resolved_in)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to setup TCP socket address with path `%s'\n",
-                bindto);
-    GNUNET_free (bindto);
+                "Failed to setup TCP socket address\n");
+    //TODO Where do we cancel the request
+    //GNUNET_RESOLVER_request_cancel (resolve_request_handle);
+    //TODO check where to free after moving code around
+    //GNUNET_free (bindto);
     return;
   }
+
+  inet_ntop(resolved_in->sa_family, resolved_in, ipstr, sizeof(ipstr));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "resolved address %s\n",
+              ipstr);
+
   listen_sock =
-    GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP);
+    GNUNET_NETWORK_socket_create (resolved_in->sa_family, SOCK_STREAM, IPPROTO_TCP);
   if (NULL == listen_sock)
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
+    //GNUNET_RESOLVER_request_cancel (resolve_request_handle);
     GNUNET_free (in);
-    GNUNET_free (bindto);
+    //GNUNET_free (bindto);
     return;
   }
+
+  if (AF_INET == resolved_in->sa_family)
+  {
+    v4 = GNUNET_new (struct sockaddr_in);
+    v4->sin_family = AF_INET;
+    v4->sin_port = htons ((uint16_t) port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    v4->sin_len = sizeof(struct sockaddr_in);
+#endif
+    in = GNUNET_memdup (v4, sizeof(v4));
+  }else if (AF_INET6 == in->sa_family)
+  {
+    v6 = GNUNET_new (struct sockaddr_in6);
+    v6->sin6_family = AF_INET6;
+    v6->sin6_port = htons ((uint16_t) port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    v6->sin6_len = sizeof(sizeof(struct sockaddr_in6));
+#endif
+    in = GNUNET_memdup (v6, sizeof(v6));
+  }
+
   if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, in, in_len))
   {
-    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto);
+    //GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto);
+    //GNUNET_RESOLVER_request_cancel (resolve_request_handle);
     GNUNET_NETWORK_socket_close (listen_sock);
     listen_sock = NULL;
     GNUNET_free (in);
-    GNUNET_free (bindto);
+    //GNUNET_free (bindto);
     return;
   }
   if (GNUNET_OK !=
@@ -2196,7 +2245,7 @@ run (void *cls,
     GNUNET_NETWORK_socket_close (listen_sock);
     listen_sock = NULL;
     GNUNET_free (in);
-    GNUNET_free (bindto);
+    //GNUNET_free (bindto);
   }
   /* We might have bound to port 0, allowing the OS to figure it out;
      thus, get the real IN-address from the socket */
@@ -2209,7 +2258,7 @@ run (void *cls,
     sto_len = in_len;
   }
   GNUNET_free (in);
-  GNUNET_free (bindto);
+  //GNUNET_free (bindto);
   in = (struct sockaddr *) &in_sto;
   in_len = sto_len;
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2225,6 +2274,7 @@ run (void *cls,
       GNUNET_ERROR_TYPE_ERROR,
       _ (
         "Transport service is lacking key configuration settings. Exiting.\n"));
+    GNUNET_RESOLVER_request_cancel (resolve_request_handle);
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
@@ -2246,6 +2296,7 @@ run (void *cls,
   if (NULL == ch)
   {
     GNUNET_break (0);
+    GNUNET_RESOLVER_request_cancel (resolve_request_handle);
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
@@ -2258,6 +2309,94 @@ run (void *cls,
                              &nat_address_cb,
                              NULL /* FIXME: support reversal: #5529 */,
                              NULL /* closure */);
+
+}
+
+/**
+ * Setup communicator and launch network interactions.
+ *
+ * @param cls NULL (always)
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+     char *const *args,
+     const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+  char *bindto;
+  struct sockaddr *in;
+  socklen_t in_len;
+  struct sockaddr_in v4;
+  struct sockaddr_in6 v6;
+  char *cp;
+  char *colon;
+  char *start;
+  unsigned int port;
+  char dummy[2];
+
+
+  (void) cls;
+  cfg = c;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             COMMUNICATOR_CONFIG_SECTION,
+                                             "BINDTO",
+                                             &bindto))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               COMMUNICATOR_CONFIG_SECTION,
+                               "BINDTO");
+    return;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg,
+                                             COMMUNICATOR_CONFIG_SECTION,
+                                             "MAX_QUEUE_LENGTH",
+                                             &max_queue_length))
+    max_queue_length = DEFAULT_MAX_QUEUE_LENGTH;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg,
+                                             COMMUNICATOR_CONFIG_SECTION,
+                                             "REKEY_INTERVAL",
+                                             &rekey_interval))
+    rekey_interval = DEFAULT_REKEY_INTERVAL;
+
+  cp = GNUNET_strdup (bindto);
+  start = extract_ipv6_address (cp);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "We try with path `%s'\n",
+              bindto);
+
+  if (1 == sscanf (bindto, "%u%1s", &port, dummy))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "We think it is port only\n");
+    in = tcp_address_to_sockaddr_port_only (bindto, port, &in_len);
+    init_own_socket (bindto, &in, &in_len);
+  }
+  else if (1 == inet_pton (AF_INET, cp, &v4.sin_addr) || 1 == inet_pton (AF_INET6, start, &v6.sin6_addr))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "We think it is address and port\n");
+    colon = strrchr (cp, ':');
+    in = tcp_address_to_sockaddr_numeric (&in_len, v4, v6, &colon);
+    init_own_socket (bindto, &in, &in_len);
+  }else
+  {
+    colon = strrchr (cp, ':');
+    port = extract_port(colon);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "We try to resolve\n");
+    resolve_request_handle = GNUNET_RESOLVER_ip_get (cp,
+                                                    AF_UNSPEC,
+                                                    GNUNET_TIME_UNIT_MINUTES,
+                                                    &init_own_socket,
+                                                    port);
+  }
 }