asyncio/ip/
icmp.rs

1use prelude::Protocol;
2use ffi::{IntoI32, AF_UNSPEC, AF_INET, AF_INET6, SOCK_RAW,
3          IPPROTO_ICMP, IPPROTO_ICMPV6};
4use raw_socket::RawSocket;
5use ip::{IpProtocol, IpEndpoint, Resolver, ResolverIter, ResolverQuery};
6
7use std::io;
8use std::fmt;
9use std::mem;
10
11/// The Internet Control Message Protocol.
12#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
13pub struct Icmp {
14    family: i32,
15    protocol: i32,
16}
17
18impl Protocol for Icmp {
19    type Endpoint = IpEndpoint<Self>;
20
21    fn family_type(&self) -> i32 {
22        self.family
23    }
24
25    fn socket_type(&self) -> i32 {
26        SOCK_RAW as i32
27    }
28
29    fn protocol_type(&self) -> i32 {
30        self.protocol
31    }
32
33    unsafe fn uninitialized(&self) -> Self::Endpoint {
34        mem::uninitialized()
35    }
36}
37
38impl IpProtocol for Icmp {
39    /// Represents a ICMP.
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// use asyncio::Endpoint;
45    /// use asyncio::ip::{IpProtocol, IpAddrV4, Icmp, IcmpEndpoint};
46    ///
47    /// let ep = IcmpEndpoint::new(IpAddrV4::any(), 0);
48    /// assert_eq!(Icmp::v4(), ep.protocol());
49    /// ```
50    fn v4() -> Icmp {
51        Icmp { family: AF_INET as i32, protocol: IPPROTO_ICMP.i32() }
52    }
53
54    /// Represents a ICMPv6.
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use asyncio::Endpoint;
60    /// use asyncio::ip::{IpProtocol, IpAddrV6, Icmp, IcmpEndpoint};
61    ///
62    /// let ep = IcmpEndpoint::new(IpAddrV6::any(), 0);
63    /// assert_eq!(Icmp::v6(), ep.protocol());
64    /// ```
65    fn v6() -> Icmp {
66        Icmp { family: AF_INET6 as i32, protocol: IPPROTO_ICMPV6.i32() }
67    }
68}
69
70impl fmt::Debug for Icmp {
71    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72        if self.is_v4() {
73            write!(f, "ICMPv4")
74        } else if self.is_v6() {
75            write!(f, "ICMPv6")
76        } else {
77            unreachable!("Invalid address family ({}).", self.family);
78        }
79    }
80}
81
82impl<'a> ResolverQuery<Icmp> for &'a str {
83    fn iter(self) -> io::Result<ResolverIter<Icmp>> {
84        ResolverIter::new(&Icmp { family: AF_UNSPEC, protocol: 0 }, self.as_ref(), "", 0)
85    }
86}
87
88impl fmt::Debug for IpEndpoint<Icmp> {
89    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90        write!(f, "Endpoint(ICMP/{})", self)
91    }
92}
93
94impl fmt::Debug for Resolver<Icmp, RawSocket<Icmp>> {
95    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
96        write!(f, "Resolver(ICMP)")
97    }
98}
99
100/// The ICMP endpoint type.
101pub type IcmpEndpoint = IpEndpoint<Icmp>;
102
103/// The ICMP socket type.
104pub type IcmpSocket = RawSocket<Icmp>;
105
106/// The ICMP resolver type.
107pub type IcmpResolver = Resolver<Icmp, RawSocket<Icmp>>;
108
109#[test]
110fn test_icmp() {
111    assert!(Icmp::v4() == Icmp::v4());
112    assert!(Icmp::v6() == Icmp::v6());
113    assert!(Icmp::v4() != Icmp::v6());
114}
115
116#[test]
117fn test_icmp_resolve() {
118    use core::IoContext;
119    use ip::*;
120
121    let ctx = &IoContext::new().unwrap();
122    let re = IcmpResolver::new(ctx);
123    for ep in re.resolve("127.0.0.1").unwrap() {
124        assert!(ep == IcmpEndpoint::new(IpAddrV4::loopback(), 0));
125    }
126    for ep in re.resolve("::1").unwrap() {
127        assert!(ep == IcmpEndpoint::new(IpAddrV6::loopback(), 0));
128    }
129    for ep in re.resolve(("localhost")).unwrap() {
130        assert!(ep.addr().is_loopback());
131    }
132}
133
134#[test]
135#[ignore]
136fn test_format() {
137    use core::IoContext;
138
139    let ctx = &IoContext::new().unwrap();
140    println!("{:?}", Icmp::v4());
141    println!("{:?}", IcmpEndpoint::new(Icmp::v4(), 12345));
142    println!("{:?}", IcmpSocket::new(ctx, Icmp::v4()).unwrap());
143    println!("{:?}", IcmpResolver::new(ctx));
144}