(index<- ) ./libstd/io/net/ip.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri Apr 25 22:40:04 2014
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 container::Container;
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::{MutableCloneableVector, ImmutableVector, MutableVector};
25
26 pub type Port = u16;
27
28 #[deriving(Eq, TotalEq, 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.buf, "{}.{}.{}.{}", a, b, c, d),
39
40 // Ipv4 Compatible address
41 Ipv6Addr(0, 0, 0, 0, 0, 0, g, h) => {
42 write!(fmt.buf, "::{}.{}.{}.{}", (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.buf, "::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.buf, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
54 a, b, c, d, e, f, g, h)
55 }
56 }
57 }
58
59 #[deriving(Eq, TotalEq, 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.buf, "{}:{}", self.ip, self.port),
69 Ipv6Addr(..) => write!(f.buf, "[{}]:{}", 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.mut_iter() {
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 >= '0' as u8 && c <= '9' as u8 {
165 Some(c - '0' as u8)
166 } else if radix > 10 && c >= 'a' as u8 && c < 'a' as u8 + (radix - 10) {
167 Some(c - 'a' as u8 + 10)
168 } else if radix > 10 && c >= 'A' as u8 && c < 'A' as u8 + (radix - 10) {
169 Some(c - 'A' as u8 + 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.mut_slice(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 enought 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_str() {
447 let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
448 assert!(a1.to_str() == "::ffff:192.0.2.128".to_owned() ||
449 a1.to_str() == "::FFFF:192.0.2.128".to_owned());
450 assert_eq!(Ipv6Addr(8, 9, 10, 11, 12, 13, 14, 15).to_str(), "8:9:a:b:c:d:e:f".to_owned());
451 }
452 }
libstd/io/net/ip.rs:240:8-240:8 -fn- definition:
fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
let mut i = 0;
while i < limit {
references:- 2296: 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)))
libstd/io/net/ip.rs:28:38-28:38 -enum- definition:
pub enum IpAddr {
Ipv4Addr(u8, u8, u8, u8),
Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
references:- 2460: pub struct SocketAddr {
61: pub ip: IpAddr,
62: pub port: Port,
--
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);
--
301: fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
302: self.read_atomically(|p| p.read_ipv6_addr_impl())
--
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 } })
--
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())
libstd/rt/rtio.rs:
238: fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
239: fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
libstd/io/net/addrinfo.rs:
75: /// that hostname.
76: pub fn get_host_addresses(host: &str) -> IoResult<Vec<IpAddr>> {
77: lookup(Some(host), None, None).map(|a| a.move_iter().map(|i| i.address.ip).collect())
libstd/io/net/udp.rs:
102: #[experimental]
103: pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
104: self.obj.join_multicast(multi)
--
108: #[experimental]
109: pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
110: self.obj.leave_multicast(multi)
libstd/io/net/ip.rs:
29: pub enum IpAddr {
libstd/io/net/ip.rs:59:38-59:38 -struct- definition:
pub struct SocketAddr {
pub ip: IpAddr,
pub port: Port,
references:- 44libstd/io/test.rs:
libstd/io/net/ip.rs:
libstd/rt/rtio.rs:
libstd/io/test.rs:
libstd/io/net/addrinfo.rs:
libstd/io/net/tcp.rs:
libstd/io/net/udp.rs:
libstd/io/net/ip.rs:73:1-73:1 -struct- definition:
struct Parser<'a> {
// parsing as ASCII, so can use byte array
s: &'a [u8],
references:- 21127: pb: |&mut Parser| -> Option<B>,
128: pc: |&mut Parser| -> Option<C>)
129: -> Option<(A, B, C)> {
--
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);