Browse Source

Update code, basic tests

Nick Peng 7 years ago
parent
commit
75ebf7ce49
8 changed files with 200 additions and 92 deletions
  1. 5 0
      dns.c
  2. 5 0
      dns.h
  3. 75 45
      dns_client.c
  4. 24 16
      dns_server.c
  5. 45 28
      fast_ping.c
  6. 1 0
      fast_ping.h
  7. 2 2
      include/atomic.h
  8. 43 1
      smartdns.c

+ 5 - 0
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 - 0
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,

+ 75 - 45
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;
 	}
 

+ 24 - 16
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;
 	}
 

+ 45 - 28
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;
 	}
 

+ 1 - 0
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;

+ 2 - 2
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);
 }
 
 /**

+ 43 - 1
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: