acl/app/jaws/global/dns_server.c

272 lines
7.0 KiB
C
Raw Normal View History

2014-11-19 00:25:21 +08:00
#include "lib_acl.h"
#include "sys_patch.h"
#ifdef ACL_BCB_COMPILER
#pragma hdrstop
#endif
#include "dns.h"
#define MSG_SEND acl_msgio_send
/* DNS<4E><53>ѯ<EFBFBD>߳<EFBFBD><DFB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̷߳<DFB3><CCB7><EFBFBD>IO<49><4F>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>̶߳<DFB3>Ҫ<EFBFBD><D2AA>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> */
static void reply_lookup_msg(DNS_CTX *dns_ctx, DNS_SERVER *dns)
{
const char *myname = "reply_lookup_msg";
/* <20><><EFBFBD><EFBFBD> */
acl_pthread_mutex_lock(&dns->lock);
/* <20><><EFBFBD><EFBFBD><EFBFBD>̷߳<DFB3><CCB7><EFBFBD>DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ */
if (MSG_SEND(dns_ctx->mio, DNS_MSG_LOOKUP_RESULT, dns_ctx, sizeof(DNS_CTX)) < 0) {
acl_msg_error("%s: send msg error, domain(%s)", myname, dns_ctx->domain_key);
}
/* <20><><EFBFBD><EFBFBD> */
acl_pthread_mutex_unlock(&dns->lock);
/* <20>ͷ<EFBFBD><CDB7><EFBFBD> msg_lookup <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD> */
acl_myfree(dns_ctx);
}
/* DNS<4E><53>ѯ<EFBFBD>̣߳<DFB3><CCA3>鵽DNS<4E><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>IO<49><4F>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4>ݸ<EFBFBD><DDB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD>̵߳<DFB3><CCB5><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD> */
static void lookup_thread(void *arg)
{
const char *myname = "lookup_thread";
#ifdef USE_THREAD_POOL
DNS_CTX *dns_ctx = (DNS_CTX *) arg;
DNS_SERVER *dns = dns_ctx->dns;
#else
DNS_CTX *dns_ctx = (DNS_CTX *) arg;
DNS_SERVER *dns = dns_ctx->dns;
#endif
int error = 0, n, i;
dns_ctx->dns_db = acl_gethostbyname(dns_ctx->domain_key, &error);
if (dns_ctx->dns_db == NULL) {
acl_msg_error("%s: gethostbyname error(%s), domain(%s)",
myname, acl_netdb_strerror(error), dns_ctx->domain_key);
dns_ctx->ip_cnt = 0;
reply_lookup_msg(dns_ctx, dns);
return;
}
n = acl_netdb_size(dns_ctx->dns_db);
dns_ctx->ip_cnt = n > DNS_IP_MAX ? DNS_IP_MAX : n;
for (i = 0; i < dns_ctx->ip_cnt; i++) {
snprintf(dns_ctx->ip[i], sizeof(dns_ctx->ip[i]), "%s",
acl_netdb_index_ip(dns_ctx->dns_db, i));
dns_ctx->port[i] = 0; /* <20><><EFBFBD><EFBFBD>DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϵĶ˿ں<CBBF> */
}
reply_lookup_msg(dns_ctx, dns);
}
/* <20><><EFBFBD>߳<EFBFBD><DFB3><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD>߳<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DNS<4E>߳̽<DFB3><CCBD><EFBFBD>DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
static int msg_lookup(int msg_type acl_unused, ACL_MSGIO *mio,
const ACL_MSGIO_INFO *info, void *arg)
{
DNS_CTX *dns_ctx;
dns_ctx = (DNS_CTX *) acl_mycalloc(1, sizeof(DNS_CTX));
memcpy(dns_ctx, acl_vstring_str(info->body.buf),
ACL_VSTRING_LEN(info->body.buf));
/* <20><><EFBFBD><EFBFBD>DNS<4E><53><EFBFBD><EFBFBD> */
dns_ctx->dns = (DNS_SERVER *) arg;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳߳<DFB3><CCB3>еIJ<D0B5>ѯ<EFBFBD>߳<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD>˾<EFBFBD><CBBE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2>֪ͨ
* <EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><EFBFBD>й<EFBFBD>DNS<EFBFBD>IJ<EFBFBD>ѯ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
dns_ctx->mio = mio;
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳̽<DFB3><CCBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽDNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
#ifdef USE_THREAD_POOL
acl_pthread_pool_add(dns_ctx->dns->wq, lookup_thread, dns_ctx);
#else
lookup_thread(dns_ctx);
#endif
return (1);
}
/* <20><><EFBFBD>߳<EFBFBD><DFB3><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD>߳<EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD>˺<EFBFBD><CBBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DNS<4E><53>ѯ<EFBFBD>̷߳<DFB3><CCB7>͵<EFBFBD>DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ */
static int msg_lookup_result(int msg_type acl_unused, ACL_MSGIO *mio acl_unused,
const ACL_MSGIO_INFO *info, void *arg)
{
DNS_CTX *dns_ctx;
DNS_SERVER *dns = (DNS_SERVER*) arg;
/* <20><><EFBFBD><EFBFBD>DNS<4E><53>ѯ<EFBFBD>̵߳Ľ<CCB5><C4BD><EFBFBD><EFBFBD><EFBFBD>Ϣ */
dns_ctx = (DNS_CTX *) acl_vstring_str(info->body.buf);
/* <20><><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>DNS<4E><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
if (dns_ctx->ip_cnt > 0)
dns_cache_push(dns->dns_cache, dns_ctx->dns_db);
/* <20>ͷ<EFBFBD><CDB7><EFBFBD> lookup_thread <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> dns_db <20><><EFBFBD><EFBFBD> */
if (dns_ctx->dns_db)
acl_netdb_free(dns_ctx->dns_db);
dns_ctx->dns_db = NULL;
/* <20>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
dns_ctx->callback(dns_ctx);
return (1);
}
/* <20><><EFBFBD><EFBFBD>DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
DNS_SERVER *dns_server_create(ACL_AIO *aio, int timeout)
{
const char *myname = "dns_server_create";
DNS_SERVER *dns;
int max_threads = 200;
int idle_timeout = 60 /* <20><>ֵĿǰ<C4BF><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD>Ҫ<EFBFBD>޸<EFBFBD>һ<EFBFBD><D2BB>ACL<43><4C><EFBFBD>ſ<EFBFBD> */;
if (aio == NULL)
acl_msg_fatal("%s(%d): aio null", myname, __LINE__);
/* acl <20><><EFBFBD><EFBFBD>DNS<4E><53><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ѯ<EFBFBD>̳߳ض<CCB3>Ҫ<EFBFBD><D2AA><EFBFBD>ʸ<EFBFBD>ͬһ<CDAC><D2BB>Դ
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> acl <EFBFBD><EFBFBD>DNS<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD>Ϊ60<EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD>Ҳ<EFBFBD>л<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD>Ѿ<EFBFBD>ʵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>DNS<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><EFBFBD><EFBFBD>ҪACL<EFBFBD><EFBFBD><EFBFBD><EFBFBD>DNS<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* acl_netdb_cache_init(60 , 1);
*/
dns = (DNS_SERVER *) acl_mycalloc(1, sizeof(DNS_SERVER));
dns->aio = aio;
/* <20><><EFBFBD>ص<EFBFBD>DNS<4E><53><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊֻ<CEAA><D6BB>һ<EFBFBD><D2BB><EFBFBD>̷߳<DFB3><CCB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ */
dns->dns_cache = dns_cache_create(timeout, 0);
/* <20><><EFBFBD><EFBFBD> IO <20>¼<EFBFBD><C2BC><EFBFBD>Ϣ */
dns->listener = acl_msgio_listen(aio, NULL);
if (dns->listener == NULL)
acl_msg_fatal("%s: listen error", myname);
/* ע<><D7A2> IO <20>¼<EFBFBD><C2BC><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD><DABC><EFBFBD><EFBFBD>µIJ<C2B5>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
acl_msgio_listen_reg(dns->listener, DNS_MSG_LOOKUP, msg_lookup, dns, 1);
acl_msgio_addr(dns->listener, dns->addr, sizeof(dns->addr));
dns->mio = acl_msgio_connect(aio, dns->addr, 0);
if (dns->mio == NULL)
acl_msg_fatal("%s: connect server(%s) error", myname, dns->addr);
/* ע<><D7A2> IO <20>¼<EFBFBD><C2BC><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD>̷߳<DFB3><CCB7>ز<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
acl_msgio_reg(dns->mio, DNS_MSG_LOOKUP_RESULT, msg_lookup_result, dns);
/* <20><>ʼ<EFBFBD><CABC>DNS<4E><53><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD><DFB3><EFBFBD> */
acl_pthread_mutex_init(&dns->lock, NULL);
/* <20><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳̲߳<CCB3>ѯDNS(<28><>Ϊ<EFBFBD><CEAA>ѯDNS<4E><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>ѯ) */
#ifdef USE_THREAD_POOL
dns->wq = acl_thread_pool_create(max_threads, idle_timeout);
#endif
return (dns);
}
/* <20>ر<EFBFBD>DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
void dns_server_close(DNS_SERVER *dns)
{
acl_msgio_close(dns->listener);
acl_pthread_pool_destroy(dns->wq);
acl_myfree(dns);
}
void dns_server_static_add(DNS_SERVER *dns, const char *map, const char *delim, int def_port)
{
ACL_DNS_DB *dns_db = NULL;
ACL_ARGV *argv = NULL;
char *ptr;
int i, port;
#undef RETURN
#define RETURN do { \
if (argv != NULL) \
acl_argv_free(argv); \
if (dns_db != NULL) \
acl_netdb_free(dns_db); \
return; \
} while (0)
argv = acl_argv_split(map, delim);
if (argv == NULL)
RETURN;
if (argv->argc < 2)
RETURN;
dns_db = acl_netdb_new(argv->argv[0]);
for (i = 1; i < argv->argc; i++) {
ptr = strchr(argv->argv[i], ':');
if (ptr != NULL) {
*ptr++ = 0;
port = atoi(ptr);
if (port <= 0)
port = def_port;
} else {
port = def_port;
}
acl_netdb_add_addr(dns_db, argv->argv[i], port);
}
/* <20><><EFBFBD>ó<EFBFBD>ʱʱ<CAB1><CAB1>Ϊ0<CEAA>Ӷ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ */
dns_cache_push_one(dns->dns_cache, dns_db, 0);
RETURN;
}
/* <20><>ʼ<EFBFBD><CABC>ѯij<D1AF><C4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
int dns_server_lookup(DNS_SERVER *dns, const DNS_CTX *ctx)
{
const char *myname = "dns_server_lookup";
ACL_MSGIO *mio = dns->mio;
DNS_CTX dns_ctx;
ACL_DNS_DB *dns_db;
/* ֻ<><D6BB><EFBFBD>Բ<EFBFBD><D4B2>ô˷<C3B4>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>Ϊ<EFBFBD>˱<EFBFBD>֤ dns_server_lookup <20><><EFBFBD><EFBFBD> ctxΪ const <20><><EFBFBD><EFBFBD> */
memcpy(&dns_ctx, ctx, sizeof(dns_ctx));
/* <20>Ȳ<EFBFBD>ѯDNS<4E><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
dns_db = dns_cache_lookup(dns->dns_cache, ctx->domain_key);
if (dns_db) {
ACL_ITER iter;
int i = 0;
acl_foreach(iter, dns_db) {
const ACL_HOST_INFO *info;
info = (const ACL_HOST_INFO*) iter.data;
ACL_SAFE_STRNCPY(dns_ctx.ip[i], info->ip,
sizeof(dns_ctx.ip[i]));
dns_ctx.port[i++] = info->hport;
dns_ctx.ip_cnt++;
if (dns_ctx.ip_cnt >= DNS_IP_MAX)
break;
}
/* <20><><EFBFBD>Ѿ<EFBFBD>DNS<4E><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>Ӵ<EFBFBD><D3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD><D8B5><EFBFBD><EFBFBD><EFBFBD> */
dns_ctx.callback(&dns_ctx);
/* <20>˴<EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ͷŸö<C5B8><C3B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ dns_cache_lookup <20><><EFBFBD>صĶ<D8B5><C4B6><EFBFBD>Ϊ<EFBFBD><CEAA>̬
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(acl_netdb_clone)
*/
acl_netdb_free(dns_db);
return (0);
}
/* <20><><EFBFBD><EFBFBD>ѯ<EFBFBD>̳߳ط<CCB3><D8B7>Ͳ<EFBFBD>ѯָ<D1AF><D6B8> */
if (MSG_SEND(mio, DNS_MSG_LOOKUP, &dns_ctx, sizeof(DNS_CTX)) < 0) {
acl_msg_error("%s: send msg error, domain(%s)",
myname, dns_ctx.domain_key);
return (-1);
}
return (0);
}