#![cfg(feature = "dnssec")]
use std::future::Future;
use std::pin::Pin;
use futures_util::stream::Stream;
use crate::client::AsyncClient;
use crate::proto::error::ProtoError;
use crate::proto::rr::dnssec::TrustAnchor;
use crate::proto::xfer::{
DnsExchangeBackground, DnsHandle, DnsRequest, DnsRequestSender, DnsResponse,
};
use crate::proto::DnssecDnsHandle;
use crate::proto::TokioTime;
pub struct AsyncDnssecClient {
client: DnssecDnsHandle<AsyncClient>,
}
impl AsyncDnssecClient {
pub fn builder<F, S>(connect_future: F) -> AsyncSecureClientBuilder<F, S>
where
F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
S: DnsRequestSender + 'static,
{
AsyncSecureClientBuilder {
connect_future,
trust_anchor: None,
}
}
pub async fn connect<F, S>(
connect_future: F,
) -> Result<(Self, DnsExchangeBackground<S, TokioTime>), ProtoError>
where
S: DnsRequestSender,
F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
{
Self::builder(connect_future).build().await
}
fn from_client(client: AsyncClient, trust_anchor: TrustAnchor) -> Self {
Self {
client: DnssecDnsHandle::with_trust_anchor(client, trust_anchor),
}
}
}
impl Clone for AsyncDnssecClient {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
}
}
}
impl DnsHandle for AsyncDnssecClient {
type Response = Pin<Box<(dyn Stream<Item = Result<DnsResponse, ProtoError>> + Send + 'static)>>;
type Error = ProtoError;
fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&mut self, request: R) -> Self::Response {
self.client.send(request)
}
}
#[cfg(feature = "dnssec")]
#[cfg_attr(docsrs, doc(cfg(feature = "dnssec")))]
pub struct AsyncSecureClientBuilder<F, S>
where
F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
S: DnsRequestSender + 'static,
{
connect_future: F,
trust_anchor: Option<TrustAnchor>,
}
#[cfg(feature = "dnssec")]
impl<F, S> AsyncSecureClientBuilder<F, S>
where
F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
S: DnsRequestSender + 'static,
{
pub fn trust_anchor(mut self, trust_anchor: TrustAnchor) -> Self {
self.trust_anchor = Some(trust_anchor);
self
}
pub async fn build(
mut self,
) -> Result<(AsyncDnssecClient, DnsExchangeBackground<S, TokioTime>), ProtoError> {
let trust_anchor = if let Some(trust_anchor) = self.trust_anchor.take() {
trust_anchor
} else {
TrustAnchor::default()
};
let result = AsyncClient::connect(self.connect_future).await;
result.map(|(client, bg)| (AsyncDnssecClient::from_client(client, trust_anchor), bg))
}
}