123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- #include "stx.h"
- #include "common.h"
- /*****************************************
- * Basic types definitions
- */
- typedef struct _stx_dns_data {
- struct in_addr *addrs;
- int num_addrs;
- int cur;
- time_t expires;
- } stx_dns_data_t;
- #define MAX_HOST_ADDRS 1024
- static struct in_addr addr_list[MAX_HOST_ADDRS];
- stx_cache_t *_stx_dns_cache = NULL;
- extern int _stx_dns_ttl;
- extern int _stx_dns_getaddrlist(const char *hostname, struct in_addr *addrs,
- int *num_addrs, st_utime_t timeout);
- static unsigned long hash_hostname(const void *key)
- {
- const char *name = (const char *)key;
- unsigned long hash = 0;
- while (*name)
- hash = (hash << 4) - hash + *name++; /* hash = hash * 15 + *name++ */
- return hash;
- }
- static void cleanup_entry(void *key, void *data)
- {
- if (key)
- free(key);
- if (data) {
- if (((stx_dns_data_t *)data)->addrs)
- free(((stx_dns_data_t *)data)->addrs);
- free(data);
- }
- }
- static int lookup_entry(const char *host, struct in_addr *addrs,
- int *num_addrs, int rotate)
- {
- stx_cache_entry_t *entry;
- stx_dns_data_t *data;
- int n;
- entry = stx_cache_entry_lookup(_stx_dns_cache, host);
- if (entry) {
- data = (stx_dns_data_t *)stx_cache_entry_getdata(entry);
- if (st_time() <= data->expires) {
- if (*num_addrs == 1) {
- if (rotate) {
- *addrs = data->addrs[data->cur++];
- if (data->cur >= data->num_addrs)
- data->cur = 0;
- } else {
- *addrs = data->addrs[0];
- }
- } else {
- n = STX_MIN(*num_addrs, data->num_addrs);
- memcpy(addrs, data->addrs, n * sizeof(*addrs));
- *num_addrs = n;
- }
- stx_cache_entry_release(_stx_dns_cache, entry);
- return 1;
- }
- /*
- * Cache entry expired: decrement its refcount and purge it from cache.
- */
- stx_cache_entry_release(_stx_dns_cache, entry);
- stx_cache_entry_delete(_stx_dns_cache, entry);
- }
- return 0;
- }
- static void insert_entry(const char *host, struct in_addr *addrs, int count)
- {
- stx_cache_entry_t *entry;
- stx_dns_data_t *data;
- char *key;
- size_t n;
- if (_stx_dns_ttl > 0) {
- key = strdup(host);
- data = (stx_dns_data_t *)malloc(sizeof(stx_dns_data_t));
- n = count * sizeof(*addrs);
- if (data) {
- data->addrs = (struct in_addr *)malloc(n);
- if (data->addrs)
- memcpy(data->addrs, addrs, n);
- data->num_addrs = count;
- data->cur = 0;
- data->expires = st_time() + _stx_dns_ttl;
- }
- entry = stx_cache_entry_create(key, data, strlen(host) + 1 +
- sizeof(stx_dns_data_t) + n +
- stx_cache_entry_sizeof());
- if (key && data && data->addrs && entry &&
- stx_cache_entry_insert(_stx_dns_cache, entry) == 0) {
- stx_cache_entry_release(_stx_dns_cache, entry);
- return;
- }
- if (entry)
- stx_cache_entry_delete(_stx_dns_cache, entry);
- else
- cleanup_entry(key, data);
- }
- }
- int _stx_dns_cache_getaddrlist(const char *hostname, struct in_addr *addrs,
- int *num_addrs, st_utime_t timeout,
- int rotate)
- {
- char host[128];
- int n, count;
- if (!_stx_dns_cache)
- return _stx_dns_getaddrlist(hostname, addrs, num_addrs, timeout);
- for (n = 0; n < sizeof(host) - 1 && hostname[n]; n++) {
- host[n] = tolower(hostname[n]);
- }
- host[n] = '\0';
- if (lookup_entry(host, addrs, num_addrs, rotate))
- return 0;
- count = MAX_HOST_ADDRS;
- if (_stx_dns_getaddrlist(host, addr_list, &count, timeout) < 0)
- return -1;
- n = STX_MIN(*num_addrs, count);
- memcpy(addrs, addr_list, n * sizeof(*addrs));
- *num_addrs = n;
- insert_entry(host, addr_list, count);
- return 0;
- }
- int stx_dns_cache_init(size_t max_size, size_t max_bytes, size_t hash_size)
- {
- _stx_dns_cache = stx_cache_create(max_size, max_bytes, hash_size,
- hash_hostname,
- (long (*)(const void *, const void *))strcmp,
- cleanup_entry);
- if (!_stx_dns_cache)
- return -1;
- return 0;
- }
- void stx_dns_cache_getinfo(stx_cache_info_t *info)
- {
- if (_stx_dns_cache)
- stx_cache_getinfo(_stx_dns_cache, info);
- else
- memset(info, 0, sizeof(stx_cache_info_t));
- }
- int stx_dns_getaddrlist(const char *hostname, struct in_addr *addrs,
- int *num_addrs, st_utime_t timeout)
- {
- return _stx_dns_cache_getaddrlist(hostname, addrs, num_addrs, timeout, 0);
- }
- int stx_dns_getaddr(const char *hostname, struct in_addr *addr,
- st_utime_t timeout)
- {
- int n = 1;
- return _stx_dns_cache_getaddrlist(hostname, addr, &n, timeout, 1);
- }
|