Nick Peng 7 years ago
parent
commit
a1906787b1
7 changed files with 147 additions and 72 deletions
  1. 2 2
      etc/smartdns/smartdns.conf
  2. 1 0
      src/conf.c
  3. 34 4
      src/dns_cache.c
  4. 2 0
      src/dns_cache.h
  5. 20 26
      src/dns_server.c
  6. 10 15
      src/include/art.h
  7. 78 25
      src/lib/art.c

+ 2 - 2
etc/smartdns/smartdns.conf

@@ -4,12 +4,12 @@
 #   IPV4: :53
 #   IPV6  [::]:53
 
-bind [::]:535
+bind [::]:53
 
 # dns cache size
 # cache-size [number]
 #   0: for no cache
-cache-size 1024
+cache-size 512
 
 # set log level
 # loglevel [level], level=error, warn, info, debug

+ 1 - 0
src/conf.c

@@ -97,6 +97,7 @@ int config_address(char *value)
 		goto errout;
 	}
 
+	memset(address, 0, sizeof(*address));
 	len = end - begin;
 	memcpy(address->domain, begin, len);
 	address->domain[len] = 0;

+ 34 - 4
src/dns_cache.c

@@ -37,6 +37,7 @@ void _dns_cache_delete(struct dns_cache *dns_cache)
 {
 	hash_del(&dns_cache->node);
 	list_del_init(&dns_cache->list);
+	dns_cache_head.num--;
 	free(dns_cache);
 }
 
@@ -92,12 +93,12 @@ int dns_cache_insert(char *domain, int ttl, dns_type_t qtype, unsigned char *add
 
 	pthread_mutex_lock(&dns_cache_head.lock);
 	hash_add(dns_cache_head.cache_hash, &dns_cache->node, key);
-	list_add(&dns_cache->list, &dns_cache_head.cache_list);
+	list_add_tail(&dns_cache->list, &dns_cache_head.cache_list);
 
 	dns_cache_head.num++;
 	if (dns_cache_head.num > dns_cache_head.size) {
 		struct dns_cache *del_cache;
-		del_cache = _dns_cache_last();
+		del_cache = _dns_cache_first();
 		dns_cache_release(del_cache);
 	}
 	pthread_mutex_unlock(&dns_cache_head.lock);
@@ -181,8 +182,37 @@ void dns_cache_delete(struct dns_cache *dns_cache)
 void dns_cache_update(struct dns_cache *dns_cache)
 {
 	pthread_mutex_lock(&dns_cache_head.lock);
-	list_del_init(&dns_cache->list);
-	list_add(&dns_cache->list, &dns_cache_head.cache_list);
+	if (!list_empty(&dns_cache->list)) {
+		list_del_init(&dns_cache->list);
+		list_add_tail(&dns_cache->list, &dns_cache_head.cache_list);
+	}
+	pthread_mutex_unlock(&dns_cache_head.lock);
+}
+
+void dns_cache_invalidate(void)
+{
+	struct dns_cache *dns_cache = NULL;
+	struct dns_cache *tmp;
+	time_t now;
+	int ttl = 0;
+
+	if (dns_cache_head.size <= 0) {
+		return;
+	}
+
+	time(&now);
+	pthread_mutex_lock(&dns_cache_head.lock);
+	list_for_each_entry_safe(dns_cache, tmp, &dns_cache_head.cache_list, list)
+	{
+		ttl = dns_cache->insert_time + dns_cache->ttl - now;
+		if (ttl > 0) {
+			break;
+		}
+
+		hash_del(&dns_cache->node);
+		list_del_init(&dns_cache->list);
+		dns_cache_release(dns_cache);
+	}
 	pthread_mutex_unlock(&dns_cache_head.lock);
 }
 

+ 2 - 0
src/dns_cache.h

@@ -34,6 +34,8 @@ void dns_cache_release(struct dns_cache *dns_cache);
 
 void dns_cache_update(struct dns_cache *dns_cache);
 
+void dns_cache_invalidate(void);
+
 int dns_cache_get_ttl(struct dns_cache *dns_cache);
 
 void dns_cache_destroy(void);

+ 20 - 26
src/dns_server.c

@@ -680,28 +680,8 @@ errout:
 	return -1;
 }
 
