added error location to all ClientErrors

This commit is contained in:
Benjamin Fry 2016-05-28 02:07:52 -07:00
parent 8ff4935079
commit 896ab32dd2
18 changed files with 229 additions and 133 deletions

32
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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.

View File

@ -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);

View File

@ -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)
}

View File

@ -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
View 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)
}
}

View File

@ -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)
// }
// }

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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); }

View File

@ -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();
}
}

View File

@ -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();
}
}