]> granicus.if.org Git - curl/commitdiff
ipv6: only probe once
authorDaniel Stenberg <daniel@haxx.se>
Wed, 23 Mar 2011 10:10:55 +0000 (11:10 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 23 Mar 2011 10:10:55 +0000 (11:10 +0100)
Move ipv6-functional-probe into a single function that is used from all
places that need to know.

Make the probe function store the result in a static variable so that
subsequent invokes just returns the previous result and won't have to
probe again.

lib/hostip.h
lib/hostip6.c
lib/hostthre.c

index 3f27a2b87614a4299ea0866335ece07c9271bcf2..c1f4486a6b5bd0bdfc992cc3292673c566b3791b 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -113,6 +113,15 @@ int Curl_resolv_timeout(struct connectdata *conn, const char *hostname,
                         int port, struct Curl_dns_entry **dnsentry,
                         long timeoutms);
 
+#ifdef CURLRES_IPV6
+/*
+ * Curl_ipv6works() returns TRUE if ipv6 seems to work.
+ */
+bool Curl_ipv6works(void);
+#else
+#define Curl_ipv6works() FALSE
+#endif
+
 /*
  * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
  * been set and returns TRUE if they are OK.
index ca0280790a5b814b5cd472a9bb0760ac9f25a210..5c05dc97cf7c797cbf6c723302d367f1e724999b 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -109,19 +109,36 @@ int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
 #endif /* defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) */
 
 /*
- * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
- * been set and returns TRUE if they are OK.
+ * Curl_ipv6works() returns TRUE if ipv6 seems to work.
  */
-bool Curl_ipvalid(struct connectdata *conn)
+bool Curl_ipv6works(void)
 {
-  if(conn->ip_version == CURL_IPRESOLVE_V6) {
-    /* see if we have an IPv6 stack */
+  /* the nature of most system is that IPv6 status doesn't come and go
+     during a program's lifetime so we only probe the first time and then we
+     have the info kept for fast re-use */
+  static int ipv6_works = -1;
+  if(-1 == ipv6_works) {
+    /* probe to see if we have a working IPv6 stack */
     curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
     if(s == CURL_SOCKET_BAD)
-      /* an ipv6 address was requested and we can't get/use one */
-      return FALSE;
-    sclose(s);
+      /* an ipv6 address was requested but we can't get/use one */
+      ipv6_works = 0;
+    else {
+      ipv6_works = 1;
+      sclose(s);
+    }
   }
+  return (ipv6_works>0)?TRUE:FALSE;
+}
+
+/*
+ * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've
+ * been set and returns TRUE if they are OK.
+ */
+bool Curl_ipvalid(struct connectdata *conn)
+{
+  if(conn->ip_version == CURL_IPRESOLVE_V6)
+    return Curl_ipv6works();
   return TRUE;
 }
 
@@ -186,23 +203,9 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
     break;
   }
 
-  if (pf != PF_INET) {
-    /* see if we have an IPv6 stack */
-    curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
-    if(s == CURL_SOCKET_BAD) {
-      /* Some non-IPv6 stacks have been found to make very slow name resolves
-       * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
-       * the stack seems to be a non-ipv6 one. */
-
-      pf = PF_INET;
-    }
-    else {
-      /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
-       * possible checks. And close the socket again.
-       */
-      sclose(s);
-    }
-  }
+  if((pf != PF_INET) && !Curl_ipv6works())
+    /* the stack seems to be a non-ipv6 one */
+    pf = PF_INET;
 
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = pf;
index d45a8993cb3a1845501f707ff067a57001f76d5a..dc8e4af74325e5c4f80806fbfa1c3c1f2a8a8276 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -530,23 +530,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
     break;
   }
 
-  if (pf != PF_INET) {
-    /* see if we have an IPv6 stack */
-    curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
-    if(s == CURL_SOCKET_BAD) {
-      /* Some non-IPv6 stacks have been found to make very slow name resolves
-       * when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
-       * the stack seems to be a non-ipv6 one. */
+  if((pf != PF_INET) && !Curl_ipv6works())
+    /* the stack seems to be a non-ipv6 one */
+    pf = PF_INET;
 
-      pf = PF_INET;
-    }
-    else {
-      /* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
-       * possible checks. And close the socket again.
-       */
-      sclose(s);
-    }
-  }
 #endif /* !CURLRES_IPV4 */
 
   memset(&hints, 0, sizeof(hints));