-int _dns_server_art_iter_callback(void *data, const unsigned char *key, uint32_t key_len, void *value)
-{
-	struct dns_address **address;
-	address = data;
-	*address = value;
-	return 0;
-}
-
-static int _dns_server_art_domain_cmp(const art_leaf *n, const unsigned char *prefix, int prefix_len)
-{
-	// Fail if the prefix length is too short
-	if (n->key_len > (uint32_t)prefix_len) {
-		return 1;
-	}
-
-	// Compare the keys
-	return memcmp(n->key, prefix, n->key_len);
-}
-
 static struct dns_address *_dns_server_get_address_by_domain(char *domain, int qtype)
 {
-	struct dns_address *address = NULL;
 	int domain_len;
 	char domain_key[DNS_MAX_CNAME_LEN];
 	char type = '4';
@@ -721,11 +701,8 @@ static struct dns_address *_dns_server_get_address_by_domain(char *domain, int q
 	reverse_string(domain_key + 1, domain, domain_len);
 	domain_key[0] = type;
 	domain_len++;
-	if (art_iter_cmp(&dns_conf_address, (unsigned char *)domain_key, domain_len, _dns_server_art_iter_callback, _dns_server_art_domain_cmp, &address) != 0) {
-		return NULL;
-	}
 
-	return address;
+	return art_substring(&dns_conf_address, (unsigned char *)domain_key, domain_len);;
 }
 
 static int _dns_server_process_address(struct dns_request *request, struct dns_packet *packet)
@@ -796,6 +773,7 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac
 
 	request->rcode = DNS_RC_NOERROR;
 	_dns_reply(request);
+	dns_cache_update(dns_cache);
 	dns_cache_release(dns_cache);
 
 	return 0;
@@ -972,11 +950,27 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
 	request->has_ping_tcp = 1;
 }
 
+void _dns_server_period_run_second(void)
+{
+	static unsigned int sec = 0;
+	sec++;
+
+	if (sec % 2 == 0) {
+		dns_cache_invalidate();
+	}
+}
+
 void _dns_server_period_run(void)
 {
 	struct dns_request *request, *tmp;
+	static unsigned int msec = 0;
 	LIST_HEAD(check_list);
 
+	msec++;
+	if (msec % 10 == 0) {
+		_dns_server_period_run_second();
+	}
+
 	unsigned long now = get_tick_count();
 
 	pthread_mutex_lock(&server.request_list_lock);
@@ -1153,7 +1147,7 @@ int dns_server_init(void)
 		return -1;
 	}
 
-	if (dns_cache_init(1024) != 0) {
+	if (dns_cache_init(dns_conf_cachesize) != 0) {
 		tlog(TLOG_ERROR, "init cache failed.");
 		return -1;
 	}
@@ -1229,7 +1223,7 @@ void dns_server_exit(void)
 
 	list_for_each_entry_safe(request, tmp, &remove_list, check_list)
 	{
-		_dns_server_request_release(request);
+		_dns_server_request_remove(request);
 	}
 
 	pthread_mutex_destroy(&server.request_list_lock);

+ 10 - 15
src/include/art.h

@@ -185,6 +185,16 @@ void* art_delete(art_tree *t, const unsigned char *key, int key_len);
  */
 void* art_search(const art_tree *t, const unsigned char *key, int key_len);
 
+/**
+ * Searches substring for a value in the ART tree
+ * @arg t The tree
+ * @arg str The key
+ * @arg str_len The length of the key
+ * @return NULL if the item was not found, otherwise
+ * the value pointer is returned.
+ */
+void *art_substring(const art_tree *t, const unsigned char *str, int str_len);
+
 /**
  * Returns the minimum valued leaf
  * @return The minimum leaf or NULL
@@ -223,21 +233,6 @@ int art_iter(art_tree *t, art_callback cb, void *data);
  */
 int art_iter_prefix(art_tree *t, const unsigned char *prefix, int prefix_len, art_callback cb, void *data);
 
-/**
- * Iterates through the entries pairs in the map,
- * invoking a callback for each that matches a given prefix.
- * The call back gets a key, value for each and returns an integer stop value.
- * If the callback returns non-zero, then the iteration stops.
- * @arg t The tree to iterate over
- * @arg prefix The prefix of keys to read
- * @arg prefix_len The length of the prefix
- * @arg cb The callback function to invoke
- * @arg data Opaque handle passed to the callback
- * @return 0 on success, or the return of the callback.
- */
-typedef int(*art_key_cmp_callback)(const art_leaf *n, const unsigned char *prefix, int prefix_len);
-int art_iter_cmp(art_tree *t, const unsigned char *str, int str_len, art_callback cb, art_key_cmp_callback key_cmp, void *data);
-
 #ifdef __cplusplus
 }
 #endif

+ 78 - 25
src/lib/art.c

@@ -912,17 +912,46 @@ int art_iter(art_tree *t, art_callback cb, void *data) {
     return recursive_iter(t->root, cb, data);
 }
 
