Skip to main content

soe_protocol/channel/
mod.rs

1//! Reliable data channels: reassembly/ordering of incoming data, and
2//! fragmentation/sequencing of outgoing data.
3
4mod input;
5mod output;
6
7pub use input::{
8    CorruptData, DataInputStats, InputConfig, OutgoingContextual, ReliableDataInputChannel,
9};
10pub use output::{DataOutputStats, OutgoingReliable, OutputConfig, ReliableDataOutputChannel};
11
12/// Computes the "true" (un-wrapped, monotonically increasing) sequence number for
13/// an incoming packet, given the embedded 16-bit packet sequence and the expected
14/// window position. Mirrors `DataUtils.GetTrueIncomingSequence`.
15pub(crate) fn true_incoming_sequence(
16    packet_sequence: u16,
17    current_sequence: i64,
18    max_queued_reliable_data_packets: i64,
19) -> i64 {
20    // Zero out the low two bytes of the last known sequence and insert the packet
21    // sequence in that space.
22    let mut sequence = packet_sequence as i64 | (current_sequence & (i64::MAX ^ 0xFFFF));
23
24    // If larger than our possible window, we wrapped back to the previous block.
25    if sequence > current_sequence + max_queued_reliable_data_packets {
26        sequence -= 0x1_0000;
27    }
28    // If smaller than our possible window, we wrapped forward to the next block.
29    if sequence < current_sequence - max_queued_reliable_data_packets {
30        sequence += 0x1_0000;
31    }
32    sequence
33}
34
35#[cfg(test)]
36mod sequence_tests {
37    use super::true_incoming_sequence;
38
39    #[test]
40    fn in_window_is_identity() {
41        assert_eq!(true_incoming_sequence(5, 5, 256), 5);
42        assert_eq!(true_incoming_sequence(300, 256, 256), 300);
43    }
44
45    #[test]
46    fn wraps_forward_past_u16_boundary() {
47        // current just below a block boundary, packet sequence wrapped to 0.
48        let current = 0x1_0000 - 1; // 65535
49        assert_eq!(true_incoming_sequence(0, current, 256), 0x1_0000);
50    }
51
52    #[test]
53    fn wraps_backward() {
54        // current just past a block boundary; a late packet from the previous block.
55        let current = 0x1_0000 + 10;
56        assert_eq!(true_incoming_sequence(0xFFFF, current, 256), 0xFFFF);
57    }
58}