rtc_stun/
uri.rs

1#[cfg(test)]
2mod uri_test;
3
4use shared::error::*;
5
6use std::fmt;
7
8// SCHEME definitions from RFC 7064 Section 3.2.
9
10pub const SCHEME: &str = "stun";
11pub const SCHEME_SECURE: &str = "stuns";
12
13// URI as defined in RFC 7064.
14#[derive(PartialEq, Eq, Debug)]
15pub struct Uri {
16    pub scheme: String,
17    pub host: String,
18    pub port: Option<u16>,
19}
20
21impl fmt::Display for Uri {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        let host = if self.host.contains("::") {
24            format!("[{}]", self.host)
25        } else {
26            self.host.clone()
27        };
28
29        if let Some(port) = self.port {
30            write!(f, "{}:{}:{}", self.scheme, host, port)
31        } else {
32            write!(f, "{}:{}", self.scheme, host)
33        }
34    }
35}
36
37impl Uri {
38    // parse_uri parses URI from string.
39    pub fn parse_uri(raw: &str) -> Result<Self> {
40        // work around for url crate
41        if raw.contains("//") {
42            return Err(Error::ErrInvalidUrl);
43        }
44
45        let mut s = raw.to_string();
46        let pos = raw.find(':');
47        let p = pos.ok_or(Error::ErrSchemeType)?;
48        s.replace_range(p..p + 1, "://");
49
50        let raw_parts = url::Url::parse(&s)?;
51
52        let scheme = raw_parts.scheme().into();
53        if scheme != SCHEME && scheme != SCHEME_SECURE {
54            return Err(Error::ErrSchemeType);
55        }
56
57        let host = raw_parts
58            .host_str()
59            .ok_or(Error::ErrHost)?
60            .trim()
61            .trim_start_matches('[')
62            .trim_end_matches(']')
63            .to_owned();
64
65        let port = raw_parts.port();
66
67        Ok(Uri { scheme, host, port })
68    }
69}