Commit 7de2f927 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

async resolvers: further cleanups

asyn-ares.c and asyn-thread.c are two separate backends that implement
the same (internal) async resolver API for libcurl to use. Backend is
specified at build time.

The internal resolver API is defined in asyn.h for asynch resolvers.
parent 24d84da0
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -15,14 +15,14 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
  memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c	\
  content_encoding.c share.c http_digest.c md4.c md5.c curl_rand.c	\
  http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c	\
  hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c	\
  inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c	\
  strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c		\
  socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c		\
  curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c	\
  warnless.c hmac.c polarssl.c curl_rtmp.c openldap.c curl_gethostname.c\
  gopher.c axtls.c idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c \
  non-ascii.c
  hostasyn.c hostip4.c hostip6.c hostsyn.c inet_ntop.c parsedate.c	\
  select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c	\
  qssl.c rawstr.c curl_addrinfo.c socks_gssapi.c socks_sspi.c		\
  curl_sspi.c slist.c nonblock.c curl_memrchr.c imap.c pop3.c smtp.c	\
  pingpong.c rtsp.c curl_threads.c warnless.c hmac.c polarssl.c		\
  curl_rtmp.c openldap.c curl_gethostname.c gopher.c axtls.c		\
  idn_win32.c http_negotiate_sspi.c cyassl.c http_proxy.c non-ascii.c	\
  asyn-ares.c asyn-thread.c

HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h	\
  progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h	\
@@ -37,5 +37,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
  curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h	\
  curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h	\
  warnless.h curl_hmac.h polarssl.h curl_rtmp.h curl_gethostname.h	\
  gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h
  gopher.h axtls.h cyassl.h http_proxy.h non-ascii.h asyn.h
+25 −20
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@

/***********************************************************************
 * Only for ares-enabled builds
 * And only for functions that fulfill the asynch resolver backend API
 * as defined in asyn.h, nothing else belongs in this file!
 **********************************************************************/

#ifdef CURLRES_ARES
@@ -180,10 +182,11 @@ int Curl_resolver_duphandle(void **to, void *from)
}

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)
void Curl_resolver_cancel(struct connectdata *conn)
{
  if( conn && conn->data && conn->data->state.resolver )
    ares_cancel((ares_channel)conn->data->state.resolver);
@@ -214,7 +217,7 @@ static void destroy_async_data (struct Curl_async *async)
}

/*
 * Curl_resolv_fdset() is called when someone from the outside world (using
 * Curl_resolver_fdset() is called when someone from the outside world (using
 * curl_multi_fdset()) wants to get our fd_set setup and we're talking with
 * ares. The caller must make sure that this function is only called when we
 * have a working ares channel.
@@ -222,7 +225,7 @@ static void destroy_async_data (struct Curl_async *async)
 * Returns: CURLE_OK always!
 */

int Curl_resolv_getsock(struct connectdata *conn,
int Curl_resolver_getsock(struct connectdata *conn,
                          curl_socket_t *socks,
                          int numsocks)

@@ -309,13 +312,13 @@ static int waitperform(struct connectdata *conn, int timeout_ms)
}

/*
 * Curl_is_resolved() is called repeatedly to check if a previous name resolve
 * request has completed. It should also make sure to time-out if the
 * operation seems to take too long.
 * Curl_resolver_is_resolved() is called repeatedly to check if a previous
 * name resolve request has completed. It should also make sure to time-out if
 * the operation seems to take too long.
 *
 * Returns normal CURLcode errors.
 */
CURLcode Curl_is_resolved(struct connectdata *conn,
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
                                   struct Curl_dns_entry **dns)
{
  struct SessionHandle *data = conn->data;
@@ -344,15 +347,17 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
}

/*
 * Curl_wait_for_resolv() waits for a resolve to finish. This function should
 * be avoided since using this risk getting the multi interface to "hang".
 * Curl_resolver_wait_resolv()
 *
 * waits for a resolve to finish. This function should be avoided since using
 * this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred.
 */
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
{
  CURLcode rc=CURLE_OK;
@@ -388,7 +393,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
      timeout_ms = 1000;

    waitperform(conn, timeout_ms);
    Curl_is_resolved(conn,&temp_entry);
    Curl_resolver_is_resolved(conn,&temp_entry);

    if(conn->async.done)
      break;
@@ -507,14 +512,14 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */
}

/*
 * Curl_getaddrinfo() - when using ares
 * Curl_resolver_getaddrinfo() - when using ares
 *
 * Returns name information about the given hostname and port number. If
 * successful, the 'hostent' is returned and the forth argument will point to
 * memory we need to free after use. That memory *MUST* be freed with
 * Curl_freeaddrinfo(), nothing else.
 */
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
                                         const char *hostname,
                                         int port,
                                         int *waitp)
