xref: /webrtc/rtcp/src/goodbye/mod.rs (revision 5d8fe953)
1 #[cfg(test)]
2 mod goodbye_test;
3 
4 use crate::{error::Error, header::*, packet::*, util::*};
5 use util::marshal::{Marshal, MarshalSize, Unmarshal};
6 
7 use bytes::{Buf, BufMut, Bytes};
8 use std::any::Any;
9 use std::fmt;
10 
11 type Result<T> = std::result::Result<T, util::Error>;
12 
13 /// The Goodbye packet indicates that one or more sources are no longer active.
14 #[derive(Debug, PartialEq, Eq, Default, Clone)]
15 pub struct Goodbye {
16     /// The SSRC/CSRC identifiers that are no longer active
17     pub sources: Vec<u32>,
18     /// Optional text indicating the reason for leaving, e.g., "camera malfunction" or "RTP loop detected"
19     pub reason: Bytes,
20 }
21 
22 impl fmt::Display for Goodbye {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result23     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24         let mut out = "Goodbye:\n\tSources:\n".to_string();
25         for s in &self.sources {
26             out += format!("\t{}\n", *s).as_str();
27         }
28         out += format!("\tReason: {:?}\n", self.reason).as_str();
29 
30         write!(f, "{out}")
31     }
32 }
33 
34 impl Packet for Goodbye {
35     /// Header returns the Header associated with this packet.
header(&self) -> Header36     fn header(&self) -> Header {
37         Header {
38             padding: get_padding_size(self.raw_size()) != 0,
39             count: self.sources.len() as u8,
40             packet_type: PacketType::Goodbye,
41             length: ((self.marshal_size() / 4) - 1) as u16,
42         }
43     }
44 
45     /// destination_ssrc returns an array of SSRC values that this packet refers to.
destination_ssrc(&self) -> Vec<u32>46     fn destination_ssrc(&self) -> Vec<u32> {
47         self.sources.to_vec()
48     }
49 
raw_size(&self) -> usize50     fn raw_size(&self) -> usize {
51         let srcs_length = self.sources.len() * SSRC_LENGTH;
52         let reason_length = self.reason.len() + 1;
53 
54         HEADER_LENGTH + srcs_length + reason_length
55     }
56 
as_any(&self) -> &(dyn Any + Send + Sync)57     fn as_any(&self) -> &(dyn Any + Send + Sync) {
58         self
59     }
60 
equal(&self, other: &(dyn Packet + Send + Sync)) -> bool61     fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
62         other
63             .as_any()
64             .downcast_ref::<Goodbye>()
65             .map_or(false, |a| self == a)
66     }
67 
cloned(&self) -> Box<dyn Packet + Send + Sync>68     fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
69         Box::new(self.clone())
70     }
71 }
72 
73 impl MarshalSize for Goodbye {
marshal_size(&self) -> usize74     fn marshal_size(&self) -> usize {
75         let l = self.raw_size();
76         // align to 32-bit boundary
77         l + get_padding_size(l)
78     }
79 }
80 
81 impl Marshal for Goodbye {
82     /// marshal_to encodes the packet in binary.
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>83     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
84         if self.sources.len() > COUNT_MAX {
85             return Err(Error::TooManySources.into());
86         }
87 
88         if self.reason.len() > SDES_MAX_OCTET_COUNT {
89             return Err(Error::ReasonTooLong.into());
90         }
91 
92         if buf.remaining_mut() < self.marshal_size() {
93             return Err(Error::BufferTooShort.into());
94         }
95 
96         /*
97          *        0                   1                   2                   3
98          *        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
99          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100          *       |V=2|P|    SC   |   PT=BYE=203  |             length            |
101          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102          *       |                           SSRC/CSRC                           |
103          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104          *       :                              ...                              :
105          *       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
106          * (opt) |     length    |               reason for leaving            ...
107          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108          */
109 
110         let h = self.header();
111         let n = h.marshal_to(buf)?;
112         buf = &mut buf[n..];
113 
114         for source in &self.sources {
115             buf.put_u32(*source);
116         }
117 
118         buf.put_u8(self.reason.len() as u8);
119         if !self.reason.is_empty() {
120             buf.put(self.reason.clone());
121         }
122 
123         if h.padding {
124             put_padding(buf, self.raw_size());
125         }
126 
127         Ok(self.marshal_size())
128     }
129 }
130 
131 impl Unmarshal for Goodbye {
unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,132     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
133     where
134         Self: Sized,
135         B: Buf,
136     {
137         /*
138          *        0                   1                   2                   3
139          *        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
140          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
141          *       |V=2|P|    SC   |   PT=BYE=203  |             length            |
142          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143          *       |                           SSRC/CSRC                           |
144          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145          *       :                              ...                              :
146          *       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
147          * (opt) |     length    |               reason for leaving            ...
148          *       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149          */
150         let raw_packet_len = raw_packet.remaining();
151 
152         let header = Header::unmarshal(raw_packet)?;
153         if header.packet_type != PacketType::Goodbye {
154             return Err(Error::WrongType.into());
155         }
156 
157         if get_padding_size(raw_packet_len) != 0 {
158             return Err(Error::PacketTooShort.into());
159         }
160 
161         let reason_offset = HEADER_LENGTH + header.count as usize * SSRC_LENGTH;
162 
163         if reason_offset > raw_packet_len {
164             return Err(Error::PacketTooShort.into());
165         }
166 
167         let mut sources = Vec::with_capacity(header.count as usize);
168         for _ in 0..header.count {
169             sources.push(raw_packet.get_u32());
170         }
171 
172         let reason = if reason_offset < raw_packet_len {
173             let reason_len = raw_packet.get_u8() as usize;
174             let reason_end = reason_offset + 1 + reason_len;
175 
176             if reason_end > raw_packet_len {
177                 return Err(Error::PacketTooShort.into());
178             }
179 
180             raw_packet.copy_to_bytes(reason_len)
181         } else {
182             Bytes::new()
183         };
184 
185         if
186         /*header.padding &&*/
187         raw_packet.has_remaining() {
188             raw_packet.advance(raw_packet.remaining());
189         }
190 
191         Ok(Goodbye { sources, reason })
192     }
193 }
194