tokio_tcp/listener.rs
1use super::Incoming;
2use super::TcpStream;
3
4use std::fmt;
5use std::io;
6use std::net::{self, SocketAddr};
7
8use futures::{Async, Poll};
9use mio;
10use tokio_reactor::{Handle, PollEvented};
11
12/// An I/O object representing a TCP socket listening for incoming connections.
13///
14/// This object can be converted into a stream of incoming connections for
15/// various forms of processing.
16///
17/// # Examples
18///
19/// ```no_run
20/// extern crate tokio;
21/// extern crate futures;
22///
23/// use futures::stream::Stream;
24/// use std::net::SocketAddr;
25/// use tokio::net::{TcpListener, TcpStream};
26///
27/// fn process_socket(socket: TcpStream) {
28/// // ...
29/// }
30///
31/// fn main() -> Result<(), Box<std::error::Error>> {
32/// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
33/// let listener = TcpListener::bind(&addr)?;
34///
35/// // accept connections and process them
36/// tokio::run(listener.incoming()
37/// .map_err(|e| eprintln!("failed to accept socket; error = {:?}", e))
38/// .for_each(|socket| {
39/// process_socket(socket);
40/// Ok(())
41/// })
42/// );
43/// Ok(())
44/// }
45/// ```
46pub struct TcpListener {
47 io: PollEvented<mio::net::TcpListener>,
48}
49
50impl TcpListener {
51 /// Create a new TCP listener associated with this event loop.
52 ///
53 /// The TCP listener will bind to the provided `addr` address, if available.
54 /// If the result is `Ok`, the socket has successfully bound.
55 ///
56 /// # Examples
57 ///
58 /// ```
59 /// # extern crate tokio;
60 /// use std::net::SocketAddr;
61 /// use tokio::net::TcpListener;
62 ///
63 /// # fn main() -> Result<(), Box<std::error::Error>> {
64 /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
65 /// let listener = TcpListener::bind(&addr)?;
66 /// # Ok(())
67 /// # }
68 /// ```
69 pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
70 let l = mio::net::TcpListener::bind(addr)?;
71 Ok(TcpListener::new(l))
72 }
73
74 #[deprecated(since = "0.1.2", note = "use poll_accept instead")]
75 #[doc(hidden)]
76 pub fn accept(&mut self) -> io::Result<(TcpStream, SocketAddr)> {
77 match self.poll_accept()? {
78 Async::Ready(ret) => Ok(ret),
79 Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
80 }
81 }
82
83 /// Attempt to accept a connection and create a new connected `TcpStream` if
84 /// successful.
85 ///
86 /// Note that typically for simple usage it's easier to treat incoming
87 /// connections as a `Stream` of `TcpStream`s with the `incoming` method
88 /// below.
89 ///
90 /// # Return
91 ///
92 /// On success, returns `Ok(Async::Ready((socket, addr)))`.
93 ///
94 /// If the listener is not ready to accept, the method returns
95 /// `Ok(Async::NotReady)` and arranges for the current task to receive a
96 /// notification when the listener becomes ready to accept.
97 ///
98 /// # Panics
99 ///
100 /// This function will panic if called from outside of a task context.
101 ///
102 /// # Examples
103 ///
104 /// ```no_run
105 /// # extern crate tokio;
106 /// # extern crate futures;
107 /// use std::net::SocketAddr;
108 /// use tokio::net::TcpListener;
109 /// use futures::Async;
110 ///
111 /// # fn main() -> Result<(), Box<std::error::Error>> {
112 /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
113 /// let mut listener = TcpListener::bind(&addr)?;
114 /// match listener.poll_accept() {
115 /// Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
116 /// Ok(Async::NotReady) => println!("listener not ready to accept!"),
117 /// Err(e) => eprintln!("got an error: {}", e),
118 /// }
119 /// # Ok(())
120 /// # }
121 /// ```
122 pub fn poll_accept(&mut self) -> Poll<(TcpStream, SocketAddr), io::Error> {
123 let (io, addr) = try_ready!(self.poll_accept_std());
124
125 let io = mio::net::TcpStream::from_stream(io)?;
126 let io = TcpStream::new(io);
127
128 Ok((io, addr).into())
129 }
130
131 #[deprecated(since = "0.1.2", note = "use poll_accept_std instead")]
132 #[doc(hidden)]
133 pub fn accept_std(&mut self) -> io::Result<(net::TcpStream, SocketAddr)> {
134 match self.poll_accept_std()? {
135 Async::Ready(ret) => Ok(ret),
136 Async::NotReady => Err(io::ErrorKind::WouldBlock.into()),
137 }
138 }
139
140 /// Attempt to accept a connection and create a new connected `TcpStream` if
141 /// successful.
142 ///
143 /// This function is the same as `accept` above except that it returns a
144 /// `std::net::TcpStream` instead of a `tokio::net::TcpStream`. This in turn
145 /// can then allow for the TCP stream to be associated with a different
146 /// reactor than the one this `TcpListener` is associated with.
147 ///
148 /// # Return
149 ///
150 /// On success, returns `Ok(Async::Ready((socket, addr)))`.
151 ///
152 /// If the listener is not ready to accept, the method returns
153 /// `Ok(Async::NotReady)` and arranges for the current task to receive a
154 /// notification when the listener becomes ready to accept.
155 ///
156 /// # Panics
157 ///
158 /// This function will panic if called from outside of a task context.
159 ///
160 /// # Examples
161 ///
162 /// ```no_run
163 /// # extern crate tokio;
164 /// # extern crate futures;
165 /// use std::net::SocketAddr;
166 /// use tokio::net::TcpListener;
167 /// use futures::Async;
168 ///
169 /// # fn main() -> Result<(), Box<std::error::Error>> {
170 /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
171 /// let mut listener = TcpListener::bind(&addr)?;
172 /// match listener.poll_accept_std() {
173 /// Ok(Async::Ready((_socket, addr))) => println!("listener ready to accept: {:?}", addr),
174 /// Ok(Async::NotReady) => println!("listener not ready to accept!"),
175 /// Err(e) => eprintln!("got an error: {}", e),
176 /// }
177 /// # Ok(())
178 /// # }
179 /// ```
180 pub fn poll_accept_std(&mut self) -> Poll<(net::TcpStream, SocketAddr), io::Error> {
181 try_ready!(self.io.poll_read_ready(mio::Ready::readable()));
182
183 match self.io.get_ref().accept_std() {
184 Ok(pair) => Ok(pair.into()),
185 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
186 self.io.clear_read_ready(mio::Ready::readable())?;
187 Ok(Async::NotReady)
188 }
189 Err(e) => Err(e),
190 }
191 }
192
193 /// Create a new TCP listener from the standard library's TCP listener.
194 ///
195 /// This method can be used when the `Handle::tcp_listen` method isn't
196 /// sufficient because perhaps some more configuration is needed in terms of
197 /// before the calls to `bind` and `listen`.
198 ///
199 /// This API is typically paired with the `net2` crate and the `TcpBuilder`
200 /// type to build up and customize a listener before it's shipped off to the
201 /// backing event loop. This allows configuration of options like
202 /// `SO_REUSEPORT`, binding to multiple addresses, etc.
203 ///
204 /// The `addr` argument here is one of the addresses that `listener` is
205 /// bound to and the listener will only be guaranteed to accept connections
206 /// of the same address type currently.
207 ///
208 /// Finally, the `handle` argument is the event loop that this listener will
209 /// be bound to.
210 /// Use [`Handle::default()`] to lazily bind to an event loop, just like `bind` does.
211 ///
212 /// The platform specific behavior of this function looks like:
213 ///
214 /// * On Unix, the socket is placed into nonblocking mode and connections
215 /// can be accepted as normal
216 ///
217 /// * On Windows, the address is stored internally and all future accepts
218 /// will only be for the same IP version as `addr` specified. That is, if
219 /// `addr` is an IPv4 address then all sockets accepted will be IPv4 as
220 /// well (same for IPv6).
221 ///
222 /// [`Handle::default()`]: ../reactor/struct.Handle.html
223 /// # Examples
224 ///
225 /// ```no_run
226 /// # extern crate tokio;
227 /// # extern crate tokio_reactor;
228 /// use tokio::net::TcpListener;
229 /// use std::net::TcpListener as StdTcpListener;
230 /// use tokio::reactor::Handle;
231 ///
232 /// # fn main() -> Result<(), Box<std::error::Error>> {
233 /// let std_listener = StdTcpListener::bind("127.0.0.1:0")?;
234 /// let listener = TcpListener::from_std(std_listener, &Handle::default())?;
235 /// # Ok(())
236 /// # }
237 /// ```
238 pub fn from_std(listener: net::TcpListener, handle: &Handle) -> io::Result<TcpListener> {
239 let io = mio::net::TcpListener::from_std(listener)?;
240 let io = PollEvented::new_with_handle(io, handle)?;
241 Ok(TcpListener { io })
242 }
243
244 fn new(listener: mio::net::TcpListener) -> TcpListener {
245 let io = PollEvented::new(listener);
246 TcpListener { io }
247 }
248
249 /// Returns the local address that this listener is bound to.
250 ///
251 /// This can be useful, for example, when binding to port 0 to figure out
252 /// which port was actually bound.
253 ///
254 /// # Examples
255 ///
256 /// ```
257 /// # extern crate tokio;
258 /// use tokio::net::TcpListener;
259 /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
260 ///
261 /// # fn main() -> Result<(), Box<std::error::Error>> {
262 /// let addr = "127.0.0.1:8080".parse::<SocketAddr>()?;
263 /// let listener = TcpListener::bind(&addr)?;
264 /// assert_eq!(listener.local_addr()?,
265 /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
266 /// # Ok(())
267 /// # }
268 /// ```
269 pub fn local_addr(&self) -> io::Result<SocketAddr> {
270 self.io.get_ref().local_addr()
271 }
272
273 /// Consumes this listener, returning a stream of the sockets this listener
274 /// accepts.
275 ///
276 /// This method returns an implementation of the `Stream` trait which
277 /// resolves to the sockets the are accepted on this listener.
278 ///
279 /// # Errors
280 ///
281 /// Note that accepting a connection can lead to various errors and not all of them are
282 /// necessarily fatal ‒ for example having too many open file descriptors or the other side
283 /// closing the connection while it waits in an accept queue. These would terminate the stream
284 /// if not handled in any way.
285 ///
286 /// If aiming for production, decision what to do about them must be made. The
287 /// [`tk-listen`](https://crates.io/crates/tk-listen) crate might be of some help.
288 ///
289 /// # Examples
290 ///
291 /// ```
292 /// # extern crate tokio;
293 /// # extern crate futures;
294 /// use tokio::net::TcpListener;
295 /// use futures::stream::Stream;
296 /// use std::net::SocketAddr;
297 ///
298 /// # fn main() -> Result<(), Box<std::error::Error>> {
299 /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
300 /// let listener = TcpListener::bind(&addr)?;
301 ///
302 /// listener.incoming()
303 /// .map_err(|e| eprintln!("failed to accept stream; error = {:?}", e))
304 /// .for_each(|_socket| {
305 /// println!("new socket!");
306 /// Ok(())
307 /// });
308 /// # Ok(())
309 /// # }
310 /// ```
311 pub fn incoming(self) -> Incoming {
312 Incoming::new(self)
313 }
314
315 /// Gets the value of the `IP_TTL` option for this socket.
316 ///
317 /// For more information about this option, see [`set_ttl`].
318 ///
319 /// [`set_ttl`]: #method.set_ttl
320 ///
321 /// # Examples
322 ///
323 /// ```
324 /// # extern crate tokio;
325 /// use tokio::net::TcpListener;
326 /// use std::net::SocketAddr;
327 ///
328 /// # fn main() -> Result<(), Box<std::error::Error>> {
329 /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
330 /// let listener = TcpListener::bind(&addr)?;
331 /// listener.set_ttl(100).expect("could not set TTL");
332 /// assert_eq!(listener.ttl()?, 100);
333 /// # Ok(())
334 /// # }
335 /// ```
336 pub fn ttl(&self) -> io::Result<u32> {
337 self.io.get_ref().ttl()
338 }
339
340 /// Sets the value for the `IP_TTL` option on this socket.
341 ///
342 /// This value sets the time-to-live field that is used in every packet sent
343 /// from this socket.
344 ///
345 /// # Examples
346 ///
347 /// ```
348 /// # extern crate tokio;
349 /// use tokio::net::TcpListener;
350 /// use std::net::SocketAddr;
351 ///
352 /// # fn main() -> Result<(), Box<std::error::Error>> {
353 /// let addr = "127.0.0.1:0".parse::<SocketAddr>()?;
354 /// let listener = TcpListener::bind(&addr)?;
355 /// listener.set_ttl(100).expect("could not set TTL");
356 /// # Ok(())
357 /// # }
358 /// ```
359 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
360 self.io.get_ref().set_ttl(ttl)
361 }
362}
363
364impl fmt::Debug for TcpListener {
365 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366 self.io.get_ref().fmt(f)
367 }
368}
369
370#[cfg(unix)]
371mod sys {
372 use super::TcpListener;
373 use std::os::unix::prelude::*;
374
375 impl AsRawFd for TcpListener {
376 fn as_raw_fd(&self) -> RawFd {
377 self.io.get_ref().as_raw_fd()
378 }
379 }
380}
381
382#[cfg(windows)]
383mod sys {
384 // TODO: let's land these upstream with mio and then we can add them here.
385 //
386 // use std::os::windows::prelude::*;
387 // use super::{TcpListener;
388 //
389 // impl AsRawHandle for TcpListener {
390 // fn as_raw_handle(&self) -> RawHandle {
391 // self.listener.io().as_raw_handle()
392 // }
393 // }
394}