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