aboutsummaryrefslogtreecommitdiff
path: root/src/net/tcp
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2021-02-09 18:18:56 -0800
committerStephen Hines <srhines@google.com>2021-03-03 21:34:52 +0000
commite3d8d80d2d8744ccdcd175323e0864c8f30fcedc (patch)
tree16d053e70d21e456d52f4a7762ee41441342b7a2 /src/net/tcp
parent925d648e545e70d6a4faae3d7efe5e0de885f922 (diff)
downloadtokio-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.rs11
-rw-r--r--src/net/tcp/stream.rs102
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