+26 −23
Original line number Diff line number Diff line
@@ -144,10 +144,11 @@ int Curl_resolver_duphandle(void **to, void *from)
}

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)
void Curl_resolver_cancel(struct connectdata *conn)
{
  destroy_async_data(&conn->async);
}
@@ -374,7 +375,7 @@ static bool init_resolve_thread (struct connectdata *conn,
    goto err_exit;

#ifdef WIN32
  /* This socket is only to keep Curl_resolv_fdset() and select() happy;
  /* This socket is only to keep Curl_resolver_fdset() and select() happy;
   * should never become signalled for read since it's unbound but
   * Windows needs at least 1 socket in select().
   */
@@ -408,14 +409,16 @@ static bool init_resolve_thread (struct connectdata *conn,


/*
 * Curl_wait_for_resolv() waits for a resolve to finish. This function should
 * be avoided since using this risk getting the multi interface to "hang".
 * Curl_resolver_wait_resolv()
 *
 * waits for a resolve to finish. This function should be avoided since using
 * this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * This is the version for resolves-in-a-thread.
 */
CURLcode Curl_wait_for_resolv(struct connectdata *conn,
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
{
  struct thread_data   *td = (struct thread_data*) conn->async.os_specific;
@@ -458,11 +461,11 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
}

/*
 * Curl_is_resolved() is called repeatedly to check if a previous name resolve
 * request has completed. It should also make sure to time-out if the
 * operation seems to take too long.
 * Curl_resolver_is_resolved() is called repeatedly to check if a previous
 * name resolve request has completed. It should also make sure to time-out if
 * the operation seems to take too long.
 */
CURLcode Curl_is_resolved(struct connectdata *conn,
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
                                   struct Curl_dns_entry **entry)
{
  struct SessionHandle *data = conn->data;
@@ -513,7 +516,7 @@ CURLcode Curl_is_resolved(struct connectdata *conn,
  return CURLE_OK;
}

int Curl_resolv_getsock(struct connectdata *conn,
int Curl_resolver_getsock(struct connectdata *conn,
                          curl_socket_t *socks,
                          int numsocks)
{
@@ -535,7 +538,7 @@ int Curl_resolv_getsock(struct connectdata *conn,
/*
 * Curl_getaddrinfo() - for platforms without getaddrinfo
 */
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
                                         const char *hostname,
                                         int port,
                                         int *waitp)
@@ -561,9 +564,9 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
#else /* !HAVE_GETADDRINFO */

/*
 * Curl_getaddrinfo() - for getaddrinfo
 * Curl_resolver_getaddrinfo() - for getaddrinfo
 */
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
                                         const char *hostname,
                                         int port,
                                         int *waitp)

lib/asyn.h

0 → 100644
+169 −0
Original line number Diff line number Diff line
#ifndef HEADER_CURL_ASYN_H
#define HEADER_CURL_ASYN_H
/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * 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
 * are also available at http://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/

#include "setup.h"
#include "curl_addrinfo.h"

struct addrinfo;
struct hostent;
struct SessionHandle;
struct connectdata;
struct Curl_dns_entry;

/*
 * This header defines all functions in the internal asynch resolver interface.
 * All asynch resolvers need to provide these functions.
 * asyn-ares.c and asyn-thread.c are the current implementations of asynch
 * resolver backends.
 */

/*
 * Curl_resolver_global_init()
 *
 * 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()
 * Called from curl_global_cleanup() to destroy global resolver environment.
 */
void Curl_resolver_global_cleanup(void);

/*
 * Curl_resolver_init()
 * 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()
 * 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()
 * 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_resolver_cancel().
 *
 * 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_resolver_cancel(struct connectdata *conn);

/* Curl_resolver_getsock()
 *
 * This function is called from the multi_getsock() function.  'sock' is a
 * pointer to an array to hold the file descriptors, with 'numsock' being the
 * size of that array (in number of entries). This function is supposed to
 * return bitmask indicating what file descriptors (referring to array indexes
 * in the 'sock' array) to wait for, read/write.
 */
int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock,
                          int numsocks);

/*
 * Curl_resolver_is_resolved()
 *
 * Called repeatedly to check if a previous name resolve request has
 * completed. It should also make sure to time-out if the operation seems to
 * take too long.
 *
 * Returns normal CURLcode errors.
 */
CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
                                   struct Curl_dns_entry **dns);

/*
 * Curl_resolver_wait_resolv()
 *
 * waits for a resolve to finish. This function should be avoided since using
 * this risk getting the multi interface to "hang".
 *
 * If 'entry' is non-NULL, make it point to the resolved dns entry
 *
 * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, and
 * CURLE_OPERATION_TIMEDOUT if a time-out occurred.

 */
CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
                                   struct Curl_dns_entry **dnsentry);

/*
 * Curl_resolver_getaddrinfo() - when using this resolver
 *
 * Returns name information about the given hostname and port number. If
 * successful, the 'hostent' is returned and the forth argument will point to
 * memory we need to free after use. That memory *MUST* be freed with
 * Curl_freeaddrinfo(), nothing else.
 *
 * Each resolver backend must of course make sure to return data in the
 * correct format to comply with this.
 */
Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn,
                                         const char *hostname,
                                         int port,
                                         int *waitp);

#ifndef CURLRES_ASYNCH
/* convert these functions if an asynch resolver isn't used */
#define Curl_resolver_cancel(x)
#define Curl_async_resolved(x,y) CURLE_OK
#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST
#define Curl_resolver_getsock(x,y,z) 0
#define Curl_resolver_duphandle(x,y) CURLE_OK
#define Curl_resolver_init(x) CURLE_OK
#define Curl_resolver_global_init() CURLE_OK
#define Curl_resolver_global_cleanup()
#define Curl_resolver_cleanup(x)
#endif

#ifdef CURLRES_ASYNCH
#define Curl_resolver_asynch() 1
#else
#define Curl_resolver_asynch() 0
#endif


/********** end of generic resolver interface functions *****************/
#endif /* HEADER_CURL_ASYN_H */
+1 −1
Original line number Diff line number Diff line
@@ -324,7 +324,7 @@ static CURLcode bindlocal(struct connectdata *conn,

      rc = Curl_resolv(conn, dev, 0, &h);
      if(rc == CURLRESOLV_PENDING)
        (void)Curl_wait_for_resolv(conn, &h);
        (void)Curl_resolver_wait_resolv(conn, &h);
      conn->ip_version = ipver;

      if(h) {
Loading