00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "setup.h"
00025
00026 #include <string.h>
00027
00028 #ifdef NEED_MALLOC_H
00029 #include <malloc.h>
00030 #endif
00031 #ifdef HAVE_SYS_SOCKET_H
00032 #include <sys/socket.h>
00033 #endif
00034 #ifdef HAVE_NETINET_IN_H
00035 #include <netinet/in.h>
00036 #endif
00037 #ifdef HAVE_NETDB_H
00038 #include <netdb.h>
00039 #endif
00040 #ifdef HAVE_ARPA_INET_H
00041 #include <arpa/inet.h>
00042 #endif
00043 #ifdef HAVE_STDLIB_H
00044 #include <stdlib.h>
00045 #endif
00046 #ifdef HAVE_UNISTD_H
00047 #include <unistd.h>
00048 #endif
00049 #ifdef VMS
00050 #include <in.h>
00051 #include <inet.h>
00052 #include <stdlib.h>
00053 #endif
00054
00055 #ifdef HAVE_SETJMP_H
00056 #include <setjmp.h>
00057 #endif
00058
00059 #ifdef HAVE_PROCESS_H
00060 #include <process.h>
00061 #endif
00062
00063 #if (defined(NETWARE) && defined(__NOVELL_LIBC__))
00064 #undef in_addr_t
00065 #define in_addr_t unsigned long
00066 #endif
00067
00068 #include "urldata.h"
00069 #include "sendf.h"
00070 #include "hostip.h"
00071 #include "hash.h"
00072 #include "share.h"
00073 #include "strerror.h"
00074 #include "url.h"
00075 #include "multiif.h"
00076 #include "connect.h"
00077 #include "select.h"
00078
00079 #define _MPRINTF_REPLACE
00080 #include <curl/mprintf.h>
00081
00082 #if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
00083 #include "inet_ntoa_r.h"
00084 #endif
00085
00086 #include "memory.h"
00087
00088
00089 #include "memdebug.h"
00090
00091
00092
00093
00094
00095 #ifdef CURLRES_ARES
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 int Curl_resolv_getsock(struct connectdata *conn,
00107 curl_socket_t *socks,
00108 int numsocks)
00109
00110 {
00111 struct timeval maxtime;
00112 struct timeval timeout;
00113 int max = ares_getsock(conn->data->state.areschannel,
00114 (int *)socks, numsocks);
00115
00116
00117 maxtime.tv_sec = CURL_TIMEOUT_RESOLVE;
00118 maxtime.tv_usec = 0;
00119
00120 ares_timeout(conn->data->state.areschannel, &maxtime, &timeout);
00121
00122 Curl_expire(conn->data,
00123 (timeout.tv_sec * 1000) + (timeout.tv_usec/1000) );
00124
00125 return max;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 static int ares_waitperform(struct connectdata *conn, int timeout_ms)
00139 {
00140 struct SessionHandle *data = conn->data;
00141 int nfds;
00142 int bitmask;
00143 int socks[ARES_GETSOCK_MAXNUM];
00144 struct pollfd pfd[ARES_GETSOCK_MAXNUM];
00145 int m;
00146 int i;
00147 int num;
00148
00149 bitmask = ares_getsock(data->state.areschannel, socks, ARES_GETSOCK_MAXNUM);
00150
00151 for(i=0; i < ARES_GETSOCK_MAXNUM; i++) {
00152 pfd[i].events = 0;
00153 m=0;
00154 if(ARES_GETSOCK_READABLE(bitmask, i)) {
00155 pfd[i].fd = socks[i];
00156 pfd[i].events |= POLLRDNORM|POLLIN;
00157 m=1;
00158 }
00159 if(ARES_GETSOCK_WRITABLE(bitmask, i)) {
00160 pfd[i].fd = socks[i];
00161 pfd[i].events |= POLLWRNORM|POLLOUT;
00162 m=1;
00163 }
00164 pfd[i].revents=0;
00165 if(!m)
00166 break;
00167 }
00168 num = i;
00169
00170 if(num)
00171 nfds = Curl_poll(pfd, num, timeout_ms);
00172 else
00173 nfds = 0;
00174
00175 if(!nfds)
00176
00177
00178 ares_process_fd(data->state.areschannel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
00179 else {
00180
00181 for(i=0; i < num; i++)
00182 ares_process_fd(data->state.areschannel,
00183 pfd[i].revents & (POLLRDNORM|POLLIN)?
00184 pfd[i].fd:ARES_SOCKET_BAD,
00185 pfd[i].revents & (POLLWRNORM|POLLOUT)?
00186 pfd[i].fd:ARES_SOCKET_BAD);
00187 }
00188 return nfds;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 CURLcode Curl_is_resolved(struct connectdata *conn,
00199 struct Curl_dns_entry **dns)
00200 {
00201 struct SessionHandle *data = conn->data;
00202
00203 *dns = NULL;
00204
00205 ares_waitperform(conn, 0);
00206
00207 if(conn->async.done) {
00208
00209 if(!conn->async.dns) {
00210 failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
00211 ares_strerror(conn->async.status));
00212 return CURLE_COULDNT_RESOLVE_HOST;
00213 }
00214 *dns = conn->async.dns;
00215 }
00216
00217 return CURLE_OK;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 CURLcode Curl_wait_for_resolv(struct connectdata *conn,
00230 struct Curl_dns_entry **entry)
00231 {
00232 CURLcode rc=CURLE_OK;
00233 struct SessionHandle *data = conn->data;
00234 long timeout;
00235
00236
00237
00238 if(conn->data->set.connecttimeout)
00239 timeout = conn->data->set.connecttimeout;
00240 else if(conn->data->set.timeout)
00241 timeout = conn->data->set.timeout;
00242 else
00243 timeout = CURL_TIMEOUT_RESOLVE * 1000;
00244
00245
00246 while (1) {
00247 struct timeval *tvp, tv, store;
00248 struct timeval now = Curl_tvnow();
00249 long timediff;
00250
00251 store.tv_sec = (int)timeout/1000;
00252 store.tv_usec = (timeout%1000)*1000;
00253
00254 tvp = ares_timeout(data->state.areschannel, &store, &tv);
00255
00256
00257 ares_waitperform(conn, tv.tv_sec * 1000 + tv.tv_usec/1000);
00258
00259 if(conn->async.done)
00260 break;
00261
00262 timediff = Curl_tvdiff(Curl_tvnow(), now);
00263 timeout -= timediff?timediff:1;
00264 if (timeout < 0) {
00265
00266 ares_cancel(data->state.areschannel);
00267 break;
00268 }
00269 }
00270
00271
00272
00273
00274 if(entry)
00275 *entry = conn->async.dns;
00276
00277 if(!conn->async.dns) {
00278
00279 if((timeout < 0) || (conn->async.status == ARES_ETIMEOUT)) {
00280 failf(data, "Resolving host timed out: %s", conn->host.dispname);
00281 rc = CURLE_OPERATION_TIMEDOUT;
00282 }
00283 else if(conn->async.done) {
00284 failf(data, "Could not resolve host: %s (%s)", conn->host.dispname,
00285 ares_strerror(conn->async.status));
00286 rc = CURLE_COULDNT_RESOLVE_HOST;
00287 }
00288 else
00289 rc = CURLE_OPERATION_TIMEDOUT;
00290
00291
00292
00293 conn->bits.close = TRUE;
00294 }
00295
00296 return rc;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
00308 const char *hostname,
00309 int port,
00310 int *waitp)
00311 {
00312 char *bufp;
00313 struct SessionHandle *data = conn->data;
00314 in_addr_t in = inet_addr(hostname);
00315
00316 *waitp = FALSE;
00317
00318 if (in != CURL_INADDR_NONE) {
00319
00320 return Curl_ip2addr(in, hostname, port);
00321 }
00322
00323 bufp = strdup(hostname);
00324
00325 if(bufp) {
00326 Curl_safefree(conn->async.hostname);
00327 conn->async.hostname = bufp;
00328 conn->async.port = port;
00329 conn->async.done = FALSE;
00330 conn->async.status = 0;
00331 conn->async.dns = NULL;
00332
00333
00334 ares_gethostbyname(data->state.areschannel, hostname, PF_INET,
00335 (ares_host_callback)Curl_addrinfo4_callback, conn);
00336
00337 *waitp = TRUE;
00338 }
00339 return NULL;
00340 }
00341 #endif