]> git.proxmox.com Git - rustc.git/blame - src/libstd/net/tcp.rs
New upstream version 1.42.0+dfsg1
[rustc.git] / src / libstd / net / tcp.rs
CommitLineData
532ac7d7 1use crate::io::prelude::*;
85aaf69f 2
532ac7d7 3use crate::fmt;
48663c56 4use crate::io::{self, Initializer, IoSlice, IoSliceMut};
60c5eb7d 5use crate::net::{Shutdown, SocketAddr, ToSocketAddrs};
532ac7d7
XL
6use crate::sys_common::net as net_imp;
7use crate::sys_common::{AsInner, FromInner, IntoInner};
8use crate::time::Duration;
85aaf69f 9
cc61c64b 10/// A TCP stream between a local and a remote socket.
85aaf69f 11///
cc61c64b
XL
12/// After creating a `TcpStream` by either [`connect`]ing to a remote host or
13/// [`accept`]ing a connection on a [`TcpListener`], data can be transmitted
14/// by [reading] and [writing] to it.
15///
16/// The connection will be closed when the value is dropped. The reading and writing
17/// portions of the connection can also be shut down individually with the [`shutdown`]
18/// method.
19///
20/// The Transmission Control Protocol is specified in [IETF RFC 793].
21///
22/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
23/// [`connect`]: #method.connect
24/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
25/// [reading]: ../../std/io/trait.Read.html
26/// [`shutdown`]: #method.shutdown
27/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
28/// [writing]: ../../std/io/trait.Write.html
85aaf69f 29///
c34b1796 30/// # Examples
85aaf69f
SL
31///
32/// ```no_run
33/// use std::io::prelude::*;
34/// use std::net::TcpStream;
35///
0bf4aa26
XL
36/// fn main() -> std::io::Result<()> {
37/// let mut stream = TcpStream::connect("127.0.0.1:34254")?;
85aaf69f 38///
0bf4aa26
XL
39/// stream.write(&[1])?;
40/// stream.read(&mut [0; 128])?;
41/// Ok(())
85aaf69f
SL
42/// } // the stream is closed here
43/// ```
c34b1796 44#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
45pub struct TcpStream(net_imp::TcpStream);
46
cc61c64b
XL
47/// A TCP socket server, listening for connections.
48///
49/// After creating a `TcpListener` by [`bind`]ing it to a socket address, it listens
50/// for incoming TCP connections. These can be accepted by calling [`accept`] or by
51/// iterating over the [`Incoming`] iterator returned by [`incoming`][`TcpListener::incoming`].
52///
53/// The socket will be closed when the value is dropped.
54///
55/// The Transmission Control Protocol is specified in [IETF RFC 793].
56///
57/// [`accept`]: #method.accept
58/// [`bind`]: #method.bind
59/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
60/// [`Incoming`]: ../../std/net/struct.Incoming.html
61/// [`TcpListener::incoming`]: #method.incoming
85aaf69f
SL
62///
63/// # Examples
64///
0531ce1d 65/// ```no_run
85aaf69f 66/// use std::net::{TcpListener, TcpStream};
85aaf69f 67///
85aaf69f
SL
68/// fn handle_client(stream: TcpStream) {
69/// // ...
70/// }
71///
dfeec247 72/// fn main() -> std::io::Result<()> {
8faf50e0 73/// let listener = TcpListener::bind("127.0.0.1:80")?;
7cac9316 74///
0531ce1d
XL
75/// // accept connections and process them serially
76/// for stream in listener.incoming() {
77/// handle_client(stream?);
78/// }
79/// Ok(())
85aaf69f 80/// }
85aaf69f 81/// ```
c34b1796 82#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
83pub struct TcpListener(net_imp::TcpListener);
84
cc61c64b 85/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
5bcae85e
SL
86///
87/// This `struct` is created by the [`incoming`] method on [`TcpListener`].
cc61c64b 88/// See its documentation for more.
5bcae85e 89///
cc61c64b
XL
90/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
91/// [`incoming`]: ../../std/net/struct.TcpListener.html#method.incoming
92/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
c34b1796 93#[stable(feature = "rust1", since = "1.0.0")]
32a655c1 94#[derive(Debug)]
60c5eb7d
XL
95pub struct Incoming<'a> {
96 listener: &'a TcpListener,
97}
85aaf69f
SL
98
99impl TcpStream {
9346a6ac 100 /// Opens a TCP connection to a remote host.
85aaf69f
SL
101 ///
102 /// `addr` is an address of the remote host. Anything which implements
cc61c64b 103 /// [`ToSocketAddrs`] trait can be supplied for the address; see this trait
85aaf69f 104 /// documentation for concrete examples.
ea8adc8c
XL
105 ///
106 /// If `addr` yields multiple addresses, `connect` will be attempted with
107 /// each of the addresses until a connection is successful. If none of
108 /// the addresses result in a successful connection, the error returned from
109 /// the last connection attempt (the last address) is returned.
476ff2be 110 ///
cc61c64b 111 /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
cc61c64b 112 ///
476ff2be
SL
113 /// # Examples
114 ///
ea8adc8c
XL
115 /// Open a TCP connection to `127.0.0.1:8080`:
116 ///
476ff2be
SL
117 /// ```no_run
118 /// use std::net::TcpStream;
119 ///
120 /// if let Ok(stream) = TcpStream::connect("127.0.0.1:8080") {
121 /// println!("Connected to the server!");
122 /// } else {
123 /// println!("Couldn't connect to server...");
124 /// }
125 /// ```
ea8adc8c
XL
126 ///
127 /// Open a TCP connection to `127.0.0.1:8080`. If the connection fails, open
128 /// a TCP connection to `127.0.0.1:8081`:
129 ///
130 /// ```no_run
131 /// use std::net::{SocketAddr, TcpStream};
132 ///
133 /// let addrs = [
134 /// SocketAddr::from(([127, 0, 0, 1], 8080)),
135 /// SocketAddr::from(([127, 0, 0, 1], 8081)),
136 /// ];
137 /// if let Ok(stream) = TcpStream::connect(&addrs[..]) {
138 /// println!("Connected to the server!");
139 /// } else {
140 /// println!("Couldn't connect to server...");
141 /// }
142 /// ```
c34b1796
AL
143 #[stable(feature = "rust1", since = "1.0.0")]
144 pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
85aaf69f
SL
145 super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream)
146 }
147
041b39d2
XL
148 /// Opens a TCP connection to a remote host with a timeout.
149 ///
150 /// Unlike `connect`, `connect_timeout` takes a single [`SocketAddr`] since
151 /// timeout must be applied to individual addresses.
152 ///
153 /// It is an error to pass a zero `Duration` to this function.
154 ///
155 /// Unlike other methods on `TcpStream`, this does not correspond to a
156 /// single system call. It instead calls `connect` in nonblocking mode and
157 /// then uses an OS-specific mechanism to await the completion of the
158 /// connection request.
159 ///
160 /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
3b2f2976 161 #[stable(feature = "tcpstream_connect_timeout", since = "1.21.0")]
041b39d2
XL
162 pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
163 net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
164 }
165
85aaf69f 166 /// Returns the socket address of the remote peer of this TCP connection.
476ff2be
SL
167 ///
168 /// # Examples
169 ///
170 /// ```no_run
171 /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream};
172 ///
173 /// let stream = TcpStream::connect("127.0.0.1:8080")
174 /// .expect("Couldn't connect to the server...");
175 /// assert_eq!(stream.peer_addr().unwrap(),
176 /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
177 /// ```
c34b1796 178 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
179 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
180 self.0.peer_addr()
181 }
182
183 /// Returns the socket address of the local half of this TCP connection.
476ff2be
SL
184 ///
185 /// # Examples
186 ///
187 /// ```no_run
ea8adc8c 188 /// use std::net::{IpAddr, Ipv4Addr, TcpStream};
476ff2be
SL
189 ///
190 /// let stream = TcpStream::connect("127.0.0.1:8080")
191 /// .expect("Couldn't connect to the server...");
ea8adc8c
XL
192 /// assert_eq!(stream.local_addr().unwrap().ip(),
193 /// IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
476ff2be 194 /// ```
c34b1796
AL
195 #[stable(feature = "rust1", since = "1.0.0")]
196 pub fn local_addr(&self) -> io::Result<SocketAddr> {
85aaf69f
SL
197 self.0.socket_addr()
198 }
199
9346a6ac 200 /// Shuts down the read, write, or both halves of this connection.
85aaf69f
SL
201 ///
202 /// This function will cause all pending and future I/O on the specified
203 /// portions to return immediately with an appropriate value (see the
476ff2be
SL
204 /// documentation of [`Shutdown`]).
205 ///
206 /// [`Shutdown`]: ../../std/net/enum.Shutdown.html
207 ///
7cac9316
XL
208 /// # Platform-specific behavior
209 ///
210 /// Calling this function multiple times may result in different behavior,
211 /// depending on the operating system. On Linux, the second call will
212 /// return `Ok(())`, but on macOS, it will return `ErrorKind::NotConnected`.
213 /// This may change in the future.
214 ///
476ff2be
SL
215 /// # Examples
216 ///
217 /// ```no_run
218 /// use std::net::{Shutdown, TcpStream};
219 ///
220 /// let stream = TcpStream::connect("127.0.0.1:8080")
221 /// .expect("Couldn't connect to the server...");
222 /// stream.shutdown(Shutdown::Both).expect("shutdown call failed");
223 /// ```
c34b1796 224 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
225 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
226 self.0.shutdown(how)
227 }
228
9346a6ac 229 /// Creates a new independently owned handle to the underlying socket.
85aaf69f
SL
230 ///
231 /// The returned `TcpStream` is a reference to the same stream that this
232 /// object references. Both handles will read and write the same stream of
233 /// data, and options set on one stream will be propagated to the other
234 /// stream.
476ff2be
SL
235 ///
236 /// # Examples
237 ///
238 /// ```no_run
239 /// use std::net::TcpStream;
240 ///
241 /// let stream = TcpStream::connect("127.0.0.1:8080")
242 /// .expect("Couldn't connect to the server...");
243 /// let stream_clone = stream.try_clone().expect("clone failed...");
244 /// ```
c34b1796 245 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
246 pub fn try_clone(&self) -> io::Result<TcpStream> {
247 self.0.duplicate().map(TcpStream)
248 }
249
62682a34
SL
250 /// Sets the read timeout to the timeout specified.
251 ///
cc61c64b 252 /// If the value specified is [`None`], then [`read`] calls will block
0531ce1d
XL
253 /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
254 /// passed to this method.
e9174d1e 255 ///
0531ce1d 256 /// # Platform-specific behavior
e9174d1e
SL
257 ///
258 /// Platforms may return a different error code whenever a read times out as
259 /// a result of setting this option. For example Unix typically returns an
476ff2be
SL
260 /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
261 ///
262 /// [`None`]: ../../std/option/enum.Option.html#variant.None
0531ce1d 263 /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
cc61c64b 264 /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
476ff2be
SL
265 /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
266 /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
0531ce1d 267 /// [`Duration`]: ../../std/time/struct.Duration.html
476ff2be
SL
268 ///
269 /// # Examples
270 ///
271 /// ```no_run
272 /// use std::net::TcpStream;
273 ///
274 /// let stream = TcpStream::connect("127.0.0.1:8080")
275 /// .expect("Couldn't connect to the server...");
276 /// stream.set_read_timeout(None).expect("set_read_timeout call failed");
277 /// ```
0531ce1d
XL
278 ///
279 /// An [`Err`] is returned if the zero [`Duration`] is passed to this
280 /// method:
281 ///
282 /// ```no_run
283 /// use std::io;
284 /// use std::net::TcpStream;
285 /// use std::time::Duration;
286 ///
287 /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
288 /// let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
289 /// let err = result.unwrap_err();
290 /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
291 /// ```
e9174d1e 292 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
293 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
294 self.0.set_read_timeout(dur)
295 }
296
297 /// Sets the write timeout to the timeout specified.
298 ///
cc61c64b 299 /// If the value specified is [`None`], then [`write`] calls will block
0531ce1d
XL
300 /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
301 /// passed to this method.
e9174d1e 302 ///
0531ce1d 303 /// # Platform-specific behavior
e9174d1e
SL
304 ///
305 /// Platforms may return a different error code whenever a write times out
306 /// as a result of setting this option. For example Unix typically returns
476ff2be
SL
307 /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`].
308 ///
309 /// [`None`]: ../../std/option/enum.Option.html#variant.None
0531ce1d 310 /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
cc61c64b 311 /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
476ff2be
SL
312 /// [`Duration`]: ../../std/time/struct.Duration.html
313 /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock
314 /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut
315 ///
316 /// # Examples
317 ///
318 /// ```no_run
319 /// use std::net::TcpStream;
320 ///
321 /// let stream = TcpStream::connect("127.0.0.1:8080")
322 /// .expect("Couldn't connect to the server...");
323 /// stream.set_write_timeout(None).expect("set_write_timeout call failed");
324 /// ```
0531ce1d
XL
325 ///
326 /// An [`Err`] is returned if the zero [`Duration`] is passed to this
327 /// method:
328 ///
329 /// ```no_run
330 /// use std::io;
331 /// use std::net::TcpStream;
332 /// use std::time::Duration;
333 ///
334 /// let stream = TcpStream::connect("127.0.0.1:8080").unwrap();
335 /// let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
336 /// let err = result.unwrap_err();
337 /// assert_eq!(err.kind(), io::ErrorKind::InvalidInput)
338 /// ```
e9174d1e 339 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
340 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
341 self.0.set_write_timeout(dur)
342 }
343
344 /// Returns the read timeout of this socket.
345 ///
cc61c64b 346 /// If the timeout is [`None`], then [`read`] calls will block indefinitely.
62682a34 347 ///
0531ce1d 348 /// # Platform-specific behavior
62682a34
SL
349 ///
350 /// Some platforms do not provide access to the current timeout.
476ff2be
SL
351 ///
352 /// [`None`]: ../../std/option/enum.Option.html#variant.None
cc61c64b 353 /// [`read`]: ../../std/io/trait.Read.html#tymethod.read
476ff2be
SL
354 ///
355 /// # Examples
356 ///
357 /// ```no_run
358 /// use std::net::TcpStream;
359 ///
360 /// let stream = TcpStream::connect("127.0.0.1:8080")
361 /// .expect("Couldn't connect to the server...");
362 /// stream.set_read_timeout(None).expect("set_read_timeout call failed");
363 /// assert_eq!(stream.read_timeout().unwrap(), None);
364 /// ```
e9174d1e 365 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
366 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
367 self.0.read_timeout()
368 }
369
370 /// Returns the write timeout of this socket.
371 ///
cc61c64b 372 /// If the timeout is [`None`], then [`write`] calls will block indefinitely.
62682a34 373 ///
0531ce1d 374 /// # Platform-specific behavior
62682a34
SL
375 ///
376 /// Some platforms do not provide access to the current timeout.
476ff2be
SL
377 ///
378 /// [`None`]: ../../std/option/enum.Option.html#variant.None
cc61c64b 379 /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
476ff2be
SL
380 ///
381 /// # Examples
382 ///
383 /// ```no_run
384 /// use std::net::TcpStream;
385 ///
386 /// let stream = TcpStream::connect("127.0.0.1:8080")
387 /// .expect("Couldn't connect to the server...");
388 /// stream.set_write_timeout(None).expect("set_write_timeout call failed");
389 /// assert_eq!(stream.write_timeout().unwrap(), None);
390 /// ```
e9174d1e 391 #[stable(feature = "socket_timeout", since = "1.4.0")]
62682a34
SL
392 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
393 self.0.write_timeout()
394 }
54a0048b 395
3b2f2976 396 /// Receives data on the socket from the remote address to which it is
8bb4bdeb
XL
397 /// connected, without removing that data from the queue. On success,
398 /// returns the number of bytes peeked.
399 ///
400 /// Successive calls return the same data. This is accomplished by passing
401 /// `MSG_PEEK` as a flag to the underlying `recv` system call.
402 ///
403 /// # Examples
404 ///
405 /// ```no_run
8bb4bdeb
XL
406 /// use std::net::TcpStream;
407 ///
408 /// let stream = TcpStream::connect("127.0.0.1:8000")
409 /// .expect("couldn't bind to address");
410 /// let mut buf = [0; 10];
411 /// let len = stream.peek(&mut buf).expect("peek failed");
412 /// ```
cc61c64b 413 #[stable(feature = "peek", since = "1.18.0")]
8bb4bdeb
XL
414 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
415 self.0.peek(buf)
416 }
417
54a0048b
SL
418 /// Sets the value of the `TCP_NODELAY` option on this socket.
419 ///
420 /// If set, this option disables the Nagle algorithm. This means that
421 /// segments are always sent as soon as possible, even if there is only a
422 /// small amount of data. When not set, data is buffered until there is a
423 /// sufficient amount to send out, thereby avoiding the frequent sending of
424 /// small packets.
476ff2be
SL
425 ///
426 /// # Examples
427 ///
428 /// ```no_run
429 /// use std::net::TcpStream;
430 ///
431 /// let stream = TcpStream::connect("127.0.0.1:8080")
432 /// .expect("Couldn't connect to the server...");
433 /// stream.set_nodelay(true).expect("set_nodelay call failed");
434 /// ```
54a0048b
SL
435 #[stable(feature = "net2_mutators", since = "1.9.0")]
436 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
437 self.0.set_nodelay(nodelay)
438 }
439
440 /// Gets the value of the `TCP_NODELAY` option on this socket.
441 ///
442 /// For more information about this option, see [`set_nodelay`][link].
443 ///
444 /// [link]: #method.set_nodelay
476ff2be
SL
445 ///
446 /// # Examples
447 ///
448 /// ```no_run
449 /// use std::net::TcpStream;
450 ///
451 /// let stream = TcpStream::connect("127.0.0.1:8080")
452 /// .expect("Couldn't connect to the server...");
453 /// stream.set_nodelay(true).expect("set_nodelay call failed");
454 /// assert_eq!(stream.nodelay().unwrap_or(false), true);
455 /// ```
54a0048b
SL
456 #[stable(feature = "net2_mutators", since = "1.9.0")]
457 pub fn nodelay(&self) -> io::Result<bool> {
458 self.0.nodelay()
459 }
460
461 /// Sets the value for the `IP_TTL` option on this socket.
462 ///
463 /// This value sets the time-to-live field that is used in every packet sent
464 /// from this socket.
476ff2be
SL
465 ///
466 /// # Examples
467 ///
468 /// ```no_run
469 /// use std::net::TcpStream;
470 ///
471 /// let stream = TcpStream::connect("127.0.0.1:8080")
472 /// .expect("Couldn't connect to the server...");
473 /// stream.set_ttl(100).expect("set_ttl call failed");
474 /// ```
54a0048b
SL
475 #[stable(feature = "net2_mutators", since = "1.9.0")]
476 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
477 self.0.set_ttl(ttl)
478 }
479
480 /// Gets the value of the `IP_TTL` option for this socket.
481 ///
482 /// For more information about this option, see [`set_ttl`][link].
483 ///
484 /// [link]: #method.set_ttl
476ff2be
SL
485 ///
486 /// # Examples
487 ///
488 /// ```no_run
489 /// use std::net::TcpStream;
490 ///
491 /// let stream = TcpStream::connect("127.0.0.1:8080")
492 /// .expect("Couldn't connect to the server...");
493 /// stream.set_ttl(100).expect("set_ttl call failed");
494 /// assert_eq!(stream.ttl().unwrap_or(0), 100);
495 /// ```
54a0048b
SL
496 #[stable(feature = "net2_mutators", since = "1.9.0")]
497 pub fn ttl(&self) -> io::Result<u32> {
498 self.0.ttl()
499 }
500
9fa01778 501 /// Gets the value of the `SO_ERROR` option on this socket.
54a0048b
SL
502 ///
503 /// This will retrieve the stored error in the underlying socket, clearing
504 /// the field in the process. This can be useful for checking errors between
505 /// calls.
476ff2be
SL
506 ///
507 /// # Examples
508 ///
509 /// ```no_run
510 /// use std::net::TcpStream;
511 ///
512 /// let stream = TcpStream::connect("127.0.0.1:8080")
513 /// .expect("Couldn't connect to the server...");
514 /// stream.take_error().expect("No error was expected...");
515 /// ```
54a0048b
SL
516 #[stable(feature = "net2_mutators", since = "1.9.0")]
517 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
518 self.0.take_error()
519 }
520
521 /// Moves this TCP stream into or out of nonblocking mode.
522 ///
abe05a73 523 /// This will result in `read`, `write`, `recv` and `send` operations
0731742a 524 /// becoming nonblocking, i.e., immediately returning from their calls.
abe05a73
XL
525 /// If the IO operation is successful, `Ok` is returned and no further
526 /// action is required. If the IO operation could not be completed and needs
527 /// to be retried, an error with kind [`io::ErrorKind::WouldBlock`] is
528 /// returned.
529 ///
530 /// On Unix platforms, calling this method corresponds to calling `fcntl`
531 /// `FIONBIO`. On Windows calling this method corresponds to calling
532 /// `ioctlsocket` `FIONBIO`.
476ff2be
SL
533 ///
534 /// # Examples
535 ///
abe05a73
XL
536 /// Reading bytes from a TCP stream in non-blocking mode:
537 ///
476ff2be 538 /// ```no_run
abe05a73 539 /// use std::io::{self, Read};
476ff2be
SL
540 /// use std::net::TcpStream;
541 ///
abe05a73
XL
542 /// let mut stream = TcpStream::connect("127.0.0.1:7878")
543 /// .expect("Couldn't connect to the server...");
476ff2be 544 /// stream.set_nonblocking(true).expect("set_nonblocking call failed");
abe05a73
XL
545 ///
546 /// # fn wait_for_fd() { unimplemented!() }
547 /// let mut buf = vec![];
548 /// loop {
549 /// match stream.read_to_end(&mut buf) {
550 /// Ok(_) => break,
551 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
552 /// // wait until network socket is ready, typically implemented
553 /// // via platform-specific APIs such as epoll or IOCP
554 /// wait_for_fd();
555 /// }
556 /// Err(e) => panic!("encountered IO error: {}", e),
557 /// };
558 /// };
559 /// println!("bytes: {:?}", buf);
476ff2be 560 /// ```
abe05a73
XL
561 ///
562 /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
54a0048b
SL
563 #[stable(feature = "net2_mutators", since = "1.9.0")]
564 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
565 self.0.set_nonblocking(nonblocking)
566 }
85aaf69f
SL
567}
568
c34b1796 569#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 570impl Read for TcpStream {
60c5eb7d
XL
571 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
572 self.0.read(buf)
573 }
041b39d2 574
48663c56 575 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
9fa01778
XL
576 self.0.read_vectored(bufs)
577 }
578
041b39d2
XL
579 #[inline]
580 unsafe fn initializer(&self) -> Initializer {
581 Initializer::nop()
c1a9b12d 582 }
85aaf69f 583}
c34b1796 584#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 585impl Write for TcpStream {
60c5eb7d
XL
586 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
587 self.0.write(buf)
588 }
9fa01778 589
48663c56 590 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
9fa01778
XL
591 self.0.write_vectored(bufs)
592 }
593
60c5eb7d
XL
594 fn flush(&mut self) -> io::Result<()> {
595 Ok(())
596 }
85aaf69f 597}
c34b1796 598#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 599impl Read for &TcpStream {
60c5eb7d
XL
600 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
601 self.0.read(buf)
602 }
041b39d2 603
48663c56 604 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
9fa01778
XL
605 self.0.read_vectored(bufs)
606 }
607
041b39d2
XL
608 #[inline]
609 unsafe fn initializer(&self) -> Initializer {
610 Initializer::nop()
c1a9b12d 611 }
85aaf69f 612}
c34b1796 613#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 614impl Write for &TcpStream {
60c5eb7d
XL
615 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
616 self.0.write(buf)
617 }
9fa01778 618
48663c56 619 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
9fa01778
XL
620 self.0.write_vectored(bufs)
621 }
622
60c5eb7d
XL
623 fn flush(&mut self) -> io::Result<()> {
624 Ok(())
625 }
85aaf69f
SL
626}
627
628impl AsInner<net_imp::TcpStream> for TcpStream {
60c5eb7d
XL
629 fn as_inner(&self) -> &net_imp::TcpStream {
630 &self.0
631 }
85aaf69f
SL
632}
633
c34b1796 634impl FromInner<net_imp::TcpStream> for TcpStream {
60c5eb7d
XL
635 fn from_inner(inner: net_imp::TcpStream) -> TcpStream {
636 TcpStream(inner)
637 }
c34b1796
AL
638}
639
c1a9b12d 640impl IntoInner<net_imp::TcpStream> for TcpStream {
60c5eb7d
XL
641 fn into_inner(self) -> net_imp::TcpStream {
642 self.0
643 }
c1a9b12d
SL
644}
645
92a42be0 646#[stable(feature = "rust1", since = "1.0.0")]
d9579d0f 647impl fmt::Debug for TcpStream {
532ac7d7 648 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
d9579d0f
AL
649 self.0.fmt(f)
650 }
651}
652
85aaf69f
SL
653impl TcpListener {
654 /// Creates a new `TcpListener` which will be bound to the specified
655 /// address.
656 ///
657 /// The returned listener is ready for accepting connections.
658 ///
659 /// Binding with a port number of 0 will request that the OS assigns a port
660 /// to this listener. The port allocated can be queried via the
cc61c64b 661 /// [`local_addr`] method.
85aaf69f 662 ///
cc61c64b 663 /// The address type can be any implementor of [`ToSocketAddrs`] trait. See
85aaf69f 664 /// its documentation for concrete examples.
476ff2be 665 ///
ea8adc8c
XL
666 /// If `addr` yields multiple addresses, `bind` will be attempted with
667 /// each of the addresses until one succeeds and returns the listener. If
668 /// none of the addresses succeed in creating a listener, the error returned
669 /// from the last attempt (the last address) is returned.
670 ///
cc61c64b
XL
671 /// [`local_addr`]: #method.local_addr
672 /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
673 ///
476ff2be
SL
674 /// # Examples
675 ///
9fa01778 676 /// Creates a TCP listener bound to `127.0.0.1:80`:
ea8adc8c 677 ///
476ff2be
SL
678 /// ```no_run
679 /// use std::net::TcpListener;
680 ///
681 /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
682 /// ```
ea8adc8c 683 ///
9fa01778 684 /// Creates a TCP listener bound to `127.0.0.1:80`. If that fails, create a
ea8adc8c
XL
685 /// TCP listener bound to `127.0.0.1:443`:
686 ///
687 /// ```no_run
688 /// use std::net::{SocketAddr, TcpListener};
689 ///
690 /// let addrs = [
691 /// SocketAddr::from(([127, 0, 0, 1], 80)),
692 /// SocketAddr::from(([127, 0, 0, 1], 443)),
693 /// ];
694 /// let listener = TcpListener::bind(&addrs[..]).unwrap();
695 /// ```
c34b1796
AL
696 #[stable(feature = "rust1", since = "1.0.0")]
697 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
85aaf69f
SL
698 super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener)
699 }
700
701 /// Returns the local socket address of this listener.
476ff2be
SL
702 ///
703 /// # Examples
704 ///
705 /// ```no_run
706 /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener};
707 ///
708 /// let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
709 /// assert_eq!(listener.local_addr().unwrap(),
710 /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
711 /// ```
c34b1796
AL
712 #[stable(feature = "rust1", since = "1.0.0")]
713 pub fn local_addr(&self) -> io::Result<SocketAddr> {
85aaf69f
SL
714 self.0.socket_addr()
715 }
716
9346a6ac 717 /// Creates a new independently owned handle to the underlying socket.
85aaf69f 718 ///
cc61c64b 719 /// The returned [`TcpListener`] is a reference to the same socket that this
85aaf69f
SL
720 /// object references. Both handles can be used to accept incoming
721 /// connections and options set on one listener will affect the other.
476ff2be 722 ///
cc61c64b
XL
723 /// [`TcpListener`]: ../../std/net/struct.TcpListener.html
724 ///
476ff2be
SL
725 /// # Examples
726 ///
727 /// ```no_run
728 /// use std::net::TcpListener;
729 ///
730 /// let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
731 /// let listener_clone = listener.try_clone().unwrap();
732 /// ```
c34b1796 733 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
734 pub fn try_clone(&self) -> io::Result<TcpListener> {
735 self.0.duplicate().map(TcpListener)
736 }
737
738 /// Accept a new incoming connection from this listener.
739 ///
740 /// This function will block the calling thread until a new TCP connection
cc61c64b 741 /// is established. When established, the corresponding [`TcpStream`] and the
85aaf69f 742 /// remote peer's address will be returned.
476ff2be 743 ///
cc61c64b
XL
744 /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
745 ///
476ff2be
SL
746 /// # Examples
747 ///
748 /// ```no_run
749 /// use std::net::TcpListener;
750 ///
751 /// let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
752 /// match listener.accept() {
753 /// Ok((_socket, addr)) => println!("new client: {:?}", addr),
754 /// Err(e) => println!("couldn't get client: {:?}", e),
755 /// }
756 /// ```
c34b1796 757 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 758 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
0731742a
XL
759 // On WASM, `TcpStream` is uninhabited (as it's unsupported) and so
760 // the `a` variable here is technically unused.
761 #[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
85aaf69f
SL
762 self.0.accept().map(|(a, b)| (TcpStream(a), b))
763 }
764
765 /// Returns an iterator over the connections being received on this
766 /// listener.
767 ///
476ff2be 768 /// The returned iterator will never return [`None`] and will also not yield
cc61c64b
XL
769 /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
770 /// calling [`accept`] in a loop.
476ff2be
SL
771 ///
772 /// [`None`]: ../../std/option/enum.Option.html#variant.None
773 /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
cc61c64b 774 /// [`accept`]: #method.accept
476ff2be
SL
775 ///
776 /// # Examples
777 ///
778 /// ```no_run
779 /// use std::net::TcpListener;
780 ///
781 /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
782 ///
783 /// for stream in listener.incoming() {
784 /// match stream {
785 /// Ok(stream) => {
786 /// println!("new client!");
787 /// }
788 /// Err(e) => { /* connection failed */ }
789 /// }
790 /// }
791 /// ```
c34b1796 792 #[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 793 pub fn incoming(&self) -> Incoming<'_> {
85aaf69f
SL
794 Incoming { listener: self }
795 }
54a0048b
SL
796
797 /// Sets the value for the `IP_TTL` option on this socket.
798 ///
799 /// This value sets the time-to-live field that is used in every packet sent
800 /// from this socket.
476ff2be
SL
801 ///
802 /// # Examples
803 ///
804 /// ```no_run
805 /// use std::net::TcpListener;
806 ///
807 /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
808 /// listener.set_ttl(100).expect("could not set TTL");
809 /// ```
54a0048b
SL
810 #[stable(feature = "net2_mutators", since = "1.9.0")]
811 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
812 self.0.set_ttl(ttl)
813 }
814
815 /// Gets the value of the `IP_TTL` option for this socket.
816 ///
cc61c64b 817 /// For more information about this option, see [`set_ttl`][link].
54a0048b
SL
818 ///
819 /// [link]: #method.set_ttl
476ff2be
SL
820 ///
821 /// # Examples
822 ///
823 /// ```no_run
824 /// use std::net::TcpListener;
825 ///
826 /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
827 /// listener.set_ttl(100).expect("could not set TTL");
828 /// assert_eq!(listener.ttl().unwrap_or(0), 100);
829 /// ```
54a0048b
SL
830 #[stable(feature = "net2_mutators", since = "1.9.0")]
831 pub fn ttl(&self) -> io::Result<u32> {
832 self.0.ttl()
833 }
834
54a0048b 835 #[stable(feature = "net2_mutators", since = "1.9.0")]
60c5eb7d
XL
836 #[rustc_deprecated(
837 since = "1.16.0",
838 reason = "this option can only be set before the socket is bound"
839 )]
32a655c1 840 #[allow(missing_docs)]
54a0048b
SL
841 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
842 self.0.set_only_v6(only_v6)
843 }
844
54a0048b 845 #[stable(feature = "net2_mutators", since = "1.9.0")]
60c5eb7d
XL
846 #[rustc_deprecated(
847 since = "1.16.0",
848 reason = "this option can only be set before the socket is bound"
849 )]
32a655c1 850 #[allow(missing_docs)]
54a0048b
SL
851 pub fn only_v6(&self) -> io::Result<bool> {
852 self.0.only_v6()
853 }
854
9fa01778 855 /// Gets the value of the `SO_ERROR` option on this socket.
54a0048b
SL
856 ///
857 /// This will retrieve the stored error in the underlying socket, clearing
858 /// the field in the process. This can be useful for checking errors between
859 /// calls.
476ff2be
SL
860 ///
861 /// # Examples
862 ///
863 /// ```no_run
864 /// use std::net::TcpListener;
865 ///
866 /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
867 /// listener.take_error().expect("No error was expected");
868 /// ```
54a0048b
SL
869 #[stable(feature = "net2_mutators", since = "1.9.0")]
870 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
871 self.0.take_error()
872 }
873
874 /// Moves this TCP stream into or out of nonblocking mode.
875 ///
abe05a73 876 /// This will result in the `accept` operation becoming nonblocking,
0731742a 877 /// i.e., immediately returning from their calls. If the IO operation is
abe05a73
XL
878 /// successful, `Ok` is returned and no further action is required. If the
879 /// IO operation could not be completed and needs to be retried, an error
880 /// with kind [`io::ErrorKind::WouldBlock`] is returned.
881 ///
882 /// On Unix platforms, calling this method corresponds to calling `fcntl`
883 /// `FIONBIO`. On Windows calling this method corresponds to calling
884 /// `ioctlsocket` `FIONBIO`.
476ff2be
SL
885 ///
886 /// # Examples
887 ///
abe05a73
XL
888 /// Bind a TCP listener to an address, listen for connections, and read
889 /// bytes in nonblocking mode:
890 ///
476ff2be 891 /// ```no_run
abe05a73 892 /// use std::io;
476ff2be
SL
893 /// use std::net::TcpListener;
894 ///
abe05a73 895 /// let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
476ff2be 896 /// listener.set_nonblocking(true).expect("Cannot set non-blocking");
abe05a73
XL
897 ///
898 /// # fn wait_for_fd() { unimplemented!() }
899 /// # fn handle_connection(stream: std::net::TcpStream) { unimplemented!() }
900 /// for stream in listener.incoming() {
901 /// match stream {
902 /// Ok(s) => {
903 /// // do something with the TcpStream
904 /// handle_connection(s);
905 /// }
906 /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
907 /// // wait until network socket is ready, typically implemented
908 /// // via platform-specific APIs such as epoll or IOCP
909 /// wait_for_fd();
910 /// continue;
911 /// }
912 /// Err(e) => panic!("encountered IO error: {}", e),
913 /// }
914 /// }
476ff2be 915 /// ```
abe05a73
XL
916 ///
917 /// [`io::ErrorKind::WouldBlock`]: ../io/enum.ErrorKind.html#variant.WouldBlock
54a0048b
SL
918 #[stable(feature = "net2_mutators", since = "1.9.0")]
919 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
920 self.0.set_nonblocking(nonblocking)
921 }
85aaf69f
SL
922}
923
c34b1796 924#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
925impl<'a> Iterator for Incoming<'a> {
926 type Item = io::Result<TcpStream>;
927 fn next(&mut self) -> Option<io::Result<TcpStream>> {
928 Some(self.listener.accept().map(|p| p.0))
929 }
930}
931
932impl AsInner<net_imp::TcpListener> for TcpListener {
60c5eb7d
XL
933 fn as_inner(&self) -> &net_imp::TcpListener {
934 &self.0
935 }
85aaf69f
SL
936}
937
c34b1796
AL
938impl FromInner<net_imp::TcpListener> for TcpListener {
939 fn from_inner(inner: net_imp::TcpListener) -> TcpListener {
940 TcpListener(inner)
941 }
942}
943
c1a9b12d 944impl IntoInner<net_imp::TcpListener> for TcpListener {
60c5eb7d
XL
945 fn into_inner(self) -> net_imp::TcpListener {
946 self.0
947 }
c1a9b12d
SL
948}
949
92a42be0 950#[stable(feature = "rust1", since = "1.0.0")]
d9579d0f 951impl fmt::Debug for TcpListener {
532ac7d7 952 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
d9579d0f
AL
953 self.0.fmt(f)
954 }
955}
956
2c00a5a8 957#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
85aaf69f 958mod tests {
532ac7d7 959 use crate::fmt;
532ac7d7 960 use crate::io::prelude::*;
60c5eb7d 961 use crate::io::{ErrorKind, IoSlice, IoSliceMut};
532ac7d7 962 use crate::net::test::{next_test_ip4, next_test_ip6};
60c5eb7d 963 use crate::net::*;
532ac7d7 964 use crate::sync::mpsc::channel;
532ac7d7 965 use crate::thread;
60c5eb7d 966 use crate::time::{Duration, Instant};
85aaf69f 967
8faf50e0 968 fn each_ip(f: &mut dyn FnMut(SocketAddr)) {
85aaf69f
SL
969 f(next_test_ip4());
970 f(next_test_ip6());
971 }
972
973 macro_rules! t {
974 ($e:expr) => {
975 match $e {
976 Ok(t) => t,
977 Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
978 }
60c5eb7d 979 };
85aaf69f
SL
980 }
981
85aaf69f
SL
982 #[test]
983 fn bind_error() {
c34b1796 984 match TcpListener::bind("1.1.1.1:9999") {
85aaf69f 985 Ok(..) => panic!(),
60c5eb7d 986 Err(e) => assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
85aaf69f
SL
987 }
988 }
989
990 #[test]
991 fn connect_error() {
992 match TcpStream::connect("0.0.0.0:1") {
993 Ok(..) => panic!(),
60c5eb7d
XL
994 Err(e) => assert!(
995 e.kind() == ErrorKind::ConnectionRefused
996 || e.kind() == ErrorKind::InvalidInput
997 || e.kind() == ErrorKind::AddrInUse
998 || e.kind() == ErrorKind::AddrNotAvailable,
999 "bad error: {} {:?}",
1000 e,
1001 e.kind()
1002 ),
85aaf69f
SL
1003 }
1004 }
1005
1006 #[test]
1007 fn listen_localhost() {
1008 let socket_addr = next_test_ip4();
1009 let listener = t!(TcpListener::bind(&socket_addr));
1010
1011 let _t = thread::spawn(move || {
60c5eb7d 1012 let mut stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
85aaf69f
SL
1013 t!(stream.write(&[144]));
1014 });
1015
1016 let mut stream = t!(listener.accept()).0;
1017 let mut buf = [0];
1018 t!(stream.read(&mut buf));
1019 assert!(buf[0] == 144);
1020 }
1021
1022 #[test]
b039eaaf
SL
1023 fn connect_loopback() {
1024 each_ip(&mut |addr| {
1025 let acceptor = t!(TcpListener::bind(&addr));
85aaf69f 1026
60c5eb7d 1027 let _t = thread::spawn(move || {
b039eaaf
SL
1028 let host = match addr {
1029 SocketAddr::V4(..) => "127.0.0.1",
1030 SocketAddr::V6(..) => "::1",
1031 };
1032 let mut stream = t!(TcpStream::connect(&(host, addr.port())));
1033 t!(stream.write(&[66]));
1034 });
85aaf69f 1035
b039eaaf
SL
1036 let mut stream = t!(acceptor.accept()).0;
1037 let mut buf = [0];
1038 t!(stream.read(&mut buf));
1039 assert!(buf[0] == 66);
1040 })
85aaf69f
SL
1041 }
1042
1043 #[test]
b039eaaf 1044 fn smoke_test() {
85aaf69f
SL
1045 each_ip(&mut |addr| {
1046 let acceptor = t!(TcpListener::bind(&addr));
1047
1048 let (tx, rx) = channel();
60c5eb7d 1049 let _t = thread::spawn(move || {
85aaf69f
SL
1050 let mut stream = t!(TcpStream::connect(&addr));
1051 t!(stream.write(&[99]));
c34b1796 1052 tx.send(t!(stream.local_addr())).unwrap();
85aaf69f
SL
1053 });
1054
1055 let (mut stream, addr) = t!(acceptor.accept());
1056 let mut buf = [0];
1057 t!(stream.read(&mut buf));
1058 assert!(buf[0] == 99);
1059 assert_eq!(addr, t!(rx.recv()));
1060 })
1061 }
1062
1063 #[test]
b039eaaf 1064 fn read_eof() {
85aaf69f
SL
1065 each_ip(&mut |addr| {
1066 let acceptor = t!(TcpListener::bind(&addr));
1067
60c5eb7d 1068 let _t = thread::spawn(move || {
85aaf69f
SL
1069 let _stream = t!(TcpStream::connect(&addr));
1070 // Close
1071 });
1072
1073 let mut stream = t!(acceptor.accept()).0;
1074 let mut buf = [0];
1075 let nread = t!(stream.read(&mut buf));
1076 assert_eq!(nread, 0);
1077 let nread = t!(stream.read(&mut buf));
1078 assert_eq!(nread, 0);
1079 })
1080 }
1081
1082 #[test]
1083 fn write_close() {
1084 each_ip(&mut |addr| {
1085 let acceptor = t!(TcpListener::bind(&addr));
1086
1087 let (tx, rx) = channel();
60c5eb7d 1088 let _t = thread::spawn(move || {
85aaf69f
SL
1089 drop(t!(TcpStream::connect(&addr)));
1090 tx.send(()).unwrap();
1091 });
1092
1093 let mut stream = t!(acceptor.accept()).0;
1094 rx.recv().unwrap();
1095 let buf = [0];
1096 match stream.write(&buf) {
1097 Ok(..) => {}
1098 Err(e) => {
60c5eb7d
XL
1099 assert!(
1100 e.kind() == ErrorKind::ConnectionReset
1101 || e.kind() == ErrorKind::BrokenPipe
1102 || e.kind() == ErrorKind::ConnectionAborted,
1103 "unknown error: {}",
1104 e
1105 );
85aaf69f
SL
1106 }
1107 }
1108 })
1109 }
1110
1111 #[test]
b039eaaf 1112 fn multiple_connect_serial() {
85aaf69f
SL
1113 each_ip(&mut |addr| {
1114 let max = 10;
1115 let acceptor = t!(TcpListener::bind(&addr));
1116
60c5eb7d 1117 let _t = thread::spawn(move || {
85aaf69f
SL
1118 for _ in 0..max {
1119 let mut stream = t!(TcpStream::connect(&addr));
1120 t!(stream.write(&[99]));
1121 }
1122 });
1123
1124 for stream in acceptor.incoming().take(max) {
1125 let mut stream = t!(stream);
1126 let mut buf = [0];
1127 t!(stream.read(&mut buf));
1128 assert_eq!(buf[0], 99);
1129 }
1130 })
1131 }
1132
1133 #[test]
1134 fn multiple_connect_interleaved_greedy_schedule() {
62682a34 1135 const MAX: usize = 10;
85aaf69f
SL
1136 each_ip(&mut |addr| {
1137 let acceptor = t!(TcpListener::bind(&addr));
1138
60c5eb7d 1139 let _t = thread::spawn(move || {
85aaf69f
SL
1140 let acceptor = acceptor;
1141 for (i, stream) in acceptor.incoming().enumerate().take(MAX) {
bd371182 1142 // Start another thread to handle the connection
60c5eb7d 1143 let _t = thread::spawn(move || {
85aaf69f
SL
1144 let mut stream = t!(stream);
1145 let mut buf = [0];
1146 t!(stream.read(&mut buf));
1147 assert!(buf[0] == i as u8);
1148 });
1149 }
1150 });
1151
1152 connect(0, addr);
1153 });
1154
1155 fn connect(i: usize, addr: SocketAddr) {
60c5eb7d
XL
1156 if i == MAX {
1157 return;
1158 }
85aaf69f 1159
60c5eb7d 1160 let t = thread::spawn(move || {
85aaf69f
SL
1161 let mut stream = t!(TcpStream::connect(&addr));
1162 // Connect again before writing
1163 connect(i + 1, addr);
1164 t!(stream.write(&[i as u8]));
1165 });
532ac7d7 1166 t.join().ok().expect("thread panicked");
85aaf69f
SL
1167 }
1168 }
1169
1170 #[test]
b039eaaf 1171 fn multiple_connect_interleaved_lazy_schedule() {
c34b1796 1172 const MAX: usize = 10;
85aaf69f
SL
1173 each_ip(&mut |addr| {
1174 let acceptor = t!(TcpListener::bind(&addr));
1175
60c5eb7d 1176 let _t = thread::spawn(move || {
85aaf69f 1177 for stream in acceptor.incoming().take(MAX) {
bd371182 1178 // Start another thread to handle the connection
60c5eb7d 1179 let _t = thread::spawn(move || {
85aaf69f
SL
1180 let mut stream = t!(stream);
1181 let mut buf = [0];
1182 t!(stream.read(&mut buf));
1183 assert!(buf[0] == 99);
1184 });
1185 }
1186 });
1187
1188 connect(0, addr);
1189 });
1190
1191 fn connect(i: usize, addr: SocketAddr) {
60c5eb7d
XL
1192 if i == MAX {
1193 return;
1194 }
85aaf69f 1195
60c5eb7d 1196 let t = thread::spawn(move || {
85aaf69f
SL
1197 let mut stream = t!(TcpStream::connect(&addr));
1198 connect(i + 1, addr);
1199 t!(stream.write(&[99]));
1200 });
532ac7d7 1201 t.join().ok().expect("thread panicked");
85aaf69f
SL
1202 }
1203 }
1204
85aaf69f 1205 #[test]
b039eaaf 1206 fn socket_and_peer_name() {
85aaf69f
SL
1207 each_ip(&mut |addr| {
1208 let listener = t!(TcpListener::bind(&addr));
c34b1796 1209 let so_name = t!(listener.local_addr());
85aaf69f 1210 assert_eq!(addr, so_name);
60c5eb7d 1211 let _t = thread::spawn(move || {
85aaf69f
SL
1212 t!(listener.accept());
1213 });
1214
1215 let stream = t!(TcpStream::connect(&addr));
1216 assert_eq!(addr, t!(stream.peer_addr()));
1217 })
1218 }
1219
1220 #[test]
1221 fn partial_read() {
1222 each_ip(&mut |addr| {
1223 let (tx, rx) = channel();
1224 let srv = t!(TcpListener::bind(&addr));
60c5eb7d 1225 let _t = thread::spawn(move || {
85aaf69f
SL
1226 let mut cl = t!(srv.accept()).0;
1227 cl.write(&[10]).unwrap();
1228 let mut b = [0];
1229 t!(cl.read(&mut b));
1230 tx.send(()).unwrap();
1231 });
1232
1233 let mut c = t!(TcpStream::connect(&addr));
1234 let mut b = [0; 10];
c34b1796 1235 assert_eq!(c.read(&mut b).unwrap(), 1);
85aaf69f
SL
1236 t!(c.write(&[1]));
1237 rx.recv().unwrap();
1238 })
1239 }
1240
9fa01778
XL
1241 #[test]
1242 fn read_vectored() {
1243 each_ip(&mut |addr| {
1244 let srv = t!(TcpListener::bind(&addr));
1245 let mut s1 = t!(TcpStream::connect(&addr));
1246 let mut s2 = t!(srv.accept()).0;
1247
1248 let len = s1.write(&[10, 11, 12]).unwrap();
1249 assert_eq!(len, 3);
1250
1251 let mut a = [];
1252 let mut b = [0];
1253 let mut c = [0; 3];
60c5eb7d
XL
1254 let len = t!(s2.read_vectored(&mut [
1255 IoSliceMut::new(&mut a),
1256 IoSliceMut::new(&mut b),
1257 IoSliceMut::new(&mut c)
1258 ],));
9fa01778
XL
1259 assert!(len > 0);
1260 assert_eq!(b, [10]);
1261 // some implementations don't support readv, so we may only fill the first buffer
1262 assert!(len == 1 || c == [11, 12, 0]);
1263 })
1264 }
1265
1266 #[test]
1267 fn write_vectored() {
1268 each_ip(&mut |addr| {
1269 let srv = t!(TcpListener::bind(&addr));
1270 let mut s1 = t!(TcpStream::connect(&addr));
1271 let mut s2 = t!(srv.accept()).0;
1272
1273 let a = [];
1274 let b = [10];
1275 let c = [11, 12];
48663c56 1276 t!(s1.write_vectored(&[IoSlice::new(&a), IoSlice::new(&b), IoSlice::new(&c)]));
9fa01778
XL
1277
1278 let mut buf = [0; 4];
1279 let len = t!(s2.read(&mut buf));
1280 // some implementations don't support writev, so we may only write the first buffer
1281 if len == 1 {
1282 assert_eq!(buf, [10, 0, 0, 0]);
1283 } else {
1284 assert_eq!(len, 3);
1285 assert_eq!(buf, [10, 11, 12, 0]);
1286 }
1287 })
1288 }
1289
85aaf69f
SL
1290 #[test]
1291 fn double_bind() {
1292 each_ip(&mut |addr| {
9fa01778 1293 let listener1 = t!(TcpListener::bind(&addr));
85aaf69f 1294 match TcpListener::bind(&addr) {
9fa01778
XL
1295 Ok(listener2) => panic!(
1296 "This system (perhaps due to options set by TcpListener::bind) \
1297 permits double binding: {:?} and {:?}",
1298 listener1, listener2
1299 ),
85aaf69f 1300 Err(e) => {
60c5eb7d
XL
1301 assert!(
1302 e.kind() == ErrorKind::ConnectionRefused
1303 || e.kind() == ErrorKind::Other
1304 || e.kind() == ErrorKind::AddrInUse,
1305 "unknown error: {} {:?}",
1306 e,
1307 e.kind()
1308 );
85aaf69f
SL
1309 }
1310 }
1311 })
1312 }
1313
85aaf69f
SL
1314 #[test]
1315 fn tcp_clone_smoke() {
1316 each_ip(&mut |addr| {
1317 let acceptor = t!(TcpListener::bind(&addr));
1318
60c5eb7d 1319 let _t = thread::spawn(move || {
85aaf69f
SL
1320 let mut s = t!(TcpStream::connect(&addr));
1321 let mut buf = [0, 0];
c34b1796 1322 assert_eq!(s.read(&mut buf).unwrap(), 1);
85aaf69f
SL
1323 assert_eq!(buf[0], 1);
1324 t!(s.write(&[2]));
1325 });
1326
1327 let mut s1 = t!(acceptor.accept()).0;
1328 let s2 = t!(s1.try_clone());
1329
1330 let (tx1, rx1) = channel();
1331 let (tx2, rx2) = channel();
60c5eb7d 1332 let _t = thread::spawn(move || {
85aaf69f
SL
1333 let mut s2 = s2;
1334 rx1.recv().unwrap();
1335 t!(s2.write(&[1]));
1336 tx2.send(()).unwrap();
1337 });
1338 tx1.send(()).unwrap();
1339 let mut buf = [0, 0];
c34b1796 1340 assert_eq!(s1.read(&mut buf).unwrap(), 1);
85aaf69f
SL
1341 rx2.recv().unwrap();
1342 })
1343 }
1344
1345 #[test]
1346 fn tcp_clone_two_read() {
1347 each_ip(&mut |addr| {
1348 let acceptor = t!(TcpListener::bind(&addr));
1349 let (tx1, rx) = channel();
1350 let tx2 = tx1.clone();
1351
60c5eb7d 1352 let _t = thread::spawn(move || {
85aaf69f
SL
1353 let mut s = t!(TcpStream::connect(&addr));
1354 t!(s.write(&[1]));
1355 rx.recv().unwrap();
1356 t!(s.write(&[2]));
1357 rx.recv().unwrap();
1358 });
1359
1360 let mut s1 = t!(acceptor.accept()).0;
1361 let s2 = t!(s1.try_clone());
1362
1363 let (done, rx) = channel();
60c5eb7d 1364 let _t = thread::spawn(move || {
85aaf69f
SL
1365 let mut s2 = s2;
1366 let mut buf = [0, 0];
1367 t!(s2.read(&mut buf));
1368 tx2.send(()).unwrap();
1369 done.send(()).unwrap();
1370 });
1371 let mut buf = [0, 0];
1372 t!(s1.read(&mut buf));
1373 tx1.send(()).unwrap();
1374
1375 rx.recv().unwrap();
1376 })
1377 }
1378
1379 #[test]
1380 fn tcp_clone_two_write() {
1381 each_ip(&mut |addr| {
1382 let acceptor = t!(TcpListener::bind(&addr));
1383
60c5eb7d 1384 let _t = thread::spawn(move || {
85aaf69f
SL
1385 let mut s = t!(TcpStream::connect(&addr));
1386 let mut buf = [0, 1];
1387 t!(s.read(&mut buf));
1388 t!(s.read(&mut buf));
1389 });
1390
1391 let mut s1 = t!(acceptor.accept()).0;
1392 let s2 = t!(s1.try_clone());
1393
1394 let (done, rx) = channel();
60c5eb7d 1395 let _t = thread::spawn(move || {
85aaf69f
SL
1396 let mut s2 = s2;
1397 t!(s2.write(&[1]));
1398 done.send(()).unwrap();
1399 });
1400 t!(s1.write(&[2]));
1401
1402 rx.recv().unwrap();
1403 })
1404 }
1405
1406 #[test]
532ac7d7
XL
1407 // FIXME: https://github.com/fortanix/rust-sgx/issues/110
1408 #[cfg_attr(target_env = "sgx", ignore)]
85aaf69f
SL
1409 fn shutdown_smoke() {
1410 each_ip(&mut |addr| {
1411 let a = t!(TcpListener::bind(&addr));
60c5eb7d 1412 let _t = thread::spawn(move || {
85aaf69f
SL
1413 let mut c = t!(a.accept()).0;
1414 let mut b = [0];
c34b1796 1415 assert_eq!(c.read(&mut b).unwrap(), 0);
85aaf69f
SL
1416 t!(c.write(&[1]));
1417 });
1418
1419 let mut s = t!(TcpStream::connect(&addr));
1420 t!(s.shutdown(Shutdown::Write));
1421 assert!(s.write(&[1]).is_err());
1422 let mut b = [0, 0];
1423 assert_eq!(t!(s.read(&mut b)), 1);
1424 assert_eq!(b[0], 1);
1425 })
1426 }
1427
1428 #[test]
532ac7d7
XL
1429 // FIXME: https://github.com/fortanix/rust-sgx/issues/110
1430 #[cfg_attr(target_env = "sgx", ignore)]
85aaf69f
SL
1431 fn close_readwrite_smoke() {
1432 each_ip(&mut |addr| {
1433 let a = t!(TcpListener::bind(&addr));
1434 let (tx, rx) = channel::<()>();
60c5eb7d 1435 let _t = thread::spawn(move || {
85aaf69f
SL
1436 let _s = t!(a.accept());
1437 let _ = rx.recv();
1438 });
1439
1440 let mut b = [0];
1441 let mut s = t!(TcpStream::connect(&addr));
1442 let mut s2 = t!(s.try_clone());
1443
1444 // closing should prevent reads/writes
1445 t!(s.shutdown(Shutdown::Write));
1446 assert!(s.write(&[0]).is_err());
1447 t!(s.shutdown(Shutdown::Read));
c34b1796 1448 assert_eq!(s.read(&mut b).unwrap(), 0);
85aaf69f
SL
1449
1450 // closing should affect previous handles
1451 assert!(s2.write(&[0]).is_err());
c34b1796 1452 assert_eq!(s2.read(&mut b).unwrap(), 0);
85aaf69f
SL
1453
1454 // closing should affect new handles
1455 let mut s3 = t!(s.try_clone());
1456 assert!(s3.write(&[0]).is_err());
c34b1796 1457 assert_eq!(s3.read(&mut b).unwrap(), 0);
85aaf69f
SL
1458
1459 // make sure these don't die
1460 let _ = s2.shutdown(Shutdown::Read);
1461 let _ = s2.shutdown(Shutdown::Write);
1462 let _ = s3.shutdown(Shutdown::Read);
1463 let _ = s3.shutdown(Shutdown::Write);
1464 drop(tx);
1465 })
1466 }
1467
1468 #[test]
32a655c1 1469 #[cfg(unix)] // test doesn't work on Windows, see #31657
85aaf69f
SL
1470 fn close_read_wakes_up() {
1471 each_ip(&mut |addr| {
1472 let a = t!(TcpListener::bind(&addr));
1473 let (tx1, rx) = channel::<()>();
60c5eb7d 1474 let _t = thread::spawn(move || {
85aaf69f
SL
1475 let _s = t!(a.accept());
1476 let _ = rx.recv();
1477 });
1478
1479 let s = t!(TcpStream::connect(&addr));
1480 let s2 = t!(s.try_clone());
1481 let (tx, rx) = channel();
60c5eb7d 1482 let _t = thread::spawn(move || {
85aaf69f
SL
1483 let mut s2 = s2;
1484 assert_eq!(t!(s2.read(&mut [0])), 0);
1485 tx.send(()).unwrap();
1486 });
bd371182 1487 // this should wake up the child thread
85aaf69f
SL
1488 t!(s.shutdown(Shutdown::Read));
1489
1490 // this test will never finish if the child doesn't wake up
1491 rx.recv().unwrap();
1492 drop(tx1);
1493 })
1494 }
1495
1496 #[test]
1497 fn clone_while_reading() {
1498 each_ip(&mut |addr| {
1499 let accept = t!(TcpListener::bind(&addr));
1500
bd371182 1501 // Enqueue a thread to write to a socket
85aaf69f
SL
1502 let (tx, rx) = channel();
1503 let (txdone, rxdone) = channel();
1504 let txdone2 = txdone.clone();
60c5eb7d 1505 let _t = thread::spawn(move || {
85aaf69f
SL
1506 let mut tcp = t!(TcpStream::connect(&addr));
1507 rx.recv().unwrap();
1508 t!(tcp.write(&[0]));
1509 txdone2.send(()).unwrap();
1510 });
1511
1512 // Spawn off a reading clone
1513 let tcp = t!(accept.accept()).0;
1514 let tcp2 = t!(tcp.try_clone());
1515 let txdone3 = txdone.clone();
60c5eb7d 1516 let _t = thread::spawn(move || {
85aaf69f
SL
1517 let mut tcp2 = tcp2;
1518 t!(tcp2.read(&mut [0]));
1519 txdone3.send(()).unwrap();
1520 });
1521
1522 // Try to ensure that the reading clone is indeed reading
1523 for _ in 0..50 {
1524 thread::yield_now();
1525 }
1526
1527 // clone the handle again while it's reading, then let it finish the
1528 // read.
1529 let _ = t!(tcp.try_clone());
1530 tx.send(()).unwrap();
1531 rxdone.recv().unwrap();
1532 rxdone.recv().unwrap();
1533 })
1534 }
1535
1536 #[test]
1537 fn clone_accept_smoke() {
1538 each_ip(&mut |addr| {
1539 let a = t!(TcpListener::bind(&addr));
1540 let a2 = t!(a.try_clone());
1541
60c5eb7d 1542 let _t = thread::spawn(move || {
85aaf69f
SL
1543 let _ = TcpStream::connect(&addr);
1544 });
60c5eb7d 1545 let _t = thread::spawn(move || {
85aaf69f
SL
1546 let _ = TcpStream::connect(&addr);
1547 });
1548
1549 t!(a.accept());
1550 t!(a2.accept());
1551 })
1552 }
1553
1554 #[test]
1555 fn clone_accept_concurrent() {
1556 each_ip(&mut |addr| {
1557 let a = t!(TcpListener::bind(&addr));
1558 let a2 = t!(a.try_clone());
1559
1560 let (tx, rx) = channel();
1561 let tx2 = tx.clone();
1562
60c5eb7d 1563 let _t = thread::spawn(move || {
85aaf69f
SL
1564 tx.send(t!(a.accept())).unwrap();
1565 });
60c5eb7d 1566 let _t = thread::spawn(move || {
85aaf69f
SL
1567 tx2.send(t!(a2.accept())).unwrap();
1568 });
1569
60c5eb7d 1570 let _t = thread::spawn(move || {
85aaf69f
SL
1571 let _ = TcpStream::connect(&addr);
1572 });
60c5eb7d 1573 let _t = thread::spawn(move || {
85aaf69f
SL
1574 let _ = TcpStream::connect(&addr);
1575 });
1576
1577 rx.recv().unwrap();
1578 rx.recv().unwrap();
1579 })
1580 }
d9579d0f
AL
1581
1582 #[test]
1583 fn debug() {
532ac7d7
XL
1584 #[cfg(not(target_env = "sgx"))]
1585 fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
1586 addr
1587 }
1588 #[cfg(target_env = "sgx")]
1589 fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a {
1590 addr.to_string()
1591 }
1592
532ac7d7
XL
1593 #[cfg(target_env = "sgx")]
1594 use crate::os::fortanix_sgx::io::AsRawFd;
60c5eb7d
XL
1595 #[cfg(unix)]
1596 use crate::os::unix::io::AsRawFd;
532ac7d7
XL
1597 #[cfg(not(windows))]
1598 fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug {
1599 addr.as_raw_fd()
1600 }
1601 #[cfg(windows)]
1602 fn render_inner(addr: &dyn crate::os::windows::io::AsRawSocket) -> impl fmt::Debug {
1603 addr.as_raw_socket()
1604 }
1605
60c5eb7d 1606 let inner_name = if cfg!(windows) { "socket" } else { "fd" };
d9579d0f
AL
1607 let socket_addr = next_test_ip4();
1608
1609 let listener = t!(TcpListener::bind(&socket_addr));
60c5eb7d
XL
1610 let compare = format!(
1611 "TcpListener {{ addr: {:?}, {}: {:?} }}",
1612 render_socket_addr(&socket_addr),
1613 inner_name,
1614 render_inner(&listener)
1615 );
d9579d0f
AL
1616 assert_eq!(format!("{:?}", listener), compare);
1617
532ac7d7 1618 let stream = t!(TcpStream::connect(&("localhost", socket_addr.port())));
60c5eb7d
XL
1619 let compare = format!(
1620 "TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}",
1621 render_socket_addr(&stream.local_addr().unwrap()),
1622 render_socket_addr(&stream.peer_addr().unwrap()),
1623 inner_name,
1624 render_inner(&stream)
1625 );
d9579d0f
AL
1626 assert_eq!(format!("{:?}", stream), compare);
1627 }
62682a34 1628
48663c56 1629 // FIXME: re-enabled openbsd tests once their socket timeout code
62682a34 1630 // no longer has rounding errors.
e1599b0c
XL
1631 // VxWorks ignores SO_SNDTIMEO.
1632 #[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
532ac7d7 1633 #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
62682a34
SL
1634 #[test]
1635 fn timeouts() {
1636 let addr = next_test_ip4();
1637 let listener = t!(TcpListener::bind(&addr));
1638
1639 let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1640 let dur = Duration::new(15410, 0);
1641
1642 assert_eq!(None, t!(stream.read_timeout()));
1643
1644 t!(stream.set_read_timeout(Some(dur)));
1645 assert_eq!(Some(dur), t!(stream.read_timeout()));
1646
1647 assert_eq!(None, t!(stream.write_timeout()));
1648
1649 t!(stream.set_write_timeout(Some(dur)));
1650 assert_eq!(Some(dur), t!(stream.write_timeout()));
1651
1652 t!(stream.set_read_timeout(None));
1653 assert_eq!(None, t!(stream.read_timeout()));
1654
1655 t!(stream.set_write_timeout(None));
1656 assert_eq!(None, t!(stream.write_timeout()));
9cc50fc6 1657 drop(listener);
62682a34
SL
1658 }
1659
1660 #[test]
532ac7d7 1661 #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
62682a34
SL
1662 fn test_read_timeout() {
1663 let addr = next_test_ip4();
1664 let listener = t!(TcpListener::bind(&addr));
1665
1666 let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
1667 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
1668
1669 let mut buf = [0; 10];
9cc50fc6 1670 let start = Instant::now();
a1dfa0c6 1671 let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
60c5eb7d
XL
1672 assert!(
1673 kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
1674 "unexpected_error: {:?}",
1675 kind
1676 );
9cc50fc6
SL
1677 assert!(start.elapsed() > Duration::from_millis(400));
1678 drop(listener);
62682a34
SL
1679 }
1680
1681 #[test]
532ac7d7 1682 #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
62682a34
SL
1683 fn test_read_with_timeout() {
1684 let addr = next_test_ip4();
1685 let listener = t!(TcpListener::bind(&addr));
1686
1687 let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
1688 t!(stream.set_read_timeout(Some(Duration::from_millis(1000))));
1689
1690 let mut other_end = t!(listener.accept()).0;
1691 t!(other_end.write_all(b"hello world"));
1692
1693 let mut buf = [0; 11];
1694 t!(stream.read(&mut buf));
1695 assert_eq!(b"hello world", &buf[..]);
1696
9cc50fc6 1697 let start = Instant::now();
a1dfa0c6 1698 let kind = stream.read_exact(&mut buf).err().expect("expected error").kind();
60c5eb7d
XL
1699 assert!(
1700 kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut,
1701 "unexpected_error: {:?}",
1702 kind
1703 );
9cc50fc6
SL
1704 assert!(start.elapsed() > Duration::from_millis(400));
1705 drop(listener);
62682a34 1706 }
54a0048b 1707
0531ce1d
XL
1708 // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
1709 // when passed zero Durations
1710 #[test]
1711 fn test_timeout_zero_duration() {
1712 let addr = next_test_ip4();
1713
1714 let listener = t!(TcpListener::bind(&addr));
1715 let stream = t!(TcpStream::connect(&addr));
1716
1717 let result = stream.set_write_timeout(Some(Duration::new(0, 0)));
1718 let err = result.unwrap_err();
1719 assert_eq!(err.kind(), ErrorKind::InvalidInput);
1720
1721 let result = stream.set_read_timeout(Some(Duration::new(0, 0)));
1722 let err = result.unwrap_err();
1723 assert_eq!(err.kind(), ErrorKind::InvalidInput);
1724
1725 drop(listener);
1726 }
1727
54a0048b 1728 #[test]
532ac7d7 1729 #[cfg_attr(target_env = "sgx", ignore)]
54a0048b
SL
1730 fn nodelay() {
1731 let addr = next_test_ip4();
1732 let _listener = t!(TcpListener::bind(&addr));
1733
1734 let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1735
1736 assert_eq!(false, t!(stream.nodelay()));
1737 t!(stream.set_nodelay(true));
1738 assert_eq!(true, t!(stream.nodelay()));
1739 t!(stream.set_nodelay(false));
1740 assert_eq!(false, t!(stream.nodelay()));
1741 }
1742
1743 #[test]
532ac7d7 1744 #[cfg_attr(target_env = "sgx", ignore)]
54a0048b
SL
1745 fn ttl() {
1746 let ttl = 100;
1747
1748 let addr = next_test_ip4();
1749 let listener = t!(TcpListener::bind(&addr));
1750
1751 t!(listener.set_ttl(ttl));
1752 assert_eq!(ttl, t!(listener.ttl()));
1753
1754 let stream = t!(TcpStream::connect(&("localhost", addr.port())));
1755
1756 t!(stream.set_ttl(ttl));
1757 assert_eq!(ttl, t!(stream.ttl()));
1758 }
1759
1760 #[test]
532ac7d7 1761 #[cfg_attr(target_env = "sgx", ignore)]
54a0048b
SL
1762 fn set_nonblocking() {
1763 let addr = next_test_ip4();
1764 let listener = t!(TcpListener::bind(&addr));
1765
1766 t!(listener.set_nonblocking(true));
1767 t!(listener.set_nonblocking(false));
1768
1769 let mut stream = t!(TcpStream::connect(&("localhost", addr.port())));
1770
1771 t!(stream.set_nonblocking(false));
1772 t!(stream.set_nonblocking(true));
1773
1774 let mut buf = [0];
1775 match stream.read(&mut buf) {
1776 Ok(_) => panic!("expected error"),
1777 Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
1778 Err(e) => panic!("unexpected error {}", e),
1779 }
1780 }
8bb4bdeb
XL
1781
1782 #[test]
532ac7d7 1783 #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
8bb4bdeb
XL
1784 fn peek() {
1785 each_ip(&mut |addr| {
1786 let (txdone, rxdone) = channel();
1787
1788 let srv = t!(TcpListener::bind(&addr));
60c5eb7d 1789 let _t = thread::spawn(move || {
8bb4bdeb 1790 let mut cl = t!(srv.accept()).0;
60c5eb7d 1791 cl.write(&[1, 3, 3, 7]).unwrap();
8bb4bdeb
XL
1792 t!(rxdone.recv());
1793 });
1794
1795 let mut c = t!(TcpStream::connect(&addr));
1796 let mut b = [0; 10];
1797 for _ in 1..3 {
1798 let len = c.peek(&mut b).unwrap();
1799 assert_eq!(len, 4);
1800 }
1801 let len = c.read(&mut b).unwrap();
1802 assert_eq!(len, 4);
1803
1804 t!(c.set_nonblocking(true));
1805 match c.peek(&mut b) {
1806 Ok(_) => panic!("expected error"),
1807 Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
1808 Err(e) => panic!("unexpected error {}", e),
1809 }
1810 t!(txdone.send(()));
1811 })
1812 }
041b39d2 1813
abe05a73 1814 #[test]
532ac7d7 1815 #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
041b39d2
XL
1816 fn connect_timeout_valid() {
1817 let listener = TcpListener::bind("127.0.0.1:0").unwrap();
1818 let addr = listener.local_addr().unwrap();
1819 TcpStream::connect_timeout(&addr, Duration::from_secs(2)).unwrap();
1820 }
85aaf69f 1821}