add global dns cache

This commit is contained in:
Y. T. Chung
2017-05-21 15:11:54 +08:00
parent bf83d00d43
commit c7d183ec8a
4 changed files with 46 additions and 16 deletions
Generated
+7
View File
@@ -14,6 +14,7 @@ dependencies = [
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lru_time_cache 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -313,6 +314,11 @@ dependencies = [
"linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lru_time_cache"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lzw"
version = "0.10.0"
@@ -713,6 +719,7 @@ dependencies = [
"checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48"
"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
"checksum lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656fa4dfcb02bcf1063c592ba3ff6a5303ee1f2afe98c8a889e8b1a77c6dfdb7"
"checksum lru_time_cache 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf17862cdf1a87c7cc0cccc498552f3e564d2ae61069f83d2279a932af4a00c"
"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
"checksum mio 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aa30e3753079b08ce3d75cf3b44783e36fe0e1f64065f65c1d894d1688fb2580"
+2 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "shadowsocks-rust"
version = "1.3.1"
version = "1.3.2"
authors = ["Y. T. CHUNG <zonyitoo@gmail.com>"]
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
repository = "https://github.com/zonyitoo/shadowsocks-rust"
@@ -38,6 +38,7 @@ env_logger = "0.4"
rust-crypto = "0.2"
openssl = "0.9"
lru-cache = "0.1"
lru_time_cache = "0.6"
libc = "0.2"
futures = "0.1"
tokio-core = "0.1"
+1
View File
@@ -74,6 +74,7 @@ extern crate serde_json;
#[macro_use]
extern crate log;
extern crate lru_cache;
extern crate lru_time_cache;
extern crate byteorder;
extern crate rand;
+36 -15
View File
@@ -1,6 +1,8 @@
//! Asynchronous DNS resolver
use std::io;
use std::time::Duration;
use std::cell::RefCell;
use futures::{Future, BoxFuture};
use futures::future;
@@ -11,13 +13,28 @@ use domain::resolv::Resolver;
use domain::resolv::lookup::lookup_host;
use domain::bits::DNameBuf;
use lru_time_cache::LruCache;
use std::net::IpAddr;
// Global DNS cache.
// Cache for 5mins and store at most 128 entries
thread_local!(static GLOBAL_DNS_CACHE: RefCell<LruCache<String, IpAddr>>
= RefCell::new(LruCache::with_expiry_duration_and_capacity(Duration::from_secs(5 * 60), 128)));
pub fn resolve(addr: &str, handle: &Handle) -> BoxFuture<IpAddr, io::Error> {
let cached_addr = GLOBAL_DNS_CACHE.with(|c| {
let mut xc = c.borrow_mut();
xc.get(addr).map(|x| *x)
});
if let Some(addr) = cached_addr {
return future::finished(addr).boxed();
}
let dname = match addr.parse::<DNameBuf>() {
Ok(dname) => dname,
Err(err) => return future::err(io::Error::new(io::ErrorKind::Other, err))
.boxed()
Err(err) => return future::err(io::Error::new(io::ErrorKind::Other, err)).boxed(),
};
let resolv = Resolver::new(handle);
@@ -25,18 +42,22 @@ pub fn resolve(addr: &str, handle: &Handle) -> BoxFuture<IpAddr, io::Error> {
lookup_host(resolv, &dname)
.map_err(From::from)
.and_then(move |hosts| {
match hosts.iter().next() {
Some(addr) => {
trace!("Resolved \"{}\" as {}", dname, addr);
Ok(addr)
}
None => {
let err = io::Error::new(io::ErrorKind::Other,
format!("Failed to resolve \"{}\"", dname));
Err(err)
}
}
})
.and_then(move |hosts| match hosts.iter().next() {
Some(addr) => {
trace!("Resolved \"{}\" as {}", dname, addr);
GLOBAL_DNS_CACHE.with(|c| {
let mut xc = c.borrow_mut();
xc.insert(dname.to_string(), addr);
});
Ok(addr)
}
None => {
let err = io::Error::new(io::ErrorKind::Other,
format!("Failed to resolve \"{}\"", dname));
Err(err)
}
})
.boxed()
}