1use crate::{
2 builder::ConnectBuilder, error::*,
3 DtDataBuilder
4};
5use bytes::{Buf, BufMut, BytesMut};
6use num_enum::{IntoPrimitive, TryFromPrimitive};
7use std::fmt::Debug;
8
9#[derive(Debug, Eq, PartialEq)]
10pub struct CoptFrame<F: Debug + Eq + PartialEq> {
11 pub pdu_type: PduType<F>
12}
13
14impl<F: Debug + Eq + PartialEq> CoptFrame<F> {
15 pub fn builder_of_dt_data(
16 payload: F
17 ) -> DtDataBuilder<F> {
18 DtDataBuilder::new(payload)
19 }
20
21 pub fn builder_of_connect()
22 -> ConnectBuilder<F> {
23 ConnectBuilder::<F>::default()
24 }
25
26 pub fn length(&self) -> u8 {
27 self.pdu_type.length()
28 }
29}
30
31#[derive(Debug, Eq, PartialEq)]
32pub enum PduType<F: Debug + Eq + PartialEq> {
33 ConnectRequest(ConnectComm),
35 ConnectConfirm(ConnectComm),
37 DtData(DtData<F>)
39}
40
41impl<F: Debug + Eq + PartialEq> PduType<F> {
42 pub fn length(&self) -> u8 {
43 match self {
44 PduType::ConnectRequest(conn) => {
45 conn.length()
46 },
47 PduType::ConnectConfirm(conn) => {
48 conn.length()
49 },
50 PduType::DtData(_) => 2
51 }
52 }
53}
54#[derive(Debug, Eq, PartialEq)]
55pub struct DtData<F: Debug + Eq + PartialEq> {
56 pub(crate) tpdu_number: u8,
57 pub(crate) last_data_unit: bool,
58 pub(crate) payload: F
59}
60
61impl<F: Debug + Eq + PartialEq> DtData<F> {
62 pub fn tpdu_number(&self) -> u8 {
63 self.tpdu_number
64 }
65
66 pub fn last_data_unit(&self) -> bool {
67 self.last_data_unit
68 }
69
70 pub fn payload(self) -> F {
71 self.payload
72 }
73}
74
75#[derive(Debug, Eq, PartialEq)]
76pub struct ConnectComm {
77 pub destination_ref: [u8; 2],
78 pub source_ref: [u8; 2],
79 pub class: u8,
80 pub extended_formats: bool,
81 pub no_explicit_flow_control: bool,
82 pub parameters: Vec<Parameter>
83}
84
85impl ConnectComm {
86 pub fn length(&self) -> u8 {
87 6 + self
88 .parameters
89 .iter()
90 .fold(0, |x, item| x + item.length())
91 }
92
93 pub(crate) fn decode(
94 src: &mut BytesMut
95 ) -> Result<Self> {
96 if src.len() < 5 {
97 return Err(Error::Error(
98 "data not enough".to_string()
99 ));
100 }
101 let destination_ref =
102 [src.get_u8(), src.get_u8()];
103 let source_ref =
104 [src.get_u8(), src.get_u8()];
105 let merge = src.get_u8();
106 let class = merge >> 4;
107 let extended_formats =
108 merge << 6 >> 7 > 0;
109 let no_explicit_flow_control =
110 merge & 1 > 0;
111
112 let mut parameters = Vec::new();
113 while let Some(parameter) =
114 Parameter::decode(src)?
115 {
116 parameters.push(parameter);
117 }
118 Ok(Self {
119 destination_ref,
120 source_ref,
121 class,
122 extended_formats,
123 no_explicit_flow_control,
124 parameters
125 })
126 }
127
128 pub(crate) fn encode(
129 &self,
130 dst: &mut BytesMut
131 ) {
132 dst.put_slice(
133 self.destination_ref.as_ref()
134 );
135 dst.put_slice(self.source_ref.as_ref());
136
137 let merge = self.class << 4
138 & if self.extended_formats {
139 2
140 } else {
141 0
142 }
143 & if self.no_explicit_flow_control {
144 1
145 } else {
146 0
147 };
148 dst.put_u8(merge);
149 self.parameters
150 .iter()
151 .for_each(|x| x.encode(dst));
152 }
153}
154
155#[derive(Debug, Eq, PartialEq)]
157pub enum Parameter {
158 TpduSize(TpduSize),
169 SrcTsap(Vec<u8>),
171 DstTsap(Vec<u8>)
173}
174
175#[derive(
176 Debug,
177 Clone,
178 Copy,
179 Eq,
180 PartialEq,
181 TryFromPrimitive,
182 IntoPrimitive,
183)]
184#[repr(u8)]
185pub enum TpduSize {
186 L8192 = 0b0000_1101,
187 L4096 = 0b0000_1100,
188 L2048 = 0b0000_1011,
189 L1024 = 0b0000_1010,
190 L512 = 0b0000_1001,
191 L256 = 0b0000_1000,
192 L128 = 0b0000_0111
193}
194
195impl TpduSize {
196 pub fn pdu_ref(&self) -> u16 {
197 match self {
198 TpduSize::L8192 => 8192,
199 TpduSize::L4096 => 4096,
200 TpduSize::L2048 => 2048,
201 TpduSize::L1024 => 1024,
202 TpduSize::L512 => 512,
203 TpduSize::L256 => 256,
204 TpduSize::L128 => 128
205 }
206 }
207}
208
209impl Parameter {
210 pub fn new_dst_tsap(data: Vec<u8>) -> Self {
211 Self::DstTsap(data)
212 }
213
214 pub fn new_src_tsap(data: Vec<u8>) -> Self {
215 Self::SrcTsap(data)
216 }
217
218 pub fn new_tpdu_size(size: TpduSize) -> Self {
219 Self::TpduSize(size)
220 }
221
222 pub fn length(&self) -> u8 {
223 match self {
224 Parameter::TpduSize(_) => 3u8,
225 Parameter::SrcTsap(data) => {
226 2 + data.len() as u8
227 },
228 Parameter::DstTsap(data) => {
229 2 + data.len() as u8
230 },
231 }
232 }
233
234 fn decode(
235 dst: &mut BytesMut
236 ) -> Result<Option<Self>> {
237 if dst.len() == 0 {
238 return Ok(None);
239 }
240 let (Some(ty), Some(length)) = (dst.get(0), dst.get(1)) else {
241 return Err(Error::Error("data not enough".to_string()));
242 };
243 let length = (length + 2) as usize;
244 let ty = *ty;
245 if dst.len() < length {
246 return Err(Error::Error(
247 "data not enough".to_string()
248 ));
249 }
250 let mut data =
251 dst.split_to(length).split_off(2);
252 match ty {
253 0xc0 => {
254 let size = data.get_u8();
255 Ok(Some(Self::TpduSize(
256 size.try_into()?
257 )))
258 },
259 0xc1 => Ok(Some(Self::SrcTsap(
260 data.to_vec()
261 ))),
262 0xc2 => Ok(Some(Self::DstTsap(
263 data.to_vec()
264 ))),
265 _ => {
266 return Err(Error::Error(
267 format!(
268 "not support parameter: \
269 {}",
270 ty
271 )
272 ));
273 }
274 }
275 }
276
277 fn encode(&self, dst: &mut BytesMut) {
278 match self {
279 Parameter::TpduSize(data) => {
280 dst.put_u8(0xc0);
281 dst.put_u8(1u8);
282 dst.put_u8(data.clone().into())
283 },
284 Parameter::SrcTsap(data) => {
285 dst.put_u8(0xc1);
286 dst.put_u8(data.len() as u8);
287 dst.extend_from_slice(
288 data.as_ref()
289 )
290 },
291 Parameter::DstTsap(data) => {
292 dst.put_u8(0xc2);
293 dst.put_u8(data.len() as u8);
294 dst.extend_from_slice(
295 data.as_ref()
296 )
297 }
298 }
299 }
300}