]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/net/ip.rs
rollup merge of #17355 : gamazeps/issue17210
[rust.git] / src / libstd / io / net / ip.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Internet Protocol (IP) addresses.
12 //!
13 //! This module contains functions useful for parsing, formatting, and
14 //! manipulating IP addresses.
15
16 #![allow(missing_doc)]
17
18 use collections::Collection;
19 use fmt;
20 use from_str::FromStr;
21 use iter::Iterator;
22 use option::{Option, None, Some};
23 use str::StrSlice;
24 use slice::{MutableCloneableSlice, ImmutableSlice, MutableSlice};
25
26 pub type Port = u16;
27
28 #[deriving(PartialEq, Eq, Clone, Hash)]
29 pub enum IpAddr {
30     Ipv4Addr(u8, u8, u8, u8),
31     Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
32 }
33
34 impl fmt::Show for IpAddr {
35     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
36         match *self {
37             Ipv4Addr(a, b, c, d) =>
38                 write!(fmt, "{}.{}.{}.{}", a, b, c, d),
39
40             // Ipv4 Compatible address
41             Ipv6Addr(0, 0, 0, 0, 0, 0, g, h) => {
42                 write!(fmt, "::{}.{}.{}.{}", (g >> 8) as u8, g as u8,
43                        (h >> 8) as u8, h as u8)
44             }
45
46             // Ipv4-Mapped address
47             Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => {
48                 write!(fmt, "::FFFF:{}.{}.{}.{}", (g >> 8) as u8, g as u8,
49                        (h >> 8) as u8, h as u8)
50             }
51
52             Ipv6Addr(a, b, c, d, e, f, g, h) =>
53                 write!(fmt, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
54                        a, b, c, d, e, f, g, h)
55         }
56     }
57 }
58
59 #[deriving(PartialEq, Eq, Clone, Hash)]
60 pub struct SocketAddr {
61     pub ip: IpAddr,
62     pub port: Port,
63 }
64
65 impl fmt::Show for SocketAddr {
66     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67         match self.ip {
68             Ipv4Addr(..) => write!(f, "{}:{}", self.ip, self.port),
69             Ipv6Addr(..) => write!(f, "[{}]:{}", self.ip, self.port),
70         }
71     }
72 }
73
74 struct Parser<'a> {
75     // parsing as ASCII, so can use byte array
76     s: &'a [u8],
77     pos: uint,
78 }
79
80 impl<'a> Parser<'a> {
81     fn new(s: &'a str) -> Parser<'a> {
82         Parser {
83             s: s.as_bytes(),
84             pos: 0,
85         }
86     }
87
88     fn is_eof(&self) -> bool {
89         self.pos == self.s.len()
90     }
91
92     // Commit only if parser returns Some
93     fn read_atomically<T>(&mut self, cb: |&mut Parser| -> Option<T>)
94                        -> Option<T> {
95         let pos = self.pos;
96         let r = cb(self);
97         if r.is_none() {
98             self.pos = pos;
99         }
100         r
101     }
102
103     // Commit only if parser read till EOF
104     fn read_till_eof<T>(&mut self, cb: |&mut Parser| -> Option<T>)
105                      -> Option<T> {
106         self.read_atomically(|p| cb(p).filtered(|_| p.is_eof()))
107     }
108
109     // Return result of first successful parser
110     fn read_or<T>(&mut self, parsers: &mut [|&mut Parser| -> Option<T>])
111                -> Option<T> {
112         for pf in parsers.iter_mut() {
113             match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
114                 Some(r) => return Some(r),
115                 None => {}
116             }
117         }
118         None
119     }
120
121     // Apply 3 parsers sequentially
122     fn read_seq_3<A,
123                   B,
124                   C>(
125                   &mut self,
126                   pa: |&mut Parser| -> Option<A>,
127                   pb: |&mut Parser| -> Option<B>,
128                   pc: |&mut Parser| -> Option<C>)
129                   -> Option<(A, B, C)> {
130         self.read_atomically(|p| {
131             let a = pa(p);
132             let b = if a.is_some() { pb(p) } else { None };
133             let c = if b.is_some() { pc(p) } else { None };
134             match (a, b, c) {
135                 (Some(a), Some(b), Some(c)) => Some((a, b, c)),
136                 _ => None
137             }
138         })
139     }
140
141     // Read next char
142     fn read_char(&mut self) -> Option<char> {
143         if self.is_eof() {
144             None
145         } else {
146             let r = self.s[self.pos] as char;
147             self.pos += 1;
148             Some(r)
149         }
150     }
151
152     // Return char and advance iff next char is equal to requested
153     fn read_given_char(&mut self, c: char) -> Option<char> {
154         self.read_atomically(|p| {
155             p.read_char().filtered(|&next| next == c)
156         })
157     }
158
159     // Read digit
160     fn read_digit(&mut self, radix: u8) -> Option<u8> {
161         fn parse_digit(c: char, radix: u8) -> Option<u8> {
162             let c = c as u8;
163             // assuming radix is either 10 or 16
164             if c >= b'0' && c <= b'9' {
165                 Some(c - b'0')
166             } else if radix > 10 && c >= b'a' && c < b'a' + (radix - 10) {
167                 Some(c - b'a' + 10)
168             } else if radix > 10 && c >= b'A' && c < b'A' + (radix - 10) {
169                 Some(c - b'A' + 10)
170             } else {
171                 None
172             }
173         }
174
175         self.read_atomically(|p| {
176             p.read_char().and_then(|c| parse_digit(c, radix))
177         })
178     }
179
180     fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
181         let mut r = 0u32;
182         let mut digit_count = 0;
183         loop {
184             match self.read_digit(radix) {
185                 Some(d) => {
186                     r = r * (radix as u32) + (d as u32);
187                     digit_count += 1;
188                     if digit_count > max_digits || r >= upto {
189                         return None
190                     }
191                 }
192                 None => {
193                     if digit_count == 0 {
194                         return None
195                     } else {
196                         return Some(r)
197                     }
198                 }
199             };
200         }
201     }
202
203     // Read number, failing if max_digits of number value exceeded
204     fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
205         self.read_atomically(|p| p.read_number_impl(radix, max_digits, upto))
206     }
207
208     fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
209         let mut bs = [0u8, ..4];
210         let mut i = 0;
211         while i < 4 {
212             if i != 0 && self.read_given_char('.').is_none() {
213                 return None;
214             }
215
216             let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
217             match octet {
218                 Some(d) => bs[i] = d,
219                 None => return None,
220             };
221             i += 1;
222         }
223         Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3]))
224     }
225
226     // Read IPv4 address
227     fn read_ipv4_addr(&mut self) -> Option<IpAddr> {
228         self.read_atomically(|p| p.read_ipv4_addr_impl())
229     }
230
231     fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
232         fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
233             assert!(head.len() + tail.len() <= 8);
234             let mut gs = [0u16, ..8];
235             gs.copy_from(head);
236             gs.slice_mut(8 - tail.len(), 8).copy_from(tail);
237             Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
238         }
239
240         fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
241             let mut i = 0;
242             while i < limit {
243                 if i < limit - 1 {
244                     let ipv4 = p.read_atomically(|p| {
245                         if i == 0 || p.read_given_char(':').is_some() {
246                             p.read_ipv4_addr()
247                         } else {
248                             None
249                         }
250                     });
251                     match ipv4 {
252                         Some(Ipv4Addr(a, b, c, d)) => {
253                             groups[i + 0] = (a as u16 << 8) | (b as u16);
254                             groups[i + 1] = (c as u16 << 8) | (d as u16);
255                             return (i + 2, true);
256                         }
257                         _ => {}
258                     }
259                 }
260
261                 let group = p.read_atomically(|p| {
262                     if i == 0 || p.read_given_char(':').is_some() {
263                         p.read_number(16, 4, 0x10000).map(|n| n as u16)
264                     } else {
265                         None
266                     }
267                 });
268                 match group {
269                     Some(g) => groups[i] = g,
270                     None => return (i, false)
271                 }
272                 i += 1;
273             }
274             (i, false)
275         }
276
277         let mut head = [0u16, ..8];
278         let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
279
280         if head_size == 8 {
281             return Some(Ipv6Addr(
282                 head[0], head[1], head[2], head[3],
283                 head[4], head[5], head[6], head[7]))
284         }
285
286         // IPv4 part is not allowed before `::`
287         if head_ipv4 {
288             return None
289         }
290
291         // read `::` if previous code parsed less than 8 groups
292         if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
293             return None;
294         }
295
296         let mut tail = [0u16, ..8];
297         let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
298         Some(ipv6_addr_from_head_tail(head.slice(0, head_size), tail.slice(0, tail_size)))
299     }
300
301     fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
302         self.read_atomically(|p| p.read_ipv6_addr_impl())
303     }
304
305     fn read_ip_addr(&mut self) -> Option<IpAddr> {
306         let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
307         let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
308         self.read_or(&mut [ipv4_addr, ipv6_addr])
309     }
310
311     fn read_socket_addr(&mut self) -> Option<SocketAddr> {
312         let ip_addr = |p: &mut Parser| {
313             let ipv4_p = |p: &mut Parser| p.read_ip_addr();
314             let ipv6_p = |p: &mut Parser| {
315                 let open_br = |p: &mut Parser| p.read_given_char('[');
316                 let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
317                 let clos_br = |p: &mut Parser| p.read_given_char(']');
318                 p.read_seq_3::<char, IpAddr, char>(open_br, ip_addr, clos_br)
319                         .map(|t| match t { (_, ip, _) => ip })
320             };
321             p.read_or(&mut [ipv4_p, ipv6_p])
322         };
323         let colon = |p: &mut Parser| p.read_given_char(':');
324         let port  = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
325
326         // host, colon, port
327         self.read_seq_3::<IpAddr, char, u16>(ip_addr, colon, port)
328                 .map(|t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
329     }
330 }
331
332 impl FromStr for IpAddr {
333     fn from_str(s: &str) -> Option<IpAddr> {
334         Parser::new(s).read_till_eof(|p| p.read_ip_addr())
335     }
336 }
337
338 impl FromStr for SocketAddr {
339     fn from_str(s: &str) -> Option<SocketAddr> {
340         Parser::new(s).read_till_eof(|p| p.read_socket_addr())
341     }
342 }
343
344
345 #[cfg(test)]
346 mod test {
347     use prelude::*;
348     use super::*;
349     use from_str::FromStr;
350
351     #[test]
352     fn test_from_str_ipv4() {
353         assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
354         assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
355         assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
356
357         // out of range
358         let none: Option<IpAddr> = FromStr::from_str("256.0.0.1");
359         assert_eq!(None, none);
360         // too short
361         let none: Option<IpAddr> = FromStr::from_str("255.0.0");
362         assert_eq!(None, none);
363         // too long
364         let none: Option<IpAddr> = FromStr::from_str("255.0.0.1.2");
365         assert_eq!(None, none);
366         // no number between dots
367         let none: Option<IpAddr> = FromStr::from_str("255.0..1");
368         assert_eq!(None, none);
369     }
370
371     #[test]
372     fn test_from_str_ipv6() {
373         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
374         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
375
376         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
377         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
378
379         assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
380                 FromStr::from_str("2a02:6b8::11:11"));
381
382         // too long group
383         let none: Option<IpAddr> = FromStr::from_str("::00000");
384         assert_eq!(None, none);
385         // too short
386         let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7");
387         assert_eq!(None, none);
388         // too long
389         let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7:8:9");
390         assert_eq!(None, none);
391         // triple colon
392         let none: Option<IpAddr> = FromStr::from_str("1:2:::6:7:8");
393         assert_eq!(None, none);
394         // two double colons
395         let none: Option<IpAddr> = FromStr::from_str("1:2::6::8");
396         assert_eq!(None, none);
397     }
398
399     #[test]
400     fn test_from_str_ipv4_in_ipv6() {
401         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
402                 FromStr::from_str("::192.0.2.33"));
403         assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
404                 FromStr::from_str("::FFFF:192.0.2.33"));
405         assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
406                 FromStr::from_str("64:ff9b::192.0.2.33"));
407         assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
408                 FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
409
410         // colon after v4
411         let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
412         assert_eq!(None, none);
413         // not enough groups
414         let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
415         assert_eq!(None, none);
416         // too many groups
417         let none: Option<IpAddr> =
418             FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1");
419         assert_eq!(None, none);
420     }
421
422     #[test]
423     fn test_from_str_socket_addr() {
424         assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
425                 FromStr::from_str("77.88.21.11:80"));
426         assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
427                 FromStr::from_str("[2a02:6b8:0:1::1]:53"));
428         assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
429                 FromStr::from_str("[::127.0.0.1]:22"));
430
431         // without port
432         let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1");
433         assert_eq!(None, none);
434         // without port
435         let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:");
436         assert_eq!(None, none);
437         // wrong brackets around v4
438         let none: Option<SocketAddr> = FromStr::from_str("[127.0.0.1]:22");
439         assert_eq!(None, none);
440         // port out of range
441         let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:123456");
442         assert_eq!(None, none);
443     }
444
445     #[test]
446     fn ipv6_addr_to_string() {
447         let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
448         assert!(a1.to_string() == "::ffff:192.0.2.128".to_string() ||
449                 a1.to_string() == "::FFFF:192.0.2.128".to_string());
450         assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_string(),
451                    "8:9:a:b:c:d:e:f".to_string());
452     }
453 }