1
0
mirror of https://github.com/moparisthebest/curl synced 2024-08-13 17:03:50 -04:00

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.
This commit is contained in:
Jason Glasgow 2011-11-30 15:23:44 -05:00 committed by Daniel Stenberg
parent 83350c9cc4
commit adc88ca203
2 changed files with 13 additions and 9 deletions

View File

@ -227,18 +227,19 @@ int Curl_resolver_getsock(struct connectdata *conn,
struct timeval maxtime; struct timeval maxtime;
struct timeval timebuf; struct timeval timebuf;
struct timeval *timeout; struct timeval *timeout;
long milli;
int max = ares_getsock((ares_channel)conn->data->state.resolver, int max = ares_getsock((ares_channel)conn->data->state.resolver,
(ares_socket_t *)socks, numsocks); (ares_socket_t *)socks, numsocks);
maxtime.tv_sec = CURL_TIMEOUT_RESOLVE; maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
maxtime.tv_usec = 0; maxtime.tv_usec = 0;
timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime, timeout = ares_timeout((ares_channel)conn->data->state.resolver, &maxtime,
&timebuf); &timebuf);
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
Curl_expire(conn->data, if(milli == 0)
(timeout->tv_sec * 1000) + (timeout->tv_usec/1000)); milli += 10;
Curl_expire(conn->data, milli);
return max; return max;
} }

View File

@ -1085,12 +1085,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* check if we have the name resolved by now */ /* check if we have the name resolved by now */
easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns); easy->result = Curl_resolver_is_resolved(easy->easy_conn, &dns);
if(dns) { /* Update sockets here, because the socket(s) may have been
/* Update sockets here. Mainly because the socket(s) may have been closed and the application thus needs to be told, even if it
closed and the application thus needs to be told, even if it is is likely that the same socket(s) will again be used further
likely that the same socket(s) will again be used further down. */ 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); singlesocket(multi, easy);
if(dns) {
/* Perform the next step in the connection phase, and then move on /* Perform the next step in the connection phase, and then move on
to the WAITCONNECT state */ to the WAITCONNECT state */
easy->result = Curl_async_resolved(easy->easy_conn, easy->result = Curl_async_resolved(easy->easy_conn,