5
5
* | (__| |_| | _ <| |___
6
6
* \___|\___/|_| \_\_____|
8
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
8
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
10
10
* This software is licensed as described in the file COPYING, which
11
11
* you should have received as part of this distribution. The terms
18
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
* KIND, either express or implied.
21
* $Id: hostthre.c,v 1.51 2008-02-10 04:20:10 yangtse Exp $
21
* $Id: hostthre.c,v 1.59 2009-04-21 11:46:16 yangtse Exp $
22
22
***************************************************************************/
96
90
/* This function is used to init a threaded resolve */
97
91
static bool init_resolve_thread(struct connectdata *conn,
98
92
const char *hostname, int port,
99
const Curl_addrinfo *hints);
93
const struct addrinfo *hints);
101
95
#ifdef CURLRES_IPV4
102
96
#define THREAD_FUNC gethostbyname_thread
106
100
#define THREAD_NAME "getaddrinfo_thread"
109
#if defined(DEBUG_THREADING_GETHOSTBYNAME) || \
110
defined(DEBUG_THREADING_GETADDRINFO)
111
/* If this is defined, provide tracing */
112
#define TRACE(args) \
113
do { trace_it("%u: ", __LINE__); trace_it args; } while(0)
115
static void trace_it (const char *fmt, ...)
117
static int do_trace = -1;
121
const char *env = getenv("CURL_TRACE");
122
do_trace = (env && atoi(env) > 0);
126
va_start (args, fmt);
127
vfprintf (stderr, fmt, args);
135
#ifdef DEBUG_THREADING_GETADDRINFO
136
static void dump_addrinfo (struct connectdata *conn, const struct addrinfo *ai)
138
TRACE(("dump_addrinfo:\n"));
139
for ( ; ai; ai = ai->ai_next) {
140
char buf [INET6_ADDRSTRLEN];
142
trace_it(" fam %2d, CNAME %s, ",
143
ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
144
if(Curl_printable_address(ai, buf, sizeof(buf)))
145
trace_it("%s\n", buf);
147
trace_it("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
152
103
struct thread_data {
153
104
HANDLE thread_hnd;
154
105
unsigned thread_id;
313
264
rc = Curl_addrinfo4_callback(conn, SOCKERRNO, NULL);
315
TRACE(("Winsock-error %d, addr %s\n", conn->async.status,
316
he ? inet_ntoa(*(struct in_addr*)he->h_addr) : "unknown"));
317
266
release_thread_sync(&tsd);
363
312
SetEvent(td->event_thread_started);
365
rc = getaddrinfo(tsd.hostname, service, &hints, &res);
314
rc = Curl_getaddrinfo_ex(tsd.hostname, service, &hints, &res);
367
316
/* is parent thread waiting for us and are we able to access conn members? */
368
317
if(acquire_thread_sync(&tsd)) {
371
320
SetEvent(td->event_resolved);
374
#ifdef DEBUG_THREADING_GETADDRINFO
375
dump_addrinfo (conn, res);
377
323
rc = Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
380
326
rc = Curl_addrinfo6_callback(conn, SOCKERRNO, NULL);
381
TRACE(("Winsock-error %d, no address\n", conn->async.status));
383
328
release_thread_sync(&tsd);
450
395
static bool init_resolve_thread (struct connectdata *conn,
451
396
const char *hostname, int port,
452
const Curl_addrinfo *hints)
397
const struct addrinfo *hints)
454
399
struct thread_data *td = calloc(sizeof(*td), 1);
455
400
HANDLE thread_and_event[2] = {0};
538
483
if(!td->thread_hnd) {
540
TRACE(("CreateThread() failed; %s\n", Curl_strerror(conn, ERRNO)));
542
485
SET_ERRNO(errno);
543
TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn, ERRNO)));
545
487
Curl_destroy_thread_data(&conn->async);
591
533
conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
592
534
conn->data->set.timeout ? conn->data->set.timeout :
593
535
CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
594
ticks = GetTickCount();
596
537
/* wait for the thread to resolve the name */
597
538
status = WaitForSingleObject(td->event_resolved, timeout);
614
555
TerminateThread(td->thread_hnd, 0);
615
556
conn->async.done = TRUE;
616
557
td->thread_status = (DWORD)-1;
617
TRACE(("%s() thread stuck?!, ", THREAD_NAME));
620
560
/* Thread finished before timeout; propagate Winsock error to this
624
564
SET_SOCKERRNO(conn->async.status);
625
565
GetExitCodeThread(td->thread_hnd, &td->thread_status);
626
TRACE(("%s() status %lu, thread retval %lu, ",
627
THREAD_NAME, status, td->thread_status));
631
569
conn->async.done = TRUE;
632
570
td->thread_status = (DWORD)-1;
633
TRACE(("%s() timeout, ", THREAD_NAME));
636
TRACE(("elapsed %lu ms\n", GetTickCount()-ticks));
639
574
*entry = conn->async.dns;
691
626
Curl_destroy_thread_data(&conn->async);
692
627
if(!conn->async.dns) {
693
TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n"));
694
628
failf(data, "Could not resolve host: %s; %s",
695
629
conn->host.name, Curl_strerror(conn, conn->async.status));
696
630
return CURLE_COULDNT_RESOLVE_HOST;
698
632
*entry = conn->async.dns;
699
TRACE(("resolved okay, dns %p\n", *entry));
731
664
struct hostent *h = NULL;
732
665
struct SessionHandle *data = conn->data;
735
668
*waitp = 0; /* don't wait, we act synchronously */
737
in = inet_addr(hostname);
738
if(in != CURL_INADDR_NONE)
670
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
739
671
/* This is a dotted IP address 123.123.123.123-style */
740
return Curl_ip2addr(in, hostname, port);
672
return Curl_ip2addr(AF_INET, &in, hostname, port);
742
674
/* fire up a new resolver thread! */
743
675
if(init_resolve_thread(conn, hostname, port, NULL)) {
771
struct addrinfo hints, *res;
703
struct addrinfo hints;
773
706
char sbuf[NI_MAXSERV];
776
708
struct SessionHandle *data = conn->data;
778
710
*waitp = FALSE; /* default to synch response */
780
/* see if we have an IPv6 stack */
781
s = socket(PF_INET6, SOCK_DGRAM, 0);
782
if(s == CURL_SOCKET_BAD) {
783
/* Some non-IPv6 stacks have been found to make very slow name resolves
784
* when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
785
* the stack seems to be a non-ipv6 one. */
713
* Check if a limited name resolve has been requested.
715
switch(data->set.ip_version) {
716
case CURL_IPRESOLVE_V4:
719
case CURL_IPRESOLVE_V6:
790
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
791
* possible checks. And close the socket again.
796
* Check if a more limited name resolve has been requested.
798
switch(data->set.ip_version) {
799
case CURL_IPRESOLVE_V4:
728
/* see if we have an IPv6 stack */
729
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
730
if(s == CURL_SOCKET_BAD) {
731
/* Some non-IPv6 stacks have been found to make very slow name resolves
732
* when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
733
* the stack seems to be a non-ipv6 one. */
802
case CURL_IPRESOLVE_V6:
738
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
739
* possible checks. And close the socket again.
826
760
infof(data, "init_resolve_thread() failed for %s; %s\n",
827
761
hostname, Curl_strerror(conn, ERRNO));
829
error = getaddrinfo(hostname, sbuf, &hints, &res);
763
error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
831
765
infof(data, "getaddrinfo() failed for %s:%d; %s\n",
832
766
hostname, port, Curl_strerror(conn, SOCKERRNO));