示例#1
0
int ares_set_servers_ports(ares_channel channel,
                           struct ares_addr_port_node *servers)
{
  struct ares_addr_port_node *srvr;
  int num_srvrs = 0;
  int i;

  if (ares_library_initialized() != ARES_SUCCESS)
    return ARES_ENOTINITIALIZED;  /* LCOV_EXCL_LINE: n/a on non-WinSock */

  if (!channel)
    return ARES_ENODATA;

  if (!ares__is_list_empty(&channel->all_queries))
    return ARES_ENOTIMP;

  ares__destroy_servers_state(channel);

  for (srvr = servers; srvr; srvr = srvr->next)
    {
      num_srvrs++;
    }

  if (num_srvrs > 0)
    {
      /* Allocate storage for servers state */
      channel->servers = ares_malloc(num_srvrs * sizeof(struct server_state));
      if (!channel->servers)
        {
          return ARES_ENOMEM;
        }
      channel->nservers = num_srvrs;
      /* Fill servers state address data */
      for (i = 0, srvr = servers; srvr; i++, srvr = srvr->next)
        {
          channel->servers[i].addr.family = srvr->family;
          channel->servers[i].addr.udp_port = htons((unsigned short)srvr->udp_port);
          channel->servers[i].addr.tcp_port = htons((unsigned short)srvr->tcp_port);
          if (srvr->family == AF_INET)
            memcpy(&channel->servers[i].addr.addrV4, &srvr->addrV4,
                   sizeof(srvr->addrV4));
          else
            memcpy(&channel->servers[i].addr.addrV6, &srvr->addrV6,
                   sizeof(srvr->addrV6));
        }
      /* Initialize servers state remaining data */
      ares__init_servers_state(channel);
    }

  return ARES_SUCCESS;
}
示例#2
0
int ares_getsock(ares_channel channel,
                 int *s,
                 int numsocks) /* size of the 'socks' array */
{
  struct server_state *server;
  int i;
  int sockindex=0;
  int bitmap = 0;
  unsigned int setbits = 0xffffffff;

  ares_socket_t *socks = (ares_socket_t *)s;

  /* Are there any active queries? */
  int active_queries = !ares__is_list_empty(&(channel->all_queries));

  for (i = 0;
       (i < channel->nservers) && (sockindex < ARES_GETSOCK_MAXNUM);
       i++)
    {
      server = &channel->servers[i];
      /* We only need to register interest in UDP sockets if we have
       * outstanding queries.
       */
      if (active_queries && server->udp_socket != ARES_SOCKET_BAD)
        {
          if(sockindex >= numsocks)
            break;
          socks[sockindex] = server->udp_socket;
          bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex);
          sockindex++;
        }
      /* We always register for TCP events, because we want to know
       * when the other side closes the connection, so we don't waste
       * time trying to use a broken connection.
       */
      if (server->tcp_socket != ARES_SOCKET_BAD)
       {
         if(sockindex >= numsocks)
           break;
         socks[sockindex] = server->tcp_socket;
         bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex);

         if (server->qhead && active_queries)
           /* then the tcp socket is also writable! */
           bitmap |= ARES_GETSOCK_WRITABLE(setbits, sockindex);

         sockindex++;
       }
    }
  return bitmap;
}
示例#3
0
/* WARNING: Beware that this is linear in the number of outstanding
 * requests! You are probably far better off just calling ares_process()
 * once per second, rather than calling ares_timeout() to figure out
 * when to next call ares_process().
 */
struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
                             struct timeval *tvbuf)
{
  struct query *query;
  struct list_node* list_head;
  struct list_node* list_node;
  struct timeval now;
  struct timeval nextstop;
  long offset, min_offset;

  /* No queries, no timeout (and no fetch of the current time). */
  if (ares__is_list_empty(&(channel->all_queries)))
    return maxtv;

  /* Find the minimum timeout for the current set of queries. */
  now = ares__tvnow();
  min_offset = -1;

  list_head = &(channel->all_queries);
  for (list_node = list_head->next; list_node != list_head;
       list_node = list_node->next)
    {
      query = list_node->data;
      if (query->timeout.tv_sec == 0)
        continue;
      offset = timeoffset(&now, &query->timeout);
      if (offset < 0)
        offset = 0;
      if (min_offset == -1 || offset < min_offset)
        min_offset = offset;
    }

  /* If we found a minimum timeout and it's sooner than the one specified in
   * maxtv (if any), return it.  Otherwise go with maxtv.
   */
  if (min_offset != -1)
    {
      int ioffset = (min_offset > (long)INT_MAX) ? INT_MAX : (int)min_offset;

      nextstop.tv_sec = ioffset/1000;
      nextstop.tv_usec = (ioffset%1000)*1000;

      if (!maxtv || ares__timedout(maxtv, &nextstop))
        {
          *tvbuf = nextstop;
          return tvbuf;
        }
    }

  return maxtv;
}
示例#4
0
/*
 * ares_cancel() cancels all ongoing requests/resolves that might be going on
 * on the given channel. It does NOT kill the channel, use ares_destroy() for
 * that.
 */
void ares_cancel(ares_channel channel)
{
  struct query *query;
  struct list_node* list_head;
  struct list_node* list_node;
  int i;

  list_head = &(channel->all_queries);
  for (list_node = list_head->next; list_node != list_head; )
  {
    query = list_node->data;
    list_node = list_node->next;  /* since we're deleting the query */
    query->callback(query->arg, ARES_ETIMEOUT, 0, NULL, 0);
    ares__free_query(query);
  }
#ifndef NDEBUG
  /* Freeing the query should remove it from all the lists in which it sits,
   * so all query lists should be empty now.
   */
  assert(ares__is_list_empty(&(channel->all_queries)));
  for (i = 0; i < ARES_QID_TABLE_SIZE; i++)
    {
      assert(ares__is_list_empty(&(channel->queries_by_qid[i])));
    }
  for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++)
    {
      assert(ares__is_list_empty(&(channel->queries_by_timeout[i])));
    }
#endif
  if (!(channel->flags & ARES_FLAG_STAYOPEN))
  {
    if (channel->servers)
    {
      for (i = 0; i < channel->nservers; i++)
        ares__close_sockets(channel, &channel->servers[i]);
    }
  }
}
示例#5
0
int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds)
{
  struct server_state *server;
  ares_socket_t nfds;
  int i;

  /* Are there any active queries? */
  int active_queries = !ares__is_list_empty(&(channel->all_queries));

  nfds = 0;
  for (i = 0; i < channel->nservers; i++)
    {
      server = &channel->servers[i];
      /* We only need to register interest in UDP sockets if we have
       * outstanding queries.
       */
      if (active_queries && server->udp_socket != ARES_SOCKET_BAD)
        {
          FD_SET(server->udp_socket, read_fds);
          if (server->udp_socket >= nfds)
            nfds = server->udp_socket + 1;
        }
      /* We always register for TCP events, because we want to know
       * when the other side closes the connection, so we don't waste
       * time trying to use a broken connection.
       */
      if (server->tcp_socket != ARES_SOCKET_BAD)
       {
         FD_SET(server->tcp_socket, read_fds);
         if (server->qhead)
           FD_SET(server->tcp_socket, write_fds);
         if (server->tcp_socket >= nfds)
           nfds = server->tcp_socket + 1;
	}
    }
  return (int)nfds;
}