From 75ebf7ce4932e7dac06d5359174be974ba86bbfc Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Sun, 27 May 2018 22:57:54 +0800 Subject: [PATCH] Update code, basic tests --- dns.c | 5 ++ dns.h | 5 ++ dns_client.c | 120 +++++++++++++++++++++++++++++------------------ dns_server.c | 40 +++++++++------- fast_ping.c | 73 +++++++++++++++++----------- fast_ping.h | 1 + include/atomic.h | 4 +- smartdns.c | 44 ++++++++++++++++- 8 files changed, 200 insertions(+), 92 deletions(-) diff --git a/dns.c b/dns.c index d2758d9..95abf81 100644 --- a/dns.c +++ b/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); diff --git a/dns.h b/dns.h index 23adf9a..6801903 100644 --- a/dns.h +++ b/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, diff --git a/dns_client.c b/dns_client.c index cdd479e..55e6443 100644 --- a/dns_client.c +++ b/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; } diff --git a/dns_server.c b/dns_server.c index 0bda1f2..296af83 100644 --- a/dns_server.c +++ b/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; } diff --git a/fast_ping.c b/fast_ping.c index cc9f01f..54067f3 100755 --- a/fast_ping.c +++ b/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; } diff --git a/fast_ping.h b/fast_ping.h index 471afd7..91d8636 100755 --- a/fast_ping.h +++ b/fast_ping.h @@ -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; diff --git a/include/atomic.h b/include/atomic.h index 728c1b0..1c25211 100755 --- a/include/atomic.h +++ b/include/atomic.h @@ -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); } /** diff --git a/smartdns.c b/smartdns.c index 7bbec15..302a426 100755 --- a/smartdns.c +++ b/smartdns.c @@ -22,9 +22,26 @@ #include "hashtable.h" #include "list.h" #include "tlog.h" +#include "atomic.h" #include #include +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: