Implement DNS resolver for Jive
This commit is contained in:
parent
18e6ebf64a
commit
9b53832c5c
23
Cargo.toml
23
Cargo.toml
|
@ -7,18 +7,37 @@ edition = "2021"
|
|||
name = "demo"
|
||||
required-features = ["server"]
|
||||
|
||||
[[example]]
|
||||
name = "axum"
|
||||
required-features = ["server"]
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[features]
|
||||
default = []
|
||||
default = ["client", "server"]
|
||||
server = ["hyper/server"]
|
||||
client = ["hyper/client"]
|
||||
client = [
|
||||
"async-trait",
|
||||
"futures-io",
|
||||
"hyper/client",
|
||||
"jive/futures-io-compat",
|
||||
"tower-service",
|
||||
"trust-dns-proto",
|
||||
"trust-dns-resolver",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
async-trait = { version = "0.1.52", optional = true }
|
||||
futures-io = { version = "0.3", optional = true }
|
||||
hyper = { version = "0.14", features = ["http1"] }
|
||||
jive = { git = "https://git.asonix.dog/safe-async/jive", features = [
|
||||
"tokio-io-compat",
|
||||
] }
|
||||
tokio = { version = "1", default-features = false }
|
||||
tower-service = { version = "0.3.1", optional = true }
|
||||
trust-dns-proto = { version = "0.21.0", default-features = false, optional = true }
|
||||
trust-dns-resolver = { version = "0.21.1", default-features = false, features = [
|
||||
"system-config",
|
||||
], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
axum = "0.4.8"
|
||||
|
|
|
@ -9,5 +9,5 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
hyperjive::server::builder(([0, 0, 0, 0], 8080)).await?.serve(app.into_make_service()).await?;
|
||||
|
||||
Ok(())
|
||||
})?
|
||||
})
|
||||
}
|
||||
|
|
|
@ -20,5 +20,5 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
server.await?;
|
||||
|
||||
Ok(())
|
||||
})?
|
||||
})
|
||||
}
|
||||
|
|
257
src/lib.rs
257
src/lib.rs
|
@ -1,9 +1,15 @@
|
|||
#[derive(Clone)]
|
||||
pub struct JiveExecutor;
|
||||
use std::future::Future;
|
||||
|
||||
impl<Fut> hyper::rt::Executor<Fut> for JiveExecutor
|
||||
#[derive(Clone)]
|
||||
pub struct JiveRuntime;
|
||||
|
||||
pub struct JiveTcpStream {
|
||||
io: jive::io::Async<jive::net::TcpStream>,
|
||||
}
|
||||
|
||||
impl<Fut> hyper::rt::Executor<Fut> for JiveRuntime
|
||||
where
|
||||
Fut: std::future::Future + Send + 'static,
|
||||
Fut: Future + Send + 'static,
|
||||
{
|
||||
fn execute(&self, fut: Fut) {
|
||||
jive::spawn(async move {
|
||||
|
@ -14,21 +20,59 @@ where
|
|||
|
||||
#[cfg(feature = "server")]
|
||||
pub mod server {
|
||||
use super::JiveTcpStream;
|
||||
use std::{
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
pub struct JiveIncoming {
|
||||
io: jive::io::Async<jive::net::TcpListener>,
|
||||
}
|
||||
|
||||
pub struct JiveConnection {
|
||||
io: jive::io::Async<jive::net::TcpStream>,
|
||||
pub async fn builder<A: Into<std::net::SocketAddr>>(
|
||||
socket_address: A,
|
||||
) -> std::io::Result<hyper::server::Builder<JiveIncoming, super::JiveRuntime>> {
|
||||
let listener = jive::io::Async::<jive::net::TcpListener>::bind(socket_address).await?;
|
||||
|
||||
let incoming = JiveIncoming { io: listener };
|
||||
|
||||
let http = hyper::server::conn::Http::new().with_executor(super::JiveRuntime);
|
||||
|
||||
Ok(hyper::server::Builder::new(incoming, http))
|
||||
}
|
||||
|
||||
impl AsyncRead for JiveTcpStream {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut tokio::io::ReadBuf<'_>,
|
||||
) -> Poll<std::io::Result<()>> {
|
||||
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<std::io::Result<usize>> {
|
||||
Pin::new(&mut self.get_mut().io).poll_write(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
Pin::new(&mut self.get_mut().io).poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
Pin::new(&mut self.get_mut().io).poll_shutdown(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl hyper::server::accept::Accept for JiveIncoming {
|
||||
type Conn = JiveConnection;
|
||||
type Conn = JiveTcpStream;
|
||||
type Error = std::io::Error;
|
||||
|
||||
fn poll_accept(
|
||||
|
@ -38,51 +82,166 @@ pub mod server {
|
|||
self.get_mut()
|
||||
.io
|
||||
.poll_accept(cx)
|
||||
.map(|res| res.map(|(stream, _)| JiveConnection { io: stream }))
|
||||
.map(|res| res.map(|(stream, _)| JiveTcpStream { io: stream }))
|
||||
.map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn builder<A: Into<std::net::SocketAddr>>(
|
||||
socket_address: A,
|
||||
) -> std::io::Result<hyper::server::Builder<JiveIncoming, super::JiveExecutor>> {
|
||||
let listener = jive::io::Async::<jive::net::TcpListener>::bind(socket_address).await?;
|
||||
|
||||
let incoming = JiveIncoming { io: listener };
|
||||
|
||||
let http = hyper::server::conn::Http::new().with_executor(super::JiveExecutor);
|
||||
|
||||
Ok(hyper::server::Builder::new(incoming, http))
|
||||
}
|
||||
|
||||
impl tokio::io::AsyncRead for JiveConnection {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut tokio::io::ReadBuf<'_>,
|
||||
) -> Poll<std::io::Result<()>> {
|
||||
tokio::io::AsyncRead::poll_read(Pin::new(&mut self.get_mut().io), cx, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl tokio::io::AsyncWrite for JiveConnection {
|
||||
fn poll_write(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
) -> Poll<std::io::Result<usize>> {
|
||||
tokio::io::AsyncWrite::poll_write(Pin::new(&mut self.get_mut().io), cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
tokio::io::AsyncWrite::poll_flush(Pin::new(&mut self.get_mut().io), cx)
|
||||
}
|
||||
|
||||
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
tokio::io::AsyncWrite::poll_shutdown(Pin::new(&mut self.get_mut().io), cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "client")]
|
||||
mod client {}
|
||||
pub mod client {
|
||||
pub mod dns {
|
||||
use crate::{JiveRuntime, JiveTcpStream};
|
||||
use futures_io::{AsyncRead, AsyncWrite};
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
|
||||
|
||||
pub async fn resolver(
|
||||
config: ResolverConfig,
|
||||
options: ResolverOpts,
|
||||
) -> Result<JiveResolver, trust_dns_resolver::error::ResolveError> {
|
||||
JiveResolver::new(config, options, JiveRuntimeHandle)
|
||||
}
|
||||
|
||||
pub fn resolver_from_system_conf(
|
||||
) -> Result<JiveResolver, trust_dns_resolver::error::ResolveError> {
|
||||
JiveResolver::from_system_conf(JiveRuntimeHandle)
|
||||
}
|
||||
|
||||
pub type JiveResolver =
|
||||
trust_dns_resolver::AsyncResolver<JiveConnection, JiveConnectionProvider>;
|
||||
|
||||
pub type JiveConnection = trust_dns_resolver::name_server::GenericConnection;
|
||||
pub type JiveConnectionProvider =
|
||||
trust_dns_resolver::name_server::GenericConnectionProvider<JiveRuntime>;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct JiveRuntimeHandle;
|
||||
|
||||
pub struct JiveTimer;
|
||||
|
||||
pub struct JiveUdpSocket {
|
||||
io: jive::io::Async<jive::net::UdpSocket>,
|
||||
}
|
||||
|
||||
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<F>(&mut self, future: F)
|
||||
where
|
||||
F: Future<Output = Result<(), trust_dns_proto::error::ProtoError>> + 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::net::SocketAddr>,
|
||||
) -> std::io::Result<Self> {
|
||||
if let Some(_bind_addr) = bind_addr {
|
||||
todo!("Implement connect with binnd");
|
||||
} else {
|
||||
let io = jive::io::Async::<jive::net::TcpStream>::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<std::io::Result<usize>> {
|
||||
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<std::io::Result<usize>> {
|
||||
Pin::new(&mut self.get_mut().io).poll_write(cx, buf)
|
||||
}
|
||||
|
||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
Pin::new(&mut self.get_mut().io).poll_flush(cx)
|
||||
}
|
||||
|
||||
fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
|
||||
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<Self> {
|
||||
let io = jive::io::Async::<jive::net::UdpSocket>::bind(addr).await?;
|
||||
|
||||
Ok(JiveUdpSocket { io })
|
||||
}
|
||||
|
||||
fn poll_send_to(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &[u8],
|
||||
target: std::net::SocketAddr,
|
||||
) -> Poll<std::io::Result<usize>> {
|
||||
self.io.poll_send_to(cx, buf, target)
|
||||
}
|
||||
|
||||
fn poll_recv_from(
|
||||
&self,
|
||||
cx: &mut Context<'_>,
|
||||
buf: &mut [u8],
|
||||
) -> Poll<std::io::Result<(usize, std::net::SocketAddr)>> {
|
||||
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<F: 'static + Future + Send>(
|
||||
duration: std::time::Duration,
|
||||
future: F,
|
||||
) -> Result<F::Output, std::io::Error> {
|
||||
jive::time::timeout(duration, Box::pin(future)).await
|
||||
}
|
||||
}
|
||||
|
||||
impl trust_dns_proto::Executor for JiveRuntime {
|
||||
fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn block_on<F: Future>(&mut self, future: F) -> F::Output {
|
||||
jive::block_on(future)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue