Skip to main content

sapflow_srt/
listener.rs

1//! The listener: every datagram to the SRT port comes here. It answers
2//! handshakes (section 4.3.1), asks the application about each stream id,
3//! and passes later packets to their connection's [`Receiver`].
4//!
5//! Sans-IO: give it datagrams with their source address and the time, and
6//! collect the datagrams to send, the events, and when to call
7//! [`Listener::handle_timeout`] next. With no connection there is no timer.
8
9use 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
22/// The version this implementation reports in its handshake response:
23/// the protocol level of draft-sharabayko-srt-01 that libsrt calls 1.5.0.
24pub const SRT_VERSION: u32 = 0x01_05_00;
25
26/// What we tell a caller we do: TSBPD, too-late packet drop, periodic NAK
27/// reports, and the two legacy flags every peer must set. Not the stream
28/// (file) mode and not packet filters.
29pub 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
36/// A SYN cookie is valid for the minute it was made in and the next.
37const COOKIE_PERIOD: i64 = 60_000_000;
38/// The largest packet we take.
39const MTU_MAX: u32 = 1500;
40/// IP and UDP headers, and the SRT header.
41const OVERHEAD: u32 = 28 + 16;
42
43/// Limits and policy for a [`Listener`].
44#[derive(Debug, Clone)]
45pub struct Config {
46    /// Our receive latency; a caller asking for more gets more.
47    pub latency: Duration,
48    /// Connections, open or waiting for the application, at most.
49    pub max_connections: usize,
50    /// Handshake packets answered per second, at most (bursts of twice).
51    pub handshakes_per_second: u32,
52    /// Receive buffer per connection, in packets.
53    pub buffer_packets: usize,
54    /// A connection that sends nothing for this long is closed.
55    pub peer_idle: Duration,
56    /// The application has this long to accept or reject a caller.
57    pub accept_timeout: Duration,
58    /// Lab/global secret. Production admission can use accept_with_crypto.
59    pub crypto: Option<CryptoConfig>,
60    /// Require KM before emitting Connect; select the session secret in
61    /// accept_with_crypto when no global secret is configured.
62    pub require_encryption: bool,
63    /// With a secret in `crypto`, also admit callers that send no key
64    /// material, as libsrt does with enforced encryption off. A caller that
65    /// does encrypt must still match the secret. Ignored when
66    /// `require_encryption` is set.
67    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/// A connection, named by the socket id we gave it.
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
88pub struct ConnId(pub u32);
89
90/// Why a handshake is refused: the code in the Handshake Type field.
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub struct RejectCode(pub u32);
93
94impl RejectCode {
95    /// 1000: no reason given (the fallback).
96    pub const UNKNOWN: Self = Self(1000);
97    /// 1001: a system function failed.
98    pub const SYSTEM: Self = Self(1001);
99    /// 1002: refused by the peer, with no further detail.
100    pub const PEER: Self = Self(1002);
101    /// 1003: a resource, usually memory, could not be allocated.
102    pub const RESOURCE: Self = Self(1003);
103    /// 1004: the handshake data could not be interpreted; sent for malformed
104    /// or inconsistent handshakes.
105    pub const ROGUE: Self = Self(1004);
106    /// 1005: the listener is full; sent when [`Config::max_connections`] is
107    /// reached.
108    pub const BACKLOG: Self = Self(1005);
109    /// 1007: the listener was closing when the request arrived.
110    pub const CLOSE: Self = Self(1007);
111    /// 1008: the peer's version is not supported; sent for any handshake
112    /// version other than 5.
113    pub const VERSION: Self = Self(1008);
114    /// 1010: the passphrases differ; sent when the caller's key material
115    /// cannot be accepted with ours.
116    pub const BADSECRET: Self = Self(1010);
117    /// 1011: only one side has a passphrase; sent when encryption is
118    /// configured or required and the caller sends none, or the reverse.
119    pub const UNSECURE: Self = Self(1011);
120    /// 1012: stream and message mode differ; sent when the caller asks for
121    /// stream mode.
122    pub const MESSAGE_API: Self = Self(1012);
123    /// 1013: the congestion controllers differ; sent for anything but `live`.
124    pub const CONGESTION: Self = Self(1013);
125    /// 1014: packet filter settings differ; sent when the caller asks for a
126    /// filter.
127    pub const FILTER: Self = Self(1014);
128    /// 1015: group settings are incompatible; sent when the caller asks for a
129    /// group.
130    pub const GROUP: Self = Self(1015);
131
132    /// An application refusal carrying an HTTP status (2000 + status),
133    /// which libsrt reports as `PREDEFINED:<status>`.
134    pub const fn http(status: u16) -> Self {
135        Self(2000 + status as u32)
136    }
137}
138
139/// Something the application needs to know about or answer; see
140/// [`Listener::poll_event`].
141#[derive(Debug, Clone, PartialEq, Eq)]
142pub enum Event {
143    /// A caller passed bounded handshake parsing and cookie checks. The
144    /// stream ID is untrusted; KM/secret validation happens during acceptance.
145    /// Answer with [`Listener::accept`], [`Listener::accept_with_crypto`] or
146    /// [`Listener::reject`]. This event does not establish peer identity.
147    Connect {
148        /// The connection, for [`Listener::accept`] and [`Listener::reject`].
149        id: ConnId,
150        /// The caller's address.
151        peer: SocketAddr,
152        /// The caller's stream ID, untrusted; empty when it sent none.
153        stream_id: Vec<u8>,
154    },
155    /// The next payload, in order, at its delivery time.
156    Data {
157        /// The connection the payload came from.
158        id: ConnId,
159        /// One packet's payload, decrypted when encryption is in use.
160        payload: Vec<u8>,
161    },
162    /// The connection ended from the other side, or a caller was not
163    /// answered in time (`reason` is `None` then).
164    Closed {
165        /// The connection that ended.
166        id: ConnId,
167        /// Why it ended; `None` when a caller was not answered in time.
168        reason: Option<CloseReason>,
169        /// The connection's final counters; all zero if it was never
170        /// accepted.
171        stats: Stats,
172    },
173}
174
175/// Datagrams the listener threw away, by kind.
176#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
177pub struct ListenerStats {
178    /// Datagrams over 1500 bytes or that did not parse as a packet.
179    pub malformed: u64,
180    /// For no connection, or from the wrong address.
181    pub stray: u64,
182    /// Conclusion handshakes whose SYN cookie was wrong or stale.
183    pub bad_cookie: u64,
184    /// Handshakes ignored because the handshake allowance was used up.
185    pub rate_limited: u64,
186    /// Callers refused with a rejection handshake, by the listener or by the
187    /// application.
188    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        /// Our conclusion response, sent again if the caller repeats its
203        /// conclusion.
204        response: Vec<u8>,
205    },
206}
207
208struct Conn {
209    peer: SocketAddr,
210    caller_socket: u32,
211    state: State,
212    next_timer: i64,
213}
214
215/// A sans-IO SRT listener: every connection on one UDP port, with its
216/// handshakes, timers and events. `S` keys the SYN cookies and socket ids;
217/// [`Listener::new`] makes a random one.
218pub struct Listener<S = RandomState> {
219    config: Config,
220    epoch: Instant,
221    /// Keyed per process: the SYN cookies and our socket ids come from it.
222    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    /// Handshake allowance, in millionths of a handshake.
229    tokens: u64,
230    tokens_at: i64,
231    stats: ListenerStats,
232}
233
234impl Listener<RandomState> {
235    /// A listener whose cookies and socket ids are keyed by a random key
236    /// made for this process.
237    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    /// A listener keyed by `key`: give it a random one (tests and fuzzing
244    /// use a fixed one, for repeatable runs).
245    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    /// Counts of datagrams discarded so far, by kind.
267    pub fn stats(&self) -> ListenerStats {
268        self.stats
269    }
270
271    /// Connections open or waiting for an answer.
272    pub fn connections(&self) -> usize {
273        self.conns.len()
274    }
275
276    /// Counters for an open connection; `None` for an unknown id or one still
277    /// waiting for an answer.
278    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    /// The negotiated latency of an open connection.
286    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    /// The next datagram to send and the address to send it to, if any.
294    pub fn poll_transmit(&mut self) -> Option<(SocketAddr, Vec<u8>)> {
295        self.transmits.pop_front()
296    }
297
298    /// The next [`Event`], if any.
299    pub fn poll_event(&mut self) -> Option<Event> {
300        self.events.pop_front()
301    }
302
303    /// When to call [`handle_timeout`](Self::handle_timeout); `None` when
304    /// there are no connections.
305    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    /// Takes a datagram that arrived from `peer` at `now`; bad ones are
314    /// counted in [`stats`](Self::stats) and dropped.
315    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    /// Does what is due at `now`: closes callers the application has not
361    /// answered in time and runs each open connection's timers.
362    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    /// Whether a caller without key material may connect.
395    fn plaintext_allowed(&self) -> bool {
396        !self.config.require_encryption
397            && (self.config.crypto.is_none() || self.config.allow_plaintext)
398    }
399
400    /// Accepts a caller announced by [`Event::Connect`]: the handshake
401    /// response goes out and data is delivered from now on.
402    pub fn accept(&mut self, id: ConnId, now: Instant) -> bool {
403        self.accept_with_crypto(id, now, self.config.crypto.clone())
404    }
405
406    /// Select an authenticated admission/session secret after inspecting the
407    /// bounded stream ID. A configured secret requires matching KM unless
408    /// `allow_plaintext` admits a caller that sent none; a missing secret
409    /// never downgrades an encrypted or encryption-required session.
410    /// Failed key validation rejects and removes the pending connection.
411    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    /// Refuses a caller announced by [`Event::Connect`].
517    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    /// Ends an open connection from our side (a SHUTDOWN goes to the
531    /// caller), or forgets one waiting for an answer.
532    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    /// Moves a connection's output into the queues and reschedules it.
552    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            // 30 bits, never 0 (0 addresses the listener).
608            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                // A repeat (our response was lost): the same answer again.
626                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                    // Not from the address it claims, or stale: no answer.
645                    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        // Observed from libsrt's listener: version 5, the magic number, the
656        // caller's own socket id, sequence number, MTU and window echoed.
657        // The key length is advertised only when encryption is required: a
658        // plaintext caller may read it as a demand and give up.
659        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    /// What this receiver cannot do, refused before the application sees
720    /// the caller.
721    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
799/// The Peer IP Address field: four 32-bit little-endian words (observed:
800/// libsrt writes 127.0.0.1 as `01 00 00 7f`, then zeros).
801fn 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    /// Induction then conclusion; returns the connection.
894    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        // Data for the connection, then delivery after the latency.
945        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        // From another address it is ignored.
960        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        // Due 2000 ms after its timestamp, which is 100 µs after the
982        // conclusion's.
983        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        // Repeated while the application decides: ignored.
992        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        // A cookie made for another address does not work either.
1012        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        // Live congestion control is what we do.
1072        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        // A burst of 10 allowed, then nothing until the allowance refills.
1104        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        // Keepalives went out meanwhile.
1164        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}