adjust interfaces for recursor
This commit is contained in:
parent
ab0094a4ff
commit
47ac8b39f7
160
crates/recursor/src/error.rs
Normal file
160
crates/recursor/src/error.rs
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright 2015-2020 Benjamin Fry <benjaminfry@me.com>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
//! Error types for the crate
|
||||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use std::{fmt, io, sync};
|
||||
|
||||
use enum_as_inner::EnumAsInner;
|
||||
use thiserror::Error;
|
||||
|
||||
#[cfg(feature = "backtrace")]
|
||||
use crate::proto::{trace, ExtBacktrace};
|
||||
use crate::{
|
||||
proto::error::{ProtoError, ProtoErrorKind},
|
||||
resolver::error::{ResolveError, ResolveErrorKind},
|
||||
};
|
||||
|
||||
/// The error kind for errors that get returned in the crate
|
||||
#[derive(Debug, EnumAsInner, Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum ErrorKind {
|
||||
/// An error with an arbitrary message, referenced as &'static str
|
||||
#[error("{0}")]
|
||||
Message(&'static str),
|
||||
|
||||
/// An error with an arbitrary message, stored as String
|
||||
#[error("{0}")]
|
||||
Msg(String),
|
||||
|
||||
/// An error got returned from IO
|
||||
#[error("io error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
|
||||
/// An error got returned by the trust-dns-proto crate
|
||||
#[error("proto error: {0}")]
|
||||
Proto(#[from] ProtoError),
|
||||
|
||||
/// An error got returned by the trust-dns-proto crate
|
||||
#[error("proto error: {0}")]
|
||||
Resolve(#[from] ResolveError),
|
||||
|
||||
/// A request timed out
|
||||
#[error("request timed out")]
|
||||
Timeout,
|
||||
}
|
||||
|
||||
/// The error type for errors that get returned in the crate
|
||||
#[derive(Error, Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct Error {
|
||||
/// Kind of error that ocurred
|
||||
pub kind: Box<ErrorKind>,
|
||||
/// Backtrace to the source of the error
|
||||
#[cfg(feature = "backtrace")]
|
||||
pub backtrack: Option<ExtBacktrace>,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
/// Get the kind of the error
|
||||
pub fn kind(&self) -> &ErrorKind {
|
||||
&self.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "backtrace")] {
|
||||
if let Some(ref backtrace) = self.backtrack {
|
||||
fmt::Display::fmt(&self.kind, f)?;
|
||||
fmt::Debug::fmt(backtrace, f)
|
||||
} else {
|
||||
fmt::Display::fmt(&self.kind, f)
|
||||
}
|
||||
} else {
|
||||
fmt::Display::fmt(&self.kind, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorKind> for Error {
|
||||
fn from(kind: ErrorKind) -> Self {
|
||||
Self {
|
||||
kind: Box::new(kind),
|
||||
#[cfg(feature = "backtrace")]
|
||||
backtrack: trace!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for Error {
|
||||
fn from(msg: &'static str) -> Self {
|
||||
ErrorKind::Message(msg).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Error {
|
||||
fn from(msg: String) -> Self {
|
||||
ErrorKind::Msg(msg).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for Error {
|
||||
fn from(e: io::Error) -> Self {
|
||||
match e.kind() {
|
||||
io::ErrorKind::TimedOut => ErrorKind::Timeout.into(),
|
||||
_ => ErrorKind::from(e).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for io::Error {
|
||||
fn from(e: Error) -> Self {
|
||||
match *e.kind() {
|
||||
ErrorKind::Timeout => Self::new(io::ErrorKind::TimedOut, e),
|
||||
_ => Self::new(io::ErrorKind::Other, e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for String {
|
||||
fn from(e: Error) -> Self {
|
||||
e.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "wasm-bindgen")))]
|
||||
impl From<Error> for wasm_bindgen_crate::JsValue {
|
||||
fn from(e: Error) -> Self {
|
||||
js_sys::Error::new(&e.to_string()).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ErrorKind {
|
||||
fn clone(&self) -> Self {
|
||||
use self::ErrorKind::*;
|
||||
match *self {
|
||||
Message(msg) => Message(msg),
|
||||
Msg(ref msg) => Msg(msg.clone()),
|
||||
Io(ref io) => Self::from(std::io::Error::from(io.kind())),
|
||||
Proto(ref proto) => Self::from(proto.clone()),
|
||||
Resolve(ref resolve) => Self::from(resolve.clone()),
|
||||
Timeout => Self::Timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait marking a type which implements From<Error> and
|
||||
/// std::error::Error types as well as Clone + Send
|
||||
pub trait FromError: From<Error> + std::error::Error + Clone {}
|
||||
|
||||
impl<E> FromError for E where E: From<Error> + std::error::Error + Clone {}
|
@ -19,7 +19,11 @@
|
||||
#![recursion_limit = "2048"]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
pub mod error;
|
||||
mod recursor;
|
||||
|
||||
pub use error::{Error, ErrorKind};
|
||||
pub use recursor::Recursor;
|
||||
pub use trust_dns_proto as proto;
|
||||
pub use trust_dns_resolver as resolver;
|
||||
pub use trust_dns_resolver::config::NameServerConfig;
|
||||
|
@ -1,15 +1,17 @@
|
||||
use std::fmt;
|
||||
use std::{fmt, time::Instant};
|
||||
|
||||
use log::debug;
|
||||
|
||||
use trust_dns_proto::rr::RecordType;
|
||||
use trust_dns_proto::rr::{RecordSet, RecordType};
|
||||
use trust_dns_resolver::{
|
||||
config::{NameServerConfig, NameServerConfigGroup, ResolverConfig, ResolverOpts},
|
||||
config::{NameServerConfigGroup, ResolverConfig, ResolverOpts},
|
||||
error::ResolveError,
|
||||
lookup::Lookup,
|
||||
IntoName, Name, TokioAsyncResolver,
|
||||
name_server::NameServerPool,
|
||||
IntoName, Name, TokioAsyncResolver, TokioConnection, TokioConnectionProvider,
|
||||
};
|
||||
|
||||
use crate::Error;
|
||||
/// A top down recursive resolver which operates off a list of "hints", this is often the root nodes.
|
||||
pub struct Recursor {
|
||||
hints: TokioAsyncResolver,
|
||||
@ -35,7 +37,8 @@ impl Recursor {
|
||||
|
||||
/// Permform a recursive resolution
|
||||
///
|
||||
/// [https://datatracker.ietf.org/doc/html/rfc1034#section-5.3.3](RFC 1034), Domain Concepts and Facilities, November 1987
|
||||
/// [RFC 1034](https://datatracker.ietf.org/doc/html/rfc1034#section-5.3.3), Domain Concepts and Facilities, November 1987
|
||||
///
|
||||
/// ```text
|
||||
/// 5.3.3. Algorithm
|
||||
///
|
||||
@ -197,11 +200,12 @@ impl Recursor {
|
||||
&self,
|
||||
domain: N,
|
||||
ty: RecordType,
|
||||
request_time: Instant,
|
||||
) -> Result<Lookup, ResolveError> {
|
||||
let domain = domain.into_name()?;
|
||||
|
||||
// wild guess on number fo lookups needed
|
||||
let mut lookups = Vec::<RecursiveLookup>::with_capacity(10);
|
||||
let mut lookups = Vec::<RecursiveQuery>::with_capacity(10);
|
||||
lookups.push((domain.clone(), ty).into());
|
||||
|
||||
// collect all the nameservers we need.
|
||||
@ -222,14 +226,23 @@ impl Recursor {
|
||||
|
||||
todo!();
|
||||
}
|
||||
|
||||
async fn lookup(
|
||||
&self,
|
||||
domain: &Name,
|
||||
ty: RecordType,
|
||||
ns: &NameServerPool<TokioConnection, TokioConnectionProvider>,
|
||||
) -> Result<RecordSet, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
struct RecursiveLookup {
|
||||
struct RecursiveQuery {
|
||||
name: Name,
|
||||
ty: RecordType,
|
||||
}
|
||||
|
||||
impl From<(Name, RecordType)> for RecursiveLookup {
|
||||
impl From<(Name, RecordType)> for RecursiveQuery {
|
||||
fn from(name_ty: (Name, RecordType)) -> Self {
|
||||
Self {
|
||||
name: name_ty.0,
|
||||
@ -238,7 +251,7 @@ impl From<(Name, RecordType)> for RecursiveLookup {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RecursiveLookup {
|
||||
impl fmt::Display for RecursiveQuery {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||
write!(f, "({},{})", self.name, self.ty)
|
||||
}
|
||||
@ -254,3 +267,8 @@ fn recursor_opts() -> ResolverOpts {
|
||||
|
||||
options
|
||||
}
|
||||
|
||||
enum RecursiveLookup {
|
||||
Found(RecordSet),
|
||||
Forward(RecordSet),
|
||||
}
|
||||
|
@ -20,7 +20,11 @@
|
||||
unreachable_pub
|
||||
)]
|
||||
|
||||
use std::net::{IpAddr, SocketAddr};
|
||||
use std::{
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::{Path, PathBuf},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use console::style;
|
||||
@ -85,6 +89,10 @@ struct Opts {
|
||||
/// Enable error logging
|
||||
#[clap(long)]
|
||||
error: bool,
|
||||
|
||||
/// Path to a hints file
|
||||
#[clap(short = 'f', long)]
|
||||
hints: PathBuf,
|
||||
}
|
||||
|
||||
/// Run the resolve programf
|
||||
@ -176,7 +184,8 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
ty = style(ty).yellow(),
|
||||
);
|
||||
|
||||
let lookup = recursor.resolve(name.to_string(), ty).await?;
|
||||
let now = Instant::now();
|
||||
let lookup = recursor.resolve(name.to_string(), ty, now).await?;
|
||||
|
||||
// report response, TODO: better display of errors
|
||||
println!(
|
||||
|
Loading…
Reference in New Issue
Block a user