host.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. // Copyright 2013-2016 The rust-url developers.
  2. //
  3. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  4. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  5. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  6. // option. This file may not be copied, modified, or distributed
  7. // except according to those terms.
  8. #[cfg(feature = "heapsize")] use heapsize::HeapSizeOf;
  9. use std::cmp;
  10. use std::fmt::{self, Formatter};
  11. use std::io;
  12. use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
  13. use std::vec;
  14. use parser::{ParseResult, ParseError};
  15. use percent_encoding::percent_decode;
  16. use idna;
  17. #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  18. pub enum HostInternal {
  19. None,
  20. Domain,
  21. Ipv4(Ipv4Addr),
  22. Ipv6(Ipv6Addr),
  23. }
  24. #[cfg(feature = "heapsize")]
  25. known_heap_size!(0, HostInternal);
  26. impl<S> From<Host<S>> for HostInternal {
  27. fn from(host: Host<S>) -> HostInternal {
  28. match host {
  29. Host::Domain(_) => HostInternal::Domain,
  30. Host::Ipv4(address) => HostInternal::Ipv4(address),
  31. Host::Ipv6(address) => HostInternal::Ipv6(address),
  32. }
  33. }
  34. }
  35. /// The host name of an URL.
  36. #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
  37. pub enum Host<S=String> {
  38. /// A DNS domain name, as '.' dot-separated labels.
  39. /// Non-ASCII labels are encoded in punycode per IDNA.
  40. Domain(S),
  41. /// An IPv4 address.
  42. /// `Url::host_str` returns the serialization of this address,
  43. /// as four decimal integers separated by `.` dots.
  44. Ipv4(Ipv4Addr),
  45. /// An IPv6 address.
  46. /// `Url::host_str` returns the serialization of that address between `[` and `]` brackets,
  47. /// in the format per [RFC 5952 *A Recommendation
  48. /// for IPv6 Address Text Representation*](https://tools.ietf.org/html/rfc5952):
  49. /// lowercase hexadecimal with maximal `::` compression.
  50. Ipv6(Ipv6Addr),
  51. }
  52. #[cfg(feature = "heapsize")]
  53. impl<S: HeapSizeOf> HeapSizeOf for Host<S> {
  54. fn heap_size_of_children(&self) -> usize {
  55. match *self {
  56. Host::Domain(ref s) => s.heap_size_of_children(),
  57. _ => 0,
  58. }
  59. }
  60. }
  61. impl<'a> Host<&'a str> {
  62. /// Return a copy of `self` that owns an allocated `String` but does not borrow an `&Url`.
  63. pub fn to_owned(&self) -> Host<String> {
  64. match *self {
  65. Host::Domain(domain) => Host::Domain(domain.to_owned()),
  66. Host::Ipv4(address) => Host::Ipv4(address),
  67. Host::Ipv6(address) => Host::Ipv6(address),
  68. }
  69. }
  70. }
  71. impl Host<String> {
  72. /// Parse a host: either an IPv6 address in [] square brackets, or a domain.
  73. ///
  74. /// https://url.spec.whatwg.org/#host-parsing
  75. pub fn parse(input: &str) -> Result<Self, ParseError> {
  76. if input.starts_with("[") {
  77. if !input.ends_with("]") {
  78. return Err(ParseError::InvalidIpv6Address)
  79. }
  80. return parse_ipv6addr(&input[1..input.len() - 1]).map(Host::Ipv6)
  81. }
  82. let domain = percent_decode(input.as_bytes()).decode_utf8_lossy();
  83. let domain = try!(idna::domain_to_ascii(&domain));
  84. if domain.find(|c| matches!(c,
  85. '\0' | '\t' | '\n' | '\r' | ' ' | '#' | '%' | '/' | ':' | '?' | '@' | '[' | '\\' | ']'
  86. )).is_some() {
  87. return Err(ParseError::InvalidDomainCharacter)
  88. }
  89. if let Some(address) = try!(parse_ipv4addr(&domain)) {
  90. Ok(Host::Ipv4(address))
  91. } else {
  92. Ok(Host::Domain(domain.into()))
  93. }
  94. }
  95. }
  96. impl<S: AsRef<str>> fmt::Display for Host<S> {
  97. fn fmt(&self, f: &mut Formatter) -> fmt::Result {
  98. match *self {
  99. Host::Domain(ref domain) => domain.as_ref().fmt(f),
  100. Host::Ipv4(ref addr) => addr.fmt(f),
  101. Host::Ipv6(ref addr) => {
  102. try!(f.write_str("["));
  103. try!(write_ipv6(addr, f));
  104. f.write_str("]")
  105. }
  106. }
  107. }
  108. }
  109. /// This mostly exists because coherence rules don’t allow us to implement
  110. /// `ToSocketAddrs for (Host<S>, u16)`.
  111. #[derive(Clone)]
  112. pub struct HostAndPort<S=String> {
  113. pub host: Host<S>,
  114. pub port: u16,
  115. }
  116. impl<'a> HostAndPort<&'a str> {
  117. /// Return a copy of `self` that owns an allocated `String` but does not borrow an `&Url`.
  118. pub fn to_owned(&self) -> HostAndPort<String> {
  119. HostAndPort {
  120. host: self.host.to_owned(),
  121. port: self.port
  122. }
  123. }
  124. }
  125. impl<S: AsRef<str>> ToSocketAddrs for HostAndPort<S> {
  126. type Iter = SocketAddrs;
  127. fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
  128. let port = self.port;
  129. match self.host {
  130. Host::Domain(ref domain) => Ok(SocketAddrs {
  131. // FIXME: use std::net::lookup_host when it’s stable.
  132. state: SocketAddrsState::Domain(try!((domain.as_ref(), port).to_socket_addrs()))
  133. }),
  134. Host::Ipv4(address) => Ok(SocketAddrs {
  135. state: SocketAddrsState::One(SocketAddr::V4(SocketAddrV4::new(address, port)))
  136. }),
  137. Host::Ipv6(address) => Ok(SocketAddrs {
  138. state: SocketAddrsState::One(SocketAddr::V6(SocketAddrV6::new(address, port, 0, 0)))
  139. }),
  140. }
  141. }
  142. }
  143. /// Socket addresses for an URL.
  144. pub struct SocketAddrs {
  145. state: SocketAddrsState
  146. }
  147. enum SocketAddrsState {
  148. Domain(vec::IntoIter<SocketAddr>),
  149. One(SocketAddr),
  150. Done,
  151. }
  152. impl Iterator for SocketAddrs {
  153. type Item = SocketAddr;
  154. fn next(&mut self) -> Option<SocketAddr> {
  155. match self.state {
  156. SocketAddrsState::Domain(ref mut iter) => iter.next(),
  157. SocketAddrsState::One(s) => {
  158. self.state = SocketAddrsState::Done;
  159. Some(s)
  160. }
  161. SocketAddrsState::Done => None
  162. }
  163. }
  164. }
  165. fn write_ipv6(addr: &Ipv6Addr, f: &mut Formatter) -> fmt::Result {
  166. let segments = addr.segments();
  167. let (compress_start, compress_end) = longest_zero_sequence(&segments);
  168. let mut i = 0;
  169. while i < 8 {
  170. if i == compress_start {
  171. try!(f.write_str(":"));
  172. if i == 0 {
  173. try!(f.write_str(":"));
  174. }
  175. if compress_end < 8 {
  176. i = compress_end;
  177. } else {
  178. break;
  179. }
  180. }
  181. try!(write!(f, "{:x}", segments[i as usize]));
  182. if i < 7 {
  183. try!(f.write_str(":"));
  184. }
  185. i += 1;
  186. }
  187. Ok(())
  188. }
  189. fn longest_zero_sequence(pieces: &[u16; 8]) -> (isize, isize) {
  190. let mut longest = -1;
  191. let mut longest_length = -1;
  192. let mut start = -1;
  193. macro_rules! finish_sequence(
  194. ($end: expr) => {
  195. if start >= 0 {
  196. let length = $end - start;
  197. if length > longest_length {
  198. longest = start;
  199. longest_length = length;
  200. }
  201. }
  202. };
  203. );
  204. for i in 0..8 {
  205. if pieces[i as usize] == 0 {
  206. if start < 0 {
  207. start = i;
  208. }
  209. } else {
  210. finish_sequence!(i);
  211. start = -1;
  212. }
  213. }
  214. finish_sequence!(8);
  215. (longest, longest + longest_length)
  216. }
  217. fn parse_ipv4number(mut input: &str) -> Result<u32, ()> {
  218. let mut r = 10;
  219. if input.starts_with("0x") || input.starts_with("0X") {
  220. input = &input[2..];
  221. r = 16;
  222. } else if input.len() >= 2 && input.starts_with("0") {
  223. input = &input[1..];
  224. r = 8;
  225. }
  226. if input.is_empty() {
  227. return Ok(0);
  228. }
  229. if input.starts_with("+") {
  230. return Err(())
  231. }
  232. match u32::from_str_radix(&input, r) {
  233. Ok(number) => Ok(number),
  234. Err(_) => Err(()),
  235. }
  236. }
  237. fn parse_ipv4addr(input: &str) -> ParseResult<Option<Ipv4Addr>> {
  238. if input.is_empty() {
  239. return Ok(None)
  240. }
  241. let mut parts: Vec<&str> = input.split('.').collect();
  242. if parts.last() == Some(&"") {
  243. parts.pop();
  244. }
  245. if parts.len() > 4 {
  246. return Ok(None);
  247. }
  248. let mut numbers: Vec<u32> = Vec::new();
  249. for part in parts {
  250. if part == "" {
  251. return Ok(None);
  252. }
  253. if let Ok(n) = parse_ipv4number(part) {
  254. numbers.push(n);
  255. } else {
  256. return Ok(None);
  257. }
  258. }
  259. let mut ipv4 = numbers.pop().expect("a non-empty list of numbers");
  260. // Equivalent to: ipv4 >= 256 ** (4 − numbers.len())
  261. if ipv4 > u32::max_value() >> (8 * numbers.len() as u32) {
  262. return Err(ParseError::InvalidIpv4Address);
  263. }
  264. if numbers.iter().any(|x| *x > 255) {
  265. return Err(ParseError::InvalidIpv4Address);
  266. }
  267. for (counter, n) in numbers.iter().enumerate() {
  268. ipv4 += n << (8 * (3 - counter as u32))
  269. }
  270. Ok(Some(Ipv4Addr::from(ipv4)))
  271. }
  272. fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
  273. let input = input.as_bytes();
  274. let len = input.len();
  275. let mut is_ip_v4 = false;
  276. let mut pieces = [0, 0, 0, 0, 0, 0, 0, 0];
  277. let mut piece_pointer = 0;
  278. let mut compress_pointer = None;
  279. let mut i = 0;
  280. if len < 2 {
  281. return Err(ParseError::InvalidIpv6Address)
  282. }
  283. if input[0] == b':' {
  284. if input[1] != b':' {
  285. return Err(ParseError::InvalidIpv6Address)
  286. }
  287. i = 2;
  288. piece_pointer = 1;
  289. compress_pointer = Some(1);
  290. }
  291. while i < len {
  292. if piece_pointer == 8 {
  293. return Err(ParseError::InvalidIpv6Address)
  294. }
  295. if input[i] == b':' {
  296. if compress_pointer.is_some() {
  297. return Err(ParseError::InvalidIpv6Address)
  298. }
  299. i += 1;
  300. piece_pointer += 1;
  301. compress_pointer = Some(piece_pointer);
  302. continue
  303. }
  304. let start = i;
  305. let end = cmp::min(len, start + 4);
  306. let mut value = 0u16;
  307. while i < end {
  308. match (input[i] as char).to_digit(16) {
  309. Some(digit) => {
  310. value = value * 0x10 + digit as u16;
  311. i += 1;
  312. },
  313. None => break
  314. }
  315. }
  316. if i < len {
  317. match input[i] {
  318. b'.' => {
  319. if i == start {
  320. return Err(ParseError::InvalidIpv6Address)
  321. }
  322. i = start;
  323. is_ip_v4 = true;
  324. },
  325. b':' => {
  326. i += 1;
  327. if i == len {
  328. return Err(ParseError::InvalidIpv6Address)
  329. }
  330. },
  331. _ => return Err(ParseError::InvalidIpv6Address)
  332. }
  333. }
  334. if is_ip_v4 {
  335. break
  336. }
  337. pieces[piece_pointer] = value;
  338. piece_pointer += 1;
  339. }
  340. if is_ip_v4 {
  341. if piece_pointer > 6 {
  342. return Err(ParseError::InvalidIpv6Address)
  343. }
  344. let mut dots_seen = 0;
  345. while i < len {
  346. let mut value = None;
  347. while i < len {
  348. let digit = match input[i] {
  349. c @ b'0' ... b'9' => c - b'0',
  350. _ => break
  351. };
  352. match value {
  353. None => value = Some(digit as u16),
  354. Some(0) => return Err(ParseError::InvalidIpv6Address), // No leading zero
  355. Some(ref mut v) => {
  356. *v = *v * 10 + digit as u16;
  357. if *v > 255 {
  358. return Err(ParseError::InvalidIpv6Address)
  359. }
  360. }
  361. }
  362. i += 1;
  363. }
  364. if dots_seen < 3 && !(i < len && input[i] == b'.') {
  365. return Err(ParseError::InvalidIpv6Address)
  366. }
  367. pieces[piece_pointer] = if let Some(v) = value {
  368. pieces[piece_pointer] * 0x100 + v
  369. } else {
  370. return Err(ParseError::InvalidIpv6Address)
  371. };
  372. if dots_seen == 1 || dots_seen == 3 {
  373. piece_pointer += 1;
  374. }
  375. i += 1;
  376. if dots_seen == 3 && i < len {
  377. return Err(ParseError::InvalidIpv6Address)
  378. }
  379. dots_seen += 1;
  380. }
  381. }
  382. match compress_pointer {
  383. Some(compress_pointer) => {
  384. let mut swaps = piece_pointer - compress_pointer;
  385. piece_pointer = 7;
  386. while swaps > 0 {
  387. pieces[piece_pointer] = pieces[compress_pointer + swaps - 1];
  388. pieces[compress_pointer + swaps - 1] = 0;
  389. swaps -= 1;
  390. piece_pointer -= 1;
  391. }
  392. }
  393. _ => if piece_pointer != 8 {
  394. return Err(ParseError::InvalidIpv6Address)
  395. }
  396. }
  397. Ok(Ipv6Addr::new(pieces[0], pieces[1], pieces[2], pieces[3],
  398. pieces[4], pieces[5], pieces[6], pieces[7]))
  399. }