rtp_rs/lib.rs
1//! Parser and builder for packets formatted per [RFC 3550](https://tools.ietf.org/html/rfc3550), _A Transport
2//! Protocol for Real-Time Applications_.
3//!
4//! Parse a packet
5//! ```
6//! use rtp_rs::*;
7//! // let data = ...acquire UDP packet from the network etc...
8//! # let data = &[
9//! # 0x80u8, 0xe0u8, 0x27u8, 0x38u8, 0x64u8, 0xe4u8,
10//! # 0x05u8, 0xa7u8, 0xa2u8, 0x42u8, 0xafu8, 0x01u8
11//! # ];
12//! if let Ok(rtp) = RtpReader::new(data) {
13//! println!("Sequence number {:?}", rtp.sequence_number());
14//! println!("Payload length {:?}", rtp.payload().len());
15//! }
16//! ```
17//!
18//! Build a packet
19//! ```
20//! use rtp_rs::*;
21//!
22//! let payload = vec![0u8, 2, 5, 4, 6];
23//! let result = RtpPacketBuilder::new()
24//! .payload_type(111)
25//! .ssrc(1337)
26//! .sequence(Seq::from(1234))
27//! .timestamp(666657)
28//! .padded(Pad::round_to(4))
29//! .marked(true)
30//! .payload(&payload)
31//! .build();
32//! if let Ok(packet) = result {
33//! println!("Packet: {:?}", packet);
34//! }
35//! ```
36
37#![forbid(unsafe_code)]
38#![deny(rust_2018_idioms, future_incompatible, missing_docs)]
39
40/// 16 bit RTP sequence number value, as obtained from the `sequence_number()` method of RtpReader.
41///
42/// ```
43/// use rtp_rs::*;
44/// let seq = Seq::from(123);
45/// ```
46///
47/// This type's behavior attempts to honour the expected wrap-around of sequence number values
48/// from `0xffff` back to `0x0000`.
49///
50/// You can perform logic over sequences of RTP packets using this type and other helpers from this
51/// crate,
52/// ```
53/// # use rtp_rs::*;
54/// let start = Seq::from(0xfffe);
55/// let end = Seq::from(0x0002);
56/// // produces the Seq values 0xfffe, 0xffff, 0x0000, 0x0001:
57/// for seq in (start..end).seq_iter() {
58/// // ...inspect some RTP packet you've stored against this sequence number...
59/// }
60/// ```
61///
62/// ## Unsoundness
63/// **Note** this type has implementations of `Ord` and `PartialOrd`, but those implementations
64/// violate the requirement for transitivity which both traits document.
65///
66/// ```should_panic
67/// # use rtp_rs::*;
68/// let a = Seq::from(0);
69/// let b = a + 0x7fff;
70/// let c = b + 0x7fff;
71/// assert!(a < b);
72/// assert!(b < c);
73/// assert!(a < c); // Assertion fails, in violation of Ord/PartialOrd requirements
74/// ```
75/// A future release will potentially deprecate `Ord` / `PartialOrd` implementations for `Seq`, and
76/// hopefully provide a mechanism for sequence number processing which is sound.
77#[derive(PartialEq, Eq, Debug, Clone, Copy)]
78pub struct Seq(u16);
79impl Seq {
80 /// Produce the sequence value which follows this one.
81 ///
82 /// Sequence numbers wrap back to `0x0000` after reaching the value `0xffff`
83 pub fn next(self) -> Seq {
84 Seq(self.0.wrapping_add(1))
85 }
86
87 /// Returns `true` if this sequence number value is immediately before the given one
88 pub fn precedes(self, other: Seq) -> bool {
89 self.next() == other
90 }
91}
92impl From<Seq> for u16 {
93 fn from(v: Seq) -> Self {
94 v.0
95 }
96}
97impl From<u16> for Seq {
98 fn from(v: u16) -> Self {
99 Seq(v)
100 }
101}
102
103/// Implements wrapped subtraction such that for instance `Seq(0x0000) - Seq(0xffff)` results in
104/// `1` (rather than `-65535`).
105///
106/// This is for symmetry with addition, where for example `Seq(0xffff) + 1` gives `Seq(0x0000)`
107impl std::ops::Sub for Seq {
108 type Output = i32;
109
110 fn sub(self, rhs: Seq) -> Self::Output {
111 let delta = i32::from(self.0) - i32::from(rhs.0);
112 if delta < std::i16::MIN as i32 {
113 std::u16::MAX as i32 + 1 + delta
114 } else if delta > std::i16::MAX as i32 {
115 delta - std::u16::MAX as i32 - 1
116 } else {
117 delta
118 }
119 }
120}
121impl PartialOrd for Seq {
122 fn partial_cmp(&self, other: &Seq) -> Option<std::cmp::Ordering> {
123 (*self - *other).partial_cmp(&0)
124 }
125}
126impl Ord for Seq {
127 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
128 (*self - *other).cmp(&0)
129 }
130}
131
132impl std::ops::Add<u16> for Seq {
133 type Output = Seq;
134
135 fn add(self, rhs: u16) -> Self::Output {
136 Seq(self.0.wrapping_add(rhs))
137 }
138}
139
140/// Trait for types that can produce a `SeqIter`, with an implementation provided for `Range<Seq>`.
141pub trait IntoSeqIterator {
142 /// Produce an `Iterator` over sequence number values
143 fn seq_iter(self) -> SeqIter;
144}
145impl IntoSeqIterator for std::ops::Range<Seq> {
146 fn seq_iter(self) -> SeqIter {
147 SeqIter(self.start, self.end)
148 }
149}
150
151/// An `Iterator` which can produce values from the given start value to the given end value, inclusive.
152///
153/// Rather than using this directly, it is convenient to use a range like so,
154/// ```
155/// use rtp_rs::*;
156/// use rtp_rs::IntoSeqIterator;
157/// let here = 12.into();
158/// let there = 22.into();
159/// for seq in (here..there).seq_iter() {
160/// println!("{:?}", seq);
161/// }
162/// ```
163pub struct SeqIter(Seq, Seq);
164impl Iterator for SeqIter {
165 type Item = Seq;
166
167 fn next(&mut self) -> Option<Self::Item> {
168 if self.0 >= self.1 {
169 None
170 } else {
171 let res = self.0;
172 self.0 = self.0.next();
173 Some(res)
174 }
175 }
176}
177
178mod reader;
179pub use reader::*;
180
181mod builder;
182pub use builder::*;