1use std::collections::{HashMap, VecDeque};
10use std::hash::{BuildHasher, RandomState};
11use std::net::SocketAddr;
12use std::time::{Duration, Instant};
13
14use crate::crypto::{CryptoConfig, Decryptor};
15use crate::packet::{
16 Control, ControlPacket, Extension, Handshake, HandshakeKind, Packet, SRT_MAGIC, SrtHandshake,
17 ext_flags, srt_flags,
18};
19use crate::receiver::{CloseReason, Receiver, Settings, Stats};
20use crate::seq::Seq;
21
22pub const SRT_VERSION: u32 = 0x01_05_00;
25
26pub const OUR_FLAGS: u32 = srt_flags::TSBPDSND
30 | srt_flags::TSBPDRCV
31 | srt_flags::CRYPT
32 | srt_flags::TLPKTDROP
33 | srt_flags::PERIODICNAK
34 | srt_flags::REXMITFLG;
35
36const COOKIE_PERIOD: i64 = 60_000_000;
38const MTU_MAX: u32 = 1500;
40const OVERHEAD: u32 = 28 + 16;
42
43#[derive(Debug, Clone)]
45pub struct Config {
46 pub latency: Duration,
48 pub max_connections: usize,
50 pub handshakes_per_second: u32,
52 pub buffer_packets: usize,
54 pub peer_idle: Duration,
56 pub accept_timeout: Duration,
58 pub crypto: Option<CryptoConfig>,
60 pub require_encryption: bool,
63 pub allow_plaintext: bool,
68}
69
70impl Default for Config {
71 fn default() -> Self {
72 Self {
73 latency: Duration::from_millis(120),
74 max_connections: 64,
75 handshakes_per_second: 100,
76 buffer_packets: 8192,
77 peer_idle: Duration::from_secs(5),
78 accept_timeout: Duration::from_secs(5),
79 crypto: None,
80 require_encryption: false,
81 allow_plaintext: false,
82 }
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
88pub struct ConnId(pub u32);
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub struct RejectCode(pub u32);
93
94impl RejectCode {
95 pub const UNKNOWN: Self = Self(1000);
97 pub const SYSTEM: Self = Self(1001);
99 pub const PEER: Self = Self(1002);
101 pub const RESOURCE: Self = Self(1003);
103 pub const ROGUE: Self = Self(1004);
106 pub const BACKLOG: Self = Self(1005);
109 pub const CLOSE: Self = Self(1007);
111 pub const VERSION: Self = Self(1008);
114 pub const BADSECRET: Self = Self(1010);
117 pub const UNSECURE: Self = Self(1011);
120 pub const MESSAGE_API: Self = Self(1012);
123 pub const CONGESTION: Self = Self(1013);
125 pub const FILTER: Self = Self(1014);
128 pub const GROUP: Self = Self(1015);
131
132 pub const fn http(status: u16) -> Self {
135 Self(2000 + status as u32)
136 }
137}
138
139#[derive(Debug, Clone, PartialEq, Eq)]
142pub enum Event {
143 Connect {
148 id: ConnId,
150 peer: SocketAddr,
152 stream_id: Vec<u8>,
154 },
155 Data {
157 id: ConnId,
159 payload: Vec<u8>,
161 },
162 Closed {
165 id: ConnId,
167 reason: Option<CloseReason>,
169 stats: Stats,
172 },
173}
174
175#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
177pub struct ListenerStats {
178 pub malformed: u64,
180 pub stray: u64,
182 pub bad_cookie: u64,
184 pub rate_limited: u64,
186 pub rejected: u64,
189}
190
191struct Pending {
192 hs: Handshake,
193 hs_timestamp: u32,
194 latency: i64,
195 since: i64,
196}
197
198enum State {
199 Pending(Box<Pending>),
200 Open {
201 rx: Box<Receiver>,
202 response: Vec<u8>,
205 },
206}
207
208struct Conn {
209 peer: SocketAddr,
210 caller_socket: u32,
211 state: State,
212 next_timer: i64,
213}
214
215pub struct Listener<S = RandomState> {
219 config: Config,
220 epoch: Instant,
221 key: S,
223 ids_made: u64,
224 conns: HashMap<u32, Conn>,
225 by_caller: HashMap<(SocketAddr, u32), u32>,
226 transmits: VecDeque<(SocketAddr, Vec<u8>)>,
227 events: VecDeque<Event>,
228 tokens: u64,
230 tokens_at: i64,
231 stats: ListenerStats,
232}
233
234impl Listener<RandomState> {
235 pub fn new(config: Config, now: Instant) -> Self {
238 Self::with_key(config, now, RandomState::new())
239 }
240}
241
242impl<S: BuildHasher> Listener<S> {
243 pub fn with_key(config: Config, now: Instant, key: S) -> Self {
246 let burst = u64::from(config.handshakes_per_second) * 2 * 1_000_000;
247 Self {
248 config,
249 epoch: now,
250 key,
251 ids_made: 0,
252 conns: HashMap::new(),
253 by_caller: HashMap::new(),
254 transmits: VecDeque::new(),
255 events: VecDeque::new(),
256 tokens: burst,
257 tokens_at: 0,
258 stats: ListenerStats::default(),
259 }
260 }
261
262 fn micros(&self, now: Instant) -> i64 {
263 i64::try_from(now.saturating_duration_since(self.epoch).as_micros()).unwrap_or(i64::MAX)
264 }
265
266 pub fn stats(&self) -> ListenerStats {
268 self.stats
269 }
270
271 pub fn connections(&self) -> usize {
273 self.conns.len()
274 }
275
276 pub fn connection_stats(&self, id: ConnId) -> Option<Stats> {
279 match &self.conns.get(&id.0)?.state {
280 State::Open { rx, .. } => Some(rx.stats()),
281 State::Pending(_) => None,
282 }
283 }
284
285 pub fn latency(&self, id: ConnId) -> Option<Duration> {
287 match &self.conns.get(&id.0)?.state {
288 State::Open { rx, .. } => Some(Duration::from_micros(rx.latency().max(0) as u64)),
289 State::Pending(_) => None,
290 }
291 }
292
293 pub fn poll_transmit(&mut self) -> Option<(SocketAddr, Vec<u8>)> {
295 self.transmits.pop_front()
296 }
297
298 pub fn poll_event(&mut self) -> Option<Event> {
300 self.events.pop_front()
301 }
302
303 pub fn poll_timeout(&self) -> Option<Instant> {
306 let t = self.conns.values().map(|c| c.next_timer).min()?;
307 let at = Duration::from_micros(t.max(0) as u64);
308 self.epoch
309 .checked_add(at)
310 .or_else(|| self.epoch.checked_add(Duration::from_secs(3600)))
311 }
312
313 pub fn handle_datagram(&mut self, now: Instant, peer: SocketAddr, datagram: &[u8]) {
316 let t = self.micros(now);
317 if datagram.len() > 1500 {
318 self.stats.malformed += 1;
319 return;
320 }
321 let packet = match Packet::parse(datagram) {
322 Ok(p) => p,
323 Err(_) => {
324 self.stats.malformed += 1;
325 return;
326 }
327 };
328 match packet {
329 Packet::Data(d) => {
330 let Some(c) = self.conns.get_mut(&d.dest).filter(|c| c.peer == peer) else {
331 self.stats.stray += 1;
332 return;
333 };
334 if let State::Open { rx, .. } = &mut c.state {
335 rx.on_data(t, &d);
336 let id = d.dest;
337 self.collect(id);
338 } else {
339 self.stats.stray += 1;
340 }
341 }
342 Packet::Control(ControlPacket {
343 timestamp,
344 body: Control::Handshake(h),
345 ..
346 }) => self.handshake(t, peer, timestamp, h),
347 Packet::Control(c) => {
348 let Some(conn) = self.conns.get_mut(&c.dest).filter(|x| x.peer == peer) else {
349 self.stats.stray += 1;
350 return;
351 };
352 if let State::Open { rx, .. } = &mut conn.state {
353 rx.on_control(t, &c.body);
354 self.collect(c.dest);
355 }
356 }
357 }
358 }
359
360 pub fn handle_timeout(&mut self, now: Instant) {
363 let t = self.micros(now);
364 let due: Vec<u32> = self
365 .conns
366 .iter()
367 .filter(|(_, c)| c.next_timer <= t)
368 .map(|(id, _)| *id)
369 .collect();
370 let accept_timeout = duration_micros(self.config.accept_timeout);
371 for id in due {
372 let Some(c) = self.conns.get_mut(&id) else {
373 continue;
374 };
375 match &mut c.state {
376 State::Pending(p) => {
377 if t - p.since >= accept_timeout {
378 self.remove(id);
379 self.events.push_back(Event::Closed {
380 id: ConnId(id),
381 reason: None,
382 stats: Stats::default(),
383 });
384 }
385 }
386 State::Open { rx, .. } => {
387 rx.on_timer(t);
388 self.collect(id);
389 }
390 }
391 }
392 }
393
394 fn plaintext_allowed(&self) -> bool {
396 !self.config.require_encryption
397 && (self.config.crypto.is_none() || self.config.allow_plaintext)
398 }
399
400 pub fn accept(&mut self, id: ConnId, now: Instant) -> bool {
403 self.accept_with_crypto(id, now, self.config.crypto.clone())
404 }
405
406 pub fn accept_with_crypto(
412 &mut self,
413 id: ConnId,
414 now: Instant,
415 crypto: Option<CryptoConfig>,
416 ) -> bool {
417 let Some(c) = self.conns.get(&id.0) else {
418 return false;
419 };
420 let State::Pending(p) = &c.state else {
421 return false;
422 };
423 let km = p.hs.extensions.iter().find_map(|e| match e {
424 Extension::KmReq(b) => Some(b),
425 _ => None,
426 });
427 let decryptor = match (&crypto, km) {
428 (Some(config), Some(bytes)) => match Decryptor::new(config, bytes) {
429 Ok(d) => Some(d),
430 Err(_) => {
431 self.reject(id, RejectCode::BADSECRET);
432 return false;
433 }
434 },
435 (_, None) if self.plaintext_allowed() => None,
436 _ => {
437 self.reject(id, RejectCode::UNSECURE);
438 return false;
439 }
440 };
441 let km_response = km.cloned();
442 let t = self.micros(now);
443 let max_payload = MTU_MAX - OVERHEAD;
444 let buffer = self.config.buffer_packets.max(32);
445 let peer_idle = duration_micros(self.config.peer_idle);
446 let Some(c) = self.conns.get_mut(&id.0) else {
447 return false;
448 };
449 let State::Pending(p) = &c.state else {
450 return false;
451 };
452 let p = &**p;
453 let req = p.hs.srt_request().unwrap_or(SrtHandshake {
454 version: 0,
455 flags: 0,
456 receiver_delay: 0,
457 sender_delay: 0,
458 });
459 let ms = u16::try_from(p.latency / 1000).unwrap_or(u16::MAX);
460 let mut response = Handshake {
461 version: 5,
462 encryption: match (&crypto, &decryptor) {
463 (Some(c), Some(_)) => c.key_size.field(),
464 _ => 0,
465 },
466 extension: ext_flags::HSREQ
467 | if decryptor.is_some() {
468 ext_flags::KMREQ
469 } else {
470 0
471 },
472 initial_seq: p.hs.initial_seq,
473 mtu: p.hs.mtu.min(MTU_MAX),
474 flow_window: p
475 .hs
476 .flow_window
477 .min(u32::try_from(buffer).unwrap_or(u32::MAX)),
478 kind: HandshakeKind::Conclusion,
479 socket_id: id.0,
480 cookie: p.hs.cookie,
481 peer_ip: encode_ip(c.peer),
482 extensions: vec![Extension::HsRsp(SrtHandshake {
483 version: SRT_VERSION,
484 flags: OUR_FLAGS,
485 receiver_delay: ms,
486 sender_delay: ms.max(req.receiver_delay),
487 })],
488 };
489 if let Some(km) = km_response {
490 response.extensions.push(Extension::KmRsp(km));
491 }
492 let mut bytes = Vec::with_capacity(184);
493 ControlPacket::new(0, c.caller_socket, Control::Handshake(response)).encode(&mut bytes);
494 let mut rx = Receiver::new(
495 Settings {
496 latency: p.latency,
497 buffer,
498 peer_idle,
499 max_payload: max_payload as usize,
500 },
501 t,
502 c.caller_socket,
503 Seq::new(p.hs.initial_seq),
504 p.hs_timestamp,
505 );
506 rx.set_crypto(decryptor);
507 self.transmits.push_back((c.peer, bytes.clone()));
508 c.state = State::Open {
509 rx: Box::new(rx),
510 response: bytes,
511 };
512 self.collect(id.0);
513 true
514 }
515
516 pub fn reject(&mut self, id: ConnId, code: RejectCode) -> bool {
518 let Some(c) = self.conns.get(&id.0) else {
519 return false;
520 };
521 let State::Pending(p) = &c.state else {
522 return false;
523 };
524 let (peer, hs) = (c.peer, p.hs.clone());
525 self.send_rejection(peer, &hs, code);
526 self.remove(id.0);
527 true
528 }
529
530 pub fn close(&mut self, id: ConnId, now: Instant) {
533 let t = self.micros(now);
534 if let Some(c) = self.conns.get_mut(&id.0)
535 && let State::Open { rx, .. } = &mut c.state
536 {
537 rx.shutdown(t);
538 while let Some(b) = rx.take_send() {
539 self.transmits.push_back((c.peer, b));
540 }
541 }
542 self.remove(id.0);
543 }
544
545 fn remove(&mut self, id: u32) {
546 if let Some(c) = self.conns.remove(&id) {
547 self.by_caller.remove(&(c.peer, c.caller_socket));
548 }
549 }
550
551 fn collect(&mut self, id: u32) {
553 let Some(c) = self.conns.get_mut(&id) else {
554 return;
555 };
556 let State::Open { rx, .. } = &mut c.state else {
557 return;
558 };
559 while let Some(b) = rx.take_send() {
560 self.transmits.push_back((c.peer, b));
561 }
562 while let Some(payload) = rx.take_delivery() {
563 self.events.push_back(Event::Data {
564 id: ConnId(id),
565 payload,
566 });
567 }
568 if let Some(reason) = rx.closed() {
569 let stats = rx.stats();
570 self.remove(id);
571 self.events.push_back(Event::Closed {
572 id: ConnId(id),
573 reason: Some(reason),
574 stats,
575 });
576 return;
577 }
578 c.next_timer = rx.next_timer();
579 }
580
581 fn take_token(&mut self, t: i64) -> bool {
582 let rate = u64::from(self.config.handshakes_per_second);
583 let burst = rate * 2 * 1_000_000;
584 let elapsed = (t - self.tokens_at).max(0) as u64;
585 self.tokens = self
586 .tokens
587 .saturating_add(elapsed.saturating_mul(rate))
588 .min(burst);
589 self.tokens_at = t;
590 if self.tokens >= 1_000_000 {
591 self.tokens -= 1_000_000;
592 true
593 } else {
594 false
595 }
596 }
597
598 fn cookie(&self, peer: SocketAddr, period: i64) -> u32 {
599 let h = self.key.hash_one((b"srt cookie", peer, period));
600 (h ^ (h >> 32)) as u32
601 }
602
603 fn new_socket_id(&mut self) -> u32 {
604 loop {
605 self.ids_made += 1;
606 let h = self.key.hash_one((b"srt socket", self.ids_made));
607 let id = ((h ^ (h >> 32)) as u32) & 0x3FFF_FFFF;
609 if id != 0 && !self.conns.contains_key(&id) {
610 return id;
611 }
612 }
613 }
614
615 fn handshake(&mut self, t: i64, peer: SocketAddr, timestamp: u32, h: Handshake) {
616 match h.kind {
617 HandshakeKind::Induction => {
618 if !self.take_token(t) {
619 self.stats.rate_limited += 1;
620 return;
621 }
622 self.induction(t, peer, &h);
623 }
624 HandshakeKind::Conclusion => {
625 if let Some(id) = self.by_caller.get(&(peer, h.socket_id)) {
627 if let Some(Conn {
628 state: State::Open { response, .. },
629 ..
630 }) = self.conns.get(id)
631 {
632 self.transmits.push_back((peer, response.clone()));
633 }
634 return;
635 }
636 if !self.take_token(t) {
637 self.stats.rate_limited += 1;
638 return;
639 }
640 let period = t / COOKIE_PERIOD;
641 if h.cookie != self.cookie(peer, period)
642 && h.cookie != self.cookie(peer, period - 1)
643 {
644 self.stats.bad_cookie += 1;
646 return;
647 }
648 self.conclusion(t, peer, timestamp, h);
649 }
650 _ => self.stats.stray += 1,
651 }
652 }
653
654 fn induction(&mut self, t: i64, peer: SocketAddr, h: &Handshake) {
655 let reply = Handshake {
660 version: 5,
661 encryption: match &self.config.crypto {
662 Some(c) if !self.config.allow_plaintext || self.config.require_encryption => {
663 c.key_size.field()
664 }
665 _ => 0,
666 },
667 extension: SRT_MAGIC,
668 initial_seq: h.initial_seq,
669 mtu: h.mtu,
670 flow_window: h.flow_window,
671 kind: HandshakeKind::Induction,
672 socket_id: h.socket_id,
673 cookie: self.cookie(peer, t / COOKIE_PERIOD),
674 peer_ip: encode_ip(peer),
675 extensions: Vec::new(),
676 };
677 let mut out = Vec::with_capacity(64);
678 ControlPacket::new(t as u32, h.socket_id, Control::Handshake(reply)).encode(&mut out);
679 self.transmits.push_back((peer, out));
680 }
681
682 fn conclusion(&mut self, t: i64, peer: SocketAddr, timestamp: u32, h: Handshake) {
683 if let Err(code) = self.check(&h) {
684 self.send_rejection(peer, &h, code);
685 return;
686 }
687 if self.conns.len() >= self.config.max_connections {
688 self.send_rejection(peer, &h, RejectCode::BACKLOG);
689 return;
690 }
691 let ours = duration_micros(self.config.latency);
692 let theirs = h
693 .srt_request()
694 .map_or(0, |r| i64::from(r.sender_delay) * 1000);
695 let id = self.new_socket_id();
696 let stream_id = h.stream_id().map(<[u8]>::to_vec).unwrap_or_default();
697 self.by_caller.insert((peer, h.socket_id), id);
698 self.conns.insert(
699 id,
700 Conn {
701 peer,
702 caller_socket: h.socket_id,
703 state: State::Pending(Box::new(Pending {
704 hs: h,
705 hs_timestamp: timestamp,
706 latency: ours.max(theirs),
707 since: t,
708 })),
709 next_timer: t.saturating_add(duration_micros(self.config.accept_timeout)),
710 },
711 );
712 self.events.push_back(Event::Connect {
713 id: ConnId(id),
714 peer,
715 stream_id,
716 });
717 }
718
719 fn check(&self, h: &Handshake) -> Result<(), RejectCode> {
722 if h.version != 5 {
723 return Err(RejectCode::VERSION);
724 }
725 let requests: Vec<_> = h
726 .extensions
727 .iter()
728 .filter_map(|e| match e {
729 Extension::KmReq(b) => Some(b),
730 _ => None,
731 })
732 .collect();
733 let km = requests.first();
734 if requests.len() > 1
735 || h.extensions
736 .iter()
737 .any(|e| matches!(e, Extension::KmRsp(_)))
738 {
739 return Err(RejectCode::ROGUE);
740 }
741 if let Some(km) = km {
742 if !self.config.require_encryption && self.config.crypto.is_none() {
743 return Err(RejectCode::UNSECURE);
744 }
745 if h.extension & ext_flags::KMREQ == 0 || !crate::crypto::valid_km(km, h.encryption) {
746 return Err(RejectCode::ROGUE);
747 }
748 } else if h.encryption != 0
749 || h.extension & ext_flags::KMREQ != 0
750 || !self.plaintext_allowed()
751 {
752 return Err(RejectCode::UNSECURE);
753 }
754 let req = h.srt_request().ok_or(RejectCode::ROGUE)?;
755 if req.flags & srt_flags::STREAM != 0 {
756 return Err(RejectCode::MESSAGE_API);
757 }
758 if req.flags & srt_flags::TSBPDSND == 0 {
759 return Err(RejectCode::ROGUE);
760 }
761 for e in &h.extensions {
762 match e {
763 Extension::Group(_) => return Err(RejectCode::GROUP),
764 Extension::Filter(_) => return Err(RejectCode::FILTER),
765 Extension::Congestion(c) if c.as_slice() != b"live" => {
766 return Err(RejectCode::CONGESTION);
767 }
768 _ => {}
769 }
770 }
771 Ok(())
772 }
773
774 fn send_rejection(&mut self, peer: SocketAddr, h: &Handshake, code: RejectCode) {
775 self.stats.rejected += 1;
776 let reply = Handshake {
777 version: 5,
778 encryption: 0,
779 extension: 0,
780 initial_seq: h.initial_seq,
781 mtu: h.mtu,
782 flow_window: h.flow_window,
783 kind: HandshakeKind::Rejection(code.0),
784 socket_id: 0,
785 cookie: h.cookie,
786 peer_ip: encode_ip(peer),
787 extensions: Vec::new(),
788 };
789 let mut out = Vec::with_capacity(64);
790 ControlPacket::new(0, h.socket_id, Control::Handshake(reply)).encode(&mut out);
791 self.transmits.push_back((peer, out));
792 }
793}
794
795fn duration_micros(d: Duration) -> i64 {
796 i64::try_from(d.as_micros()).unwrap_or(i64::MAX)
797}
798
799fn encode_ip(peer: SocketAddr) -> [u8; 16] {
802 let mut out = [0u8; 16];
803 let octets: Vec<u8> = match peer {
804 SocketAddr::V4(a) => a.ip().octets().to_vec(),
805 SocketAddr::V6(a) => a.ip().octets().to_vec(),
806 };
807 for (dst, src) in out.chunks_mut(4).zip(octets.chunks(4)) {
808 for (d, s) in dst.iter_mut().zip(src.iter().rev()) {
809 *d = *s;
810 }
811 }
812 out
813}
814
815#[cfg(test)]
816mod tests {
817 use super::*;
818 use crate::packet::{DataPacket, Position};
819 use std::hash::BuildHasherDefault;
820 use std::hash::DefaultHasher;
821
822 type Fixed = BuildHasherDefault<DefaultHasher>;
823
824 fn listener(t0: Instant) -> Listener<Fixed> {
825 Listener::with_key(Config::default(), t0, Fixed::default())
826 }
827
828 fn peer() -> SocketAddr {
829 "192.0.2.1:5000".parse().expect("addr")
830 }
831
832 fn induction(socket: u32) -> Vec<u8> {
833 let h = Handshake {
834 version: 4,
835 encryption: 0,
836 extension: 2,
837 initial_seq: 1000,
838 mtu: 1500,
839 flow_window: 8192,
840 kind: HandshakeKind::Induction,
841 socket_id: socket,
842 cookie: 0,
843 peer_ip: [0; 16],
844 extensions: vec![],
845 };
846 let mut out = Vec::new();
847 ControlPacket::new(10, 0, Control::Handshake(h)).encode(&mut out);
848 out
849 }
850
851 fn conclusion(socket: u32, cookie: u32, extra: Vec<Extension>) -> Vec<u8> {
852 let mut extensions = vec![
853 Extension::HsReq(SrtHandshake {
854 version: 0x01_05_04,
855 flags: 0xBF,
856 receiver_delay: 2000,
857 sender_delay: 2000,
858 }),
859 Extension::StreamId(b"publish:live/event-x:u:p".to_vec()),
860 ];
861 extensions.extend(extra);
862 let h = Handshake {
863 version: 5,
864 encryption: 0,
865 extension: ext_flags::HSREQ | ext_flags::CONFIG,
866 initial_seq: 1000,
867 mtu: 1500,
868 flow_window: 8192,
869 kind: HandshakeKind::Conclusion,
870 socket_id: socket,
871 cookie,
872 peer_ip: [0; 16],
873 extensions,
874 };
875 let mut out = Vec::new();
876 ControlPacket::new(500, 0, Control::Handshake(h)).encode(&mut out);
877 out
878 }
879
880 fn sent_handshakes<S: BuildHasher>(l: &mut Listener<S>) -> Vec<(u32, Handshake)> {
881 std::iter::from_fn(|| l.poll_transmit())
882 .filter_map(|(_, b)| match Packet::parse(&b) {
883 Ok(Packet::Control(ControlPacket {
884 dest,
885 body: Control::Handshake(h),
886 ..
887 })) => Some((dest, h)),
888 _ => None,
889 })
890 .collect()
891 }
892
893 fn connect(l: &mut Listener<Fixed>, t: Instant, socket: u32) -> ConnId {
895 l.handle_datagram(t, peer(), &induction(socket));
896 let hs = sent_handshakes(l);
897 let [(dest, reply)] = hs.as_slice() else {
898 panic!("{hs:?}");
899 };
900 assert_eq!(*dest, socket);
901 assert_eq!(reply.version, 5);
902 assert_eq!(reply.extension, SRT_MAGIC);
903 assert_eq!(reply.kind, HandshakeKind::Induction);
904 assert_eq!(reply.peer_ip[..4], [1, 2, 0, 192]);
905 l.handle_datagram(t, peer(), &conclusion(socket, reply.cookie, vec![]));
906 match l.poll_event() {
907 Some(Event::Connect {
908 id,
909 peer: p,
910 stream_id,
911 }) => {
912 assert_eq!(p, peer());
913 assert_eq!(stream_id, b"publish:live/event-x:u:p");
914 id
915 }
916 other => panic!("{other:?}"),
917 }
918 }
919
920 #[test]
921 fn handshake_accept_and_data() {
922 let t0 = Instant::now();
923 let mut l = listener(t0);
924 assert_eq!(l.poll_timeout(), None, "no connections, no timer");
925 let id = connect(&mut l, t0, 0x1234);
926 assert!(sent_handshakes(&mut l).is_empty(), "nothing until accepted");
927 assert!(l.accept(id, t0));
928 let hs = sent_handshakes(&mut l);
929 let [(dest, r)] = hs.as_slice() else {
930 panic!("{hs:?}");
931 };
932 assert_eq!(*dest, 0x1234);
933 assert_eq!(r.kind, HandshakeKind::Conclusion);
934 assert_eq!(r.socket_id, id.0);
935 assert_eq!(r.extension, ext_flags::HSREQ);
936 let Some(Extension::HsRsp(rsp)) = r.extensions.first() else {
937 panic!("{r:?}");
938 };
939 assert_eq!(rsp.flags, OUR_FLAGS);
940 assert_eq!(rsp.receiver_delay, 2000, "the larger latency wins");
941 assert_eq!(l.latency(id), Some(Duration::from_secs(2)));
942 assert!(l.poll_timeout().is_some());
943
944 let mut b = Vec::new();
946 DataPacket {
947 seq: Seq::new(1000),
948 position: Position::Only,
949 in_order: false,
950 key: 0,
951 retransmitted: false,
952 message: 1,
953 timestamp: 600,
954 dest: id.0,
955 payload: b"ts",
956 }
957 .encode(&mut b);
958 l.handle_datagram(t0, peer(), &b);
959 l.handle_datagram(t0, "192.0.2.9:5000".parse().expect("addr"), &b);
961 assert_eq!(l.stats().stray, 1);
962 let mut t = t0;
963 let mut got = Vec::new();
964 while let Some(next) = l.poll_timeout() {
965 if next > t0 + Duration::from_millis(2200) {
966 break;
967 }
968 l.handle_timeout(next);
969 while let Some(ev) = l.poll_event() {
970 got.push(ev);
971 t = next;
972 }
973 }
974 assert_eq!(
975 got,
976 vec![Event::Data {
977 id,
978 payload: b"ts".to_vec()
979 }]
980 );
981 assert_eq!(t - t0, Duration::from_micros(2_000_100));
984 }
985
986 #[test]
987 fn a_repeated_conclusion_gets_the_same_response_not_a_second_connection() {
988 let t0 = Instant::now();
989 let mut l = listener(t0);
990 let id = connect(&mut l, t0, 7);
991 let cookie = l.cookie(peer(), 0);
993 l.handle_datagram(t0, peer(), &conclusion(7, cookie, vec![]));
994 assert_eq!(l.poll_event(), None);
995 l.accept(id, t0);
996 let first = sent_handshakes(&mut l);
997 l.handle_datagram(t0, peer(), &conclusion(7, cookie, vec![]));
998 assert_eq!(sent_handshakes(&mut l), first);
999 assert_eq!(l.connections(), 1);
1000 assert_eq!(l.poll_event(), None);
1001 }
1002
1003 #[test]
1004 fn a_wrong_cookie_gets_no_answer() {
1005 let t0 = Instant::now();
1006 let mut l = listener(t0);
1007 l.handle_datagram(t0, peer(), &conclusion(7, 12345, vec![]));
1008 assert!(sent_handshakes(&mut l).is_empty());
1009 assert_eq!(l.poll_event(), None);
1010 assert_eq!(l.stats().bad_cookie, 1);
1011 let other: SocketAddr = "192.0.2.2:5000".parse().expect("addr");
1013 let c = l.cookie(other, 0);
1014 l.handle_datagram(t0, peer(), &conclusion(7, c, vec![]));
1015 assert_eq!(l.stats().bad_cookie, 2);
1016 }
1017
1018 #[test]
1019 fn cookies_last_one_to_two_minutes_and_depend_on_the_key() {
1020 let t0 = Instant::now();
1021 let mut l = listener(t0);
1022 let c = l.cookie(peer(), 0);
1023 let t = t0 + Duration::from_secs(90);
1024 l.handle_datagram(t, peer(), &conclusion(7, c, vec![]));
1025 assert!(matches!(l.poll_event(), Some(Event::Connect { .. })));
1026 let t = t0 + Duration::from_secs(121);
1027 l.handle_datagram(t, peer(), &conclusion(8, c, vec![]));
1028 assert_eq!(l.poll_event(), None);
1029 let other = Listener::new(Config::default(), t0);
1030 assert_ne!(other.cookie(peer(), 0), c, "a random key per process");
1031 }
1032
1033 #[test]
1034 fn rejection_carries_the_code() {
1035 let t0 = Instant::now();
1036 let mut l = listener(t0);
1037 let id = connect(&mut l, t0, 9);
1038 assert!(l.reject(id, RejectCode::http(401)));
1039 let hs = sent_handshakes(&mut l);
1040 assert!(
1041 matches!(hs.as_slice(), [(9, h)] if h.kind == HandshakeKind::Rejection(2401)),
1042 "{hs:?}"
1043 );
1044 assert_eq!(l.connections(), 0);
1045 assert_eq!(l.poll_timeout(), None);
1046 }
1047
1048 #[test]
1049 fn what_we_cannot_do_is_refused_in_the_handshake() {
1050 let t0 = Instant::now();
1051 let cases = [
1052 (Extension::KmReq(vec![0; 16]), RejectCode::UNSECURE),
1053 (Extension::Group(vec![0; 8]), RejectCode::GROUP),
1054 (Extension::Filter(b"fec".to_vec()), RejectCode::FILTER),
1055 (
1056 Extension::Congestion(b"file".to_vec()),
1057 RejectCode::CONGESTION,
1058 ),
1059 ];
1060 for (i, (ext, code)) in cases.into_iter().enumerate() {
1061 let mut l = listener(t0);
1062 let c = l.cookie(peer(), 0);
1063 l.handle_datagram(t0, peer(), &conclusion(i as u32 + 1, c, vec![ext]));
1064 assert_eq!(l.poll_event(), None);
1065 let hs = sent_handshakes(&mut l);
1066 assert!(
1067 matches!(hs.as_slice(), [(_, h)] if h.kind == HandshakeKind::Rejection(code.0)),
1068 "{code:?}: {hs:?}"
1069 );
1070 }
1071 let mut l = listener(t0);
1073 let c = l.cookie(peer(), 0);
1074 l.handle_datagram(
1075 t0,
1076 peer(),
1077 &conclusion(1, c, vec![Extension::Congestion(b"live".to_vec())]),
1078 );
1079 assert!(matches!(l.poll_event(), Some(Event::Connect { .. })));
1080 }
1081
1082 #[test]
1083 fn connection_limit_and_handshake_rate() {
1084 let t0 = Instant::now();
1085 let mut l = Listener::with_key(
1086 Config {
1087 max_connections: 2,
1088 handshakes_per_second: 5,
1089 ..Config::default()
1090 },
1091 t0,
1092 Fixed::default(),
1093 );
1094 let c = l.cookie(peer(), 0);
1095 for s in 1..=3 {
1096 l.handle_datagram(t0, peer(), &conclusion(s, c, vec![]));
1097 }
1098 let hs = sent_handshakes(&mut l);
1099 assert!(
1100 matches!(hs.as_slice(), [(3, h)] if h.kind == HandshakeKind::Rejection(1005)),
1101 "{hs:?}"
1102 );
1103 for s in 0..20 {
1105 l.handle_datagram(t0, peer(), &induction(100 + s));
1106 }
1107 assert_eq!(sent_handshakes(&mut l).len(), 7);
1108 assert_eq!(l.stats().rate_limited, 13);
1109 l.handle_datagram(t0 + Duration::from_secs(1), peer(), &induction(200));
1110 assert_eq!(sent_handshakes(&mut l).len(), 1);
1111 }
1112
1113 #[test]
1114 fn an_unanswered_caller_is_forgotten() {
1115 let t0 = Instant::now();
1116 let mut l = listener(t0);
1117 let id = connect(&mut l, t0, 1);
1118 let t = l.poll_timeout().expect("pending timer");
1119 assert_eq!(t - t0, Duration::from_secs(5));
1120 l.handle_timeout(t);
1121 assert!(matches!(
1122 l.poll_event(),
1123 Some(Event::Closed { id: i, reason: None, .. }) if i == id
1124 ));
1125 assert_eq!(l.connections(), 0);
1126 }
1127
1128 #[test]
1129 fn shutdown_and_idle_timeout_close() {
1130 let t0 = Instant::now();
1131 let mut l = listener(t0);
1132 let id = connect(&mut l, t0, 1);
1133 l.accept(id, t0);
1134 let mut b = Vec::new();
1135 ControlPacket::new(0, id.0, Control::Shutdown).encode(&mut b);
1136 l.handle_datagram(t0, peer(), &b);
1137 assert!(matches!(
1138 l.poll_event(),
1139 Some(Event::Closed {
1140 reason: Some(CloseReason::Shutdown),
1141 ..
1142 })
1143 ));
1144 assert_eq!(l.poll_timeout(), None);
1145
1146 while l.poll_transmit().is_some() {}
1147 let id = connect(&mut l, t0, 2);
1148 l.accept(id, t0);
1149 let mut t = t0;
1150 while l.connections() > 0 {
1151 t = l.poll_timeout().expect("timer while connected");
1152 l.handle_timeout(t);
1153 }
1154 assert_eq!(t - t0, Duration::from_secs(5));
1155 let events: Vec<_> = std::iter::from_fn(|| l.poll_event()).collect();
1156 assert!(matches!(
1157 events.last(),
1158 Some(Event::Closed {
1159 reason: Some(CloseReason::Timeout),
1160 ..
1161 })
1162 ));
1163 let keepalives = std::iter::from_fn(|| l.poll_transmit())
1165 .filter(|(_, b)| b.get(..4) == Some(&[0x80, 0x01, 0, 0]))
1166 .count();
1167 assert_eq!(keepalives, 4);
1168 }
1169
1170 #[test]
1171 fn close_sends_shutdown() {
1172 let t0 = Instant::now();
1173 let mut l = listener(t0);
1174 let id = connect(&mut l, t0, 1);
1175 l.accept(id, t0);
1176 sent_handshakes(&mut l);
1177 l.close(id, t0);
1178 let out: Vec<_> = std::iter::from_fn(|| l.poll_transmit()).collect();
1179 assert_eq!(out.len(), 1);
1180 assert_eq!(
1181 out.first().and_then(|(_, b)| b.get(..4)),
1182 Some(&[0x80, 0x05, 0, 0][..])
1183 );
1184 assert_eq!(l.connections(), 0);
1185 }
1186
1187 #[test]
1188 fn ipv6_peer_address_field() {
1189 let a: SocketAddr = "[2001:db8::1]:5000".parse().expect("addr");
1190 let f = encode_ip(a);
1191 assert_eq!(f[..4], [0xB8, 0x0D, 0x01, 0x20]);
1192 assert_eq!(f[12..], [1, 0, 0, 0]);
1193 }
1194}