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#[derive(Debug, PartialEq, Eq, Default, Clone)]
16pub struct Goodbye {
17 pub sources: Vec<u32>,
19 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 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 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 l + get_padding_size(l)
76 }
77}
78
79impl Marshal for Goodbye {
80 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 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 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 raw_packet.has_remaining() {
186 raw_packet.advance(raw_packet.remaining());
187 }
188
189 Ok(Goodbye { sources, reason })
190 }
191}