use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use futures_util::stream::Stream;
use crate::client::Client;
use crate::proto::ProtoError;
use crate::proto::dnssec::DnssecDnsHandle;
use crate::proto::dnssec::TrustAnchors;
use crate::proto::runtime::TokioTime;
use crate::proto::xfer::{
DnsExchangeBackground, DnsHandle, DnsRequest, DnsRequestSender, DnsResponse,
};
pub struct DnssecClient {
client: DnssecDnsHandle<Client>,
}
impl DnssecClient {
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: Client, trust_anchor: Arc<TrustAnchors>) -> Self {
Self {
client: DnssecDnsHandle::with_trust_anchor(client, trust_anchor),
}
}
}
impl Clone for DnssecClient {
fn clone(&self) -> Self {
Self {
client: self.client.clone(),
}
}
}
impl DnsHandle for DnssecClient {
type Response = Pin<Box<dyn Stream<Item = Result<DnsResponse, ProtoError>> + Send + 'static>>;
fn send<R: Into<DnsRequest> + Unpin + Send + 'static>(&self, request: R) -> Self::Response {
self.client.send(request)
}
}
pub struct AsyncSecureClientBuilder<F, S>
where
F: Future<Output = Result<S, ProtoError>> + 'static + Send + Unpin,
S: DnsRequestSender + 'static,
{
connect_future: F,
trust_anchor: Option<TrustAnchors>,
}
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: TrustAnchors) -> Self {
self.trust_anchor = Some(trust_anchor);
self
}
pub async fn build(
mut self,
) -> Result<(DnssecClient, DnsExchangeBackground<S, TokioTime>), ProtoError> {
let trust_anchor = Arc::new(self.trust_anchor.take().unwrap_or_default());
let result = Client::connect(self.connect_future).await;
result.map(|(client, bg)| (DnssecClient::from_client(client, trust_anchor), bg))
}
}