diff options
| author | Linus Färnstrand <linus@mullvad.net> | 2016-12-07 13:37:28 +0100 |
|---|---|---|
| committer | Linus Färnstrand <linus@mullvad.net> | 2016-12-07 14:31:08 +0100 |
| commit | 6d8e98afb08d067b98616d5c7f9ebe3570fdc838 (patch) | |
| tree | aef3464d1db8c9f81841112617acf9104cdf30eb /src | |
| parent | 171eca6adc5e5ce1937470fe5a3e128f4d3af481 (diff) | |
| download | mullvadvpn-6d8e98afb08d067b98616d5c7f9ebe3570fdc838.tar.xz mullvadvpn-6d8e98afb08d067b98616d5c7f9ebe3570fdc838.zip | |
Change RemoteAddr::from_str to support IPv6
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/net.rs | 58 |
2 files changed, 24 insertions, 36 deletions
diff --git a/src/lib.rs b/src/lib.rs index c65c221aec..7683c6dc3b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ //! The core components of the talpidaemon VPN client. +extern crate regex; + /// Working with processes. pub mod process; diff --git a/src/net.rs b/src/net.rs index 0ef87be58e..250720782e 100644 --- a/src/net.rs +++ b/src/net.rs @@ -1,3 +1,5 @@ +use regex::Regex; + use std::error::Error; use std::fmt; use std::net::SocketAddr; @@ -42,26 +44,21 @@ impl From<SocketAddr> for RemoteAddr { impl FromStr for RemoteAddr { type Err = AddrParseError; - /// Parse a string into a `RemoteAddr`. Does not work correctly with IPv6, see tests for - /// defined behavior fn from_str(s: &str) -> Result<Self, Self::Err> { - let (address_str, port_str) = split_at_colon(s).map_err(|_| AddrParseError(()))?; + let (address, port_str) = split_remote_addr_string(s).map_err(|_| AddrParseError(()))?; let port = u16::from_str(port_str).map_err(|_| AddrParseError(()))?; - if address_str.len() == 0 { - return Err(AddrParseError(())); - } Ok(RemoteAddr { - address: String::from(address_str), + address: address.to_owned(), port: port, }) } } -fn split_at_colon(s: &str) -> Result<(&str, &str), ()> { - let mut iter = s.rsplitn(2, ":"); - let port = iter.next().unwrap(); - let address = iter.next().ok_or(())?; - Ok((address, port)) +fn split_remote_addr_string(s: &str) -> Result<(&str, &str), ()> { + let with_brackets = Regex::new(r"^\[([^\]]+)\]:([0-9]+)$").unwrap(); + let without_brackets = Regex::new(r"^([^:]+):([0-9]+)$").unwrap(); + let captures = with_brackets.captures(s).or(without_brackets.captures(s)); + captures.map(|cs| (cs.at(1).unwrap(), cs.at(2).unwrap())).ok_or(()) } impl fmt::Display for RemoteAddr { @@ -116,32 +113,21 @@ mod tests { assert_eq!(3333, remote_addr.port()); } - // These tests exist to show that the parsing does not work exactly as the standard suggests - // https://tools.ietf.org/html/rfc3986#appendix-A - mod ipv6_invalid_parsing { - use std::str::FromStr; - use super::super::*; - - #[test] - fn remote_addr_from_ipv6_str_without_brackets() { - let remote_addr = RemoteAddr::from_str("fe80::1:1337").unwrap(); - assert_eq!("fe80::1", remote_addr.address()); - assert_eq!(1337, remote_addr.port()); - } + #[test] + fn remote_addr_from_ipv6_str_without_brackets() { + assert!(RemoteAddr::from_str("fe80::1:1337").is_err()); + } - #[test] - fn remote_addr_from_ipv6_str_with_brackets() { - let remote_addr = RemoteAddr::from_str("[fe80::1]:1337").unwrap(); - assert_eq!("[fe80::1]", remote_addr.address()); - assert_eq!(1337, remote_addr.port()); - } + #[test] + fn remote_addr_from_ipv6_str_with_brackets() { + let remote_addr = RemoteAddr::from_str("[fe80::1]:1337").unwrap(); + assert_eq!("fe80::1", remote_addr.address()); + assert_eq!(1337, remote_addr.port()); + } - #[test] - fn remote_addr_from_ipv6_str_without_port() { - let remote_addr = RemoteAddr::from_str("fe80::1").unwrap(); - assert_eq!("fe80:", remote_addr.address()); - assert_eq!(1, remote_addr.port()); - } + #[test] + fn remote_addr_from_ipv6_str_without_port() { + assert!(RemoteAddr::from_str("fe80::1").is_err()); } #[test] |
