28 #ifdef CURLRES_THREADED 30 #ifdef HAVE_NETINET_IN_H 31 #include <netinet/in.h> 36 #ifdef HAVE_ARPA_INET_H 37 #include <arpa/inet.h> 44 #if defined(USE_THREADS_POSIX) 45 # ifdef HAVE_PTHREAD_H 48 #elif defined(USE_THREADS_WIN32) 49 # ifdef HAVE_PROCESS_H 54 #if (defined(NETWARE) && defined(__NOVELL_LIBC__)) 56 #define in_addr_t unsigned long 59 #ifdef HAVE_GETADDRINFO 60 # define RESOLVER_ENOMEM EAI_MEMORY 62 # define RESOLVER_ENOMEM ENOMEM 137 static void destroy_async_data(
struct Curl_async *);
144 destroy_async_data(&conn->async);
148 static bool init_resolve_thread(
struct connectdata *conn,
150 const struct addrinfo *hints);
154 struct thread_sync_data {
163 #ifdef HAVE_GETADDRINFO 164 struct addrinfo hints;
166 struct thread_data *td;
170 curl_thread_t thread_hnd;
171 unsigned int poll_interval;
173 struct thread_sync_data tsd;
176 static struct thread_sync_data *conn_thread_sync_data(
struct connectdata *conn)
178 return &(((
struct thread_data *)conn->async.os_specific)->tsd);
181 #define CONN_THREAD_SYNC_DATA(conn) &(((conn)->async.os_specific)->tsd); 185 void destroy_thread_sync_data(
struct thread_sync_data * tsd)
188 Curl_mutex_destroy(tsd->mtx);
197 memset(tsd, 0,
sizeof(*tsd));
202 int init_thread_sync_data(
struct thread_data * td,
205 const struct addrinfo *hints)
207 struct thread_sync_data *tsd = &td->tsd;
209 memset(tsd, 0,
sizeof(*tsd));
217 #ifdef HAVE_GETADDRINFO 224 tsd->mtx =
malloc(
sizeof(curl_mutex_t));
228 Curl_mutex_init(tsd->mtx);
235 tsd->hostname =
strdup(hostname);
243 destroy_thread_sync_data(tsd);
247 static int getaddrinfo_complete(
struct connectdata *conn)
249 struct thread_sync_data *tsd = conn_thread_sync_data(conn);
262 #ifdef HAVE_GETADDRINFO 270 static unsigned int CURL_STDCALL getaddrinfo_thread(
void *arg)
272 struct thread_sync_data *tsd = (
struct thread_sync_data*)arg;
273 struct thread_data *td = tsd->td;
277 snprintf(service,
sizeof(service),
"%d", tsd->port);
279 rc = Curl_getaddrinfo_ex(tsd->hostname, service, &tsd->hints, &tsd->res);
283 if(tsd->sock_error == 0)
284 tsd->sock_error = RESOLVER_ENOMEM;
287 Curl_addrinfo_set_port(tsd->res, tsd->port);
290 Curl_mutex_acquire(tsd->mtx);
293 Curl_mutex_release(tsd->mtx);
294 destroy_thread_sync_data(tsd);
299 Curl_mutex_release(tsd->mtx);
310 static unsigned int CURL_STDCALL gethostbyname_thread(
void *arg)
312 struct thread_sync_data *tsd = (
struct thread_sync_data *)arg;
313 struct thread_data *td = tsd->td;
319 if(tsd->sock_error == 0)
320 tsd->sock_error = RESOLVER_ENOMEM;
323 Curl_mutex_acquire(tsd->mtx);
326 Curl_mutex_release(tsd->mtx);
327 destroy_thread_sync_data(tsd);
332 Curl_mutex_release(tsd->mtx);
343 static void destroy_async_data(
struct Curl_async *async)
345 if(async->os_specific) {
346 struct thread_data *td = (
struct thread_data*) async->os_specific;
353 Curl_mutex_acquire(td->tsd.mtx);
356 Curl_mutex_release(td->tsd.mtx);
359 Curl_thread_destroy(td->thread_hnd);
362 if(td->thread_hnd != curl_thread_t_null)
363 Curl_thread_join(&td->thread_hnd);
365 destroy_thread_sync_data(&td->tsd);
367 free(async->os_specific);
370 async->os_specific = NULL;
372 free(async->hostname);
373 async->hostname = NULL;
382 static bool init_resolve_thread(
struct connectdata *conn,
383 const char *hostname,
int port,
384 const struct addrinfo *hints)
386 struct thread_data *td =
calloc(1,
sizeof(
struct thread_data));
389 conn->async.os_specific = (
void *)td;
394 conn->async.done =
FALSE;
395 conn->async.status = 0;
396 conn->async.dns = NULL;
397 td->thread_hnd = curl_thread_t_null;
399 if(!init_thread_sync_data(td, hostname, port, hints)) {
400 conn->async.os_specific = NULL;
405 free(conn->async.hostname);
406 conn->async.hostname =
strdup(hostname);
407 if(!conn->async.hostname)
413 #ifdef HAVE_GETADDRINFO 414 td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd);
416 td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd);
419 if(!td->thread_hnd) {
429 destroy_async_data(&conn->async);
443 const char *host_or_proxy;
447 host_or_proxy =
"proxy";
451 host_or_proxy =
"host";
455 failf(conn->
data,
"Could not resolve %s: %s", host_or_proxy,
456 conn->async.hostname);
474 struct thread_data *td = (
struct thread_data*) conn->async.os_specific;
480 if(Curl_thread_join(&td->thread_hnd))
481 result = getaddrinfo_complete(conn);
485 conn->async.done =
TRUE;
488 *entry = conn->async.dns;
492 result = resolver_error(conn);
494 destroy_async_data(&conn->async);
497 connclose(conn,
"asynch resolve failed");
511 struct thread_data *td = (
struct thread_data*) conn->async.os_specific;
521 Curl_mutex_acquire(td->tsd.mtx);
523 Curl_mutex_release(td->tsd.mtx);
526 getaddrinfo_complete(conn);
528 if(!conn->async.dns) {
529 CURLcode result = resolver_error(conn);
530 destroy_async_data(&conn->async);
533 destroy_async_data(&conn->async);
534 *entry = conn->async.dns;
542 if(td->poll_interval == 0)
544 td->poll_interval = 1;
545 else if(elapsed >= td->interval_end)
547 td->poll_interval *= 2;
549 if(td->poll_interval > 250)
550 td->poll_interval = 250;
552 td->interval_end = elapsed + td->poll_interval;
569 #ifndef HAVE_GETADDRINFO 574 const char *hostname,
587 if(init_resolve_thread(conn, hostname, port, NULL)) {
602 const char *hostname,
606 struct addrinfo hints;
614 #ifndef USE_RESOLVE_ON_IPS 654 memset(&hints, 0,
sizeof(hints));
655 hints.ai_family = pf;
658 snprintf(sbuf,
sizeof(sbuf),
"%d", port);
661 if(init_resolve_thread(conn, hostname, port, &hints)) {
667 infof(conn->
data,
"init_resolve_thread() failed for %s; %s\n",
670 error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
672 infof(conn->
data,
"getaddrinfo() failed for %s:%d; %s\n",
677 Curl_addrinfo_set_port(res, port);
703 const char *local_ip4)
711 const char *local_ip6)
#define CURL_IPRESOLVE_V6
CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, const char *local_ip4)
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock, int numsocks)
Curl_addrinfo * Curl_ipv4_resolve_r(const char *hostname, int port)
#define CURL_IPRESOLVE_V4
CURLcode Curl_resolver_init(void **resolver)
Curl_addrinfo * Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port)
void Curl_freeaddrinfo(Curl_addrinfo *cahead)
UNITTEST_START int result
void Curl_resolver_cancel(struct connectdata *conn)
static srvr_sockaddr_union_t from
#define CURL_ASYNC_SUCCESS
Curl_addrinfo * Curl_resolver_getaddrinfo(struct connectdata *conn, const char *hostname, int port, int *waitp)
CURLcode Curl_addrinfo_callback(struct connectdata *conn, int status, Curl_addrinfo *ai)
CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, const char *local_ip6)
const char * Curl_strerror(struct connectdata *conn, int err)
CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers)
void Curl_resolver_cleanup(void *resolver)
#define Curl_resolver_global_init()
int Curl_inet_pton(int af, const char *src, void *dst)
static unsigned short port
struct curltime t_startsingle
CURLcode Curl_resolver_is_resolved(struct connectdata *conn, struct Curl_dns_entry **dns)
#define Curl_tvdiff(x, y)
int Curl_resolver_duphandle(void **to, void *from)
#define Curl_resolver_global_cleanup()
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, struct Curl_dns_entry **dnsentry)
void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
CURLcode Curl_set_dns_interface(struct Curl_easy *data, const char *interf)
#define calloc(nbelem, size)