Skip to main content

Listener

Struct Listener 

Source
pub struct Listener<S = RandomState> { /* private fields */ }
Expand description

A sans-IO SRT listener: every connection on one UDP port, with its handshakes, timers and events. S keys the SYN cookies and socket ids; Listener::new makes a random one.

Implementations§

Source§

impl Listener<RandomState>

Source

pub fn new(config: Config, now: Instant) -> Self

A listener whose cookies and socket ids are keyed by a random key made for this process.

Examples found in repository?
examples/listen.rs (line 16)
14fn main() -> std::io::Result<()> {
15    let socket = UdpSocket::bind("0.0.0.0:9000")?;
16    let mut listener = Listener::new(Config::default(), Instant::now());
17    // An SRT datagram is at most 1,500 bytes on an ordinary network.
18    let mut buf = [0u8; 2048];
19
20    loop {
21        // Wait for a datagram or until the listener next needs the time.
22        let now = Instant::now();
23        let wait = listener
24            .poll_timeout()
25            .map_or(Duration::from_millis(100), |at| {
26                at.saturating_duration_since(now)
27            })
28            .max(Duration::from_millis(1));
29        socket.set_read_timeout(Some(wait))?;
30        match socket.recv_from(&mut buf) {
31            Ok((n, peer)) => {
32                if let Some(datagram) = buf.get(..n) {
33                    listener.handle_datagram(Instant::now(), peer, datagram);
34                }
35            }
36            Err(e) if matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) => {}
37            Err(e) => return Err(e),
38        }
39        listener.handle_timeout(Instant::now());
40
41        while let Some(event) = listener.poll_event() {
42            match event {
43                Event::Connect {
44                    id,
45                    peer,
46                    stream_id,
47                } => {
48                    // The stream id is untrusted input: check it here, and
49                    // call `listener.reject(id, code)` to refuse a caller.
50                    println!("{peer} wants {:?}", String::from_utf8_lossy(&stream_id));
51                    listener.accept(id, Instant::now());
52                }
53                Event::Data { id, payload } => println!("{id:?}: {} bytes", payload.len()),
54                Event::Closed { id, reason, .. } => println!("{id:?} closed: {reason:?}"),
55            }
56        }
57        while let Some((to, datagram)) = listener.poll_transmit() {
58            socket.send_to(&datagram, to)?;
59        }
60    }
61}
More examples
Hide additional examples
examples/receive.rs (line 37)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source§

impl<S: BuildHasher> Listener<S>

Source

pub fn with_key(config: Config, now: Instant, key: S) -> Self

A listener keyed by key: give it a random one (tests and fuzzing use a fixed one, for repeatable runs).

Source

pub fn stats(&self) -> ListenerStats

Counts of datagrams discarded so far, by kind.

Examples found in repository?
examples/receive.rs (line 89)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source

pub fn connections(&self) -> usize

Connections open or waiting for an answer.

Source

pub fn connection_stats(&self, id: ConnId) -> Option<Stats>

Counters for an open connection; None for an unknown id or one still waiting for an answer.

Examples found in repository?
examples/receive.rs (line 62)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source

pub fn latency(&self, id: ConnId) -> Option<Duration>

The negotiated latency of an open connection.

Source

pub fn poll_transmit(&mut self) -> Option<(SocketAddr, Vec<u8>)>

The next datagram to send and the address to send it to, if any.

