Curl_addrinfo *Curl_resolv(struct SessionHandle *data, char *hostname, int port, char **bufp) { char *entry_id = NULL; struct curl_dns_cache_entry *p = NULL; ssize_t entry_len; time_t now; /* If the host cache timeout is 0, we don't do DNS cach'ing so fall through */ if (data->set.dns_cache_timeout == 0) { return Curl_getaddrinfo(data, hostname, port, bufp); } /* Create an entry id, based upon the hostname and port */ entry_len = strlen(hostname); entry_id = _create_hostcache_id(hostname, port, &entry_len); /* If we can't create the entry id, don't cache, just fall-through to the plain Curl_getaddrinfo() */ if (!entry_id) { return Curl_getaddrinfo(data, hostname, port, bufp); } time(&now); /* See if its already in our dns cache */ if (entry_id && curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) { /* Do we need to check for a cache timeout? */ if (data->set.dns_cache_timeout != -1) { /* Return if the entry has not timed out */ if ((now - p->timestamp) < data->set.dns_cache_timeout) { _hostcache_return(p->addr); } } else { _hostcache_return(p->addr); } } /* Create a new cache entry */ p = (struct curl_dns_cache_entry *) malloc(sizeof(struct curl_dns_cache_entry)); if (!p) { _hostcache_return(NULL); } p->addr = Curl_getaddrinfo(data, hostname, port, bufp); if (!p->addr) { free(p); _hostcache_return(NULL); } p->timestamp = now; /* Save it in our host cache */ curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p); _hostcache_return(p->addr); }
int Curl_resolv(struct connectdata *conn, char *hostname, int port, struct Curl_dns_entry **entry) { char *entry_id = NULL; struct Curl_dns_entry *dns = NULL; size_t entry_len; int wait; struct SessionHandle *data = conn->data; CURLcode result; int rc; *entry = NULL; #ifdef HAVE_SIGSETJMP /* this allows us to time-out from the name resolver, as the timeout will generate a signal and we will siglongjmp() from that here */ if(!data->set.no_signal && sigsetjmp(curl_jmpenv, 1)) { /* this is coming from a siglongjmp() */ failf(data, "name lookup timed out"); return CURLRESOLV_ERROR; } #endif /* Create an entry id, based upon the hostname and port */ entry_id = create_hostcache_id(hostname, port); /* If we can't create the entry id, fail */ if (!entry_id) return CURLRESOLV_ERROR; entry_len = strlen(entry_id); if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* See if its already in our dns cache */ dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); /* free the allocated entry_id again */ free(entry_id); /* See whether the returned entry is stale. Deliberately done after the locked block */ if ( remove_entry_if_stale(data,dns) ) dns = NULL; /* the memory deallocation is being handled by the hash */ rc = CURLRESOLV_ERROR; /* default to failure */ if (!dns) { /* The entry was not in the cache. Resolve it to IP address */ Curl_addrinfo *addr; /* Check what IP specifics the app has requested and if we can provide it. * If not, bail out. */ if(!Curl_ipvalid(data)) return CURLRESOLV_ERROR; /* If Curl_getaddrinfo() returns NULL, 'wait' might be set to a non-zero value indicating that we need to wait for the response to the resolve call */ addr = Curl_getaddrinfo(conn, hostname, port, &wait); if (!addr) { if(wait) { /* the response to our resolve call will come asynchronously at a later time, good or bad */ /* First, check that we haven't received the info by now */ result = Curl_is_resolved(conn, &dns); if(result) /* error detected */ return CURLRESOLV_ERROR; if(dns) rc = CURLRESOLV_RESOLVED; /* pointer provided */ else rc = CURLRESOLV_PENDING; /* no info yet */ } } else { if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* we got a response, store it in the cache */ dns = Curl_cache_addr(data, addr, hostname, port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) /* returned failure, bail out nicely */ Curl_freeaddrinfo(addr); else rc = CURLRESOLV_RESOLVED; } } else { if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); dns->inuse++; /* we use it! */ if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); rc = CURLRESOLV_RESOLVED; } *entry = dns; return rc; }
int Curl_resolv(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **entry) { char *entry_id = NULL; struct Curl_dns_entry *dns = NULL; size_t entry_len; struct SessionHandle *data = conn->data; CURLcode result; int rc = CURLRESOLV_ERROR; /* default to failure */ *entry = NULL; /* Create an entry id, based upon the hostname and port */ entry_id = create_hostcache_id(hostname, port); /* If we can't create the entry id, fail */ if(!entry_id) return rc; entry_len = strlen(entry_id); if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* See if its already in our dns cache */ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); /* free the allocated entry_id again */ free(entry_id); /* See whether the returned entry is stale. Done before we release lock */ if( remove_entry_if_stale(data, dns) ) dns = NULL; /* the memory deallocation is being handled by the hash */ if(dns) { dns->inuse++; /* we use it! */ rc = CURLRESOLV_RESOLVED; } if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) { /* The entry was not in the cache. Resolve it to IP address */ Curl_addrinfo *addr; int respwait; /* Check what IP specifics the app has requested and if we can provide it. * If not, bail out. */ if(!Curl_ipvalid(conn)) return CURLRESOLV_ERROR; /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a non-zero value indicating that we need to wait for the response to the resolve call */ addr = Curl_getaddrinfo(conn, #ifdef DEBUGBUILD (data->set.str[STRING_DEVICE] && !strcmp(data->set.str[STRING_DEVICE], "LocalHost"))?"localhost": #endif hostname, port, &respwait); if(!addr) { if(respwait) { /* the response to our resolve call will come asynchronously at a later time, good or bad */ /* First, check that we haven't received the info by now */ result = Curl_is_resolved(conn, &dns); if(result) /* error detected */ return CURLRESOLV_ERROR; if(dns) rc = CURLRESOLV_RESOLVED; /* pointer provided */ else rc = CURLRESOLV_PENDING; /* no info yet */ } } else { if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* we got a response, store it in the cache */ dns = Curl_cache_addr(data, addr, hostname, port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) /* returned failure, bail out nicely */ Curl_freeaddrinfo(addr); else rc = CURLRESOLV_RESOLVED; } } *entry = dns; return rc; }
int Curl_resolv(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **entry) { struct Curl_dns_entry *dns = NULL; struct SessionHandle *data = conn->data; CURLcode result; int rc = CURLRESOLV_ERROR; /* default to failure */ *entry = NULL; if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); dns = fetch_addr(conn, hostname, port); if(dns) { infof(data, "Hostname %s was found in DNS cache\n", hostname); dns->inuse++; /* we use it! */ rc = CURLRESOLV_RESOLVED; } if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) { /* The entry was not in the cache. Resolve it to IP address */ Curl_addrinfo *addr; int respwait; /* Check what IP specifics the app has requested and if we can provide it. * If not, bail out. */ if(!Curl_ipvalid(conn)) return CURLRESOLV_ERROR; /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a non-zero value indicating that we need to wait for the response to the resolve call */ addr = Curl_getaddrinfo(conn, #ifdef DEBUGBUILD (data->set.str[STRING_DEVICE] && !strcmp(data->set.str[STRING_DEVICE], "LocalHost"))?"localhost": #endif hostname, port, &respwait); if(!addr) { if(respwait) { /* the response to our resolve call will come asynchronously at a later time, good or bad */ /* First, check that we haven't received the info by now */ result = Curl_resolver_is_resolved(conn, &dns); if(result) /* error detected */ return CURLRESOLV_ERROR; if(dns) rc = CURLRESOLV_RESOLVED; /* pointer provided */ else rc = CURLRESOLV_PENDING; /* no info yet */ } } else { if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* we got a response, store it in the cache */ dns = Curl_cache_addr(data, addr, hostname, port); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) /* returned failure, bail out nicely */ Curl_freeaddrinfo(addr); else rc = CURLRESOLV_RESOLVED; } } *entry = dns; return rc; }