1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#[cfg(test)]
mod tests;
pub mod avp;
mod control_message;
pub use control_message::ControlMessage;
mod data_message;
pub use data_message::DataMessage;
mod flags;
use flags::{Flags, MessageFlagType};
use crate::common::{Reader, ResultStr, Writer};
#[derive(Debug, Eq, PartialEq)]
pub enum Message<'a> {
Control(ControlMessage),
Data(DataMessage<'a>),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ValidateReserved {
Yes,
No,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ValidateVersion {
Yes,
No,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ValidateUnused {
Yes,
No,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ValidationOptions {
pub reserved: ValidateReserved,
pub version: ValidateVersion,
pub unused: ValidateUnused,
}
impl<'a> Message<'a> {
const PROTOCOL_VERSION: u8 = 2;
#[inline]
pub fn try_read<'b>(reader: &'b mut impl Reader<'a>) -> ResultStr<Self> {
Self::try_read_validate(
reader,
ValidationOptions {
reserved: ValidateReserved::No,
version: ValidateVersion::Yes,
unused: ValidateUnused::No,
},
)
}
#[inline]
pub fn try_read_validate<'b>(
reader: &'b mut impl Reader<'a>,
validation_options: ValidationOptions,
) -> ResultStr<Self> {
let flags = Flags::read(reader)?;
if let ValidateVersion::Yes = validation_options.version {
let version = flags.get_version();
if version != Self::PROTOCOL_VERSION {
return Err("Invalid version encountered");
}
}
if let ValidateReserved::Yes = validation_options.reserved {
if !flags.reserved_bits_ok() {
return Err("Invalid reserved bits encountered");
}
}
match flags.get_type() {
MessageFlagType::Data => Ok(Message::Data(DataMessage::try_read(flags, reader)?)),
MessageFlagType::Control => Ok(Message::Control(ControlMessage::try_read(
flags,
validation_options,
reader,
)?)),
}
}
#[inline]
pub unsafe fn write(&self, writer: &mut impl Writer) {
match self {
Message::Control(control) => control.write(Self::PROTOCOL_VERSION, writer),
Message::Data(data) => data.write(Self::PROTOCOL_VERSION, writer),
}
}
}