Examples found in repository?
examples/listen.rs (line 57)
14fn main() -> std::io::Result<()> {
15    let socket = UdpSocket::bind("0.0.0.0:9000")?;
16    let mut listener = Listener::new(Config::default(), Instant::now());
17    // An SRT datagram is at most 1,500 bytes on an ordinary network.
18    let mut buf = [0u8; 2048];
19
20    loop {
21        // Wait for a datagram or until the listener next needs the time.
22        let now = Instant::now();
23        let wait = listener
24            .poll_timeout()
25            .map_or(Duration::from_millis(100), |at| {
26                at.saturating_duration_since(now)
27            })
28            .max(Duration::from_millis(1));
29        socket.set_read_timeout(Some(wait))?;
30        match socket.recv_from(&mut buf) {
31            Ok((n, peer)) => {
32                if let Some(datagram) = buf.get(..n) {
33                    listener.handle_datagram(Instant::now(), peer, datagram);
34                }
35            }
36            Err(e) if matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) => {}
37            Err(e) => return Err(e),
38        }
39        listener.handle_timeout(Instant::now());
40
41        while let Some(event) = listener.poll_event() {
42            match event {
43                Event::Connect {
44                    id,
45                    peer,
46                    stream_id,
47                } => {
48                    // The stream id is untrusted input: check it here, and
49                    // call `listener.reject(id, code)` to refuse a caller.
50                    println!("{peer} wants {:?}", String::from_utf8_lossy(&stream_id));
51                    listener.accept(id, Instant::now());
52                }
53                Event::Data { id, payload } => println!("{id:?}: {} bytes", payload.len()),
54                Event::Closed { id, reason, .. } => println!("{id:?} closed: {reason:?}"),
55            }
56        }
57        while let Some((to, datagram)) = listener.poll_transmit() {
58            socket.send_to(&datagram, to)?;
59        }
60    }
61}
More examples
Hide additional examples
examples/receive.rs (line 67)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source

pub fn poll_event(&mut self) -> Option<Event>

The next Event, if any.

Examples found in repository?
examples/listen.rs (line 41)
14fn main() -> std::io::Result<()> {
15    let socket = UdpSocket::bind("0.0.0.0:9000")?;
16    let mut listener = Listener::new(Config::default(), Instant::now());
17    // An SRT datagram is at most 1,500 bytes on an ordinary network.
18    let mut buf = [0u8; 2048];
19
20    loop {
21        // Wait for a datagram or until the listener next needs the time.
22        let now = Instant::now();
23        let wait = listener
24            .poll_timeout()
25            .map_or(Duration::from_millis(100), |at| {
26                at.saturating_duration_since(now)
27            })
28            .max(Duration::from_millis(1));
29        socket.set_read_timeout(Some(wait))?;
30        match socket.recv_from(&mut buf) {
31            Ok((n, peer)) => {
32                if let Some(datagram) = buf.get(..n) {
33                    listener.handle_datagram(Instant::now(), peer, datagram);
34                }
35            }
36            Err(e) if matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) => {}
37            Err(e) => return Err(e),
38        }
39        listener.handle_timeout(Instant::now());
40
41        while let Some(event) = listener.poll_event() {
42            match event {
43                Event::Connect {
44                    id,
45                    peer,
46                    stream_id,
47                } => {
48                    // The stream id is untrusted input: check it here, and
49                    // call `listener.reject(id, code)` to refuse a caller.
50                    println!("{peer} wants {:?}", String::from_utf8_lossy(&stream_id));
51                    listener.accept(id, Instant::now());
52                }
53                Event::Data { id, payload } => println!("{id:?}: {} bytes", payload.len()),
54                Event::Closed { id, reason, .. } => println!("{id:?} closed: {reason:?}"),
55            }
56        }
57        while let Some((to, datagram)) = listener.poll_transmit() {
58            socket.send_to(&datagram, to)?;
59        }
60    }
61}
More examples
Hide additional examples
examples/receive.rs (line 46)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source

pub fn poll_timeout(&self) -> Option<Instant>

When to call handle_timeout; None when there are no connections.

