Commit 79d59ec9 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Brad House added ares_save_options() and ares_destroy_options() that can be

used to keep options for later re-usal when ares_init_options() is used.
parent a49e78d9
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -2,6 +2,25 @@

* May 30 2007

- Brad House added ares_save_options() and ares_destroy_options() that can be
  used to keep options for later re-usal when ares_init_options() is used.
  
  Problem: Calling ares_init() for each lookup can be unnecessarily resource
         intensive.  On windows, it must LoadLibrary() or search the registry
         on each call to ares_init().  On unix, it must read and parse
         multiple files to obtain the necessary configuration information.  In
         a single-threaded environment, it would make sense to only
         ares_init() once, but in a heavily multi-threaded environment, it is
         undesirable to ares_init() and ares_destroy() for each thread created
         and track that.

  Solution: Create ares_save_options() and ares_destroy_options() functions to
         retrieve and free options obtained from an initialized channel.  The
         options populated can be used to pass back into ares_init_options(),
         it should populate all needed fields and not retrieve any information
         from the system.  Probably wise to destroy the cache every minute or
         so to prevent the data from becoming stale.

- Daniel S added ares_process_fd() to allow applications to ask for processing
  on specific sockets and thus avoiding select() and associated
  functions/macros.  This function will be used by upcoming libcurl releases
+7 −0
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ extern "C" {
#define ARES_OPT_DOMAINS        (1 << 7)
#define ARES_OPT_LOOKUPS        (1 << 8)
#define ARES_OPT_SOCK_STATE_CB  (1 << 9)
#define ARES_OPT_SORTLIST       (1 << 10)

/* Nameinfo flag values */
#define ARES_NI_NOFQDN                  (1 << 0)
@@ -164,6 +165,8 @@ typedef void (*ares_sock_state_cb)(void *data,
                                   int writable);
#endif

struct apattern;

struct ares_options {
  int flags;
  int timeout;
@@ -178,6 +181,8 @@ struct ares_options {
  char *lookups;
  ares_sock_state_cb sock_state_cb;
  void *sock_state_cb_data;
  struct apattern *sortlist;
  int nsort;
};

struct hostent;
@@ -195,6 +200,8 @@ typedef void (*ares_nameinfo_callback)(void *arg, int status,
int ares_init(ares_channel *channelptr);
int ares_init_options(ares_channel *channelptr, struct ares_options *options,
                      int optmask);
int ares_save_options(ares_channel channel, struct ares_options *options, int *optmask);
void ares_destroy_options(struct ares_options *options);
void ares_destroy(ares_channel channel);
void ares_cancel(ares_channel channel);
void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
+13 −0
Original line number Diff line number Diff line
@@ -20,6 +20,19 @@
#include "ares.h"
#include "ares_private.h"

void ares_destroy_options(struct ares_options *options)
{
  int i;

  free(options->servers);
  for (i = 0; i < options->ndomains; i++)
    free(options->domains[i]);
  free(options->domains);
  if(options->sortlist)
    free(options->sortlist);
  free(options->lookups);
}

void ares_destroy(ares_channel channel)
{
  int i;
+94 −2
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@
#undef WIN32  /* Redefined in MingW/MSVC headers */
#endif

static int init_by_options(ares_channel channel, struct ares_options *options,
static int init_by_options(ares_channel channel, const struct ares_options *options,
                           int optmask);
static int init_by_environment(ares_channel channel);
static int init_by_resolv_conf(ares_channel channel);
@@ -84,6 +84,12 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
static char *try_config(char *s, const char *opt);
#endif

#define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
			     x->nservers > -1 && \
                             x->ndomains > -1 && \
			     x->ndots > -1 && x->timeout > -1 && \
			     x->tries > -1)

int ares_init(ares_channel *channelptr)
{
  return ares_init_options(channelptr, NULL, 0);
@@ -212,7 +218,76 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
  return ARES_SUCCESS;
}

static int init_by_options(ares_channel channel, struct ares_options *options,
/* Save options from initialized channel */
int ares_save_options(ares_channel channel, struct ares_options *options,
                      int *optmask)
{
  int i;

  /* Zero everything out */
  memset(options, 0, sizeof(struct ares_options));

  if (!ARES_CONFIG_CHECK(channel))
    return ARES_ENODATA;

  (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TIMEOUT|ARES_OPT_TRIES|ARES_OPT_NDOTS|
                ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB|
                ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS|
                ARES_OPT_SORTLIST);

  /* Copy easy stuff */
  options->flags   = channel->flags;
  options->timeout = channel->timeout;
  options->tries   = channel->tries;
  options->ndots   = channel->ndots;
  options->udp_port = channel->udp_port;
  options->tcp_port = channel->tcp_port;
  options->sock_state_cb     = channel->sock_state_cb;
  options->sock_state_cb_data = channel->sock_state_cb_data;

  /* Copy servers */
  options->servers =
    malloc(channel->nservers * sizeof(struct server_state));
  if (!options->servers && channel->nservers != 0)
    return ARES_ENOMEM;
  for (i = 0; i < channel->nservers; i++)
    options->servers[i] = channel->servers[i].addr;
  options->nservers = channel->nservers;

  /* copy domains */
  options->domains = malloc(channel->ndomains * sizeof(char *));
  if (!options->domains)
    return ARES_ENOMEM;
  for (i = 0; i < channel->ndomains; i++)
  {
    options->ndomains = i;
    options->domains[i] = strdup(channel->domains[i]);
    if (!options->domains[i])
      return ARES_ENOMEM;
  }
  options->ndomains = channel->ndomains;

  /* copy lookups */
  options->lookups = strdup(channel->lookups);
  if (!options->lookups)
    return ARES_ENOMEM;

  /* copy sortlist */
  options->sortlist = malloc(channel->nsort * sizeof(struct apattern));
  if (!options->sortlist)
    return ARES_ENOMEM;
  for (i = 0; i < channel->nsort; i++)
  {
    memcpy(&(options->sortlist[i]), &(channel->sortlist[i]),
           sizeof(struct apattern));
  }
  options->nsort = channel->nsort;

  return ARES_SUCCESS;
}

static int init_by_options(ares_channel channel,
                           const struct ares_options *options,
                           int optmask)
{
  int i;
@@ -282,6 +357,19 @@ static int init_by_options(ares_channel channel, struct ares_options *options,
        return ARES_ENOMEM;
    }

  /* copy sortlist */
  if ((optmask & ARES_OPT_SORTLIST) && channel->nsort == -1)
    {
      channel->sortlist = malloc(options->nsort * sizeof(struct apattern));
      if (!channel->sortlist)
        return ARES_ENOMEM;
      for (i = 0; i < options->nsort; i++)
        {
          memcpy(&(channel->sortlist[i]), &(options->sortlist[i]), sizeof(struct apattern));
        }
      channel->nsort = options->nsort;
    }

  return ARES_SUCCESS;
}

@@ -615,6 +703,10 @@ DhcpNameServer
    int linesize;
    int error;

    /* Don't read resolv.conf and friends if we don't have to */
    if (ARES_CONFIG_CHECK(channel))
        return ARES_SUCCESS;

    fp = fopen(PATH_RESOLV_CONF, "r");
    if (fp) {
      while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS)