ordered_datagram/
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::{ReadOctetStream, WriteOctetStream};
6use std::io::ErrorKind;
7use std::{fmt, io};
8
9#[derive(Debug, Default, Copy, Clone)]
10pub struct DatagramId(u16);
11
12impl DatagramId {
13    pub fn new(id: u16) -> Self {
14        Self(id)
15    }
16
17    pub fn inner(self) -> u16 {
18        self.0
19    }
20
21    pub fn next(self) -> Self {
22        Self(self.0 + 1)
23    }
24
25    fn to_stream(self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
26        stream.write_u16(self.0)
27    }
28
29    #[allow(unused)]
30    fn from_stream(stream: &mut impl ReadOctetStream) -> io::Result<DatagramId> {
31        Ok(Self(stream.read_u16()?))
32    }
33
34    fn diff(self, after: DatagramId) -> i32 {
35        after.0.wrapping_sub(self.0) as i32
36    }
37
38    #[allow(unused)]
39    pub fn is_valid_successor(self, after: DatagramId) -> bool {
40        const ORDERED_DATAGRAM_ID_ACCEPTABLE_DIFF: i32 = 625; // 10 datagrams / tick * tickFrequency (62.5) * 1 second latency
41        let diff = self.diff(after);
42        diff > 0 && diff <= ORDERED_DATAGRAM_ID_ACCEPTABLE_DIFF
43    }
44
45    fn is_equal_or_successor(self, after: DatagramId) -> bool {
46        const ORDERED_DATAGRAM_ID_ACCEPTABLE_DIFF: i32 = 625; // 10 datagrams / tick * tickFrequency (62.5) * 1 second latency
47        let diff = self.diff(after);
48        (0..=ORDERED_DATAGRAM_ID_ACCEPTABLE_DIFF).contains(&diff)
49    }
50}
51
52impl fmt::Display for DatagramId {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        write!(f, "DatagramId({:X})", self.0)
55    }
56}
57
58#[derive(Debug, Default, Clone, Copy)]
59pub struct OrderedOut {
60    pub sequence_to_send: DatagramId,
61}
62
63impl OrderedOut {
64    pub fn new() -> Self {
65        Self {
66            sequence_to_send: DatagramId(0),
67        }
68    }
69    pub fn to_stream(&self, stream: &mut impl WriteOctetStream) -> io::Result<()> {
70        self.sequence_to_send.to_stream(stream)
71    }
72
73    pub fn commit(&mut self) {
74        self.sequence_to_send = DatagramId(self.sequence_to_send.0 + 1);
75    }
76}
77
78#[derive(Debug, Default, Clone, Copy)]
79pub struct OrderedIn {
80    expected_sequence: DatagramId,
81}
82
83impl OrderedIn {
84    pub fn read_and_verify(&mut self, stream: &mut impl ReadOctetStream) -> io::Result<()> {
85        let potential_expected_or_successor = DatagramId::from_stream(stream)?;
86
87        if self
88            .expected_sequence
89            .is_equal_or_successor(potential_expected_or_successor)
90        {
91            self.expected_sequence = potential_expected_or_successor.next();
92            Ok(())
93        } else {
94            Err(io::Error::new(
95                ErrorKind::InvalidData,
96                format!(
97                    "wrong datagram order. expected {} but received {}",
98                    self.expected_sequence, potential_expected_or_successor
99                ),
100            ))
101        }
102    }
103}