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#[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 fn v4() -> Udp {
83 Udp { family: AF_INET as i32 }
84 }
85
86 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
145pub type UdpEndpoint = IpEndpoint<Udp>;
147
148pub type UdpSocket = DgramSocket<Udp>;
162
163pub 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}