From 2241a178fb78a088a78496e70cb664bfa1ba841c Mon Sep 17 00:00:00 2001 From: "Aode (lion)" Date: Fri, 22 Jul 2022 14:37:18 -0500 Subject: [PATCH] Extract DNS logic from hyperjive --- .gitignore | 2 + Cargo.toml | 17 ++++++ src/lib.rs | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..5368ff4 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "jive-dns" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = { version = "0.1.52" } +futures-io = "0.3.21" +jive = { git = "https://git.asonix.dog/safe-async/jive", features = [ + "futures-io-compat", +] } +trust-dns-proto = { version = "0.21.0", default-features = false } +trust-dns-resolver = { version = "0.21.1", default-features = false, features = [ + "system-config", +] } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..668bc6a --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,167 @@ +use futures_io::{AsyncRead, AsyncWrite}; +use std::{ + future::Future, + pin::Pin, + task::{Context, Poll}, +}; +use trust_dns_resolver::config::{ResolverConfig, ResolverOpts}; + +pub fn resolver( + config: ResolverConfig, + options: ResolverOpts, +) -> Result { + JiveResolver::new(config, options, JiveRuntimeHandle) +} + +pub fn resolver_from_system_conf() -> Result +{ + JiveResolver::from_system_conf(JiveRuntimeHandle) +} + +#[derive(Clone)] +pub struct JiveRuntime; + +pub struct JiveTcpStream { + pub(crate) io: jive::io::Async, +} + +pub struct JiveUdpSocket { + io: jive::io::Async, +} + +pub type JiveResolver = trust_dns_resolver::AsyncResolver; + +pub type JiveConnection = trust_dns_resolver::name_server::GenericConnection; +pub type JiveConnectionProvider = + trust_dns_resolver::name_server::GenericConnectionProvider; + +#[derive(Clone, Copy)] +pub struct JiveRuntimeHandle; + +pub struct JiveTimer; + +impl JiveTcpStream { + pub fn into_inner(self) -> jive::io::Async { + self.io + } + + pub fn from_inner(io: jive::io::Async) -> Self { + JiveTcpStream { io } + } +} + +impl trust_dns_resolver::name_server::RuntimeProvider for JiveRuntime { + type Handle = JiveRuntimeHandle; + type Tcp = JiveTcpStream; + type Timer = JiveTimer; + type Udp = JiveUdpSocket; +} + +impl trust_dns_resolver::name_server::Spawn for JiveRuntimeHandle { + fn spawn_bg(&mut self, future: F) + where + F: Future> + Send + 'static, + { + let _join = jive::spawn(future); + } +} + +#[async_trait::async_trait] +impl trust_dns_proto::tcp::Connect for JiveTcpStream { + async fn connect_with_bind( + addr: std::net::SocketAddr, + bind_addr: Option, + ) -> std::io::Result { + if let Some(_bind_addr) = bind_addr { + todo!("Implement connect with bind"); + } else { + let io = jive::io::Async::::connect(addr).await?; + + Ok(JiveTcpStream { io }) + } + } +} + +impl trust_dns_proto::tcp::DnsTcpStream for JiveTcpStream { + type Time = JiveTimer; +} + +impl AsyncRead for JiveTcpStream { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + Pin::new(&mut self.get_mut().io).poll_read(cx, buf) + } +} + +impl AsyncWrite for JiveTcpStream { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + Pin::new(&mut self.get_mut().io).poll_write(cx, buf) + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.get_mut().io).poll_flush(cx) + } + + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(&mut self.get_mut().io).poll_close(cx) + } +} + +#[async_trait::async_trait] +impl trust_dns_proto::udp::UdpSocket for JiveUdpSocket { + type Time = JiveTimer; + + async fn bind(addr: std::net::SocketAddr) -> std::io::Result { + let io = jive::io::Async::::bind(addr).await?; + + Ok(JiveUdpSocket { io }) + } + + fn poll_send_to( + &self, + cx: &mut Context<'_>, + buf: &[u8], + target: std::net::SocketAddr, + ) -> Poll> { + self.io.poll_send_to(cx, buf, target) + } + + fn poll_recv_from( + &self, + cx: &mut Context<'_>, + buf: &mut [u8], + ) -> Poll> { + self.io.poll_recv_from(cx, buf) + } +} + +#[async_trait::async_trait] +impl trust_dns_proto::Time for JiveTimer { + async fn delay_for(duration: std::time::Duration) { + jive::time::sleep(duration).await + } + + async fn timeout( + duration: std::time::Duration, + future: F, + ) -> Result { + jive::time::timeout(duration, Box::pin(future)).await + } +} + +impl trust_dns_proto::Executor for JiveRuntime { + fn new() -> Self { + Self + } + + fn block_on(&mut self, future: F) -> F::Output { + jive::block_on(future) + } +}