ns_std_threaded/
lib.rs

1//! This crate provides a simple name resolver that uses lib's name resolution.
2//!
3//! Unfortunately libc doesn't provide asyncrhonous name resolution for many
4//! reasons so we run requests in a thread pool.
5//!
6//! For high-performance server applications this way is far from being
7//! performant, still it is the most compatible to everything else. So it
8//! might be used:
9//!
10//! 1. To provide maximum compatibility (i.e. good default for dev environment)
11//! 2. In applications where name resolution is not slow part
12//! 3. As a fallthrough resolver for `ns_router::Router` where more frequently
13//!    used name suffixes are overriden with faster resolver for that namespace
14#![warn(missing_docs)]
15#![warn(missing_debug_implementations)]
16extern crate futures;
17extern crate abstract_ns;
18extern crate futures_cpupool;
19
20use std::fmt;
21use std::net::ToSocketAddrs;
22
23use futures::Async;
24use abstract_ns::{HostResolve, Name, IpList, Error};
25use futures_cpupool::{CpuPool, CpuFuture};
26
27/// A resolver that uses ToSocketAddrs from stdlib in thread pool
28#[derive(Clone, Debug)]
29pub struct ThreadedResolver {
30    pool: CpuPool,
31}
32
33/// A Future returned from resolver
34pub struct Future(CpuFuture<IpList, Error>);
35
36impl ThreadedResolver {
37    /// Create a resolver with 8 threads in it's own thread pool
38    ///
39    /// Use `use_pool` with a configured `CpuPool` to change the
40    /// configuration or share thread pool with something else
41    pub fn new() -> Self {
42        ThreadedResolver {
43            pool: CpuPool::new(8),
44        }
45    }
46    /// Create a new Resolver with the given thread pool
47    ///
48    /// This is often used to share thread pool with other service or to
49    /// configure thread pool diffently
50    pub fn use_pool(pool: CpuPool) -> Self {
51        ThreadedResolver {
52            pool: pool,
53        }
54    }
55}
56
57
58impl futures::Future for Future {
59    type Item = IpList;
60    type Error = Error;
61    fn poll(&mut self) -> Result<Async<IpList>, Error> {
62        self.0.poll()
63    }
64}
65
66
67impl HostResolve for ThreadedResolver {
68    type HostFuture = Future;
69    fn resolve_host(&self, name: &Name) -> Future {
70        let name = name.clone();
71        Future(self.pool.spawn_fn(move || {
72            match (name.as_ref(), 0).to_socket_addrs() {
73                Ok(it) => Ok(it.map(|sa| sa.ip())
74                    .collect::<Vec<_>>().into()),
75                Err(e) => Err(Error::TemporaryError(Box::new(e))),
76            }
77        }))
78    }
79}
80
81impl fmt::Debug for Future {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        write!(f, "ns_std_threaded::Future {{}}")
84    }
85}