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