Skip to main content

rusty_cosp/packet/
parameters.rs

1use bitfield::bitfield;
2use strum::IntoStaticStr;
3
4use crate::api::CospError;
5
6#[derive(Debug, IntoStaticStr)]
7pub(crate) enum SessionPduParameter {
8    // We are treating the PDU tpyes as parameters as their tags do not conflict and they follow the same encoding rules.
9    // The main difference is that the order of concatenation is not determined by the tag. So serialize and deserialize is different.
10    Connect(Vec<SessionPduParameter>),
11    OverflowAccept(Vec<SessionPduParameter>),
12    ConnectDataOverflow(Vec<SessionPduParameter>),
13    Accept(Vec<SessionPduParameter>),
14    GiveTokens(),
15    DataTransfer(Vec<SessionPduParameter>),
16
17    ConnectAcceptItemParameter(Vec<SessionPduParameter>),
18
19    ProtocolOptionsParameter(ProtocolOptionsField),
20    TsduMaximumSizeParameter(TsduMaximumSizeField),
21    VersionNumberParameter(VersionNumberField),
22    // ReasonCodeParameter(ReasonCode), TODO
23    SessionUserRequirementsParameter(SessionUserRequirementsField),
24    CallingSessionSelectorParameter(Vec<u8>),
25    CalledSessionSelectorParameter(Vec<u8>),
26    UserDataParameter(Vec<u8>),
27    ExtendedUserDataParameter(Vec<u8>),
28    DataOverflowParameter(DataOverflowField),
29    EnclosureParameter(EnclosureField),
30
31    Unknown,
32}
33
34// ---
35// Utilities
36
37pub(crate) fn encode_length(length: usize) -> Result<Vec<u8>, CospError> {
38    if length > u16::MAX as usize {
39        Err(CospError::InternalError(format!("Parameter length is greater than max length {}", length)).into())
40    } else if length < 255 {
41        Ok(vec![length as u8])
42    } else {
43        let length_bytes = (length as u16).to_be_bytes();
44        Ok(vec![0xFF, length_bytes[0], length_bytes[1]])
45    }
46}
47
48#[macro_export]
49macro_rules! serialise_parameter_value {
50    ($code: expr, $parameter_value: expr) => {{
51        let mut buffer: VecDeque<u8> = VecDeque::new();
52
53        let encoded_value = $parameter_value.to_be_bytes();
54
55        buffer.push_back($code);
56        buffer.extend(encode_length(encoded_value.len())?);
57        buffer.extend(encoded_value);
58
59        Result::<Vec<u8>, CospError>::Ok(buffer.drain(..).collect())
60    }};
61}
62
63// ---
64// Protocol Options
65
66bitfield! {
67    pub(crate) struct ProtocolOptionsField(u8);
68
69    impl new;
70    impl Debug;
71
72    pub(crate) extended_concatenated_spdu_support, _ : 0;
73    pub(crate) reserved, _ : 7, 1;
74}
75
76// ---
77// TSDU Maximum Size
78
79bitfield! {
80    pub(crate) struct TsduMaximumSizeField(u32);
81
82    impl new;
83    impl Debug;
84
85    u16;
86    pub(crate) to_initiator, set_to_initiator : 15, 0;
87    pub(crate) to_responder, set_to_responder : 31, 16;
88}
89
90// ---
91// Version Number
92
93bitfield! {
94    pub(crate) struct VersionNumberField(u8);
95
96    impl new;
97    impl Debug;
98
99    pub(crate) version1, _ : 0;
100    pub(crate) version2, _ : 1;
101    pub(crate) reserved, _ : 7, 2;
102}
103
104// ---
105// Reason Code
106
107// TODO
108// #[derive(Debug, IntoStaticStr)]
109// pub(crate) enum ReasonCode {
110//     RejectionByCalledSsUser,
111//     RejectionByCalledSsUserDueToTemporaryCongestion,
112//     RejectionByCalledSsUserWithData(Vec<u8>),
113//     SessionSelectorUnknown,
114//     SsUserNotAttachedToSsap,
115//     SpmCongestionAtConnectTime,
116//     ProposedProtocolVersionsNotSupported,
117//     RejectionByTheSpm,
118//     RejectionByTheSpm2,
119//     Unknown(u8),
120// }
121
122// impl ReasonCode {
123//     pub(crate) fn new(code: u8, user_data: &[u8]) -> Self {
124//         match code {
125//             0 => ReasonCode::RejectionByCalledSsUser,
126//             1 => ReasonCode::RejectionByCalledSsUserDueToTemporaryCongestion,
127//             2 => ReasonCode::RejectionByCalledSsUserWithData(user_data.to_vec()),
128//             129 => ReasonCode::SessionSelectorUnknown,
129//             130 => ReasonCode::SsUserNotAttachedToSsap,
130//             131 => ReasonCode::SpmCongestionAtConnectTime,
131//             132 => ReasonCode::ProposedProtocolVersionsNotSupported,
132//             133 => ReasonCode::RejectionByTheSpm,
133//             134 => ReasonCode::RejectionByTheSpm2,
134//             x => ReasonCode::Unknown(x),
135//         }
136//     }
137// }
138
139// impl TryFrom<&ReasonCode> for Vec<u8> {
140//     type Error = CospError;
141
142//     fn try_from(value: &ReasonCode) -> Result<Self, Self::Error> {
143//         let mut buffer = VecDeque::new();
144
145//         let code = match value {
146//             ReasonCode::RejectionByCalledSsUser => 0,
147//             ReasonCode::RejectionByCalledSsUserDueToTemporaryCongestion => 1,
148//             ReasonCode::RejectionByCalledSsUserWithData(_) => 2,
149//             ReasonCode::SessionSelectorUnknown => 129,
150//             ReasonCode::SsUserNotAttachedToSsap => 130,
151//             ReasonCode::SpmCongestionAtConnectTime => 131,
152//             ReasonCode::ProposedProtocolVersionsNotSupported => 132,
153//             ReasonCode::RejectionByTheSpm => 133,
154//             ReasonCode::RejectionByTheSpm2 => 134,
155//             ReasonCode::Unknown(code) => *code,
156//         };
157
158//         let empty_vec = vec![];
159//         let user_data = match value {
160//             ReasonCode::RejectionByCalledSsUserWithData(user_data) => user_data,
161//             _ => &empty_vec,
162//         };
163
164//         buffer.push_back(REASON_CODE_PARAMETER_CODE);
165//         buffer.extend(encode_length(1 + user_data.len())?);
166//         buffer.push_back(code);
167//         buffer.extend(user_data);
168
169//         Ok(buffer.into_iter().collect())
170//     }
171// }
172
173// ---
174// Session User Requirements
175
176bitfield! {
177    pub(crate) struct SessionUserRequirementsField(u16);
178
179    impl new;
180    impl Debug;
181
182    pub(crate) half_duplex, _ : 0;
183    pub(crate) full_duplex, _ : 1;
184    pub(crate) expedited, _ : 2;
185    pub(crate) minor_synchronize, _ : 3;
186    pub(crate) major_synchronize, _ : 4;
187    pub(crate) resynchronize, _ : 5;
188    pub(crate) activity_management, _ : 6;
189    pub(crate) negotiated_release, _ : 7;
190    pub(crate) capability_data, _ : 8;
191    pub(crate) exceptions, _ : 9;
192    pub(crate) typed_data, _ : 10;
193    pub(crate) reserved, _ : 15, 11;
194}
195
196impl Clone for SessionUserRequirementsField {
197    fn clone(&self) -> Self {
198        Self(self.0)
199    }
200}
201
202impl Copy for SessionUserRequirementsField {}
203
204impl Default for SessionUserRequirementsField {
205    fn default() -> Self {
206        Self(0x0349) // Default as per X.225
207    }
208}
209
210// ---
211// Data Overflow Field
212
213bitfield! {
214    #[derive(Debug)]
215    pub(crate) struct DataOverflowField(u8);
216
217    pub(crate) more_data, _ : 0; // The only valid value is true
218    pub(crate) reserved, _ : 7, 1;
219}
220
221impl Clone for DataOverflowField {
222    fn clone(&self) -> Self {
223        Self(self.0)
224    }
225}
226
227impl Copy for DataOverflowField {}
228
229impl Default for DataOverflowField {
230    fn default() -> Self {
231        Self(0x01)
232    }
233}
234
235// --
236// Enclosure Field
237
238bitfield! {
239    #[derive(Debug)]
240    pub(crate) struct EnclosureField(u8);
241
242    pub(crate) begining, _ : 0; // The only valid value is false
243    pub(crate) end, _ : 1;
244    pub(crate) reserved, _ : 7, 2;
245}
246
247impl Clone for EnclosureField {
248    fn clone(&self) -> Self {
249        Self(self.0)
250    }
251}
252
253impl Copy for EnclosureField {}
254
255impl Default for EnclosureField {
256    fn default() -> Self {
257        Self(0x02)
258    }
259}