All tests passing for Messages

This commit is contained in:
Benjamin Fry 2015-08-18 11:33:55 -07:00
parent b6c1ad2117
commit d781deceee
11 changed files with 56 additions and 39 deletions

View File

@ -65,6 +65,26 @@ impl Message {
pub fn add_name_server(&mut self, record: Record) -> &mut Self { self.name_servers.push(record); self }
pub fn add_additional(&mut self, record: Record) -> &mut Self { self.additionals.push(record); self }
/// this is necessary to match the counts in the header from the record sections
/// this happens implicitly on write_to, so no need to call before write_to
pub fn update_counts(&mut self) -> &mut Self {
self.header = self.update_header_counts();
self
}
fn update_header_counts(&self) -> Header {
assert!(self.queries.len() <= u16::max_value() as usize);
assert!(self.answers.len() <= u16::max_value() as usize);
assert!(self.name_servers.len() <= u16::max_value() as usize);
assert!(self.additionals.len() <= u16::max_value() as usize);
self.header.clone(
self.queries.len() as u16,
self.answers.len() as u16,
self.name_servers.len() as u16,
self.additionals.len() as u16)
}
pub fn parse(data: &mut Vec<u8>) -> Self {
let header = Header::parse(data);
@ -98,24 +118,8 @@ impl Message {
}
pub fn write_to(&self, buf: &mut Vec<u8>) {
assert!(self.queries.len() <= u16::max_value() as usize);
assert!(self.answers.len() <= u16::max_value() as usize);
assert!(self.name_servers.len() <= u16::max_value() as usize);
assert!(self.additionals.len() <= u16::max_value() as usize);
// clone the header to set the counts lazily
self.header.clone(
self.queries.len() as u16,
self.answers.len() as u16,
self.name_servers.len() as u16,
self.additionals.len() as u16).write_to(buf);
// self.header.write_to(buf);
//
// assert_eq!(self.header.getQueryCount() as usize, self.queries.len());
// assert_eq!(self.header.getAnswerCount() as usize, self.answers.len());
// assert_eq!(self.header.getNameServerCount() as usize, self.name_servers.len());
// assert_eq!(self.header.getAdditionalCount() as usize, self.additionals.len());
self.update_header_counts().write_to(buf);
for q in &self.queries {
q.write_to(buf);
@ -154,7 +158,7 @@ fn test_write_and_parse_query() {
let mut message = Message::new();
message.id(10).message_type(MessageType::Response).op_code(OpCode::Update).
authoritative(true).truncated(true).recursion_desired(true).recursion_available(true).
response_code(ResponseCode::ServFail).add_query(Query::new()); // we're not testing the query parsing, just message
response_code(ResponseCode::ServFail).add_query(Query::new()).update_counts(); // we're not testing the query parsing, just message
let mut buf: Vec<u8> = Vec::new();
message.write_to(&mut buf);
@ -173,9 +177,9 @@ fn test_write_and_parse_records() {
response_code(ResponseCode::ServFail);
message.add_answer(Record::new());
message.add_name_server(Record::new());
message.add_additional(Record::new());
//message.add_name_server(Record::new());
//message.add_additional(Record::new());
message.update_counts(); // needed for the comparison...
let mut buf: Vec<u8> = Vec::new();
message.write_to(&mut buf);

View File

@ -46,9 +46,9 @@ pub struct Query {
}
impl Query {
/// return a default query with an empty name and ANY, ANY for the query_type and query_class
/// return a default query with an empty name and A, IN for the query_type and query_class
pub fn new() -> Self {
Query { name: Name::new(), query_type: RecordType::ANY, query_class: DNSClass::ANY }
Query { name: Name::new(), query_type: RecordType::A, query_class: DNSClass::IN }
}
/// replaces name with the new name

View File

@ -34,7 +34,7 @@ pub fn write_to(mx: &RData, buf: &mut Vec<u8>) {
util::write_u16_to(buf, *preference);
exchange.write_to(buf);
} else {
panic!();
panic!("wrong type here {:?}", mx);
}
}

View File

@ -33,6 +33,6 @@ pub fn write_to(ns: &RData, buf: &mut Vec<u8>) {
if let RData::NS{ ref nsdname } = *ns {
nsdname.write_to(buf);
} else {
panic!()
panic!("wrong type here {:?}", ns);
}
}

View File

@ -18,3 +18,13 @@ use super::super::record_data::RData;
pub fn parse(data: &mut Vec<u8>) -> RData {
unimplemented!()
}
pub fn write_to(nil: &RData, buf: &mut Vec<u8>) {
if let RData::NULL{ref anything} = *nil {
for b in anything {
buf.push(*b);
}
} else {
panic!("wrong type here {:?}", nil);
}
}

View File

@ -27,6 +27,6 @@ pub fn write_to(ptr: &RData, buf: &mut Vec<u8>) {
if let RData::PTR { ref ptrdname } = *ptr {
ptrdname.write_to(buf);
} else {
panic!()
panic!("wrong type here {:?}", ptr);
}
}

View File

@ -90,6 +90,6 @@ pub fn write_to(soa: &RData, buf: &mut Vec<u8>) {
util::write_i32_to(buf, *expire);
util::write_u32_to(buf, *minimum);
} else {
panic!()
panic!("wrong type here {:?}", soa);
}
}

View File

@ -33,6 +33,6 @@ pub fn write_to(txt: &RData, buf: &mut Vec<u8>) {
util::write_character_data_to(buf, s);
}
} else {
panic!()
panic!("wrong type here {:?}", txt);
}
}

View File

@ -321,7 +321,7 @@ impl RData {
RecordType::TXT => rdata::txt::parse(data, rd_length),
RecordType::A => rdata::a::parse(data),
RecordType::AAAA => rdata::aaaa::parse(data),
_ => unimplemented!()
_ => panic!("unsupported RecordType: {:?}", rtype)
}
}
@ -329,14 +329,14 @@ impl RData {
match *self {
RData::CNAME{ref cname} => rdata::cname::write_to(self, buf),
RData::MX{ref preference,ref exchange} => rdata::mx::write_to(self, buf),
// RData::NULL => rdata::null::write_to(self, buf),
RData::NULL{ref anything} => rdata::null::write_to(self, buf),
RData::NS{ref nsdname} => rdata::ns::write_to(self, buf),
RData::PTR{ref ptrdname} => rdata::ptr::write_to(self, buf),
RData::SOA{ref mname, ref rname, ref serial, ref refresh, ref retry, ref expire, ref minimum} => rdata::soa::write_to(self, buf),
RData::TXT{ ref txt_data } => rdata::txt::write_to(self, buf),
RData::A{ ref address } => rdata::a::write_to(self, buf),
RData::AAAA{ ref address } => rdata::aaaa::write_to(self, buf),
_ => unimplemented!()
_ => panic!("unsupported RecordType: {:?}", self)
}
}
}
@ -352,7 +352,7 @@ impl<'a> From<&'a RData> for RecordType {
RData::TXT{ref txt_data } => RecordType::TXT,
RData::A{ref address } => RecordType::A,
RData::AAAA{ref address } => RecordType::AAAA,
_ => unimplemented!()
_ => panic!("unsupported RecordType: {:?}", rdata)
}
}
}

