hylarana_transport/
package.rs

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
use crate::adapter::StreamKind;

use bytes::{Buf, BufMut, Bytes, BytesMut};
use xxhash_rust::xxh3::xxh3_64;

#[derive(Debug)]
pub struct PacketInfo {
    pub kind: StreamKind,
    pub flags: i32,
    pub timestamp: u64,
}

/// Creates a BytesMut and copies from src to a buffer. The created buffer
/// contains the initial message header required for message encoding, which is
/// an optimization to reduce data copying in the process.
pub fn copy_from_slice(src: &[u8]) -> BytesMut {
    let mut bytes = BytesMut::with_capacity(src.len() + Package::HEAD_SIZE);
    bytes.put_bytes(0, Package::HEAD_SIZE);
    bytes.put(src);
    bytes
}

/// Create a BytesMut and initialize it according to the capacity. The created
/// buffer contains the initialization message header required for message
/// encoding, which is an optimization to reduce data copying in the process.
pub fn with_capacity(size: usize) -> BytesMut {
    BytesMut::zeroed(size + Package::HEAD_SIZE)
}

/// Because of the need to transmit both audio and video data in srt, it is
/// necessary to identify the type of packet, this encoder is used to packetize
/// specific types of data for transmission over the network.
pub struct Package;

impl Package {
    const HEAD_SIZE: usize = 26;

    /// The result of the encoding may be null, this is because an empty packet
    /// may be passed in from outside.
    pub fn pack(info: PacketInfo, mut bytes: BytesMut) -> Bytes {
        let size = bytes.len();

        unsafe {
            bytes.set_len(0);
        }

        bytes.put_u64(0);
        bytes.put_u64(size as u64);
        bytes.put_u8(info.kind as u8);
        bytes.put_u8(info.flags as u8);
        bytes.put_u64(info.timestamp);

        unsafe {
            bytes.set_len(size);
        }

        let hash = xxh3_64(&bytes[8..]);
        bytes[0..8].copy_from_slice(&hash.to_be_bytes());
        bytes.freeze()
    }
}

/// Decode the packets received from the network and separate out the different
/// types of data.
pub struct UnPackage;

impl UnPackage {
    pub fn unpack(mut bytes: Bytes) -> Option<(PacketInfo, Bytes)> {
        let count = bytes.len();
        if bytes.get_u64() == xxh3_64(&bytes) {
            if bytes.get_u64() as usize == count {
                Some((
                    PacketInfo {
                        kind: StreamKind::try_from(bytes.get_u8()).ok()?,
                        flags: bytes.get_u8() as i32,
                        timestamp: bytes.get_u64(),
                    },
                    bytes,
                ))
            } else {
                None
            }
        } else {
            None
        }
    }
}