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.
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.
12 use io::{self, Error, ErrorKind};
13 use net::{ToSocketAddrs, SocketAddr};
14 use sys_common::net as net_imp;
15 use sys_common::{AsInner, FromInner, IntoInner};
18 /// A User Datagram Protocol socket.
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.
27 /// use std::net::UdpSocket;
29 /// # fn foo() -> std::io::Result<()> {
30 /// let mut socket = try!(UdpSocket::bind("127.0.0.1:34254"));
32 /// let mut buf = [0; 10];
33 /// let (amt, src) = try!(socket.recv_from(&mut buf));
35 /// // Send a reply to the socket we received data from
36 /// let buf = &mut buf[..amt];
38 /// try!(socket.send_to(buf, &src));
40 /// drop(socket); // close the socket
44 #[stable(feature = "rust1", since = "1.0.0")]
45 pub struct UdpSocket(net_imp::UdpSocket);
48 /// Creates a UDP socket from the given address.
50 /// The address type can be any implementor of `ToSocketAddr` trait. See
51 /// its documentation for concrete examples.
52 #[stable(feature = "rust1", since = "1.0.0")]
53 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
54 super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
57 /// Receives data from the socket. On success, returns the number of bytes
58 /// read and the address from whence the data came.
59 #[stable(feature = "rust1", since = "1.0.0")]
60 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
64 /// Sends data on the socket to the given address. On success, returns the
65 /// number of bytes written.
67 /// Address type can be any implementor of `ToSocketAddrs` trait. See its
68 /// documentation for concrete examples.
69 #[stable(feature = "rust1", since = "1.0.0")]
70 pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A)
71 -> io::Result<usize> {
72 match try!(addr.to_socket_addrs()).next() {
73 Some(addr) => self.0.send_to(buf, &addr),
74 None => Err(Error::new(ErrorKind::InvalidInput,
75 "no addresses to send data to")),
79 /// Returns the socket address that this socket was created from.
80 #[stable(feature = "rust1", since = "1.0.0")]
81 pub fn local_addr(&self) -> io::Result<SocketAddr> {
85 /// Creates a new independently owned handle to the underlying socket.
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.
90 #[stable(feature = "rust1", since = "1.0.0")]
91 pub fn try_clone(&self) -> io::Result<UdpSocket> {
92 self.0.duplicate().map(UdpSocket)
95 /// Sets the read timeout to the timeout specified.
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
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")]
107 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
108 self.0.set_read_timeout(dur)
111 /// Sets the write timeout to the timeout specified.
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
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")]
123 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
124 self.0.set_write_timeout(dur)
127 /// Returns the read timeout of this socket.
129 /// If the timeout is `None`, then `read` calls will block indefinitely.
130 #[stable(feature = "socket_timeout", since = "1.4.0")]
131 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
132 self.0.read_timeout()
135 /// Returns the write timeout of this socket.
137 /// If the timeout is `None`, then `write` calls will block indefinitely.
138 #[stable(feature = "socket_timeout", since = "1.4.0")]
139 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
140 self.0.write_timeout()
144 impl AsInner<net_imp::UdpSocket> for UdpSocket {
145 fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 }
148 impl FromInner<net_imp::UdpSocket> for UdpSocket {
149 fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) }
152 impl IntoInner<net_imp::UdpSocket> for UdpSocket {
153 fn into_inner(self) -> net_imp::UdpSocket { self.0 }
156 #[stable(feature = "rust1", since = "1.0.0")]
157 impl fmt::Debug for UdpSocket {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169 use net::test::{next_test_ip4, next_test_ip6};
170 use sync::mpsc::channel;
171 use sys_common::AsInner;
175 fn each_ip(f: &mut FnMut(SocketAddr, SocketAddr)) {
176 f(next_test_ip4(), next_test_ip4());
177 f(next_test_ip6(), next_test_ip6());
184 Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
191 match UdpSocket::bind("1.1.1.1:9999") {
194 assert_eq!(e.kind(), ErrorKind::AddrNotAvailable)
200 fn socket_smoke_test_ip4() {
201 each_ip(&mut |server_ip, client_ip| {
202 let (tx1, rx1) = channel();
203 let (tx2, rx2) = channel();
205 let _t = thread::spawn(move|| {
206 let client = t!(UdpSocket::bind(&client_ip));
208 t!(client.send_to(&[99], &server_ip));
209 tx2.send(()).unwrap();
212 let server = t!(UdpSocket::bind(&server_ip));
213 tx1.send(()).unwrap();
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);
224 fn socket_name_ip4() {
225 each_ip(&mut |addr, _| {
226 let server = t!(UdpSocket::bind(&addr));
227 assert_eq!(addr, t!(server.local_addr()));
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));
237 let _t = thread::spawn(move|| {
238 let mut buf = [0, 0];
239 assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
240 assert_eq!(buf[0], 1);
241 t!(sock2.send_to(&[2], &addr1));
244 let sock3 = t!(sock1.try_clone());
246 let (tx1, rx1) = channel();
247 let (tx2, rx2) = channel();
248 let _t = thread::spawn(move|| {
250 t!(sock3.send_to(&[1], &addr2));
251 tx2.send(()).unwrap();
253 tx1.send(()).unwrap();
254 let mut buf = [0, 0];
255 assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2));
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();
268 let _t = thread::spawn(move|| {
269 t!(sock2.send_to(&[1], &addr1));
271 t!(sock2.send_to(&[2], &addr1));
275 let sock3 = t!(sock1.try_clone());
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();
284 let mut buf = [0, 0];
285 t!(sock1.recv_from(&mut buf));
286 tx1.send(()).unwrap();
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));
298 let (tx, rx) = channel();
299 let (serv_tx, serv_rx) = channel();
301 let _t = thread::spawn(move|| {
302 let mut buf = [0, 1];
304 t!(sock2.recv_from(&mut buf));
305 serv_tx.send(()).unwrap();
308 let sock3 = t!(sock1.try_clone());
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(()); }
317 done.send(()).unwrap();
319 match sock1.send_to(&[2], &addr2) {
320 Ok(..) => { let _ = tx.send(()); }
326 serv_rx.recv().unwrap();
332 let name = if cfg!(windows) {"socket"} else {"fd"};
333 let socket_addr = next_test_ip4();
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);
342 // FIXME: re-enabled bitrig/openbsd/netbsd tests once their socket timeout code
343 // no longer has rounding errors.
344 #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)]
347 let addr = next_test_ip4();
349 let stream = t!(UdpSocket::bind(&addr));
350 let dur = Duration::new(15410, 0);
352 assert_eq!(None, t!(stream.read_timeout()));
354 t!(stream.set_read_timeout(Some(dur)));
355 assert_eq!(Some(dur), t!(stream.read_timeout()));
357 assert_eq!(None, t!(stream.write_timeout()));
359 t!(stream.set_write_timeout(Some(dur)));
360 assert_eq!(Some(dur), t!(stream.write_timeout()));
362 t!(stream.set_read_timeout(None));
363 assert_eq!(None, t!(stream.read_timeout()));
365 t!(stream.set_write_timeout(None));
366 assert_eq!(None, t!(stream.write_timeout()));
370 fn test_read_timeout() {
371 let addr = next_test_ip4();
373 let mut stream = t!(UdpSocket::bind(&addr));
374 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
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);
381 assert!(wait > Duration::from_millis(400));
385 fn test_read_with_timeout() {
386 let addr = next_test_ip4();
388 let mut stream = t!(UdpSocket::bind(&addr));
389 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
391 t!(stream.send_to(b"hello world", &addr));
393 let mut buf = [0; 11];
394 t!(stream.recv_from(&mut buf));
395 assert_eq!(b"hello world", &buf[..]);
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);
401 assert!(wait > Duration::from_millis(400));