]> git.proxmox.com Git - rustc.git/blame - src/libstd/net/udp.rs
Imported Upstream version 1.4.0+dfsg1
[rustc.git] / src / libstd / net / udp.rs
CommitLineData
85aaf69f
SL
1// Copyright 2015 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
d9579d0f 11use fmt;
85aaf69f 12use io::{self, Error, ErrorKind};
e9174d1e 13use net::{ToSocketAddrs, SocketAddr};
d9579d0f 14use sys_common::net as net_imp;
c1a9b12d 15use sys_common::{AsInner, FromInner, IntoInner};
62682a34 16use time::Duration;
85aaf69f
SL
17
18/// A User Datagram Protocol socket.
19///
20/// This is an implementation of a bound UDP socket. This supports both IPv4 and
21/// IPv6 addresses, and there is no corresponding notion of a server because UDP
22/// is a datagram protocol.
23///
c34b1796 24/// # Examples
85aaf69f
SL
25///
26/// ```no_run
27/// use std::net::UdpSocket;
28///
29/// # fn foo() -> std::io::Result<()> {
30/// let mut socket = try!(UdpSocket::bind("127.0.0.1:34254"));
31///
32/// let mut buf = [0; 10];
33/// let (amt, src) = try!(socket.recv_from(&mut buf));
34///
35/// // Send a reply to the socket we received data from
36/// let buf = &mut buf[..amt];
37/// buf.reverse();
38/// try!(socket.send_to(buf, &src));
39///
40/// drop(socket); // close the socket
41/// # Ok(())
42/// # }
43/// ```
c34b1796 44#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
45pub struct UdpSocket(net_imp::UdpSocket);
46
47impl UdpSocket {
48 /// Creates a UDP socket from the given address.
49 ///
bd371182
AL
50 /// The address type can be any implementor of `ToSocketAddr` trait. See
51 /// its documentation for concrete examples.
c34b1796
AL
52 #[stable(feature = "rust1", since = "1.0.0")]
53 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
85aaf69f
SL
54 super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
55 }
56
57 /// Receives data from the socket. On success, returns the number of bytes
58 /// read and the address from whence the data came.
c34b1796 59 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
60 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
61 self.0.recv_from(buf)
62 }
63
bd371182
AL
64 /// Sends data on the socket to the given address. On success, returns the
65 /// number of bytes written.
85aaf69f
SL
66 ///
67 /// Address type can be any implementor of `ToSocketAddrs` trait. See its
68 /// documentation for concrete examples.
c34b1796
AL
69 #[stable(feature = "rust1", since = "1.0.0")]
70 pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A)
71 -> io::Result<usize> {
85aaf69f
SL
72 match try!(addr.to_socket_addrs()).next() {
73 Some(addr) => self.0.send_to(buf, &addr),
74 None => Err(Error::new(ErrorKind::InvalidInput,
c34b1796 75 "no addresses to send data to")),
85aaf69f
SL
76 }
77 }
78
79 /// Returns the socket address that this socket was created from.
c34b1796
AL
80 #[stable(feature = "rust1", since = "1.0.0")]
81 pub fn local_addr(&self) -> io::Result<SocketAddr> {
85aaf69f
SL
82 self.0.socket_addr()
83 }
84
9346a6ac 85 /// Creates a new independently owned handle to the underlying socket.
85aaf69f
SL
86 ///
87 /// The returned `UdpSocket` is a reference to the same socket that this
88 /// object references. Both handles will read and write the same port, and
89 /// options set on one socket will be propagated to the other.
c34b1796 90 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
91 pub fn try_clone(&self) -> io::Result<UdpSocket> {
92 self.0.duplicate().map(UdpSocket)
93 }
94
62682a34
SL
95 /// Sets the read timeout to the timeout specified.
96 ///
97 /// If the value specified is `None`, then `read` calls will block
98 /// indefinitely. It is an error to pass the zero `Duration` to this
99 /// method.
e9174d1e
SL
100 ///
101 /// # Note
102 ///
103 /// Platforms may return a different error code whenever a read times out as
104 /// a result of setting this option. For example Unix typically returns an
105 /// error of the kind `WouldBlock`, but Windows may return `TimedOut`.
106 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
107 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
108 self.0.set_read_timeout(dur)
109 }
110
111 /// Sets the write timeout to the timeout specified.
112 ///
113 /// If the value specified is `None`, then `write` calls will block
114 /// indefinitely. It is an error to pass the zero `Duration` to this
115 /// method.
e9174d1e
SL
116 ///
117 /// # Note
118 ///
119 /// Platforms may return a different error code whenever a write times out
120 /// as a result of setting this option. For example Unix typically returns
121 /// an error of the kind `WouldBlock`, but Windows may return `TimedOut`.
122 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
123 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
124 self.0.set_write_timeout(dur)
125 }
126
127 /// Returns the read timeout of this socket.
128 ///
129 /// If the timeout is `None`, then `read` calls will block indefinitely.
e9174d1e 130 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
131 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
132 self.0.read_timeout()
133 }
134
135 /// Returns the write timeout of this socket.
136 ///
137 /// If the timeout is `None`, then `write` calls will block indefinitely.
e9174d1e 138 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
139 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
140 self.0.write_timeout()
141 }
85aaf69f
SL
142}
143
144impl AsInner<net_imp::UdpSocket> for UdpSocket {
145 fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 }
146}
147
c34b1796
AL
148impl FromInner<net_imp::UdpSocket> for UdpSocket {
149 fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) }
150}
151
c1a9b12d
SL
152impl IntoInner<net_imp::UdpSocket> for UdpSocket {
153 fn into_inner(self) -> net_imp::UdpSocket { self.0 }
154}
155
d9579d0f
AL
156impl fmt::Debug for UdpSocket {
157 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158 self.0.fmt(f)
159 }
160}
161
85aaf69f
SL
162#[cfg(test)]
163mod tests {
164 use prelude::v1::*;
165
166 use io::ErrorKind;
167 use net::*;
168 use net::test::{next_test_ip4, next_test_ip6};
169 use sync::mpsc::channel;
d9579d0f 170 use sys_common::AsInner;
62682a34 171 use time::Duration;
85aaf69f
SL
172 use thread;
173
174 fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) {
175 f(next_test_ip4(), next_test_ip4());
176 f(next_test_ip6(), next_test_ip6());
177 }
178
179 macro_rules! t {
180 ($e:expr) => {
181 match $e {
182 Ok(t) => t,
183 Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
184 }
185 }
186 }
187
188 // FIXME #11530 this fails on android because tests are run as root
189 #[cfg_attr(any(windows, target_os = "android"), ignore)]
190 #[test]
191 fn bind_error() {
c34b1796 192 let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 1);
85aaf69f
SL
193 match UdpSocket::bind(&addr) {
194 Ok(..) => panic!(),
195 Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied),
196 }
197 }
198
199 #[test]
200 fn socket_smoke_test_ip4() {
201 each_ip(&mut |server_ip, client_ip| {
202 let (tx1, rx1) = channel();
203 let (tx2, rx2) = channel();
204
205 let _t = thread::spawn(move|| {
206 let client = t!(UdpSocket::bind(&client_ip));
207 rx1.recv().unwrap();
208 t!(client.send_to(&[99], &server_ip));
209 tx2.send(()).unwrap();
210 });
211
212 let server = t!(UdpSocket::bind(&server_ip));
213 tx1.send(()).unwrap();
214 let mut buf = [0];
215 let (nread, src) = t!(server.recv_from(&mut buf));
216 assert_eq!(nread, 1);
217 assert_eq!(buf[0], 99);
218 assert_eq!(src, client_ip);
219 rx2.recv().unwrap();
220 })
221 }
222
223 #[test]
224 fn socket_name_ip4() {
225 each_ip(&mut |addr, _| {
226 let server = t!(UdpSocket::bind(&addr));
c34b1796 227 assert_eq!(addr, t!(server.local_addr()));
85aaf69f
SL
228 })
229 }
230
231 #[test]
232 fn udp_clone_smoke() {
233 each_ip(&mut |addr1, addr2| {
234 let sock1 = t!(UdpSocket::bind(&addr1));
235 let sock2 = t!(UdpSocket::bind(&addr2));
236
237 let _t = thread::spawn(move|| {
238 let mut buf = [0, 0];
c34b1796 239 assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
85aaf69f
SL
240 assert_eq!(buf[0], 1);
241 t!(sock2.send_to(&[2], &addr1));
242 });
243
244 let sock3 = t!(sock1.try_clone());
245
246 let (tx1, rx1) = channel();
247 let (tx2, rx2) = channel();
248 let _t = thread::spawn(move|| {
249 rx1.recv().unwrap();
250 t!(sock3.send_to(&[1], &addr2));
251 tx2.send(()).unwrap();
252 });
253 tx1.send(()).unwrap();
254 let mut buf = [0, 0];
c34b1796 255 assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2));
85aaf69f
SL
256 rx2.recv().unwrap();
257 })
258 }
259
260 #[test]
261 fn udp_clone_two_read() {
262 each_ip(&mut |addr1, addr2| {
263 let sock1 = t!(UdpSocket::bind(&addr1));
264 let sock2 = t!(UdpSocket::bind(&addr2));
265 let (tx1, rx) = channel();
266 let tx2 = tx1.clone();
267
268 let _t = thread::spawn(move|| {
269 t!(sock2.send_to(&[1], &addr1));
270 rx.recv().unwrap();
271 t!(sock2.send_to(&[2], &addr1));
272 rx.recv().unwrap();
273 });
274
275 let sock3 = t!(sock1.try_clone());
276
277 let (done, rx) = channel();
278 let _t = thread::spawn(move|| {
279 let mut buf = [0, 0];
280 t!(sock3.recv_from(&mut buf));
281 tx2.send(()).unwrap();
282 done.send(()).unwrap();
283 });
284 let mut buf = [0, 0];
285 t!(sock1.recv_from(&mut buf));
286 tx1.send(()).unwrap();
287
288 rx.recv().unwrap();
289 })
290 }
291
292 #[test]
293 fn udp_clone_two_write() {
294 each_ip(&mut |addr1, addr2| {
295 let sock1 = t!(UdpSocket::bind(&addr1));
296 let sock2 = t!(UdpSocket::bind(&addr2));
297
298 let (tx, rx) = channel();
299 let (serv_tx, serv_rx) = channel();
300
301 let _t = thread::spawn(move|| {
302 let mut buf = [0, 1];
303 rx.recv().unwrap();
304 t!(sock2.recv_from(&mut buf));
305 serv_tx.send(()).unwrap();
306 });
307
308 let sock3 = t!(sock1.try_clone());
309
310 let (done, rx) = channel();
311 let tx2 = tx.clone();
312 let _t = thread::spawn(move|| {
313 match sock3.send_to(&[1], &addr2) {
314 Ok(..) => { let _ = tx2.send(()); }
315 Err(..) => {}
316 }
317 done.send(()).unwrap();
318 });
319 match sock1.send_to(&[2], &addr2) {
320 Ok(..) => { let _ = tx.send(()); }
321 Err(..) => {}
322 }
323 drop(tx);
324
325 rx.recv().unwrap();
326 serv_rx.recv().unwrap();
327 })
328 }
d9579d0f
AL
329
330 #[test]
331 fn debug() {
332 let name = if cfg!(windows) {"socket"} else {"fd"};
333 let socket_addr = next_test_ip4();
334
335 let udpsock = t!(UdpSocket::bind(&socket_addr));
336 let udpsock_inner = udpsock.0.socket().as_inner();
337 let compare = format!("UdpSocket {{ addr: {:?}, {}: {:?} }}",
338 socket_addr, name, udpsock_inner);
339 assert_eq!(format!("{:?}", udpsock), compare);
340 }
62682a34 341
c1a9b12d 342 // FIXME: re-enabled bitrig/openbsd/netbsd tests once their socket timeout code
62682a34 343 // no longer has rounding errors.
c1a9b12d 344 #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
62682a34
SL
345 #[test]
346 fn timeouts() {
347 let addr = next_test_ip4();
348
349 let stream = t!(UdpSocket::bind(&addr));
350 let dur = Duration::new(15410, 0);
351
352 assert_eq!(None, t!(stream.read_timeout()));
353
354 t!(stream.set_read_timeout(Some(dur)));
355 assert_eq!(Some(dur), t!(stream.read_timeout()));
356
357 assert_eq!(None, t!(stream.write_timeout()));
358
359 t!(stream.set_write_timeout(Some(dur)));
360 assert_eq!(Some(dur), t!(stream.write_timeout()));
361
362 t!(stream.set_read_timeout(None));
363 assert_eq!(None, t!(stream.read_timeout()));
364
365 t!(stream.set_write_timeout(None));
366 assert_eq!(None, t!(stream.write_timeout()));
367 }
368
369 #[test]
370 fn test_read_timeout() {
371 let addr = next_test_ip4();
372
373 let mut stream = t!(UdpSocket::bind(&addr));
374 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
375
376 let mut buf = [0; 10];
377 let wait = Duration::span(|| {
378 let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
379 assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
380 });
381 assert!(wait > Duration::from_millis(400));
62682a34
SL
382 }
383
384 #[test]
385 fn test_read_with_timeout() {
386 let addr = next_test_ip4();
387
388 let mut stream = t!(UdpSocket::bind(&addr));
389 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
390
391 t!(stream.send_to(b"hello world", &addr));
392
393 let mut buf = [0; 11];
394 t!(stream.recv_from(&mut buf));
395 assert_eq!(b"hello world", &buf[..]);
396
397 let wait = Duration::span(|| {
398 let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
399 assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut);
400 });
401 assert!(wait > Duration::from_millis(400));
62682a34 402 }
85aaf69f 403}