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>
impl Listener<RandomState>
Sourcepub fn new(config: Config, now: Instant) -> Self
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?
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
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>
impl<S: BuildHasher> Listener<S>
Sourcepub fn with_key(config: Config, now: Instant, key: S) -> Self
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).
Sourcepub fn stats(&self) -> ListenerStats
pub fn stats(&self) -> ListenerStats
Counts of datagrams discarded so far, by kind.
Examples found in repository?
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}Sourcepub fn connections(&self) -> usize
pub fn connections(&self) -> usize
Connections open or waiting for an answer.
Sourcepub fn connection_stats(&self, id: ConnId) -> Option<Stats>
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?
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}Sourcepub fn latency(&self, id: ConnId) -> Option<Duration>
pub fn latency(&self, id: ConnId) -> Option<Duration>
The negotiated latency of an open connection.
Sourcepub fn poll_transmit(&mut self) -> Option<(SocketAddr, Vec<u8>)>
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?
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
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}Sourcepub fn poll_event(&mut self) -> Option<Event>
pub fn poll_event(&mut self) -> Option<Event>
The next Event, if any.
Examples found in repository?
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
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}Sourcepub fn poll_timeout(&self) -> Option<Instant>
pub fn poll_timeout(&self) -> Option<Instant>
When to call handle_timeout; None when
there are no connections.
Examples found in repository?
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}Sourcepub fn handle_datagram(
&mut self,
now: Instant,
peer: SocketAddr,
datagram: &[u8],
)
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?
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
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}Sourcepub fn handle_timeout(&mut self, now: Instant)
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?
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
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}Sourcepub fn accept(&mut self, id: ConnId, now: Instant) -> bool
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?
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
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}Sourcepub fn accept_with_crypto(
&mut self,
id: ConnId,
now: Instant,
crypto: Option<CryptoConfig>,
) -> bool
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.
Sourcepub fn reject(&mut self, id: ConnId, code: RejectCode) -> bool
pub fn reject(&mut self, id: ConnId, code: RejectCode) -> bool
Refuses a caller announced by Event::Connect.
Sourcepub fn close(&mut self, id: ConnId, now: Instant)
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?
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}