1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
//! Abstract traits for name service library //! //! # Traits //! //! There are four traits: //! //! * [`HostResolve`](trait.HostResolve.html) //! -- resolves hostname to a list of IP addresses //! (maps to `A` record in DNS) //! * [`Resolve`](trait.Resolve.html) //! -- resolves service name to a set of weighted and prioritized host:port //! pairs ([`Address`](struct.Address.html) struct). //! Maps to `SRV` record in DNS. //! * [`HostSubscribe`](trait.HostSubscribe.html) //! -- resolves hostname to a list of IP addresses and tracks changes of //! the addresses //! * [`Subscribe`](trait.Subscribe.html) //! -- resolves service name to an [`Address`](struct.Address.html) and //! subscribes on updates of the address //! //! And there are two address types: //! //! * [`IpList`](ip_list/struct.IpList.html) -- represents `Arc<Vec<IpAddr>>` //! this is used as a result of hostname resolution and it should be converted //! into an `Address` struct. //! * [`Address`](addr/struct.Address.html) -- represets weighed and //! prioritized list of addresses, this is what all user code should accept //! for maximum flexibility. //! //! There are three category of users of the library: //! //! * Implementors of resolution methods //! * Service authors //! * Application writers //! //! Let's explain how to use traits to all of them. //! //! # Implementing A Resolver //! //! The `*Resolve` traits are used for ad-hoc resolution of the addresses. //! //! The `*Subscribe` traits are used to get updates for the name. If your //! name service supports updates you should implement it. If not, there //! are shims which periodically poll `resolve*` methods to get the //! update functionality. Still if you want to poll again based on TTL value //! and your resolver does have this value you might want to implement //! `*Subscribe` traits too. //! //! But `abstract-ns` is not just for DNS subsystem. You may want `*.consul` //! names to be resolved against consul and subscribe on updates in consul. //! Another option is to use eureka, etcd, or zookeeper. All of them having //! a way to deliver updates. //! //! # Writing Protocols //! //! In general, your library should depend on a minimum set of functionality //! here. Here are the rules of thumb: //! //! 1. Clients: when you need to connect once, accept //! `T: Future<Item=SocketAddr>`, there are adapters that pick a random //! host from `Future<Item=Address>` returned by `PollResolver::resolve` //! 2. Clients: when writing a connection pool, accept //! `T: Stream<Item=Address>`, there are adapters to make that stream //! by resolving a single name (into potentially multiple IP addresses), //! a list of names, and a `Stream<Item=Vec<Name>>` (so that config is //! adaptable). As well as adapters that help diffing the `Address`, //! effectively allowing connection pool to adapt //! (also take a look at [tk-pool]) //! 3. Servers: accept `T: AsyncRead + AsyncWrite`, we have //! [tk-listen] crate that can turn all kinds of configuration //! into actually accepted connections. //! 4. Servers: if you need more control accept `TcpStream` //! or `Stream<io::Result<TcpStream>>`, this provides same flexibility //! for name resolution but allows control over parameters of TCP socket //! or of the accepting actual connections //! //! [tk-pool]: https://crates.io/crates/tk-pool //! [tk-listen]: https://crates.io/crates/tk-listen //! //! # Writing Applications //! //! Applications should use `ns-router` crate that supports multiple resolvers, //! and configuring them on-the-fly. //! //! # Writing Connection Pools //! //! As said in [Writing Protocols](#writing-protocols) section a single //! connection pool should use `T: Stream<Item=Address>` for as a name //! source, this allows good flexibility (also see [tk-pool]) //! //! But in case you need kinda connection pool to a lot of different names //! and services, this is the good case for accepting `Resolver` trait itself. //! (Still, most of the time actual application should supply //! `ns_router::Router`) //! #![deny(missing_docs)] #![deny(missing_debug_implementations)] extern crate futures; extern crate rand; extern crate void; #[macro_use] extern crate quick_error; mod error; mod resolver; pub mod addr; pub mod name; pub mod ip_list; pub mod combinators; pub use addr::Address; pub use ip_list::IpList; pub use error::Error; pub use name::Name; pub use resolver::{HostResolve, Resolve, HostSubscribe, Subscribe}; trait AssertTraits: Send + Sync {} impl AssertTraits for Address {} impl AssertTraits for IpList {} impl AssertTraits for Name {} impl AssertTraits for Error {}