]>
Commit | Line | Data |
---|---|---|
1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT | |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | use io::prelude::*; | |
12 | ||
13 | use fmt; | |
14 | use io; | |
15 | use net::{ToSocketAddrs, SocketAddr, Shutdown}; | |
16 | use sys_common::net as net_imp; | |
17 | use sys_common::{AsInner, FromInner, IntoInner}; | |
18 | use time::Duration; | |
19 | ||
20 | /// A structure which represents a TCP stream between a local socket and a | |
21 | /// remote socket. | |
22 | /// | |
23 | /// The socket will be closed when the value is dropped. | |
24 | /// | |
25 | /// # Examples | |
26 | /// | |
27 | /// ```no_run | |
28 | /// use std::io::prelude::*; | |
29 | /// use std::net::TcpStream; | |
30 | /// | |
31 | /// { | |
32 | /// let mut stream = TcpStream::connect("127.0.0.1:34254").unwrap(); | |
33 | /// | |
34 | /// // ignore the Result | |
35 | /// let _ = stream.write(&[1]); | |
36 | /// let _ = stream.read(&mut [0; 128]); // ignore here too | |
37 | /// } // the stream is closed here | |
38 | /// ``` | |
39 | #[stable(feature = "rust1", since = "1.0.0")] | |
40 | pub struct TcpStream(net_imp::TcpStream); | |
41 | ||
42 | /// A structure representing a socket server. | |
43 | /// | |
44 | /// # Examples | |
45 | /// | |
46 | /// ```no_run | |
47 | /// use std::net::{TcpListener, TcpStream}; | |
48 | /// | |
49 | /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); | |
50 | /// | |
51 | /// fn handle_client(stream: TcpStream) { | |
52 | /// // ... | |
53 | /// } | |
54 | /// | |
55 | /// // accept connections and process them serially | |
56 | /// for stream in listener.incoming() { | |
57 | /// match stream { | |
58 | /// Ok(stream) => { | |
59 | /// handle_client(stream); | |
60 | /// } | |
61 | /// Err(e) => { /* connection failed */ } | |
62 | /// } | |
63 | /// } | |
64 | /// ``` | |
65 | #[stable(feature = "rust1", since = "1.0.0")] | |
66 | pub struct TcpListener(net_imp::TcpListener); | |
67 | ||
68 | /// An infinite iterator over the connections from a `TcpListener`. | |
69 | /// | |
70 | /// This iterator will infinitely yield [`Some`] of the accepted connections. It | |
71 | /// is equivalent to calling `accept` in a loop. | |
72 | /// | |
73 | /// This `struct` is created by the [`incoming`] method on [`TcpListener`]. | |
74 | /// | |
75 | /// [`Some`]: ../../std/option/enum.Option.html#variant.Some | |
76 | /// [`incoming`]: struct.TcpListener.html#method.incoming | |
77 | /// [`TcpListener`]: struct.TcpListener.html | |
78 | #[stable(feature = "rust1", since = "1.0.0")] | |
79 | #[derive(Debug)] | |
80 | pub struct Incoming<'a> { listener: &'a TcpListener } | |
81 | ||
82 | impl TcpStream { | |
83 | /// Opens a TCP connection to a remote host. | |
84 | /// | |
85 | /// `addr` is an address of the remote host. Anything which implements | |
86 | /// `ToSocketAddrs` trait can be supplied for the address; see this trait | |
87 | /// documentation for concrete examples. | |
88 | /// In case `ToSocketAddrs::to_socket_addrs()` returns more than one entry, | |
89 | /// then the first valid and reachable address is used. | |
90 | /// | |
91 | /// # Examples | |
92 | /// | |
93 | /// ```no_run | |
94 | /// use std::net::TcpStream; | |
95 | /// | |
96 | /// if let Ok(stream) = TcpStream::connect("127.0.0.1:8080") { | |
97 | /// println!("Connected to the server!"); | |
98 | /// } else { | |
99 | /// println!("Couldn't connect to server..."); | |
100 | /// } | |
101 | /// ``` | |
102 | #[stable(feature = "rust1", since = "1.0.0")] | |
103 | pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> { | |
104 | super::each_addr(addr, net_imp::TcpStream::connect).map(TcpStream) | |
105 | } | |
106 | ||
107 | /// Returns the socket address of the remote peer of this TCP connection. | |
108 | /// | |
109 | /// # Examples | |
110 | /// | |
111 | /// ```no_run | |
112 | /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream}; | |
113 | /// | |
114 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
115 | /// .expect("Couldn't connect to the server..."); | |
116 | /// assert_eq!(stream.peer_addr().unwrap(), | |
117 | /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080))); | |
118 | /// ``` | |
119 | #[stable(feature = "rust1", since = "1.0.0")] | |
120 | pub fn peer_addr(&self) -> io::Result<SocketAddr> { | |
121 | self.0.peer_addr() | |
122 | } | |
123 | ||
124 | /// Returns the socket address of the local half of this TCP connection. | |
125 | /// | |
126 | /// # Examples | |
127 | /// | |
128 | /// ```no_run | |
129 | /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpStream}; | |
130 | /// | |
131 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
132 | /// .expect("Couldn't connect to the server..."); | |
133 | /// assert_eq!(stream.local_addr().unwrap(), | |
134 | /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080))); | |
135 | /// ``` | |
136 | #[stable(feature = "rust1", since = "1.0.0")] | |
137 | pub fn local_addr(&self) -> io::Result<SocketAddr> { | |
138 | self.0.socket_addr() | |
139 | } | |
140 | ||
141 | /// Shuts down the read, write, or both halves of this connection. | |
142 | /// | |
143 | /// This function will cause all pending and future I/O on the specified | |
144 | /// portions to return immediately with an appropriate value (see the | |
145 | /// documentation of [`Shutdown`]). | |
146 | /// | |
147 | /// [`Shutdown`]: ../../std/net/enum.Shutdown.html | |
148 | /// | |
149 | /// # Examples | |
150 | /// | |
151 | /// ```no_run | |
152 | /// use std::net::{Shutdown, TcpStream}; | |
153 | /// | |
154 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
155 | /// .expect("Couldn't connect to the server..."); | |
156 | /// stream.shutdown(Shutdown::Both).expect("shutdown call failed"); | |
157 | /// ``` | |
158 | #[stable(feature = "rust1", since = "1.0.0")] | |
159 | pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { | |
160 | self.0.shutdown(how) | |
161 | } | |
162 | ||
163 | /// Creates a new independently owned handle to the underlying socket. | |
164 | /// | |
165 | /// The returned `TcpStream` is a reference to the same stream that this | |
166 | /// object references. Both handles will read and write the same stream of | |
167 | /// data, and options set on one stream will be propagated to the other | |
168 | /// stream. | |
169 | /// | |
170 | /// # Examples | |
171 | /// | |
172 | /// ```no_run | |
173 | /// use std::net::TcpStream; | |
174 | /// | |
175 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
176 | /// .expect("Couldn't connect to the server..."); | |
177 | /// let stream_clone = stream.try_clone().expect("clone failed..."); | |
178 | /// ``` | |
179 | #[stable(feature = "rust1", since = "1.0.0")] | |
180 | pub fn try_clone(&self) -> io::Result<TcpStream> { | |
181 | self.0.duplicate().map(TcpStream) | |
182 | } | |
183 | ||
184 | /// Sets the read timeout to the timeout specified. | |
185 | /// | |
186 | /// If the value specified is [`None`], then [`read()`] calls will block | |
187 | /// indefinitely. It is an error to pass the zero `Duration` to this | |
188 | /// method. | |
189 | /// | |
190 | /// # Note | |
191 | /// | |
192 | /// Platforms may return a different error code whenever a read times out as | |
193 | /// a result of setting this option. For example Unix typically returns an | |
194 | /// error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. | |
195 | /// | |
196 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
197 | /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read | |
198 | /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock | |
199 | /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut | |
200 | /// | |
201 | /// # Examples | |
202 | /// | |
203 | /// ```no_run | |
204 | /// use std::net::TcpStream; | |
205 | /// | |
206 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
207 | /// .expect("Couldn't connect to the server..."); | |
208 | /// stream.set_read_timeout(None).expect("set_read_timeout call failed"); | |
209 | /// ``` | |
210 | #[stable(feature = "socket_timeout", since = "1.4.0")] | |
211 | pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> { | |
212 | self.0.set_read_timeout(dur) | |
213 | } | |
214 | ||
215 | /// Sets the write timeout to the timeout specified. | |
216 | /// | |
217 | /// If the value specified is [`None`], then [`write()`] calls will block | |
218 | /// indefinitely. It is an error to pass the zero [`Duration`] to this | |
219 | /// method. | |
220 | /// | |
221 | /// # Note | |
222 | /// | |
223 | /// Platforms may return a different error code whenever a write times out | |
224 | /// as a result of setting this option. For example Unix typically returns | |
225 | /// an error of the kind [`WouldBlock`], but Windows may return [`TimedOut`]. | |
226 | /// | |
227 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
228 | /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write | |
229 | /// [`Duration`]: ../../std/time/struct.Duration.html | |
230 | /// [`WouldBlock`]: ../../std/io/enum.ErrorKind.html#variant.WouldBlock | |
231 | /// [`TimedOut`]: ../../std/io/enum.ErrorKind.html#variant.TimedOut | |
232 | /// | |
233 | /// # Examples | |
234 | /// | |
235 | /// ```no_run | |
236 | /// use std::net::TcpStream; | |
237 | /// | |
238 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
239 | /// .expect("Couldn't connect to the server..."); | |
240 | /// stream.set_write_timeout(None).expect("set_write_timeout call failed"); | |
241 | /// ``` | |
242 | #[stable(feature = "socket_timeout", since = "1.4.0")] | |
243 | pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> { | |
244 | self.0.set_write_timeout(dur) | |
245 | } | |
246 | ||
247 | /// Returns the read timeout of this socket. | |
248 | /// | |
249 | /// If the timeout is [`None`], then [`read()`] calls will block indefinitely. | |
250 | /// | |
251 | /// # Note | |
252 | /// | |
253 | /// Some platforms do not provide access to the current timeout. | |
254 | /// | |
255 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
256 | /// [`read()`]: ../../std/io/trait.Read.html#tymethod.read | |
257 | /// | |
258 | /// # Examples | |
259 | /// | |
260 | /// ```no_run | |
261 | /// use std::net::TcpStream; | |
262 | /// | |
263 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
264 | /// .expect("Couldn't connect to the server..."); | |
265 | /// stream.set_read_timeout(None).expect("set_read_timeout call failed"); | |
266 | /// assert_eq!(stream.read_timeout().unwrap(), None); | |
267 | /// ``` | |
268 | #[stable(feature = "socket_timeout", since = "1.4.0")] | |
269 | pub fn read_timeout(&self) -> io::Result<Option<Duration>> { | |
270 | self.0.read_timeout() | |
271 | } | |
272 | ||
273 | /// Returns the write timeout of this socket. | |
274 | /// | |
275 | /// If the timeout is [`None`], then [`write()`] calls will block indefinitely. | |
276 | /// | |
277 | /// # Note | |
278 | /// | |
279 | /// Some platforms do not provide access to the current timeout. | |
280 | /// | |
281 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
282 | /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write | |
283 | /// | |
284 | /// # Examples | |
285 | /// | |
286 | /// ```no_run | |
287 | /// use std::net::TcpStream; | |
288 | /// | |
289 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
290 | /// .expect("Couldn't connect to the server..."); | |
291 | /// stream.set_write_timeout(None).expect("set_write_timeout call failed"); | |
292 | /// assert_eq!(stream.write_timeout().unwrap(), None); | |
293 | /// ``` | |
294 | #[stable(feature = "socket_timeout", since = "1.4.0")] | |
295 | pub fn write_timeout(&self) -> io::Result<Option<Duration>> { | |
296 | self.0.write_timeout() | |
297 | } | |
298 | ||
299 | /// Receives data on the socket from the remote adress to which it is | |
300 | /// connected, without removing that data from the queue. On success, | |
301 | /// returns the number of bytes peeked. | |
302 | /// | |
303 | /// Successive calls return the same data. This is accomplished by passing | |
304 | /// `MSG_PEEK` as a flag to the underlying `recv` system call. | |
305 | /// | |
306 | /// # Examples | |
307 | /// | |
308 | /// ```no_run | |
309 | /// #![feature(peek)] | |
310 | /// use std::net::TcpStream; | |
311 | /// | |
312 | /// let stream = TcpStream::connect("127.0.0.1:8000") | |
313 | /// .expect("couldn't bind to address"); | |
314 | /// let mut buf = [0; 10]; | |
315 | /// let len = stream.peek(&mut buf).expect("peek failed"); | |
316 | /// ``` | |
317 | #[unstable(feature = "peek", issue = "38980")] | |
318 | pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { | |
319 | self.0.peek(buf) | |
320 | } | |
321 | ||
322 | /// Sets the value of the `TCP_NODELAY` option on this socket. | |
323 | /// | |
324 | /// If set, this option disables the Nagle algorithm. This means that | |
325 | /// segments are always sent as soon as possible, even if there is only a | |
326 | /// small amount of data. When not set, data is buffered until there is a | |
327 | /// sufficient amount to send out, thereby avoiding the frequent sending of | |
328 | /// small packets. | |
329 | /// | |
330 | /// # Examples | |
331 | /// | |
332 | /// ```no_run | |
333 | /// use std::net::TcpStream; | |
334 | /// | |
335 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
336 | /// .expect("Couldn't connect to the server..."); | |
337 | /// stream.set_nodelay(true).expect("set_nodelay call failed"); | |
338 | /// ``` | |
339 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
340 | pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { | |
341 | self.0.set_nodelay(nodelay) | |
342 | } | |
343 | ||
344 | /// Gets the value of the `TCP_NODELAY` option on this socket. | |
345 | /// | |
346 | /// For more information about this option, see [`set_nodelay`][link]. | |
347 | /// | |
348 | /// [link]: #method.set_nodelay | |
349 | /// | |
350 | /// # Examples | |
351 | /// | |
352 | /// ```no_run | |
353 | /// use std::net::TcpStream; | |
354 | /// | |
355 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
356 | /// .expect("Couldn't connect to the server..."); | |
357 | /// stream.set_nodelay(true).expect("set_nodelay call failed"); | |
358 | /// assert_eq!(stream.nodelay().unwrap_or(false), true); | |
359 | /// ``` | |
360 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
361 | pub fn nodelay(&self) -> io::Result<bool> { | |
362 | self.0.nodelay() | |
363 | } | |
364 | ||
365 | /// Sets the value for the `IP_TTL` option on this socket. | |
366 | /// | |
367 | /// This value sets the time-to-live field that is used in every packet sent | |
368 | /// from this socket. | |
369 | /// | |
370 | /// # Examples | |
371 | /// | |
372 | /// ```no_run | |
373 | /// use std::net::TcpStream; | |
374 | /// | |
375 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
376 | /// .expect("Couldn't connect to the server..."); | |
377 | /// stream.set_ttl(100).expect("set_ttl call failed"); | |
378 | /// ``` | |
379 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
380 | pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { | |
381 | self.0.set_ttl(ttl) | |
382 | } | |
383 | ||
384 | /// Gets the value of the `IP_TTL` option for this socket. | |
385 | /// | |
386 | /// For more information about this option, see [`set_ttl`][link]. | |
387 | /// | |
388 | /// [link]: #method.set_ttl | |
389 | /// | |
390 | /// # Examples | |
391 | /// | |
392 | /// ```no_run | |
393 | /// use std::net::TcpStream; | |
394 | /// | |
395 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
396 | /// .expect("Couldn't connect to the server..."); | |
397 | /// stream.set_ttl(100).expect("set_ttl call failed"); | |
398 | /// assert_eq!(stream.ttl().unwrap_or(0), 100); | |
399 | /// ``` | |
400 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
401 | pub fn ttl(&self) -> io::Result<u32> { | |
402 | self.0.ttl() | |
403 | } | |
404 | ||
405 | /// Get the value of the `SO_ERROR` option on this socket. | |
406 | /// | |
407 | /// This will retrieve the stored error in the underlying socket, clearing | |
408 | /// the field in the process. This can be useful for checking errors between | |
409 | /// calls. | |
410 | /// | |
411 | /// # Examples | |
412 | /// | |
413 | /// ```no_run | |
414 | /// use std::net::TcpStream; | |
415 | /// | |
416 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
417 | /// .expect("Couldn't connect to the server..."); | |
418 | /// stream.take_error().expect("No error was expected..."); | |
419 | /// ``` | |
420 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
421 | pub fn take_error(&self) -> io::Result<Option<io::Error>> { | |
422 | self.0.take_error() | |
423 | } | |
424 | ||
425 | /// Moves this TCP stream into or out of nonblocking mode. | |
426 | /// | |
427 | /// On Unix this corresponds to calling fcntl, and on Windows this | |
428 | /// corresponds to calling ioctlsocket. | |
429 | /// | |
430 | /// # Examples | |
431 | /// | |
432 | /// ```no_run | |
433 | /// use std::net::TcpStream; | |
434 | /// | |
435 | /// let stream = TcpStream::connect("127.0.0.1:8080") | |
436 | /// .expect("Couldn't connect to the server..."); | |
437 | /// stream.set_nonblocking(true).expect("set_nonblocking call failed"); | |
438 | /// ``` | |
439 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
440 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { | |
441 | self.0.set_nonblocking(nonblocking) | |
442 | } | |
443 | } | |
444 | ||
445 | #[stable(feature = "rust1", since = "1.0.0")] | |
446 | impl Read for TcpStream { | |
447 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } | |
448 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { | |
449 | self.0.read_to_end(buf) | |
450 | } | |
451 | } | |
452 | #[stable(feature = "rust1", since = "1.0.0")] | |
453 | impl Write for TcpStream { | |
454 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } | |
455 | fn flush(&mut self) -> io::Result<()> { Ok(()) } | |
456 | } | |
457 | #[stable(feature = "rust1", since = "1.0.0")] | |
458 | impl<'a> Read for &'a TcpStream { | |
459 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } | |
460 | fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { | |
461 | self.0.read_to_end(buf) | |
462 | } | |
463 | } | |
464 | #[stable(feature = "rust1", since = "1.0.0")] | |
465 | impl<'a> Write for &'a TcpStream { | |
466 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } | |
467 | fn flush(&mut self) -> io::Result<()> { Ok(()) } | |
468 | } | |
469 | ||
470 | impl AsInner<net_imp::TcpStream> for TcpStream { | |
471 | fn as_inner(&self) -> &net_imp::TcpStream { &self.0 } | |
472 | } | |
473 | ||
474 | impl FromInner<net_imp::TcpStream> for TcpStream { | |
475 | fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) } | |
476 | } | |
477 | ||
478 | impl IntoInner<net_imp::TcpStream> for TcpStream { | |
479 | fn into_inner(self) -> net_imp::TcpStream { self.0 } | |
480 | } | |
481 | ||
482 | #[stable(feature = "rust1", since = "1.0.0")] | |
483 | impl fmt::Debug for TcpStream { | |
484 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
485 | self.0.fmt(f) | |
486 | } | |
487 | } | |
488 | ||
489 | impl TcpListener { | |
490 | /// Creates a new `TcpListener` which will be bound to the specified | |
491 | /// address. | |
492 | /// | |
493 | /// The returned listener is ready for accepting connections. | |
494 | /// | |
495 | /// Binding with a port number of 0 will request that the OS assigns a port | |
496 | /// to this listener. The port allocated can be queried via the | |
497 | /// `local_addr` method. | |
498 | /// | |
499 | /// The address type can be any implementor of `ToSocketAddrs` trait. See | |
500 | /// its documentation for concrete examples. | |
501 | /// | |
502 | /// # Examples | |
503 | /// | |
504 | /// ```no_run | |
505 | /// use std::net::TcpListener; | |
506 | /// | |
507 | /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); | |
508 | /// ``` | |
509 | #[stable(feature = "rust1", since = "1.0.0")] | |
510 | pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> { | |
511 | super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener) | |
512 | } | |
513 | ||
514 | /// Returns the local socket address of this listener. | |
515 | /// | |
516 | /// # Examples | |
517 | /// | |
518 | /// ```no_run | |
519 | /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener}; | |
520 | /// | |
521 | /// let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); | |
522 | /// assert_eq!(listener.local_addr().unwrap(), | |
523 | /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080))); | |
524 | /// ``` | |
525 | #[stable(feature = "rust1", since = "1.0.0")] | |
526 | pub fn local_addr(&self) -> io::Result<SocketAddr> { | |
527 | self.0.socket_addr() | |
528 | } | |
529 | ||
530 | /// Creates a new independently owned handle to the underlying socket. | |
531 | /// | |
532 | /// The returned `TcpListener` is a reference to the same socket that this | |
533 | /// object references. Both handles can be used to accept incoming | |
534 | /// connections and options set on one listener will affect the other. | |
535 | /// | |
536 | /// # Examples | |
537 | /// | |
538 | /// ```no_run | |
539 | /// use std::net::TcpListener; | |
540 | /// | |
541 | /// let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); | |
542 | /// let listener_clone = listener.try_clone().unwrap(); | |
543 | /// ``` | |
544 | #[stable(feature = "rust1", since = "1.0.0")] | |
545 | pub fn try_clone(&self) -> io::Result<TcpListener> { | |
546 | self.0.duplicate().map(TcpListener) | |
547 | } | |
548 | ||
549 | /// Accept a new incoming connection from this listener. | |
550 | /// | |
551 | /// This function will block the calling thread until a new TCP connection | |
552 | /// is established. When established, the corresponding `TcpStream` and the | |
553 | /// remote peer's address will be returned. | |
554 | /// | |
555 | /// # Examples | |
556 | /// | |
557 | /// ```no_run | |
558 | /// use std::net::TcpListener; | |
559 | /// | |
560 | /// let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); | |
561 | /// match listener.accept() { | |
562 | /// Ok((_socket, addr)) => println!("new client: {:?}", addr), | |
563 | /// Err(e) => println!("couldn't get client: {:?}", e), | |
564 | /// } | |
565 | /// ``` | |
566 | #[stable(feature = "rust1", since = "1.0.0")] | |
567 | pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { | |
568 | self.0.accept().map(|(a, b)| (TcpStream(a), b)) | |
569 | } | |
570 | ||
571 | /// Returns an iterator over the connections being received on this | |
572 | /// listener. | |
573 | /// | |
574 | /// The returned iterator will never return [`None`] and will also not yield | |
575 | /// the peer's [`SocketAddr`] structure. | |
576 | /// | |
577 | /// [`None`]: ../../std/option/enum.Option.html#variant.None | |
578 | /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html | |
579 | /// | |
580 | /// # Examples | |
581 | /// | |
582 | /// ```no_run | |
583 | /// use std::net::TcpListener; | |
584 | /// | |
585 | /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); | |
586 | /// | |
587 | /// for stream in listener.incoming() { | |
588 | /// match stream { | |
589 | /// Ok(stream) => { | |
590 | /// println!("new client!"); | |
591 | /// } | |
592 | /// Err(e) => { /* connection failed */ } | |
593 | /// } | |
594 | /// } | |
595 | /// ``` | |
596 | #[stable(feature = "rust1", since = "1.0.0")] | |
597 | pub fn incoming(&self) -> Incoming { | |
598 | Incoming { listener: self } | |
599 | } | |
600 | ||
601 | /// Sets the value for the `IP_TTL` option on this socket. | |
602 | /// | |
603 | /// This value sets the time-to-live field that is used in every packet sent | |
604 | /// from this socket. | |
605 | /// | |
606 | /// # Examples | |
607 | /// | |
608 | /// ```no_run | |
609 | /// use std::net::TcpListener; | |
610 | /// | |
611 | /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); | |
612 | /// listener.set_ttl(100).expect("could not set TTL"); | |
613 | /// ``` | |
614 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
615 | pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { | |
616 | self.0.set_ttl(ttl) | |
617 | } | |
618 | ||
619 | /// Gets the value of the `IP_TTL` option for this socket. | |
620 | /// | |
621 | /// For more information about this option, see [`set_ttl()`][link]. | |
622 | /// | |
623 | /// [link]: #method.set_ttl | |
624 | /// | |
625 | /// # Examples | |
626 | /// | |
627 | /// ```no_run | |
628 | /// use std::net::TcpListener; | |
629 | /// | |
630 | /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); | |
631 | /// listener.set_ttl(100).expect("could not set TTL"); | |
632 | /// assert_eq!(listener.ttl().unwrap_or(0), 100); | |
633 | /// ``` | |
634 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
635 | pub fn ttl(&self) -> io::Result<u32> { | |
636 | self.0.ttl() | |
637 | } | |
638 | ||
639 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
640 | #[rustc_deprecated(since = "1.16.0", | |
641 | reason = "this option can only be set before the socket is bound")] | |
642 | #[allow(missing_docs)] | |
643 | pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { | |
644 | self.0.set_only_v6(only_v6) | |
645 | } | |
646 | ||
647 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
648 | #[rustc_deprecated(since = "1.16.0", | |
649 | reason = "this option can only be set before the socket is bound")] | |
650 | #[allow(missing_docs)] | |
651 | pub fn only_v6(&self) -> io::Result<bool> { | |
652 | self.0.only_v6() | |
653 | } | |
654 | ||
655 | /// Get the value of the `SO_ERROR` option on this socket. | |
656 | /// | |
657 | /// This will retrieve the stored error in the underlying socket, clearing | |
658 | /// the field in the process. This can be useful for checking errors between | |
659 | /// calls. | |
660 | /// | |
661 | /// # Examples | |
662 | /// | |
663 | /// ```no_run | |
664 | /// use std::net::TcpListener; | |
665 | /// | |
666 | /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); | |
667 | /// listener.take_error().expect("No error was expected"); | |
668 | /// ``` | |
669 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
670 | pub fn take_error(&self) -> io::Result<Option<io::Error>> { | |
671 | self.0.take_error() | |
672 | } | |
673 | ||
674 | /// Moves this TCP stream into or out of nonblocking mode. | |
675 | /// | |
676 | /// On Unix this corresponds to calling fcntl, and on Windows this | |
677 | /// corresponds to calling ioctlsocket. | |
678 | /// | |
679 | /// # Examples | |
680 | /// | |
681 | /// ```no_run | |
682 | /// use std::net::TcpListener; | |
683 | /// | |
684 | /// let listener = TcpListener::bind("127.0.0.1:80").unwrap(); | |
685 | /// listener.set_nonblocking(true).expect("Cannot set non-blocking"); | |
686 | /// ``` | |
687 | #[stable(feature = "net2_mutators", since = "1.9.0")] | |
688 | pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { | |
689 | self.0.set_nonblocking(nonblocking) | |
690 | } | |
691 | } | |
692 | ||
693 | #[stable(feature = "rust1", since = "1.0.0")] | |
694 | impl<'a> Iterator for Incoming<'a> { | |
695 | type Item = io::Result<TcpStream>; | |
696 | fn next(&mut self) -> Option<io::Result<TcpStream>> { | |
697 | Some(self.listener.accept().map(|p| p.0)) | |
698 | } | |
699 | } | |
700 | ||
701 | impl AsInner<net_imp::TcpListener> for TcpListener { | |
702 | fn as_inner(&self) -> &net_imp::TcpListener { &self.0 } | |
703 | } | |
704 | ||
705 | impl FromInner<net_imp::TcpListener> for TcpListener { | |
706 | fn from_inner(inner: net_imp::TcpListener) -> TcpListener { | |
707 | TcpListener(inner) | |
708 | } | |
709 | } | |
710 | ||
711 | impl IntoInner<net_imp::TcpListener> for TcpListener { | |
712 | fn into_inner(self) -> net_imp::TcpListener { self.0 } | |
713 | } | |
714 | ||
715 | #[stable(feature = "rust1", since = "1.0.0")] | |
716 | impl fmt::Debug for TcpListener { | |
717 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
718 | self.0.fmt(f) | |
719 | } | |
720 | } | |
721 | ||
722 | #[cfg(all(test, not(target_os = "emscripten")))] | |
723 | mod tests { | |
724 | use io::ErrorKind; | |
725 | use io::prelude::*; | |
726 | use net::*; | |
727 | use net::test::{next_test_ip4, next_test_ip6}; | |
728 | use sync::mpsc::channel; | |
729 | use sys_common::AsInner; | |
730 | use time::{Instant, Duration}; | |
731 | use thread; | |
732 | ||
733 | fn each_ip(f: &mut FnMut(SocketAddr)) { | |
734 | f(next_test_ip4()); | |
735 | f(next_test_ip6()); | |
736 | } | |
737 | ||
738 | macro_rules! t { | |
739 | ($e:expr) => { | |
740 | match $e { | |
741 | Ok(t) => t, | |
742 | Err(e) => panic!("received error for `{}`: {}", stringify!($e), e), | |
743 | } | |
744 | } | |
745 | } | |
746 | ||
747 | #[test] | |
748 | fn bind_error() { | |
749 | match TcpListener::bind("1.1.1.1:9999") { | |
750 | Ok(..) => panic!(), | |
751 | Err(e) => | |
752 | assert_eq!(e.kind(), ErrorKind::AddrNotAvailable), | |
753 | } | |
754 | } | |
755 | ||
756 | #[test] | |
757 | fn connect_error() { | |
758 | match TcpStream::connect("0.0.0.0:1") { | |
759 | Ok(..) => panic!(), | |
760 | Err(e) => assert!(e.kind() == ErrorKind::ConnectionRefused || | |
761 | e.kind() == ErrorKind::InvalidInput || | |
762 | e.kind() == ErrorKind::AddrInUse || | |
763 | e.kind() == ErrorKind::AddrNotAvailable, | |
764 | "bad error: {} {:?}", e, e.kind()), | |
765 | } | |
766 | } | |
767 | ||
768 | #[test] | |
769 | fn listen_localhost() { | |
770 | let socket_addr = next_test_ip4(); | |
771 | let listener = t!(TcpListener::bind(&socket_addr)); | |
772 | ||
773 | let _t = thread::spawn(move || { | |
774 | let mut stream = t!(TcpStream::connect(&("localhost", | |
775 | socket_addr.port()))); | |
776 | t!(stream.write(&[144])); | |
777 | }); | |
778 | ||
779 | let mut stream = t!(listener.accept()).0; | |
780 | let mut buf = [0]; | |
781 | t!(stream.read(&mut buf)); | |
782 | assert!(buf[0] == 144); | |
783 | } | |
784 | ||
785 | #[test] | |
786 | fn connect_loopback() { | |
787 | each_ip(&mut |addr| { | |
788 | let acceptor = t!(TcpListener::bind(&addr)); | |
789 | ||
790 | let _t = thread::spawn(move|| { | |
791 | let host = match addr { | |
792 | SocketAddr::V4(..) => "127.0.0.1", | |
793 | SocketAddr::V6(..) => "::1", | |
794 | }; | |
795 | let mut stream = t!(TcpStream::connect(&(host, addr.port()))); | |
796 | t!(stream.write(&[66])); | |
797 | }); | |
798 | ||
799 | let mut stream = t!(acceptor.accept()).0; | |
800 | let mut buf = [0]; | |
801 | t!(stream.read(&mut buf)); | |
802 | assert!(buf[0] == 66); | |
803 | }) | |
804 | } | |
805 | ||
806 | #[test] | |
807 | fn smoke_test() { | |
808 | each_ip(&mut |addr| { | |
809 | let acceptor = t!(TcpListener::bind(&addr)); | |
810 | ||
811 | let (tx, rx) = channel(); | |
812 | let _t = thread::spawn(move|| { | |
813 | let mut stream = t!(TcpStream::connect(&addr)); | |
814 | t!(stream.write(&[99])); | |
815 | tx.send(t!(stream.local_addr())).unwrap(); | |
816 | }); | |
817 | ||
818 | let (mut stream, addr) = t!(acceptor.accept()); | |
819 | let mut buf = [0]; | |
820 | t!(stream.read(&mut buf)); | |
821 | assert!(buf[0] == 99); | |
822 | assert_eq!(addr, t!(rx.recv())); | |
823 | }) | |
824 | } | |
825 | ||
826 | #[test] | |
827 | fn read_eof() { | |
828 | each_ip(&mut |addr| { | |
829 | let acceptor = t!(TcpListener::bind(&addr)); | |
830 | ||
831 | let _t = thread::spawn(move|| { | |
832 | let _stream = t!(TcpStream::connect(&addr)); | |
833 | // Close | |
834 | }); | |
835 | ||
836 | let mut stream = t!(acceptor.accept()).0; | |
837 | let mut buf = [0]; | |
838 | let nread = t!(stream.read(&mut buf)); | |
839 | assert_eq!(nread, 0); | |
840 | let nread = t!(stream.read(&mut buf)); | |
841 | assert_eq!(nread, 0); | |
842 | }) | |
843 | } | |
844 | ||
845 | #[test] | |
846 | fn write_close() { | |
847 | each_ip(&mut |addr| { | |
848 | let acceptor = t!(TcpListener::bind(&addr)); | |
849 | ||
850 | let (tx, rx) = channel(); | |
851 | let _t = thread::spawn(move|| { | |
852 | drop(t!(TcpStream::connect(&addr))); | |
853 | tx.send(()).unwrap(); | |
854 | }); | |
855 | ||
856 | let mut stream = t!(acceptor.accept()).0; | |
857 | rx.recv().unwrap(); | |
858 | let buf = [0]; | |
859 | match stream.write(&buf) { | |
860 | Ok(..) => {} | |
861 | Err(e) => { | |
862 | assert!(e.kind() == ErrorKind::ConnectionReset || | |
863 | e.kind() == ErrorKind::BrokenPipe || | |
864 | e.kind() == ErrorKind::ConnectionAborted, | |
865 | "unknown error: {}", e); | |
866 | } | |
867 | } | |
868 | }) | |
869 | } | |
870 | ||
871 | #[test] | |
872 | fn multiple_connect_serial() { | |
873 | each_ip(&mut |addr| { | |
874 | let max = 10; | |
875 | let acceptor = t!(TcpListener::bind(&addr)); | |
876 | ||
877 | let _t = thread::spawn(move|| { | |
878 | for _ in 0..max { | |
879 | let mut stream = t!(TcpStream::connect(&addr)); | |
880 | t!(stream.write(&[99])); | |
881 | } | |
882 | }); | |
883 | ||
884 | for stream in acceptor.incoming().take(max) { | |
885 | let mut stream = t!(stream); | |
886 | let mut buf = [0]; | |
887 | t!(stream.read(&mut buf)); | |
888 | assert_eq!(buf[0], 99); | |
889 | } | |
890 | }) | |
891 | } | |
892 | ||
893 | #[test] | |
894 | fn multiple_connect_interleaved_greedy_schedule() { | |
895 | const MAX: usize = 10; | |
896 | each_ip(&mut |addr| { | |
897 | let acceptor = t!(TcpListener::bind(&addr)); | |
898 | ||
899 | let _t = thread::spawn(move|| { | |
900 | let acceptor = acceptor; | |
901 | for (i, stream) in acceptor.incoming().enumerate().take(MAX) { | |
902 | // Start another thread to handle the connection | |
903 | let _t = thread::spawn(move|| { | |
904 | let mut stream = t!(stream); | |
905 | let mut buf = [0]; | |
906 | t!(stream.read(&mut buf)); | |
907 | assert!(buf[0] == i as u8); | |
908 | }); | |
909 | } | |
910 | }); | |
911 | ||
912 | connect(0, addr); | |
913 | }); | |
914 | ||
915 | fn connect(i: usize, addr: SocketAddr) { | |
916 | if i == MAX { return } | |
917 | ||
918 | let t = thread::spawn(move|| { | |
919 | let mut stream = t!(TcpStream::connect(&addr)); | |
920 | // Connect again before writing | |
921 | connect(i + 1, addr); | |
922 | t!(stream.write(&[i as u8])); | |
923 | }); | |
924 | t.join().ok().unwrap(); | |
925 | } | |
926 | } | |
927 | ||
928 | #[test] | |
929 | fn multiple_connect_interleaved_lazy_schedule() { | |
930 | const MAX: usize = 10; | |
931 | each_ip(&mut |addr| { | |
932 | let acceptor = t!(TcpListener::bind(&addr)); | |
933 | ||
934 | let _t = thread::spawn(move|| { | |
935 | for stream in acceptor.incoming().take(MAX) { | |
936 | // Start another thread to handle the connection | |
937 | let _t = thread::spawn(move|| { | |
938 | let mut stream = t!(stream); | |
939 | let mut buf = [0]; | |
940 | t!(stream.read(&mut buf)); | |
941 | assert!(buf[0] == 99); | |
942 | }); | |
943 | } | |
944 | }); | |
945 | ||
946 | connect(0, addr); | |
947 | }); | |
948 | ||
949 | fn connect(i: usize, addr: SocketAddr) { | |
950 | if i == MAX { return } | |
951 | ||
952 | let t = thread::spawn(move|| { | |
953 | let mut stream = t!(TcpStream::connect(&addr)); | |
954 | connect(i + 1, addr); | |
955 | t!(stream.write(&[99])); | |
956 | }); | |
957 | t.join().ok().unwrap(); | |
958 | } | |
959 | } | |
960 | ||
961 | #[test] | |
962 | fn socket_and_peer_name() { | |
963 | each_ip(&mut |addr| { | |
964 | let listener = t!(TcpListener::bind(&addr)); | |
965 | let so_name = t!(listener.local_addr()); | |
966 | assert_eq!(addr, so_name); | |
967 | let _t = thread::spawn(move|| { | |
968 | t!(listener.accept()); | |
969 | }); | |
970 | ||
971 | let stream = t!(TcpStream::connect(&addr)); | |
972 | assert_eq!(addr, t!(stream.peer_addr())); | |
973 | }) | |
974 | } | |
975 | ||
976 | #[test] | |
977 | fn partial_read() { | |
978 | each_ip(&mut |addr| { | |
979 | let (tx, rx) = channel(); | |
980 | let srv = t!(TcpListener::bind(&addr)); | |
981 | let _t = thread::spawn(move|| { | |
982 | let mut cl = t!(srv.accept()).0; | |
983 | cl.write(&[10]).unwrap(); | |
984 | let mut b = [0]; | |
985 | t!(cl.read(&mut b)); | |
986 | tx.send(()).unwrap(); | |
987 | }); | |
988 | ||
989 | let mut c = t!(TcpStream::connect(&addr)); | |
990 | let mut b = [0; 10]; | |
991 | assert_eq!(c.read(&mut b).unwrap(), 1); | |
992 | t!(c.write(&[1])); | |
993 | rx.recv().unwrap(); | |
994 | }) | |
995 | } | |
996 | ||
997 | #[test] | |
998 | fn double_bind() { | |
999 | each_ip(&mut |addr| { | |
1000 | let _listener = t!(TcpListener::bind(&addr)); | |
1001 | match TcpListener::bind(&addr) { | |
1002 | Ok(..) => panic!(), | |
1003 | Err(e) => { | |
1004 | assert!(e.kind() == ErrorKind::ConnectionRefused || | |
1005 | e.kind() == ErrorKind::Other || | |
1006 | e.kind() == ErrorKind::AddrInUse, | |
1007 | "unknown error: {} {:?}", e, e.kind()); | |
1008 | } | |
1009 | } | |
1010 | }) | |
1011 | } | |
1012 | ||
1013 | #[test] | |
1014 | fn fast_rebind() { | |
1015 | each_ip(&mut |addr| { | |
1016 | let acceptor = t!(TcpListener::bind(&addr)); | |
1017 | ||
1018 | let _t = thread::spawn(move|| { | |
1019 | t!(TcpStream::connect(&addr)); | |
1020 | }); | |
1021 | ||
1022 | t!(acceptor.accept()); | |
1023 | drop(acceptor); | |
1024 | t!(TcpListener::bind(&addr)); | |
1025 | }); | |
1026 | } | |
1027 | ||
1028 | #[test] | |
1029 | fn tcp_clone_smoke() { | |
1030 | each_ip(&mut |addr| { | |
1031 | let acceptor = t!(TcpListener::bind(&addr)); | |
1032 | ||
1033 | let _t = thread::spawn(move|| { | |
1034 | let mut s = t!(TcpStream::connect(&addr)); | |
1035 | let mut buf = [0, 0]; | |
1036 | assert_eq!(s.read(&mut buf).unwrap(), 1); | |
1037 | assert_eq!(buf[0], 1); | |
1038 | t!(s.write(&[2])); | |
1039 | }); | |
1040 | ||
1041 | let mut s1 = t!(acceptor.accept()).0; | |
1042 | let s2 = t!(s1.try_clone()); | |
1043 | ||
1044 | let (tx1, rx1) = channel(); | |
1045 | let (tx2, rx2) = channel(); | |
1046 | let _t = thread::spawn(move|| { | |
1047 | let mut s2 = s2; | |
1048 | rx1.recv().unwrap(); | |
1049 | t!(s2.write(&[1])); | |
1050 | tx2.send(()).unwrap(); | |
1051 | }); | |
1052 | tx1.send(()).unwrap(); | |
1053 | let mut buf = [0, 0]; | |
1054 | assert_eq!(s1.read(&mut buf).unwrap(), 1); | |
1055 | rx2.recv().unwrap(); | |
1056 | }) | |
1057 | } | |
1058 | ||
1059 | #[test] | |
1060 | fn tcp_clone_two_read() { | |
1061 | each_ip(&mut |addr| { | |
1062 | let acceptor = t!(TcpListener::bind(&addr)); | |
1063 | let (tx1, rx) = channel(); | |
1064 | let tx2 = tx1.clone(); | |
1065 | ||
1066 | let _t = thread::spawn(move|| { | |
1067 | let mut s = t!(TcpStream::connect(&addr)); | |
1068 | t!(s.write(&[1])); | |
1069 | rx.recv().unwrap(); | |
1070 | t!(s.write(&[2])); | |
1071 | rx.recv().unwrap(); | |
1072 | }); | |
1073 | ||
1074 | let mut s1 = t!(acceptor.accept()).0; | |
1075 | let s2 = t!(s1.try_clone()); | |
1076 | ||
1077 | let (done, rx) = channel(); | |
1078 | let _t = thread::spawn(move|| { | |
1079 | let mut s2 = s2; | |
1080 | let mut buf = [0, 0]; | |
1081 | t!(s2.read(&mut buf)); | |
1082 | tx2.send(()).unwrap(); | |
1083 | done.send(()).unwrap(); | |
1084 | }); | |
1085 | let mut buf = [0, 0]; | |
1086 | t!(s1.read(&mut buf)); | |
1087 | tx1.send(()).unwrap(); | |
1088 | ||
1089 | rx.recv().unwrap(); | |
1090 | }) | |
1091 | } | |
1092 | ||
1093 | #[test] | |
1094 | fn tcp_clone_two_write() { | |
1095 | each_ip(&mut |addr| { | |
1096 | let acceptor = t!(TcpListener::bind(&addr)); | |
1097 | ||
1098 | let _t = thread::spawn(move|| { | |
1099 | let mut s = t!(TcpStream::connect(&addr)); | |
1100 | let mut buf = [0, 1]; | |
1101 | t!(s.read(&mut buf)); | |
1102 | t!(s.read(&mut buf)); | |
1103 | }); | |
1104 | ||
1105 | let mut s1 = t!(acceptor.accept()).0; | |
1106 | let s2 = t!(s1.try_clone()); | |
1107 | ||
1108 | let (done, rx) = channel(); | |
1109 | let _t = thread::spawn(move|| { | |
1110 | let mut s2 = s2; | |
1111 | t!(s2.write(&[1])); | |
1112 | done.send(()).unwrap(); | |
1113 | }); | |
1114 | t!(s1.write(&[2])); | |
1115 | ||
1116 | rx.recv().unwrap(); | |
1117 | }) | |
1118 | } | |
1119 | ||
1120 | #[test] | |
1121 | fn shutdown_smoke() { | |
1122 | each_ip(&mut |addr| { | |
1123 | let a = t!(TcpListener::bind(&addr)); | |
1124 | let _t = thread::spawn(move|| { | |
1125 | let mut c = t!(a.accept()).0; | |
1126 | let mut b = [0]; | |
1127 | assert_eq!(c.read(&mut b).unwrap(), 0); | |
1128 | t!(c.write(&[1])); | |
1129 | }); | |
1130 | ||
1131 | let mut s = t!(TcpStream::connect(&addr)); | |
1132 | t!(s.shutdown(Shutdown::Write)); | |
1133 | assert!(s.write(&[1]).is_err()); | |
1134 | let mut b = [0, 0]; | |
1135 | assert_eq!(t!(s.read(&mut b)), 1); | |
1136 | assert_eq!(b[0], 1); | |
1137 | }) | |
1138 | } | |
1139 | ||
1140 | #[test] | |
1141 | fn close_readwrite_smoke() { | |
1142 | each_ip(&mut |addr| { | |
1143 | let a = t!(TcpListener::bind(&addr)); | |
1144 | let (tx, rx) = channel::<()>(); | |
1145 | let _t = thread::spawn(move|| { | |
1146 | let _s = t!(a.accept()); | |
1147 | let _ = rx.recv(); | |
1148 | }); | |
1149 | ||
1150 | let mut b = [0]; | |
1151 | let mut s = t!(TcpStream::connect(&addr)); | |
1152 | let mut s2 = t!(s.try_clone()); | |
1153 | ||
1154 | // closing should prevent reads/writes | |
1155 | t!(s.shutdown(Shutdown::Write)); | |
1156 | assert!(s.write(&[0]).is_err()); | |
1157 | t!(s.shutdown(Shutdown::Read)); | |
1158 | assert_eq!(s.read(&mut b).unwrap(), 0); | |
1159 | ||
1160 | // closing should affect previous handles | |
1161 | assert!(s2.write(&[0]).is_err()); | |
1162 | assert_eq!(s2.read(&mut b).unwrap(), 0); | |
1163 | ||
1164 | // closing should affect new handles | |
1165 | let mut s3 = t!(s.try_clone()); | |
1166 | assert!(s3.write(&[0]).is_err()); | |
1167 | assert_eq!(s3.read(&mut b).unwrap(), 0); | |
1168 | ||
1169 | // make sure these don't die | |
1170 | let _ = s2.shutdown(Shutdown::Read); | |
1171 | let _ = s2.shutdown(Shutdown::Write); | |
1172 | let _ = s3.shutdown(Shutdown::Read); | |
1173 | let _ = s3.shutdown(Shutdown::Write); | |
1174 | drop(tx); | |
1175 | }) | |
1176 | } | |
1177 | ||
1178 | #[test] | |
1179 | #[cfg(unix)] // test doesn't work on Windows, see #31657 | |
1180 | fn close_read_wakes_up() { | |
1181 | each_ip(&mut |addr| { | |
1182 | let a = t!(TcpListener::bind(&addr)); | |
1183 | let (tx1, rx) = channel::<()>(); | |
1184 | let _t = thread::spawn(move|| { | |
1185 | let _s = t!(a.accept()); | |
1186 | let _ = rx.recv(); | |
1187 | }); | |
1188 | ||
1189 | let s = t!(TcpStream::connect(&addr)); | |
1190 | let s2 = t!(s.try_clone()); | |
1191 | let (tx, rx) = channel(); | |
1192 | let _t = thread::spawn(move|| { | |
1193 | let mut s2 = s2; | |
1194 | assert_eq!(t!(s2.read(&mut [0])), 0); | |
1195 | tx.send(()).unwrap(); | |
1196 | }); | |
1197 | // this should wake up the child thread | |
1198 | t!(s.shutdown(Shutdown::Read)); | |
1199 | ||
1200 | // this test will never finish if the child doesn't wake up | |
1201 | rx.recv().unwrap(); | |
1202 | drop(tx1); | |
1203 | }) | |
1204 | } | |
1205 | ||
1206 | #[test] | |
1207 | fn clone_while_reading() { | |
1208 | each_ip(&mut |addr| { | |
1209 | let accept = t!(TcpListener::bind(&addr)); | |
1210 | ||
1211 | // Enqueue a thread to write to a socket | |
1212 | let (tx, rx) = channel(); | |
1213 | let (txdone, rxdone) = channel(); | |
1214 | let txdone2 = txdone.clone(); | |
1215 | let _t = thread::spawn(move|| { | |
1216 | let mut tcp = t!(TcpStream::connect(&addr)); | |
1217 | rx.recv().unwrap(); | |
1218 | t!(tcp.write(&[0])); | |
1219 | txdone2.send(()).unwrap(); | |
1220 | }); | |
1221 | ||
1222 | // Spawn off a reading clone | |
1223 | let tcp = t!(accept.accept()).0; | |
1224 | let tcp2 = t!(tcp.try_clone()); | |
1225 | let txdone3 = txdone.clone(); | |
1226 | let _t = thread::spawn(move|| { | |
1227 | let mut tcp2 = tcp2; | |
1228 | t!(tcp2.read(&mut [0])); | |
1229 | txdone3.send(()).unwrap(); | |
1230 | }); | |
1231 | ||
1232 | // Try to ensure that the reading clone is indeed reading | |
1233 | for _ in 0..50 { | |
1234 | thread::yield_now(); | |
1235 | } | |
1236 | ||
1237 | // clone the handle again while it's reading, then let it finish the | |
1238 | // read. | |
1239 | let _ = t!(tcp.try_clone()); | |
1240 | tx.send(()).unwrap(); | |
1241 | rxdone.recv().unwrap(); | |
1242 | rxdone.recv().unwrap(); | |
1243 | }) | |
1244 | } | |
1245 | ||
1246 | #[test] | |
1247 | fn clone_accept_smoke() { | |
1248 | each_ip(&mut |addr| { | |
1249 | let a = t!(TcpListener::bind(&addr)); | |
1250 | let a2 = t!(a.try_clone()); | |
1251 | ||
1252 | let _t = thread::spawn(move|| { | |
1253 | let _ = TcpStream::connect(&addr); | |
1254 | }); | |
1255 | let _t = thread::spawn(move|| { | |
1256 | let _ = TcpStream::connect(&addr); | |
1257 | }); | |
1258 | ||
1259 | t!(a.accept()); | |
1260 | t!(a2.accept()); | |
1261 | }) | |
1262 | } | |
1263 | ||
1264 | #[test] | |
1265 | fn clone_accept_concurrent() { | |
1266 | each_ip(&mut |addr| { | |
1267 | let a = t!(TcpListener::bind(&addr)); | |
1268 | let a2 = t!(a.try_clone()); | |
1269 | ||
1270 | let (tx, rx) = channel(); | |
1271 | let tx2 = tx.clone(); | |
1272 | ||
1273 | let _t = thread::spawn(move|| { | |
1274 | tx.send(t!(a.accept())).unwrap(); | |
1275 | }); | |
1276 | let _t = thread::spawn(move|| { | |
1277 | tx2.send(t!(a2.accept())).unwrap(); | |
1278 | }); | |
1279 | ||
1280 | let _t = thread::spawn(move|| { | |
1281 | let _ = TcpStream::connect(&addr); | |
1282 | }); | |
1283 | let _t = thread::spawn(move|| { | |
1284 | let _ = TcpStream::connect(&addr); | |
1285 | }); | |
1286 | ||
1287 | rx.recv().unwrap(); | |
1288 | rx.recv().unwrap(); | |
1289 | }) | |
1290 | } | |
1291 | ||
1292 | #[test] | |
1293 | fn debug() { | |
1294 | let name = if cfg!(windows) {"socket"} else {"fd"}; | |
1295 | let socket_addr = next_test_ip4(); | |
1296 | ||
1297 | let listener = t!(TcpListener::bind(&socket_addr)); | |
1298 | let listener_inner = listener.0.socket().as_inner(); | |
1299 | let compare = format!("TcpListener {{ addr: {:?}, {}: {:?} }}", | |
1300 | socket_addr, name, listener_inner); | |
1301 | assert_eq!(format!("{:?}", listener), compare); | |
1302 | ||
1303 | let stream = t!(TcpStream::connect(&("localhost", | |
1304 | socket_addr.port()))); | |
1305 | let stream_inner = stream.0.socket().as_inner(); | |
1306 | let compare = format!("TcpStream {{ addr: {:?}, \ | |
1307 | peer: {:?}, {}: {:?} }}", | |
1308 | stream.local_addr().unwrap(), | |
1309 | stream.peer_addr().unwrap(), | |
1310 | name, | |
1311 | stream_inner); | |
1312 | assert_eq!(format!("{:?}", stream), compare); | |
1313 | } | |
1314 | ||
1315 | // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code | |
1316 | // no longer has rounding errors. | |
1317 | #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)] | |
1318 | #[test] | |
1319 | fn timeouts() { | |
1320 | let addr = next_test_ip4(); | |
1321 | let listener = t!(TcpListener::bind(&addr)); | |
1322 | ||
1323 | let stream = t!(TcpStream::connect(&("localhost", addr.port()))); | |
1324 | let dur = Duration::new(15410, 0); | |
1325 | ||
1326 | assert_eq!(None, t!(stream.read_timeout())); | |
1327 | ||
1328 | t!(stream.set_read_timeout(Some(dur))); | |
1329 | assert_eq!(Some(dur), t!(stream.read_timeout())); | |
1330 | ||
1331 | assert_eq!(None, t!(stream.write_timeout())); | |
1332 | ||
1333 | t!(stream.set_write_timeout(Some(dur))); | |
1334 | assert_eq!(Some(dur), t!(stream.write_timeout())); | |
1335 | ||
1336 | t!(stream.set_read_timeout(None)); | |
1337 | assert_eq!(None, t!(stream.read_timeout())); | |
1338 | ||
1339 | t!(stream.set_write_timeout(None)); | |
1340 | assert_eq!(None, t!(stream.write_timeout())); | |
1341 | drop(listener); | |
1342 | } | |
1343 | ||
1344 | #[test] | |
1345 | fn test_read_timeout() { | |
1346 | let addr = next_test_ip4(); | |
1347 | let listener = t!(TcpListener::bind(&addr)); | |
1348 | ||
1349 | let mut stream = t!(TcpStream::connect(&("localhost", addr.port()))); | |
1350 | t!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); | |
1351 | ||
1352 | let mut buf = [0; 10]; | |
1353 | let start = Instant::now(); | |
1354 | let kind = stream.read(&mut buf).err().expect("expected error").kind(); | |
1355 | assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); | |
1356 | assert!(start.elapsed() > Duration::from_millis(400)); | |
1357 | drop(listener); | |
1358 | } | |
1359 | ||
1360 | #[test] | |
1361 | fn test_read_with_timeout() { | |
1362 | let addr = next_test_ip4(); | |
1363 | let listener = t!(TcpListener::bind(&addr)); | |
1364 | ||
1365 | let mut stream = t!(TcpStream::connect(&("localhost", addr.port()))); | |
1366 | t!(stream.set_read_timeout(Some(Duration::from_millis(1000)))); | |
1367 | ||
1368 | let mut other_end = t!(listener.accept()).0; | |
1369 | t!(other_end.write_all(b"hello world")); | |
1370 | ||
1371 | let mut buf = [0; 11]; | |
1372 | t!(stream.read(&mut buf)); | |
1373 | assert_eq!(b"hello world", &buf[..]); | |
1374 | ||
1375 | let start = Instant::now(); | |
1376 | let kind = stream.read(&mut buf).err().expect("expected error").kind(); | |
1377 | assert!(kind == ErrorKind::WouldBlock || kind == ErrorKind::TimedOut); | |
1378 | assert!(start.elapsed() > Duration::from_millis(400)); | |
1379 | drop(listener); | |
1380 | } | |
1381 | ||
1382 | #[test] | |
1383 | fn nodelay() { | |
1384 | let addr = next_test_ip4(); | |
1385 | let _listener = t!(TcpListener::bind(&addr)); | |
1386 | ||
1387 | let stream = t!(TcpStream::connect(&("localhost", addr.port()))); | |
1388 | ||
1389 | assert_eq!(false, t!(stream.nodelay())); | |
1390 | t!(stream.set_nodelay(true)); | |
1391 | assert_eq!(true, t!(stream.nodelay())); | |
1392 | t!(stream.set_nodelay(false)); | |
1393 | assert_eq!(false, t!(stream.nodelay())); | |
1394 | } | |
1395 | ||
1396 | #[test] | |
1397 | fn ttl() { | |
1398 | let ttl = 100; | |
1399 | ||
1400 | let addr = next_test_ip4(); | |
1401 | let listener = t!(TcpListener::bind(&addr)); | |
1402 | ||
1403 | t!(listener.set_ttl(ttl)); | |
1404 | assert_eq!(ttl, t!(listener.ttl())); | |
1405 | ||
1406 | let stream = t!(TcpStream::connect(&("localhost", addr.port()))); | |
1407 | ||
1408 | t!(stream.set_ttl(ttl)); | |
1409 | assert_eq!(ttl, t!(stream.ttl())); | |
1410 | } | |
1411 | ||
1412 | #[test] | |
1413 | fn set_nonblocking() { | |
1414 | let addr = next_test_ip4(); | |
1415 | let listener = t!(TcpListener::bind(&addr)); | |
1416 | ||
1417 | t!(listener.set_nonblocking(true)); | |
1418 | t!(listener.set_nonblocking(false)); | |
1419 | ||
1420 | let mut stream = t!(TcpStream::connect(&("localhost", addr.port()))); | |
1421 | ||
1422 | t!(stream.set_nonblocking(false)); | |
1423 | t!(stream.set_nonblocking(true)); | |
1424 | ||
1425 | let mut buf = [0]; | |
1426 | match stream.read(&mut buf) { | |
1427 | Ok(_) => panic!("expected error"), | |
1428 | Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} | |
1429 | Err(e) => panic!("unexpected error {}", e), | |
1430 | } | |
1431 | } | |
1432 | ||
1433 | #[test] | |
1434 | fn peek() { | |
1435 | each_ip(&mut |addr| { | |
1436 | let (txdone, rxdone) = channel(); | |
1437 | ||
1438 | let srv = t!(TcpListener::bind(&addr)); | |
1439 | let _t = thread::spawn(move|| { | |
1440 | let mut cl = t!(srv.accept()).0; | |
1441 | cl.write(&[1,3,3,7]).unwrap(); | |
1442 | t!(rxdone.recv()); | |
1443 | }); | |
1444 | ||
1445 | let mut c = t!(TcpStream::connect(&addr)); | |
1446 | let mut b = [0; 10]; | |
1447 | for _ in 1..3 { | |
1448 | let len = c.peek(&mut b).unwrap(); | |
1449 | assert_eq!(len, 4); | |
1450 | } | |
1451 | let len = c.read(&mut b).unwrap(); | |
1452 | assert_eq!(len, 4); | |
1453 | ||
1454 | t!(c.set_nonblocking(true)); | |
1455 | match c.peek(&mut b) { | |
1456 | Ok(_) => panic!("expected error"), | |
1457 | Err(ref e) if e.kind() == ErrorKind::WouldBlock => {} | |
1458 | Err(e) => panic!("unexpected error {}", e), | |
1459 | } | |
1460 | t!(txdone.send(())); | |
1461 | }) | |
1462 | } | |
1463 | } |