mio_st/net/
tcp.rs

1use std::io::{self, Read, Write};
2use std::net::{Shutdown, SocketAddr};
3#[cfg(unix)]
4use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
5
6use crate::sys;
7use crate::event::{Evented, EventedId};
8use crate::poll::{Interests, PollOption, Poller};
9
10/// A non-blocking TCP stream between a local socket and a remote socket.
11///
12/// This works much like the `TcpStream` in the standard library, but the
13/// [`Read`] and [`Write`] implementation don't block and instead return a
14/// [`WouldBlock`] error.
15///
16/// [`Read`]: #impl-Read
17/// [`Write`]: #impl-Write
18/// [`WouldBlock`]: https://doc.rust-lang.org/nightly/std/io/enum.ErrorKind.html#variant.WouldBlock
19///
20/// # Deregistering
21///
22/// `TcpStream` will deregister itself when dropped.
23///
24/// # Examples
25///
26/// ```
27/// # fn main() -> Result<(), Box<std::error::Error>> {
28/// use mio_st::event::{Events, EventedId};
29/// use mio_st::net::TcpStream;
30/// use mio_st::poll::{Poller, PollOption};
31///
32/// let address = "127.0.0.1:8000".parse()?;
33/// let mut stream = TcpStream::connect(address)?;
34///
35/// let mut poller = Poller::new()?;
36/// let mut events = Events::new();
37///
38/// // Register the socket with `Poller`.
39/// poller.register(&mut stream, EventedId(0), TcpStream::INTERESTS, PollOption::Edge)?;
40///
41/// poller.poll(&mut events, None)?;
42///
43/// // The socket might be ready at this point.
44/// #     Ok(())
45/// # }
46/// ```
47#[derive(Debug)]
48pub struct TcpStream {
49    inner: sys::TcpStream,
50}
51
52impl TcpStream {
53    /// The interests to use when registering to receive both readable and
54    /// writable events.
55    pub const INTERESTS: Interests = Interests::BOTH;
56
57    /// Create a new TCP stream and issue a non-blocking connect to the
58    /// specified address.
59    pub fn connect(address: SocketAddr) -> io::Result<TcpStream> {
60        sys::TcpStream::connect(address).map(|inner| TcpStream { inner })
61    }
62
63    /// Returns the socket address of the remote peer of this TCP connection.
64    pub fn peer_addr(&mut self) -> io::Result<SocketAddr> {
65        self.inner.peer_addr()
66    }
67
68    /// Returns the socket address of the local half of this TCP connection.
69    pub fn local_addr(&mut self) -> io::Result<SocketAddr> {
70        self.inner.local_addr()
71    }
72
73    /// Sets the value for the `IP_TTL` option on this socket.
74    pub fn set_ttl(&mut self, ttl: u32) -> io::Result<()> {
75        self.inner.set_ttl(ttl)
76    }
77
78    /// Gets the value of the `IP_TTL` option for this socket.
79    pub fn ttl(&mut self) -> io::Result<u32> {
80        self.inner.ttl()
81    }
82
83    /// Sets the value of the `TCP_NODELAY` option on this socket.
84    pub fn set_nodelay(&mut self, nodelay: bool) -> io::Result<()> {
85        self.inner.set_nodelay(nodelay)
86    }
87
88    /// Gets the value of the `TCP_NODELAY` option on this socket.
89    pub fn nodelay(&mut self) -> io::Result<bool> {
90        self.inner.nodelay()
91    }
92
93    /// Receives data on the socket from the remote address to which it is
94    /// connected, without removing that data from the queue. On success,
95    /// returns the number of bytes peeked.
96    ///
97    /// Successive calls return the same data. This is accomplished by passing
98    /// `MSG_PEEK` as a flag to the underlying recv system call.
99    pub fn peek(&mut self, buf: &mut [u8]) -> io::Result<usize> {
100        self.inner.peek(buf)
101    }
102
103    /// Shuts down the read, write, or both halves of this connection.
104    ///
105    /// This function will cause all pending and future I/O on the specified
106    /// portions to return immediately with an appropriate value (see the
107    /// documentation of [`Shutdown`]).
108    ///
109    /// [`Shutdown`]: https://doc.rust-lang.org/nightly/std/net/enum.Shutdown.html
110    pub fn shutdown(&mut self, how: Shutdown) -> io::Result<()> {
111        self.inner.shutdown(how)
112    }
113
114    /// Get the value of the `SO_ERROR` option on this socket.
115    ///
116    /// This will retrieve the stored error in the underlying socket, clearing
117    /// the field in the process. This can be useful for checking errors between
118    /// calls.
119    pub fn take_error(&mut self) -> io::Result<Option<io::Error>> {
120        self.inner.take_error()
121    }
122}
123
124impl Read for TcpStream {
125    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
126        self.inner.read(buf)
127    }
128}
129
130impl Write for TcpStream {
131    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
132        self.inner.write(buf)
133    }
134
135    fn flush(&mut self) -> io::Result<()> {
136        self.inner.flush()
137    }
138}
139
140impl Evented for TcpStream {
141    fn register(&mut self, poller: &mut Poller, id: EventedId, interests: Interests, opt: PollOption) -> io::Result<()> {
142        self.inner.register(poller, id, interests, opt)
143    }
144
145    fn reregister(&mut self, poller: &mut Poller, id: EventedId, interests: Interests, opt: PollOption) -> io::Result<()> {
146        self.inner.reregister(poller, id, interests, opt)
147    }
148
149    fn deregister(&mut self, poller: &mut Poller) -> io::Result<()> {
150        self.inner.deregister(poller)
151    }
152}
153
154#[cfg(unix)]
155impl FromRawFd for TcpStream {
156    /// The caller must ensure that the stream is in non-blocking mode when
157    /// using this function.
158    unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
159        TcpStream {
160            inner: FromRawFd::from_raw_fd(fd),
161        }
162    }
163}
164
165#[cfg(unix)]
166impl IntoRawFd for TcpStream {
167    fn into_raw_fd(self) -> RawFd {
168        self.inner.into_raw_fd()
169    }
170}
171
172#[cfg(unix)]
173impl AsRawFd for TcpStream {
174    fn as_raw_fd(&self) -> RawFd {
175        self.inner.as_raw_fd()
176    }
177}
178
179/// A TCP socket listener.
180///
181/// This works much like the `TcpListener` in the standard library, but this
182/// doesn't block when calling [`accept`] and instead returns a [`WouldBlock`]
183/// error.
184///
185/// [`accept`]: #method.accept
186/// [`WouldBlock`]: https://doc.rust-lang.org/nightly/std/io/enum.ErrorKind.html#variant.WouldBlock
187///
188/// # Deregistering
189///
190/// `TcpListener` will deregister itself when dropped, **iff** it is not cloned
191/// (via [`try_clone`]).
192///
193/// [`try_clone`]: #method.try_clone
194///
195/// # Examples
196///
197/// ```
198/// # fn main() -> Result<(), Box<std::error::Error>> {
199/// use std::time::Duration;
200///
201/// use mio_st::event::{Events, EventedId};
202/// use mio_st::net::TcpListener;
203/// use mio_st::poll::{Poller, PollOption};
204///
205/// let address = "127.0.0.1:8001".parse()?;
206/// let mut listener = TcpListener::bind(address)?;
207///
208/// let mut poller = Poller::new()?;
209/// let mut events = Events::new();
210///
211/// // Register the socket with `Poller`
212/// poller.register(&mut listener, EventedId(0), TcpListener::INTERESTS, PollOption::Edge)?;
213///
214/// poller.poll(&mut events, Some(Duration::from_millis(100)))?;
215///
216/// // There may be a socket ready to be accepted.
217/// #     Ok(())
218/// # }
219/// ```
220#[derive(Debug)]
221pub struct TcpListener {
222    inner: sys::TcpListener,
223}
224
225impl TcpListener {
226    /// The interests to use when registering to receive acceptable connections
227    /// events.
228    pub const INTERESTS: Interests = Interests::READABLE;
229
230    /// Convenience method to bind a new TCP listener to the specified address
231    /// to receive new connections.
232    ///
233    /// This also sets the `SO_REUSEPORT` and `SO_REUSEADDR` options on the
234    /// socket.
235    pub fn bind(address: SocketAddr) -> io::Result<TcpListener> {
236        sys::TcpListener::bind(address).map(|inner| TcpListener { inner })
237    }
238
239    /// Create a independently owned handle to the underlying socket.
240    ///
241    /// The returned `TcpListener` is a reference to the same socket as `self`.
242    /// Both handles can be used to accept incoming connections and options set
243    /// on one listener will affect the other.
244    ///
245    /// # Notes
246    ///
247    /// On Linux when a `TcpListener` is cloned it must deregistered. If its not
248    /// deregistered explicitly and one listener is closed (dropped) and onother
249    /// is still open the poller will still receive events.
250    pub fn try_clone(&self) -> io::Result<TcpListener> {
251        self.inner.try_clone().map(|inner| TcpListener { inner })
252    }
253
254    /// Accepts a new `TcpStream`.
255    ///
256    /// This may return an [`WouldBlock`] error, this means a stream may be
257    /// ready at a later point and one should wait for a notification before
258    /// calling `accept` again.
259    ///
260    /// If an accepted stream is returned, the remote address of the peer is
261    /// returned along with it.
262    ///
263    /// [`WouldBlock`]: https://doc.rust-lang.org/nightly/std/io/enum.ErrorKind.html#variant.WouldBlock
264    pub fn accept(&mut self) -> io::Result<(TcpStream, SocketAddr)> {
265        self.inner.accept().map(|(inner, address)| (TcpStream{ inner }, address))
266    }
267
268    /// Returns the local socket address of this listener.
269    pub fn local_addr(&mut self) -> io::Result<SocketAddr> {
270        self.inner.local_addr()
271    }
272
273    /// Sets the value for the `IP_TTL` option on this socket.
274    pub fn set_ttl(&mut self, ttl: u32) -> io::Result<()> {
275        self.inner.set_ttl(ttl)
276    }
277
278    /// Gets the value of the `IP_TTL` option for this socket.
279    pub fn ttl(&mut self) -> io::Result<u32> {
280        self.inner.ttl()
281    }
282
283    /// Get the value of the `SO_ERROR` option on this socket.
284    ///
285    /// This will retrieve the stored error in the underlying socket, clearing
286    /// the field in the process. This can be useful for checking errors between
287    /// calls.
288    pub fn take_error(&mut self) -> io::Result<Option<io::Error>> {
289        self.inner.take_error()
290    }
291}
292
293impl Evented for TcpListener {
294    fn register(&mut self, poller: &mut Poller, id: EventedId, interests: Interests, opt: PollOption) -> io::Result<()> {
295        debug_assert!(!interests.is_writable(), "TcpListener only needs readable interests");
296        self.inner.register(poller, id, interests, opt)
297    }
298
299    fn reregister(&mut self, poller: &mut Poller, id: EventedId, interests: Interests, opt: PollOption) -> io::Result<()> {
300        debug_assert!(!interests.is_writable(), "TcpListener only needs readable interests");
301        self.inner.reregister(poller, id, interests, opt)
302    }
303
304    fn deregister(&mut self, poller: &mut Poller) -> io::Result<()> {
305        self.inner.deregister(poller)
306    }
307}
308
309#[cfg(unix)]
310impl FromRawFd for TcpListener {
311    /// The caller must ensure that the listener is in non-blocking mode when
312    /// using this function.
313    unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
314        TcpListener {
315            inner: sys::TcpListener::from_raw_fd(fd),
316        }
317    }
318}
319
320#[cfg(unix)]
321impl IntoRawFd for TcpListener {
322    fn into_raw_fd(self) -> RawFd {
323        self.inner.into_raw_fd()
324    }
325}
326
327#[cfg(unix)]
328impl AsRawFd for TcpListener {
329    fn as_raw_fd(&self) -> RawFd {
330        self.inner.as_raw_fd()
331    }
332}