1use super::ack::AckPacket;
21use super::handshake::HandshakePacket;
22use super::misc::{
23 AckAckPacket, CongestionWarningPacket, DropReqPacket, KeepAlivePacket, PeerErrorPacket,
24 ShutdownPacket,
25};
26use super::nak::NakPacket;
27use super::{Error, Result, SRT_HEADER_LEN, be32, put_be32};
28
29pub const CONTROL_TYPE_HANDSHAKE: u16 = 0x0000;
31pub const CONTROL_TYPE_KEEPALIVE: u16 = 0x0001;
33pub const CONTROL_TYPE_ACK: u16 = 0x0002;
35pub const CONTROL_TYPE_NAK: u16 = 0x0003;
37pub const CONTROL_TYPE_CONGESTION_WARNING: u16 = 0x0004;
39pub const CONTROL_TYPE_SHUTDOWN: u16 = 0x0005;
41pub const CONTROL_TYPE_ACKACK: u16 = 0x0006;
43pub const CONTROL_TYPE_DROPREQ: u16 = 0x0007;
45pub const CONTROL_TYPE_PEERERROR: u16 = 0x0008;
47pub const CONTROL_TYPE_USER_DEFINED: u16 = 0x7FFF;
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
54#[cfg_attr(feature = "serde", derive(serde::Serialize))]
55#[non_exhaustive]
56pub enum ControlType {
57 Handshake,
59 KeepAlive,
61 Ack,
63 Nak,
65 CongestionWarning,
67 Shutdown,
69 AckAck,
71 DropReq,
73 PeerError,
75 UserDefined,
78 Reserved(u16),
80}
81
82impl ControlType {
83 pub fn from_bits(v: u16) -> Self {
85 match v {
86 CONTROL_TYPE_HANDSHAKE => ControlType::Handshake,
87 CONTROL_TYPE_KEEPALIVE => ControlType::KeepAlive,
88 CONTROL_TYPE_ACK => ControlType::Ack,
89 CONTROL_TYPE_NAK => ControlType::Nak,
90 CONTROL_TYPE_CONGESTION_WARNING => ControlType::CongestionWarning,
91 CONTROL_TYPE_SHUTDOWN => ControlType::Shutdown,
92 CONTROL_TYPE_ACKACK => ControlType::AckAck,
93 CONTROL_TYPE_DROPREQ => ControlType::DropReq,
94 CONTROL_TYPE_PEERERROR => ControlType::PeerError,
95 CONTROL_TYPE_USER_DEFINED => ControlType::UserDefined,
96 other => ControlType::Reserved(other),
97 }
98 }
99
100 pub fn to_bits(self) -> u16 {
102 match self {
103 ControlType::Handshake => CONTROL_TYPE_HANDSHAKE,
104 ControlType::KeepAlive => CONTROL_TYPE_KEEPALIVE,
105 ControlType::Ack => CONTROL_TYPE_ACK,
106 ControlType::Nak => CONTROL_TYPE_NAK,
107 ControlType::CongestionWarning => CONTROL_TYPE_CONGESTION_WARNING,
108 ControlType::Shutdown => CONTROL_TYPE_SHUTDOWN,
109 ControlType::AckAck => CONTROL_TYPE_ACKACK,
110 ControlType::DropReq => CONTROL_TYPE_DROPREQ,
111 ControlType::PeerError => CONTROL_TYPE_PEERERROR,
112 ControlType::UserDefined => CONTROL_TYPE_USER_DEFINED,
113 ControlType::Reserved(v) => v,
114 }
115 }
116
117 pub fn name(&self) -> &'static str {
119 match self {
120 ControlType::Handshake => "handshake",
121 ControlType::KeepAlive => "keep-alive",
122 ControlType::Ack => "ACK",
123 ControlType::Nak => "NAK",
124 ControlType::CongestionWarning => "congestion warning",
125 ControlType::Shutdown => "shutdown",
126 ControlType::AckAck => "ACKACK",
127 ControlType::DropReq => "message drop request",
128 ControlType::PeerError => "peer error",
129 ControlType::UserDefined => "user-defined",
130 ControlType::Reserved(_) => "reserved",
131 }
132 }
133}
134
135broadcast_common::impl_spec_display!(ControlType, Reserved);
136
137#[derive(Debug, Clone, PartialEq)]
142#[cfg_attr(feature = "serde", derive(serde::Serialize))]
143pub struct UserDefinedPacket<'a> {
144 pub control_type: u16,
146 pub subtype: u16,
149 pub type_specific_info: u32,
151 pub timestamp: u32,
153 pub dest_socket_id: u32,
155 pub cif: &'a [u8],
157}
158
159impl<'a> UserDefinedPacket<'a> {
160 pub fn as_key_material(&self) -> Result<super::KeyMaterial<'a>> {
164 super::KeyMaterial::parse(self.cif)
165 }
166}
167
168#[derive(Debug, Clone, PartialEq)]
170#[cfg_attr(feature = "serde", derive(serde::Serialize))]
171#[non_exhaustive]
172pub enum ControlPacket<'a> {
173 Handshake(HandshakePacket<'a>),
175 KeepAlive(KeepAlivePacket),
177 Ack(AckPacket),
179 Nak(NakPacket<'a>),
181 CongestionWarning(CongestionWarningPacket),
183 Shutdown(ShutdownPacket),
185 AckAck(AckAckPacket),
187 DropReq(DropReqPacket),
189 PeerError(PeerErrorPacket),
191 UserDefined(UserDefinedPacket<'a>),
193}
194
195fn check_reserved_u16(what: &'static str, v: u16) -> Result<()> {
196 if v != 0 {
197 return Err(Error::ReservedFieldNotZero {
198 what,
199 value: u64::from(v),
200 });
201 }
202 Ok(())
203}
204
205fn check_reserved_u32(what: &'static str, v: u32) -> Result<()> {
206 if v != 0 {
207 return Err(Error::ReservedFieldNotZero {
208 what,
209 value: u64::from(v),
210 });
211 }
212 Ok(())
213}
214
215fn check_no_cif(what: &'static str, cif: &[u8]) -> Result<()> {
216 if !cif.is_empty() {
217 return Err(Error::UnexpectedTrailingBytes {
218 what,
219 extra: cif.len(),
220 });
221 }
222 Ok(())
223}
224
225impl<'a> ControlPacket<'a> {
226 pub fn parse(bytes: &'a [u8]) -> Result<Self> {
233 if bytes.len() < SRT_HEADER_LEN {
234 return Err(Error::BufferTooShort {
235 need: SRT_HEADER_LEN,
236 have: bytes.len(),
237 what: "SRT control packet header",
238 });
239 }
240 let word0 = be32(bytes, 0);
241 if word0 & super::F_BIT == 0 {
242 return Err(Error::WrongPacketKind {
243 expected: "control packet (F=1)",
244 });
245 }
246 let control_type_bits = ((word0 >> 16) & 0x7FFF) as u16;
247 let subtype = (word0 & 0xFFFF) as u16;
248 let type_specific_info = be32(bytes, 4);
249 let timestamp = be32(bytes, 8);
250 let dest_socket_id = be32(bytes, 12);
251 let cif = &bytes[SRT_HEADER_LEN..];
252 let control_type = ControlType::from_bits(control_type_bits);
253
254 Ok(match control_type {
255 ControlType::Handshake => {
256 check_reserved_u16("Subtype", subtype)?;
257 check_reserved_u32("Type-specific Information", type_specific_info)?;
258 ControlPacket::Handshake(HandshakePacket::parse_cif(
259 timestamp,
260 dest_socket_id,
261 cif,
262 )?)
263 }
264 ControlType::KeepAlive => {
265 check_reserved_u16("Subtype", subtype)?;
266 check_reserved_u32("Type-specific Information", type_specific_info)?;
267 check_no_cif("keep-alive CIF", cif)?;
268 ControlPacket::KeepAlive(KeepAlivePacket {
269 timestamp,
270 dest_socket_id,
271 })
272 }
273 ControlType::Ack => {
274 check_reserved_u16("Subtype", subtype)?;
275 ControlPacket::Ack(AckPacket::parse_cif(
276 type_specific_info,
277 timestamp,
278 dest_socket_id,
279 cif,
280 )?)
281 }
282 ControlType::Nak => {
283 check_reserved_u16("Subtype", subtype)?;
284 check_reserved_u32("Type-specific Information", type_specific_info)?;
285 ControlPacket::Nak(NakPacket::parse_cif(timestamp, dest_socket_id, cif))
286 }
287 ControlType::CongestionWarning => {
288 check_reserved_u16("Subtype", subtype)?;
289 check_reserved_u32("Type-specific Information", type_specific_info)?;
290 check_no_cif("congestion warning CIF", cif)?;
291 ControlPacket::CongestionWarning(CongestionWarningPacket {
292 timestamp,
293 dest_socket_id,
294 })
295 }
296 ControlType::Shutdown => {
297 check_reserved_u16("Subtype", subtype)?;
298 check_reserved_u32("Type-specific Information", type_specific_info)?;
299 check_no_cif("shutdown CIF", cif)?;
300 ControlPacket::Shutdown(ShutdownPacket {
301 timestamp,
302 dest_socket_id,
303 })
304 }
305 ControlType::AckAck => {
306 check_reserved_u16("Subtype", subtype)?;
307 check_no_cif("ACKACK CIF", cif)?;
308 ControlPacket::AckAck(AckAckPacket {
309 ack_number: type_specific_info,
310 timestamp,
311 dest_socket_id,
312 })
313 }
314 ControlType::DropReq => {
315 check_reserved_u16("Subtype", subtype)?;
316 ControlPacket::DropReq(DropReqPacket::parse_cif(
317 type_specific_info,
318 timestamp,
319 dest_socket_id,
320 cif,
321 )?)
322 }
323 ControlType::PeerError => {
324 check_reserved_u16("Subtype", subtype)?;
325 check_no_cif("peer error CIF", cif)?;
326 ControlPacket::PeerError(PeerErrorPacket {
327 error_code: type_specific_info,
328 timestamp,
329 dest_socket_id,
330 })
331 }
332 ControlType::UserDefined | ControlType::Reserved(_) => {
333 ControlPacket::UserDefined(UserDefinedPacket {
334 control_type: control_type_bits,
335 subtype,
336 type_specific_info,
337 timestamp,
338 dest_socket_id,
339 cif,
340 })
341 }
342 })
343 }
344
345 pub fn control_type(&self) -> ControlType {
347 match self {
348 ControlPacket::Handshake(_) => ControlType::Handshake,
349 ControlPacket::KeepAlive(_) => ControlType::KeepAlive,
350 ControlPacket::Ack(_) => ControlType::Ack,
351 ControlPacket::Nak(_) => ControlType::Nak,
352 ControlPacket::CongestionWarning(_) => ControlType::CongestionWarning,
353 ControlPacket::Shutdown(_) => ControlType::Shutdown,
354 ControlPacket::AckAck(_) => ControlType::AckAck,
355 ControlPacket::DropReq(_) => ControlType::DropReq,
356 ControlPacket::PeerError(_) => ControlType::PeerError,
357 ControlPacket::UserDefined(u) => ControlType::from_bits(u.control_type),
358 }
359 }
360
361 fn subtype(&self) -> u16 {
362 match self {
363 ControlPacket::UserDefined(u) => u.subtype,
364 _ => 0,
365 }
366 }
367
368 fn word1(&self) -> u32 {
369 match self {
370 ControlPacket::Handshake(_)
371 | ControlPacket::KeepAlive(_)
372 | ControlPacket::Nak(_)
373 | ControlPacket::CongestionWarning(_)
374 | ControlPacket::Shutdown(_) => 0,
375 ControlPacket::Ack(a) => a.ack_number,
376 ControlPacket::AckAck(a) => a.ack_number,
377 ControlPacket::DropReq(d) => d.message_number,
378 ControlPacket::PeerError(p) => p.error_code,
379 ControlPacket::UserDefined(u) => u.type_specific_info,
380 }
381 }
382
383 fn timestamp(&self) -> u32 {
384 match self {
385 ControlPacket::Handshake(h) => h.timestamp,
386 ControlPacket::KeepAlive(k) => k.timestamp,
387 ControlPacket::Ack(a) => a.timestamp,
388 ControlPacket::Nak(n) => n.timestamp,
389 ControlPacket::CongestionWarning(c) => c.timestamp,
390 ControlPacket::Shutdown(s) => s.timestamp,
391 ControlPacket::AckAck(a) => a.timestamp,
392 ControlPacket::DropReq(d) => d.timestamp,
393 ControlPacket::PeerError(p) => p.timestamp,
394 ControlPacket::UserDefined(u) => u.timestamp,
395 }
396 }
397
398 fn dest_socket_id(&self) -> u32 {
399 match self {
400 ControlPacket::Handshake(h) => h.dest_socket_id,
401 ControlPacket::KeepAlive(k) => k.dest_socket_id,
402 ControlPacket::Ack(a) => a.dest_socket_id,
403 ControlPacket::Nak(n) => n.dest_socket_id,
404 ControlPacket::CongestionWarning(c) => c.dest_socket_id,
405 ControlPacket::Shutdown(s) => s.dest_socket_id,
406 ControlPacket::AckAck(a) => a.dest_socket_id,
407 ControlPacket::DropReq(d) => d.dest_socket_id,
408 ControlPacket::PeerError(p) => p.dest_socket_id,
409 ControlPacket::UserDefined(u) => u.dest_socket_id,
410 }
411 }
412
413 fn cif_len(&self) -> usize {
414 match self {
415 ControlPacket::Handshake(h) => h.cif_len(),
416 ControlPacket::KeepAlive(_)
417 | ControlPacket::CongestionWarning(_)
418 | ControlPacket::Shutdown(_)
419 | ControlPacket::AckAck(_)
420 | ControlPacket::PeerError(_) => 0,
421 ControlPacket::Ack(a) => a.cif_len(),
422 ControlPacket::Nak(n) => n.cif_len(),
423 ControlPacket::DropReq(d) => d.cif_len(),
424 ControlPacket::UserDefined(u) => u.cif.len(),
425 }
426 }
427
428 pub fn serialized_len(&self) -> usize {
430 SRT_HEADER_LEN + self.cif_len()
431 }
432
433 pub fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
435 let len = self.serialized_len();
436 if buf.len() < len {
437 return Err(Error::OutputBufferTooSmall {
438 need: len,
439 have: buf.len(),
440 });
441 }
442 let control_type_bits = self.control_type().to_bits();
443 if control_type_bits > 0x7FFF {
444 return Err(Error::FieldTooWide {
445 what: "Control Type",
446 value: u64::from(control_type_bits),
447 bits: 15,
448 });
449 }
450 let word0 = super::F_BIT | (u32::from(control_type_bits) << 16) | u32::from(self.subtype());
451 put_be32(buf, 0, word0);
452 put_be32(buf, 4, self.word1());
453 put_be32(buf, 8, self.timestamp());
454 put_be32(buf, 12, self.dest_socket_id());
455 let cif = &mut buf[SRT_HEADER_LEN..len];
456 match self {
457 ControlPacket::Handshake(h) => {
458 h.write_cif(cif)?;
459 }
460 ControlPacket::KeepAlive(_)
461 | ControlPacket::CongestionWarning(_)
462 | ControlPacket::Shutdown(_)
463 | ControlPacket::AckAck(_)
464 | ControlPacket::PeerError(_) => {}
465 ControlPacket::Ack(a) => {
466 a.write_cif(cif)?;
467 }
468 ControlPacket::Nak(n) => {
469 n.write_cif(cif);
470 }
471 ControlPacket::DropReq(d) => {
472 d.write_cif(cif);
473 }
474 ControlPacket::UserDefined(u) => {
475 cif.copy_from_slice(u.cif);
476 }
477 }
478 Ok(len)
479 }
480}