async_net/tcp.rs
1use std::fmt;
2use std::io::{self, IoSlice, Read as _, Write as _};
3use std::net::{Shutdown, SocketAddr};
4#[cfg(unix)]
5use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
6use std::panic::{RefUnwindSafe, UnwindSafe};
7use std::pin::Pin;
8use std::sync::Arc;
9use std::task::{Context, Poll};
10
11use async_io::Async;
12use futures_lite::{prelude::*, ready};
13
14use crate::addr::AsyncToSocketAddrs;
15
16/// A TCP server, listening for connections.
17///
18/// After creating a [`TcpListener`] by [`bind`][`TcpListener::bind()`]ing it to an address, it
19/// listens for incoming TCP connections. These can be accepted by calling
20/// [`accept()`][`TcpListener::accept()`] or by awaiting items from the stream of
21/// [`incoming`][`TcpListener::incoming()`] connections.
22///
23/// Cloning a [`TcpListener`] creates another handle to the same socket. The socket will be closed
24/// when all handles to it are dropped.
25///
26/// The Transmission Control Protocol is specified in [IETF RFC 793].
27///
28/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
29///
30/// # Examples
31///
32/// ```no_run
33/// use async_net::TcpListener;
34/// use futures_lite::prelude::*;
35///
36/// # futures_lite::future::block_on(async {
37/// let listener = TcpListener::bind("127.0.0.1:8080").await?;
38/// let mut incoming = listener.incoming();
39///
40/// while let Some(stream) = incoming.next().await {
41/// let mut stream = stream?;
42/// stream.write_all(b"hello").await?;
43/// }
44/// # std::io::Result::Ok(()) });
45/// ```
46#[derive(Clone, Debug)]
47pub struct TcpListener {
48 inner: Arc<Async<std::net::TcpListener>>,
49}
50
51impl TcpListener {
52 fn new(inner: Arc<Async<std::net::TcpListener>>) -> TcpListener {
53 TcpListener { inner }
54 }
55
56 /// Creates a new [`TcpListener`] bound to the given address.
57 ///
58 /// Binding with a port number of 0 will request that the operating system assigns an available
59 /// port to this listener. The assigned port can be queried via the
60 /// [`local_addr()`][`TcpListener::local_addr()`] method.
61 ///
62 /// If `addr` yields multiple addresses, binding will be attempted with each of the addresses
63 /// until one succeeds and returns the listener. If none of the addresses succeed in creating a
64 /// listener, the error from the last attempt is returned.
65 ///
66 /// # Examples
67 ///
68 /// Create a TCP listener bound to `127.0.0.1:80`:
69 ///
70 /// ```no_run
71 /// use async_net::TcpListener;
72 ///
73 /// # futures_lite::future::block_on(async {
74 /// let listener = TcpListener::bind("127.0.0.1:80").await?;
75 /// # std::io::Result::Ok(()) });
76 /// ```
77 ///
78 /// Create a TCP listener bound to `127.0.0.1:80`. If that address is unavailable, then try
79 /// binding to `127.0.0.1:443`:
80 ///
81 /// ```no_run
82 /// use async_net::{SocketAddr, TcpListener};
83 ///
84 /// # futures_lite::future::block_on(async {
85 /// let addrs = [
86 /// SocketAddr::from(([127, 0, 0, 1], 80)),
87 /// SocketAddr::from(([127, 0, 0, 1], 443)),
88 /// ];
89 /// let listener = TcpListener::bind(&addrs[..]).await.unwrap();
90 /// # std::io::Result::Ok(()) });
91 pub async fn bind<A: AsyncToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
92 let mut last_err = None;
93
94 for addr in addr.to_socket_addrs().await? {
95 match Async::<std::net::TcpListener>::bind(addr) {
96 Ok(listener) => return Ok(TcpListener::new(Arc::new(listener))),
97 Err(err) => last_err = Some(err),
98 }
99 }
100
101 Err(last_err.unwrap_or_else(|| {
102 io::Error::new(
103 io::ErrorKind::InvalidInput,
104 "could not resolve to any of the addresses",
105 )
106 }))
107 }
108
109 /// Returns the local address this listener is bound to.
110 ///
111 /// # Examples
112 ///
113 /// Bind to port 0 and then see which port was assigned by the operating system:
114 ///
115 /// ```no_run
116 /// use async_net::{SocketAddr, TcpListener};
117 ///
118 /// # futures_lite::future::block_on(async {
119 /// let listener = TcpListener::bind("127.0.0.1:0").await?;
120 /// println!("Listening on {}", listener.local_addr()?);
121 /// # std::io::Result::Ok(()) });
122 pub fn local_addr(&self) -> io::Result<SocketAddr> {
123 self.inner.get_ref().local_addr()
124 }
125
126 /// Accepts a new incoming connection.
127 ///
128 /// Returns a TCP stream and the address it is connected to.
129 ///
130 /// # Examples
131 ///
132 /// ```no_run
133 /// use async_net::TcpListener;
134 ///
135 /// # futures_lite::future::block_on(async {
136 /// let listener = TcpListener::bind("127.0.0.1:8080").await?;
137 /// let (stream, addr) = listener.accept().await?;
138 /// # std::io::Result::Ok(()) });
139 /// ```
140 pub async fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
141 let (stream, addr) = self.inner.accept().await?;
142 Ok((TcpStream::new(Arc::new(stream)), addr))
143 }
144
145 /// Returns a stream of incoming connections.
146 ///
147 /// Iterating over this stream is equivalent to calling [`accept()`][`TcpListener::accept()`]
148 /// in a loop. The stream of connections is infinite, i.e awaiting the next connection will
149 /// never result in [`None`].
150 ///
151 /// # Examples
152 ///
153 /// ```no_run
154 /// use async_net::TcpListener;
155 /// use futures_lite::prelude::*;
156 ///
157 /// # futures_lite::future::block_on(async {
158 /// let listener = TcpListener::bind("127.0.0.1:0").await?;
159 /// let mut incoming = listener.incoming();
160 ///
161 /// while let Some(stream) = incoming.next().await {
162 /// let mut stream = stream?;
163 /// stream.write_all(b"hello").await?;
164 /// }
165 /// # std::io::Result::Ok(()) });
166 /// ```
167 pub fn incoming(&self) -> Incoming<'_> {
168 Incoming {
169 incoming: Box::pin(self.inner.incoming()),
170 }
171 }
172
173 /// Gets the value of the `IP_TTL` option for this socket.
174 ///
175 /// This option configures the time-to-live field that is used in every packet sent from this
176 /// socket.
177 ///
178 /// # Examples
179 ///
180 /// ```no_run
181 /// use async_net::TcpListener;
182 ///
183 /// # futures_lite::future::block_on(async {
184 /// let listener = TcpListener::bind("127.0.0.1:80").await?;
185 /// listener.set_ttl(100)?;
186 /// assert_eq!(listener.ttl()?, 100);
187 /// # std::io::Result::Ok(()) });
188 /// ```
189 pub fn ttl(&self) -> io::Result<u32> {
190 self.inner.get_ref().ttl()
191 }
192
193 /// Sets the value of the `IP_TTL` option for this socket.
194 ///
195 /// This option configures the time-to-live field that is used in every packet sent from this
196 /// socket.
197 ///
198 /// # Examples
199 ///
200 /// ```no_run
201 /// use async_net::TcpListener;
202 ///
203 /// # futures_lite::future::block_on(async {
204 /// let listener = TcpListener::bind("127.0.0.1:80").await?;
205 /// listener.set_ttl(100)?;
206 /// # std::io::Result::Ok(()) });
207 /// ```
208 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
209 self.inner.get_ref().set_ttl(ttl)
210 }
211}
212
213impl From<Async<std::net::TcpListener>> for TcpListener {
214 fn from(listener: Async<std::net::TcpListener>) -> TcpListener {
215 TcpListener::new(Arc::new(listener))
216 }
217}
218
219impl TryFrom<std::net::TcpListener> for TcpListener {
220 type Error = io::Error;
221
222 fn try_from(listener: std::net::TcpListener) -> io::Result<TcpListener> {
223 Ok(TcpListener::new(Arc::new(Async::new(listener)?)))
224 }
225}
226
227impl From<TcpListener> for Arc<Async<std::net::TcpListener>> {
228 fn from(val: TcpListener) -> Self {
229 val.inner
230 }
231}
232
233#[cfg(unix)]
234impl AsRawFd for TcpListener {
235 fn as_raw_fd(&self) -> RawFd {
236 self.inner.as_raw_fd()
237 }
238}
239
240#[cfg(unix)]
241impl AsFd for TcpListener {
242 fn as_fd(&self) -> BorrowedFd<'_> {
243 self.inner.get_ref().as_fd()
244 }
245}
246
247#[cfg(unix)]
248impl TryFrom<OwnedFd> for TcpListener {
249 type Error = io::Error;
250
251 fn try_from(value: OwnedFd) -> Result<Self, Self::Error> {
252 Self::try_from(std::net::TcpListener::from(value))
253 }
254}
255
256/// A stream of incoming TCP connections.
257///
258/// This stream is infinite, i.e awaiting the next connection will never result in [`None`]. It is
259/// created by the [`TcpListener::incoming()`] method.
260pub struct Incoming<'a> {
261 incoming:
262 Pin<Box<dyn Stream<Item = io::Result<Async<std::net::TcpStream>>> + Send + Sync + 'a>>,
263}
264
265impl Stream for Incoming<'_> {
266 type Item = io::Result<TcpStream>;
267
268 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
269 let res = ready!(Pin::new(&mut self.incoming).poll_next(cx));
270 Poll::Ready(res.map(|res| res.map(|stream| TcpStream::new(Arc::new(stream)))))
271 }
272}
273
274impl fmt::Debug for Incoming<'_> {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 write!(f, "Incoming {{ ... }}")
277 }
278}
279
280/// A TCP connection.
281///
282/// A [`TcpStream`] can be created by [`connect`][`TcpStream::connect()`]ing to an endpoint or by
283/// [`accept`][`TcpListener::accept()`]ing an incoming connection.
284///
285/// [`TcpStream`] is a bidirectional stream that implements traits [`AsyncRead`] and
286/// [`AsyncWrite`].
287///
288/// Cloning a [`TcpStream`] creates another handle to the same socket. The socket will be closed
289/// when all handles to it are dropped. The reading and writing portions of the connection can also
290/// be shut down individually with the [`shutdown()`][`TcpStream::shutdown()`] method.
291///
292/// The Transmission Control Protocol is specified in [IETF RFC 793].
293///
294/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
295///
296/// # Examples
297///
298/// ```no_run
299/// use async_net::TcpStream;
300/// use futures_lite::prelude::*;
301///
302/// # futures_lite::future::block_on(async {
303/// let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
304/// stream.write_all(b"hello").await?;
305///
306/// let mut buf = vec![0u8; 1024];
307/// let n = stream.read(&mut buf).await?;
308/// # std::io::Result::Ok(()) });
309/// ```
310pub struct TcpStream {
311 inner: Arc<Async<std::net::TcpStream>>,
312 readable: Option<async_io::ReadableOwned<std::net::TcpStream>>,
313 writable: Option<async_io::WritableOwned<std::net::TcpStream>>,
314}
315
316impl UnwindSafe for TcpStream {}
317impl RefUnwindSafe for TcpStream {}
318
319impl TcpStream {
320 fn new(inner: Arc<Async<std::net::TcpStream>>) -> TcpStream {
321 TcpStream {
322 inner,
323 readable: None,
324 writable: None,
325 }
326 }
327
328 /// Creates a TCP connection to the specified address.
329 ///
330 /// This method will create a new TCP socket and attempt to connect it to the provided `addr`,
331 ///
332 /// If `addr` yields multiple addresses, connecting will be attempted with each of the
333 /// addresses until connecting to one succeeds. If none of the addresses result in a successful
334 /// connection, the error from the last connect attempt is returned.
335 ///
336 /// # Examples
337 ///
338 /// Connect to `example.com:80`:
339 ///
340 /// ```
341 /// use async_net::TcpStream;
342 ///
343 /// # futures_lite::future::block_on(async {
344 /// let stream = TcpStream::connect("example.com:80").await?;
345 /// # std::io::Result::Ok(()) });
346 /// ```
347 ///
348 /// Connect to `127.0.0.1:8080`. If that fails, then try connecting to `127.0.0.1:8081`:
349 ///
350 /// ```no_run
351 /// use async_net::{SocketAddr, TcpStream};
352 ///
353 /// # futures_lite::future::block_on(async {
354 /// let addrs = [
355 /// SocketAddr::from(([127, 0, 0, 1], 8080)),
356 /// SocketAddr::from(([127, 0, 0, 1], 8081)),
357 /// ];
358 /// let stream = TcpStream::connect(&addrs[..]).await?;
359 /// # std::io::Result::Ok(()) });
360 /// ```
361 pub async fn connect<A: AsyncToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
362 let mut last_err = None;
363
364 for addr in addr.to_socket_addrs().await? {
365 match Async::<std::net::TcpStream>::connect(addr).await {
366 Ok(stream) => return Ok(TcpStream::new(Arc::new(stream))),
367 Err(e) => last_err = Some(e),
368 }
369 }
370
371 Err(last_err.unwrap_or_else(|| {
372 io::Error::new(
373 io::ErrorKind::InvalidInput,
374 "could not connect to any of the addresses",
375 )
376 }))
377 }
378
379 /// Returns the local address this stream is bound to.
380 ///
381 /// # Examples
382 ///
383 /// ```
384 /// use async_net::TcpStream;
385 ///
386 /// # futures_lite::future::block_on(async {
387 /// let stream = TcpStream::connect("example.com:80").await?;
388 /// println!("Local address is {}", stream.local_addr()?);
389 /// # std::io::Result::Ok(()) });
390 /// ```
391 pub fn local_addr(&self) -> io::Result<SocketAddr> {
392 self.inner.get_ref().local_addr()
393 }
394
395 /// Returns the remote address this stream is connected to.
396 ///
397 /// # Examples
398 ///
399 /// ```
400 /// use async_net::TcpStream;
401 ///
402 /// # futures_lite::future::block_on(async {
403 /// let stream = TcpStream::connect("example.com:80").await?;
404 /// println!("Connected to {}", stream.peer_addr()?);
405 /// # std::io::Result::Ok(()) });
406 /// ```
407 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
408 self.inner.get_ref().peer_addr()
409 }
410
411 /// Shuts down the read half, write half, or both halves of this connection.
412 ///
413 /// This method will cause all pending and future I/O in the given directions to return
414 /// immediately with an appropriate value (see the documentation of [`Shutdown`]).
415 ///
416 /// [`Shutdown`]: https://doc.rust-lang.org/std/net/enum.Shutdown.html
417 ///
418 /// # Examples
419 ///
420 /// ```no_run
421 /// use async_net::{Shutdown, TcpStream};
422 ///
423 /// # futures_lite::future::block_on(async {
424 /// let stream = TcpStream::connect("127.0.0.1:8080").await?;
425 /// stream.shutdown(Shutdown::Both)?;
426 /// # std::io::Result::Ok(()) });
427 /// ```
428 pub fn shutdown(&self, how: std::net::Shutdown) -> std::io::Result<()> {
429 self.inner.get_ref().shutdown(how)
430 }
431
432 /// Receives data without removing it from the queue.
433 ///
434 /// On success, returns the number of bytes peeked.
435 ///
436 /// Successive calls return the same data. This is accomplished by passing `MSG_PEEK` as a flag
437 /// to the underlying `recv` system call.
438 ///
439 /// # Examples
440 ///
441 /// ```no_run
442 /// use async_net::TcpStream;
443 ///
444 /// # futures_lite::future::block_on(async {
445 /// let stream = TcpStream::connect("127.0.0.1:8080").await?;
446 ///
447 /// let mut buf = vec![0; 1024];
448 /// let n = stream.peek(&mut buf).await?;
449 /// # std::io::Result::Ok(()) });
450 /// ```
451 pub async fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
452 self.inner.peek(buf).await
453 }
454
455 /// Gets the value of the `TCP_NODELAY` option for this socket.
456 ///
457 /// If set to `true`, this option disables the [Nagle algorithm][nagle-wiki]. This means that
458 /// written data is always sent as soon as possible, even if there is only a small amount of
459 /// it.
460 ///
461 /// When set to `false`, written data is buffered until there is a certain amount to send out,
462 /// thereby avoiding the frequent sending of small packets.
463 ///
464 /// [nagle-wiki]: https://en.wikipedia.org/wiki/Nagle%27s_algorithm
465 ///
466 /// # Examples
467 ///
468 /// ```no_run
469 /// use async_net::TcpStream;
470 ///
471 /// # futures_lite::future::block_on(async {
472 /// let stream = TcpStream::connect("127.0.0.1:8080").await?;
473 /// println!("TCP_NODELAY is set to {}", stream.nodelay()?);
474 /// # std::io::Result::Ok(()) });
475 /// ```
476 pub fn nodelay(&self) -> io::Result<bool> {
477 self.inner.get_ref().nodelay()
478 }
479
480 /// Sets the value of the `TCP_NODELAY` option for this socket.
481 ///
482 /// If set to `true`, this option disables the [Nagle algorithm][nagle-wiki]. This means that
483 /// written data is always sent as soon as possible, even if there is only a small amount of
484 /// it.
485 ///
486 /// When set to `false`, written data is buffered until there is a certain amount to send out,
487 /// thereby avoiding the frequent sending of small packets.
488 ///
489 /// [nagle-wiki]: https://en.wikipedia.org/wiki/Nagle%27s_algorithm
490 ///
491 /// # Examples
492 ///
493 /// ```no_run
494 /// use async_net::TcpStream;
495 ///
496 /// # futures_lite::future::block_on(async {
497 /// let stream = TcpStream::connect("127.0.0.1:8080").await?;
498 /// stream.set_nodelay(false)?;
499 /// # std::io::Result::Ok(()) });
500 /// ```
501 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
502 self.inner.get_ref().set_nodelay(nodelay)
503 }
504
505 /// Gets the value of the `IP_TTL` option for this socket.
506 ///
507 /// This option configures the time-to-live field that is used in every packet sent from this
508 /// socket.
509 ///
510 /// # Examples
511 ///
512 /// ```no_run
513 /// use async_net::TcpStream;
514 ///
515 /// # futures_lite::future::block_on(async {
516 /// let stream = TcpStream::connect("127.0.0.1:8080").await?;
517 /// println!("IP_TTL is set to {}", stream.ttl()?);
518 /// # std::io::Result::Ok(()) });
519 /// ```
520 pub fn ttl(&self) -> io::Result<u32> {
521 self.inner.get_ref().ttl()
522 }
523
524 /// Sets the value of the `IP_TTL` option for this socket.
525 ///
526 /// This option configures the time-to-live field that is used in every packet sent from this
527 /// socket.
528 ///
529 /// # Examples
530 ///
531 /// ```no_run
532 /// use async_net::TcpStream;
533 ///
534 /// # futures_lite::future::block_on(async {
535 /// let stream = TcpStream::connect("127.0.0.1:8080").await?;
536 /// stream.set_ttl(100)?;
537 /// # std::io::Result::Ok(()) });
538 /// ```
539 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
540 self.inner.get_ref().set_ttl(ttl)
541 }
542}
543
544impl fmt::Debug for TcpStream {
545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546 self.inner.fmt(f)
547 }
548}
549
550impl Clone for TcpStream {
551 fn clone(&self) -> TcpStream {
552 TcpStream::new(self.inner.clone())
553 }
554}
555
556impl From<Async<std::net::TcpStream>> for TcpStream {
557 fn from(stream: Async<std::net::TcpStream>) -> TcpStream {
558 TcpStream::new(Arc::new(stream))
559 }
560}
561
562impl From<TcpStream> for Arc<Async<std::net::TcpStream>> {
563 fn from(val: TcpStream) -> Self {
564 val.inner
565 }
566}
567
568impl TryFrom<std::net::TcpStream> for TcpStream {
569 type Error = io::Error;
570
571 fn try_from(stream: std::net::TcpStream) -> io::Result<TcpStream> {
572 Ok(TcpStream::new(Arc::new(Async::new(stream)?)))
573 }
574}
575
576#[cfg(unix)]
577impl AsRawFd for TcpStream {
578 fn as_raw_fd(&self) -> RawFd {
579 self.inner.as_raw_fd()
580 }
581}
582
583#[cfg(unix)]
584impl AsFd for TcpStream {
585 fn as_fd(&self) -> BorrowedFd<'_> {
586 self.inner.get_ref().as_fd()
587 }
588}
589
590#[cfg(unix)]
591impl TryFrom<OwnedFd> for TcpStream {
592 type Error = io::Error;
593
594 fn try_from(value: OwnedFd) -> Result<Self, Self::Error> {
595 Self::try_from(std::net::TcpStream::from(value))
596 }
597}
598
599impl AsyncRead for TcpStream {
600 fn poll_read(
601 mut self: Pin<&mut Self>,
602 cx: &mut Context<'_>,
603 buf: &mut [u8],
604 ) -> Poll<io::Result<usize>> {
605 loop {
606 // Attempt the non-blocking operation.
607 match self.inner.get_ref().read(buf) {
608 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {}
609 res => {
610 self.readable = None;
611 return Poll::Ready(res);
612 }
613 }
614
615 // Initialize the future to wait for readiness.
616 if self.readable.is_none() {
617 self.readable = Some(self.inner.clone().readable_owned());
618 }
619
620 // Poll the future for readiness.
621 if let Some(f) = &mut self.readable {
622 let res = ready!(Pin::new(f).poll(cx));
623 self.readable = None;
624 res?;
625 }
626 }
627 }
628}
629
630impl AsyncWrite for TcpStream {
631 fn poll_write(
632 mut self: Pin<&mut Self>,
633 cx: &mut Context<'_>,
634 buf: &[u8],
635 ) -> Poll<io::Result<usize>> {
636 loop {
637 // Attempt the non-blocking operation.
638 match self.inner.get_ref().write(buf) {
639 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {}
640 res => {
641 self.writable = None;
642 return Poll::Ready(res);
643 }
644 }
645
646 // Initialize the future to wait for readiness.
647 if self.writable.is_none() {
648 self.writable = Some(self.inner.clone().writable_owned());
649 }
650
651 // Poll the future for readiness.
652 if let Some(f) = &mut self.writable {
653 let res = ready!(Pin::new(f).poll(cx));
654 self.writable = None;
655 res?;
656 }
657 }
658 }
659
660 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
661 loop {
662 // Attempt the non-blocking operation.
663 match self.inner.get_ref().flush() {
664 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {}
665 res => {
666 self.writable = None;
667 return Poll::Ready(res);
668 }
669 }
670
671 // Initialize the future to wait for readiness.
672 if self.writable.is_none() {
673 self.writable = Some(self.inner.clone().writable_owned());
674 }
675
676 // Poll the future for readiness.
677 if let Some(f) = &mut self.writable {
678 let res = ready!(Pin::new(f).poll(cx));
679 self.writable = None;
680 res?;
681 }
682 }
683 }
684
685 fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
686 Poll::Ready(self.inner.get_ref().shutdown(Shutdown::Write))
687 }
688
689 fn poll_write_vectored(
690 mut self: Pin<&mut Self>,
691 cx: &mut Context<'_>,
692 bufs: &[IoSlice<'_>],
693 ) -> Poll<io::Result<usize>> {
694 loop {
695 // Attempt the non-blocking operation.
696 match self.inner.get_ref().write_vectored(bufs) {
697 Err(err) if err.kind() == io::ErrorKind::WouldBlock => {}
698 res => {
699 self.writable = None;
700 return Poll::Ready(res);
701 }
702 }
703
704 // Initialize the future to wait for readiness.
705 if self.writable.is_none() {
706 self.writable = Some(self.inner.clone().writable_owned());
707 }
708
709 // Poll the future for readiness.
710 if let Some(f) = &mut self.writable {
711 let res = ready!(Pin::new(f).poll(cx));
712 self.writable = None;
713 res?;
714 }
715 }
716 }
717}