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
//! Codec for modern F1 games

use crate::nineteen::decode_nineteen;
use crate::packet::Packet;
use bytes::{Buf, BytesMut};
use std::io::{Cursor, Error, ErrorKind};
use tokio_util::codec::Decoder;

/// Codec to decode UDP packets published by modern F1 games.
///
/// This struct implements the `Decoder` trait for tokio-utils. It can be used to decode incoming
/// UDP packets, and convert them into internal data representations. The F1 codec can decode the
/// packets of all F1 games that are supported by this library.
pub struct F1Codec;

impl Decoder for F1Codec {
    type Item = Packet;
    type Error = Error;

    /// Decode a UDP packet and return its data.
    ///
    /// The `decode` method is called whenever a new data frame is received on a UDP socket, and the
    /// data frame is passed as an argument. This method has to make a few decisions then:
    ///
    /// 1. Does the data form a complete packet so that it can be decoded?
    /// 2. Is the packet a valid packet sent by an F1 game?
    /// 3. Can the packet be parsed?
    ///
    /// To answer these questions, the following process is used. First, the packet header is read
    /// to determine the game that sent the packet. With the game and the packet type from the
    /// header, the expected size of the packet can be determined by calling `buffer_size` from the
    /// `FromBytes` trait. If the packet is too small, `Ok(None)` is returned to signal that more
    /// data needs to be retrieved from the UDP socket.
    ///
    /// If the packet is complete, it is decoded using the `from_bytes` method in the `FromBytes`
    /// trait. If the packet can be decoded successfully, it is returned. Otherwise, the error from
    /// the decoding is returned, signaling that the UDP stream is corrupted and should be shut
    /// down.
    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
        let mut cursor = Cursor::new(src);

        // Not enough data yet to decode the packet format.
        if cursor.remaining() < 2 {
            return Ok(None);
        }

        let packet_format = cursor.get_u16_le();

        let packet = match packet_format {
            2019 => decode_nineteen(&mut cursor),
            format => Err(Error::new(
                ErrorKind::InvalidData,
                format!("Unknown packet format {}.", format),
            )),
        };

        match packet {
            Ok(packet) => Ok(Some(packet)),
            Err(error) => match error.kind() {
                ErrorKind::UnexpectedEof => Ok(None),
                _ => Err(error),
            },
        }
    }
}