xref: /webrtc/rtp/src/packet/mod.rs (revision 5d8fe953)
1 #[cfg(test)]
2 mod packet_test;
3 
4 use crate::{error::Error, header::*};
5 use util::marshal::{Marshal, MarshalSize, Unmarshal};
6 
7 use bytes::{Buf, BufMut, Bytes};
8 use std::fmt;
9 
10 /// Packet represents an RTP Packet
11 /// NOTE: Raw is populated by Marshal/Unmarshal and should not be modified
12 #[derive(Debug, Eq, PartialEq, Default, Clone)]
13 pub struct Packet {
14     pub header: Header,
15     pub payload: Bytes,
16 }
17 
18 impl fmt::Display for Packet {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result19     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20         let mut out = "RTP PACKET:\n".to_string();
21 
22         out += format!("\tVersion: {}\n", self.header.version).as_str();
23         out += format!("\tMarker: {}\n", self.header.marker).as_str();
24         out += format!("\tPayload Type: {}\n", self.header.payload_type).as_str();
25         out += format!("\tSequence Number: {}\n", self.header.sequence_number).as_str();
26         out += format!("\tTimestamp: {}\n", self.header.timestamp).as_str();
27         out += format!("\tSSRC: {} ({:x})\n", self.header.ssrc, self.header.ssrc).as_str();
28         out += format!("\tPayload Length: {}\n", self.payload.len()).as_str();
29 
30         write!(f, "{out}")
31     }
32 }
33 
34 impl Unmarshal for Packet {
35     /// Unmarshal parses the passed byte slice and stores the result in the Header this method is called upon
unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error> where Self: Sized, B: Buf,36     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self, util::Error>
37     where
38         Self: Sized,
39         B: Buf,
40     {
41         let header = Header::unmarshal(raw_packet)?;
42         let payload_len = raw_packet.remaining();
43         let payload = raw_packet.copy_to_bytes(payload_len);
44         if header.padding {
45             if payload_len > 0 {
46                 let padding_len = payload[payload_len - 1] as usize;
47                 if padding_len <= payload_len {
48                     Ok(Packet {
49                         header,
50                         payload: payload.slice(..payload_len - padding_len),
51                     })
52                 } else {
53                     Err(Error::ErrShortPacket.into())
54                 }
55             } else {
56                 Err(Error::ErrShortPacket.into())
57             }
58         } else {
59             Ok(Packet { header, payload })
60         }
61     }
62 }
63 
64 impl MarshalSize for Packet {
65     /// MarshalSize returns the size of the packet once marshaled.
marshal_size(&self) -> usize66     fn marshal_size(&self) -> usize {
67         let payload_len = self.payload.len();
68         let padding_len = if self.header.padding {
69             let padding_len = get_padding(payload_len);
70             if padding_len == 0 {
71                 4
72             } else {
73                 padding_len
74             }
75         } else {
76             0
77         };
78         self.header.marshal_size() + payload_len + padding_len
79     }
80 }
81 
82 impl Marshal for Packet {
83     /// MarshalTo serializes the packet and writes to the buffer.
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error>84     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize, util::Error> {
85         if buf.remaining_mut() < self.marshal_size() {
86             return Err(Error::ErrBufferTooSmall.into());
87         }
88 
89         let n = self.header.marshal_to(buf)?;
90         buf = &mut buf[n..];
91         buf.put(&*self.payload);
92         let padding_len = if self.header.padding {
93             let mut padding_len = get_padding(self.payload.len());
94             if padding_len == 0 {
95                 padding_len = 4;
96             }
97             for i in 0..padding_len {
98                 if i != padding_len - 1 {
99                     buf.put_u8(0);
100                 } else {
101                     buf.put_u8(padding_len as u8);
102                 }
103             }
104             padding_len
105         } else {
106             0
107         };
108 
109         Ok(n + self.payload.len() + padding_len)
110     }
111 }
112 
113 /// getPadding Returns the padding required to make the length a multiple of 4
get_padding(len: usize) -> usize114 fn get_padding(len: usize) -> usize {
115     if len % 4 == 0 {
116         0
117     } else {
118         4 - (len % 4)
119     }
120 }
121