]> git.proxmox.com Git - rustc.git/blame - src/libstd/net/udp.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / libstd / net / udp.rs
CommitLineData
532ac7d7
XL
1use crate::fmt;
2use crate::io::{self, Error, ErrorKind};
60c5eb7d 3use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
532ac7d7
XL
4use crate::sys_common::net as net_imp;
5use crate::sys_common::{AsInner, FromInner, IntoInner};
6use crate::time::Duration;
85aaf69f 7
cc61c64b 8/// A UDP socket.
85aaf69f 9///
cc61c64b
XL
10/// After creating a `UdpSocket` by [`bind`]ing it to a socket address, data can be
11/// [sent to] and [received from] any other socket address.
12///
13/// Although UDP is a connectionless protocol, this implementation provides an interface
14/// to set an address where data should be sent and received from. After setting a remote
15/// address with [`connect`], data can be sent to and received from that address with
16/// [`send`] and [`recv`].
17///
18/// As stated in the User Datagram Protocol's specification in [IETF RFC 768], UDP is
19/// an unordered, unreliable protocol; refer to [`TcpListener`] and [`TcpStream`] for TCP
20/// primitives.
21///
22/// [`bind`]: #method.bind
23/// [`connect`]: #method.connect
24/// [IETF RFC 768]: https://tools.ietf.org/html/rfc768
25/// [`recv`]: #method.recv
26/// [received from]: #method.recv_from
27/// [`send`]: #method.send
28/// [sent to]: #method.send_to
29/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
30/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
85aaf69f 31///
c34b1796 32/// # Examples
85aaf69f
SL
33///
34/// ```no_run
35/// use std::net::UdpSocket;
36///
0531ce1d
XL
37/// fn main() -> std::io::Result<()> {
38/// {
39/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
85aaf69f 40///
0531ce1d
XL
41/// // Receives a single datagram message on the socket. If `buf` is too small to hold
42/// // the message, it will be cut off.
43/// let mut buf = [0; 10];
44/// let (amt, src) = socket.recv_from(&mut buf)?;
85aaf69f 45///
0531ce1d
XL
46/// // Redeclare `buf` as slice of the received data and send reverse data back to origin.
47/// let buf = &mut buf[..amt];
48/// buf.reverse();
49/// socket.send_to(buf, &src)?;
50/// } // the socket is closed here
51/// Ok(())
52/// }
85aaf69f 53/// ```
c34b1796 54#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
55pub struct UdpSocket(net_imp::UdpSocket);
56
57impl UdpSocket {
58 /// Creates a UDP socket from the given address.
59 ///
476ff2be 60 /// The address type can be any implementor of [`ToSocketAddrs`] trait. See
bd371182 61 /// its documentation for concrete examples.
476ff2be 62 ///
ea8adc8c
XL
63 /// If `addr` yields multiple addresses, `bind` will be attempted with
64 /// each of the addresses until one succeeds and returns the socket. If none
65 /// of the addresses succeed in creating a socket, the error returned from
66 /// the last attempt (the last address) is returned.
67 ///
476ff2be
SL
68 /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
69 ///
70 /// # Examples
71 ///
9fa01778 72 /// Creates a UDP socket bound to `127.0.0.1:3400`:
ea8adc8c 73 ///
476ff2be
SL
74 /// ```no_run
75 /// use std::net::UdpSocket;
76 ///
ea8adc8c
XL
77 /// let socket = UdpSocket::bind("127.0.0.1:3400").expect("couldn't bind to address");
78 /// ```
79 ///
9fa01778 80 /// Creates a UDP socket bound to `127.0.0.1:3400`. If the socket cannot be
ea8adc8c
XL
81 /// bound to that address, create a UDP socket bound to `127.0.0.1:3401`:
82 ///
83 /// ```no_run
84 /// use std::net::{SocketAddr, UdpSocket};
85 ///
86 /// let addrs = [
87 /// SocketAddr::from(([127, 0, 0, 1], 3400)),
88 /// SocketAddr::from(([127, 0, 0, 1], 3401)),
89 /// ];
90 /// let socket = UdpSocket::bind(&addrs[..]).expect("couldn't bind to address");
476ff2be 91 /// ```
c34b1796
AL
92 #[stable(feature = "rust1", since = "1.0.0")]
93 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
85aaf69f
SL
94 super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
95 }
96
ea8adc8c
XL
97 /// Receives a single datagram message on the socket. On success, returns the number
98 /// of bytes read and the origin.
99 ///
100 /// The function must be called with valid byte array `buf` of sufficient size to
101 /// hold the message bytes. If a message is too long to fit in the supplied buffer,
102 /// excess bytes may be discarded.
476ff2be
SL
103 ///
104 /// # Examples
105 ///
106 /// ```no_run
107 /// use std::net::UdpSocket;
108 ///
109 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
110 /// let mut buf = [0; 10];
111 /// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf)
112 /// .expect("Didn't receive data");
ea8adc8c 113 /// let filled_buf = &mut buf[..number_of_bytes];
476ff2be 114 /// ```
c34b1796 115 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
116 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
117 self.0.recv_from(buf)
118 }
119
ea8adc8c
XL
120 /// Receives a single datagram message on the socket, without removing it from the
121 /// queue. On success, returns the number of bytes read and the origin.
122 ///
123 /// The function must be called with valid byte array `buf` of sufficient size to
124 /// hold the message bytes. If a message is too long to fit in the supplied buffer,
125 /// excess bytes may be discarded.
8bb4bdeb
XL
126 ///
127 /// Successive calls return the same data. This is accomplished by passing
128 /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
129 ///
ea8adc8c
XL
130 /// Do not use this function to implement busy waiting, instead use `libc::poll` to
131 /// synchronize IO events on one or more sockets.
8bb4bdeb
XL
132 ///
133 /// # Examples
134 ///
135 /// ```no_run
8bb4bdeb
XL
136 /// use std::net::UdpSocket;
137 ///
138 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
139 /// let mut buf = [0; 10];
140 /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
141 /// .expect("Didn't receive data");
ea8adc8c 142 /// let filled_buf = &mut buf[..number_of_bytes];
8bb4bdeb 143 /// ```
cc61c64b 144 #[stable(feature = "peek", since = "1.18.0")]
8bb4bdeb
XL
145 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
146 self.0.peek_from(buf)
147 }
148
bd371182
AL
149 /// Sends data on the socket to the given address. On success, returns the
150 /// number of bytes written.
85aaf69f 151 ///
476ff2be 152 /// Address type can be any implementor of [`ToSocketAddrs`] trait. See its
85aaf69f 153 /// documentation for concrete examples.
476ff2be 154 ///
ea8adc8c
XL
155 /// It is possible for `addr` to yield multiple addresses, but `send_to`
156 /// will only send data to the first address yielded by `addr`.
157 ///
476ff2be
SL
158 /// This will return an error when the IP version of the local socket
159 /// does not match that returned from [`ToSocketAddrs`].
160 ///
9fa01778 161 /// See issue #34202 for more details.
476ff2be
SL
162 ///
163 /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
164 ///
165 /// # Examples
166 ///
167 /// ```no_run
168 /// use std::net::UdpSocket;
169 ///
170 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
171 /// socket.send_to(&[0; 10], "127.0.0.1:4242").expect("couldn't send data");
172 /// ```
c34b1796 173 #[stable(feature = "rust1", since = "1.0.0")]
60c5eb7d 174 pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> {
54a0048b 175 match addr.to_socket_addrs()?.next() {
85aaf69f 176 Some(addr) => self.0.send_to(buf, &addr),
60c5eb7d 177 None => Err(Error::new(ErrorKind::InvalidInput, "no addresses to send data to")),
85aaf69f
SL
178 }
179 }
180
532ac7d7
XL
181 /// Returns the socket address of the remote peer this socket was connected to.
182 ///
183 /// # Examples
184 ///
185 /// ```no_run
532ac7d7
XL
186 /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
187 ///
188 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
189 /// socket.connect("192.168.0.1:41203").expect("couldn't connect to address");
190 /// assert_eq!(socket.peer_addr().unwrap(),
191 /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203)));
192 /// ```
193 ///
194 /// If the socket isn't connected, it will return a [`NotConnected`] error.
195 ///
196 /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected
197 ///
198 /// ```no_run
532ac7d7
XL
199 /// use std::net::UdpSocket;
200 ///
201 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
202 /// assert_eq!(socket.peer_addr().unwrap_err().kind(),
e74abb32 203 /// std::io::ErrorKind::NotConnected);
532ac7d7 204 /// ```
e74abb32 205 #[stable(feature = "udp_peer_addr", since = "1.40.0")]
532ac7d7
XL
206 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
207 self.0.peer_addr()
208 }
209
85aaf69f 210 /// Returns the socket address that this socket was created from.
476ff2be
SL
211 ///
212 /// # Examples
213 ///
214 /// ```no_run
215 /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
216 ///
217 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
218 /// assert_eq!(socket.local_addr().unwrap(),
219 /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 34254)));
220 /// ```
c34b1796
AL
221 #[stable(feature = "rust1", since = "1.0.0")]
222 pub fn local_addr(&self) -> io::Result<SocketAddr> {
85aaf69f
SL
223 self.0.socket_addr()
224 }
225
9346a6ac 226 /// Creates a new independently owned handle to the underlying socket.
85aaf69f
SL
227 ///
228 /// The returned `UdpSocket` is a reference to the same socket that this
229 /// object references. Both handles will read and write the same port, and
230 /// options set on one socket will be propagated to the other.
476ff2be
SL
231 ///
232 /// # Examples
233 ///
234 /// ```no_run
235 /// use std::net::UdpSocket;
236 ///
237 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
238 /// let socket_clone = socket.try_clone().expect("couldn't clone the socket");
239 /// ```
c34b1796 240 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
241 pub fn try_clone(&self) -> io::Result<UdpSocket> {
242 self.0.duplicate().map(UdpSocket)
243 }
244
62682a34
SL
245 /// Sets the read timeout to the timeout specified.
246 ///
cc61c64b 247 /// If the value specified is [`None`], then [`read`] calls will block
0531ce1d
XL
248 /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
249 /// passed to this method.
e9174d1e 250 ///
0531ce1d 251 /// # Platform-specific behavior
e9174d1e
SL
252 ///
253 /// Platforms may return a different error code whenever a read times out as
254 /// a result of setting this option. For example Unix typically returns an
476ff2be
SL
255 /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
256 ///
257 /// [`None`]: ../../std/option/enum.Option.html#variant.None
0531ce1d 258 /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
cc61c64b 259 /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
476ff2be
SL
260 /// [`Duration`]: ../../std/time/struct.Duration.html
261 /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
262 /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
263 ///
264 /// # Examples
265 ///
266 /// ```no_run
267 /// use std::net::UdpSocket;
268 ///
269 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
270 /// socket.set_read_timeout(None).expect("set_read_timeout call failed");
271 /// ```
0531ce1d
XL
272 ///
273 /// An [`Err`] is returned if the zero [`Duration`] is passed to this
274 /// method:
275 ///
276 /// ```no_run
277 /// use std::io;
278 /// use std::net::UdpSocket;
279 /// use std::time::Duration;
280 ///
281 /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
282 /// let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
283 /// let err = result.unwrap_err();
284 /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
285 /// ```
e9174d1e 286 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
287 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
288 self.0.set_read_timeout(dur)
289 }
290
291 /// Sets the write timeout to the timeout specified.
292 ///
cc61c64b 293 /// If the value specified is [`None`], then [`write`] calls will block
0531ce1d
XL
294 /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
295 /// passed to this method.
e9174d1e 296 ///
0531ce1d 297 /// # Platform-specific behavior
e9174d1e
SL
298 ///
299 /// Platforms may return a different error code whenever a write times out
300 /// as a result of setting this option. For example Unix typically returns
476ff2be
SL
301 /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
302 ///
303 /// [`None`]: ../../std/option/enum.Option.html#variant.None
0531ce1d 304 /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
cc61c64b 305 /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
476ff2be
SL
306 /// [`Duration`]: ../../std/time/struct.Duration.html
307 /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
308 /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
309 ///
310 /// # Examples
311 ///
312 /// ```no_run
313 /// use std::net::UdpSocket;
314 ///
315 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
316 /// socket.set_write_timeout(None).expect("set_write_timeout call failed");
317 /// ```
0531ce1d
XL
318 ///
319 /// An [`Err`] is returned if the zero [`Duration`] is passed to this
320 /// method:
321 ///
322 /// ```no_run
323 /// use std::io;
324 /// use std::net::UdpSocket;
325 /// use std::time::Duration;
326 ///
327 /// let socket = UdpSocket::bind("127.0.0.1:34254").unwrap();
328 /// let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
329 /// let err = result.unwrap_err();
330 /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
331 /// ```
e9174d1e 332 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
333 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
334 self.0.set_write_timeout(dur)
335 }
336
337 /// Returns the read timeout of this socket.
338 ///
cc61c64b 339 /// If the timeout is [`None`], then [`read`] calls will block indefinitely.
476ff2be
SL
340 ///
341 /// [`None`]: ../../std/option/enum.Option.html#variant.None
cc61c64b 342 /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
476ff2be
SL
343 ///
344 /// # Examples
345 ///
346 /// ```no_run
347 /// use std::net::UdpSocket;
348 ///
349 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
350 /// socket.set_read_timeout(None).expect("set_read_timeout call failed");
351 /// assert_eq!(socket.read_timeout().unwrap(), None);
352 /// ```
e9174d1e 353 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
354 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
355 self.0.read_timeout()
356 }
357
358 /// Returns the write timeout of this socket.
359 ///
cc61c64b 360 /// If the timeout is [`None`], then [`write`] calls will block indefinitely.
476ff2be
SL
361 ///
362 /// [`None`]: ../../std/option/enum.Option.html#variant.None
cc61c64b 363 /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
476ff2be
SL
364 ///
365 /// # Examples
366 ///
367 /// ```no_run
368 /// use std::net::UdpSocket;
369 ///
370 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
371 /// socket.set_write_timeout(None).expect("set_write_timeout call failed");
372 /// assert_eq!(socket.write_timeout().unwrap(), None);
373 /// ```
e9174d1e 374 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
375 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
376 self.0.write_timeout()
377 }
54a0048b
SL
378
379 /// Sets the value of the `SO_BROADCAST` option for this socket.
380 ///
381 /// When enabled, this socket is allowed to send packets to a broadcast
382 /// address.
476ff2be
SL
383 ///
384 /// # Examples
385 ///
386 /// ```no_run
387 /// use std::net::UdpSocket;
388 ///
389 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
390 /// socket.set_broadcast(false).expect("set_broadcast call failed");
391 /// ```
54a0048b
SL
392 #[stable(feature = "net2_mutators", since = "1.9.0")]
393 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
394 self.0.set_broadcast(broadcast)
395 }
396
397 /// Gets the value of the `SO_BROADCAST` option for this socket.
398 ///
399 /// For more information about this option, see
400 /// [`set_broadcast`][link].
401 ///
402 /// [link]: #method.set_broadcast
476ff2be
SL
403 ///
404 /// # Examples
405 ///
406 /// ```no_run
407 /// use std::net::UdpSocket;
408 ///
409 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
410 /// socket.set_broadcast(false).expect("set_broadcast call failed");
411 /// assert_eq!(socket.broadcast().unwrap(), false);
412 /// ```
54a0048b
SL
413 #[stable(feature = "net2_mutators", since = "1.9.0")]
414 pub fn broadcast(&self) -> io::Result<bool> {
415 self.0.broadcast()
416 }
417
418 /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
419 ///
420 /// If enabled, multicast packets will be looped back to the local socket.
416331ca 421 /// Note that this may not have any effect on IPv6 sockets.
476ff2be
SL
422 ///
423 /// # Examples
424 ///
425 /// ```no_run
426 /// use std::net::UdpSocket;
427 ///
428 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
429 /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed");
430 /// ```
54a0048b
SL
431 #[stable(feature = "net2_mutators", since = "1.9.0")]
432 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
433 self.0.set_multicast_loop_v4(multicast_loop_v4)
434 }
435
436 /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
437 ///
438 /// For more information about this option, see
439 /// [`set_multicast_loop_v4`][link].
440 ///
441 /// [link]: #method.set_multicast_loop_v4
476ff2be
SL
442 ///
443 /// # Examples
444 ///
445 /// ```no_run
446 /// use std::net::UdpSocket;
447 ///
448 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
449 /// socket.set_multicast_loop_v4(false).expect("set_multicast_loop_v4 call failed");
450 /// assert_eq!(socket.multicast_loop_v4().unwrap(), false);
451 /// ```
54a0048b
SL
452 #[stable(feature = "net2_mutators", since = "1.9.0")]
453 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
454 self.0.multicast_loop_v4()
455 }
456
457 /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
458 ///
459 /// Indicates the time-to-live value of outgoing multicast packets for
460 /// this socket. The default value is 1 which means that multicast packets
461 /// don't leave the local network unless explicitly requested.
462 ///
416331ca 463 /// Note that this may not have any effect on IPv6 sockets.
476ff2be
SL
464 ///
465 /// # Examples
466 ///
467 /// ```no_run
468 /// use std::net::UdpSocket;
469 ///
470 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
471 /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed");
472 /// ```
54a0048b
SL
473 #[stable(feature = "net2_mutators", since = "1.9.0")]
474 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
475 self.0.set_multicast_ttl_v4(multicast_ttl_v4)
476 }
477
478 /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
479 ///
480 /// For more information about this option, see
481 /// [`set_multicast_ttl_v4`][link].
482 ///
483 /// [link]: #method.set_multicast_ttl_v4
476ff2be
SL
484 ///
485 /// # Examples
486 ///
487 /// ```no_run
488 /// use std::net::UdpSocket;
489 ///
490 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
491 /// socket.set_multicast_ttl_v4(42).expect("set_multicast_ttl_v4 call failed");
492 /// assert_eq!(socket.multicast_ttl_v4().unwrap(), 42);
493 /// ```
54a0048b
SL
494 #[stable(feature = "net2_mutators", since = "1.9.0")]
495 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
496 self.0.multicast_ttl_v4()
497 }
498
499 /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
500 ///
501 /// Controls whether this socket sees the multicast packets it sends itself.
502 /// Note that this may not have any affect on IPv4 sockets.
476ff2be
SL
503 ///
504 /// # Examples
505 ///
506 /// ```no_run
507 /// use std::net::UdpSocket;
508 ///
509 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
510 /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed");
511 /// ```
54a0048b
SL
512 #[stable(feature = "net2_mutators", since = "1.9.0")]
513 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
514 self.0.set_multicast_loop_v6(multicast_loop_v6)
515 }
516
517 /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
518 ///
519 /// For more information about this option, see
520 /// [`set_multicast_loop_v6`][link].
521 ///
522 /// [link]: #method.set_multicast_loop_v6
476ff2be
SL
523 ///
524 /// # Examples
525 ///
526 /// ```no_run
527 /// use std::net::UdpSocket;
528 ///
529 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
530 /// socket.set_multicast_loop_v6(false).expect("set_multicast_loop_v6 call failed");
531 /// assert_eq!(socket.multicast_loop_v6().unwrap(), false);
532 /// ```
54a0048b
SL
533 #[stable(feature = "net2_mutators", since = "1.9.0")]
534 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
535 self.0.multicast_loop_v6()
536 }
537
538 /// Sets the value for the `IP_TTL` option on this socket.
539 ///
540 /// This value sets the time-to-live field that is used in every packet sent
541 /// from this socket.
476ff2be
SL
542 ///
543 /// # Examples
544 ///
545 /// ```no_run
546 /// use std::net::UdpSocket;
547 ///
548 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
549 /// socket.set_ttl(42).expect("set_ttl call failed");
550 /// ```
54a0048b
SL
551 #[stable(feature = "net2_mutators", since = "1.9.0")]
552 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
553 self.0.set_ttl(ttl)
554 }
555
556 /// Gets the value of the `IP_TTL` option for this socket.
557 ///
558 /// For more information about this option, see [`set_ttl`][link].
559 ///
560 /// [link]: #method.set_ttl
476ff2be
SL
561 ///
562 /// # Examples
563 ///
564 /// ```no_run
565 /// use std::net::UdpSocket;
566 ///
567 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
568 /// socket.set_ttl(42).expect("set_ttl call failed");
569 /// assert_eq!(socket.ttl().unwrap(), 42);
570 /// ```
54a0048b
SL
571 #[stable(feature = "net2_mutators", since = "1.9.0")]
572 pub fn ttl(&self) -> io::Result<u32> {
573 self.0.ttl()
574 }
575
576 /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
577 ///
578 /// This function specifies a new multicast group for this socket to join.
579 /// The address must be a valid multicast address, and `interface` is the
580 /// address of the local interface with which the system should join the
581 /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
582 /// interface is chosen by the system.
583 #[stable(feature = "net2_mutators", since = "1.9.0")]
584 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
585 self.0.join_multicast_v4(multiaddr, interface)
586 }
587
588 /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
589 ///
590 /// This function specifies a new multicast group for this socket to join.
591 /// The address must be a valid multicast address, and `interface` is the
592 /// index of the interface to join/leave (or 0 to indicate any interface).
593 #[stable(feature = "net2_mutators", since = "1.9.0")]
594 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
595 self.0.join_multicast_v6(multiaddr, interface)
596 }
597
598 /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
599 ///
600 /// For more information about this option, see
601 /// [`join_multicast_v4`][link].
602 ///
603 /// [link]: #method.join_multicast_v4
604 #[stable(feature = "net2_mutators", since = "1.9.0")]
605 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
606 self.0.leave_multicast_v4(multiaddr, interface)
607 }
608
609 /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
610 ///
611 /// For more information about this option, see
612 /// [`join_multicast_v6`][link].
613 ///
614 /// [link]: #method.join_multicast_v6
615 #[stable(feature = "net2_mutators", since = "1.9.0")]
616 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
617 self.0.leave_multicast_v6(multiaddr, interface)
618 }
619
9fa01778 620 /// Gets the value of the `SO_ERROR` option on this socket.
54a0048b
SL
621 ///
622 /// This will retrieve the stored error in the underlying socket, clearing
623 /// the field in the process. This can be useful for checking errors between
624 /// calls.
476ff2be
SL
625 ///
626 /// # Examples
627 ///
628 /// ```no_run
629 /// use std::net::UdpSocket;
630 ///
631 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
632 /// match socket.take_error() {
633 /// Ok(Some(error)) => println!("UdpSocket error: {:?}", error),
634 /// Ok(None) => println!("No error"),
635 /// Err(error) => println!("UdpSocket.take_error failed: {:?}", error),
636 /// }
637 /// ```
54a0048b
SL
638 #[stable(feature = "net2_mutators", since = "1.9.0")]
639 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
640 self.0.take_error()
641 }
642
643 /// Connects this UDP socket to a remote address, allowing the `send` and
644 /// `recv` syscalls to be used to send data and also applies filters to only
645 /// receive data from the specified address.
476ff2be 646 ///
ea8adc8c
XL
647 /// If `addr` yields multiple addresses, `connect` will be attempted with
648 /// each of the addresses until the underlying OS function returns no
649 /// error. Note that usually, a successful `connect` call does not specify
650 /// that there is a remote server listening on the port, rather, such an
651 /// error would only be detected after the first send. If the OS returns an
652 /// error for each of the specified addresses, the error returned from the
653 /// last connection attempt (the last address) is returned.
654 ///
476ff2be
SL
655 /// # Examples
656 ///
9fa01778 657 /// Creates a UDP socket bound to `127.0.0.1:3400` and connect the socket to
ea8adc8c
XL
658 /// `127.0.0.1:8080`:
659 ///
476ff2be
SL
660 /// ```no_run
661 /// use std::net::UdpSocket;
662 ///
ea8adc8c 663 /// let socket = UdpSocket::bind("127.0.0.1:3400").expect("couldn't bind to address");
476ff2be
SL
664 /// socket.connect("127.0.0.1:8080").expect("connect function failed");
665 /// ```
ea8adc8c
XL
666 ///
667 /// Unlike in the TCP case, passing an array of addresses to the `connect`
668 /// function of a UDP socket is not a useful thing to do: The OS will be
669 /// unable to determine whether something is listening on the remote
670 /// address without the application sending data.
54a0048b
SL
671 #[stable(feature = "net2_mutators", since = "1.9.0")]
672 pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
673 super::each_addr(addr, |addr| self.0.connect(addr))
674 }
675
676 /// Sends data on the socket to the remote address to which it is connected.
677 ///
cc61c64b 678 /// The [`connect`] method will connect this socket to a remote address. This
54a0048b 679 /// method will fail if the socket is not connected.
476ff2be 680 ///
cc61c64b 681 /// [`connect`]: #method.connect
476ff2be
SL
682 ///
683 /// # Examples
684 ///
685 /// ```no_run
686 /// use std::net::UdpSocket;
687 ///
688 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
689 /// socket.connect("127.0.0.1:8080").expect("connect function failed");
690 /// socket.send(&[0, 1, 2]).expect("couldn't send message");
691 /// ```
54a0048b
SL
692 #[stable(feature = "net2_mutators", since = "1.9.0")]
693 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
694 self.0.send(buf)
695 }
696
ea8adc8c
XL
697 /// Receives a single datagram message on the socket from the remote address to
698 /// which it is connected. On success, returns the number of bytes read.
699 ///
700 /// The function must be called with valid byte array `buf` of sufficient size to
701 /// hold the message bytes. If a message is too long to fit in the supplied buffer,
702 /// excess bytes may be discarded.
54a0048b 703 ///
cc61c64b 704 /// The [`connect`] method will connect this socket to a remote address. This
54a0048b 705 /// method will fail if the socket is not connected.
476ff2be 706 ///
cc61c64b
XL
707 /// [`connect`]: #method.connect
708 ///
476ff2be
SL
709 /// # Examples
710 ///
711 /// ```no_run
712 /// use std::net::UdpSocket;
713 ///
714 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
715 /// socket.connect("127.0.0.1:8080").expect("connect function failed");
716 /// let mut buf = [0; 10];
717 /// match socket.recv(&mut buf) {
ea8adc8c 718 /// Ok(received) => println!("received {} bytes {:?}", received, &buf[..received]),
476ff2be
SL
719 /// Err(e) => println!("recv function failed: {:?}", e),
720 /// }
721 /// ```
54a0048b
SL
722 #[stable(feature = "net2_mutators", since = "1.9.0")]
723 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
724 self.0.recv(buf)
725 }
726
ea8adc8c
XL
727 /// Receives single datagram on the socket from the remote address to which it is
728 /// connected, without removing the message from input queue. On success, returns
729 /// the number of bytes peeked.
730 ///
731 /// The function must be called with valid byte array `buf` of sufficient size to
732 /// hold the message bytes. If a message is too long to fit in the supplied buffer,
733 /// excess bytes may be discarded.
8bb4bdeb
XL
734 ///
735 /// Successive calls return the same data. This is accomplished by passing
736 /// `MSG_PEEK` as a flag to the underlying `recv` system call.
737 ///
ea8adc8c
XL
738 /// Do not use this function to implement busy waiting, instead use `libc::poll` to
739 /// synchronize IO events on one or more sockets.
740 ///
741 /// The [`connect`] method will connect this socket to a remote address. This
742 /// method will fail if the socket is not connected.
743 ///
744 /// [`connect`]: #method.connect
745 ///
8bb4bdeb
XL
746 /// # Errors
747 ///
748 /// This method will fail if the socket is not connected. The `connect` method
749 /// will connect this socket to a remote address.
750 ///
751 /// # Examples
752 ///
753 /// ```no_run
8bb4bdeb
XL
754 /// use std::net::UdpSocket;
755 ///
756 /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
757 /// socket.connect("127.0.0.1:8080").expect("connect function failed");
758 /// let mut buf = [0; 10];
759 /// match socket.peek(&mut buf) {
760 /// Ok(received) => println!("received {} bytes", received),
761 /// Err(e) => println!("peek function failed: {:?}", e),
762 /// }
763 /// ```
cc61c64b 764 #[stable(feature = "peek", since = "1.18.0")]
8bb4bdeb
XL
765 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
766 self.0.peek(buf)
767 }
768
a7813a04 769 /// Moves this UDP socket into or out of nonblocking mode.
54a0048b 770 ///
abe05a73 771 /// This will result in `recv`, `recv_from`, `send`, and `send_to`
0731742a 772 /// operations becoming nonblocking, i.e., immediately returning from their
abe05a73
XL
773 /// calls. If the IO operation is successful, `Ok` is returned and no
774 /// further action is required. If the IO operation could not be completed
775 /// and needs to be retried, an error with kind
776 /// [`io::ErrorKind::WouldBlock`] is returned.
777 ///
778 /// On Unix platforms, calling this method corresponds to calling `fcntl`
779 /// `FIONBIO`. On Windows calling this method corresponds to calling
780 /// `ioctlsocket` `FIONBIO`.
781 ///
782 /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
476ff2be
SL
783 ///
784 /// # Examples
785 ///
9fa01778 786 /// Creates a UDP socket bound to `127.0.0.1:7878` and read bytes in
abe05a73
XL
787 /// nonblocking mode:
788 ///
476ff2be 789 /// ```no_run
abe05a73 790 /// use std::io;
476ff2be
SL
791 /// use std::net::UdpSocket;
792 ///
abe05a73
XL
793 /// let socket = UdpSocket::bind("127.0.0.1:7878").unwrap();
794 /// socket.set_nonblocking(true).unwrap();
795 ///
796 /// # fn wait_for_fd() { unimplemented!() }
797 /// let mut buf = [0; 10];
798 /// let (num_bytes_read, _) = loop {
799 /// match socket.recv_from(&mut buf) {
800 /// Ok(n) => break n,
801 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
802 /// // wait until network socket is ready, typically implemented
803 /// // via platform-specific APIs such as epoll or IOCP
804 /// wait_for_fd();
805 /// }
806 /// Err(e) => panic!("encountered IO error: {}", e),
807 /// }
808 /// };
809 /// println!("bytes: {:?}", &buf[..num_bytes_read]);
476ff2be 810 /// ```
54a0048b
SL
811 #[stable(feature = "net2_mutators", since = "1.9.0")]
812 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
813 self.0.set_nonblocking(nonblocking)
814 }
85aaf69f
SL
815}
816
817impl AsInner<net_imp::UdpSocket> for UdpSocket {
60c5eb7d
XL
818 fn as_inner(&self) -> &net_imp::UdpSocket {
819 &self.0
820 }
85aaf69f
SL
821}
822
c34b1796 823impl FromInner<net_imp::UdpSocket> for UdpSocket {
60c5eb7d
XL
824 fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket {
825 UdpSocket(inner)
826 }
c34b1796
AL
827}
828
c1a9b12d 829impl IntoInner<net_imp::UdpSocket> for UdpSocket {
60c5eb7d
XL
830 fn into_inner(self) -> net_imp::UdpSocket {
831 self.0
832 }
c1a9b12d
SL
833}
834
92a42be0 835#[stable(feature = "rust1", since = "1.0.0")]
d9579d0f 836impl fmt::Debug for UdpSocket {
532ac7d7 837 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
d9579d0f
AL
838 self.0.fmt(f)
839 }
840}
841
532ac7d7 842#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
85aaf69f 843mod tests {
532ac7d7 844 use crate::io::ErrorKind;
532ac7d7 845 use crate::net::test::{next_test_ip4, next_test_ip6};
60c5eb7d 846 use crate::net::*;
532ac7d7
XL
847 use crate::sync::mpsc::channel;
848 use crate::sys_common::AsInner;
532ac7d7 849 use crate::thread;
60c5eb7d 850 use crate::time::{Duration, Instant};
85aaf69f 851
8faf50e0 852 fn each_ip(f: &mut dyn FnMut(SocketAddr, SocketAddr)) {
85aaf69f
SL
853 f(next_test_ip4(), next_test_ip4());
854 f(next_test_ip6(), next_test_ip6());
855 }
856
857 macro_rules! t {
858 ($e:expr) => {
859 match $e {
860 Ok(t) => t,
861 Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
862 }
60c5eb7d 863 };
85aaf69f
SL
864 }
865
85aaf69f
SL
866 #[test]
867 fn bind_error() {
b039eaaf 868 match UdpSocket::bind("1.1.1.1:9999") {
85aaf69f 869 Ok(..) => panic!(),
60c5eb7d 870 Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
85aaf69f
SL
871 }
872 }
873
874 #[test]
875 fn socket_smoke_test_ip4() {
876 each_ip(&mut |server_ip, client_ip| {
877 let (tx1, rx1) = channel();
878 let (tx2, rx2) = channel();
879
60c5eb7d 880 let _t = thread::spawn(move || {
85aaf69f
SL
881 let client = t!(UdpSocket::bind(&client_ip));
882 rx1.recv().unwrap();
883 t!(client.send_to(&[99], &server_ip));
884 tx2.send(()).unwrap();
885 });
886
887 let server = t!(UdpSocket::bind(&server_ip));
888 tx1.send(()).unwrap();
889 let mut buf = [0];
890 let (nread, src) = t!(server.recv_from(&mut buf));
891 assert_eq!(nread, 1);
892 assert_eq!(buf[0], 99);
893 assert_eq!(src, client_ip);
894 rx2.recv().unwrap();
895 })
896 }
897
898 #[test]
532ac7d7 899 fn socket_name() {
85aaf69f
SL
900 each_ip(&mut |addr, _| {
901 let server = t!(UdpSocket::bind(&addr));
c34b1796 902 assert_eq!(addr, t!(server.local_addr()));
85aaf69f
SL
903 })
904 }
905
532ac7d7
XL
906 #[test]
907 fn socket_peer() {
908 each_ip(&mut |addr1, addr2| {
909 let server = t!(UdpSocket::bind(&addr1));
910 assert_eq!(server.peer_addr().unwrap_err().kind(), ErrorKind::NotConnected);
911 t!(server.connect(&addr2));
912 assert_eq!(addr2, t!(server.peer_addr()));
913 })
914 }
915
85aaf69f
SL
916 #[test]
917 fn udp_clone_smoke() {
918 each_ip(&mut |addr1, addr2| {
919 let sock1 = t!(UdpSocket::bind(&addr1));
920 let sock2 = t!(UdpSocket::bind(&addr2));
921
60c5eb7d 922 let _t = thread::spawn(move || {
85aaf69f 923 let mut buf = [0, 0];
c34b1796 924 assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
85aaf69f
SL
925 assert_eq!(buf[0], 1);
926 t!(sock2.send_to(&[2], &addr1));
927 });
928
929 let sock3 = t!(sock1.try_clone());
930
931 let (tx1, rx1) = channel();
932 let (tx2, rx2) = channel();
60c5eb7d 933 let _t = thread::spawn(move || {
85aaf69f
SL
934 rx1.recv().unwrap();
935 t!(sock3.send_to(&[1], &addr2));
936 tx2.send(()).unwrap();
937 });
938 tx1.send(()).unwrap();
939 let mut buf = [0, 0];
c34b1796 940 assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2));
85aaf69f
SL
941 rx2.recv().unwrap();
942 })
943 }
944
945 #[test]
946 fn udp_clone_two_read() {
947 each_ip(&mut |addr1, addr2| {
948 let sock1 = t!(UdpSocket::bind(&addr1));
949 let sock2 = t!(UdpSocket::bind(&addr2));
950 let (tx1, rx) = channel();
951 let tx2 = tx1.clone();
952
60c5eb7d 953 let _t = thread::spawn(move || {
85aaf69f
SL
954 t!(sock2.send_to(&[1], &addr1));
955 rx.recv().unwrap();
956 t!(sock2.send_to(&[2], &addr1));
957 rx.recv().unwrap();
958 });
959
960 let sock3 = t!(sock1.try_clone());
961
962 let (done, rx) = channel();
60c5eb7d 963 let _t = thread::spawn(move || {
85aaf69f
SL
964 let mut buf = [0, 0];
965 t!(sock3.recv_from(&mut buf));
966 tx2.send(()).unwrap();
967 done.send(()).unwrap();
968 });
969 let mut buf = [0, 0];
970 t!(sock1.recv_from(&mut buf));
971 tx1.send(()).unwrap();
972
973 rx.recv().unwrap();
974 })
975 }
976
977 #[test]
978 fn udp_clone_two_write() {
979 each_ip(&mut |addr1, addr2| {
980 let sock1 = t!(UdpSocket::bind(&addr1));
981 let sock2 = t!(UdpSocket::bind(&addr2));
982
983 let (tx, rx) = channel();
984 let (serv_tx, serv_rx) = channel();
985
60c5eb7d 986 let _t = thread::spawn(move || {
85aaf69f
SL
987 let mut buf = [0, 1];
988 rx.recv().unwrap();
989 t!(sock2.recv_from(&mut buf));
990 serv_tx.send(()).unwrap();
991 });
992
993 let sock3 = t!(sock1.try_clone());
994
995 let (done, rx) = channel();
996 let tx2 = tx.clone();
60c5eb7d 997 let _t = thread::spawn(move || {
85aaf69f 998 match sock3.send_to(&[1], &addr2) {
60c5eb7d
XL
999 Ok(..) => {
1000 let _ = tx2.send(());
1001 }
85aaf69f
SL
1002 Err(..) => {}
1003 }
1004 done.send(()).unwrap();
1005 });
1006 match sock1.send_to(&[2], &addr2) {
60c5eb7d
XL
1007 Ok(..) => {
1008 let _ = tx.send(());
1009 }
85aaf69f
SL
1010 Err(..) => {}
1011 }
1012 drop(tx);
1013
1014 rx.recv().unwrap();
1015 serv_rx.recv().unwrap();
1016 })
1017 }
d9579d0f
AL
1018
1019 #[test]
1020 fn debug() {
60c5eb7d 1021 let name = if cfg!(windows) { "socket" } else { "fd" };
d9579d0f
AL
1022 let socket_addr = next_test_ip4();
1023
1024 let udpsock = t!(UdpSocket::bind(&socket_addr));
1025 let udpsock_inner = udpsock.0.socket().as_inner();
60c5eb7d
XL
1026 let compare =
1027 format!("UdpSocket {{ addr: {:?}, {}: {:?} }}", socket_addr, name, udpsock_inner);
d9579d0f
AL
1028 assert_eq!(format!("{:?}", udpsock), compare);
1029 }
62682a34 1030
48663c56 1031 // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
62682a34 1032 // no longer has rounding errors.
e1599b0c
XL
1033 // VxWorks ignores SO_SNDTIMEO.
1034 #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
62682a34
SL
1035 #[test]
1036 fn timeouts() {
1037 let addr = next_test_ip4();
1038
1039 let stream = t!(UdpSocket::bind(&addr));
1040 let dur = Duration::new(15410, 0);
1041
1042 assert_eq!(None, t!(stream.read_timeout()));
1043
1044 t!(stream.set_read_timeout(Some(dur)));
1045 assert_eq!(Some(dur), t!(stream.read_timeout()));
1046
1047 assert_eq!(None, t!(stream.write_timeout()));
1048
1049 t!(stream.set_write_timeout(Some(dur)));
1050 assert_eq!(Some(dur), t!(stream.write_timeout()));
1051
1052 t!(stream.set_read_timeout(None));
1053 assert_eq!(None, t!(stream.read_timeout()));
1054
1055 t!(stream.set_write_timeout(None));
1056 assert_eq!(None, t!(stream.write_timeout()));
1057 }
1058
1059 #[test]
1060 fn test_read_timeout() {
1061 let addr = next_test_ip4();
1062
9cc50fc6 1063 let stream = t!(UdpSocket::bind(&addr));
62682a34
SL
1064 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
1065
1066 let mut buf = [0; 10];
9cc50fc6
SL
1067
1068 let start = Instant::now();
a1dfa0c6
XL
1069 loop {
1070 let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
1071 if kind != ErrorKind::Interrupted {
60c5eb7d
XL
1072 assert!(
1073 kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
1074 "unexpected_error: {:?}",
1075 kind
1076 );
a1dfa0c6
XL
1077 break;
1078 }
1079 }
9cc50fc6 1080 assert!(start.elapsed() > Duration::from_millis(400));
62682a34
SL
1081 }
1082
1083 #[test]
1084 fn test_read_with_timeout() {
1085 let addr = next_test_ip4();
1086
9cc50fc6 1087 let stream = t!(UdpSocket::bind(&addr));
62682a34
SL
1088 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
1089
1090 t!(stream.send_to(b"hello world", &addr));
1091
1092 let mut buf = [0; 11];
1093 t!(stream.recv_from(&mut buf));
1094 assert_eq!(b"hello world", &buf[..]);
1095
9cc50fc6 1096 let start = Instant::now();
a1dfa0c6
XL
1097 loop {
1098 let kind = stream.recv_from(&mut buf).err().expect("expected error").kind();
1099 if kind != ErrorKind::Interrupted {
60c5eb7d
XL
1100 assert!(
1101 kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
1102 "unexpected_error: {:?}",
1103 kind
1104 );
a1dfa0c6
XL
1105 break;
1106 }
1107 }
9cc50fc6 1108 assert!(start.elapsed() > Duration::from_millis(400));
62682a34 1109 }
54a0048b 1110
0531ce1d
XL
1111 // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
1112 // when passed zero Durations
1113 #[test]
1114 fn test_timeout_zero_duration() {
1115 let addr = next_test_ip4();
1116
1117 let socket = t!(UdpSocket::bind(&addr));
1118
1119 let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
1120 let err = result.unwrap_err();
1121 assert_eq!(err.kind(), ErrorKind::InvalidInput);
1122
1123 let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
1124 let err = result.unwrap_err();
1125 assert_eq!(err.kind(), ErrorKind::InvalidInput);
1126 }
1127
54a0048b
SL
1128 #[test]
1129 fn connect_send_recv() {
1130 let addr = next_test_ip4();
1131
1132 let socket = t!(UdpSocket::bind(&addr));
1133 t!(socket.connect(addr));
1134
1135 t!(socket.send(b"hello world"));
1136
1137 let mut buf = [0; 11];
1138 t!(socket.recv(&mut buf));
1139 assert_eq!(b"hello world", &buf[..]);
1140 }
1141
8bb4bdeb
XL
1142 #[test]
1143 fn connect_send_peek_recv() {
1144 each_ip(&mut |addr, _| {
1145 let socket = t!(UdpSocket::bind(&addr));
1146 t!(socket.connect(addr));
1147
1148 t!(socket.send(b"hello world"));
1149
1150 for _ in 1..3 {
1151 let mut buf = [0; 11];
1152 let size = t!(socket.peek(&mut buf));
1153 assert_eq!(b"hello world", &buf[..]);
1154 assert_eq!(size, 11);
1155 }
1156
1157 let mut buf = [0; 11];
1158 let size = t!(socket.recv(&mut buf));
1159 assert_eq!(b"hello world", &buf[..]);
1160 assert_eq!(size, 11);
1161 })
1162 }
1163
1164 #[test]
1165 fn peek_from() {
1166 each_ip(&mut |addr, _| {
1167 let socket = t!(UdpSocket::bind(&addr));
1168 t!(socket.send_to(b"hello world", &addr));
1169
1170 for _ in 1..3 {
1171 let mut buf = [0; 11];
1172 let (size, _) = t!(socket.peek_from(&mut buf));
1173 assert_eq!(b"hello world", &buf[..]);
1174 assert_eq!(size, 11);
1175 }
1176
1177 let mut buf = [0; 11];
1178 let (size, _) = t!(socket.recv_from(&mut buf));
1179 assert_eq!(b"hello world", &buf[..]);
1180 assert_eq!(size, 11);
1181 })
1182 }
1183
54a0048b
SL
1184 #[test]
1185 fn ttl() {
1186 let ttl = 100;
1187
1188 let addr = next_test_ip4();
1189
1190 let stream = t!(UdpSocket::bind(&addr));
1191
1192 t!(stream.set_ttl(ttl));
1193 assert_eq!(ttl, t!(stream.ttl()));
1194 }
1195
1196 #[test]
1197 fn set_nonblocking() {
32a655c1
SL
1198 each_ip(&mut |addr, _| {
1199 let socket = t!(UdpSocket::bind(&addr));
54a0048b 1200
32a655c1
SL
1201 t!(socket.set_nonblocking(true));
1202 t!(socket.set_nonblocking(false));
1203
1204 t!(socket.connect(addr));
54a0048b 1205
32a655c1
SL
1206 t!(socket.set_nonblocking(false));
1207 t!(socket.set_nonblocking(true));
1208
1209 let mut buf = [0];
1210 match socket.recv(&mut buf) {
1211 Ok(_) => panic!("expected error"),
1212 Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
1213 Err(e) => panic!("unexpected error {}", e),
1214 }
1215 })
54a0048b 1216 }
85aaf69f 1217}