Examples found in repository?
examples/listen.rs (line 24)
14fn main() -> std::io::Result<()> {
15    let socket = UdpSocket::bind("0.0.0.0:9000")?;
16    let mut listener = Listener::new(Config::default(), Instant::now());
17    // An SRT datagram is at most 1,500 bytes on an ordinary network.
18    let mut buf = [0u8; 2048];
19
20    loop {
21        // Wait for a datagram or until the listener next needs the time.
22        let now = Instant::now();
23        let wait = listener
24            .poll_timeout()
25            .map_or(Duration::from_millis(100), |at| {
26                at.saturating_duration_since(now)
27            })
28            .max(Duration::from_millis(1));
29        socket.set_read_timeout(Some(wait))?;
30        match socket.recv_from(&mut buf) {
31            Ok((n, peer)) => {
32                if let Some(datagram) = buf.get(..n) {
33                    listener.handle_datagram(Instant::now(), peer, datagram);
34                }
35            }
36            Err(e) if matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) => {}
37            Err(e) => return Err(e),
38        }
39        listener.handle_timeout(Instant::now());
40
41        while let Some(event) = listener.poll_event() {
42            match event {
43                Event::Connect {
44                    id,
45                    peer,
46                    stream_id,
47                } => {
48                    // The stream id is untrusted input: check it here, and
49                    // call `listener.reject(id, code)` to refuse a caller.
50                    println!("{peer} wants {:?}", String::from_utf8_lossy(&stream_id));
51                    listener.accept(id, Instant::now());
52                }
53                Event::Data { id, payload } => println!("{id:?}: {} bytes", payload.len()),
54                Event::Closed { id, reason, .. } => println!("{id:?} closed: {reason:?}"),
55            }
56        }
57        while let Some((to, datagram)) = listener.poll_transmit() {
58            socket.send_to(&datagram, to)?;
59        }
60    }
61}
Source

pub fn handle_datagram( &mut self, now: Instant, peer: SocketAddr, datagram: &[u8], )

Takes a datagram that arrived from peer at now; bad ones are counted in stats and dropped.

Examples found in repository?
examples/listen.rs (line 33)
14fn main() -> std::io::Result<()> {
15    let socket = UdpSocket::bind("0.0.0.0:9000")?;
16    let mut listener = Listener::new(Config::default(), Instant::now());
17    // An SRT datagram is at most 1,500 bytes on an ordinary network.
18    let mut buf = [0u8; 2048];
19
20    loop {
21        // Wait for a datagram or until the listener next needs the time.
22        let now = Instant::now();
23        let wait = listener
24            .poll_timeout()
25            .map_or(Duration::from_millis(100), |at| {
26                at.saturating_duration_since(now)
27            })
28            .max(Duration::from_millis(1));
29        socket.set_read_timeout(Some(wait))?;
30        match socket.recv_from(&mut buf) {
31            Ok((n, peer)) => {
32                if let Some(datagram) = buf.get(..n) {
33                    listener.handle_datagram(Instant::now(), peer, datagram);
34                }
35            }
36            Err(e) if matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) => {}
37            Err(e) => return Err(e),
38        }
39        listener.handle_timeout(Instant::now());
40
41        while let Some(event) = listener.poll_event() {
42            match event {
43                Event::Connect {
44                    id,
45                    peer,
46                    stream_id,
47                } => {
48                    // The stream id is untrusted input: check it here, and
49                    // call `listener.reject(id, code)` to refuse a caller.
50                    println!("{peer} wants {:?}", String::from_utf8_lossy(&stream_id));
51                    listener.accept(id, Instant::now());
52                }
53                Event::Data { id, payload } => println!("{id:?}: {} bytes", payload.len()),
54                Event::Closed { id, reason, .. } => println!("{id:?} closed: {reason:?}"),
55            }
56        }
57        while let Some((to, datagram)) = listener.poll_transmit() {
58            socket.send_to(&datagram, to)?;
59        }
60    }
61}
More examples
Hide additional examples
examples/receive.rs (line 77)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source

pub fn handle_timeout(&mut self, now: Instant)

Does what is due at now: closes callers the application has not answered in time and runs each open connection’s timers.

