Fetch the repository succeeded.
This action will force synchronization from hotmocha/sbalance, which will overwrite any changes that you have made since you forked the repository, and can not be recovered!!!
Synchronous operation will process in the background and will refresh the page when finishing processing. Please be patient.
#include <ares.h>
#include <sys/types.h>
#include <string.h>
#include <arpa/nameser.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "sblist.h"
#include "sbparsehost.h"
#include "sbalance.h"
#define SB_DNS_HASH_SLOTS 111
#define SB_DNS_TIMEOUT_TIME 2500 /* 5000ms */
#define SB_DNS_ARES_OPT ARES_OPT_TIMEOUTMS|ARES_OPT_TRIES
static struct hlist_head *hash_slots;
static struct list_head *wait_parse_list_head;
static struct list_head *parsing_list_head;
struct ares_options options;
static void callback_gethost(void *arg, int status, int timeouts, struct hostent *h);
static unsigned long RSHash(const char *str)
{
unsigned long a = 63689;
unsigned long b = 378551;
unsigned long hash = 0;
while(*str) {
hash = hash * a + (*str++);
a *= b;
}
return hash;
}
int sb_dns_init_env()
{
int i = 0;
hash_slots = (struct hlist_head*)(malloc( sizeof(struct hlist_head) * SB_DNS_HASH_SLOTS ));
if (hash_slots == NULL)
return SB_ERROR;
for (i = 0; i < SB_DNS_HASH_SLOTS; i++) {
INIT_HLIST_HEAD(&hash_slots[i]);
}
wait_parse_list_head = (struct list_head*)(malloc(sizeof(struct list_head)));
if (wait_parse_list_head == NULL) {
free(hash_slots);
return SB_ERROR;
}
INIT_LIST_HEAD(wait_parse_list_head);
parsing_list_head = (struct list_head*)(malloc(sizeof(struct list_head)));
if (wait_parse_list_head == NULL) {
free(hash_slots);
free(wait_parse_list_head);
return SB_ERROR;
}
INIT_LIST_HEAD(parsing_list_head);
options.timeout = SB_DNS_TIMEOUT_TIME;
options.tries = 2;
return SB_OK;
}
/* @RETURN 1. SB_NOTFOUND 2. SB_OK */
int sb_dns_modify_status(char *host, int new_status)
{
int slot_index;
struct hlist_head *hash_head;
slot_index = RSHash(host) % SB_DNS_HASH_SLOTS;
hash_head = &hash_slots[slot_index];
if (hash_head->first == NULL)
return SB_NOTFOUND;
else {
struct hlist_node *pos;
struct hlist_node *pre_pos = NULL;
struct sb_dns *type;
int cmp;
hlist_for_each_entry(type, pos, hash_head, hash_node) {
if ((cmp = strcmp(type->host, host)) == 0) {
type->status = new_status;
return SB_OK;
} else if (cmp > 0) {
return SB_NOTFOUND;
}
}
return SB_NOTFOUND;
}
}
void sb_dns_remove_session(struct sb_session *sess)
{
if (sess->dns_list_node.next != &sess->dns_list_node) {
list_del_init(&sess->dns_list_node);
}
}
/* @RETURN
1. SB_OK(find host's ip)
2. SB_AGAIN(a. not find host's ip, but add query request, b. find host, but the status is parsing)
3. SB_TIMEOUT(find host, but status is timeout) temp status, not possible status
4. SB_ERROR
*/
int sb_dns_query_host_ip(const char *host, struct sb_session *sess)
{
int rc;
struct sb_dns *new_sb_dns;
unsigned long hash_val;
int slot_index;
struct hlist_head *hash_head;
int flag = 0;
char *ip;
int len;
int i =0;
slot_index = RSHash(host) % SB_DNS_HASH_SLOTS;
hash_head = &hash_slots[slot_index];
ip = sess->server.net_address.ip;
len = sizeof(sess->server.net_address.ip);
if (hash_head->first == NULL) {
new_sb_dns = (struct sb_dns*)calloc(1, sizeof(struct sb_dns));
if (!new_sb_dns) {
return SB_ERROR;
}
/* new_sb_dns->timeout_time = sb_get_msec_timeout_time(SB_DNS_TIMEOUT); */
INIT_LIST_HEAD(&new_sb_dns->waiting_session_list);
list_add(&sess->dns_list_node, &new_sb_dns->waiting_session_list);
sess->dns = new_sb_dns;
strcpy(new_sb_dns->host, host);
rc = ares_init_options(&new_sb_dns->channel, &options, SB_DNS_ARES_OPT);
if (rc) {
return SB_ERROR;
}
ares_gethostbyname(new_sb_dns->channel, new_sb_dns->host, AF_INET,callback_gethost, new_sb_dns);
/* add to hash and wait list */
hlist_add_head(&new_sb_dns->hash_node, hash_head);
new_sb_dns->status = SB_DNS_STATUS_WAITING;
list_add(&new_sb_dns->list_node, wait_parse_list_head);
return SB_AGAIN;
}
else {
struct hlist_node *pos = NULL;
struct hlist_node *pre_pos = NULL;
struct sb_dns *type;
int cmp;
int ip_len;
hlist_for_each_entry(type, pos, hash_head, hash_node) {
if ((cmp = strcmp(type->host, host)) == 0) {
sess->dns = (struct sb_dns*)type;
if (type->status == SB_DNS_STATUS_OK) {
if ((ip_len = strlen(type->ip)) > len) {
return SB_ERROR;
} else {
memcpy(ip, type->ip, ip_len);
ip[ip_len] = '\0';
return SB_OK;
}
} else if (type->status == SB_DNS_STATUS_WAITING || type->status == SB_DNS_STATUS_PARSING) {
/* add the session to the waiting list for this dns request */
list_add(&sess->dns_list_node, &type->waiting_session_list);
return SB_AGAIN;
} else if (type->status == SB_DNS_STATUS_DESTORYED) {
list_add(&sess->dns_list_node, &type->waiting_session_list);
/* re-add to wait parsing list to request a parse */
rc = ares_init_options(&type->channel, &options, SB_DNS_ARES_OPT);
if (rc)
return SB_ERROR;
type->status = SB_DNS_STATUS_WAITING;
list_add(&type->list_node, wait_parse_list_head);
return SB_AGAIN;
} else {
FatalOutput("not possible status for sb_dns, bug need fix");
return SB_ERROR;
}
} else if (cmp > 0) {
new_sb_dns = (struct sb_dns*)calloc(1, sizeof(struct sb_dns));
if (!new_sb_dns)
return SB_ERROR;
INIT_LIST_HEAD(&new_sb_dns->waiting_session_list);
list_add(&sess->dns_list_node, &new_sb_dns->waiting_session_list);
sess->dns = new_sb_dns;
strcpy(new_sb_dns->host, host);
rc = ares_init_options(&new_sb_dns->channel, &options, SB_DNS_ARES_OPT);
if (rc)
return SB_ERROR;
ares_gethostbyname(new_sb_dns->channel, new_sb_dns->host, AF_INET,callback_gethost, new_sb_dns);
/* new_sb_dns->timeout_time = sb_get_msec_timeout_time(SB_DNS_TIMEOUT); */
hlist_add_before(&new_sb_dns->hash_node, pos);
new_sb_dns->status = SB_DNS_STATUS_WAITING;
list_add(&new_sb_dns->list_node, wait_parse_list_head);
return SB_AGAIN;
} else {
pre_pos = pos;
}
}
new_sb_dns = (struct sb_dns*)calloc(1, sizeof(struct sb_dns));
if (!new_sb_dns)
return SB_ERROR;
INIT_LIST_HEAD(&new_sb_dns->waiting_session_list);
list_add(&sess->dns_list_node, &new_sb_dns->waiting_session_list);
sess->dns = new_sb_dns;
strcpy(new_sb_dns->host, host);
rc = ares_init_options(&new_sb_dns->channel, &options, SB_DNS_ARES_OPT);
if (rc)
return SB_ERROR;
ares_gethostbyname(new_sb_dns->channel, new_sb_dns->host, AF_INET, callback_gethost, new_sb_dns);
/* new_sb_dns->timeout_time = sb_get_msec_timeout_time(SB_DNS_TIMEOUT); */
hlist_add_after(pre_pos, &new_sb_dns->hash_node);
new_sb_dns->status = SB_DNS_STATUS_WAITING;
list_add(&new_sb_dns->list_node, wait_parse_list_head);
return SB_AGAIN;
}
}
int sb_dns_reparse_host(struct sb_dns *dns, struct sb_session *sess)
{
int rc;
if (ares_init_options(&dns->channel, &options, SB_DNS_ARES_OPT)) {
return SB_ERROR;
}
dns->status = SB_DNS_STATUS_WAITING;
list_add(&dns->list_node, wait_parse_list_head);
list_add(&sess->dns_list_node, &dns->waiting_session_list);
return SB_OK;
}
static void callback_gethost(void *arg, int status, int timeouts, struct hostent *h)
{
struct sb_dns *dns;
char** pptr;
dns = (struct sb_dns*)arg;
if (h == NULL) {
if (status == ARES_ETIMEOUT)
dns->status = SB_DNS_STATUS_TIMEOUT;
else
dns->status = SB_DNS_STATUS_ERROR;
} else {
dns->status = SB_DNS_STATUS_OK;
for (pptr = h->h_addr_list; *pptr != NULL; pptr++) {
/* if (inet_ntop(h->h_addrtype, *pptr, dns->ip, sizeof(dns->ip) - 1)) */
if (inet_ntop(AF_INET, *pptr, dns->ip, sizeof(dns->ip) - 1)) { /* just use ipv4 */
return;
}
}
FatalOutput("inet_ntop not right %s", *pptr);
}
}
/* @RETURN 1. SB_ERROR 2. SB_OK */
int
sb_dns_process (struct sb_cycle_env *env)
{
fd_set readers, writers;
int nfds = 1;
FD_ZERO (&readers);
FD_ZERO (&writers);
int count;
struct sb_dns *pos, *n;
struct sb_session *sess_pos, *sess_n;
struct timeval maxtv = { 0, 500 }; /* 50ms */
int rc;
list_for_each_entry (pos, parsing_list_head, list_node)
{
nfds = ares_fds (pos->channel, &readers, &writers);
}
count = select (nfds, &readers, &writers, NULL, &maxtv);
if (count == -1)
{
return SB_ERROR;
}
list_for_each_entry_safe (pos, n, parsing_list_head, list_node)
{
ares_process (pos->channel, &readers, &writers);
if (pos->status != SB_DNS_STATUS_PARSING)
{
list_del_init (&pos->list_node);
/* do session's done callback */
list_for_each_entry_safe (sess_pos, sess_n,
&pos->waiting_session_list, dns_list_node)
{
sess_pos->sb_dns_request_done (env, sess_pos);
list_del_init (&sess_pos->dns_list_node);
}
/* destory channel */
ares_destroy (pos->channel);
if (pos->status != SB_DNS_STATUS_OK)
{
pos->status = SB_DNS_STATUS_DESTORYED;
}
pos->channel = NULL;
}
}
rc = SB_OK;
/* add wait_parse_list_head to parsing_list_head */
list_for_each_entry (pos, wait_parse_list_head, list_node)
{
pos->status = SB_DNS_STATUS_PARSING;
}
list_splice_init (wait_parse_list_head, parsing_list_head);
return rc;
}
int sb_dns_main()
{
int rc = 0;
rc = sb_dns_init_env();
if (rc) {
fprintf("init dns env failed\n");
return SB_ERROR;
}
while (1) {
/* 1. */
/* 2. ܽ */
sb_dns_process();
}
return SB_OK;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。