1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
use std::net::SocketAddr;

use crate::packet::{DeliveryGuarantee, OrderingGuarantee, PacketType};

#[derive(Clone, PartialEq, Eq, Debug)]
/// This is a user friendly packet containing the payload, endpoint, and reliability guarantees.
/// A packet could have reliability guarantees to specify how it should be delivered and processed.
///
/// | Reliability Type             | Packet Drop     | Packet Duplication | Packet Order     | Packet Fragmentation |Packet Delivery|
/// | :-------------:              | :-------------: | :-------------:    | :-------------:  | :-------------:      | :-------------:
/// |   **Unreliable Unordered**   |       Any       |      Yes           |     No           |      No              |   No
/// |   **Unreliable Sequenced**   |    Any + old    |      No            |     Sequenced    |      No              |   No
/// |   **Reliable Unordered**     |       No        |      No            |     No           |      Yes             |   Yes
/// |   **Reliable Ordered**       |       No        |      No            |     Ordered      |      Yes             |   Yes
/// |   **Reliable Sequenced**     |    Only old     |      No            |     Sequenced    |      Yes             |   Only newest
///
/// You are able to send packets with the above reliability types.
pub struct Packet {
    /// The endpoint from where it came.
    addr: SocketAddr,
    /// The raw payload of the packet.
    payload: Box<[u8]>,
    /// Defines on how the packet will be delivered.
    delivery: DeliveryGuarantee,
    /// Defines on how the packet will be ordered.
    ordering: OrderingGuarantee,
}

impl Packet {
    /// Creates a new packet by passing the receiver, data, and guarantees on how this packet should be delivered.
    pub(crate) fn new(
        addr: SocketAddr,
        payload: Box<[u8]>,
        delivery: DeliveryGuarantee,
        ordering: OrderingGuarantee,
    ) -> Packet {
        Packet {
            addr,
            payload,
            delivery,
            ordering,
        }
    }

    /// Creates a new unreliable packet by passing the receiver, data.
    ///
    /// Unreliable: Packets can be dropped, duplicated or arrive without order.
    ///
    /// **Details**
    ///
    /// | Packet Drop     | Packet Duplication | Packet Order     | Packet Fragmentation | Packet Delivery |
    /// | :-------------: | :-------------:    | :-------------:  | :-------------:      | :-------------: |
    /// |       Any       |        Yes         |      No          |      No              |       No        |
    ///
    /// Basically just bare UDP. The packet may or may not be delivered.
    pub fn unreliable(addr: SocketAddr, payload: Vec<u8>) -> Packet {
        Packet {
            addr,
            payload: payload.into_boxed_slice(),
            delivery: DeliveryGuarantee::Unreliable,
            ordering: OrderingGuarantee::None,
        }
    }

    /// Creates a new unreliable sequenced packet by passing the receiver, data.
    ///
    /// Unreliable Sequenced; Packets can be dropped, but could not be duplicated and arrive in sequence.
    ///
    /// *Details*
    ///
    /// | Packet Drop     | Packet Duplication | Packet Order     | Packet Fragmentation | Packet Delivery |
    /// | :-------------: | :-------------:    | :-------------:  | :-------------:      | :-------------: |
    /// |    Any + old    |        No          |      Sequenced   |      No              |       No        |
    ///
    /// Basically just bare UDP, free to be dropped, but has some sequencing to it so that only the newest packets are kept.
    pub fn unreliable_sequenced(
        addr: SocketAddr,
        payload: Vec<u8>,
        stream_id: Option<u8>,
    ) -> Packet {
        Packet {
            addr,
            payload: payload.into_boxed_slice(),
            delivery: DeliveryGuarantee::Unreliable,
            ordering: OrderingGuarantee::Sequenced(stream_id),
        }
    }

    /// Creates a new packet by passing the receiver, data.
    /// Reliable; All packets will be sent and received, but without order.
    ///
    /// *Details*
    ///
    /// |   Packet Drop   | Packet Duplication | Packet Order     | Packet Fragmentation | Packet Delivery |
    /// | :-------------: | :-------------:    | :-------------:  | :-------------:      | :-------------: |
    /// |       No        |      No            |      No          |      Yes             |       Yes       |
    ///
    /// Basically this is almost TCP without ordering of packets.
    pub fn reliable_unordered(addr: SocketAddr, payload: Vec<u8>) -> Packet {
        Packet {
            addr,
            payload: payload.into_boxed_slice(),
            delivery: DeliveryGuarantee::Reliable,
            ordering: OrderingGuarantee::None,
        }
    }

    /// Creates a new packet by passing the receiver, data and a optional stream on which the ordering will be done.
    ///
    /// Reliable; All packets will be sent and received, with order.
    ///
    /// *Details*
    ///
    /// |   Packet Drop   | Packet Duplication | Packet Order     | Packet Fragmentation | Packet Delivery |
    /// | :-------------: | :-------------:    | :-------------:  | :-------------:      | :-------------: |
    /// |       No        |      No            |      Ordered     |      Yes             |       Yes       |
    ///
    /// Basically this is almost TCP-like with ordering of packets.
    ///
    /// # Remark
    /// - When `stream_id` is specified as `None` the default stream will be used; if you are not sure what this is you can leave it at `None`.
    pub fn reliable_ordered(addr: SocketAddr, payload: Vec<u8>, stream_id: Option<u8>) -> Packet {
        Packet {
            addr,
            payload: payload.into_boxed_slice(),
            delivery: DeliveryGuarantee::Reliable,
            ordering: OrderingGuarantee::Ordered(stream_id),
        }
    }