Examples found in repository?
examples/listen.rs (line 39)
14fn main() -> std::io::Result<()> {
15    let socket = UdpSocket::bind("0.0.0.0:9000")?;
16    let mut listener = Listener::new(Config::default(), Instant::now());
17    // An SRT datagram is at most 1,500 bytes on an ordinary network.
18    let mut buf = [0u8; 2048];
19
20    loop {
21        // Wait for a datagram or until the listener next needs the time.
22        let now = Instant::now();
23        let wait = listener
24            .poll_timeout()
25            .map_or(Duration::from_millis(100), |at| {
26                at.saturating_duration_since(now)
27            })
28            .max(Duration::from_millis(1));
29        socket.set_read_timeout(Some(wait))?;
30        match socket.recv_from(&mut buf) {
31            Ok((n, peer)) => {
32                if let Some(datagram) = buf.get(..n) {
33                    listener.handle_datagram(Instant::now(), peer, datagram);
34                }
35            }
36            Err(e) if matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) => {}
37            Err(e) => return Err(e),
38        }
39        listener.handle_timeout(Instant::now());
40
41        while let Some(event) = listener.poll_event() {
42            match event {
43                Event::Connect {
44                    id,
45                    peer,
46                    stream_id,
47                } => {
48                    // The stream id is untrusted input: check it here, and
49                    // call `listener.reject(id, code)` to refuse a caller.
50                    println!("{peer} wants {:?}", String::from_utf8_lossy(&stream_id));
51                    listener.accept(id, Instant::now());
52                }
53                Event::Data { id, payload } => println!("{id:?}: {} bytes", payload.len()),
54                Event::Closed { id, reason, .. } => println!("{id:?} closed: {reason:?}"),
55            }
56        }
57        while let Some((to, datagram)) = listener.poll_transmit() {
58            socket.send_to(&datagram, to)?;
59        }
60    }
61}
More examples
Hide additional examples
examples/receive.rs (line 45)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source

pub fn accept(&mut self, id: ConnId, now: Instant) -> bool

Accepts a caller announced by Event::Connect: the handshake response goes out and data is delivered from now on.

Examples found in repository?
examples/listen.rs (line 51)
14fn main() -> std::io::Result<()> {
15    let socket = UdpSocket::bind("0.0.0.0:9000")?;
16    let mut listener = Listener::new(Config::default(), Instant::now());
17    // An SRT datagram is at most 1,500 bytes on an ordinary network.
18    let mut buf = [0u8; 2048];
19
20    loop {
21        // Wait for a datagram or until the listener next needs the time.
22        let now = Instant::now();
23        let wait = listener
24            .poll_timeout()
25            .map_or(Duration::from_millis(100), |at| {
26                at.saturating_duration_since(now)
27            })
28            .max(Duration::from_millis(1));
29        socket.set_read_timeout(Some(wait))?;
30        match socket.recv_from(&mut buf) {
31            Ok((n, peer)) => {
32                if let Some(datagram) = buf.get(..n) {
33                    listener.handle_datagram(Instant::now(), peer, datagram);
34                }
35            }
36            Err(e) if matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) => {}
37            Err(e) => return Err(e),
38        }
39        listener.handle_timeout(Instant::now());
40
41        while let Some(event) = listener.poll_event() {
42            match event {
43                Event::Connect {
44                    id,
45                    peer,
46                    stream_id,
47                } => {
48                    // The stream id is untrusted input: check it here, and
49                    // call `listener.reject(id, code)` to refuse a caller.
50                    println!("{peer} wants {:?}", String::from_utf8_lossy(&stream_id));
51                    listener.accept(id, Instant::now());
52                }
53                Event::Data { id, payload } => println!("{id:?}: {} bytes", payload.len()),
54                Event::Closed { id, reason, .. } => println!("{id:?} closed: {reason:?}"),
55            }
56        }
57        while let Some((to, datagram)) = listener.poll_transmit() {
58            socket.send_to(&datagram, to)?;
59        }
60    }
61}
More examples
Hide additional examples
examples/receive.rs (line 50)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}
Source

pub fn accept_with_crypto( &mut self, id: ConnId, now: Instant, crypto: Option<CryptoConfig>, ) -> bool

Select an authenticated admission/session secret after inspecting the bounded stream ID. A configured secret requires matching KM unless allow_plaintext admits a caller that sent none; a missing secret never downgrades an encrypted or encryption-required session. Failed key validation rejects and removes the pending connection.

Source

pub fn reject(&mut self, id: ConnId, code: RejectCode) -> bool

Refuses a caller announced by Event::Connect.

Source

