nimble_layer/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/nimble-rust/nimble
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use flood_rs::prelude::{InOctetStream, OutOctetStream};
6use hexify::format_hex;
7use log::trace;
8use metricator::{AggregateMetric, MinMaxAvg};
9
10use nimble_ordered_datagram::{DatagramOrderInError, OrderedIn, OrderedOut};
11use std::io;
12
13#[derive(Debug)]
14pub struct NimbleLayer {
15    ordered_datagram_out: OrderedOut,
16    ordered_in: OrderedIn,
17    datagram_drops: AggregateMetric<u16>,
18}
19
20impl Default for NimbleLayer {
21    fn default() -> Self {
22        Self {
23            ordered_datagram_out: OrderedOut::default(),
24            ordered_in: OrderedIn::default(),
25            datagram_drops: AggregateMetric::new(16).expect("threshold should be ok"),
26        }
27    }
28}
29
30#[derive(Debug)]
31pub enum NimbleLayerError {
32    IoError(io::Error),
33    DatagramInOrderError(DatagramOrderInError),
34    MillisFromLowerError,
35    AbsoluteTimeError,
36}
37
38impl From<DatagramOrderInError> for NimbleLayerError {
39    fn from(err: DatagramOrderInError) -> Self {
40        Self::DatagramInOrderError(err)
41    }
42}
43
44impl From<io::Error> for NimbleLayerError {
45    fn from(err: io::Error) -> Self {
46        Self::IoError(err)
47    }
48}
49
50const ORDERED_DATAGRAM_OCTETS: usize = 2;
51
52impl NimbleLayer {
53    #[must_use]
54    #[allow(clippy::missing_panics_doc)]
55    pub fn new() -> Self {
56        Self {
57            ordered_datagram_out: OrderedOut::default(),
58            ordered_in: OrderedIn::default(),
59            datagram_drops: AggregateMetric::<u16>::new(10).unwrap(),
60        }
61    }
62
63    /// # Errors
64    ///
65    /// `io::Error` // TODO:
66    pub fn send(&mut self, datagrams: &Vec<Vec<u8>>) -> Result<Vec<Vec<u8>>, io::Error> {
67        let mut packet = [0u8; 1200];
68        let mut out_datagrams: Vec<Vec<u8>> = vec![];
69
70        for datagram in datagrams {
71            let mut stream = OutOctetStream::new();
72
73            self.ordered_datagram_out.to_stream(&mut stream)?;
74
75            packet[0..ORDERED_DATAGRAM_OCTETS].copy_from_slice(stream.octets_ref());
76            packet[ORDERED_DATAGRAM_OCTETS..ORDERED_DATAGRAM_OCTETS + datagram.len()]
77                .copy_from_slice(datagram);
78
79            let complete_datagram = packet[0..ORDERED_DATAGRAM_OCTETS + datagram.len()].to_vec();
80            out_datagrams.push(complete_datagram);
81            self.ordered_datagram_out.commit();
82        }
83
84        Ok(out_datagrams)
85    }
86
87    /// # Errors
88    ///
89    /// `io::Error` // TODO:
90    pub fn receive<'a>(&mut self, datagram: &'a [u8]) -> Result<&'a [u8], NimbleLayerError> {
91        let mut in_stream = InOctetStream::new(datagram);
92        let dropped_packets = self.ordered_in.read_and_verify(&mut in_stream)?;
93        self.datagram_drops.add(dropped_packets.inner());
94
95        let slice = &datagram[ORDERED_DATAGRAM_OCTETS..];
96        trace!(
97            "nimble-layer host received without header\n{}",
98            format_hex(slice)
99        );
100        Ok(slice)
101    }
102
103    #[must_use]
104    pub fn datagram_drops(&self) -> Option<MinMaxAvg<u16>> {
105        self.datagram_drops.values()
106    }
107}