async_std_resolver/
runtime.rs

1// Copyright 2015-2020 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use hickory_resolver::config::{NameServerConfig, ResolverOpts};
9use std::future::Future;
10use std::net::SocketAddr;
11use std::pin::Pin;
12
13use hickory_resolver::proto::error::ProtoError;
14use hickory_resolver::proto::Executor;
15
16use hickory_resolver::name_server::{ConnectionProvider, GenericConnector, RuntimeProvider, Spawn};
17
18use crate::net::{AsyncStdTcpStream, AsyncStdUdpSocket};
19use crate::proto::tcp::Connect;
20use crate::proto::udp::UdpSocket;
21use crate::time::AsyncStdTime;
22
23/// The async_std runtime.
24///
25/// The runtime provides an I/O [driver], task scheduler, [timer], and blocking
26/// pool, necessary for running asynchronous tasks.
27///
28/// Instances of `AsyncStdRuntime` can be created using [`new`]. However, most
29/// users will use the `#[async_std::main]` annotation on their entry point instead.
30///
31/// See [module level][mod] documentation for more details.
32///
33/// # Shutdown
34///
35/// Shutting down the runtime is done by dropping the value. The current thread
36/// will block until the shut down operation has completed.
37///
38/// * Drain any scheduled work queues.
39/// * Drop any futures that have not yet completed.
40/// * Drop the reactor.
41///
42/// Once the reactor has dropped, any outstanding I/O resources bound to
43/// that reactor will no longer function. Calling any method on them will
44/// result in an error.
45///
46/// [driver]: crate::io::driver
47/// [timer]: crate::time
48/// [mod]: index.html
49/// [`new`]: #method.new
50#[derive(Clone, Copy, Default)]
51pub struct AsyncStdRuntimeProvider;
52
53impl Executor for AsyncStdRuntimeProvider {
54    fn new() -> Self {
55        Self {}
56    }
57
58    fn block_on<F: Future>(&mut self, future: F) -> F::Output {
59        async_std::task::block_on(future)
60    }
61}
62
63#[derive(Clone, Copy)]
64pub struct AsyncStdRuntimeHandle;
65impl Spawn for AsyncStdRuntimeHandle {
66    fn spawn_bg<F>(&mut self, future: F)
67    where
68        F: Future<Output = Result<(), ProtoError>> + Send + 'static,
69    {
70        let _join = async_std::task::spawn(future);
71    }
72}
73
74impl RuntimeProvider for AsyncStdRuntimeProvider {
75    type Handle = AsyncStdRuntimeHandle;
76    type Timer = AsyncStdTime;
77    type Udp = AsyncStdUdpSocket;
78    type Tcp = AsyncStdTcpStream;
79
80    fn create_handle(&self) -> Self::Handle {
81        AsyncStdRuntimeHandle {}
82    }
83
84    fn connect_tcp(
85        &self,
86        server_addr: SocketAddr,
87    ) -> Pin<Box<dyn Send + Future<Output = std::io::Result<Self::Tcp>>>> {
88        Box::pin(AsyncStdTcpStream::connect(server_addr))
89    }
90
91    fn bind_udp(
92        &self,
93        local_addr: SocketAddr,
94        _server_addr: SocketAddr,
95    ) -> Pin<Box<dyn Send + Future<Output = std::io::Result<Self::Udp>>>> {
96        Box::pin(AsyncStdUdpSocket::bind(local_addr))
97    }
98}
99
100#[derive(Clone, Default)]
101pub struct AsyncStdConnectionProvider {
102    runtime_provider: AsyncStdRuntimeProvider,
103    connection_provider: GenericConnector<AsyncStdRuntimeProvider>,
104}
105
106impl Executor for AsyncStdConnectionProvider {
107    fn new() -> Self {
108        let p = AsyncStdRuntimeProvider::new();
109        Self {
110            runtime_provider: p,
111            connection_provider: GenericConnector::new(p),
112        }
113    }
114
115    fn block_on<F: Future>(&mut self, future: F) -> F::Output {
116        self.runtime_provider.block_on(future)
117    }
118}
119
120impl ConnectionProvider for AsyncStdConnectionProvider {
121    type Conn = <GenericConnector<AsyncStdRuntimeProvider> as ConnectionProvider>::Conn;
122    type FutureConn = <GenericConnector<AsyncStdRuntimeProvider> as ConnectionProvider>::FutureConn;
123    type RuntimeProvider = AsyncStdRuntimeProvider;
124
125    fn new_connection(
126        &self,
127        config: &NameServerConfig,
128        options: &ResolverOpts,
129    ) -> Self::FutureConn {
130        self.connection_provider.new_connection(config, options)
131    }
132}