xref: /webrtc/stun/src/uri.rs (revision c40fea4f)
1 #[cfg(test)]
2 mod uri_test;
3 
4 use crate::error::*;
5 
6 use std::fmt;
7 
8 // SCHEME definitions from RFC 7064 Section 3.2.
9 
10 pub const SCHEME: &str = "stun";
11 pub const SCHEME_SECURE: &str = "stuns";
12 
13 // URI as defined in RFC 7064.
14 #[derive(PartialEq, Eq, Debug)]
15 pub struct Uri {
16     pub scheme: String,
17     pub host: String,
18     pub port: Option<u16>,
19 }
20 
21 impl fmt::Display for Uri {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result22     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23         let host = if self.host.contains("::") {
24             "[".to_owned() + self.host.as_str() + "]"
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 
37 impl Uri {
38     // parse_uri parses URI from string.
parse_uri(raw: &str) -> Result<Self>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         if let Some(p) = pos {
48             s.replace_range(p..p + 1, "://");
49         } else {
50             return Err(Error::ErrSchemeType);
51         }
52 
53         let raw_parts = url::Url::parse(&s)?;
54 
55         let scheme = raw_parts.scheme().into();
56         if scheme != SCHEME && scheme != SCHEME_SECURE {
57             return Err(Error::ErrSchemeType);
58         }
59 
60         let host = if let Some(host) = raw_parts.host_str() {
61             host.trim()
62                 .trim_start_matches('[')
63                 .trim_end_matches(']')
64                 .to_owned()
65         } else {
66             return Err(Error::ErrHost);
67         };
68 
69         let port = raw_parts.port();
70 
71         Ok(Uri { scheme, host, port })
72     }
73 }
74