scuffle_rtmp/chunk/
mod.rs

1//! RTMP chunk protocol.
2
3use bytes::Bytes;
4
5use crate::messages::MessageType;
6
7pub mod error;
8pub mod reader;
9pub mod writer;
10
11/// The chunk stream ID for command messages is 3.
12pub const CHUNK_STREAM_ID_COMMAND: u32 = 3;
13/// The chunk stream ID for audio messages is 4.
14pub const CHUNK_STREAM_ID_AUDIO: u32 = 4;
15/// The chunk stream ID for video messages is 5.
16pub const CHUNK_STREAM_ID_VIDEO: u32 = 5;
17
18/// A chunk type represents the format of the chunk header.
19#[derive(Debug, PartialEq, Eq, Clone, Copy, num_derive::FromPrimitive, Hash)]
20#[repr(u8)]
21pub enum ChunkType {
22    /// Type 0 chunk - 5.3.1.2.1
23    ///
24    /// Type 0 chunk headers are 11 bytes long.
25    Type0 = 0,
26    /// Type 1 chunk - 5.3.1.2.2
27    ///
28    /// Type 1 chunk headers are 7 bytes long.
29    Type1 = 1,
30    /// Type 2 chunk - 5.3.1.2.3
31    ///
32    /// Type 2 chunk headers are 3 bytes long.
33    Type2 = 2,
34    /// Type 3 chunk - 5.3.1.1.4
35    ///
36    /// Type 3 chunks have no message header.
37    Type3 = 3,
38}
39
40#[derive(Eq, PartialEq, Debug, Clone)]
41/// A chunk basic header.
42pub struct ChunkBasicHeader {
43    /// Used for decoding the header only.
44    pub format: ChunkType, // 2 bits
45    /// The chunk stream id.
46    pub chunk_stream_id: u32, // 6 bits (if format == 0, 8 bits, if format == 1, 16 bits)
47}
48
49#[derive(Eq, PartialEq, Debug, Clone)]
50/// A chunk message header.
51pub struct ChunkMessageHeader {
52    /// The timestamp of the message.
53    pub timestamp: u32, /* 3 bytes (when writing the header, if the timestamp is >= 0xFFFFFF,
54                         * write 0xFFFFFF) */
55    /// The length of the message.
56    pub msg_length: u32, // 3 bytes
57    /// The type of the message.
58    pub msg_type_id: MessageType, // 1 byte
59    /// The stream id of the message.
60    pub msg_stream_id: u32, // 4 bytes
61    /// Whether the timestamp is extended.
62    pub was_extended_timestamp: bool, // used for reading the header only
63}
64
65impl ChunkMessageHeader {
66    /// is_extended_timestamp returns true if the timestamp is >= 0xFFFFFF.
67    /// This means that the timestamp is extended and is written in the extended
68    /// timestamp field.
69    #[inline]
70    pub fn is_extended_timestamp(&self) -> bool {
71        self.timestamp >= 0xFFFFFF
72    }
73}
74
75/// A chunk.
76#[derive(Eq, PartialEq, Debug, Clone)]
77pub struct Chunk {
78    /// The basic header of the chunk.
79    pub basic_header: ChunkBasicHeader,
80    /// The message header of the chunk.
81    pub message_header: ChunkMessageHeader,
82    /// The payload of the chunk.
83    pub payload: Bytes,
84}
85
86impl Chunk {
87    /// new creates a new chunk.
88    /// Helper function to create a new chunk.
89    pub fn new(chunk_stream_id: u32, timestamp: u32, msg_type_id: MessageType, msg_stream_id: u32, payload: Bytes) -> Self {
90        Self {
91            basic_header: ChunkBasicHeader {
92                chunk_stream_id,
93                format: ChunkType::Type0,
94            },
95            message_header: ChunkMessageHeader {
96                timestamp,
97                msg_length: payload.len() as u32,
98                msg_type_id,
99                msg_stream_id,
100                was_extended_timestamp: false,
101            },
102            payload,
103        }
104    }
105}
106
107/// We bump our chunk size to 4096 bytes.
108pub const CHUNK_SIZE: usize = 4096;
109
110/// Not apart of the spec but we have a limit on how big a chunk can be.
111/// This is the maximum chunk size we will accept. If the peer requests a chunk
112/// size bigger than this, we will close the connection.
113pub const MAX_CHUNK_SIZE: usize = 4096 * 16; // 64 KB
114
115/// The default chunk size is 128 bytes.
116/// 5.4.1 "The maximum chunk size defaults to 128 bytes ..."
117pub const INIT_CHUNK_SIZE: usize = 128;