Commit adc88ca2 authored by Jason Glasgow's avatar Jason Glasgow Committed by Daniel Stenberg
Browse files

multi: handle timeouts on DNS servers by checking for new sockets

If the first name server is not available, the multi interface does
not invoke the socket_cb when the DNS request to the first name server
timesout.  Ensure that the list of sockets are always updated after
calling Curl_resolver_is_resolved.

This bug can be reproduced if Curl is complied with --enable_ares and
your code uses the multi socket interfaces and the
CURLMOPT_SOCKETFUNCTION option.  To test try:
  iptables -I INPUT \
           -s $(sed -n -e '/name/{s/.* //p;q}' /etc/resolv.conf)/32 \
           -j REJECT
and then run a program which uses the multi-interface.
parent 83350c9c
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -227,18 +227,19 @@ int Curl_resolver_getsock(struct connectdata *conn,
  struct timeval maxtime;
  struct timeval timebuf;
  struct timeval *timeout;
  long milli;
  int max = ares_getsock((ares_channel)conn->data->state.resolver,
                         (ares_socket_t *)socks, numsocks);


  maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
  maxtime.tv_usec = 0;

  timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime,
                         &timebuf);

  Curl_expire(conn->data,
              (timeout->tv_sec * 1000) + (timeout->tv_usec/1000));
  milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
  if(milli == 0)
    milli += 10;
  Curl_expire(conn->data, milli);

  return max;
}
+8 −5
Original line number Diff line number Diff line
@@ -1085,12 +1085,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
      /* check if we have the name resolved by now */
      easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);

      if(dns) {
        /* Update sockets here. Mainly because the socket(s) may have been
           closed and the application thus needs to be told, even if it is
           likely that the same socket(s) will again be used further down. */
      /* Update sockets here, because the socket(s) may have been
         closed and the application thus needs to be told, even if it
         is likely that the same socket(s) will again be used further
         down.  If the name has not yet been resolved, it is likely
         that new sockets have been opened in an attempt to contact
         another resolver. */
      singlesocket(multi, easy);

      if(dns) {
        /* Perform the next step in the connection phase, and then move on
           to the WAITCONNECT state */
        easy->result = Curl_async_resolved(easy->easy_conn,