1use crate::packet::PacketError::VersionInHeaderConflicted;
2use crate::serializer::{Serializable, SerializeError};
3use crate::{header, v1, v2, version};
4use thiserror::Error;
5
6#[derive(Error, Debug, PartialEq)]
7pub enum PacketError {
8 #[error("version in the header conflicted")]
9 VersionInHeaderConflicted,
10 #[error("the number of RIP entries exceeds the maximum number. it allows to have the entries up to 25 in a packet")]
11 MaxRIPEntriesNumberExceeded,
12}
13
14#[derive(PartialEq, Debug)]
15pub struct Packet<T> {
16 header: header::Header,
17 entries: Vec<T>,
18}
19
20impl<T> Packet<T> {
21 fn new(header: header::Header, entries: Vec<T>) -> Result<Self, PacketError> {
22 if entries.len() > 25 {
23 return Err(PacketError::MaxRIPEntriesNumberExceeded);
24 }
25
26 Ok(Packet { header, entries })
27 }
28
29 pub fn get_header(&self) -> &header::Header {
30 &self.header
31 }
32
33 pub fn get_entries(&self) -> &Vec<T> {
34 &self.entries
35 }
36}
37
38impl Packet<v1::Entry> {
39 pub fn make_v1_packet(
40 header: header::Header,
41 entries: Vec<v1::Entry>,
42 ) -> Result<Self, PacketError> {
43 let ver = header.get_version();
44 if ver != version::Version::Version1 {
45 return Err(VersionInHeaderConflicted);
46 }
47 Packet::new(header, entries)
48 }
49}
50
51impl Packet<v2::Entry> {
52 pub fn make_v2_packet(
53 header: header::Header,
54 entries: Vec<v2::Entry>,
55 ) -> Result<Self, PacketError> {
56 let ver = header.get_version();
57 if ver != version::Version::Version2 {
58 return Err(VersionInHeaderConflicted);
59 }
60 Packet::new(header, entries)
61 }
62}
63
64impl<T: Serializable> Serializable for Packet<T> {
65 fn to_bytes(&self) -> Result<Vec<u8>, SerializeError> {
66 let mut entries_bytes = vec![];
67
68 for entry in self.get_entries() {
69 entries_bytes.extend(entry.to_bytes()?);
70 }
71
72 Ok([self.get_header().to_bytes()?, entries_bytes].concat())
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use crate::address_family::Identifier;
79 use crate::header::Header;
80 use crate::packet::{Packet, PacketError};
81 use crate::serializer::Serializable;
82 use crate::{command, v1, version};
83 use std::net::Ipv4Addr;
84
85 #[test]
86 fn test_make_v1_packet_on_version_conflict() {
87 assert_eq!(
88 Packet::make_v1_packet(
89 Header::new(command::Kind::Response, version::Version::Version2),
90 vec![]
91 )
92 .unwrap_err(),
93 PacketError::VersionInHeaderConflicted
94 );
95 }
96
97 #[test]
98 fn test_make_v2_packet_on_version_conflict() {
99 assert_eq!(
100 Packet::make_v2_packet(
101 Header::new(command::Kind::Response, version::Version::Version1),
102 vec![]
103 )
104 .unwrap_err(),
105 PacketError::VersionInHeaderConflicted
106 );
107 }
108
109 #[test]
110 fn test_max_entries_num_exceeded() {
111 let result = Packet::new(
112 Header::new(command::Kind::Response, version::Version::Version1),
113 vec![
114 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 101), 1),
115 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 102), 2),
116 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 103), 3),
117 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 104), 4),
118 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 105), 5),
119 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 106), 6),
120 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 107), 7),
121 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 108), 8),
122 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 109), 9),
123 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 110), 10),
124 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 111), 11),
125 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 112), 12),
126 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 113), 13),
127 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 114), 14),
128 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 115), 15),
129 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 116), 16),
130 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 117), 17),
131 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 118), 18),
132 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 119), 19),
133 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 120), 20),
134 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 121), 21),
135 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 122), 22),
136 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 123), 23),
137 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 124), 24),
138 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 125), 25),
139 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 126), 26),
140 ],
141 );
142 assert_eq!(
143 result.unwrap_err(),
144 PacketError::MaxRIPEntriesNumberExceeded
145 )
146 }
147
148 #[test]
149 fn test_parse_single_packet() {
150 let packet = Packet::new(
151 Header::new(command::Kind::Response, version::Version::Version1),
152 vec![v1::Entry::new(
153 Identifier::IP,
154 Ipv4Addr::new(192, 0, 2, 101),
155 1,
156 )],
157 )
158 .unwrap();
159
160 assert_eq!(
161 packet.to_bytes().unwrap(),
162 vec![
163 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x00, 0x02, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, ]
170 );
171 }
172
173 #[test]
174 fn test_parse_multi_packets() {
175 let packet = Packet::new(
176 Header::new(command::Kind::Response, version::Version::Version1),
177 vec![
178 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 101), 1),
179 v1::Entry::new(Identifier::IP, Ipv4Addr::new(192, 0, 2, 102), 2),
180 ],
181 )
182 .unwrap();
183
184 assert_eq!(
185 packet.to_bytes().unwrap(),
186 vec![
187 0x02, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x00, 0x02, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0xc0, 0x00, 0x02, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, ]
199 );
200 }
201}