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}