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
122
123
124
125
126
127
128
129
130
131
//! [rsdns] is a DNS client library.
//!
//! *rsdns* provides an API to directly communicate with DNS servers using its own implementation
//! of the DNS protocol. It strives to be minimal and fast.
//!
//! # Notable Features
//!
//! * Minimal API
//! * Three independent asynchronous clients for different async runtimes:
//! [`tokio`], [`async-std`] and [`smol`]
//! * An independent blocking client implemented with [`std::net`]
//! * Zero memory allocations when parsing records with no variable size fields
//! (e.g. [`A`], [`AAAA`])
//! * Sockets can be bound to network interfaces by name (requires `SO_BINDTODEVICE` support
//! from the underlying OS)
//! * Minimal set of dependencies
//!
//! [rsdns]: crate
//! [`tokio`]: https://docs.rs/tokio
//! [`async-std`]: https://docs.rs/async-std
//! [`smol`]: https://docs.rs/smol
//! [`std::net`]: https://doc.rust-lang.org/std/net
//! [`A`]: crate::records::data::A
//! [`AAAA`]: crate::records::data::Aaaa
//! # Library Structure
//!
//! *rsdns* is built from two major parts: *message parsing* and *clients*.
//!
//! The *message parsing* part is the core of *rsdns*. It is generic and is suitable for any type
//! of client that you may choose. It can be used even without an *rsdns* client at all,
//! if you have DNS messages obtained by other means. This part is always present and cannot
//! be disabled. See the [`message::reader`] module for more details.
//!
//! The *clients* part is comprised of four independent implementations
//! of the client API. Usually an application will use only one of those.
//! See the [`clients`] module for more information.
//!
//! [`MessageReader`]: message::reader::MessageReader
//! ## Crate Features
//!
//! *rsdns* has several crate features which enable different functionalities:
//!
//! 1. `net-tokio` - enables the [`clients::tokio`] module
//! 2. `net-async-std` - enables the [`clients::async_std`] module
//! 3. `net-smol` - enables the [`clients::smol`] module
//! 4. `net-std` - enables the [`clients::std`] module
//! 5. `socket2` - together with `net-tokio` enables `bind-to-device` support
//! (currently on Linux only)
//!
//! Note that none of the features is enabled by default. The [`clients`] module exists only
//! if one of the `net-*` features is enabled.
//! # Examples
//!
//! The following function retrieves [`A`] records using *rsdns's* asynchronous [`tokio::Client`].
//! To retrieve a different type of record, or use a different asynchronous client, use the
//! relevant types from [`records::data`] and [`clients`] modules respectively.
//!
//! This is a very simplified example of the available API. In a real application initialization
//! of the Client object would be done once for many DNS queries.
//! Also, please note that a full application requires `tokio` runtime initialization,
//! which is out of *rsdns* scope. See the [`tokio`] documentation for details.
//!
//! [`A`]: crate::records::data::A
//! [`tokio::Client`]: crate::clients::tokio::Client
//! [`records::data`]: crate::records::data
//! [`clients`]: crate::clients
//!
//! ```rust
//! use rsdns::records::{data::A, Class};
//! # #[cfg(feature = "net-tokio")]
//! use rsdns::clients::{tokio::Client, ClientConfig};
//! # use std::{error::Error, net::{Ipv4Addr, SocketAddr}, str::FromStr};
//!
//! # #[cfg(feature = "net-tokio")]
//! async fn get_a_records(qname: &str) -> Result<Vec<A>, Box<dyn Error>> {
//! // use Google's Public DNS recursor as nameserver
//! let nameserver = SocketAddr::from_str("8.8.8.8:53")?;
//!
//! // default client configuration; specify nameserver address only
//! let config = ClientConfig::with_nameserver(nameserver);
//!
//! // create tokio Client
//! let mut client = Client::new(config).await?;
//!
//! // issue an A query
//! let rrset = client.query_rrset::<A>(qname, Class::IN).await?;
//!
//! Ok(rrset.rdata)
//! }
//! ```
//!
//! The same function using *rsdns's* synchronous [`std::Client`].
//!
//! [`std::Client`]: crate::clients::std::Client
//!
//! ```rust
//! use rsdns::records::{data::A, Class};
//! # #[cfg(feature = "net-std")]
//! use rsdns::clients::{std::Client, ClientConfig};
//! # use std::{error::Error, net::{Ipv4Addr, SocketAddr}, str::FromStr};
//!
//! # #[cfg(feature = "net-std")]
//! fn get_a_records(qname: &str) -> Result<Vec<A>, Box<dyn Error>> {
//! let nameserver = SocketAddr::from_str("8.8.8.8:53")?;
//! let mut client = Client::new(ClientConfig::with_nameserver(nameserver))?;
//! let rrset = client.query_rrset::<A>(qname, Class::IN)?;
//! Ok(rrset.rdata)
//! }
//! ```
pub
pub
cfg_any_client!
pub use ;