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