1use super::bbheader::{BBHeader, SisMis, TsGs};
10use bytes::Bytes;
11use std::io::{Read, Result};
12use std::net::UdpSocket;
13
14#[allow(unused_imports)]
16use std::net::TcpStream;
17
18pub const HEADER_MAX_LEN: usize = 64;
25
26pub const BBFRAME_MAX_LEN: usize = 7274 + HEADER_MAX_LEN;
34
35#[derive(Debug)]
41pub struct BBFrameDefrag<R> {
42 recv_fragment: R,
43 buffer: Box<[u8; BBFRAME_MAX_LEN]>,
44 occupied_bytes: usize,
45 validator: BBFrameValidator,
46 header_bytes: usize,
47}
48
49#[derive(Debug)]
54pub struct BBFrameRecv<R> {
55 recv_bbframe: R,
56 buffer: Box<[u8; BBFRAME_MAX_LEN]>,
57 validator: BBFrameValidator,
58 header_bytes: usize,
59}
60
61#[derive(Debug)]
66pub struct BBFrameStream<R> {
67 recv_stream: R,
68 buffer: Box<[u8; BBFRAME_MAX_LEN]>,
69 validator: BBFrameValidator,
70 header_bytes: usize,
71}
72
73pub trait BBFrameReceiver {
78 fn get_bbframe(&mut self) -> Result<BBFrame>;
80}
81
82#[derive(Debug, Default)]
87pub struct BBFrameValidator {
88 isi: Option<u8>,
89 log_bbheader_crc_errors: bool,
90}
91
92impl BBFrameValidator {
93 pub fn new() -> BBFrameValidator {
95 BBFrameValidator::default()
96 }
97
98 pub fn set_isi(&mut self, isi: Option<u8>) {
107 self.isi = isi;
108 }
109
110 pub fn set_log_bbheader_crc_errors(&mut self, log_bbheader_crc_errors: bool) {
119 self.log_bbheader_crc_errors = log_bbheader_crc_errors;
120 }
121
122 pub fn bbheader_is_valid(&self, bbheader: BBHeader) -> bool {
141 if !bbheader.crc_is_valid() {
142 if self.log_bbheader_crc_errors {
143 log::warn!("BBHEADER CRC error");
144 }
145 return false;
146 }
147 log::trace!("received {} with valid CRC", bbheader);
148 if !matches!(bbheader.tsgs(), TsGs::GenericContinuous | TsGs::GseHem) {
149 log::error!(
150 "unsupported TS/GS type '{}' (only 'Generic continous' and 'GSE-HEM' are supported)",
151 bbheader.tsgs()
152 );
153 return false;
154 }
155 match self.isi {
156 None => {
157 if !matches!(bbheader.sismis(), SisMis::Sis) {
158 log::error!("MIS (multiple input stream) BBFRAME unsupported in SIS mode");
159 return false;
160 }
161 }
162 Some(isi) => {
163 if !matches!(bbheader.sismis(), SisMis::Mis) {
164 log::error!("SIS (single input stream) BBFRAME unsupported in MIS mode");
165 return false;
166 }
167 if bbheader.isi() != isi {
168 log::debug!("dropping BBFRAME with ISI = {}", bbheader.isi());
169 return false;
170 }
171 }
172 }
173 if !matches!(bbheader.tsgs(), TsGs::GseHem) && bbheader.issyi() {
174 log::error!("ISSYI only supported in GSE-HEM mode");
175 return false;
176 }
177 if bbheader.dfl() % 8 != 0 {
178 log::error!("unsupported data field length not a multiple of 8 bits");
179 return false;
180 }
181 if usize::from(bbheader.dfl() / 8) > BBFRAME_MAX_LEN - BBHeader::LEN - HEADER_MAX_LEN {
182 log::error!("DFL value {} too large", bbheader.dfl());
183 return false;
184 }
185 true
186 }
187}
188
189pub type BBFrame = Bytes;
194
195pub trait RecvFragment {
206 fn recv_fragment(&mut self, buf: &mut [u8]) -> Result<usize>;
213}
214
215impl RecvFragment for UdpSocket {
216 fn recv_fragment(&mut self, buf: &mut [u8]) -> Result<usize> {
217 self.recv_from(buf).map(|x| x.0)
218 }
219}
220
221impl<F> RecvFragment for F
222where
223 F: FnMut(&mut [u8]) -> Result<usize>,
224{
225 fn recv_fragment(&mut self, buf: &mut [u8]) -> Result<usize> {
226 self(buf)
227 }
228}
229
230pub trait RecvBBFrame {
240 fn recv_bbframe(&mut self, buf: &mut [u8; BBFRAME_MAX_LEN]) -> Result<usize>;
246}
247
248impl RecvBBFrame for UdpSocket {
249 fn recv_bbframe(&mut self, buf: &mut [u8; BBFRAME_MAX_LEN]) -> Result<usize> {
250 self.recv_from(&mut buf[..]).map(|x| x.0)
251 }
252}
253
254impl<F> RecvBBFrame for F
255where
256 F: FnMut(&mut [u8; BBFRAME_MAX_LEN]) -> Result<usize>,
257{
258 fn recv_bbframe(&mut self, buf: &mut [u8; BBFRAME_MAX_LEN]) -> Result<usize> {
259 self(buf)
260 }
261}
262
263pub trait RecvStream {
274 fn recv_stream(&mut self, buf: &mut [u8]) -> Result<()>;
276}
277
278impl<R: Read> RecvStream for R {
279 fn recv_stream(&mut self, buf: &mut [u8]) -> Result<()> {
280 self.read_exact(buf)
281 }
282}
283
284trait BBFrameRecvCommon {
285 fn buffer(&self) -> &[u8; BBFRAME_MAX_LEN];
286
287 fn bbheader(&self) -> BBHeader {
288 BBHeader::new(self.buffer()[..BBHeader::LEN].try_into().unwrap())
289 }
290}
291
292macro_rules! impl_recv_common {
293 ($($id:ident),*) => {
294 $(
295 impl<R> BBFrameRecvCommon for $id<R> {
296 fn buffer(&self) -> &[u8; BBFRAME_MAX_LEN] {
297 &self.buffer
298 }
299 }
300 )*
301 }
302}
303
304impl_recv_common!(BBFrameDefrag, BBFrameRecv, BBFrameStream);
305
306macro_rules! impl_set_isi {
307 ($t:ident) => {
308 pub fn set_isi(&mut self, isi: Option<u8>) {
317 self.validator.set_isi(isi);
318 }
319 };
320}
321
322impl<R> BBFrameDefrag<R> {
323 pub fn new(recv_fragment: R) -> BBFrameDefrag<R> {
328 BBFrameDefrag {
329 recv_fragment,
330 buffer: Box::new([0; BBFRAME_MAX_LEN]),
331 occupied_bytes: 0,
332 validator: BBFrameValidator::new(),
333 header_bytes: 0,
334 }
335 }
336
337 impl_set_isi!(BBFrameDefrag);
338
339 pub fn set_header_bytes(&mut self, header_bytes: usize) -> Result<()> {
348 if header_bytes > HEADER_MAX_LEN {
349 log::error!("header bytes larger than maximum header size");
350 return Err(std::io::Error::new(
351 std::io::ErrorKind::InvalidData,
352 "header bytes larger than maximum header size",
353 ));
354 }
355 self.header_bytes = header_bytes;
356 Ok(())
357 }
358}
359
360impl<R: RecvFragment> BBFrameReceiver for BBFrameDefrag<R> {
361 fn get_bbframe(&mut self) -> Result<BBFrame> {
367 loop {
368 self.occupied_bytes = 0;
369 while self.occupied_bytes < BBHeader::LEN {
372 self.recv()?;
373 }
374 if !self.validator.bbheader_is_valid(self.bbheader()) {
375 continue;
376 }
377 let bbframe_len = usize::from(self.bbheader().dfl() / 8) + BBHeader::LEN;
378 while self.occupied_bytes < bbframe_len {
379 self.recv()?;
380 }
381 let bbframe = Bytes::copy_from_slice(&self.buffer[..bbframe_len]);
382 log::trace!("completed BBFRAME {}", faster_hex::hex_string(&bbframe));
383 return Ok(bbframe);
384 }
385 }
386}
387
388impl<R: RecvFragment> BBFrameDefrag<R> {
389 fn recv(&mut self) -> Result<()> {
390 let n = self
391 .recv_fragment
392 .recv_fragment(&mut self.buffer[self.occupied_bytes..])?;
393 if self.header_bytes != 0 {
394 if self.header_bytes > n {
395 log::error!("received a fragment smaller than the header size");
396 return Err(std::io::Error::new(
397 std::io::ErrorKind::InvalidData,
398 "BBFRAME is too short",
399 ));
400 }
401 self.buffer.copy_within(
403 self.occupied_bytes + self.header_bytes..self.occupied_bytes + n,
404 self.occupied_bytes,
405 );
406 }
407 self.occupied_bytes += n - self.header_bytes;
408 Ok(())
409 }
410}
411
412impl<R> BBFrameRecv<R> {
413 pub fn new(recv_bbframe: R) -> BBFrameRecv<R> {
418 let mut validator = BBFrameValidator::new();
419 validator.set_log_bbheader_crc_errors(true);
420 BBFrameRecv {
421 recv_bbframe,
422 buffer: Box::new([0; BBFRAME_MAX_LEN]),
423 validator,
424 header_bytes: 0,
425 }
426 }
427
428 impl_set_isi!(BBFrameRecv);
429
430 pub fn set_header_bytes(&mut self, header_bytes: usize) -> Result<()> {
438 if header_bytes > HEADER_MAX_LEN {
439 log::error!("header bytes larger than maximum header size");
440 return Err(std::io::Error::new(
441 std::io::ErrorKind::InvalidData,
442 "header bytes larger than maximum header size",
443 ));
444 }
445 self.header_bytes = header_bytes;
446 Ok(())
447 }
448}
449
450impl<R: RecvBBFrame> BBFrameReceiver for BBFrameRecv<R> {
451 fn get_bbframe(&mut self) -> Result<BBFrame> {
458 let recv_len = self.recv_bbframe.recv_bbframe(&mut self.buffer)?;
459 if self.header_bytes != 0 {
460 if self.header_bytes > recv_len {
461 log::error!("received a fragment smaller than the header size");
462 return Err(std::io::Error::new(
463 std::io::ErrorKind::InvalidData,
464 "BBFRAME is too short",
465 ));
466 }
467 self.buffer.copy_within(self.header_bytes..recv_len, 0);
470 }
471 let recv_len = recv_len - self.header_bytes;
472 if recv_len < BBHeader::LEN {
473 log::error!("received BBFRAME is too short (length {recv_len})");
474 return Err(std::io::Error::new(
475 std::io::ErrorKind::InvalidData,
476 "BBFRAME is too short",
477 ));
478 }
479 if !self.validator.bbheader_is_valid(self.bbheader()) {
480 return Err(std::io::Error::new(
481 std::io::ErrorKind::InvalidData,
482 "invalid BBFRAME received",
483 ));
484 }
485 let bbframe_len = usize::from(self.bbheader().dfl() / 8) + BBHeader::LEN;
486 if recv_len < bbframe_len {
487 log::error!(
488 "received BBFRAME has length {recv_len}, \
489 but according to DFL it should have length {bbframe_len}"
490 );
491 return Err(std::io::Error::new(
492 std::io::ErrorKind::InvalidData,
493 "BBFRAME is too short",
494 ));
495 }
496 let bbframe = Bytes::copy_from_slice(&self.buffer[..bbframe_len]);
497 log::trace!("completed BBFRAME {}", faster_hex::hex_string(&bbframe));
498 Ok(bbframe)
499 }
500}
501
502impl<R> BBFrameStream<R> {
503 pub fn new(recv_stream: R) -> BBFrameStream<R> {
508 let mut validator = BBFrameValidator::new();
509 validator.set_log_bbheader_crc_errors(true);
510 BBFrameStream {
511 recv_stream,
512 buffer: Box::new([0; BBFRAME_MAX_LEN]),
513 validator,
514 header_bytes: 0,
515 }
516 }
517
518 impl_set_isi!(BBFrameStream);
519
520 pub fn set_header_bytes(&mut self, header_bytes: usize) -> Result<()> {
525 if header_bytes > HEADER_MAX_LEN {
526 log::error!("header bytes larger than maximum header size");
527 return Err(std::io::Error::new(
528 std::io::ErrorKind::InvalidData,
529 "header bytes larger than maximum header size",
530 ));
531 }
532 self.header_bytes = header_bytes;
533 Ok(())
534 }
535}
536
537impl<R: RecvStream> BBFrameReceiver for BBFrameStream<R> {
538 fn get_bbframe(&mut self) -> Result<BBFrame> {
545 if self.header_bytes != 0 {
546 self.recv_stream
548 .recv_stream(&mut self.buffer[..self.header_bytes])?;
549 }
550 self.recv_stream
552 .recv_stream(&mut self.buffer[..BBHeader::LEN])?;
553 if !self.validator.bbheader_is_valid(self.bbheader()) {
554 let bbframe_len = usize::from(self.bbheader().dfl() / 8) + BBHeader::LEN;
557 if bbframe_len <= BBFRAME_MAX_LEN {
558 self.recv_stream
559 .recv_stream(&mut self.buffer[BBHeader::LEN..bbframe_len])?;
560 }
561 return Err(std::io::Error::new(
562 std::io::ErrorKind::InvalidData,
563 "invalid BBHEADER received",
564 ));
565 }
566 let bbframe_len = usize::from(self.bbheader().dfl() / 8) + BBHeader::LEN;
567 self.recv_stream
569 .recv_stream(&mut self.buffer[BBHeader::LEN..bbframe_len])?;
570 let bbframe = Bytes::copy_from_slice(&self.buffer[..bbframe_len]);
571 log::trace!("completed BBFRAME {}", faster_hex::hex_string(&bbframe));
572 Ok(bbframe)
573 }
574}
575
576#[cfg(test)]
577mod test {
578 use super::*;
579 use hex_literal::hex;
580
581 pub const SINGLE_FRAGMENT: [u8; 104] = hex!(
582 "72 00 00 00 02 f0 00 00 00 15 c0 5c 08 00 02 00
583 48 55 4c 4b 45 00 00 54 6f aa 40 00 40 01 72 fc
584 2c 00 00 01 2c 00 00 02 08 00 4e 94 00 3b 00 04
585 19 7d 6b 63 00 00 00 00 5d 79 08 00 00 00 00 00
586 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
587 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
588 30 31 32 33 34 35 36 37"
589 );
590
591 static FRAGMENT0: [u8; 510] = hex!(
592 "72 00 00 00 26 b0 00 00 00 66 c4 d4 08 00 02 00
593 48 55 4c 4b 45 00 04 cc a2 89 40 00 40 01 3b a5
594 2c 00 00 01 2c 00 00 02 08 00 3e b0 00 3c 00 01
595 b7 88 6b 63 00 00 00 00 ba 09 0d 00 00 00 00 00
596 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
597 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
598 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
599 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
600 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
601 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
602 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
603 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
604 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
605 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
606 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
607 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd ce cf
608 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df
609 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed ee ef
610 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd fe ff
611 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
612 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
613 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
614 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
615 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
616 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
617 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
618 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
619 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
620 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
621 a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
622 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
623 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd"
624 );
625
626 static FRAGMENT1: [u8; 510] = hex!(
627 "ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd
628 de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed
629 ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd
630 fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d
631 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d
632 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d
633 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d
634 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d
635 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d
636 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d
637 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d
638 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d
639 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d
640 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad
641 ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd
642 be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb cc cd
643 ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd
644 de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb ec ed
645 ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb fc fd
646 fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d
647 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d
648 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d
649 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d
650 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d
651 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d
652 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d
653 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d
654 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d
655 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d
656 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad
657 ae af b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd
658 be bf c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cb"
659 );
660
661 static FRAGMENT2: [u8; 228] = hex!(
662 "cc cd ce cf d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db
663 dc dd de df e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea eb
664 ec ed ee ef f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb
665 fc fd fe ff 00 01 02 03 04 05 06 07 08 09 0a 0b
666 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b
667 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b
668 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b
669 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b
670 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b
671 5c 5d 5e 5f 60 61 62 63 64 65 66 67 68 69 6a 6b
672 6c 6d 6e 6f 70 71 72 73 74 75 76 77 78 79 7a 7b
673 7c 7d 7e 7f 80 81 82 83 84 85 86 87 88 89 8a 8b
674 8c 8d 8e 8f 90 91 92 93 94 95 96 97 98 99 9a 9b
675 9c 9d 9e 9f a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab
676 ac ad ae af"
677 );
678
679 const SINGLE_FRAGMENT_MIS: [u8; 104] = hex!(
680 "52 2a 00 00 02 f0 00 00 00 dc c0 5c 08 00 02 00
681 48 55 4c 4b 45 00 00 54 6f aa 40 00 40 01 72 fc
682 2c 00 00 01 2c 00 00 02 08 00 4e 94 00 3b 00 04
683 19 7d 6b 63 00 00 00 00 5d 79 08 00 00 00 00 00
684 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
685 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
686 30 31 32 33 34 35 36 37"
687 );
688
689 const SINGLE_FRAGMENT_MIS_OTHER_STREAM: [u8; 104] = hex!(
690 "52 2b 00 00 02 f0 00 00 00 9f c0 5c 08 00 02 00
691 48 55 4c 4b 45 00 00 54 6f aa 40 00 40 01 72 fc
692 2c 00 00 01 2c 00 00 02 08 00 4e 94 00 3b 00 04
693 19 7d 6b 63 00 00 00 00 5d 79 08 00 00 00 00 00
694 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
695 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
696 30 31 32 33 34 35 36 37"
697 );
698
699 static MULTIPLE_FRAGMENTS: [&[u8]; 3] = [&FRAGMENT0, &FRAGMENT1, &FRAGMENT2];
700
701 #[test]
702 fn single_fragment_defrag() {
703 let times_called = std::cell::Cell::new(0);
704 let mut defrag = BBFrameDefrag::new(|buff: &mut [u8]| {
705 times_called.replace(times_called.get() + 1);
706 buff[..SINGLE_FRAGMENT.len()].copy_from_slice(&SINGLE_FRAGMENT);
707 Ok(SINGLE_FRAGMENT.len())
708 });
709 assert_eq!(
710 defrag.get_bbframe().unwrap(),
711 Bytes::from_static(&SINGLE_FRAGMENT)
712 );
713 assert_eq!(times_called.get(), 1);
714 }
715
716 #[test]
717 fn single_fragment_defrag_mis() {
718 let isi = 0x2a;
719 let times_called = std::cell::Cell::new(0);
720 let mut defrag = BBFrameDefrag::new(|buff: &mut [u8]| {
721 let fragment = if times_called.get() % 2 == 0 {
722 &SINGLE_FRAGMENT_MIS_OTHER_STREAM
723 } else {
724 &SINGLE_FRAGMENT_MIS
725 };
726 times_called.replace(times_called.get() + 1);
727 buff[..fragment.len()].copy_from_slice(fragment);
728 Ok(fragment.len())
729 });
730 defrag.set_isi(Some(isi));
731 assert_eq!(
732 defrag.get_bbframe().unwrap(),
733 Bytes::from_static(&SINGLE_FRAGMENT_MIS)
734 );
735 assert_eq!(times_called.get(), 2);
736 }
737
738 #[test]
739 fn multiple_fragments_defrag() {
740 let times_called = std::cell::Cell::new(0);
741 let mut defrag = BBFrameDefrag::new(|buff: &mut [u8]| {
742 let fragment = MULTIPLE_FRAGMENTS[times_called.get()];
743 times_called.replace(times_called.get() + 1);
744 buff[..fragment.len()].copy_from_slice(fragment);
745 Ok(fragment.len())
746 });
747 let mut expected = bytes::BytesMut::new();
748 for fragment in &MULTIPLE_FRAGMENTS {
749 expected.extend_from_slice(fragment);
750 }
751 assert_eq!(defrag.get_bbframe().unwrap(), expected);
752 assert_eq!(times_called.get(), 3);
753 }
754
755 #[test]
756 fn recv_one_bbframe() {
757 let times_called = std::cell::Cell::new(0);
758 let mut defrag = BBFrameRecv::new(|buff: &mut [u8; BBFRAME_MAX_LEN]| {
759 times_called.replace(times_called.get() + 1);
760 buff[..SINGLE_FRAGMENT.len()].copy_from_slice(&SINGLE_FRAGMENT);
761 Ok(SINGLE_FRAGMENT.len())
762 });
763 assert_eq!(
764 defrag.get_bbframe().unwrap(),
765 Bytes::from_static(&SINGLE_FRAGMENT)
766 );
767 assert_eq!(times_called.get(), 1);
768 }
769
770 #[test]
771 fn recv_one_bbframe_with_header() {
772 let header_bytes = 4;
773 let times_called = std::cell::Cell::new(0);
774 let mut defrag = BBFrameRecv::new(|buff: &mut [u8; BBFRAME_MAX_LEN]| {
775 times_called.replace(times_called.get() + 1);
776 buff[..header_bytes].fill(0);
777 let total_len = header_bytes + SINGLE_FRAGMENT.len();
778 buff[header_bytes..total_len].copy_from_slice(&SINGLE_FRAGMENT);
779 Ok(total_len)
780 });
781 defrag.set_header_bytes(header_bytes).unwrap();
782 assert_eq!(
783 defrag.get_bbframe().unwrap(),
784 Bytes::from_static(&SINGLE_FRAGMENT)
785 );
786 assert_eq!(times_called.get(), 1);
787 }
788
789 #[test]
790 fn stream_one_bbframe() {
791 let stream = &SINGLE_FRAGMENT[..];
792 let mut defrag = BBFrameStream::new(stream);
793 assert_eq!(
794 defrag.get_bbframe().unwrap(),
795 Bytes::from_static(&SINGLE_FRAGMENT)
796 );
797 }
798
799 #[test]
800 fn validator() {
801 let valid_header = hex!("72 00 00 00 02 f0 00 00 00 15");
802 let mut validator = BBFrameValidator::new();
803 assert!(validator.bbheader_is_valid(BBHeader::new(&valid_header)));
804
805 let valid_hem_header = hex!("b2 00 00 00 02 f0 00 00 00 87");
806 assert!(validator.bbheader_is_valid(BBHeader::new(&valid_hem_header)));
807
808 let valid_hem_issy_header = hex!("ba 00 12 34 02 f0 56 02 11 7c");
809 assert!(validator.bbheader_is_valid(BBHeader::new(&valid_hem_issy_header)));
810
811 let wrong_crc = hex!("72 00 00 00 02 f0 00 00 00 14");
812 assert!(!BBHeader::new(&wrong_crc).crc_is_valid());
813 assert!(!validator.bbheader_is_valid(BBHeader::new(&wrong_crc)));
814
815 fn test_invalid(validator: &BBFrameValidator, bbheader: &[u8; 10]) {
816 let bbheader = BBHeader::new(bbheader);
817 assert!(bbheader.crc_is_valid());
818 assert!(!validator.bbheader_is_valid(bbheader));
819 }
820
821 let ts_header = hex!("f2 00 00 00 02 f0 00 00 00 44");
822 test_invalid(&validator, &ts_header);
823 let packetized_header = hex!("32 00 00 00 02 f0 00 00 00 d7");
824 test_invalid(&validator, &packetized_header);
825 let mis_header = hex!("52 2a 00 00 02 f0 00 00 00 dc");
826 test_invalid(&validator, &mis_header);
827 let issyi_header = hex!("7a 00 00 00 02 f0 00 00 00 78");
828 test_invalid(&validator, &issyi_header);
829 let dfl_not_divisible = hex!("72 00 00 00 02 f1 00 00 00 50");
830 test_invalid(&validator, &dfl_not_divisible);
831 let dfl_too_large = hex!("72 00 00 00 e3 08 00 00 00 36");
832 test_invalid(&validator, &dfl_too_large);
833
834 let isi = 0x2a;
835 validator.set_isi(Some(isi));
836 assert!(!validator.bbheader_is_valid(BBHeader::new(&valid_header)));
837 assert!(validator.bbheader_is_valid(BBHeader::new(&mis_header)));
838 let other_isi_header = hex!("52 2b 00 00 02 f0 00 00 00 9f");
839 test_invalid(&validator, &other_isi_header);
840
841 validator.set_isi(None);
842 assert!(validator.bbheader_is_valid(BBHeader::new(&valid_header)));
843 assert!(!validator.bbheader_is_valid(BBHeader::new(&mis_header)));
844 }
845}
846
847#[cfg(test)]
848mod proptests {
849 use super::test::SINGLE_FRAGMENT;
850 use super::*;
851 use proptest::prelude::*;
852
853 fn garbage() -> impl Strategy<Value = Vec<Vec<u8>>> {
854 proptest::collection::vec(proptest::collection::vec(any::<u8>(), 1..10000), 0..100)
855 }
856
857 proptest! {
858 #[test]
863 fn bbframe_defrag_garbage(garbage_data in garbage()) {
864 let times_called = std::cell::Cell::new(0);
865 let single_fragment = SINGLE_FRAGMENT.to_vec();
866 let mut defrag = BBFrameDefrag::new(|buff: &mut [u8]| {
867 let j = times_called.get();
868 let fragment = if j < garbage_data.len() {
869 &garbage_data[j]
870 } else {
871 &single_fragment
875 };
876 times_called.replace(times_called.get() + 1);
877 let copy_len = fragment.len().min(buff.len());
878 buff[..copy_len].copy_from_slice(&fragment[..copy_len]);
879 Ok(fragment.len())
880 });
881 let bbframe = defrag.get_bbframe().unwrap();
882 assert!(times_called.get() <= garbage_data.len() + 2);
888 if times_called.get() > garbage_data.len() {
889 assert_eq!(bbframe, Bytes::from_static(&SINGLE_FRAGMENT));
890 }
891 }
892 }
893
894 proptest! {
895 #[test]
900 fn bbframe_recv_garbage(garbage_data in garbage()) {
901 let times_called = std::cell::Cell::new(0);
902 let single_fragment = SINGLE_FRAGMENT.to_vec();
903 let mut recv = BBFrameRecv::new(|buff: &mut [u8; BBFRAME_MAX_LEN]| {
904 let j = times_called.get();
905 let fragment = if j < garbage_data.len() {
906 &garbage_data[j]
907 } else {
908 &single_fragment
912 };
913 times_called.replace(times_called.get() + 1);
914 let copy_len = fragment.len().min(buff.len());
915 buff[..copy_len].copy_from_slice(&fragment[..copy_len]);
916 Ok(fragment.len())
917 });
918 while times_called.get() <= garbage_data.len() {
919 if let Ok(bbframe) = recv.get_bbframe() {
920 assert!(times_called.get() <= garbage_data.len() + 1);
921 if times_called.get() > garbage_data.len() {
922 assert_eq!(bbframe, Bytes::from_static(&SINGLE_FRAGMENT));
923 }
924 }
925 }
926 }
927 }
928
929 #[derive(Debug)]
930 struct Garbage {
931 times_called: std::rc::Rc<std::cell::Cell<usize>>,
932 garbage_data: Vec<Vec<u8>>,
933 }
934
935 impl RecvStream for Garbage {
936 fn recv_stream(&mut self, buff: &mut [u8]) -> Result<()> {
937 let j = self.times_called.get();
938 self.times_called.replace(j + 1);
939 let fragment = if j < self.garbage_data.len() {
940 &self.garbage_data[j]
941 } else {
942 return Err(std::io::Error::new(
943 std::io::ErrorKind::Other,
944 "no more garbage",
945 ));
946 };
947 let copy_len = fragment.len().min(buff.len());
948 buff[..copy_len].copy_from_slice(&fragment[..copy_len]);
949 Ok(())
950 }
951 }
952
953 proptest! {
954 #[test]
955 fn bbframe_stream_garbage(garbage_data in garbage()) {
956 let times_called = std::rc::Rc::new(std::cell::Cell::new(0));
957 let len_garbage_data = garbage_data.len();
958 let mut stream = BBFrameStream::new(Garbage { times_called: times_called.clone(),
959 garbage_data });
960 while times_called.get() < len_garbage_data {
961 let _ = stream.get_bbframe();
962 }
963 }
964 }
965}