    /// Creates a new packet by passing the receiver, data and a optional stream on which the sequencing will be done.
    ///
    /// Reliable; All packets will be sent and received, but arranged in sequence.
    /// Which means that only the newest packets will be let through, older packets will be received but they won't get to the user.
    ///
    /// *Details*
    ///
    /// |   Packet Drop   | Packet Duplication | Packet Order     | Packet Fragmentation | Packet Delivery |
    /// | :-------------: | :-------------:    | :-------------:  | :-------------:      | :-------------: |
    /// |    Only old     |      No            |      Sequenced   |      Yes             |   Only newest   |
    ///
    /// Basically this is almost TCP-like but then sequencing instead of ordering.
    ///
    /// # Remark
    /// - When `stream_id` is specified as `None` the default stream will be used; if you are not sure what this is you can leave it at `None`.
    pub fn reliable_sequenced(addr: SocketAddr, payload: Vec<u8>, stream_id: Option<u8>) -> Packet {
        Packet {
            addr,
            payload: payload.into_boxed_slice(),
            delivery: DeliveryGuarantee::Reliable,
            ordering: OrderingGuarantee::Sequenced(stream_id),
        }
    }

    /// Returns the payload of this packet.
    pub fn payload(&self) -> &[u8] {
        &self.payload
    }

    /// Returns the address of this packet.
    ///
    /// # Remark
    /// Could be both the receiving endpoint or the one to send this packet to.
    /// This depends whether it is a packet that has been received or one that needs to be send.
    pub fn addr(&self) -> SocketAddr {
        self.addr
    }

    /// Returns the [`DeliveryGuarantee`](./enum.DeliveryGuarantee.html) of this packet.
    pub fn delivery_guarantee(&self) -> DeliveryGuarantee {
        self.delivery
    }

    /// Returns the [`OrderingGuarantee`](./enum.OrderingGuarantee.html) of this packet.
    pub fn order_guarantee(&self) -> OrderingGuarantee {
        self.ordering
    }
}

/// This packet type has similar properties to `Packet` except that it doesn't own anything, and additionally has `PacketType`.
#[derive(Debug)]
pub struct PacketInfo<'a> {
    /// Defines a type of the packet.
    pub(crate) packet_type: PacketType,
    /// The raw payload of the packet.
    pub(crate) payload: &'a [u8],
    /// Defines how the packet will be delivered.
    pub(crate) delivery: DeliveryGuarantee,
    /// Defines how the packet will be ordered.
    pub(crate) ordering: OrderingGuarantee,
}

impl<'a> PacketInfo<'a> {
    /// Creates a user packet that can be received by the user.
    pub fn user_packet(
        payload: &'a [u8],
        delivery: DeliveryGuarantee,
        ordering: OrderingGuarantee,
    ) -> Self {
        PacketInfo {
            packet_type: PacketType::Packet,
            payload,
            delivery,
            ordering,
        }
    }

    /// Creates a heartbeat packet that is expected to be sent over the network.
    pub fn heartbeat_packet(payload: &'a [u8]) -> Self {
        PacketInfo {
            packet_type: PacketType::Heartbeat,
            payload,
            delivery: DeliveryGuarantee::Unreliable,
            ordering: OrderingGuarantee::None,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::net::SocketAddr;

    use crate::packet::{DeliveryGuarantee, OrderingGuarantee, Packet};

    #[test]
    fn assure_creation_unreliable_packet() {
        let packet = Packet::unreliable(test_addr(), test_payload());

        assert_eq!(packet.addr(), test_addr());
        assert_eq!(packet.payload(), test_payload().as_slice());
        assert_eq!(packet.delivery_guarantee(), DeliveryGuarantee::Unreliable);
        assert_eq!(packet.order_guarantee(), OrderingGuarantee::None);
    }

    #[test]
    fn assure_creation_unreliable_sequenced() {
        let packet = Packet::unreliable_sequenced(test_addr(), test_payload(), Some(1));

        assert_eq!(packet.addr(), test_addr());
        assert_eq!(packet.payload(), test_payload().as_slice());
        assert_eq!(packet.delivery_guarantee(), DeliveryGuarantee::Unreliable);
        assert_eq!(
            packet.order_guarantee(),
            OrderingGuarantee::Sequenced(Some(1))
        );
    }

    #[test]
    fn assure_creation_reliable() {
        let packet = Packet::reliable_unordered(test_addr(), test_payload());

        assert_eq!(packet.addr(), test_addr());
        assert_eq!(packet.payload(), test_payload().as_slice());
        assert_eq!(packet.delivery_guarantee(), DeliveryGuarantee::Reliable);
        assert_eq!(packet.order_guarantee(), OrderingGuarantee::None);
    }

    #[test]
    fn assure_creation_reliable_ordered() {
        let packet = Packet::reliable_ordered(test_addr(), test_payload(), Some(1));

        assert_eq!(packet.addr(), test_addr());
        assert_eq!(packet.payload(), test_payload().as_slice());
        assert_eq!(packet.delivery_guarantee(), DeliveryGuarantee::Reliable);
        assert_eq!(
            packet.order_guarantee(),
            OrderingGuarantee::Ordered(Some(1))
        );
    }

    #[test]
    fn assure_creation_reliable_sequence() {
        let packet = Packet::reliable_sequenced(test_addr(), test_payload(), Some(1));

        assert_eq!(packet.addr(), test_addr());
        assert_eq!(packet.payload(), test_payload().as_slice());
        assert_eq!(packet.delivery_guarantee(), DeliveryGuarantee::Reliable);
        assert_eq!(
            packet.order_guarantee(),
            OrderingGuarantee::Sequenced(Some(1))
        );
    }

    fn test_payload() -> Vec<u8> {
        b"test".to_vec()
    }

    fn test_addr() -> SocketAddr {
        "127.0.0.1:12345".parse().unwrap()
    }
}