hickory_proto/
lib.rs

1// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
2// Copyright 2017 Google LLC.
3//
4// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
5// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
6// https://opensource.org/licenses/MIT>, at your option. This file may not be
7// copied, modified, or distributed except according to those terms.
8
9// LIBRARY WARNINGS
10#![warn(
11    clippy::default_trait_access,
12    clippy::dbg_macro,
13    clippy::print_stdout,
14    clippy::unimplemented,
15    clippy::use_self,
16    missing_copy_implementations,
17    missing_docs,
18    non_snake_case,
19    non_upper_case_globals,
20    rust_2018_idioms,
21    unreachable_pub
22)]
23#![allow(
24    clippy::single_component_path_imports,
25    clippy::upper_case_acronyms, // can be removed on a major release boundary
26    clippy::bool_to_int_with_if,
27)]
28#![recursion_limit = "2048"]
29#![cfg_attr(docsrs, feature(doc_cfg))]
30
31//! Hickory DNS Protocol library
32
33use async_trait::async_trait;
34use futures_util::future::Future;
35
36use std::marker::Send;
37use std::time::Duration;
38#[cfg(any(test, feature = "tokio-runtime"))]
39use tokio::runtime::Runtime;
40#[cfg(any(test, feature = "tokio-runtime"))]
41use tokio::task::JoinHandle;
42
43macro_rules! try_ready_stream {
44    ($e:expr) => {{
45        match $e {
46            Poll::Ready(Some(Ok(t))) => t,
47            Poll::Ready(None) => return Poll::Ready(None),
48            Poll::Pending => return Poll::Pending,
49            Poll::Ready(Some(Err(e))) => return Poll::Ready(Some(Err(From::from(e)))),
50        }
51    }};
52}
53
54/// Spawn a background task, if it was present
55#[cfg(any(test, feature = "tokio-runtime"))]
56#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
57pub fn spawn_bg<F: Future<Output = R> + Send + 'static, R: Send + 'static>(
58    runtime: &Runtime,
59    background: F,
60) -> JoinHandle<R> {
61    runtime.spawn(background)
62}
63
64pub mod error;
65#[cfg(feature = "dns-over-https")]
66#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-https")))]
67pub mod h2;
68#[cfg(feature = "dns-over-h3")]
69#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-h3")))]
70pub mod h3;
71#[cfg(any(feature = "dns-over-https", feature = "dns-over-h3"))]
72#[cfg_attr(
73    docsrs,
74    doc(cfg(any(feature = "dns-over-https", feature = "dns-over-h3")))
75)]
76pub mod http;
77#[cfg(feature = "mdns")]
78#[cfg_attr(docsrs, doc(cfg(feature = "mdns")))]
79pub mod multicast;
80#[cfg(feature = "dns-over-native-tls")]
81#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-native-tls")))]
82pub mod native_tls;
83pub mod op;
84#[cfg(feature = "dns-over-openssl")]
85#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-openssl")))]
86pub mod openssl;
87#[cfg(all(feature = "dns-over-quic", feature = "tokio-runtime"))]
88#[cfg_attr(
89    docsrs,
90    doc(cfg(all(feature = "dns-over-quic", feature = "tokio-runtime")))
91)]
92pub mod quic;
93pub mod rr;
94#[cfg(feature = "dns-over-rustls")]
95#[cfg_attr(docsrs, doc(cfg(feature = "dns-over-rustls")))]
96pub mod rustls;
97pub mod serialize;
98pub mod tcp;
99#[cfg(any(test, feature = "testing"))]
100#[cfg_attr(docsrs, doc(cfg(feature = "testing")))]
101pub mod tests;
102pub mod udp;
103pub mod xfer;
104
105#[doc(hidden)]
106pub use crate::xfer::dns_handle::{DnsHandle, DnsStreamHandle};
107#[doc(hidden)]
108pub use crate::xfer::dns_multiplexer::DnsMultiplexer;
109#[doc(hidden)]
110#[cfg(feature = "dnssec")]
111pub use crate::xfer::dnssec_dns_handle::DnssecDnsHandle;
112#[doc(hidden)]
113pub use crate::xfer::retry_dns_handle::RetryDnsHandle;
114#[doc(hidden)]
115pub use crate::xfer::BufDnsStreamHandle;
116#[cfg(feature = "backtrace")]
117#[cfg_attr(docsrs, doc(cfg(feature = "backtrace")))]
118pub use error::ExtBacktrace;
119
120#[cfg(feature = "tokio-runtime")]
121#[doc(hidden)]
122pub mod iocompat {
123    use std::io;
124    use std::pin::Pin;
125    use std::task::{Context, Poll};
126
127    use futures_io::{AsyncRead, AsyncWrite};
128    use tokio::io::{AsyncRead as TokioAsyncRead, AsyncWrite as TokioAsyncWrite, ReadBuf};
129
130    /// Conversion from `tokio::io::{AsyncRead, AsyncWrite}` to `std::io::{AsyncRead, AsyncWrite}`
131    pub struct AsyncIoTokioAsStd<T: TokioAsyncRead + TokioAsyncWrite>(pub T);
132
133    impl<T: TokioAsyncRead + TokioAsyncWrite + Unpin> Unpin for AsyncIoTokioAsStd<T> {}
134    impl<R: TokioAsyncRead + TokioAsyncWrite + Unpin> AsyncRead for AsyncIoTokioAsStd<R> {
135        fn poll_read(
136            mut self: Pin<&mut Self>,
137            cx: &mut Context<'_>,
138            buf: &mut [u8],
139        ) -> Poll<io::Result<usize>> {
140            let mut buf = ReadBuf::new(buf);
141            let polled = Pin::new(&mut self.0).poll_read(cx, &mut buf);
142
143            polled.map_ok(|_| buf.filled().len())
144        }
145    }
146
147    impl<W: TokioAsyncRead + TokioAsyncWrite + Unpin> AsyncWrite for AsyncIoTokioAsStd<W> {
148        fn poll_write(
149            mut self: Pin<&mut Self>,
150            cx: &mut Context<'_>,
151            buf: &[u8],
152        ) -> Poll<io::Result<usize>> {
153            Pin::new(&mut self.0).poll_write(cx, buf)
154        }
155        fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
156            Pin::new(&mut self.0).poll_flush(cx)
157        }
158        fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
159            Pin::new(&mut self.0).poll_shutdown(cx)
160        }
161    }
162
163    /// Conversion from `std::io::{AsyncRead, AsyncWrite}` to `tokio::io::{AsyncRead, AsyncWrite}`
164    pub struct AsyncIoStdAsTokio<T: AsyncRead + AsyncWrite>(pub T);
165
166    impl<T: AsyncRead + AsyncWrite + Unpin> Unpin for AsyncIoStdAsTokio<T> {}
167    impl<R: AsyncRead + AsyncWrite + Unpin> TokioAsyncRead for AsyncIoStdAsTokio<R> {
168        fn poll_read(
169            self: Pin<&mut Self>,
170            cx: &mut Context<'_>,
171            buf: &mut ReadBuf<'_>,
172        ) -> Poll<io::Result<()>> {
173            Pin::new(&mut self.get_mut().0)
174                .poll_read(cx, buf.initialized_mut())
175                .map_ok(|len| buf.advance(len))
176        }
177    }
178
179    impl<W: AsyncRead + AsyncWrite + Unpin> TokioAsyncWrite for AsyncIoStdAsTokio<W> {
180        fn poll_write(
181            self: Pin<&mut Self>,
182            cx: &mut Context<'_>,
183            buf: &[u8],
184        ) -> Poll<Result<usize, io::Error>> {
185            Pin::new(&mut self.get_mut().0).poll_write(cx, buf)
186        }
187
188        fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
189            Pin::new(&mut self.get_mut().0).poll_flush(cx)
190        }
191
192        fn poll_shutdown(
193            self: Pin<&mut Self>,
194            cx: &mut Context<'_>,
195        ) -> Poll<Result<(), io::Error>> {
196            Pin::new(&mut self.get_mut().0).poll_close(cx)
197        }
198    }
199}
200
201/// Generic executor.
202// This trait is created to facilitate running the tests defined in the tests mod using different types of
203// executors. It's used in Fuchsia OS, please be mindful when update it.
204pub trait Executor {
205    /// Create the implementor itself.
206    fn new() -> Self;
207
208    /// Spawns a future object to run synchronously or asynchronously depending on the specific
209    /// executor.
210    fn block_on<F: Future>(&mut self, future: F) -> F::Output;
211}
212
213#[cfg(feature = "tokio-runtime")]
214#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
215impl Executor for Runtime {
216    fn new() -> Self {
217        Self::new().expect("failed to create tokio runtime")
218    }
219
220    fn block_on<F: Future>(&mut self, future: F) -> F::Output {
221        Self::block_on(self, future)
222    }
223}
224
225/// Generic Time for Delay and Timeout.
226// This trait is created to allow to use different types of time systems. It's used in Fuchsia OS, please be mindful when update it.
227#[async_trait]
228pub trait Time {
229    /// Return a type that implements `Future` that will wait until the specified duration has
230    /// elapsed.
231    async fn delay_for(duration: Duration);
232
233    /// Return a type that implement `Future` to complete before the specified duration has elapsed.
234    async fn timeout<F: 'static + Future + Send>(
235        duration: Duration,
236        future: F,
237    ) -> Result<F::Output, std::io::Error>;
238}
239
240/// New type which is implemented using tokio::time::{Delay, Timeout}
241#[cfg(any(test, feature = "tokio-runtime"))]
242#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
243#[derive(Clone, Copy, Debug)]
244pub struct TokioTime;
245
246#[cfg(any(test, feature = "tokio-runtime"))]
247#[cfg_attr(docsrs, doc(cfg(feature = "tokio-runtime")))]
248#[async_trait]
249impl Time for TokioTime {
250    async fn delay_for(duration: Duration) {
251        tokio::time::sleep(duration).await
252    }
253
254    async fn timeout<F: 'static + Future + Send>(
255        duration: Duration,
256        future: F,
257    ) -> Result<F::Output, std::io::Error> {
258        tokio::time::timeout(duration, future)
259            .await
260            .map_err(move |_| std::io::Error::new(std::io::ErrorKind::TimedOut, "future timed out"))
261    }
262}