asyncio/ip/
udp.rs

1use prelude::Protocol;
2use ffi::{IntoI32, AF_UNSPEC, AF_INET, AF_INET6, SOCK_DGRAM,
3          IPPROTO_UDP, AI_PASSIVE, AI_NUMERICSERV};
4use dgram_socket::DgramSocket;
5use ip::{IpProtocol, IpEndpoint, Resolver, ResolverIter, ResolverQuery, Passive};
6
7use std::io;
8use std::fmt;
9use std::mem;
10
11/// The User Datagram Protocol.
12///
13/// # Examples
14/// In this example, Create a UDP client socket and send to an endpoint.
15///
16/// ```rust,no_run
17/// use asyncio::{IoContext, Protocol, Endpoint};
18/// use asyncio::ip::{IpProtocol, IpAddrV4, Udp, UdpEndpoint, UdpSocket};
19///
20/// let ctx = &IoContext::new().unwrap();
21/// let soc = UdpSocket::new(ctx, Udp::v4()).unwrap();
22///
23/// let ep = UdpEndpoint::new(IpAddrV4::loopback(), 12345);
24/// soc.send_to("hello".as_bytes(), 0, ep).unwrap();
25/// ```
26///
27/// # Examples
28/// In this example, Creates a UDP server and receive from an endpoint.
29///
30/// ```rust,no_run
31/// use asyncio::{IoContext, Protocol, Endpoint};
32/// use asyncio::ip::{IpProtocol, IpAddrV4, Udp, UdpEndpoint, UdpSocket};
33/// use asyncio::socket_base::ReuseAddr;
34///
35/// let ctx = &IoContext::new().unwrap();
36/// let ep = UdpEndpoint::new(Udp::v4(), 12345);
37/// let soc = UdpSocket::new(ctx, ep.protocol()).unwrap();
38///
39/// soc.set_option(ReuseAddr::new(true)).unwrap();
40/// soc.bind(&ep).unwrap();
41///
42/// let mut buf = [0; 256];
43/// let (len, ep) = soc.receive_from(&mut buf, 0).unwrap();
44/// ```
45#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
46pub struct Udp {
47    family: i32,
48}
49
50impl Protocol for Udp {
51    type Endpoint = IpEndpoint<Self>;
52
53    fn family_type(&self) -> i32 {
54        self.family
55    }
56
57    fn socket_type(&self) -> i32 {
58        SOCK_DGRAM as i32
59    }
60
61    fn protocol_type(&self) -> i32 {
62        IPPROTO_UDP.i32()
63    }
64
65    unsafe fn uninitialized(&self) -> Self::Endpoint {
66        mem::uninitialized()
67    }
68}
69
70impl IpProtocol for Udp {
71    /// Represents a UDP for IPv4.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use asyncio::Endpoint;
77    /// use asyncio::ip::{IpProtocol, IpAddrV4, Udp, UdpEndpoint};
78    ///
79    /// let ep = UdpEndpoint::new(IpAddrV4::any(), 0);
80    /// assert_eq!(Udp::v4(), ep.protocol());
81    /// ```
82    fn v4() -> Udp {
83        Udp { family: AF_INET as i32 }
84    }
85
86    /// Represents a UDP for IPv6.
87    ///
88    /// Examples
89    ///
90    /// ```
91    /// use asyncio::Endpoint;
92    /// use asyncio::ip::{IpProtocol, IpAddrV6, Udp, UdpEndpoint};
93    ///
94    /// let ep = UdpEndpoint::new(IpAddrV6::any(), 0);
95    /// assert_eq!(Udp::v6(), ep.protocol());
96    /// ```
97    fn v6() -> Udp {
98        Udp { family: AF_INET6 as i32 }
99    }
100}
101
102impl fmt::Debug for Udp {
103    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104        if self.is_v4() {
105            write!(f, "UDPv4")
106        } else if self.is_v6() {
107            write!(f, "UDPv6")
108        } else {
109            unreachable!("Invalid address family ({}).", self.family);
110        }
111    }
112}
113
114impl fmt::Debug for IpEndpoint<Udp> {
115    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116        write!(f, "Endpoint(UDP/{})", self)
117    }
118}
119
120impl fmt::Debug for Resolver<Udp, DgramSocket<Udp>> {
121    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122        write!(f, "Resolver(UDP)")
123    }
124}
125
126impl ResolverQuery<Udp> for (Passive, u16) {
127    fn iter(self) -> io::Result<ResolverIter<Udp>> {
128        let port = self.1.to_string();
129        ResolverIter::new(&Udp { family: AF_UNSPEC }, "", &port, AI_PASSIVE | AI_NUMERICSERV)
130    }
131}
132
133impl<'a> ResolverQuery<Udp> for (Passive, &'a str) {
134    fn iter(self) -> io::Result<ResolverIter<Udp>> {
135        ResolverIter::new(&Udp { family: AF_UNSPEC }, "", self.1, AI_PASSIVE)
136    }
137}
138
139impl<'a, 'b> ResolverQuery<Udp> for (&'a str, &'b str) {
140    fn iter(self) -> io::Result<ResolverIter<Udp>> {
141        ResolverIter::new(&Udp { family: AF_UNSPEC }, self.0, self.1, 0)
142    }
143}
144
145/// The UDP endpoint type.
146pub type UdpEndpoint = IpEndpoint<Udp>;
147
148/// The UDP socket type.
149///
150/// # Examples
151/// Constructs a UDP socket.
152///
153/// ```
154/// use asyncio::IoContext;
155/// use asyncio::ip::{IpProtocol, Udp, UdpSocket};
156///
157/// let ctx = &IoContext::new().unwrap();
158/// let udp4 = UdpSocket::new(ctx, Udp::v4()).unwrap();
159/// let udp6 = UdpSocket::new(ctx, Udp::v6()).unwrap();
160/// ```
161pub type UdpSocket = DgramSocket<Udp>;
162
163/// The UDP resolver type.
164pub type UdpResolver = Resolver<Udp, DgramSocket<Udp>>;
165
166#[test]
167fn test_udp() {
168    assert!(Udp::v4() == Udp::v4());
169    assert!(Udp::v6() == Udp::v6());
170    assert!(Udp::v4() != Udp::v6());
171}
172
173#[test]
174fn test_udp_resolve() {
175    use core::IoContext;
176    use ip::*;
177
178    let ctx = &IoContext::new().unwrap();
179    let re = UdpResolver::new(ctx);
180    for ep in re.resolve(("127.0.0.1", "80")).unwrap() {
181        assert!(ep == UdpEndpoint::new(IpAddrV4::loopback(), 80));
182    }
183    for ep in re.resolve(("::1", "80")).unwrap() {
184        assert!(ep == UdpEndpoint::new(IpAddrV6::loopback(), 80));
185    }
186    for ep in re.resolve(("localhost", "http")).unwrap() {
187        assert!(ep.addr().is_loopback());
188        assert!(ep.port() == 80);
189    }
190}
191
192
193#[test]
194fn test_format() {
195    use core::IoContext;
196
197    let ctx = &IoContext::new().unwrap();
198    println!("{:?}", Udp::v4());
199    println!("{:?}", UdpEndpoint::new(Udp::v4(), 12345));
200    println!("{:?}", UdpSocket::new(ctx, Udp::v4()).unwrap());
201    println!("{:?}", UdpResolver::new(ctx));
202}