Update code, basic tests
This commit is contained in:
5
dns.c
5
dns.c
@@ -497,6 +497,11 @@ int _dns_encode_head(struct dns_context *context)
|
||||
|
||||
int fields = 0;
|
||||
fields |= (head->qr << 15) & QR_MASK;
|
||||
fields |= (head->opcode << 11) & OPCODE_MASK;
|
||||
fields |= (head->aa << 10) & AA_MASK;
|
||||
fields |= (head->tc << 9) & TC_MASK;
|
||||
fields |= (head->rd << 8) & RD_MASK;
|
||||
fields |= (head->ra << 7) & RA_MASK;
|
||||
fields |= (head->rcode << 0) & RCODE_MASK;
|
||||
dns_write_short(&context->ptr, fields);
|
||||
|
||||
|
||||
5
dns.h
5
dns.h
@@ -12,6 +12,11 @@
|
||||
#define DNS_IN_PACKSIZE (512 * 2)
|
||||
#define DNS_PACKSIZE (512 * 4)
|
||||
|
||||
typedef enum dns_qr {
|
||||
DNS_QR_QUERY = 0,
|
||||
DNS_QR_ANSWER = 1,
|
||||
}dns_qr;
|
||||
|
||||
typedef enum dns_rr_type {
|
||||
DNS_RRS_QD = 0,
|
||||
DNS_RRS_AN = 1,
|
||||
|
||||
120
dns_client.c
120
dns_client.c
@@ -108,13 +108,17 @@ static struct addrinfo *_dns_client_getaddr(const char *host, char *port, int ty
|
||||
{
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result = NULL;
|
||||
int ret = 0;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_protocol = protocol;
|
||||
if (getaddrinfo(host, port, &hints, &result) != 0) {
|
||||
fprintf(stderr, "get addr info failed. %s\n", strerror(errno));
|
||||
|
||||
ret = getaddrinfo(host, port, &hints, &result);
|
||||
if (ret != 0) {
|
||||
tlog(TLOG_ERROR, "get addr info failed. %s\n", gai_strerror(errno));
|
||||
tlog(TLOG_ERROR, "host = %s, port = %s, type = %d, protocol = %d", host, port, type, protocol);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -268,6 +272,11 @@ int dns_remove_server(char *server_ip, int port, dns_server_type_t server_type)
|
||||
int _dns_client_query_complete(struct dns_query_struct *query)
|
||||
{
|
||||
int ret = -1;
|
||||
if (atomic_inc_return(&query->notified) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tlog(TLOG_INFO, "call back result : %s", query->domain);
|
||||
if (query->callback) {
|
||||
ret = query->callback(query->domain, &query->result, query->user_ptr);
|
||||
}
|
||||
@@ -275,26 +284,35 @@ int _dns_client_query_complete(struct dns_query_struct *query)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void _dns_client_query_release(struct dns_query_struct *query, int locked)
|
||||
void _dns_client_query_release(struct dns_query_struct *query)
|
||||
{
|
||||
if (!atomic_dec_and_test(&query->refcnt)) {
|
||||
int refcnt = atomic_dec_return(&query->refcnt);
|
||||
if (refcnt) {
|
||||
if (refcnt < 0) {
|
||||
tlog(TLOG_ERROR, "BUG: refcnt is %d", refcnt);
|
||||
abort();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_dns_client_query_complete(query);
|
||||
memset(query, 0, sizeof(*query));
|
||||
free(query);
|
||||
}
|
||||
|
||||
void _dns_client_query_remove(struct dns_query_struct *query, int locked)
|
||||
{
|
||||
if (locked == 0) {
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
list_del(&query->dns_request_list);
|
||||
list_del_init(&query->dns_request_list);
|
||||
hash_del(&query->domain_node);
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
} else {
|
||||
list_del(&query->dns_request_list);
|
||||
list_del_init(&query->dns_request_list);
|
||||
hash_del(&query->domain_node);
|
||||
}
|
||||
if (atomic_inc_return(&query->notified) == 1) {
|
||||
_dns_client_query_complete(query);
|
||||
}
|
||||
memset(query, 0, sizeof(*query));
|
||||
free(query);
|
||||
|
||||
_dns_client_query_release(query);
|
||||
}
|
||||
|
||||
void _dns_client_query_get(struct dns_query_struct *query)
|
||||
@@ -311,6 +329,11 @@ void dns_client_ping_result(struct ping_host_struct *ping_host, const char *host
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == PING_RESULT_END) {
|
||||
_dns_client_query_release(query);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
|
||||
|
||||
switch (addr->sa_family) {
|
||||
@@ -340,6 +363,11 @@ void dns_client_ping_result(struct ping_host_struct *ping_host, const char *host
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (result == PING_RESULT_RESPONSE) {
|
||||
tlog(TLOG_INFO, "from %15s: seq=%d time=%d\n", host, seqno, rtt);
|
||||
} else {
|
||||
tlog(TLOG_INFO, "from %15s: seq=%d timeout\n", host, seqno);
|
||||
}
|
||||
|
||||
if (rtt < 100) {
|
||||
may_complete = 1;
|
||||
@@ -348,12 +376,8 @@ void dns_client_ping_result(struct ping_host_struct *ping_host, const char *host
|
||||
}
|
||||
|
||||
if (may_complete) {
|
||||
if (atomic_inc_return(&query->notified) == 1) {
|
||||
_dns_client_query_complete(query);
|
||||
}
|
||||
_dns_client_query_complete(query);
|
||||
}
|
||||
tlog(TLOG_INFO, "from %15s: seq=%d time=%d\n", host, seqno, rtt);
|
||||
_dns_client_query_release(query, 0);
|
||||
}
|
||||
|
||||
void _dns_client_period_run()
|
||||
@@ -364,9 +388,9 @@ void _dns_client_period_run()
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
list_for_each_entry_safe(query, tmp, &client.dns_request_list, dns_request_list)
|
||||
{
|
||||
if (now - query->send_tick > 500) {
|
||||
atomic_set(&query->dns_request_sent, -1);
|
||||
//_dns_client_query_release(query, 1);
|
||||
if (now - query->send_tick >= 2000) {
|
||||
_dns_client_query_complete(query);
|
||||
_dns_client_query_remove(query, 1);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
@@ -405,23 +429,23 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet)
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
struct dns_rrs *rrs = NULL;
|
||||
int ret = -1;
|
||||
int request_num = 0;
|
||||
|
||||
query = _dns_client_get_request(packet->head.id, domain);
|
||||
if (query == NULL) {
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
request_num = atomic_dec_return(&query->dns_request_sent);
|
||||
if (request_num < 0) {
|
||||
tlog(TLOG_ERROR, "send count is invalid, %d", request_num);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (packet->head.rcode != DNS_RC_NOERROR) {
|
||||
tlog(TLOG_ERROR, "inquery failed, %s, rcode = %d\n", name, packet->head.rcode);
|
||||
if (request_num == 0) {
|
||||
_dns_client_query_release(query, 0);
|
||||
_dns_client_query_remove(query, 0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -439,7 +463,7 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet)
|
||||
if (strncmp(name, domain, DNS_MAX_CNAME_LEN) == 0 || strncmp(alias, name, DNS_MAX_CNAME_LEN) == 0) {
|
||||
_dns_client_query_get(query);
|
||||
if (fast_ping_start(ip, 1, 500, dns_client_ping_result, query) == NULL) {
|
||||
_dns_client_query_release(query, 0);
|
||||
_dns_client_query_release(query);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -450,7 +474,7 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet)
|
||||
addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
|
||||
_dns_client_query_get(query);
|
||||
if (fast_ping_start(name, 1, 500, dns_client_ping_result, query) == NULL) {
|
||||
_dns_client_query_release(query, 0);
|
||||
_dns_client_query_release(query);
|
||||
}
|
||||
} break;
|
||||
case DNS_T_NS: {
|
||||
@@ -471,10 +495,10 @@ static int _dns_client_process_answer(char *domain, struct dns_packet *packet)
|
||||
}
|
||||
|
||||
if (request_num == 0) {
|
||||
_dns_client_query_release(query, 0);
|
||||
_dns_client_query_remove(query, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct sockaddr_storage *from, socklen_t from_len)
|
||||
@@ -513,7 +537,13 @@ static int _dns_client_recv(unsigned char *inpacket, int inpacket_len, struct so
|
||||
tlog(TLOG_DEBUG, "domain: %s qtype: %d qclass: %d\n", name, qtype, qclass);
|
||||
}
|
||||
|
||||
return _dns_client_process_answer(name, packet);
|
||||
if (_dns_client_process_answer(name, packet) != 0) {
|
||||
char host[DNS_HOSTNAME_LEN];
|
||||
tlog(TLOG_ERROR, "process answer failed, %s from %s", name, gethost_by_addr(host, (struct sockaddr *)from, from_len));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long now)
|
||||
@@ -526,7 +556,7 @@ static int _dns_client_process(struct dns_query_struct *dns_query, unsigned long
|
||||
|
||||
len = recvfrom(client.udp, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len);
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "recvfrom failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "recvfrom failed, %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -600,6 +630,7 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
||||
pthread_mutex_lock(&client.server_list_lock);
|
||||
list_for_each_entry_safe(server_info, tmp, &client.dns_server_list, list)
|
||||
{
|
||||
atomic_inc(&query->dns_request_sent);
|
||||
switch (server_info->type) {
|
||||
case DNS_SERVER_UDP:
|
||||
ret = _dns_client_send_udp(server_info, packet, len);
|
||||
@@ -610,11 +641,9 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet,
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
atomic_dec(&query->dns_request_sent);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
atomic_inc(&query->dns_request_sent);
|
||||
}
|
||||
pthread_mutex_unlock(&client.server_list_lock);
|
||||
return 0;
|
||||
@@ -629,18 +658,19 @@ static int _dns_client_send_query(struct dns_query_struct *query, char *doamin)
|
||||
|
||||
struct dns_head head;
|
||||
memset(&head, 0, sizeof(head));
|
||||
head.rcode = 0;
|
||||
head.qr = DNS_OP_QUERY;
|
||||
head.id = query->sid;
|
||||
head.qr = DNS_QR_QUERY;
|
||||
head.opcode = DNS_OP_QUERY;
|
||||
head.aa = 1;
|
||||
head.rd = 1;
|
||||
head.ra = 0;
|
||||
head.id = query->sid;
|
||||
head.ra = 1;
|
||||
head.rcode = 0;
|
||||
|
||||
dns_packet_init(packet, DNS_PACKSIZE, &head);
|
||||
dns_add_domain(packet, doamin, DNS_T_A, DNS_C_IN);
|
||||
encode_len = dns_encode(inpacket, DNS_IN_PACKSIZE, packet);
|
||||
if (encode_len <= 0) {
|
||||
printf("encode query failed.\n");
|
||||
tlog(TLOG_ERROR, "encode query failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -689,7 +719,7 @@ int dns_client_query(char *domain, dns_client_callback callback, void *user_ptr)
|
||||
errout_del_list:
|
||||
atomic_dec(&query->refcnt);
|
||||
pthread_mutex_lock(&client.domain_map_lock);
|
||||
list_del(&query->dns_request_list);
|
||||
list_del_init(&query->dns_request_list);
|
||||
hash_del(&query->domain_node);
|
||||
pthread_mutex_unlock(&client.domain_map_lock);
|
||||
errout:
|
||||
@@ -715,7 +745,7 @@ static struct addrinfo *_dns_server_getaddr(const char *host, const char *port,
|
||||
hints.ai_protocol = protocol;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
if (getaddrinfo(host, port, &hints, &result) != 0) {
|
||||
fprintf(stderr, "get addr info failed. %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -733,7 +763,7 @@ int dns_client_start(void)
|
||||
event.events = EPOLLIN;
|
||||
event.data.fd = client.udp;
|
||||
if (epoll_ctl(client.epoll_fd, EPOLL_CTL_ADD, client.udp, &event) != 0) {
|
||||
fprintf(stderr, "epoll ctl failed.");
|
||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -747,13 +777,13 @@ int dns_client_socket(void)
|
||||
|
||||
gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0);
|
||||
if (gai == NULL) {
|
||||
fprintf(stderr, "get address failed.\n");
|
||||
tlog(TLOG_ERROR, "get address failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "create socket failed.\n");
|
||||
tlog(TLOG_ERROR, "create socket failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -812,13 +842,13 @@ int dns_client_init()
|
||||
|
||||
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollfd < 0) {
|
||||
fprintf(stderr, "create epoll failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "create epoll failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
fd = dns_client_socket();
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "create client socket failed.\n");
|
||||
tlog(TLOG_ERROR, "create client socket failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -835,12 +865,12 @@ int dns_client_init()
|
||||
client.udp = fd;
|
||||
ret = pthread_create(&client.tid, &attr, _dns_client_work, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "create client work thread failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "create client work thread failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (dns_client_start()) {
|
||||
fprintf(stderr, "start client failed.\n");
|
||||
tlog(TLOG_ERROR, "start client failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
||||
40
dns_server.c
40
dns_server.c
@@ -187,9 +187,11 @@ static int _dns_reply(struct dns_request *request)
|
||||
|
||||
memset(&head, 0, sizeof(head));
|
||||
head.id = request->id;
|
||||
head.qr = DNS_OP_IQUERY;
|
||||
head.qr = DNS_QR_ANSWER;
|
||||
head.opcode = DNS_OP_QUERY;
|
||||
head.rd = 1;
|
||||
head.ra = 0;
|
||||
head.rcode = DNS_RC_NOERROR;
|
||||
ret = dns_packet_init(packet, DNS_PACKSIZE, &head);
|
||||
if (ret != 0) {
|
||||
return -1;
|
||||
@@ -223,10 +225,20 @@ static int dns_server_resolve_callback(char *domain, struct dns_result *result,
|
||||
{
|
||||
struct dns_request *request = user_ptr;
|
||||
|
||||
int refcnt;
|
||||
|
||||
if (user_ptr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
refcnt = atomic_dec_return(&request->refcnt);
|
||||
if (refcnt) {
|
||||
if (refcnt < 0) {
|
||||
abort();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(request->ipv4_addr, result->addr_ipv4, 4);
|
||||
strncpy(request->alias, result->alias, DNS_MAX_CNAME_LEN);
|
||||
// memcpy(request->ipv6_addr, result->addr_ipv6, 16);
|
||||
@@ -239,10 +251,6 @@ static int dns_server_resolve_callback(char *domain, struct dns_result *result,
|
||||
request->ipv4_addr[3]);
|
||||
_dns_reply(request);
|
||||
|
||||
if (!atomic_dec_and_test(&request->refcnt)) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
memset(request, 0, sizeof(*request));
|
||||
free(request);
|
||||
@@ -271,7 +279,7 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (packet->head.qr != DNS_OP_QUERY) {
|
||||
if (packet->head.qr != DNS_QR_QUERY) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -333,7 +341,7 @@ static int _dns_server_process(unsigned long now)
|
||||
|
||||
len = recvfrom(server.fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len);
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "recvfrom failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "recvfrom failed, %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -376,7 +384,7 @@ int dns_server_run(void)
|
||||
for (i = 0; i < num; i++) {
|
||||
struct epoll_event *event = &events[i];
|
||||
if (event->data.fd != server.fd) {
|
||||
fprintf(stderr, "invalid fd\n");
|
||||
tlog(TLOG_ERROR, "invalid fd\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -401,7 +409,7 @@ static struct addrinfo *_dns_server_getaddr(const char *host, const char *port,
|
||||
hints.ai_protocol = protocol;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
if (getaddrinfo(host, port, &hints, &result) != 0) {
|
||||
fprintf(stderr, "get addr info failed. %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -419,7 +427,7 @@ int dns_server_start(void)
|
||||
event.events = EPOLLIN;
|
||||
event.data.fd = server.fd;
|
||||
if (epoll_ctl(server.epoll_fd, EPOLL_CTL_ADD, server.fd, &event) != 0) {
|
||||
fprintf(stderr, "epoll ctl failed.");
|
||||
tlog(TLOG_ERROR, "epoll ctl failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -433,18 +441,18 @@ int dns_server_socket(void)
|
||||
|
||||
gai = _dns_server_getaddr(NULL, "53", SOCK_DGRAM, 0);
|
||||
if (gai == NULL) {
|
||||
fprintf(stderr, "get address failed.\n");
|
||||
tlog(TLOG_ERROR, "get address failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "create socket failed.\n");
|
||||
tlog(TLOG_ERROR, "create socket failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (bind(fd, gai->ai_addr, gai->ai_addrlen) != 0) {
|
||||
fprintf(stderr, "bind failed.\n");
|
||||
tlog(TLOG_ERROR, "bind failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -478,13 +486,13 @@ int dns_server_init(void)
|
||||
|
||||
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollfd < 0) {
|
||||
fprintf(stderr, "create epoll failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "create epoll failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
fd = dns_server_socket();
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "create server socket failed.\n");
|
||||
tlog(TLOG_ERROR, "create server socket failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -495,7 +503,7 @@ int dns_server_init(void)
|
||||
server.run = 1;
|
||||
|
||||
if (dns_server_start() != 0) {
|
||||
fprintf(stderr, "start service failed.\n");
|
||||
tlog(TLOG_ERROR, "start service failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
||||
73
fast_ping.c
73
fast_ping.c
@@ -187,7 +187,7 @@ static struct addrinfo *_fast_ping_getaddr(const char *host, int type, int proto
|
||||
hints.ai_socktype = type;
|
||||
hints.ai_protocol = protocol;
|
||||
if (getaddrinfo(host, NULL, &hints, &result) != 0) {
|
||||
fprintf(stderr, "get addr info failed. %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ static int _fast_ping_getdomain(const char *host)
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
if (getaddrinfo(host, NULL, &hints, &result) != 0) {
|
||||
fprintf(stderr, "get addr info failed. %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "get addr info failed. %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -235,8 +235,8 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host)
|
||||
{
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
if (atomic_dec_and_test(&ping_host->ref)) {
|
||||
hlist_del(&ping_host->host_node);
|
||||
hlist_del(&ping_host->addr_node);
|
||||
hash_del(&ping_host->host_node);
|
||||
hash_del(&ping_host->addr_node);
|
||||
} else {
|
||||
ping_host = NULL;
|
||||
}
|
||||
@@ -252,8 +252,8 @@ static void _fast_ping_host_put(struct ping_host_struct *ping_host)
|
||||
static void _fast_ping_host_put_locked(struct ping_host_struct *ping_host)
|
||||
{
|
||||
if (atomic_dec_and_test(&ping_host->ref)) {
|
||||
hlist_del(&ping_host->host_node);
|
||||
hlist_del(&ping_host->addr_node);
|
||||
hash_del(&ping_host->host_node);
|
||||
hash_del(&ping_host->addr_node);
|
||||
} else {
|
||||
ping_host = NULL;
|
||||
}
|
||||
@@ -262,6 +262,12 @@ static void _fast_ping_host_put_locked(struct ping_host_struct *ping_host)
|
||||
return;
|
||||
}
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_END, &ping_host->addr, ping_host->addr_len, ping_host->seq, &tv, ping_host->userptr);
|
||||
|
||||
free(ping_host);
|
||||
}
|
||||
|
||||
@@ -286,7 +292,7 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host)
|
||||
|
||||
len = sendto(ping_host->fd, &ping_host->packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
||||
if (len < 0 || len != sizeof(struct fast_ping_packet)) {
|
||||
fprintf(stderr, "sendto %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "sendto %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -317,7 +323,7 @@ static int _fast_ping_sendping_v4(struct ping_host_struct *ping_host)
|
||||
|
||||
len = sendto(ping_host->fd, packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len);
|
||||
if (len < 0 || len != sizeof(struct fast_ping_packet)) {
|
||||
fprintf(stderr, "sendto %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "sendto %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -337,13 +343,13 @@ static int _fast_ping_sendping(struct ping_host_struct *ping_host)
|
||||
ret = _fast_ping_sendping_v6(ping_host);
|
||||
}
|
||||
|
||||
ping_host->send = 1;
|
||||
gettimeofday(&ping_host->last, 0);
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ping_host->send = 1;
|
||||
gettimeofday(&ping_host->last, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -352,12 +358,14 @@ static int _fast_ping_create_sock(FAST_PING_TYPE type)
|
||||
int fd = -1;
|
||||
struct ping_host_struct *icmp_host = NULL;
|
||||
struct epoll_event event;
|
||||
int buffsize = 64 * 1024;
|
||||
socklen_t optlen = sizeof(buffsize);
|
||||
|
||||
switch (type) {
|
||||
case FAST_PING_ICMP:
|
||||
fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "create icmp socket failed.\n");
|
||||
tlog(TLOG_ERROR, "create icmp socket failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
_fast_ping_install_filter_v4(fd);
|
||||
@@ -366,7 +374,7 @@ static int _fast_ping_create_sock(FAST_PING_TYPE type)
|
||||
case FAST_PING_ICMP6:
|
||||
fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "create icmp socket failed.\n");
|
||||
tlog(TLOG_ERROR, "create icmp socket failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
_fast_ping_install_filter_v6(fd);
|
||||
@@ -376,6 +384,9 @@ static int _fast_ping_create_sock(FAST_PING_TYPE type)
|
||||
return -1;
|
||||
}
|
||||
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&buffsize, optlen);
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char *)&buffsize, optlen);
|
||||
|
||||
event.events = EPOLLIN;
|
||||
event.data.ptr = icmp_host;
|
||||
if (epoll_ctl(ping.epoll_fd, EPOLL_CTL_ADD, fd, &event) != 0) {
|
||||
@@ -435,9 +446,9 @@ void fast_ping_print_result(struct ping_host_struct *ping_host, const char *host
|
||||
{
|
||||
if (result == PING_RESULT_RESPONSE) {
|
||||
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
||||
printf("from %15s: seq=%d time=%.3f\n", host, seqno, rtt);
|
||||
tlog(TLOG_INFO, "from %15s: seq=%d time=%.3f\n", host, seqno, rtt);
|
||||
} else if (result == PING_RESULT_TIMEOUT) {
|
||||
printf("from %15s: seq=%d timeout\n", host, seqno);
|
||||
tlog(TLOG_INFO, "from %15s: seq=%d timeout\n", host, seqno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,6 +519,8 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int timeou
|
||||
}
|
||||
memcpy(&ping_host->addr, gai->ai_addr, gai->ai_addrlen);
|
||||
|
||||
_fast_ping_sendping(ping_host);
|
||||
|
||||
hostkey = hash_string(ping_host->host);
|
||||
addrkey = jhash(&ping_host->addr, ping_host->addr_len, 0);
|
||||
addrkey = jhash(&ping_host->sid, sizeof(ping_host->sid), addrkey);
|
||||
@@ -519,7 +532,6 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int timeou
|
||||
|
||||
freeaddrinfo(gai);
|
||||
|
||||
_fast_ping_sendping(ping_host);
|
||||
return ping_host;
|
||||
errout:
|
||||
if (fd > 0) {
|
||||
@@ -653,14 +665,14 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
|
||||
len = recvfrom(ping_host->fd, inpacket, sizeof(inpacket), 0, (struct sockaddr *)&from, (socklen_t *)&from_len);
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "recvfrom failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "recvfrom failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
packet = _fast_ping_recv_packet(ping_host, inpacket, len, now);
|
||||
if (packet == NULL) {
|
||||
char name[PING_MAX_HOSTLEN];
|
||||
tlog(TLOG_ERROR, "recv ping packet from %s failed.", gethost_by_addr(name, (struct sockaddr *)&from, from_len));
|
||||
tlog(TLOG_DEBUG, "recv ping packet from %s failed.", gethost_by_addr(name, (struct sockaddr *)&from, from_len));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -676,6 +688,7 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&ping.map_lock);
|
||||
|
||||
if (recv_ping_host == NULL) {
|
||||
@@ -695,9 +708,10 @@ static int _fast_ping_process_icmp(struct ping_host_struct *ping_host, struct ti
|
||||
|
||||
recv_ping_host->send = 0;
|
||||
|
||||
if (recv_ping_host->count == 0) {
|
||||
if (recv_ping_host->count == 1) {
|
||||
_fast_ping_host_put(recv_ping_host);
|
||||
}
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
return -1;
|
||||
@@ -726,7 +740,7 @@ static void _fast_ping_period_run()
|
||||
int i = 0;
|
||||
struct timeval now;
|
||||
struct timeval interval;
|
||||
uint64_t millisecond;
|
||||
int64_t millisecond;
|
||||
gettimeofday(&now, 0);
|
||||
|
||||
pthread_mutex_lock(&ping.map_lock);
|
||||
@@ -735,7 +749,7 @@ static void _fast_ping_period_run()
|
||||
interval = now;
|
||||
tv_sub(&interval, &ping_host->last);
|
||||
millisecond = interval.tv_sec * 1000 + interval.tv_usec / 1000;
|
||||
if (millisecond > ping_host->timeout && ping_host->send == 1) {
|
||||
if (millisecond >= ping_host->timeout && ping_host->send == 1) {
|
||||
ping_host->ping_callback(ping_host, ping_host->host, PING_RESULT_TIMEOUT, &ping_host->addr, ping_host->addr_len, ping_host->seq, &interval,
|
||||
ping_host->userptr);
|
||||
ping_host->send = 0;
|
||||
@@ -744,13 +758,16 @@ static void _fast_ping_period_run()
|
||||
if (millisecond < ping_host->interval) {
|
||||
continue;
|
||||
}
|
||||
if (ping_host->count >= 0) {
|
||||
|
||||
if (ping_host->count > 0) {
|
||||
if (ping_host->count == 1) {
|
||||
hash_del(&ping_host->host_node);
|
||||
hash_del(&ping_host->addr_node);
|
||||
_fast_ping_host_put_locked(ping_host);
|
||||
continue;
|
||||
}
|
||||
ping_host->count--;
|
||||
}
|
||||
if (ping_host->count == 0) {
|
||||
_fast_ping_host_put_locked(ping_host);
|
||||
continue;
|
||||
}
|
||||
|
||||
_fast_ping_sendping(ping_host);
|
||||
}
|
||||
@@ -817,7 +834,7 @@ int fast_ping_init()
|
||||
|
||||
epollfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epollfd < 0) {
|
||||
fprintf(stderr, "create epoll failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "create epoll failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -830,7 +847,7 @@ int fast_ping_init()
|
||||
ping.run = 1;
|
||||
ret = pthread_create(&ping.tid, &attr, _fast_ping_work, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "create ping work thread failed, %s\n", strerror(errno));
|
||||
tlog(TLOG_ERROR, "create ping work thread failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
PING_RESULT_RESPONSE = 1,
|
||||
PING_RESULT_TIMEOUT = 2,
|
||||
PING_RESULT_END = 3,
|
||||
} FAST_PING_RESULT;
|
||||
|
||||
struct ping_host_struct;
|
||||
|
||||
@@ -99,7 +99,7 @@ static inline void atomic_dec( atomic_t *v )
|
||||
*/
|
||||
static inline int atomic_inc_return( atomic_t *v )
|
||||
{
|
||||
return __sync_fetch_and_add(&v->counter, 1);
|
||||
return __sync_add_and_fetch(&v->counter, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +111,7 @@ static inline int atomic_inc_return( atomic_t *v )
|
||||
*/
|
||||
static inline int atomic_dec_return( atomic_t *v )
|
||||
{
|
||||
return __sync_fetch_and_sub(&v->counter, 1);
|
||||
return __sync_sub_and_fetch(&v->counter, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
44
smartdns.c
44
smartdns.c
@@ -22,9 +22,26 @@
|
||||
#include "hashtable.h"
|
||||
#include "list.h"
|
||||
#include "tlog.h"
|
||||
#include "atomic.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
atomic_t r = ATOMIC_INIT(0);
|
||||
|
||||
void print_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno,
|
||||
struct timeval *tv, void *userptr)
|
||||
{
|
||||
atomic_inc(&r);
|
||||
#if 0
|
||||
if (result == PING_RESULT_RESPONSE) {
|
||||
double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0;
|
||||
printf("from %15s: seq=%d time=%.3f\n", host, seqno, rtt);
|
||||
} else if (result == PING_RESULT_TIMEOUT) {
|
||||
printf("from %15s: seq=%d timeout\n", host, seqno);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int smartdns_init()
|
||||
{
|
||||
int ret;
|
||||
@@ -61,7 +78,32 @@ int smartdns_init()
|
||||
dns_add_server("193.112.15.186", 53, DNS_SERVER_UDP);
|
||||
dns_add_server("202.141.178.13", 5353, DNS_SERVER_UDP);
|
||||
dns_add_server("208.67.222.222", 5353, DNS_SERVER_UDP);
|
||||
|
||||
dns_add_server("77.88.8.8", 53, DNS_SERVER_UDP);
|
||||
dns_add_server("202.141.162.123", 53, DNS_SERVER_UDP);
|
||||
dns_add_server("101.132.183.99", 53, DNS_SERVER_UDP);
|
||||
|
||||
// int i = 0;
|
||||
// for(i = 0; i < 10; i++)
|
||||
// {
|
||||
// fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL);
|
||||
// fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL);
|
||||
// }
|
||||
|
||||
// sleep(2);
|
||||
// printf("i = %d, n = %d\n", i, atomic_read(&r));
|
||||
|
||||
fast_ping_start("192.168.1.1", 10, 1000, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
errout:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user