View File

@ -82,7 +82,7 @@ impl From<RecordType> for &'static str {
RecordType::NS => "NS",
RecordType::SOA => "SOA",
RecordType::ANY => "ANY",
_ => unimplemented!(),
_ => panic!("unsupported RecordType: {:?}", rt),
}
}
}
@ -109,7 +109,7 @@ impl<'a> From<&'a str> for RecordType {
"SOA" => RecordType::SOA,
"ANY" => RecordType::ANY,
"*" => RecordType::ANY,
_ => unimplemented!(),
_ => panic!("unsupported RecordType: {:?}", str),
}
}
}
@ -135,7 +135,7 @@ impl From<RecordType> for u16 {
RecordType::NS => 2,
RecordType::SOA => 6,
RecordType::ANY => 255,
_ => unimplemented!(),
_ => panic!("unsupported RecordType: {:?}", rt),
}
}
}
@ -161,7 +161,7 @@ impl From<u16> for RecordType {
2 => RecordType::NS,
6 => RecordType::SOA,
255 => RecordType::ANY,
_ => unimplemented!(),
_ => panic!("unsupported RecordType: {:?}", value),
}
}
}

View File

@ -1,6 +1,7 @@
use std::io::Read;
use std::iter;
use std::slice::{IterMut,Iter};
use std::net::Ipv4Addr;
use super::record_data::RData;
use super::record_type::RecordType;
@ -76,14 +77,16 @@ pub struct Record {
impl Record {
/**
* Creates a not very useful empty record, use the setters to build a more useful object
* There are no optional elements in this object, defaults are an empty name, type A, class IN,
* ttl of 0 and the 0.0.0.0 ip address.
*/
pub fn new() -> Record {
Record {
name_labels: domain::Name::new(),
rr_type: RecordType::ANY,
dns_class: DNSClass::ANY,
rr_type: RecordType::A,
dns_class: DNSClass::IN,
ttl: 0,
rdata: RData::NULL { anything: vec![] }
rdata: RData::A { address: Ipv4Addr::new(0,0,0,0) }
}
}