|
1 | | -use std::{future::Future, io, net::SocketAddr}; |
| 1 | +use std::{ |
| 2 | + future::Future, |
| 3 | + io, |
| 4 | + net::SocketAddr, |
| 5 | + pin::Pin, |
| 6 | + task::{Context, Poll}, |
| 7 | +}; |
2 | 8 |
|
3 | 9 | use compio_buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut}; |
4 | 10 | use compio_driver::impl_raw_fd; |
5 | 11 | use compio_io::{AsyncRead, AsyncReadManaged, AsyncWrite, util::Splittable}; |
6 | 12 | use compio_runtime::{BorrowedBuffer, BufferPool, fd::PollFd}; |
| 13 | +use futures_util::{Stream, StreamExt, stream::FusedStream}; |
7 | 14 | use socket2::{Protocol, SockAddr, Socket as Socket2, Type}; |
8 | 15 |
|
9 | 16 | use crate::{ |
10 | | - OwnedReadHalf, OwnedWriteHalf, ReadHalf, Socket, SocketOpts, ToSocketAddrsAsync, WriteHalf, |
| 17 | + Incoming, OwnedReadHalf, OwnedWriteHalf, ReadHalf, Socket, SocketOpts, ToSocketAddrsAsync, |
| 18 | + WriteHalf, |
11 | 19 | }; |
12 | 20 |
|
13 | 21 | /// A TCP socket server, listening for connections. |
@@ -120,6 +128,20 @@ impl TcpListener { |
120 | 128 | Ok((stream, addr.as_socket().expect("should be SocketAddr"))) |
121 | 129 | } |
122 | 130 |
|
| 131 | + /// Returns a stream of incoming connections to this listener. |
| 132 | + pub fn incoming(&self) -> TcpIncoming<'_> { |
| 133 | + self.incoming_with_options(&SocketOpts::default()) |
| 134 | + } |
| 135 | + |
| 136 | + /// Returns a stream of incoming connections to this listener, and sets |
| 137 | + /// options for each accepted connection. |
| 138 | + pub fn incoming_with_options<'a>(&'a self, options: &SocketOpts) -> TcpIncoming<'a> { |
| 139 | + TcpIncoming { |
| 140 | + inner: self.inner.incoming(), |
| 141 | + opts: *options, |
| 142 | + } |
| 143 | + } |
| 144 | + |
123 | 145 | /// Returns the local address that this listener is bound to. |
124 | 146 | /// |
125 | 147 | /// This can be useful, for example, when binding to port 0 to |
@@ -152,6 +174,33 @@ impl TcpListener { |
152 | 174 |
|
153 | 175 | impl_raw_fd!(TcpListener, socket2::Socket, inner, socket); |
154 | 176 |
|
| 177 | +/// A stream of incoming TCP connections. |
| 178 | +pub struct TcpIncoming<'a> { |
| 179 | + inner: Incoming<'a>, |
| 180 | + opts: SocketOpts, |
| 181 | +} |
| 182 | + |
| 183 | +impl Stream for TcpIncoming<'_> { |
| 184 | + type Item = io::Result<TcpStream>; |
| 185 | + |
| 186 | + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { |
| 187 | + let this = self.get_mut(); |
| 188 | + this.inner.poll_next_unpin(cx).map(|res| { |
| 189 | + res.map(|res| { |
| 190 | + let socket = res?; |
| 191 | + this.opts.setup_socket(&socket)?; |
| 192 | + Ok(TcpStream { inner: socket }) |
| 193 | + }) |
| 194 | + }) |
| 195 | + } |
| 196 | +} |
| 197 | + |
| 198 | +impl FusedStream for TcpIncoming<'_> { |
| 199 | + fn is_terminated(&self) -> bool { |
| 200 | + self.inner.is_terminated() |
| 201 | + } |
| 202 | +} |
| 203 | + |
155 | 204 | /// A TCP stream between a local and a remote socket. |
156 | 205 | /// |
157 | 206 | /// A TCP stream can either be created by connecting to an endpoint, via the |
|
0 commit comments