mirror of https://github.com/ossrs/srs.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.3 KiB
C
191 lines
4.3 KiB
C
5 years ago
|
#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);
|
||
|
}
|
||
|
|