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.57 2008-11-06 17:19:57 yangtse Exp $
22
22
***************************************************************************/
96
93
/* This function is used to init a threaded resolve */
97
94
static bool init_resolve_thread(struct connectdata *conn,
98
95
const char *hostname, int port,
99
const Curl_addrinfo *hints);
96
const struct addrinfo *hints);
101
98
#ifdef CURLRES_IPV4
102
99
#define THREAD_FUNC gethostbyname_thread
106
103
#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
106
struct thread_data {
153
107
HANDLE thread_hnd;
154
108
unsigned thread_id;
313
267
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
269
release_thread_sync(&tsd);
363
315
SetEvent(td->event_thread_started);
365
rc = getaddrinfo(tsd.hostname, service, &hints, &res);
317
rc = Curl_getaddrinfo_ex(tsd.hostname, service, &hints, &res);
367
319
/* is parent thread waiting for us and are we able to access conn members? */
368
320
if(acquire_thread_sync(&tsd)) {
371
323
SetEvent(td->event_resolved);
374
#ifdef DEBUG_THREADING_GETADDRINFO
375
dump_addrinfo (conn, res);
377
326
rc = Curl_addrinfo6_callback(conn, CURL_ASYNC_SUCCESS, res);
380
329
rc = Curl_addrinfo6_callback(conn, SOCKERRNO, NULL);
381
TRACE(("Winsock-error %d, no address\n", conn->async.status));
383
331
release_thread_sync(&tsd);
450
398
static bool init_resolve_thread (struct connectdata *conn,
451
399
const char *hostname, int port,
452
const Curl_addrinfo *hints)
400
const struct addrinfo *hints)
454
402
struct thread_data *td = calloc(sizeof(*td), 1);
455
403
HANDLE thread_and_event[2] = {0};
538
486
if(!td->thread_hnd) {
540
TRACE(("CreateThread() failed; %s\n", Curl_strerror(conn, ERRNO)));
542
488
SET_ERRNO(errno);
543
TRACE(("_beginthreadex() failed; %s\n", Curl_strerror(conn, ERRNO)));
545
490
Curl_destroy_thread_data(&conn->async);
591
536
conn->data->set.connecttimeout ? conn->data->set.connecttimeout :
592
537
conn->data->set.timeout ? conn->data->set.timeout :
593
538
CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */
594
ticks = GetTickCount();
596
540
/* wait for the thread to resolve the name */
597
541
status = WaitForSingleObject(td->event_resolved, timeout);
614
558
TerminateThread(td->thread_hnd, 0);
615
559
conn->async.done = TRUE;
616
560
td->thread_status = (DWORD)-1;
617
TRACE(("%s() thread stuck?!, ", THREAD_NAME));
620
563
/* Thread finished before timeout; propagate Winsock error to this
624
567
SET_SOCKERRNO(conn->async.status);
625
568
GetExitCodeThread(td->thread_hnd, &td->thread_status);
626
TRACE(("%s() status %lu, thread retval %lu, ",
627
THREAD_NAME, status, td->thread_status));
631
572
conn->async.done = TRUE;
632
573
td->thread_status = (DWORD)-1;
633
TRACE(("%s() timeout, ", THREAD_NAME));
636
TRACE(("elapsed %lu ms\n", GetTickCount()-ticks));
639
577
*entry = conn->async.dns;
691
629
Curl_destroy_thread_data(&conn->async);
692
630
if(!conn->async.dns) {
693
TRACE(("Curl_is_resolved(): CURLE_COULDNT_RESOLVE_HOST\n"));
694
631
failf(data, "Could not resolve host: %s; %s",
695
632
conn->host.name, Curl_strerror(conn, conn->async.status));
696
633
return CURLE_COULDNT_RESOLVE_HOST;
698
635
*entry = conn->async.dns;
699
TRACE(("resolved okay, dns %p\n", *entry));
731
667
struct hostent *h = NULL;
732
668
struct SessionHandle *data = conn->data;
735
671
*waitp = 0; /* don't wait, we act synchronously */
737
in = inet_addr(hostname);
738
if(in != CURL_INADDR_NONE)
673
if(Curl_inet_pton(AF_INET, hostname, &in) > 0)
739
674
/* This is a dotted IP address 123.123.123.123-style */
740
return Curl_ip2addr(in, hostname, port);
675
return Curl_ip2addr(AF_INET, &in, hostname, port);
742
677
/* fire up a new resolver thread! */
743
678
if(init_resolve_thread(conn, hostname, port, NULL)) {
771
struct addrinfo hints, *res;
706
struct addrinfo hints;
773
709
char sbuf[NI_MAXSERV];
776
711
struct SessionHandle *data = conn->data;
778
713
*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. */
716
* Check if a limited name resolve has been requested.
718
switch(data->set.ip_version) {
719
case CURL_IPRESOLVE_V4:
722
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:
731
/* see if we have an IPv6 stack */
732
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
733
if(s == CURL_SOCKET_BAD) {
734
/* Some non-IPv6 stacks have been found to make very slow name resolves
735
* when PF_UNSPEC is used, so thus we switch to a mere PF_INET lookup if
736
* the stack seems to be a non-ipv6 one. */
802
case CURL_IPRESOLVE_V6:
741
/* This seems to be an IPv6-capable stack, use PF_UNSPEC for the widest
742
* possible checks. And close the socket again.
826
763
infof(data, "init_resolve_thread() failed for %s; %s\n",
827
764
hostname, Curl_strerror(conn, ERRNO));
829
error = getaddrinfo(hostname, sbuf, &hints, &res);
766
error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
831
768
infof(data, "getaddrinfo() failed for %s:%d; %s\n",
832
769
hostname, port, Curl_strerror(conn, SOCKERRNO));