mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05: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:
parent
83350c9cc4
commit
adc88ca203
@ -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;
|
||||||
}
|
}
|
||||||
|
13
lib/multi.c
13
lib/multi.c
@ -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
|
||||||
singlesocket(multi, easy);
|
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
|
/* 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,
|
||||||
|
Loading…
Reference in New Issue
Block a user