asyncio/ip/
mod.rs

1use prelude::{Protocol, SockAddr, Endpoint};
2use ffi::{SockAddrImpl, sockaddr_in, sockaddr_in6, sockaddr_storage, gethostname, AF_INET, AF_INET6, };
3use core::IoContext;
4
5use std::io;
6use std::fmt;
7use std::mem;
8use std::marker::PhantomData;
9
10mod addr;
11pub use self::addr::*;
12
13pub trait IpProtocol : Protocol + Eq {
14    fn v4() -> Self;
15
16    fn v6() -> Self;
17
18    fn is_v4(&self) -> bool {
19        self == &Self::v4()
20    }
21
22    fn is_v6(&self) -> bool {
23        self == &Self::v6()
24    }
25}
26
27/// The endpoint of internet protocol.
28#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
29pub struct IpEndpoint<P> {
30    ss: SockAddrImpl<sockaddr_storage>,
31    _marker: PhantomData<P>,
32}
33
34impl<P: Protocol> IpEndpoint<P> {
35    /// Returns a IpEndpoint from IP address and port number.
36    ///
37    /// # Examples
38    ///
39    /// ```
40    /// use asyncio::ip::{IpEndpoint, IpAddrV4, Tcp};
41    /// let ep: IpEndpoint<Tcp> = IpEndpoint::new(IpAddrV4::loopback(), 80);
42    /// ```
43    pub fn new<T>(addr: T, port: u16) -> Self
44        where T: IntoEndpoint<P>,
45    {
46        addr.into_endpoint(port)
47    }
48
49    /// Returns true if this is IpEndpoint of IP-v4 address.
50    ///
51    /// # Examples
52    ///
53    /// ```
54    /// use asyncio::ip::{IpEndpoint, IpAddrV4, IpAddrV6, Tcp};
55    ///
56    /// let ep: IpEndpoint<Tcp> = IpEndpoint::new(IpAddrV4::loopback(), 80);
57    /// assert_eq!(ep.is_v4(), true);
58    ///
59    /// let ep: IpEndpoint<Tcp> = IpEndpoint::new(IpAddrV6::loopback(), 80);
60    /// assert_eq!(ep.is_v4(), false);
61    /// ```
62    pub fn is_v4(&self) -> bool {
63        self.ss.ss_family as i32 == AF_INET
64    }
65
66    /// Returns true if this is IpEndpoint of IP-v6 address.
67    ///
68    /// # Examples
69    ///
70    /// ```
71    /// use asyncio::ip::{IpEndpoint, IpAddrV4, IpAddrV6, Tcp};
72    ///
73    /// let ep: IpEndpoint<Tcp> = IpEndpoint::new(IpAddrV4::loopback(), 80);
74    /// assert_eq!(ep.is_v6(), false);
75    ///
76    /// let ep: IpEndpoint<Tcp> = IpEndpoint::new(IpAddrV6::loopback(), 80);
77    /// assert_eq!(ep.is_v6(), true);
78    /// ```
79    pub fn is_v6(&self) -> bool {
80        self.ss.ss_family as i32 == AF_INET6
81    }
82
83    /// Returns a IP address.
84    pub fn addr(&self) -> IpAddr {
85        match self.ss.ss_family as i32 {
86            AF_INET => unsafe {
87                let sin: &sockaddr_in = mem::transmute(&*self.ss);
88                let bytes: [u8; 4] = mem::transmute(sin.sin_addr);
89                IpAddr::V4(IpAddrV4::from(bytes))
90            },
91            AF_INET6  => unsafe {
92                let sin6: &sockaddr_in6 = mem::transmute(&*self.ss);
93                let bytes: [u8; 16] = mem::transmute(sin6.sin6_addr);
94                IpAddr::V6(IpAddrV6::from(bytes, sin6.sin6_scope_id))
95            },
96            _ => panic!("Invalid address family ({}).", self.ss.ss_family),
97        }
98    }
99
100    /// Returns a port number.
101    pub fn port(&self) -> u16 {
102        let sin: &sockaddr_in = unsafe { mem::transmute(&*self.ss) };
103        u16::from_be(sin.sin_port)
104    }
105
106    fn from_v4(addr: &IpAddrV4, port: u16) -> IpEndpoint<P> {
107        let mut ep = IpEndpoint {
108            ss: SockAddrImpl::new(AF_INET, mem::size_of::<sockaddr_in>()),
109            _marker: PhantomData,
110        };
111        unsafe {
112            let sin: &mut sockaddr_in = mem::transmute(&mut *ep.ss);
113            sin.sin_port = port.to_be();
114            sin.sin_addr = mem::transmute(addr.as_bytes().clone());
115            sin.sin_zero = [0; 8];
116        }
117        ep
118    }
119
120    fn from_v6(addr: &IpAddrV6, port: u16) -> IpEndpoint<P> {
121        let mut ep = IpEndpoint {
122            ss: SockAddrImpl::new(AF_INET6, mem::size_of::<sockaddr_in6>()),
123            _marker: PhantomData,
124        };
125        unsafe {
126            let sin6: &mut sockaddr_in6 = mem::transmute(&mut *ep.ss);
127            sin6.sin6_port = port.to_be();
128            sin6.sin6_flowinfo = 0;
129            sin6.sin6_addr = mem::transmute(addr.as_bytes().clone());
130            sin6.sin6_scope_id = addr.get_scope_id();
131        }
132        ep
133    }
134}
135
136impl<P: Protocol> SockAddr for IpEndpoint<P> {
137    type SockAddr = sockaddr_storage;
138
139    fn as_ref(&self) -> &Self::SockAddr {
140        &*self.ss
141    }
142
143    unsafe fn as_mut(&mut self) -> &mut Self::SockAddr {
144        &mut *self.ss
145    }
146
147    fn capacity(&self) -> usize {
148        self.ss.capacity()
149    }
150
151    fn size(&self) -> usize {
152        self.ss.size()
153    }
154
155    unsafe fn resize(&mut self, size: usize) {
156        debug_assert!(size <= self.capacity());
157        self.ss.resize(size)
158    }
159}
160
161impl<P: Protocol> fmt::Display for IpEndpoint<P> {
162    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163        match self.addr() {
164            IpAddr::V4(addr) => write!(f, "{}:{}", addr, self.port()),
165            IpAddr::V6(addr) => write!(f, "[{}]:{}", addr, self.port()),
166        }
167    }
168}
169
170impl<P: IpProtocol> Endpoint<P> for IpEndpoint<P> {
171    fn protocol(&self) -> P {
172        if self.is_v4() {
173            P::v4()
174        } else if self.is_v6() {
175            P::v6()
176        } else {
177            unreachable!("Invalid address family ({}).", self.ss.ss_family);
178        }
179    }
180}
181
182/// Provides conversion to a IP-endpoint.
183pub trait IntoEndpoint<P: Protocol> {
184    fn into_endpoint(self, port: u16) -> IpEndpoint<P>;
185}
186
187impl<P: IpProtocol> IntoEndpoint<P> for P {
188    fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
189        if self.is_v4() {
190            IpEndpoint::from_v4(&IpAddrV4::any(), port)
191        } else if self.is_v6() {
192            IpEndpoint::from_v6(&IpAddrV6::any(), port)
193        } else {
194            unreachable!("Invalid protocol");
195        }
196    }
197}
198
199impl<P: Protocol> IntoEndpoint<P> for IpAddrV4 {
200    fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
201        IpEndpoint::from_v4(&self, port)
202    }
203}
204
205impl<P: Protocol> IntoEndpoint<P> for IpAddrV6 {
206    fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
207        IpEndpoint::from_v6(&self, port)
208    }
209}
210
211impl<P: Protocol> IntoEndpoint<P> for IpAddr {
212    fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
213        match self {
214            IpAddr::V4(addr) => IpEndpoint::from_v4(&addr, port),
215            IpAddr::V6(addr) => IpEndpoint::from_v6(&addr, port),
216        }
217    }
218}
219
220impl<'a, P: Protocol> IntoEndpoint<P> for &'a IpAddrV4 {
221    fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
222        IpEndpoint::from_v4(self, port)
223    }
224}
225
226impl<'a, P: Protocol> IntoEndpoint<P> for &'a IpAddrV6 {
227    fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
228        IpEndpoint::from_v6(self, port)
229    }
230}
231
232impl<'a, P: Protocol> IntoEndpoint<P> for &'a IpAddr {
233    fn into_endpoint(self, port: u16) -> IpEndpoint<P> {
234        match self {
235            &IpAddr::V4(ref addr) => IpEndpoint::from_v4(addr, port),
236            &IpAddr::V6(ref addr) => IpEndpoint::from_v6(addr, port),
237        }
238    }
239}
240
241/// Get the current host name.
242///
243/// # Examples
244///
245/// ```
246/// use asyncio::IoContext;
247/// use asyncio::ip::host_name;
248///
249/// let ctx = &IoContext::new().unwrap();
250/// println!("{}", host_name(ctx).unwrap());
251/// ```
252pub fn host_name(_: &IoContext) -> io::Result<String> {
253    gethostname()
254}
255
256mod resolver;
257pub use self::resolver::*;
258
259mod tcp;
260pub use self::tcp::*;
261
262mod udp;
263pub use self::udp::*;
264
265mod icmp;
266pub use self::icmp::*;
267
268mod options;
269pub use self::options::*;
270
271#[test]
272fn test_host_name() {
273    let ctx = &IoContext::new().unwrap();
274    host_name(ctx).unwrap();
275}
276
277#[test]
278fn test_endpoint_v4() {
279    let ep = UdpEndpoint::new(IpAddrV4::new(1,2,3,4), 10);
280    assert!(ep.is_v4());
281    assert!(!ep.is_v6());
282    assert_eq!(ep.addr(), IpAddr::V4(IpAddrV4::new(1,2,3,4)));
283    assert_eq!(ep.port(), 10);
284}
285
286#[test]
287fn test_endpoint_v6() {
288    let ep = TcpEndpoint::new(IpAddrV6::new(1,2,3,4,5,6,7,8), 10);
289    assert!(ep.is_v6());
290    assert!(!ep.is_v4());
291    assert_eq!(ep.addr(), IpAddr::V6(IpAddrV6::new(1,2,3,4,5,6,7,8)));
292    assert_eq!(ep.port(), 10);
293}
294
295#[test]
296fn test_endpoint_cmp() {
297    let a = IcmpEndpoint::new(IpAddrV6::new(1,2,3,4,5,6,7,8), 10);
298    let b = IcmpEndpoint::new(IpAddrV6::with_scope_id(1,2,3,4,5,6,7,8,1), 10);
299    let c = IcmpEndpoint::new(IpAddrV6::new(1,2,3,4,5,6,7,8), 11);
300    assert!(a == a && b == b && c == c);
301    assert!(a != b && b != c);
302    assert!(a < b);
303    assert!(b < c);
304}