diff options
author | Haibo Huang <hhb@google.com> | 2021-02-09 18:18:56 -0800 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2021-03-03 21:34:52 +0000 |
commit | e3d8d80d2d8744ccdcd175323e0864c8f30fcedc (patch) | |
tree | 16d053e70d21e456d52f4a7762ee41441342b7a2 /src/net/tcp | |
parent | 925d648e545e70d6a4faae3d7efe5e0de885f922 (diff) | |
download | tokio-e3d8d80d2d8744ccdcd175323e0864c8f30fcedc.tar.gz |
Upgrade rust/crates/tokio to 1.2.0
Test: make
Change-Id: Ib0f6a5201b51e9d122b6e867388a3856e16f803a
Diffstat (limited to 'src/net/tcp')
-rw-r--r-- | src/net/tcp/listener.rs | 11 | ||||
-rw-r--r-- | src/net/tcp/stream.rs | 102 |
2 files changed, 102 insertions, 11 deletions
diff --git a/src/net/tcp/listener.rs b/src/net/tcp/listener.rs index a2a8637..1ff0949 100644 --- a/src/net/tcp/listener.rs +++ b/src/net/tcp/listener.rs @@ -14,6 +14,10 @@ cfg_net! { /// You can accept a new connection by using the [`accept`](`TcpListener::accept`) /// method. /// + /// A `TcpListener` can be turned into a `Stream` with [`TcpListenerStream`]. + /// + /// [`TcpListenerStream`]: https://docs.rs/tokio-stream/0.1/tokio_stream/wrappers/struct.TcpListenerStream.html + /// /// # Errors /// /// Note that accepting a connection can lead to various errors and not all @@ -60,9 +64,6 @@ impl TcpListener { /// method. /// /// The address type can be any implementor of the [`ToSocketAddrs`] trait. - /// Note that strings only implement this trait when the **`net`** feature - /// is enabled, as strings may contain domain names that need to be resolved. - /// /// If `addr` yields multiple addresses, bind will be attempted with each of /// the addresses until one succeeds and returns the listener. If none of /// the addresses succeed in creating a listener, the error returned from @@ -70,7 +71,11 @@ impl TcpListener { /// /// This function sets the `SO_REUSEADDR` option on the socket. /// + /// To configure the socket before binding, you can use the [`TcpSocket`] + /// type. + /// /// [`ToSocketAddrs`]: trait@crate::net::ToSocketAddrs + /// [`TcpSocket`]: struct@crate::net::TcpSocket /// /// # Examples /// diff --git a/src/net/tcp/stream.rs b/src/net/tcp/stream.rs index d4bfba4..91e357f 100644 --- a/src/net/tcp/stream.rs +++ b/src/net/tcp/stream.rs @@ -17,11 +17,16 @@ use std::pin::Pin; use std::task::{Context, Poll}; use std::time::Duration; +cfg_io_util! { + use bytes::BufMut; +} + cfg_net! { /// A TCP stream between a local and a remote socket. /// /// A TCP stream can either be created by connecting to an endpoint, via the - /// [`connect`] method, or by [accepting] a connection from a [listener]. + /// [`connect`] method, or by [accepting] a connection from a [listener]. A + /// TCP stream can also be created via the [`TcpSocket`] type. /// /// Reading and writing to a `TcpStream` is usually done using the /// convenience methods found on the [`AsyncReadExt`] and [`AsyncWriteExt`] @@ -30,6 +35,7 @@ cfg_net! { /// [`connect`]: method@TcpStream::connect /// [accepting]: method@crate::net::TcpListener::accept /// [listener]: struct@crate::net::TcpListener + /// [`TcpSocket`]: struct@crate::net::TcpSocket /// [`AsyncReadExt`]: trait@crate::io::AsyncReadExt /// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt /// @@ -72,16 +78,17 @@ impl TcpStream { /// Opens a TCP connection to a remote host. /// /// `addr` is an address of the remote host. Anything which implements the - /// [`ToSocketAddrs`] trait can be supplied as the address. Note that - /// strings only implement this trait when the **`net`** feature is enabled, - /// as strings may contain domain names that need to be resolved. + /// [`ToSocketAddrs`] trait can be supplied as the address. If `addr` + /// yields multiple addresses, connect will be attempted with each of the + /// addresses until a connection is successful. If none of the addresses + /// result in a successful connection, the error returned from the last + /// connection attempt (the last address) is returned. /// - /// If `addr` yields multiple addresses, connect will be attempted with each - /// of the addresses until a connection is successful. If none of the - /// addresses result in a successful connection, the error returned from the - /// last connection attempt (the last address) is returned. + /// To configure the socket before connecting, you can use the [`TcpSocket`] + /// type. /// /// [`ToSocketAddrs`]: trait@crate::net::ToSocketAddrs + /// [`TcpSocket`]: struct@crate::net::TcpSocket /// /// # Examples /// @@ -559,6 +566,85 @@ impl TcpStream { .try_io(Interest::READABLE, || (&*self.io).read(buf)) } + cfg_io_util! { + /// Try to read data from the stream into the provided buffer, advancing the + /// buffer's internal cursor, returning how many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_buf()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: TcpStream::readable() + /// [`ready()`]: TcpStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box<dyn Error>> { + /// // Connect to a peer + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// loop { + /// // Wait for the socket to be readable + /// stream.readable().await?; + /// + /// let mut buf = Vec::with_capacity(4096); + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match stream.try_read_buf(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_buf<B: BufMut>(&self, buf: &mut B) -> io::Result<usize> { + self.io.registration().try_io(Interest::READABLE, || { + use std::io::Read; + + let dst = buf.chunk_mut(); + let dst = + unsafe { &mut *(dst as *mut _ as *mut [std::mem::MaybeUninit<u8>] as *mut [u8]) }; + + // Safety: We trust `TcpStream::read` to have filled up `n` bytes in the + // buffer. + let n = (&*self.io).read(dst)?; + + unsafe { + buf.advance_mut(n); + } + + Ok(n) + }) + } + } + /// Wait for the socket to become writable. /// /// This function is equivalent to `ready(Interest::WRITABLE)` and is usually |