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
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    async_trait::async_trait,
    fuchsia_async::{self as fasync, TimeoutExt},
    fuchsia_zircon as zx,
    futures::{future::FutureExt, Future},
    std::{io, time::Duration},
    trust_dns_proto::{Executor, Time},
};

pub mod async_resolver;
pub mod config;
pub mod tcp;
pub mod test_util;
pub mod udp;

/// Default DNS server port.
pub const DEFAULT_PORT: u16 = 53;

/// A Fuchsia LocalExecutor which implements the `trust_dns_proto::Executor` trait.
pub struct FuchsiaExec(fasync::LocalExecutor);

impl FuchsiaExec {
    /// Constructs a Fuchsia LocalExecutor.
    pub fn new() -> Result<Self, zx::Status> {
        Ok(Self(fasync::LocalExecutor::new()))
    }

    /// Gets a mutable reference to the internal `fuchsia_async::LocalExecutor`.
    pub fn get(&mut self) -> &mut fasync::LocalExecutor {
        &mut self.0
    }
}

impl Executor for FuchsiaExec {
    fn new() -> Self {
        Self::new().expect("failed to create fuchsia executor")
    }

    fn block_on<F: Future>(&mut self, future: F) -> F::Output {
        self.0.run_singlethreaded(future)
    }
}

/// A Fuchsia Time with time-related capabilities which implements the `trust_dns_proto::Time` trait.
pub struct FuchsiaTime;

#[async_trait]
impl Time for FuchsiaTime {
    async fn timeout<F: 'static + Future + Send>(
        duration: Duration,
        future: F,
    ) -> Result<F::Output, io::Error> {
        let nanos = i64::try_from(duration.as_nanos()).expect("failed to cast the input into i64 ");
        let zx_duration = zx::Duration::from_nanos(nanos);

        future
            .map(|output| Ok(output))
            .on_timeout(fasync::Time::after(zx_duration), || {
                Err(io::Error::new(io::ErrorKind::TimedOut, "future timed out"))
            })
            .await
    }

    async fn delay_for(duration: Duration) -> () {
        let nanos = i64::try_from(duration.as_nanos()).expect("failed to cast the input into i64");
        let zx_duration = zx::Duration::from_nanos(nanos);
        fasync::Timer::new(fasync::Time::after(zx_duration)).await
    }
}