From 210fabe4b30ca4044a9d8c6d5b3b8f6aec3f6147 Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Sat, 5 May 2018 15:28:26 +0800 Subject: [PATCH] update code --- Makefile | 2 +- dns_server.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++ dns_server.h | 10 +++ smartdns.c | 21 ++--- 4 files changed, 241 insertions(+), 11 deletions(-) create mode 100644 dns_server.c create mode 100644 dns_server.h diff --git a/Makefile b/Makefile index 8cb6fe9..cca0091 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BIN=smartdns -OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o +OBJS=smartdns.o fast_ping.o lib/bitops.o dns_client.o dns_server.o CFLAGS=-g -O0 -Wall CFLAGS +=-Iinclude CXXFLAGS=-g -O0 -Wall -std=c++11 diff --git a/dns_server.c b/dns_server.c new file mode 100644 index 0000000..c2920d5 --- /dev/null +++ b/dns_server.c @@ -0,0 +1,219 @@ +#include "dns_server.h" +#include "hashtable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DNS_MAX_EVENTS 256 + +#define DNS_INPACKET_SIZE 512 + +struct dns_server { + int run; + int epoll_fd; + + int fd; + + pthread_mutex_t map_lock; + DECLARE_HASHTABLE(hostmap, 6); +}; + +static struct dns_server server; + +static void tv_sub(struct timeval *out, struct timeval *in) +{ + if ((out->tv_usec -= in->tv_usec) < 0) { /* out -= in */ + --out->tv_sec; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + +void _dns_server_period_run() +{ +} + +static int _dns_server_process(struct timeval *now) +{ + int len; + u_char inpacket[DNS_INPACKET_SIZE]; + struct sockaddr_storage from; + socklen_t from_len = sizeof(from); + + 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)); + goto errout; + } + + return 0; +errout: + return -1; +} + +int dns_server_run(void) +{ + struct epoll_event events[DNS_MAX_EVENTS + 1]; + int num; + int i; + struct timeval last = { 0 }; + struct timeval now = { 0 }; + struct timeval diff = { 0 }; + uint millisec = 0; + + while (server.run) { + diff = now; + tv_sub(&diff, &last); + millisec = diff.tv_sec * 1000 + diff.tv_usec / 1000; + if (millisec >= 100) { + _dns_server_period_run(); + last = now; + } + + num = epoll_wait(server.epoll_fd, events, DNS_MAX_EVENTS, 100); + if (num < 0) { + gettimeofday(&now, 0); + usleep(100000); + continue; + } + + if (num == 0) { + gettimeofday(&now, 0); + continue; + } + + gettimeofday(&now, 0); + for (i = 0; i < num; i++) { + struct epoll_event *event = &events[i]; + _dns_server_process(&now); + } + } + + close(server.epoll_fd); + server.epoll_fd = -1; + + return 0; +} + +static struct addrinfo *_dns_server_getaddr(const char *host, int port, int type, int protocol) +{ + struct addrinfo hints; + struct addrinfo *result = NULL; + + 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)); + goto errout; + } + + return result; +errout: + if (result) { + freeaddrinfo(result); + } + return NULL; +} + +int dns_server_socket(void) +{ + int fd = -1; + struct addrinfo *gai = NULL; + + gai = _dns_server_getaddr(NULL, 53, SOCK_DGRAM, 0); + + fd = socket(gai->ai_family, gai->ai_socktype, gai->ai_protocol); + if (fd < 0) { + fprintf(stderr, "create socket failed.\n"); + goto errout; + } + + if (bind() != 0) { + fprintf(stderr, "bind failed.\n"); + goto errout; + } + + server.fd = fd; + freeaddrinfo(gai); + + return 0; +errout: + if (fd > 0) { + close(fd); + } + + if (gai) { + freeaddrinfo(gai); + } + return -1; +} + +int dns_server_init(void) +{ + pthread_attr_t attr; + int epollfd = -1; + int fd = -1; + + if (server.epoll_fd > 0) { + return -1; + } + + memset(&server, 0, sizeof(server)); + pthread_attr_init(&attr); + + epollfd = epoll_create1(EPOLL_CLOEXEC); + if (epollfd < 0) { + fprintf(stderr, "create epoll failed, %s\n", strerror(errno)); + goto errout; + } + + pthread_mutex_init(&server.map_lock, 0); + hash_init(server.hostmap); + server.epoll_fd = epollfd; + server.fd = fd; + server.run = 1; + + return 0; +errout: + server.run = 0; + + if (fd > 0) { + close(fd); + } + + if (epollfd) { + close(epollfd); + } + + pthread_mutex_destroy(&server.map_lock); + + return -1; +} + +void dns_server_exit(void) +{ + server.run = 0; + + if (server.fd > 0) { + close(server.fd); + server.fd = -1; + } + + pthread_mutex_destroy(&server.map_lock); +} \ No newline at end of file diff --git a/dns_server.h b/dns_server.h new file mode 100644 index 0000000..c21c6be --- /dev/null +++ b/dns_server.h @@ -0,0 +1,10 @@ +#ifndef _SMART_DNS_SERVER_H +#define _SMART_DNS_SERVER_H + +int dns_server_init(void); + +int dns_server_run(void); + +void dns_server_exit(void); + +#endif diff --git a/smartdns.c b/smartdns.c index cb4ecca..db747a7 100755 --- a/smartdns.c +++ b/smartdns.c @@ -1,4 +1,6 @@ #include "fast_ping.h" +#include "dns_client.h" +#include "dns_server.h" #include "hashtable.h" #include "list.h" #include @@ -26,6 +28,12 @@ int smartdns_init() fast_ping_result_callback(smartdns_ping_result); + ret = dns_server_init(); + if (ret != 0) { + fprintf(stderr, "start dns server failed.\n"); + goto errout; + } + ret = dns_client_init(); if (ret != 0) { fprintf(stderr, "start dns client failed.\n"); @@ -40,16 +48,7 @@ errout: int smartdns_run() { - fast_ping_start("192.168.1.1", 2000, 0); - fast_ping_start("192.168.1.35", 2000, 0); - fast_ping_start("14.215.177.38", 2000, 0); - fast_ping_start("113.96.161.87", 2000, 0); - fast_ping_start("::1", 2000, 0); - fast_ping_start("12.4.3.1", 1000, 0); - while (1) { - sleep(10); - //fast_ping_stop("192.168.1.35"); - } + return dns_server_run(); } void smartdns_exit() @@ -57,6 +56,8 @@ void smartdns_exit() fast_ping_exit(); dns_client_exit(); + + dns_server_exit(); } struct data {