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;