mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
asynch resolvers: unified
Introducing an internal API for handling of different async resolver backends.
This commit is contained in:
parent
722f286f80
commit
ca015f1a45
19
lib/easy.c
19
lib/easy.c
@ -269,12 +269,10 @@ CURLcode curl_global_init(long flags)
|
|||||||
idna_init();
|
idna_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CARES_HAVE_ARES_LIBRARY_INIT
|
if( Curl_resolver_global_init() != CURLE_OK ) {
|
||||||
if(ares_library_init(ARES_LIB_INIT_ALL)) {
|
DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n"));
|
||||||
DEBUGF(fprintf(stderr, "Error: ares_library_init failed\n"));
|
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
|
#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
|
||||||
if(libssh2_init(0)) {
|
if(libssh2_init(0)) {
|
||||||
@ -340,9 +338,7 @@ void curl_global_cleanup(void)
|
|||||||
if(init_flags & CURL_GLOBAL_SSL)
|
if(init_flags & CURL_GLOBAL_SSL)
|
||||||
Curl_ssl_cleanup();
|
Curl_ssl_cleanup();
|
||||||
|
|
||||||
#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
|
Curl_resolver_global_cleanup();
|
||||||
ares_library_cleanup();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(init_flags & CURL_GLOBAL_WIN32)
|
if(init_flags & CURL_GLOBAL_WIN32)
|
||||||
win32_cleanup();
|
win32_cleanup();
|
||||||
@ -676,12 +672,9 @@ CURL *curl_easy_duphandle(CURL *incurl)
|
|||||||
outcurl->change.referer_alloc = TRUE;
|
outcurl->change.referer_alloc = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_ARES
|
/* Clone the resolver handle, if present, for the new handle */
|
||||||
/* If we use ares, we clone the ares channel for the new handle */
|
if( Curl_resolver_duphandle(&outcurl->state.resolver, data->state.resolver) != CURLE_OK )
|
||||||
if(ARES_SUCCESS != ares_dup(&outcurl->state.areschannel,
|
goto fail;
|
||||||
data->state.areschannel))
|
|
||||||
goto fail;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Curl_convert_setup(outcurl);
|
Curl_convert_setup(outcurl);
|
||||||
|
|
||||||
|
227
lib/hostares.c
227
lib/hostares.c
@ -60,6 +60,12 @@
|
|||||||
#define in_addr_t unsigned long
|
#define in_addr_t unsigned long
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Only for ares-enabled builds
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#ifdef CURLRES_ARES
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "hostip.h"
|
#include "hostip.h"
|
||||||
@ -76,15 +82,132 @@
|
|||||||
#define _MPRINTF_REPLACE /* use our functions only */
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
|
||||||
|
(defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
|
||||||
|
# define CARES_STATICLIB
|
||||||
|
# endif
|
||||||
|
# include <ares.h>
|
||||||
|
|
||||||
|
#if ARES_VERSION >= 0x010500
|
||||||
|
/* c-ares 1.5.0 or later, the callback proto is modified */
|
||||||
|
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
/***********************************************************************
|
struct ResolverResults {
|
||||||
* Only for ares-enabled builds
|
int num_pending; /* number of ares_gethostbyname() requests */
|
||||||
**********************************************************************/
|
Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
|
||||||
|
int last_status;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CURLRES_ARES
|
/*
|
||||||
|
* Curl_resolver_global_init() - the generic low-level asynchronous name resolve API.
|
||||||
|
* Called from curl_global_init() to initialize global resolver environment.
|
||||||
|
* Initializes ares library.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_global_init()
|
||||||
|
{
|
||||||
|
#ifdef CARES_HAVE_ARES_LIBRARY_INIT
|
||||||
|
if(ares_library_init(ARES_LIB_INIT_ALL)) {
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_global_cleanup() - the generic low-level asynchronous name resolve API.
|
||||||
|
* Called from curl_global_cleanup() to destroy global resolver environment.
|
||||||
|
* Deinitializes ares library.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_global_cleanup()
|
||||||
|
{
|
||||||
|
#ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
|
||||||
|
ares_library_cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_init() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_init() -> Curl_open() to initialize resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Fills the passed pointer by the initialized ares_channel.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_init(void **resolver)
|
||||||
|
{
|
||||||
|
int status = ares_init((ares_channel*)resolver);
|
||||||
|
if(status != ARES_SUCCESS) {
|
||||||
|
if(status == ARES_ENOMEM)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
else
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
}
|
||||||
|
return CURLE_OK;
|
||||||
|
/* make sure that all other returns from this function should destroy the
|
||||||
|
ares channel before returning error! */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_cleanup() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Destroys the ares channel.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_cleanup(void *resolver)
|
||||||
|
{
|
||||||
|
ares_destroy((ares_channel)resolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_duphandle() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_duphandle() to duplicate resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Duplicates the 'from' ares channel and passes the resulting channel to the 'to' pointer.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_duphandle(void **to, void *from)
|
||||||
|
{
|
||||||
|
/* Clone the ares channel for the new handle */
|
||||||
|
if(ARES_SUCCESS != ares_dup((ares_channel*)to,(ares_channel)from))
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_async_data (struct Curl_async *async);
|
||||||
|
/*
|
||||||
|
* Cancel all possibly still on-going resolves for this connection.
|
||||||
|
*/
|
||||||
|
void Curl_async_cancel(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
if( conn && conn->data && conn->data->state.resolver )
|
||||||
|
ares_cancel((ares_channel)conn->data->state.resolver);
|
||||||
|
destroy_async_data(&conn->async);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* destroy_async_data() cleans up async resolver data.
|
||||||
|
*/
|
||||||
|
static void destroy_async_data (struct Curl_async *async)
|
||||||
|
{
|
||||||
|
if(async->hostname)
|
||||||
|
free(async->hostname);
|
||||||
|
|
||||||
|
if(async->os_specific) {
|
||||||
|
struct ResolverResults *res = (struct ResolverResults *)async->os_specific;
|
||||||
|
if( res ) {
|
||||||
|
if( res->temp_ai ) {
|
||||||
|
Curl_freeaddrinfo(res->temp_ai);
|
||||||
|
res->temp_ai = NULL;
|
||||||
|
}
|
||||||
|
free(res);
|
||||||
|
}
|
||||||
|
async->os_specific = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
async->hostname = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_resolv_fdset() is called when someone from the outside world (using
|
* Curl_resolv_fdset() is called when someone from the outside world (using
|
||||||
@ -103,14 +226,14 @@ int Curl_resolv_getsock(struct connectdata *conn,
|
|||||||
struct timeval maxtime;
|
struct timeval maxtime;
|
||||||
struct timeval timebuf;
|
struct timeval timebuf;
|
||||||
struct timeval *timeout;
|
struct timeval *timeout;
|
||||||
int max = ares_getsock(conn->data->state.areschannel,
|
int max = ares_getsock((ares_channel)conn->data->state.resolver,
|
||||||
(ares_socket_t *)socks, numsocks);
|
(ares_socket_t *)socks, numsocks);
|
||||||
|
|
||||||
|
|
||||||
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
|
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
|
||||||
maxtime.tv_usec = 0;
|
maxtime.tv_usec = 0;
|
||||||
|
|
||||||
timeout = ares_timeout(conn->data->state.areschannel, &maxtime, &timebuf);
|
timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, &timebuf);
|
||||||
|
|
||||||
Curl_expire(conn->data,
|
Curl_expire(conn->data,
|
||||||
(timeout->tv_sec * 1000) + (timeout->tv_usec/1000));
|
(timeout->tv_sec * 1000) + (timeout->tv_usec/1000));
|
||||||
@ -138,7 +261,7 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
|
|||||||
int i;
|
int i;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
bitmask = ares_getsock(data->state.areschannel, socks, ARES_GETSOCK_MAXNUM);
|
bitmask = ares_getsock((ares_channel)data->state.resolver, socks, ARES_GETSOCK_MAXNUM);
|
||||||
|
|
||||||
for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
|
for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
|
||||||
pfd[i].events = 0;
|
pfd[i].events = 0;
|
||||||
@ -165,11 +288,11 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
|
|||||||
if(!nfds)
|
if(!nfds)
|
||||||
/* Call ares_process() unconditonally here, even if we simply timed out
|
/* Call ares_process() unconditonally here, even if we simply timed out
|
||||||
above, as otherwise the ares name resolve won't timeout! */
|
above, as otherwise the ares name resolve won't timeout! */
|
||||||
ares_process_fd(data->state.areschannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
|
ares_process_fd((ares_channel)data->state.resolver, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
|
||||||
else {
|
else {
|
||||||
/* move through the descriptors and ask for processing on them */
|
/* move through the descriptors and ask for processing on them */
|
||||||
for(i=0; i < num; i++)
|
for(i=0; i < num; i++)
|
||||||
ares_process_fd(data->state.areschannel,
|
ares_process_fd((ares_channel)data->state.resolver,
|
||||||
pfd[i].revents & (POLLRDNORM|POLLIN)?
|
pfd[i].revents & (POLLRDNORM|POLLIN)?
|
||||||
pfd[i].fd:ARES_SOCKET_BAD,
|
pfd[i].fd:ARES_SOCKET_BAD,
|
||||||
pfd[i].revents & (POLLWRNORM|POLLOUT)?
|
pfd[i].revents & (POLLWRNORM|POLLOUT)?
|
||||||
@ -189,13 +312,17 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
|||||||
struct Curl_dns_entry **dns)
|
struct Curl_dns_entry **dns)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
struct ResolverResults *res = (struct ResolverResults *)conn->async.os_specific;
|
||||||
|
|
||||||
*dns = NULL;
|
*dns = NULL;
|
||||||
|
|
||||||
waitperform(conn, 0);
|
waitperform(conn, 0);
|
||||||
|
|
||||||
if(conn->async.done) {
|
if( res && !res->num_pending ) {
|
||||||
/* we're done, kill the ares handle */
|
(void)Curl_addrinfo_callback(conn, res->last_status, res->temp_ai);
|
||||||
|
/* temp_ai ownership is moved to the connection, so we need not free-up them */
|
||||||
|
res->temp_ai = NULL;
|
||||||
|
destroy_async_data(&conn->async);
|
||||||
if(!conn->async.dns) {
|
if(!conn->async.dns) {
|
||||||
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
|
failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
|
||||||
ares_strerror(conn->async.status));
|
ares_strerror(conn->async.status));
|
||||||
@ -223,6 +350,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
|||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
long timeout;
|
long timeout;
|
||||||
struct timeval now = Curl_tvnow();
|
struct timeval now = Curl_tvnow();
|
||||||
|
struct Curl_dns_entry *temp_entry;
|
||||||
|
|
||||||
timeout = Curl_timeleft(data, &now, TRUE);
|
timeout = Curl_timeleft(data, &now, TRUE);
|
||||||
if(!timeout)
|
if(!timeout)
|
||||||
@ -240,7 +368,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
|||||||
store.tv_sec = itimeout/1000;
|
store.tv_sec = itimeout/1000;
|
||||||
store.tv_usec = (itimeout%1000)*1000;
|
store.tv_usec = (itimeout%1000)*1000;
|
||||||
|
|
||||||
tvp = ares_timeout(data->state.areschannel, &store, &tv);
|
tvp = ares_timeout((ares_channel)data->state.resolver, &store, &tv);
|
||||||
|
|
||||||
/* use the timeout period ares returned to us above if less than one
|
/* use the timeout period ares returned to us above if less than one
|
||||||
second is left, otherwise just use 1000ms to make sure the progress
|
second is left, otherwise just use 1000ms to make sure the progress
|
||||||
@ -251,6 +379,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
|||||||
timeout_ms = 1000;
|
timeout_ms = 1000;
|
||||||
|
|
||||||
waitperform(conn, timeout_ms);
|
waitperform(conn, timeout_ms);
|
||||||
|
Curl_is_resolved(conn,&temp_entry);
|
||||||
|
|
||||||
if(conn->async.done)
|
if(conn->async.done)
|
||||||
break;
|
break;
|
||||||
@ -267,7 +396,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
if(timeout < 0) {
|
if(timeout < 0) {
|
||||||
/* our timeout, so we cancel the ares operation */
|
/* our timeout, so we cancel the ares operation */
|
||||||
ares_cancel(data->state.areschannel);
|
ares_cancel((ares_channel)data->state.resolver);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,6 +442,22 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Connects results to the list */
|
||||||
|
static void ares_compound_results(struct ResolverResults *res, Curl_addrinfo *ai)
|
||||||
|
{
|
||||||
|
Curl_addrinfo *ai_tail;
|
||||||
|
if( !ai )
|
||||||
|
return;
|
||||||
|
ai_tail = ai;
|
||||||
|
|
||||||
|
while (ai_tail->ai_next)
|
||||||
|
ai_tail = ai_tail->ai_next;
|
||||||
|
|
||||||
|
/* Add the new results to the list of old results. */
|
||||||
|
ai_tail->ai_next = res->temp_ai;
|
||||||
|
res->temp_ai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ares_query_completed_cb() is the callback that ares will call when
|
* ares_query_completed_cb() is the callback that ares will call when
|
||||||
* the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
|
* the host query initiated by ares_gethostbyname() from Curl_getaddrinfo(),
|
||||||
@ -326,26 +471,44 @@ static void ares_query_completed_cb(void *arg, /* (struct connectdata *) */
|
|||||||
struct hostent *hostent)
|
struct hostent *hostent)
|
||||||
{
|
{
|
||||||
struct connectdata *conn = (struct connectdata *)arg;
|
struct connectdata *conn = (struct connectdata *)arg;
|
||||||
struct Curl_addrinfo * ai = NULL;
|
struct ResolverResults *res = (struct ResolverResults *)conn->async.os_specific;
|
||||||
|
|
||||||
|
if( !conn->data ) {
|
||||||
|
/* Immediately return just because the handle is destroying */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !conn->data->magic ) {
|
||||||
|
/* Immediately return just because the handle is destroying */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !res ) {
|
||||||
|
/* Immediately return just because the results are destroyed for some reason */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
|
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
|
||||||
(void)timeouts; /* ignored */
|
(void)timeouts; /* ignored */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
res->num_pending--;
|
||||||
|
|
||||||
switch(status) {
|
switch(status) {
|
||||||
case CURL_ASYNC_SUCCESS:
|
case CURL_ASYNC_SUCCESS:
|
||||||
ai = Curl_he2ai(hostent, conn->async.port);
|
ares_compound_results(res,Curl_he2ai(hostent, conn->async.port));
|
||||||
break;
|
break;
|
||||||
case ARES_EDESTRUCTION:
|
/* this ares handle is getting destroyed, the 'arg' pointer may not be
|
||||||
/* this ares handle is getting destroyed, the 'arg' pointer may not be
|
|
||||||
valid! */
|
valid! */
|
||||||
return;
|
/* conn->magic check instead
|
||||||
|
case ARES_EDESTRUCTION:
|
||||||
|
return; */
|
||||||
default:
|
default:
|
||||||
/* do nothing */
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/* The successfull result empties any error */
|
||||||
(void)Curl_addrinfo_callback(arg, status, ai);
|
if( res->last_status != ARES_SUCCESS )
|
||||||
|
res->last_status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -402,33 +565,41 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
#endif /* CURLRES_IPV6 */
|
#endif /* CURLRES_IPV6 */
|
||||||
|
|
||||||
bufp = strdup(hostname);
|
bufp = strdup(hostname);
|
||||||
|
|
||||||
if(bufp) {
|
if(bufp) {
|
||||||
|
struct ResolverResults *res = NULL;
|
||||||
Curl_safefree(conn->async.hostname);
|
Curl_safefree(conn->async.hostname);
|
||||||
conn->async.hostname = bufp;
|
conn->async.hostname = bufp;
|
||||||
conn->async.port = port;
|
conn->async.port = port;
|
||||||
conn->async.done = FALSE; /* not done */
|
conn->async.done = FALSE; /* not done */
|
||||||
conn->async.status = 0; /* clear */
|
conn->async.status = 0; /* clear */
|
||||||
conn->async.dns = NULL; /* clear */
|
conn->async.dns = NULL; /* clear */
|
||||||
conn->async.temp_ai = NULL; /* clear */
|
res = (struct ResolverResults *)calloc(sizeof(struct ResolverResults),1);
|
||||||
|
if( !res ) {
|
||||||
|
Curl_safefree(conn->async.hostname);
|
||||||
|
conn->async.hostname = NULL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
conn->async.os_specific = res;
|
||||||
|
|
||||||
|
/* initial status - failed */
|
||||||
|
res->last_status = ARES_ENOTFOUND;
|
||||||
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
#ifdef ENABLE_IPV6 /* CURLRES_IPV6 */
|
||||||
if(family == PF_UNSPEC) {
|
if(family == PF_UNSPEC) {
|
||||||
conn->async.num_pending = 2;
|
res->num_pending = 2;
|
||||||
|
|
||||||
/* areschannel is already setup in the Curl_open() function */
|
/* areschannel is already setup in the Curl_open() function */
|
||||||
ares_gethostbyname(data->state.areschannel, hostname, PF_INET,
|
ares_gethostbyname((ares_channel)data->state.resolver, hostname, PF_INET,
|
||||||
ares_query_completed_cb, conn);
|
ares_query_completed_cb, conn);
|
||||||
ares_gethostbyname(data->state.areschannel, hostname, PF_INET6,
|
ares_gethostbyname((ares_channel)data->state.resolver, hostname, PF_INET6,
|
||||||
ares_query_completed_cb, conn);
|
ares_query_completed_cb, conn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* CURLRES_IPV6 */
|
#endif /* CURLRES_IPV6 */
|
||||||
{
|
{
|
||||||
conn->async.num_pending = 1;
|
res->num_pending = 1;
|
||||||
|
|
||||||
/* areschannel is already setup in the Curl_open() function */
|
/* areschannel is already setup in the Curl_open() function */
|
||||||
ares_gethostbyname(data->state.areschannel, hostname, family,
|
ares_gethostbyname((ares_channel)data->state.resolver, hostname, family,
|
||||||
ares_query_completed_cb, conn);
|
ares_query_completed_cb, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,20 +72,6 @@
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
#ifdef CURLRES_ASYNCH
|
#ifdef CURLRES_ASYNCH
|
||||||
|
|
||||||
/*
|
|
||||||
* Cancel all possibly still on-going resolves for this connection.
|
|
||||||
*/
|
|
||||||
void Curl_async_cancel(struct connectdata *conn)
|
|
||||||
{
|
|
||||||
/* If we have a "half" response already received, we first clear that off
|
|
||||||
so that nothing is tempted to use it */
|
|
||||||
if(conn->async.temp_ai) {
|
|
||||||
Curl_freeaddrinfo(conn->async.temp_ai);
|
|
||||||
conn->async.temp_ai = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
|
* Curl_addrinfo_callback() gets called by ares, gethostbyname_thread()
|
||||||
* or getaddrinfo_thread() when we got the name resolved (or not!).
|
* or getaddrinfo_thread() when we got the name resolved (or not!).
|
||||||
@ -109,24 +95,6 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
|
|||||||
if(ai) {
|
if(ai) {
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
|
|
||||||
#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */
|
|
||||||
Curl_addrinfo *ai_tail = ai;
|
|
||||||
|
|
||||||
while (ai_tail->ai_next)
|
|
||||||
ai_tail = ai_tail->ai_next;
|
|
||||||
|
|
||||||
/* Add the new results to the list of old results. */
|
|
||||||
ai_tail->ai_next = conn->async.temp_ai;
|
|
||||||
conn->async.temp_ai = ai;
|
|
||||||
|
|
||||||
if(--conn->async.num_pending > 0)
|
|
||||||
/* We are not done yet. Just return. */
|
|
||||||
return CURLE_OK;
|
|
||||||
|
|
||||||
/* make sure the temp pointer is cleared and isn't pointing to something
|
|
||||||
we take care of below */
|
|
||||||
conn->async.temp_ai = NULL;
|
|
||||||
#endif
|
|
||||||
if(data->share)
|
if(data->share)
|
||||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
||||||
|
|
||||||
@ -143,52 +111,9 @@ CURLcode Curl_addrinfo_callback(struct connectdata *conn,
|
|||||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */
|
|
||||||
if(--conn->async.num_pending > 0) {
|
|
||||||
/* We are not done yet. Clean up and return.
|
|
||||||
This function will be called again. */
|
|
||||||
if(conn->async.temp_ai) {
|
|
||||||
Curl_freeaddrinfo(conn->async.temp_ai);
|
|
||||||
conn->async.temp_ai = NULL;
|
|
||||||
}
|
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
rc = CURLE_OUT_OF_MEMORY;
|
rc = CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(ENABLE_IPV6) && defined(CURLRES_ARES) /* CURLRES_IPV6 */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(--conn->async.num_pending > 0)
|
|
||||||
/* We are not done yet. Just return. */
|
|
||||||
return CURLE_OK;
|
|
||||||
|
|
||||||
if(conn->async.temp_ai) {
|
|
||||||
/* We are done, and while this latest request
|
|
||||||
failed, some previous results exist. */
|
|
||||||
struct SessionHandle *data = conn->data;
|
|
||||||
|
|
||||||
if(data->share)
|
|
||||||
Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);
|
|
||||||
|
|
||||||
dns = Curl_cache_addr(data, conn->async.temp_ai,
|
|
||||||
conn->async.hostname,
|
|
||||||
conn->async.port);
|
|
||||||
if(!dns) {
|
|
||||||
/* failed to store, cleanup and return error */
|
|
||||||
Curl_freeaddrinfo(conn->async.temp_ai);
|
|
||||||
rc = CURLE_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
if(data->share)
|
|
||||||
Curl_share_unlock(data, CURL_LOCK_DATA_DNS);
|
|
||||||
|
|
||||||
/* make sure the temp pointer is cleared and isn't pointing to
|
|
||||||
something we've taken care of already */
|
|
||||||
conn->async.temp_ai = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
conn->async.dns = dns;
|
conn->async.dns = dns;
|
||||||
|
|
||||||
|
79
lib/hostip.h
79
lib/hostip.h
@ -35,14 +35,6 @@
|
|||||||
#define in_addr_t unsigned long
|
#define in_addr_t unsigned long
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Comfortable CURLRES_* definitions are included from setup.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef USE_ARES
|
|
||||||
#include <ares_version.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Allocate enough memory to hold the full name information structs and
|
/* Allocate enough memory to hold the full name information structs and
|
||||||
* everything. OSF1 is known to require at least 8872 bytes. The buffer
|
* everything. OSF1 is known to require at least 8872 bytes. The buffer
|
||||||
* required for storing all possible aliases and IP numbers is according to
|
* required for storing all possible aliases and IP numbers is according to
|
||||||
@ -53,29 +45,13 @@
|
|||||||
#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this
|
#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this
|
||||||
many seconds for a name resolve */
|
many seconds for a name resolve */
|
||||||
|
|
||||||
#ifdef CURLRES_ARES
|
|
||||||
#define CURL_ASYNC_SUCCESS ARES_SUCCESS
|
|
||||||
#if ARES_VERSION >= 0x010500
|
|
||||||
/* c-ares 1.5.0 or later, the callback proto is modified */
|
|
||||||
#define HAVE_CARES_CALLBACK_TIMEOUTS 1
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#define CURL_ASYNC_SUCCESS CURLE_OK
|
#define CURL_ASYNC_SUCCESS CURLE_OK
|
||||||
#define ares_cancel(x) do {} while(0)
|
|
||||||
#define ares_destroy(x) do {} while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
struct hostent;
|
struct hostent;
|
||||||
struct SessionHandle;
|
struct SessionHandle;
|
||||||
struct connectdata;
|
struct connectdata;
|
||||||
|
|
||||||
#ifdef CURLRES_ASYNCH
|
|
||||||
void Curl_async_cancel(struct connectdata *conn);
|
|
||||||
#else
|
|
||||||
#define Curl_async_cancel(x) do {} while(0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_global_host_cache_init() initializes and sets up a global DNS cache.
|
* Curl_global_host_cache_init() initializes and sets up a global DNS cache.
|
||||||
* Global DNS cache is general badness. Do not use. This will be removed in
|
* Global DNS cache is general badness. Do not use. This will be removed in
|
||||||
@ -128,6 +104,45 @@ bool Curl_ipv6works(void);
|
|||||||
*/
|
*/
|
||||||
bool Curl_ipvalid(struct connectdata *conn);
|
bool Curl_ipvalid(struct connectdata *conn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_global_init() - the generic low-level name resolver API.
|
||||||
|
* Called from curl_global_init() to initialize global resolver environment.
|
||||||
|
* Returning anything else than CURLE_OK fails curl_global_init().
|
||||||
|
*/
|
||||||
|
int Curl_resolver_global_init(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_global_cleanup() - the generic low-level name resolver API.
|
||||||
|
* Called from curl_global_cleanup() to destroy global resolver environment.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_global_cleanup(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_init() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_init() -> Curl_open() to initialize resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Should fill the passed pointer by the initialized handler.
|
||||||
|
* Returning anything else than CURLE_OK fails curl_easy_init() with the correspondent code.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_init(void **resolver);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_cleanup() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Should destroy the handler and free all resources connected to it.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_cleanup(void *resolver);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_duphandle() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_duphandle() to duplicate resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Should duplicate the 'from' handle and pass the resulting handle to the 'to' pointer.
|
||||||
|
* Returning anything else than CURLE_OK causes failed curl_easy_duphandle() call.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_duphandle(void **to, void *from);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_getaddrinfo() is the generic low-level name resolve API within this
|
* Curl_getaddrinfo() is the generic low-level name resolve API within this
|
||||||
* source file. There are several versions of this function - for different
|
* source file. There are several versions of this function - for different
|
||||||
@ -139,6 +154,15 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
int port,
|
int port,
|
||||||
int *waitp);
|
int *waitp);
|
||||||
|
|
||||||
|
#ifdef CURLRES_ASYNCH
|
||||||
|
/*
|
||||||
|
* Curl_async_cancel() is the generic low-level asynchronous name resolve API.
|
||||||
|
* It is called from inside other functions to cancel currently performing resolver
|
||||||
|
* request. Should also free any temporary resources allocated to perform a request.
|
||||||
|
*/
|
||||||
|
void Curl_async_cancel(struct connectdata *conn);
|
||||||
|
#endif
|
||||||
|
|
||||||
CURLcode Curl_is_resolved(struct connectdata *conn,
|
CURLcode Curl_is_resolved(struct connectdata *conn,
|
||||||
struct Curl_dns_entry **dns);
|
struct Curl_dns_entry **dns);
|
||||||
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
||||||
@ -209,13 +233,6 @@ struct Curl_dns_entry *
|
|||||||
Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
|
Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr,
|
||||||
const char *hostname, int port);
|
const char *hostname, int port);
|
||||||
|
|
||||||
/*
|
|
||||||
* Curl_destroy_thread_data() cleans up async resolver data.
|
|
||||||
* Complementary of ares_destroy.
|
|
||||||
*/
|
|
||||||
struct Curl_async; /* forward-declaration */
|
|
||||||
void Curl_destroy_thread_data(struct Curl_async *async);
|
|
||||||
|
|
||||||
#ifndef INADDR_NONE
|
#ifndef INADDR_NONE
|
||||||
#define CURL_INADDR_NONE (in_addr_t) ~0
|
#define CURL_INADDR_NONE (in_addr_t) ~0
|
||||||
#else
|
#else
|
||||||
|
@ -87,6 +87,7 @@ bool Curl_ipvalid(struct connectdata *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CURLRES_SYNCH
|
#ifdef CURLRES_SYNCH
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_getaddrinfo() - the ipv4 synchronous version.
|
* Curl_getaddrinfo() - the ipv4 synchronous version.
|
||||||
*
|
*
|
||||||
|
@ -72,6 +72,61 @@
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
#ifdef CURLRES_SYNCH
|
#ifdef CURLRES_SYNCH
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_global_init() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_global_init() to initialize global resolver environment.
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_global_init()
|
||||||
|
{
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_global_cleanup() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_global_cleanup() to destroy global resolver environment.
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_global_cleanup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_init() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_init() -> Curl_open() to initialize resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_init(void **resolver)
|
||||||
|
{
|
||||||
|
(void)resolver;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_cleanup() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_cleanup(void *resolver)
|
||||||
|
{
|
||||||
|
(void)resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_duphandle() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_duphandle() to duplicate resolver URL state-specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_duphandle(void **to, void *from)
|
||||||
|
{
|
||||||
|
(void)to;
|
||||||
|
(void)from;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_wait_for_resolv() for synch-builds. Curl_resolv() can never return
|
* Curl_wait_for_resolv() for synch-builds. Curl_resolv() can never return
|
||||||
* wait==TRUE, so this function will never be called. If it still gets called,
|
* wait==TRUE, so this function will never be called. If it still gets called,
|
||||||
|
@ -88,6 +88,70 @@
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
#ifdef CURLRES_THREADED
|
#ifdef CURLRES_THREADED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_global_init() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_global_init() to initialize global resolver environment.
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_global_init()
|
||||||
|
{
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_global_cleanup() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_global_cleanup() to destroy global resolver environment.
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_global_cleanup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_init() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_init() -> Curl_open() to initialize resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_init(void **resolver)
|
||||||
|
{
|
||||||
|
(void)resolver;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_cleanup() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver URL-state specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
void Curl_resolver_cleanup(void *resolver)
|
||||||
|
{
|
||||||
|
(void)resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_resolver_duphandle() - the generic low-level name resolve API.
|
||||||
|
* Called from curl_easy_duphandle() to duplicate resolver URL state-specific environment
|
||||||
|
* ('resolver' member of the UrlState structure).
|
||||||
|
* Does nothing here.
|
||||||
|
*/
|
||||||
|
int Curl_resolver_duphandle(void **to, void *from)
|
||||||
|
{
|
||||||
|
(void)to;
|
||||||
|
(void)from;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_async_data(struct Curl_async *);
|
||||||
|
/*
|
||||||
|
* Cancel all possibly still on-going resolves for this connection.
|
||||||
|
*/
|
||||||
|
void Curl_async_cancel(struct connectdata *conn)
|
||||||
|
{
|
||||||
|
destroy_async_data(&conn->async);
|
||||||
|
}
|
||||||
|
|
||||||
/* This function is used to init a threaded resolve */
|
/* This function is used to init a threaded resolve */
|
||||||
static bool init_resolve_thread(struct connectdata *conn,
|
static bool init_resolve_thread(struct connectdata *conn,
|
||||||
const char *hostname, int port,
|
const char *hostname, int port,
|
||||||
@ -253,10 +317,9 @@ static unsigned int CURL_STDCALL gethostbyname_thread (void *arg)
|
|||||||
#endif /* HAVE_GETADDRINFO */
|
#endif /* HAVE_GETADDRINFO */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_destroy_thread_data() cleans up async resolver data and thread handle.
|
* destroy_async_data() cleans up async resolver data and thread handle.
|
||||||
* Complementary of ares_destroy.
|
|
||||||
*/
|
*/
|
||||||
void Curl_destroy_thread_data (struct Curl_async *async)
|
static void destroy_async_data (struct Curl_async *async)
|
||||||
{
|
{
|
||||||
if(async->hostname)
|
if(async->hostname)
|
||||||
free(async->hostname);
|
free(async->hostname);
|
||||||
@ -336,7 +399,7 @@ static bool init_resolve_thread (struct connectdata *conn,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
err_exit:
|
err_exit:
|
||||||
Curl_destroy_thread_data(&conn->async);
|
destroy_async_data(&conn->async);
|
||||||
|
|
||||||
SET_ERRNO(err);
|
SET_ERRNO(err);
|
||||||
|
|
||||||
@ -386,7 +449,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Curl_destroy_thread_data(&conn->async);
|
destroy_async_data(&conn->async);
|
||||||
|
|
||||||
if(!conn->async.dns)
|
if(!conn->async.dns)
|
||||||
conn->bits.close = TRUE;
|
conn->bits.close = TRUE;
|
||||||
@ -419,7 +482,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
|
|||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
getaddrinfo_complete(conn);
|
getaddrinfo_complete(conn);
|
||||||
Curl_destroy_thread_data(&conn->async);
|
destroy_async_data(&conn->async);
|
||||||
|
|
||||||
if(!conn->async.dns) {
|
if(!conn->async.dns) {
|
||||||
failf(data, "Could not resolve host: %s; %s",
|
failf(data, "Could not resolve host: %s; %s",
|
||||||
|
27
lib/url.c
27
lib/url.c
@ -526,7 +526,7 @@ CURLcode Curl_close(struct SessionHandle *data)
|
|||||||
Curl_safefree(data->info.wouldredirect);
|
Curl_safefree(data->info.wouldredirect);
|
||||||
|
|
||||||
/* this destroys the channel and we cannot use it anymore after this */
|
/* this destroys the channel and we cannot use it anymore after this */
|
||||||
ares_destroy(data->state.areschannel);
|
Curl_resolver_cleanup(data->state.resolver);
|
||||||
|
|
||||||
Curl_convert_close(data);
|
Curl_convert_close(data);
|
||||||
|
|
||||||
@ -766,9 +766,7 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
|||||||
{
|
{
|
||||||
CURLcode res = CURLE_OK;
|
CURLcode res = CURLE_OK;
|
||||||
struct SessionHandle *data;
|
struct SessionHandle *data;
|
||||||
#ifdef USE_ARES
|
|
||||||
int status;
|
int status;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Very simple start-up: alloc the struct, init it with zeroes and return */
|
/* Very simple start-up: alloc the struct, init it with zeroes and return */
|
||||||
data = calloc(1, sizeof(struct SessionHandle));
|
data = calloc(1, sizeof(struct SessionHandle));
|
||||||
@ -780,18 +778,11 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
|||||||
|
|
||||||
data->magic = CURLEASY_MAGIC_NUMBER;
|
data->magic = CURLEASY_MAGIC_NUMBER;
|
||||||
|
|
||||||
#ifdef USE_ARES
|
if( (status=Curl_resolver_init(&data->state.resolver)) != CURLE_OK ) {
|
||||||
if((status = ares_init(&data->state.areschannel)) != ARES_SUCCESS) {
|
DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
|
||||||
DEBUGF(fprintf(stderr, "Error: ares_init failed\n"));
|
|
||||||
free(data);
|
free(data);
|
||||||
if(status == ARES_ENOMEM)
|
return status;
|
||||||
return CURLE_OUT_OF_MEMORY;
|
|
||||||
else
|
|
||||||
return CURLE_FAILED_INIT;
|
|
||||||
}
|
}
|
||||||
/* make sure that all other returns from this function should destroy the
|
|
||||||
ares channel before returning error! */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* We do some initial setup here, all those fields that can't be just 0 */
|
/* We do some initial setup here, all those fields that can't be just 0 */
|
||||||
|
|
||||||
@ -823,7 +814,7 @@ CURLcode Curl_open(struct SessionHandle **curl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(res) {
|
if(res) {
|
||||||
ares_destroy(data->state.areschannel);
|
Curl_resolver_cleanup(data->state.resolver);
|
||||||
if(data->state.headerbuff)
|
if(data->state.headerbuff)
|
||||||
free(data->state.headerbuff);
|
free(data->state.headerbuff);
|
||||||
Curl_freeset(data);
|
Curl_freeset(data);
|
||||||
@ -2521,6 +2512,11 @@ static void conn_free(struct connectdata *conn)
|
|||||||
if(!conn)
|
if(!conn)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* possible left-overs from the async name resolvers */
|
||||||
|
#if defined(CURLRES_ASYNCH)
|
||||||
|
Curl_async_cancel(conn);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* close the SSL stuff before we close any sockets since they will/may
|
/* close the SSL stuff before we close any sockets since they will/may
|
||||||
write to the sockets */
|
write to the sockets */
|
||||||
Curl_ssl_close(conn, FIRSTSOCKET);
|
Curl_ssl_close(conn, FIRSTSOCKET);
|
||||||
@ -2564,6 +2560,7 @@ static void conn_free(struct connectdata *conn)
|
|||||||
Curl_safefree(conn->async.os_specific);
|
Curl_safefree(conn->async.os_specific);
|
||||||
#endif
|
#endif
|
||||||
Curl_safefree(conn->localdev);
|
Curl_safefree(conn->localdev);
|
||||||
|
|
||||||
Curl_free_ssl_config(&conn->ssl_config);
|
Curl_free_ssl_config(&conn->ssl_config);
|
||||||
|
|
||||||
free(conn); /* free all the connection oriented data */
|
free(conn); /* free all the connection oriented data */
|
||||||
@ -5195,7 +5192,9 @@ CURLcode Curl_done(struct connectdata **connp,
|
|||||||
data->req.location = NULL;
|
data->req.location = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CURLRES_ASYNCH)
|
||||||
Curl_async_cancel(conn);
|
Curl_async_cancel(conn);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(conn->dns_entry) {
|
if(conn->dns_entry) {
|
||||||
Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
|
Curl_resolv_unlock(data, conn->dns_entry); /* done with this */
|
||||||
|
@ -145,14 +145,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_ARES
|
|
||||||
# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \
|
|
||||||
(defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
|
|
||||||
# define CARES_STATICLIB
|
|
||||||
# endif
|
|
||||||
# include <ares.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "http_chunks.h" /* for the structs and enum stuff */
|
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||||
@ -508,8 +500,6 @@ struct Curl_async {
|
|||||||
bool done; /* set TRUE when the lookup is complete */
|
bool done; /* set TRUE when the lookup is complete */
|
||||||
int status; /* if done is TRUE, this is the status from the callback */
|
int status; /* if done is TRUE, this is the status from the callback */
|
||||||
void *os_specific; /* 'struct thread_data' for Windows */
|
void *os_specific; /* 'struct thread_data' for Windows */
|
||||||
int num_pending; /* number of ares_gethostbyname() requests */
|
|
||||||
Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1153,9 +1143,7 @@ struct UrlState {
|
|||||||
|
|
||||||
bool authproblem; /* TRUE if there's some problem authenticating */
|
bool authproblem; /* TRUE if there's some problem authenticating */
|
||||||
|
|
||||||
#ifdef USE_ARES
|
void *resolver; /* resolver state, if it is used in the URL state - ares_channel f.e. */
|
||||||
ares_channel areschannel; /* for name resolves */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
|
#if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
|
||||||
ENGINE *engine;
|
ENGINE *engine;
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include <curl/mprintf.h>
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
#ifdef USE_ARES
|
#ifdef USE_ARES
|
||||||
#include <ares_version.h>
|
#include <ares.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIBIDN
|
#ifdef USE_LIBIDN
|
||||||
|
Loading…
Reference in New Issue
Block a user