added error location to all ClientErrors
This commit is contained in:
parent
8ff4935079
commit
896ab32dd2
32
Cargo.lock
generated
32
Cargo.lock
generated
@ -2,6 +2,7 @@
|
||||
name = "trust-dns"
|
||||
version = "0.5.3"
|
||||
dependencies = [
|
||||
"backtrace 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"data-encoding 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"docopt 0.6.78 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -21,6 +22,28 @@ dependencies = [
|
||||
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "0.4.0"
|
||||
@ -50,6 +73,15 @@ name = "data-encoding"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "dbghelp-sys"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "0.6.78"
|
||||
|
@ -68,6 +68,7 @@ debug-assertions = true
|
||||
codegen-units = 1
|
||||
|
||||
[dependencies]
|
||||
backtrace = "^0.2.1"
|
||||
chrono = "^0.2.21"
|
||||
data-encoding = "^1.1.2"
|
||||
docopt = "^0.6.78"
|
||||
|
@ -1,13 +1,6 @@
|
||||
Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
// Copyright 2015-2016 Benjamin Fry
|
||||
//
|
||||
// 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.
|
||||
|
@ -21,7 +21,7 @@ use std::sync::RwLock;
|
||||
|
||||
use ::rr::{Name, RecordType};
|
||||
use ::authority::{Authority, ZoneType};
|
||||
use ::op::*;
|
||||
use ::op::{Edns, Message, MessageType, OpCode, Query, UpdateMessage, ResponseCode};
|
||||
|
||||
/// Set of authorities, zones, available to this server.
|
||||
pub struct Catalog {
|
||||
@ -86,7 +86,7 @@ impl Catalog {
|
||||
// recursive queries should be cached.
|
||||
},
|
||||
OpCode::Update => {
|
||||
let response = self.update(&request);
|
||||
let response = self.update(request);
|
||||
debug!("update response: {:?}", response);
|
||||
response
|
||||
}
|
||||
@ -175,14 +175,12 @@ impl Catalog {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `request` - an update message
|
||||
pub fn update(&self, request: &Message) -> Message {
|
||||
pub fn update(&self, update: &UpdateMessage) -> Message {
|
||||
let mut response: Message = Message::new();
|
||||
response.id(request.get_id());
|
||||
response.id(update.get_id());
|
||||
response.op_code(OpCode::Update);
|
||||
response.message_type(MessageType::Response);
|
||||
|
||||
let update: &UpdateMessage = request;
|
||||
|
||||
let zones: &[Query] = update.get_zones();
|
||||
if zones.len() != 1 || zones[0].get_query_type() != RecordType::SOA {
|
||||
response.response_code(ResponseCode::FormErr);
|
||||
|
@ -96,7 +96,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
.filter(|rr| rr.get_rr_type() == RecordType::RRSIG).collect();
|
||||
|
||||
if rrsigs.is_empty() {
|
||||
return Err(ClientError::NoRRSIG);
|
||||
return Err(ClientError::NoRRSIG(error_loc!()));
|
||||
}
|
||||
|
||||
// group the record sets by name and type
|
||||
@ -146,7 +146,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
}
|
||||
}
|
||||
|
||||
if !validated_nx { return Err(ClientError::NoNsec) }
|
||||
if !validated_nx { return Err(ClientError::NoNsec(error_loc!())) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +193,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
if !rdata.is_zone_key() { continue }
|
||||
if *rdata.get_algorithm() != sig.get_algorithm() { continue }
|
||||
|
||||
let pkey = try!(rdata.get_algorithm().public_key_from_vec(rdata.get_public_key()));
|
||||
let pkey = try_rethrow!(ClientError::DecodeError, rdata.get_algorithm().public_key_from_vec(rdata.get_public_key()));
|
||||
if !pkey.can(Role::Verify) { debug!("pkey can't verify, {:?}", dnskey.get_name()); continue }
|
||||
|
||||
let signer: Signer = Signer::new_verifier(*rdata.get_algorithm(), pkey, sig.get_signer_name().clone());
|
||||
@ -225,7 +225,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
}
|
||||
}
|
||||
|
||||
Err(ClientError::NoDNSKEY)
|
||||
Err(ClientError::NoDNSKEY(error_loc!()))
|
||||
}
|
||||
|
||||
/// attempts to verify the DNSKey against the DS of the parent.
|
||||
@ -267,8 +267,8 @@ impl<C: ClientConnection> Client<C> {
|
||||
{
|
||||
let mut encoder: BinEncoder = BinEncoder::new(&mut buf);
|
||||
encoder.set_canonical_names(true);
|
||||
try!(name.emit(&mut encoder));
|
||||
try!(dnskey.get_rdata().emit(&mut encoder));
|
||||
try_rethrow!(ClientError::EncodeError, name.emit(&mut encoder));
|
||||
try_rethrow!(ClientError::EncodeError, dnskey.get_rdata().emit(&mut encoder));
|
||||
}
|
||||
|
||||
let hash: Vec<u8> = ds_rdata.get_digest_type().hash(&buf);
|
||||
@ -283,7 +283,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
}
|
||||
}
|
||||
|
||||
Err(ClientError::NoDS)
|
||||
Err(ClientError::NoDS(error_loc!()))
|
||||
}
|
||||
|
||||
// RFC 4035 DNSSEC Protocol Modifications March 2005
|
||||
@ -362,7 +362,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
// TODO: need to validate ANY or *.domain record existance, which doesn't make sense since
|
||||
// that would have been returned in the request
|
||||
// if we got here, then there are no matching NSEC records, no validation
|
||||
Err(ClientError::InvalidNsec)
|
||||
Err(ClientError::InvalidNsec(error_loc!()))
|
||||
}
|
||||
|
||||
// Laurie, et al. Standards Track [Page 22]
|
||||
@ -439,7 +439,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
_: DNSClass, soa: Option<&Record>,
|
||||
nsec3s: Vec<&Record>) -> ClientResult<()> {
|
||||
// the search name is the one to look for
|
||||
let zone_name = try!(soa.ok_or(ClientError::NoSOARecord(query_name.clone()))).get_name();
|
||||
let zone_name = try!(soa.ok_or(ClientError::NoSOARecord(error_loc!(), query_name.clone()))).get_name();
|
||||
debug!("nsec3s: {:?}", nsec3s);
|
||||
|
||||
for nsec3 in nsec3s {
|
||||
@ -472,7 +472,7 @@ impl<C: ClientConnection> Client<C> {
|
||||
}
|
||||
}
|
||||
|
||||
Err(ClientError::InvalidNsec3)
|
||||
Err(ClientError::InvalidNsec3(error_loc!()))
|
||||
}
|
||||
|
||||
/// A *classic* DNS query, i.e. does not perform and DNSSec operations
|
||||
@ -523,16 +523,16 @@ impl<C: ClientConnection> Client<C> {
|
||||
let mut buffer: Vec<u8> = Vec::with_capacity(512);
|
||||
{
|
||||
let mut encoder = BinEncoder::new(&mut buffer);
|
||||
try!(message.emit(&mut encoder));
|
||||
try_rethrow!(ClientError::EncodeError, message.emit(&mut encoder));
|
||||
}
|
||||
|
||||
// send the message and get the response from the connection.
|
||||
let resp_buffer = try!(self.client_connection.borrow_mut().send(buffer));
|
||||
|
||||
let mut decoder = BinDecoder::new(&resp_buffer);
|
||||
let response = try!(Message::read(&mut decoder));
|
||||
let response = try_rethrow!(ClientError::DecodeError, Message::read(&mut decoder));
|
||||
|
||||
if response.get_id() != id { return Err(ClientError::IncorrectMessageId{ got: response.get_id(), expect: id }); }
|
||||
if response.get_id() != id { return Err(ClientError::IncorrectMessageId{ loc: error_loc!(), got: response.get_id(), expect: id }); }
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
|
@ -52,13 +52,13 @@ pub mod test {
|
||||
fn send(&mut self, bytes: Vec<u8>) -> ClientResult<Vec<u8>> {
|
||||
let mut decoder = BinDecoder::new(&bytes);
|
||||
|
||||
let message = try!(Message::read(&mut decoder));
|
||||
let message = try_rethrow!(ClientError::DecodeError, Message::read(&mut decoder));
|
||||
let response = self.catalog.handle_request(&message);
|
||||
|
||||
let mut buf = Vec::with_capacity(512);
|
||||
{
|
||||
let mut encoder = BinEncoder::new(&mut buf);
|
||||
try!(response.emit(&mut encoder));
|
||||
try_rethrow!(ClientError::EncodeError, response.emit(&mut encoder));
|
||||
}
|
||||
|
||||
Ok(buf)
|
||||
|
36
src/error/base_error.rs
Normal file
36
src/error/base_error.rs
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2015-2016 Benjamin Fry
|
||||
//
|
||||
// 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.
|
||||
|
||||
//! Base Error type and macro for creating
|
||||
use std::fmt;
|
||||
|
||||
pub struct ErrorLoc{ pub file: &'static str, pub line: u32, pub col: u32 }
|
||||
|
||||
macro_rules! error_loc {
|
||||
() => { ::error::ErrorLoc { file: file!(), line: line!(), col: column!() } };
|
||||
}
|
||||
|
||||
macro_rules! try_rethrow {
|
||||
( $error_type:path, $error:expr ) => {
|
||||
match $error {
|
||||
Ok(r) => r,
|
||||
Err(e) => return Err($error_type( error_loc!(), e )),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl fmt::Debug for ErrorLoc {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}:{}:{}", self.file, self.line, self.col)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrorLoc {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}:{}:{}", self.file, self.line, self.col)
|
||||
}
|
||||
}
|
@ -21,53 +21,58 @@ use std::fmt;
|
||||
use ::op::ResponseCode;
|
||||
use ::rr::{Name, Record};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ClientError {
|
||||
DecodeError(super::DecodeError),
|
||||
EncodeError(super::EncodeError),
|
||||
IoError(io::Error),
|
||||
NotAllBytesSent{ sent: usize, expect: usize},
|
||||
NotAllBytesReceived{ received: usize, expect: usize},
|
||||
IncorrectMessageId{ got: u16, expect: u16},
|
||||
TimedOut,
|
||||
NoAddress,
|
||||
NoNameServer,
|
||||
TimerError,
|
||||
NoDataReceived,
|
||||
ErrorResponse(ResponseCode),
|
||||
NoRRSIG,
|
||||
NoDNSKEY,
|
||||
NoDS,
|
||||
NoSOARecord(Name),
|
||||
SecNxDomain{proof: Vec<Record>},
|
||||
InvalidNsec,
|
||||
InvalidNsec3,
|
||||
NoNsec,
|
||||
DecodeError(super::ErrorLoc, super::DecodeError),
|
||||
EncodeError(super::ErrorLoc, super::EncodeError),
|
||||
IoError(super::ErrorLoc, io::Error),
|
||||
NotAllBytesSent{ loc: super::ErrorLoc, sent: usize, expect: usize},
|
||||
NotAllBytesReceived{ loc: super::ErrorLoc, received: usize, expect: usize},
|
||||
IncorrectMessageId{ loc: super::ErrorLoc, got: u16, expect: u16},
|
||||
TimedOut(super::ErrorLoc),
|
||||
NoAddress(super::ErrorLoc),
|
||||
NoNameServer(super::ErrorLoc),
|
||||
TimerError(super::ErrorLoc),
|
||||
NoDataReceived(super::ErrorLoc),
|
||||
ErrorResponse(super::ErrorLoc, ResponseCode),
|
||||
NoRRSIG(super::ErrorLoc),
|
||||
NoDNSKEY(super::ErrorLoc),
|
||||
NoDS(super::ErrorLoc),
|
||||
NoSOARecord(super::ErrorLoc, Name),
|
||||
SecNxDomain{ loc: super::ErrorLoc, proof: Vec<Record>},
|
||||
InvalidNsec(super::ErrorLoc),
|
||||
InvalidNsec3(super::ErrorLoc),
|
||||
NoNsec(super::ErrorLoc),
|
||||
}
|
||||
|
||||
impl fmt::Debug for ClientError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ClientError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ClientError::DecodeError(ref err) => err.fmt(f),
|
||||
ClientError::EncodeError(ref err) => err.fmt(f),
|
||||
ClientError::IoError(ref err) => err.fmt(f),
|
||||
ClientError::NotAllBytesSent{ sent, expect } => write!(f, "Not all bytes were sent: {}, expected: {}", sent, expect),
|
||||
ClientError::NotAllBytesReceived{ received, expect } => write!(f, "Not all bytes were sent: {}, expected: {}", received, expect),
|
||||
ClientError::IncorrectMessageId { got, expect } => write!(f, "IncorrectMessageId got: {}, expected: {}", got, expect),
|
||||
ClientError::TimedOut => write!(f, "TimedOut awaiting response from server(s)"),
|
||||
ClientError::NoAddress => write!(f, "No address received in response"),
|
||||
ClientError::NoNameServer => write!(f, "No name server address available"),
|
||||
ClientError::TimerError => write!(f, "Error setting timer"),
|
||||
ClientError::NoDataReceived => write!(f, "No data was received from the remote"),
|
||||
ClientError::ErrorResponse(response_code) => write!(f, "Response was an error: {}", response_code.to_str()),
|
||||
ClientError::NoRRSIG => write!(f, "No RRSIG was recieved"),
|
||||
ClientError::NoDS => write!(f, "No DS was recieved"),
|
||||
ClientError::NoDNSKEY => write!(f, "No DNSKEY proof available"),
|
||||
ClientError::NoSOARecord(ref name) => write!(f, "No SOA record found for {}", name),
|
||||
ClientError::SecNxDomain{..} => write!(f, "Verified secure non-existence"),
|
||||
ClientError::InvalidNsec => write!(f, "Can not validate NSEC records"),
|
||||
ClientError::InvalidNsec3 => write!(f, "Can not validate NSEC3 records"),
|
||||
ClientError::NoNsec => write!(f, "No NSEC(3) records to validate NXDOMAIN"),
|
||||
ClientError::DecodeError(ref err_loc, ref err) => write!(f, "{}:{}", err_loc, err),
|
||||
ClientError::EncodeError(ref err_loc, ref err) => write!(f, "{}:{}", err_loc, err),
|
||||
ClientError::IoError(ref err_loc, ref err) => write!(f, "{}:{}", err_loc, err),
|
||||
ClientError::NotAllBytesSent{ ref loc, sent, expect } => write!(f, "{}: Not all bytes were sent: {}, expected: {}", loc, sent, expect),
|
||||
ClientError::NotAllBytesReceived{ ref loc, received, expect } => write!(f, "{}: Not all bytes were sent: {}, expected: {}", loc, received, expect),
|
||||
ClientError::IncorrectMessageId { ref loc, got, expect } => write!(f, "{}: IncorrectMessageId got: {}, expected: {}", loc, got, expect),
|
||||
ClientError::TimedOut(ref loc) => write!(f, "{}: TimedOut awaiting response from server(s)", loc),
|
||||
ClientError::NoAddress(ref loc) => write!(f, "{}: No address received in response", loc),
|
||||
ClientError::NoNameServer(ref loc) => write!(f, "{}: No name server address available", loc),
|
||||
ClientError::TimerError(ref loc) => write!(f, "{}: Error setting timer", loc),
|
||||
ClientError::NoDataReceived(ref loc) => write!(f, "{}: No data was received from the remote", loc),
|
||||
ClientError::ErrorResponse(ref loc, response_code) => write!(f, "{}: Response was an error: {}", loc, response_code.to_str()),
|
||||
ClientError::NoRRSIG(ref loc) => write!(f, "{}: No RRSIG was recieved", loc),
|
||||
ClientError::NoDS(ref loc) => write!(f, "{}: No DS was recieved", loc),
|
||||
ClientError::NoDNSKEY(ref loc) => write!(f, "{}: No DNSKEY proof available", loc),
|
||||
ClientError::NoSOARecord(ref loc, ref name) => write!(f, "{}: No SOA record found for {}", loc, name),
|
||||
ClientError::SecNxDomain{ref loc, ..} => write!(f, "{}: Verified secure non-existence", loc),
|
||||
ClientError::InvalidNsec(ref loc) => write!(f, "{}: Can not validate NSEC records", loc),
|
||||
ClientError::InvalidNsec3(ref loc) => write!(f, "{}: Can not validate NSEC3 records", loc),
|
||||
ClientError::NoNsec(ref loc) => write!(f, "{}: No NSEC(3) records to validate NXDOMAIN", loc),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,53 +80,53 @@ impl fmt::Display for ClientError {
|
||||
impl Error for ClientError {
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
ClientError::DecodeError(ref err) => err.description(),
|
||||
ClientError::EncodeError(ref err) => err.description(),
|
||||
ClientError::IoError(ref err) => err.description(),
|
||||
ClientError::DecodeError(_, ref err) => err.description(),
|
||||
ClientError::EncodeError(_, ref err) => err.description(),
|
||||
ClientError::IoError(_, ref err) => err.description(),
|
||||
ClientError::NotAllBytesSent{ .. } => "Not all bytes were sent",
|
||||
ClientError::NotAllBytesReceived{ .. } => "Not all bytes were received",
|
||||
ClientError::IncorrectMessageId { .. } => "IncorrectMessageId received",
|
||||
ClientError::TimedOut => "TimedOut",
|
||||
ClientError::NoAddress => "NoAddress received",
|
||||
ClientError::NoNameServer => "No name server address available",
|
||||
ClientError::TimerError => "Error setting timer",
|
||||
ClientError::NoDataReceived => "No data was received from the remote",
|
||||
ClientError::TimedOut(..) => "TimedOut",
|
||||
ClientError::NoAddress(..) => "NoAddress received",
|
||||
ClientError::NoNameServer(..) => "No name server address available",
|
||||
ClientError::TimerError(..) => "Error setting timer",
|
||||
ClientError::NoDataReceived(..) => "No data was received from the remote",
|
||||
ClientError::ErrorResponse(..) => "Response was an error",
|
||||
ClientError::NoRRSIG => "No RRSIG was recieved",
|
||||
ClientError::NoDS => "No DS was recieved",
|
||||
ClientError::NoDNSKEY => "No DNSKEY proof available",
|
||||
ClientError::NoRRSIG(..) => "No RRSIG was recieved",
|
||||
ClientError::NoDS(..) => "No DS was recieved",
|
||||
ClientError::NoDNSKEY(..) => "No DNSKEY proof available",
|
||||
ClientError::NoSOARecord(..) => "No SOA record found",
|
||||
ClientError::SecNxDomain{ .. } => "Verified secure non-existence",
|
||||
ClientError::InvalidNsec => "Can not validate NSEC records",
|
||||
ClientError::InvalidNsec3 => "Can not validate NSEC3 records",
|
||||
ClientError::NoNsec => "No NSEC(3) records to validate NXDOMAIN",
|
||||
ClientError::InvalidNsec(..) => "Can not validate NSEC records",
|
||||
ClientError::InvalidNsec3(..) => "Can not validate NSEC3 records",
|
||||
ClientError::NoNsec(..) => "No NSEC(3) records to validate NXDOMAIN",
|
||||
}
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&Error> {
|
||||
match *self {
|
||||
ClientError::DecodeError(ref err) => Some(err),
|
||||
ClientError::EncodeError(ref err) => Some(err),
|
||||
ClientError::IoError(ref err) => Some(err),
|
||||
ClientError::DecodeError(_, ref err) => Some(err),
|
||||
ClientError::EncodeError(_, ref err) => Some(err),
|
||||
ClientError::IoError(_, ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<super::DecodeError> for ClientError {
|
||||
fn from(err: super::DecodeError) -> Self {
|
||||
ClientError::DecodeError(err)
|
||||
}
|
||||
}
|
||||
// impl From<super::DecodeError> for ClientError {
|
||||
// fn from(err: super::DecodeError) -> Self {
|
||||
// ClientError::DecodeError(error_loc!(), err)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl From<super::EncodeError> for ClientError {
|
||||
fn from(err: super::EncodeError) -> Self {
|
||||
ClientError::EncodeError(err)
|
||||
}
|
||||
}
|
||||
// impl From<super::EncodeError> for ClientError {
|
||||
// fn from(err: super::EncodeError) -> Self {
|
||||
// ClientError::EncodeError(err)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl From<io::Error> for ClientError {
|
||||
fn from(err: io::Error) -> Self {
|
||||
ClientError::IoError(err)
|
||||
}
|
||||
}
|
||||
// impl From<io::Error> for ClientError {
|
||||
// fn from(err: io::Error) -> Self {
|
||||
// ClientError::IoError(err)
|
||||
// }
|
||||
// }
|
||||
|
@ -21,7 +21,6 @@ use toml::ParserError;
|
||||
use toml::DecodeError;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConfigError {
|
||||
IoError(io::Error),
|
||||
ParserError(ParserError),
|
||||
@ -29,6 +28,12 @@ pub enum ConfigError {
|
||||
DecodeError(DecodeError),
|
||||
}
|
||||
|
||||
impl fmt::Debug for ConfigError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConfigError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -20,7 +20,6 @@ use std::string::FromUtf8Error;
|
||||
|
||||
use openssl::ssl::error::SslError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DecodeError {
|
||||
ParseUtf8Error(FromUtf8Error),
|
||||
UnknownDnsClassValue(u16),
|
||||
@ -41,6 +40,12 @@ pub enum DecodeError {
|
||||
SslError(SslError),
|
||||
}
|
||||
|
||||
impl fmt::Debug for DecodeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DecodeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -17,13 +17,18 @@
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EncodeError {
|
||||
CharacterDataTooLong(usize),
|
||||
LabelBytesTooLong(usize),
|
||||
DomainNameTooLong(usize),
|
||||
}
|
||||
|
||||
impl fmt::Debug for EncodeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for EncodeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -18,7 +18,6 @@ use std::fmt;
|
||||
use std::num;
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LexerError {
|
||||
ParseUtf8Error(FromUtf8Error),
|
||||
EscapedCharOutsideCharData,
|
||||
@ -34,6 +33,12 @@ pub enum LexerError {
|
||||
IllegalState(&'static str),
|
||||
}
|
||||
|
||||
impl fmt::Debug for LexerError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LexerError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
//! All defined errors for Trust-DNS
|
||||
|
||||
#[macro_use]
|
||||
mod base_error;
|
||||
mod decode_error;
|
||||
mod encode_error;
|
||||
mod client_error;
|
||||
@ -23,6 +25,7 @@ mod lexer_error;
|
||||
mod parse_error;
|
||||
mod config_error;
|
||||
|
||||
pub use self::base_error::ErrorLoc;
|
||||
pub use self::decode_error::DecodeError;
|
||||
pub use self::encode_error::EncodeError;
|
||||
pub use self::client_error::ClientError;
|
||||
|
@ -23,7 +23,6 @@ use super::DecodeError;
|
||||
use super::LexerError;
|
||||
use ::serialize::txt::Token;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParseError {
|
||||
LexerError(LexerError),
|
||||
DecodeError(DecodeError),
|
||||
@ -43,6 +42,12 @@ pub enum ParseError {
|
||||
ParseTimeError(String),
|
||||
}
|
||||
|
||||
impl fmt::Debug for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Display::fmt(&self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -25,6 +25,7 @@
|
||||
//! * Secure dynamic update
|
||||
//! * New features for securing public information
|
||||
|
||||
extern crate backtrace;
|
||||
extern crate chrono;
|
||||
extern crate data_encoding;
|
||||
#[macro_use] extern crate log;
|
||||
@ -35,6 +36,7 @@ extern crate rustc_serialize;
|
||||
extern crate toml;
|
||||
|
||||
|
||||
#[macro_use] pub mod error;
|
||||
pub mod logger;
|
||||
pub mod rr;
|
||||
pub mod authority;
|
||||
@ -43,7 +45,6 @@ pub mod udp;
|
||||
pub mod tcp;
|
||||
pub mod client;
|
||||
pub mod server;
|
||||
pub mod error;
|
||||
pub mod serialize;
|
||||
pub mod config;
|
||||
|
||||
|
@ -298,6 +298,7 @@ impl Message {
|
||||
/// to reduce errors in using the Message struct as an Update, this will do the call throughs
|
||||
/// to properly do that.
|
||||
pub trait UpdateMessage: Debug {
|
||||
fn get_id(&self) -> u16;
|
||||
fn add_zone(&mut self, query: Query);
|
||||
fn add_pre_requisite(&mut self, record: Record);
|
||||
fn add_all_pre_requisites(&mut self, vector: &[&Record]);
|
||||
@ -321,6 +322,7 @@ pub trait UpdateMessage: Debug {
|
||||
/// to reduce errors in using the Message struct as an Update, this will do the call throughs
|
||||
/// to properly do that.
|
||||
impl UpdateMessage for Message {
|
||||
fn get_id(&self) -> u16 { self.get_id() }
|
||||
fn add_zone(&mut self, query: Query) { self.add_query(query); }
|
||||
fn add_pre_requisite(&mut self, record: Record) { self.add_answer(record); }
|
||||
fn add_all_pre_requisites(&mut self, vector: &[&Record]) { self.add_all_answers(vector); }
|
||||
|
@ -47,15 +47,15 @@ impl TcpClientConnection {
|
||||
/// * `name_server` - address of the name server to use for queries
|
||||
pub fn new(name_server: SocketAddr) -> ClientResult<Self> {
|
||||
debug!("connecting to {:?}", name_server);
|
||||
let stream = try!(TcpStream::connect(&name_server));
|
||||
let stream = try_rethrow!(ClientError::IoError, TcpStream::connect(&name_server));
|
||||
|
||||
let mut event_loop: EventLoop<ClientHandler> = try!(EventLoop::new());
|
||||
let mut event_loop: EventLoop<ClientHandler> = try_rethrow!(ClientError::IoError, EventLoop::new());
|
||||
// TODO make the timeout configurable, 5 seconds is the dig default
|
||||
// TODO the error is private to mio, which makes this awkward...
|
||||
if event_loop.timeout_ms((), 5000).is_err() { return Err(ClientError::TimerError) };
|
||||
if event_loop.timeout_ms((), 5000).is_err() { return Err(ClientError::TimerError(error_loc!())) };
|
||||
// TODO: Linux requires a register before a reregister, reregister is needed b/c of OSX later
|
||||
// ideally this would not be added to the event loop until the client connection request.
|
||||
try!(event_loop.register(&stream, RESPONSE, EventSet::all(), PollOpt::all()));
|
||||
try_rethrow!(ClientError::IoError, event_loop.register(&stream, RESPONSE, EventSet::all(), PollOpt::all()));
|
||||
|
||||
Ok(TcpClientConnection{ handler: Some(TcpHandler::new_client_handler(stream)), event_loop: event_loop, error: None })
|
||||
}
|
||||
@ -66,7 +66,7 @@ impl ClientConnection for TcpClientConnection {
|
||||
self.error = None;
|
||||
// TODO: b/c of OSX this needs to be a reregister (since deregister is not working)
|
||||
// ideally it should be a register with the later deregister...
|
||||
try!(self.event_loop.reregister(self.handler.as_ref().expect("never none").get_stream(), RESPONSE, EventSet::all(), PollOpt::all()));
|
||||
try_rethrow!(ClientError::IoError, self.event_loop.reregister(self.handler.as_ref().expect("never none").get_stream(), RESPONSE, EventSet::all(), PollOpt::all()));
|
||||
// this is the request message, needs to be set each time
|
||||
// TODO: it would be cool to reuse this buffer.
|
||||
let mut handler = mem::replace(&mut self.handler, None).expect("never none");
|
||||
@ -75,7 +75,7 @@ impl ClientConnection for TcpClientConnection {
|
||||
let result = self.event_loop.run(&mut client_handler);
|
||||
self.handler = Some(client_handler.handler);
|
||||
|
||||
try!(result);
|
||||
try_rethrow!(ClientError::IoError, result);
|
||||
|
||||
if self.error.is_some() { return Err(mem::replace(&mut self.error, None).unwrap()) }
|
||||
Ok(self.handler.as_mut().expect("never none").remove_buffer())
|
||||
@ -151,13 +151,13 @@ impl Handler for ClientHandler {
|
||||
},
|
||||
_ => {
|
||||
error!("unrecognized token: {:?}", token);
|
||||
self.error = Some(ClientError::NoDataReceived);
|
||||
self.error = Some(ClientError::NoDataReceived(error_loc!()));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn timeout(&mut self, event_loop: &mut EventLoop<Self>, _: ()) {
|
||||
self.error = Some(ClientError::TimedOut);
|
||||
self.error = Some(ClientError::TimedOut(error_loc!()));
|
||||
event_loop.shutdown();
|
||||
}
|
||||
}
|
||||
|
@ -47,14 +47,14 @@ impl UdpClientConnection {
|
||||
let zero_addr = ("0.0.0.0", 0).to_socket_addrs().expect("could not parse 0.0.0.0 address").
|
||||
next().expect("no addresses parsed from 0.0.0.0");
|
||||
|
||||
let socket = try!(UdpSocket::bound(&zero_addr));
|
||||
let mut event_loop: EventLoop<Response> = try!(EventLoop::new());
|
||||
let socket = try_rethrow!(ClientError::IoError, UdpSocket::bound(&zero_addr));
|
||||
let mut event_loop: EventLoop<Response> = try_rethrow!(ClientError::IoError, EventLoop::new());
|
||||
// TODO make the timeout configurable, 5 seconds is the dig default
|
||||
// TODO the error is private to mio, which makes this awkward...
|
||||
if event_loop.timeout_ms((), 5000).is_err() { return Err(ClientError::TimerError) };
|
||||
if event_loop.timeout_ms((), 5000).is_err() { return Err(ClientError::TimerError(error_loc!())) };
|
||||
// TODO: Linux requires a register before a reregister, reregister is needed b/c of OSX later
|
||||
// ideally this would not be added to the event loop until the client connection request.
|
||||
try!(event_loop.register(&socket, RESPONSE, EventSet::readable(), PollOpt::all()));
|
||||
try_rethrow!(ClientError::IoError, event_loop.register(&socket, RESPONSE, EventSet::readable(), PollOpt::all()));
|
||||
|
||||
debug!("client event_loop created");
|
||||
|
||||
@ -66,20 +66,20 @@ impl ClientConnection for UdpClientConnection {
|
||||
fn send(&mut self, buffer: Vec<u8>) -> ClientResult<Vec<u8>> {
|
||||
debug!("client reregistering");
|
||||
// TODO: b/c of OSX this needs to be a reregister (since deregister is not working)
|
||||
try!(self.event_loop.reregister(self.socket.as_ref().expect("never none"), RESPONSE, EventSet::readable(), PollOpt::all()));
|
||||
try_rethrow!(ClientError::IoError, self.event_loop.reregister(self.socket.as_ref().expect("never none"), RESPONSE, EventSet::readable(), PollOpt::all()));
|
||||
debug!("client sending");
|
||||
try!(self.socket.as_ref().expect("never none").send_to(&buffer, &self.name_server));
|
||||
try_rethrow!(ClientError::IoError, self.socket.as_ref().expect("never none").send_to(&buffer, &self.name_server));
|
||||
debug!("client sent data");
|
||||
|
||||
let mut response: Response = Response::new(mem::replace(&mut self.socket, None).expect("never none"));
|
||||
|
||||
// run_once should be enough, if something else nepharious hits the socket, what?
|
||||
try!(self.event_loop.run(&mut response));
|
||||
try_rethrow!(ClientError::IoError, self.event_loop.run(&mut response));
|
||||
debug!("client event_loop running");
|
||||
|
||||
|
||||
if response.error.is_some() { return Err(response.error.unwrap()) }
|
||||
if response.buf.is_none() { return Err(ClientError::NoDataReceived) }
|
||||
if response.buf.is_none() { return Err(ClientError::NoDataReceived(error_loc!())) }
|
||||
let result = Ok(response.buf.unwrap());
|
||||
//debug!("client deregistering");
|
||||
// TODO: when this line is added OSX starts failing, but we should have it...
|
||||
@ -127,14 +127,14 @@ impl Handler for Response {
|
||||
if recv_result.is_err() {
|
||||
// debug b/c we're returning the error explicitly
|
||||
debug!("could not recv_from on {:?}: {:?}", self.socket, recv_result);
|
||||
self.error = Some(recv_result.unwrap_err().into());
|
||||
self.error = Some(ClientError::IoError(error_loc!(), recv_result.unwrap_err()));
|
||||
return
|
||||
}
|
||||
|
||||
if recv_result.as_ref().unwrap().is_none() {
|
||||
// debug b/c we're returning the error explicitly
|
||||
debug!("no return address on recv_from: {:?}", self.socket);
|
||||
self.error = Some(ClientError::NoAddress);
|
||||
self.error = Some(ClientError::NoAddress(error_loc!()));
|
||||
return
|
||||
}
|
||||
|
||||
@ -156,13 +156,13 @@ impl Handler for Response {
|
||||
},
|
||||
_ => {
|
||||
error!("unrecognized token: {:?}", token);
|
||||
self.error = Some(ClientError::NoDataReceived);
|
||||
self.error = Some(ClientError::NoDataReceived(error_loc!()));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn timeout(&mut self, event_loop: &mut EventLoop<Self>, _: ()) {
|
||||
self.error = Some(ClientError::TimedOut);
|
||||
self.error = Some(ClientError::TimedOut(error_loc!()));
|
||||
event_loop.shutdown();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user