-int art_iter_cmp(art_tree *t, const unsigned char *key, int key_len, art_callback cb, art_key_cmp_callback key_cmp, void *data)
-{
+/**
+ * Checks if a leaf prefix matches
+ * @return 0 on success.
+ */
+static int leaf_prefix_matches(const art_leaf *n, const unsigned char *prefix, int prefix_len) {
+    // Fail if the key length is too short
+    if (n->key_len < (uint32_t)prefix_len) return 1;
+
+    // Compare the keys
+    return memcmp(n->key, prefix, prefix_len);
+}
+
+/**
+ * Iterates through the entries pairs in the map,
+ * invoking a callback for each that matches a given prefix.
+ * The call back gets a key, value for each and returns an integer stop value.
+ * If the callback returns non-zero, then the iteration stops.
+ * @arg t The tree to iterate over
+ * @arg prefix The prefix of keys to read
+ * @arg prefix_len The length of the prefix
+ * @arg cb The callback function to invoke
+ * @arg data Opaque handle passed to the callback
+ * @return 0 on success, or the return of the callback.
+ */
+int art_iter_prefix(art_tree *t, const unsigned char *key, int key_len, art_callback cb, void *data) {
     art_node **child;
     art_node *n = t->root;
     int prefix_len, depth = 0;
     while (n) {
+
+        if (IS_LEAF(n)) {
+            n = (art_node*)LEAF_RAW(n);
+            art_leaf *l = (art_leaf*)n;
+			printf("LEAF: %s\n", l->key);
+		} 
         // Might be a leaf
         if (IS_LEAF(n)) {
             n = (art_node*)LEAF_RAW(n);
             // Check if the expanded path matches
-            if (!key_cmp((art_leaf*)n, key, key_len)) {
+            if (!leaf_prefix_matches((art_leaf*)n, key, key_len)) {
                 art_leaf *l = (art_leaf*)n;
                 return cb(data, (const unsigned char*)l->key, l->key_len, l->value);
             }
@@ -932,7 +961,7 @@ int art_iter_cmp(art_tree *t, const unsigned char *key, int key_len, art_callbac
         // If the depth matches the prefix, we need to handle this node
         if (depth == key_len) {
             art_leaf *l = minimum(n);
-            if (!key_cmp(l, key, key_len))
+            if (!leaf_prefix_matches(l, key, key_len))
                return recursive_iter(n, cb, data);
             return 0;
         }
@@ -967,30 +996,54 @@ int art_iter_cmp(art_tree *t, const unsigned char *key, int key_len, art_callbac
     return 0;
 }
 
-/**
- * Checks if a leaf prefix matches
- * @return 0 on success.
- */
-static int leaf_prefix_matches(const art_leaf *n, const unsigned char *prefix, int prefix_len) {
+static int str_prefix_matches(const art_leaf *n, const unsigned char *str, int str_len) {
     // Fail if the key length is too short
-    if (n->key_len < (uint32_t)prefix_len) return 1;
+	if (n->key_len > (uint32_t)str_len) return 1;
 
     // Compare the keys
-    return memcmp(n->key, prefix, prefix_len);
+    return memcmp(str, n->key, n->key_len);
 }
 
-/**
- * Iterates through the entries pairs in the map,
- * invoking a callback for each that matches a given prefix.
- * The call back gets a key, value for each and returns an integer stop value.
- * If the callback returns non-zero, then the iteration stops.
- * @arg t The tree to iterate over
- * @arg prefix The prefix of keys to read
- * @arg prefix_len The length of the prefix
- * @arg cb The callback function to invoke
- * @arg data Opaque handle passed to the callback
- * @return 0 on success, or the return of the callback.
- */
-int art_iter_prefix(art_tree *t, const unsigned char *key, int key_len, art_callback cb, void *data) {
-	return art_iter_cmp(t, key, key_len, cb, leaf_prefix_matches, data);
+void *art_substring(const art_tree *t, const unsigned char *str, int str_len)
+{
+    art_node **child;
+    art_node *n = t->root;
+	art_leaf *found = NULL;
+
+	int prefix_len, depth = 0;
+    while (n) {
+        // Might be a leaf
+        if (IS_LEAF(n)) {
+            n = (art_node*)LEAF_RAW(n);
+            // Check if the expanded path matches
+            if (!str_prefix_matches((art_leaf*)n, str, str_len)) {
+				found = (art_leaf*)n;
+            }
+			break;
+		}
+
+        // Bail if the prefix does not match
+        if (n->partial_len) {
+            prefix_len = check_prefix(n, str, str_len, depth);
+            if (prefix_len != min(MAX_PREFIX_LEN, n->partial_len))
+				break;
+			depth = depth + n->partial_len;
+        }
+
+        art_leaf *l = maximum(n);
+        if (!str_prefix_matches(l, str, str_len)) {
+			found = l;
+		}
+
+        // Recursively search
+        child = find_child(n, str[depth]);
+        n = (child) ? *child : NULL;
+        depth++;
+    }
+
+    if (found == NULL) {
+		return NULL;
+	}
+
+    return found->value;
 }