Skip to main content

rtc_rtcp/goodbye/
mod.rs

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