use serialize::hex::{ ToHex };
use self::PacketType::{ Command, Answer, Error };
use crypto;
+use utils::from_elem;
+#[derive(Show, Copy)]
pub enum Variant {
Weak, // The MAC is computed on data without padding.
Fixed // The MAC is computed on data and padding.
}
// There are all the errors that may occur when reading an encrypted and authenticated packet.
-#[deriving(Show)]
+#[derive(Show)]
pub enum ReadingError {
IO(io::IoError),
UnknownPacketType, // If the first byte is unknown.
// A macro to return a 'Err(ReadingError::IO(..))' in case of error.
macro_rules! try_read_io(
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(ReadingError::IO(e)) })
-)
+);
// There are all the errors that may occur when encrypting, authenticating and writing a packet.
-#[deriving(Show)]
+#[derive(Show)]
pub enum WritingError {
IO(io::IoError),
Encrypt,
// A macro to return a 'Err(WritingError::IO(..))' in case of error.
macro_rules! try_write_io(
($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(WritingError::IO(e)) })
-)
+);
pub type ReadingResult = Result<Packet, ReadingError>;
pub type WritingResult = Result<(), WritingError>;
static MAX_PAYLOAD_SIZE: uint = 39;
static FIXED_PACKET_SIZE: uint = 1 + 8 + 10; // Packet type + timestamp + MAC.
-#[deriving(Show, Clone)]
+#[derive(Show, Clone)]
pub struct PacketData {
id: u8,
payload: Vec<u8> // The size can vary from 'MIN_PAYLOAD_SIZE' to 'MAX_PAYLOAD_SIZE' bytes.
}
-#[deriving(Show, Clone)]
+#[derive(Show, Clone)]
pub enum ErrorType {
Crypt,
Auth
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum PacketType {
Command(PacketData),
Answer(PacketData),
/// |I|C...C| for weak variant
/// |I|C...C|P...P|for fixed variant
/// |0000000000000000| for error packet
-#[deriving(Show)]
+#[derive(Show)]
pub struct Packet {
pub t: PacketType,
pub timestamp: u64
-}
+}
impl fmt::Show for PacketType {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
&Command(ref data) => write!(formatter, "Command {{ {} }}", data_to_str(data)),
&Answer(ref data) => write!(formatter, "Answer {{ {} }}", data_to_str(data)),
- &Error(error_type) => write!(formatter, "Error {{ errorType: {} }}", error_type)
+ &Error(ref error_type) => write!(formatter, "Error {{ errorType: {} }}", error_type)
}
}
}
impl Packet {
pub fn random_packet_data(seed: &[uint]) -> PacketData {
let mut rng = if seed.is_empty() { StdRng::new().unwrap() } else { SeedableRng::from_seed(seed) };
- let mut payload = Vec::from_elem(distributions::Range::new(MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE + 1).ind_sample(&mut rng), 0u8);
- rng.fill_bytes(payload.as_mut_slice_());
+ let mut payload = from_elem(distributions::Range::new(MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE + 1).ind_sample(&mut rng), 0u8);
+ rng.fill_bytes(payload.as_mut_slice());
PacketData {
id: rng.gen::<u8>(),
payload: payload
let mut data =
match self.t {
Command(ref p) | Answer(ref p) => packet_data(p),
- Error(_) => Vec::from_elem(16, 0) // Padding as data: 16 * 0.
+ Error(_) => from_elem(16, 0) // Padding as data: 16 * 0.
};
let data_size = data.len();
let timestamp = try_read_io!(input.read_be_u64());
- let mut encrypted_data = Vec::from_elem(data_size as uint - FIXED_PACKET_SIZE, 0u8);
- if try_read_io!(input.read(encrypted_data.as_mut_slice_())) != encrypted_data.len() {
+ let mut encrypted_data = from_elem(data_size as uint - FIXED_PACKET_SIZE, 0u8);
+ if try_read_io!(input.read(encrypted_data.as_mut_slice())) != encrypted_data.len() {
return Err(ReadingError::UnconsistentEncryptedSize)
}
let mut data = match crypto::decrypt(encrypted_data.as_slice(), iv_from_timestamp(timestamp).as_slice()) {
};
// Reads the MAC.
- let mut mac_read = [0u8, ..10];
+ let mut mac_read = [0u8; 10];
if try_read_io!(input.read(&mut mac_read)) != mac_read.len() {
return Err(ReadingError::UnconsistentMACSize)
}
_ => {
if data.len() != 16 {
return Err(ReadingError::UnconsistentDataSize)
- } else if data != Vec::from_elem(16, 0) {
+ } else if data != from_elem(16, 0) {
return Err(ReadingError::Data)
}
match packet_type { 0x0A => Error(ErrorType::Crypt), _ => Error(ErrorType::Auth) }