rtc_shared/
util.rs

1use crate::error::{Error, Result};
2use std::net::{SocketAddr, ToSocketAddrs};
3
4// match_range is a MatchFunc that accepts packets with the first byte in [lower..upper]
5fn match_range(lower: u8, upper: u8) -> impl Fn(&[u8]) -> bool {
6    move |buf: &[u8]| -> bool {
7        if buf.is_empty() {
8            return false;
9        }
10        let b = buf[0];
11        b >= lower && b <= upper
12    }
13}
14
15/// MatchFuncs as described in RFC7983
16/// <https://tools.ietf.org/html/rfc7983>
17///              +----------------+
18///              |        [0..3] -+--> forward to STUN
19///              |                |
20///              |      [16..19] -+--> forward to ZRTP
21///              |                |
22///  packet -->  |      [20..63] -+--> forward to DTLS
23///              |                |
24///              |      [64..79] -+--> forward to TURN Channel
25///              |                |
26///              |    [128..191] -+--> forward to RTP/RTCP
27///              +----------------+
28/// match_dtls is a MatchFunc that accepts packets with the first byte in [20..63]
29/// as defied in RFC7983
30pub fn match_dtls(b: &[u8]) -> bool {
31    match_range(20, 63)(b)
32}
33
34// match_srtp_or_srtcp is a MatchFunc that accepts packets with the first byte in [128..191]
35// as defied in RFC7983
36pub fn match_srtp_or_srtcp(b: &[u8]) -> bool {
37    match_range(128, 191)(b)
38}
39
40pub fn is_rtcp(buf: &[u8]) -> bool {
41    // Not long enough to determine RTP/RTCP
42    if buf.len() < 4 {
43        return false;
44    }
45
46    let rtcp_packet_type = buf[1];
47    (192..=223).contains(&rtcp_packet_type)
48}
49
50/// match_srtp is a MatchFunc that only matches SRTP and not SRTCP
51pub fn match_srtp(buf: &[u8]) -> bool {
52    match_srtp_or_srtcp(buf) && !is_rtcp(buf)
53}
54
55/// match_srtcp is a MatchFunc that only matches SRTCP and not SRTP
56pub fn match_srtcp(buf: &[u8]) -> bool {
57    match_srtp_or_srtcp(buf) && is_rtcp(buf)
58}
59
60/// lookup host to SocketAddr
61pub fn lookup_host<T>(use_ipv4: bool, host: T) -> Result<SocketAddr>
62where
63    T: ToSocketAddrs,
64{
65    for remote_addr in host.to_socket_addrs()? {
66        if (use_ipv4 && remote_addr.is_ipv4()) || (!use_ipv4 && remote_addr.is_ipv6()) {
67            return Ok(remote_addr);
68        }
69    }
70
71    Err(Error::ErrAddressParseFailed)
72}