(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, cchar) -> 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, radixu8) -> Option<u8> {
 161          fn parse_digit(cchar, radixu8) -> 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, radixu8, max_digitsu32, uptou32) -> 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, radixu8, max_digitsu32, uptou32) -> 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], limituint) -> (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 Parserp.read_ipv4_addr();
 307          let ipv6_addr = |p&mut Parserp.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 Parserp.read_ip_addr();
 314              let ipv6_p = |p&mut Parser{
 315                  let open_br = |p&mut Parserp.read_given_char('[');
 316                  let ip_addr = |p&mut Parserp.read_ipv6_addr();
 317                  let clos_br = |p&mut Parserp.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 Parserp.read_given_char(':');
 324          let port  = |p&mut Parserp.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:- 2
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)))


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:- 24
60: 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:- 44
libstd/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:- 21
127:                   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);