Commit 12fa877f authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Timeout slow ares name lookups. This is based on the patch brought by

Dirk Manske, but modified by me.
parent 580a2fe7
Loading
Loading
Loading
Loading
+29 −6
Original line number Diff line number Diff line
@@ -481,27 +481,46 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
{
  CURLcode rc=CURLE_OK;
  struct SessionHandle *data = conn->data;
  struct timeval now = Curl_tvnow();
  bool timedout = FALSE;
  long timeout = 300; /* default name resolve timeout in seconds */
  long elapsed = 0; /* time taken so far */

  /* now, see if there's a connect timeout or a regular timeout to
     use instead of the default one */
  if(conn->data->set.connecttimeout)
    timeout = conn->data->set.connecttimeout;
  else if(conn->data->set.timeout)
    timeout = conn->data->set.timeout;

  /* Wait for the name resolve query to complete. */
  while (1) {
    int nfds=0;
    fd_set read_fds, write_fds;
    struct timeval *tvp, tv;
    struct timeval *tvp, tv, store;
    int count;

    store.tv_sec = timeout - elapsed;
    store.tv_usec = 0;
    
    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);
    nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds);
    if (nfds == 0)
      break;
    tvp = ares_timeout(data->state.areschannel,
                       NULL, /* pass in our maximum time here */
                       &tv);
                       &store, &tv);
    count = select(nfds, &read_fds, &write_fds, NULL, tvp);
    if (count < 0 && errno != EINVAL)
      break;

    else if(!count) {
      /* timeout */
      timedout = TRUE;
      break;
    }
    ares_process(data->state.areschannel, &read_fds, &write_fds);

    elapsed = Curl_tvdiff(Curl_tvnow(), now)/1000; /* spent time */
  }

  /* Operation complete, if the lookup was successful we now have the entry
@@ -515,7 +534,11 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,

  if(!conn->async.dns) {
    /* a name was not resolved */
    if(conn->async.done) {
    if(timedout) {
      failf(data, "Resolving host timed out: %s", conn->name);
      rc = CURLE_OPERATION_TIMEDOUT;
    }
    else if(conn->async.done) {
      failf(data, "Could not resolve host: %s", conn->name);
      rc = CURLE_COULDNT_RESOLVE_HOST;
    }