pub fn close(&mut self, id: ConnId, now: Instant)

Ends an open connection from our side (a SHUTDOWN goes to the caller), or forgets one waiting for an answer.

Examples found in repository?
examples/receive.rs (line 65)
13fn main() -> Result<(), Box<dyn Error>> {
14    let args: Vec<_> = std::env::args().skip(1).collect();
15    let (Some(bind), Some(path), Some(expected)) = (args.first(), args.get(1), args.get(2)) else {
16        return Err("receive <bind> <output> <expected bytes> [latency ms]".into());
17    };
18    let bind: SocketAddr = bind.parse()?;
19    let expected: usize = expected.parse()?;
20    let mut config = Config::default();
21    if let Some(ms) = args.get(3) {
22        config.latency = Duration::from_millis(ms.parse()?);
23    }
24    if let Ok(secret) = std::env::var("SAPFLOW_SRT_PASSPHRASE") {
25        let size = match std::env::var("SAPFLOW_SRT_KEY_BITS").as_deref() {
26            Ok("256") => KeySize::Aes256,
27            Ok("128") | Err(_) => KeySize::Aes128,
28            _ => return Err("key bits must be 128 or 256".into()),
29        };
30        config.crypto = Some(CryptoConfig::new(secret.into_bytes(), size)?);
31        config.require_encryption = true;
32    }
33    let socket = UdpSocket::bind(bind)?;
34    socket.set_read_timeout(Some(Duration::from_millis(5)))?;
35    let mut output = File::create(path)?;
36    let start = Instant::now();
37    let mut listener = Listener::new(config, start);
38    let mut packet = [0; 2048];
39    let mut bytes = 0;
40    let mut connection = None;
41    println!("listening {}", socket.local_addr()?);
42    std::io::stdout().flush()?;
43    while start.elapsed() < Duration::from_secs(20) {
44        let now = Instant::now();
45        listener.handle_timeout(now);
46        while let Some(event) = listener.poll_event() {
47            match event {
48                Event::Connect { id, stream_id, .. } => {
49                    println!("stream_id={}", String::from_utf8_lossy(&stream_id));
50                    if listener.accept(id, now) {
51                        connection = Some(id);
52                    }
53                }
54                Event::Data { payload, .. } => {
55                    output.write_all(&payload)?;
56                    bytes += payload.len();
57                }
58                Event::Closed { .. } => {}
59            }
60        }
61        if bytes >= expected {
62            let stats = connection.and_then(|id| listener.connection_stats(id));
63            println!("received_bytes={bytes} stats={stats:?}");
64            if let Some(id) = connection {
65                listener.close(id, now);
66            }
67            while let Some((peer, b)) = listener.poll_transmit() {
68                socket.send_to(&b, peer)?;
69            }
70            return Ok(());
71        }
72        while let Some((peer, b)) = listener.poll_transmit() {
73            socket.send_to(&b, peer)?;
74        }
75        match socket.recv_from(&mut packet) {
76            Ok((n, peer)) => {
77                listener.handle_datagram(Instant::now(), peer, packet.get(..n).unwrap_or_default())
78            }
79            Err(e)
80                if matches!(
81                    e.kind(),
82                    ErrorKind::TimedOut | ErrorKind::WouldBlock | ErrorKind::Interrupted
83                ) => {}
84            Err(e) => return Err(e.into()),
85        }
86    }
87    Err(format!(
88        "receiver timeout bytes={bytes} rejected={}",
89        listener.stats().rejected
90    )
91    .into())
92}

Auto Trait Implementations§

§

impl<S> Freeze for Listener<S>
where S: Freeze,

§

impl<S> RefUnwindSafe for Listener<S>
where S: RefUnwindSafe,

§

impl<S> Send for Listener<S>
where S: Send,

§

impl<S> Sync for Listener<S>
where S: Sync,

§

impl<S> Unpin for Listener<S>
where S: Unpin,

§

impl<S> UnsafeUnpin for Listener<S>
where S: UnsafeUnpin,

§

impl<S> UnwindSafe for Listener<S>
where S: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.