/* lookup address, returns entry if found and not stale */ static struct Curl_dns_entry * fetch_addr(struct connectdata *conn, const char *hostname, int port) { char *entry_id = NULL; struct Curl_dns_entry *dns = NULL; size_t entry_len; struct SessionHandle *data = conn->data; /* 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 dns; entry_len = strlen(entry_id); /* See if its already in our dns cache */ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); if(dns && (data->set.dns_cache_timeout != -1)) { /* See whether the returned entry is stale. Done before we release lock */ struct hostcache_prune_data user; time(&user.now); user.cache_timeout = data->set.dns_cache_timeout; if(hostcache_timestamp_remove(&user, dns)) { infof(data, "Hostname in DNS cache was stale, zapped\n"); dns = NULL; /* the memory deallocation is being handled by the hash */ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1); } } /* free the allocated entry_id again */ free(entry_id); return dns; }
static void conncache_remove_bundle(struct conncache *connc, struct connectbundle *bundle) { struct curl_hash_iterator iter; struct curl_hash_element *he; if(!connc) return; Curl_hash_start_iterate(&connc->hash, &iter); he = Curl_hash_next_element(&iter); while(he) { if(he->ptr == bundle) { /* The bundle is destroyed by the hash destructor function, free_bundle_hash_entry() */ Curl_hash_delete(&connc->hash, he->key, he->key_len); return; } he = Curl_hash_next_element(&iter); } }
static int on_stream_close(nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *userp) { struct connectdata *conn = (struct connectdata *)userp; struct SessionHandle *data_s; struct HTTP *stream; (void)session; (void)stream_id; DEBUGF(infof(conn->data, "on_stream_close(), error_code = %d, stream %u\n", error_code, stream_id)); if(stream_id) { /* get the stream from the hash based on Stream ID, stream ID zero is for connection-oriented stuff */ data_s = Curl_hash_pick(&conn->proto.httpc.streamsh, &stream_id, sizeof(stream_id)); if(!data_s) { /* We could get stream ID not in the hash. For example, if we decided to reject stream (e.g., PUSH_PROMISE). We call infof as a debugging purpose for now. */ infof(conn->data, "Received frame on Stream ID: %x not in stream hash!\n", stream_id); return 0; } stream = data_s->req.protop; stream->error_code = error_code; stream->closed = TRUE; /* remove the entry from the hash as the stream is now gone */ Curl_hash_delete(&conn->proto.httpc.streamsh, &stream_id, sizeof(stream_id)); DEBUGF(infof(conn->data, "Removed stream %u hash!\n", stream_id)); } return 0; }
CURLcode Curl_loadhostpairs(struct SessionHandle *data) { struct curl_slist *hostp; char hostname[256]; char address[256]; int port; for(hostp = data->change.resolve; hostp; hostp = hostp->next) { if(!hostp->data) continue; if(hostp->data[0] == '-') { char *entry_id; size_t entry_len; if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n", hostp->data); continue; } /* 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 CURLE_OUT_OF_MEMORY; } entry_len = strlen(entry_id); if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* delete entry, ignore if it didn't exist */ Curl_hash_delete(data->dns.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); } else { struct Curl_dns_entry *dns; Curl_addrinfo *addr; char *entry_id; size_t entry_len; if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, address)) { infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n", hostp->data); continue; } addr = Curl_str2addr(address, port); if(!addr) { infof(data, "Address in '%s' found illegal!\n", hostp->data); continue; } /* 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) { Curl_freeaddrinfo(addr); return CURLE_OUT_OF_MEMORY; } 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); if(!dns) { /* if not in the cache already, put this host in the cache */ dns = Curl_cache_addr(data, addr, hostname, port); if(dns) { dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */ /* release the returned reference; the cache itself will keep the * entry alive: */ dns->inuse--; } } else /* this is a duplicate, free it again */ Curl_freeaddrinfo(addr); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) { Curl_freeaddrinfo(addr); return CURLE_OUT_OF_MEMORY; } infof(data, "Added %s:%d:%s to DNS cache\n", hostname, port, address); } } data->change.resolve = NULL; /* dealt with now */ return CURLE_OK; }