1use super::ber::{self, BerReader, BerWriter, Class, tags};
9use super::isp1::Credentials;
10use super::types::{BindResult, ServiceType, SleError, Time};
11
12const MAX_ID_LEN: usize = 64;
14
15#[derive(Copy, Clone, Debug, PartialEq, Eq)]
17#[repr(u8)]
18pub enum RequestedFrameQuality {
19 GoodOnly = 0,
21 ErredOnly = 1,
23 AllFrames = 2,
25}
26
27impl RequestedFrameQuality {
28 pub fn from_i64(v: i64) -> Result<Self, SleError> {
30 match v {
31 0 => Ok(Self::GoodOnly),
32 1 => Ok(Self::ErredOnly),
33 2 => Ok(Self::AllFrames),
34 _ => Err(SleError::InvalidEnumValue),
35 }
36 }
37}
38
39#[derive(Copy, Clone, Debug, PartialEq, Eq)]
42#[repr(u8)]
43pub enum RafOp {
44 Bind = 0,
46 BindReturn = 1,
48 Unbind = 2,
50 UnbindReturn = 3,
52 Start = 4,
54 StartReturn = 5,
56 Stop = 6,
58 StopReturn = 7,
60 TransferBuffer = 8,
62 StatusReport = 9,
64}
65
66#[derive(Clone, Debug)]
68pub struct RafBindInvocation {
69 pub initiator_id: [u8; MAX_ID_LEN],
71 pub initiator_id_len: usize,
73 pub responder_id: [u8; MAX_ID_LEN],
75 pub responder_id_len: usize,
77 pub service_type: ServiceType,
79 pub version: u16,
81 pub credentials: Option<Credentials>,
83}
84
85impl RafBindInvocation {
86 pub fn new(
88 initiator_id: &[u8],
89 responder_id: &[u8],
90 service_type: ServiceType,
91 version: u16,
92 credentials: Option<Credentials>,
93 ) -> Result<Self, SleError> {
94 if initiator_id.len() > MAX_ID_LEN
95 || responder_id.len() > MAX_ID_LEN
96 {
97 return Err(SleError::TooLong);
98 }
99 let mut init = [0u8; MAX_ID_LEN];
100 init[..initiator_id.len()]
101 .copy_from_slice(initiator_id);
102 let mut resp = [0u8; MAX_ID_LEN];
103 resp[..responder_id.len()]
104 .copy_from_slice(responder_id);
105 Ok(Self {
106 initiator_id: init,
107 initiator_id_len: initiator_id.len(),
108 responder_id: resp,
109 responder_id_len: responder_id.len(),
110 service_type,
111 version,
112 credentials,
113 })
114 }
115
116 pub fn initiator_id(&self) -> &[u8] {
118 &self.initiator_id[..self.initiator_id_len]
119 }
120
121 pub fn responder_id(&self) -> &[u8] {
123 &self.responder_id[..self.responder_id_len]
124 }
125
126 pub fn encode(
129 &self,
130 buf: &mut [u8],
131 ) -> Result<usize, SleError> {
132 let mut w = BerWriter::new(buf);
133 let outer = w.begin_context(
134 RafOp::Bind as u8,
135 true,
136 )?;
137 let seq = w.begin_sequence()?;
138
139 match &self.credentials {
141 None => w.write_null()?,
142 Some(cred) => {
143 let cred_seq = w.begin_sequence()?;
144 w.write_octet_string(&cred.time)?;
145 w.write_integer(cred.random as i64)?;
146 w.write_octet_string(&cred.hash)?;
147 w.end_sequence(cred_seq)?;
148 }
149 }
150
151 w.write_octet_string(self.initiator_id())?;
152 w.write_octet_string(self.responder_id())?;
153 w.write_enum(self.service_type as i64)?;
154 w.write_integer(self.version as i64)?;
155
156 w.end_sequence(seq)?;
157 w.end_sequence(outer)?;
158 Ok(w.len())
159 }
160
161 pub fn decode(buf: &[u8]) -> Result<Self, SleError> {
163 let mut r = BerReader::new(buf);
164
165 let (tag, _len) = r.read_context_tag()?;
167 if tag != RafOp::Bind as u8 {
168 return Err(SleError::UnexpectedTag);
169 }
170
171 let _seq_len = r.read_sequence()?;
172
173 let (peek_tag, peek_class, _) = r.peek_tag()?;
175 let credentials = if peek_tag == tags::NULL
176 && peek_class == Class::Universal
177 {
178 r.read_null()?;
179 None
180 } else {
181 let _cred_len = r.read_sequence()?;
182 let time_bytes = r.read_octet_string()?;
183 let random = r.read_integer()? as u32;
184 let hash_bytes = r.read_octet_string()?;
185 let mut time = [0u8; 8];
186 if time_bytes.len() != 8 {
187 return Err(SleError::Truncated);
188 }
189 time.copy_from_slice(time_bytes);
190 let mut hash = [0u8; 20];
191 if hash_bytes.len() != 20 {
192 return Err(SleError::Truncated);
193 }
194 hash.copy_from_slice(hash_bytes);
195 Some(Credentials { time, random, hash })
196 };
197
198 let initiator = r.read_octet_string()?;
199 let responder = r.read_octet_string()?;
200 let service_type =
201 ServiceType::from_u8(r.read_enum()? as u8)?;
202 let version = r.read_integer()? as u16;
203
204 Self::new(
205 initiator,
206 responder,
207 service_type,
208 version,
209 credentials,
210 )
211 }
212}
213
214#[derive(Copy, Clone, Debug, PartialEq, Eq)]
216pub struct RafBindReturn {
217 pub result: BindResult,
219 pub credentials: Option<Credentials>,
221}
222
223impl RafBindReturn {
224 pub fn encode(
226 &self,
227 buf: &mut [u8],
228 ) -> Result<usize, SleError> {
229 let mut w = BerWriter::new(buf);
230 let outer = w.begin_context(
231 RafOp::BindReturn as u8,
232 true,
233 )?;
234 let seq = w.begin_sequence()?;
235
236 match &self.credentials {
237 None => w.write_null()?,
238 Some(cred) => {
239 let cred_seq = w.begin_sequence()?;
240 w.write_octet_string(&cred.time)?;
241 w.write_integer(cred.random as i64)?;
242 w.write_octet_string(&cred.hash)?;
243 w.end_sequence(cred_seq)?;
244 }
245 }
246
247 w.write_enum(self.result as i64)?;
248
249 w.end_sequence(seq)?;
250 w.end_sequence(outer)?;
251 Ok(w.len())
252 }
253
254 pub fn decode(buf: &[u8]) -> Result<Self, SleError> {
256 let mut r = BerReader::new(buf);
257
258 let (tag, _len) = r.read_context_tag()?;
259 if tag != RafOp::BindReturn as u8 {
260 return Err(SleError::UnexpectedTag);
261 }
262
263 let _seq_len = r.read_sequence()?;
264
265 let (peek_tag, peek_class, _) = r.peek_tag()?;
266 let credentials = if peek_tag == tags::NULL
267 && peek_class == Class::Universal
268 {
269 r.read_null()?;
270 None
271 } else {
272 let _cred_len = r.read_sequence()?;
273 let time_bytes = r.read_octet_string()?;
274 let random = r.read_integer()? as u32;
275 let hash_bytes = r.read_octet_string()?;
276 let mut time = [0u8; 8];
277 time.copy_from_slice(
278 time_bytes.get(..8).ok_or(SleError::Truncated)?,
279 );
280 let mut hash = [0u8; 20];
281 hash.copy_from_slice(
282 hash_bytes
283 .get(..20)
284 .ok_or(SleError::Truncated)?,
285 );
286 Some(Credentials { time, random, hash })
287 };
288
289 let result =
290 BindResult::from_u8(r.read_enum()? as u8)?;
291
292 Ok(Self {
293 result,
294 credentials,
295 })
296 }
297}
298
299#[derive(Copy, Clone, Debug, PartialEq, Eq)]
301pub struct RafStartInvocation {
302 pub start_time: Option<Time>,
304 pub stop_time: Option<Time>,
306 pub quality: RequestedFrameQuality,
308 pub credentials: Option<Credentials>,
310}
311
312impl RafStartInvocation {
313 pub fn encode(
315 &self,
316 buf: &mut [u8],
317 ) -> Result<usize, SleError> {
318 let mut w = BerWriter::new(buf);
319 let outer = w.begin_context(
320 RafOp::Start as u8,
321 true,
322 )?;
323 let seq = w.begin_sequence()?;
324
325 match &self.credentials {
326 None => w.write_null()?,
327 Some(cred) => {
328 let cred_seq = w.begin_sequence()?;
329 w.write_octet_string(&cred.time)?;
330 w.write_integer(cred.random as i64)?;
331 w.write_octet_string(&cred.hash)?;
332 w.end_sequence(cred_seq)?;
333 }
334 }
335
336 match &self.start_time {
338 None => w.write_null()?,
339 Some(t) => w.write_octet_string(&t.cds)?,
340 }
341
342 match &self.stop_time {
344 None => w.write_null()?,
345 Some(t) => w.write_octet_string(&t.cds)?,
346 }
347
348 w.write_enum(self.quality as i64)?;
349
350 w.end_sequence(seq)?;
351 w.end_sequence(outer)?;
352 Ok(w.len())
353 }
354
355 pub fn decode(buf: &[u8]) -> Result<Self, SleError> {
357 let mut r = BerReader::new(buf);
358
359 let (tag, _len) = r.read_context_tag()?;
360 if tag != RafOp::Start as u8 {
361 return Err(SleError::UnexpectedTag);
362 }
363
364 let _seq_len = r.read_sequence()?;
365
366 let (peek_tag, peek_class, _) = r.peek_tag()?;
368 let credentials = if peek_tag == tags::NULL
369 && peek_class == Class::Universal
370 {
371 r.read_null()?;
372 None
373 } else {
374 let _cred_len = r.read_sequence()?;
375 let time_bytes = r.read_octet_string()?;
376 let random = r.read_integer()? as u32;
377 let hash_bytes = r.read_octet_string()?;
378 let mut time = [0u8; 8];
379 time.copy_from_slice(
380 time_bytes.get(..8).ok_or(SleError::Truncated)?,
381 );
382 let mut hash = [0u8; 20];
383 hash.copy_from_slice(
384 hash_bytes
385 .get(..20)
386 .ok_or(SleError::Truncated)?,
387 );
388 Some(Credentials { time, random, hash })
389 };
390
391 let (pt, _, _) = r.peek_tag()?;
393 let start_time = if pt == tags::NULL {
394 r.read_null()?;
395 None
396 } else {
397 let bytes = r.read_octet_string()?;
398 let (t, _) = Time::decode(bytes)?;
399 Some(t)
400 };
401
402 let (pt, _, _) = r.peek_tag()?;
404 let stop_time = if pt == tags::NULL {
405 r.read_null()?;
406 None
407 } else {
408 let bytes = r.read_octet_string()?;
409 let (t, _) = Time::decode(bytes)?;
410 Some(t)
411 };
412
413 let quality =
414 RequestedFrameQuality::from_i64(r.read_enum()?)?;
415
416 Ok(Self {
417 start_time,
418 stop_time,
419 quality,
420 credentials,
421 })
422 }
423}
424
425#[derive(Clone, Debug)]
427pub struct RafTransferDataInvocation {
428 pub earth_receive_time: Time,
430 pub data_link_continuity: i16,
432 frame_buf: [u8; Self::MAX_FRAME_LEN],
434 frame_len: usize,
436}
437
438impl RafTransferDataInvocation {
439 pub const MAX_FRAME_LEN: usize = 2048;
441
442 pub fn new(
444 earth_receive_time: Time,
445 data_link_continuity: i16,
446 frame: &[u8],
447 ) -> Result<Self, SleError> {
448 if frame.len() > Self::MAX_FRAME_LEN {
449 return Err(SleError::TooLong);
450 }
451 let mut frame_buf = [0u8; Self::MAX_FRAME_LEN];
452 frame_buf[..frame.len()].copy_from_slice(frame);
453 Ok(Self {
454 earth_receive_time,
455 data_link_continuity,
456 frame_buf,
457 frame_len: frame.len(),
458 })
459 }
460
461 pub fn frame(&self) -> &[u8] {
463 &self.frame_buf[..self.frame_len]
464 }
465
466 pub fn encode(
468 &self,
469 buf: &mut [u8],
470 ) -> Result<usize, SleError> {
471 let mut w = BerWriter::new(buf);
472 let seq = w.begin_sequence()?;
473 w.write_octet_string(&self.earth_receive_time.cds)?;
474 w.write_integer(
475 self.data_link_continuity as i64,
476 )?;
477 w.write_octet_string(self.frame())?;
478 w.end_sequence(seq)?;
479 Ok(w.len())
480 }
481
482 pub fn decode(buf: &[u8]) -> Result<Self, SleError> {
484 let mut r = BerReader::new(buf);
485 let _seq_len = r.read_sequence()?;
486
487 let time_bytes = r.read_octet_string()?;
488 let (ert, _) = Time::decode(time_bytes)?;
489 let continuity = r.read_integer()? as i16;
490 let frame_data = r.read_octet_string()?;
491
492 Self::new(ert, continuity, frame_data)
493 }
494}
495
496pub struct RafTransferBuffer;
502
503impl RafTransferBuffer {
504 pub fn decode_header(
509 buf: &[u8],
510 ) -> Result<(usize, usize), SleError> {
511 let mut r = BerReader::new(buf);
512 let (tag, _class, _, _consumed) =
514 ber::decode_tag(&buf[r.pos()..])?;
515 if tag != RafOp::TransferBuffer as u8 {
516 return Err(SleError::UnexpectedTag);
517 }
518 r.read_tag()?;
519 let content_len = r.read_length()?;
520 Ok((content_len, r.pos()))
521 }
522}
523
524#[cfg(test)]
525mod tests {
526 use super::*;
527
528 #[test]
529 fn bind_invocation_roundtrip() {
530 let bind = RafBindInvocation::new(
531 b"user1",
532 b"gs-station",
533 ServiceType::RafOnline,
534 5,
535 None,
536 )
537 .unwrap();
538
539 let mut buf = [0u8; 256];
540 let n = bind.encode(&mut buf).unwrap();
541
542 let decoded =
543 RafBindInvocation::decode(&buf[..n]).unwrap();
544 assert_eq!(decoded.initiator_id(), b"user1");
545 assert_eq!(decoded.responder_id(), b"gs-station");
546 assert_eq!(
547 decoded.service_type,
548 ServiceType::RafOnline,
549 );
550 assert_eq!(decoded.version, 5);
551 assert!(decoded.credentials.is_none());
552 }
553
554 #[test]
555 fn bind_return_roundtrip() {
556 let ret = RafBindReturn {
557 result: BindResult::Success,
558 credentials: None,
559 };
560 let mut buf = [0u8; 64];
561 let n = ret.encode(&mut buf).unwrap();
562
563 let decoded =
564 RafBindReturn::decode(&buf[..n]).unwrap();
565 assert_eq!(decoded.result, BindResult::Success);
566 assert!(decoded.credentials.is_none());
567 }
568
569 #[test]
570 fn start_invocation_roundtrip() {
571 let start = RafStartInvocation {
572 start_time: None,
573 stop_time: None,
574 quality: RequestedFrameQuality::AllFrames,
575 credentials: None,
576 };
577 let mut buf = [0u8; 128];
578 let n = start.encode(&mut buf).unwrap();
579
580 let decoded =
581 RafStartInvocation::decode(&buf[..n]).unwrap();
582 assert!(decoded.start_time.is_none());
583 assert!(decoded.stop_time.is_none());
584 assert_eq!(
585 decoded.quality,
586 RequestedFrameQuality::AllFrames,
587 );
588 }
589
590 #[test]
591 fn transfer_data_roundtrip() {
592 let frame_data = [0xDE, 0xAD, 0xBE, 0xEF];
593 let td = RafTransferDataInvocation::new(
594 Time::from_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
595 -1,
596 &frame_data,
597 )
598 .unwrap();
599
600 let mut buf = [0u8; 128];
601 let n = td.encode(&mut buf).unwrap();
602
603 let decoded =
604 RafTransferDataInvocation::decode(&buf[..n])
605 .unwrap();
606 assert_eq!(decoded.frame(), &frame_data);
607 assert_eq!(decoded.data_link_continuity, -1);
608 assert_eq!(
609 decoded.earth_receive_time,
610 Time::from_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
611 );
612 }
613}