Skip to main content

pingora_core/protocols/l4/
stream.rs

1// Copyright 2026 Cloudflare, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Transport layer connection
16
17use async_trait::async_trait;
18use futures::FutureExt;
19use log::{debug, error};
20
21use pingora_error::{ErrorType::*, OrErr, Result};
22#[cfg(target_os = "linux")]
23use std::io::IoSliceMut;
24#[cfg(unix)]
25use std::os::unix::io::AsRawFd;
26#[cfg(windows)]
27use std::os::windows::io::AsRawSocket;
28use std::pin::Pin;
29use std::sync::Arc;
30use std::task::{Context, Poll};
31use std::time::{Duration, Instant, SystemTime};
32#[cfg(target_os = "linux")]
33use tokio::io::Interest;
34use tokio::io::{self, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader, BufWriter, ReadBuf};
35use tokio::net::TcpStream;
36#[cfg(unix)]
37use tokio::net::UnixStream;
38
39use crate::protocols::l4::ext::{set_tcp_keepalive, TcpKeepalive};
40use crate::protocols::l4::virt;
41use crate::protocols::raw_connect::ProxyDigest;
42use crate::protocols::{
43    GetProxyDigest, GetSocketDigest, GetTimingDigest, Peek, Shutdown, SocketDigest, Ssl,
44    TimingDigest, UniqueID, UniqueIDType,
45};
46use crate::upstreams::peer::Tracer;
47
48#[derive(Debug)]
49enum RawStream {
50    Tcp(TcpStream),
51    #[cfg(unix)]
52    Unix(UnixStream),
53    Virtual(virt::VirtualSocketStream),
54}
55
56impl AsyncRead for RawStream {
57    fn poll_read(
58        self: Pin<&mut Self>,
59        cx: &mut Context<'_>,
60        buf: &mut ReadBuf<'_>,
61    ) -> Poll<io::Result<()>> {
62        // Safety: Basic enum pin projection
63        unsafe {
64            match &mut Pin::get_unchecked_mut(self) {
65                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_read(cx, buf),
66                #[cfg(unix)]
67                RawStream::Unix(s) => Pin::new_unchecked(s).poll_read(cx, buf),
68                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_read(cx, buf),
69            }
70        }
71    }
72}
73
74impl AsyncWrite for RawStream {
75    fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<io::Result<usize>> {
76        // Safety: Basic enum pin projection
77        unsafe {
78            match &mut Pin::get_unchecked_mut(self) {
79                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_write(cx, buf),
80                #[cfg(unix)]
81                RawStream::Unix(s) => Pin::new_unchecked(s).poll_write(cx, buf),
82                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_write(cx, buf),
83            }
84        }
85    }
86
87    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
88        // Safety: Basic enum pin projection
89        unsafe {
90            match &mut Pin::get_unchecked_mut(self) {
91                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_flush(cx),
92                #[cfg(unix)]
93                RawStream::Unix(s) => Pin::new_unchecked(s).poll_flush(cx),
94                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_flush(cx),
95            }
96        }
97    }
98
99    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
100        // Safety: Basic enum pin projection
101        unsafe {
102            match &mut Pin::get_unchecked_mut(self) {
103                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_shutdown(cx),
104                #[cfg(unix)]
105                RawStream::Unix(s) => Pin::new_unchecked(s).poll_shutdown(cx),
106                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_shutdown(cx),
107            }
108        }
109    }
110
111    fn poll_write_vectored(
112        self: Pin<&mut Self>,
113        cx: &mut Context<'_>,
114        bufs: &[std::io::IoSlice<'_>],
115    ) -> Poll<io::Result<usize>> {
116        // Safety: Basic enum pin projection
117        unsafe {
118            match &mut Pin::get_unchecked_mut(self) {
119                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_write_vectored(cx, bufs),
120                #[cfg(unix)]
121                RawStream::Unix(s) => Pin::new_unchecked(s).poll_write_vectored(cx, bufs),
122                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_write_vectored(cx, bufs),
123            }
124        }
125    }
126
127    fn is_write_vectored(&self) -> bool {
128        match self {
129            RawStream::Tcp(s) => s.is_write_vectored(),
130            #[cfg(unix)]
131            RawStream::Unix(s) => s.is_write_vectored(),
132            RawStream::Virtual(s) => s.is_write_vectored(),
133        }
134    }
135}
136
137#[cfg(unix)]
138impl AsRawFd for RawStream {
139    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
140        match self {
141            RawStream::Tcp(s) => s.as_raw_fd(),
142            RawStream::Unix(s) => s.as_raw_fd(),
143            RawStream::Virtual(_) => -1, // Virtual stream does not have a real fd
144        }
145    }
146}
147
148#[cfg(windows)]
149impl AsRawSocket for RawStream {
150    fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
151        match self {
152            RawStream::Tcp(s) => s.as_raw_socket(),
153            // Virtual stream does not have a real socket, return INVALID_SOCKET (!0)
154            RawStream::Virtual(_) => !0,
155        }
156    }
157}
158
159#[derive(Debug)]
160struct RawStreamWrapper {
161    pub(crate) stream: RawStream,
162    /// store the last rx timestamp of the stream.
163    pub(crate) rx_ts: Option<SystemTime>,
164    /// enable reading rx timestamp
165    #[cfg(target_os = "linux")]
166    pub(crate) enable_rx_ts: bool,
167    #[cfg(target_os = "linux")]
168    /// This can be reused across multiple recvmsg calls. The cmsg buffer may
169    /// come from old sockets created by older version of pingora and so,
170    /// this vector can only grow.
171    reusable_cmsg_space: Vec<u8>,
172}
173
174impl RawStreamWrapper {
175    pub fn new(stream: RawStream) -> Self {
176        RawStreamWrapper {
177            stream,
178            rx_ts: None,
179            #[cfg(target_os = "linux")]
180            enable_rx_ts: false,
181            #[cfg(target_os = "linux")]
182            reusable_cmsg_space: nix::cmsg_space!(nix::sys::socket::Timestamps),
183        }
184    }
185
186    #[cfg(target_os = "linux")]
187    pub fn enable_rx_ts(&mut self, enable_rx_ts: bool) {
188        self.enable_rx_ts = enable_rx_ts;
189    }
190}
191
192impl AsyncRead for RawStreamWrapper {
193    #[cfg(not(target_os = "linux"))]
194    fn poll_read(
195        self: Pin<&mut Self>,
196        cx: &mut Context<'_>,
197        buf: &mut ReadBuf<'_>,
198    ) -> Poll<io::Result<()>> {
199        // Safety: Basic enum pin projection
200        unsafe {
201            let rs_wrapper = Pin::get_unchecked_mut(self);
202            match &mut rs_wrapper.stream {
203                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_read(cx, buf),
204                #[cfg(unix)]
205                RawStream::Unix(s) => Pin::new_unchecked(s).poll_read(cx, buf),
206                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_read(cx, buf),
207            }
208        }
209    }
210
211    #[cfg(target_os = "linux")]
212    fn poll_read(
213        self: Pin<&mut Self>,
214        cx: &mut Context<'_>,
215        buf: &mut ReadBuf<'_>,
216    ) -> Poll<io::Result<()>> {
217        use futures::ready;
218        use nix::sys::socket::{recvmsg, ControlMessageOwned, MsgFlags, SockaddrStorage};
219
220        // if we do not need rx timestamp, then use the standard path
221        if !self.enable_rx_ts {
222            // Safety: Basic enum pin projection
223            unsafe {
224                let rs_wrapper = Pin::get_unchecked_mut(self);
225                match &mut rs_wrapper.stream {
226                    RawStream::Tcp(s) => return Pin::new_unchecked(s).poll_read(cx, buf),
227                    RawStream::Unix(s) => return Pin::new_unchecked(s).poll_read(cx, buf),
228                    RawStream::Virtual(s) => return Pin::new_unchecked(s).poll_read(cx, buf),
229                }
230            }
231        }
232
233        // Safety: Basic pin projection to get mutable stream
234        let rs_wrapper = unsafe { Pin::get_unchecked_mut(self) };
235        match &mut rs_wrapper.stream {
236            RawStream::Tcp(s) => {
237                loop {
238                    ready!(s.poll_read_ready(cx))?;
239                    // Safety: maybe uninitialized bytes will only be passed to recvmsg
240                    let b = unsafe {
241                        &mut *(buf.unfilled_mut() as *mut [std::mem::MaybeUninit<u8>]
242                            as *mut [u8])
243                    };
244                    let mut iov = [IoSliceMut::new(b)];
245
246                    rs_wrapper.reusable_cmsg_space.fill(0);
247
248                    match s.try_io(Interest::READABLE, || {
249                        recvmsg::<SockaddrStorage>(
250                            s.as_raw_fd(),
251                            &mut iov,
252                            Some(&mut rs_wrapper.reusable_cmsg_space),
253                            MsgFlags::empty(),
254                        )
255                        .map_err(|errno| errno.into())
256                    }) {
257                        Ok(r) => {
258                            if let Some(ControlMessageOwned::ScmTimestampsns(rtime)) = r
259                                .cmsgs()?
260                                .find(|i| matches!(i, ControlMessageOwned::ScmTimestampsns(_)))
261                            {
262                                // The returned timestamp is a real (i.e. not monotonic) timestamp
263                                // https://docs.kernel.org/networking/timestamping.html
264                                rs_wrapper.rx_ts =
265                                    SystemTime::UNIX_EPOCH.checked_add(rtime.system.into());
266                            }
267                            // Safety: We trust `recvmsg` to have filled up `r.bytes` bytes in the buffer.
268                            unsafe {
269                                buf.assume_init(r.bytes);
270                            }
271                            buf.advance(r.bytes);
272                            return Poll::Ready(Ok(()));
273                        }
274                        Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => continue,
275                        Err(e) => return Poll::Ready(Err(e)),
276                    }
277                }
278            }
279            // Unix RX timestamp only works with datagram for now, so we do not care about it
280            RawStream::Unix(s) => unsafe { Pin::new_unchecked(s).poll_read(cx, buf) },
281            RawStream::Virtual(s) => unsafe { Pin::new_unchecked(s).poll_read(cx, buf) },
282        }
283    }
284}
285
286impl AsyncWrite for RawStreamWrapper {
287    fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll<io::Result<usize>> {
288        // Safety: Basic enum pin projection
289        unsafe {
290            match &mut Pin::get_unchecked_mut(self).stream {
291                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_write(cx, buf),
292                #[cfg(unix)]
293                RawStream::Unix(s) => Pin::new_unchecked(s).poll_write(cx, buf),
294                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_write(cx, buf),
295            }
296        }
297    }
298
299    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
300        // Safety: Basic enum pin projection
301        unsafe {
302            match &mut Pin::get_unchecked_mut(self).stream {
303                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_flush(cx),
304                #[cfg(unix)]
305                RawStream::Unix(s) => Pin::new_unchecked(s).poll_flush(cx),
306                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_flush(cx),
307            }
308        }
309    }
310
311    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
312        // Safety: Basic enum pin projection
313        unsafe {
314            match &mut Pin::get_unchecked_mut(self).stream {
315                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_shutdown(cx),
316                #[cfg(unix)]
317                RawStream::Unix(s) => Pin::new_unchecked(s).poll_shutdown(cx),
318                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_shutdown(cx),
319            }
320        }
321    }
322
323    fn poll_write_vectored(
324        self: Pin<&mut Self>,
325        cx: &mut Context<'_>,
326        bufs: &[std::io::IoSlice<'_>],
327    ) -> Poll<io::Result<usize>> {
328        // Safety: Basic enum pin projection
329        unsafe {
330            match &mut Pin::get_unchecked_mut(self).stream {
331                RawStream::Tcp(s) => Pin::new_unchecked(s).poll_write_vectored(cx, bufs),
332                #[cfg(unix)]
333                RawStream::Unix(s) => Pin::new_unchecked(s).poll_write_vectored(cx, bufs),
334                RawStream::Virtual(s) => Pin::new_unchecked(s).poll_write_vectored(cx, bufs),
335            }
336        }
337    }
338
339    fn is_write_vectored(&self) -> bool {
340        self.stream.is_write_vectored()
341    }
342}
343
344#[cfg(unix)]
345impl AsRawFd for RawStreamWrapper {
346    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
347        self.stream.as_raw_fd()
348    }
349}
350
351#[cfg(windows)]
352impl AsRawSocket for RawStreamWrapper {
353    fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
354        self.stream.as_raw_socket()
355    }
356}
357
358/// The default L4 read buffer size.
359///
360/// Large read buffering helps reducing syscalls with little trade-off. The SSL
361/// layer always does "small" reads in 16k chunks (TLS record size), so L4 read
362/// buffering helps a lot.
363pub const DEFAULT_L4_READ_BUFFER_SIZE: usize = 64 * 1024;
364
365/// The default L4 write buffer size.
366///
367/// Small write buffering matches a typical MSS. Too large a write buffer delays
368/// real-time communication. This buffering effectively implements something
369/// similar to Nagle's algorithm, but user space can control when to flush.
370pub const DEFAULT_L4_WRITE_BUFFER_SIZE: usize = 1460;
371
372/// L4 read and write buffer sizing.
373///
374/// Leaving either side as `None` preserves Pingora's default for that side.
375/// Setting either side to `Some(0)` disables buffering for that direction.
376#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
377pub struct L4BufferSettings {
378    /// Read buffer size in bytes. `None` uses [`DEFAULT_L4_READ_BUFFER_SIZE`].
379    pub read: Option<usize>,
380    /// Write buffer size in bytes. `None` uses [`DEFAULT_L4_WRITE_BUFFER_SIZE`].
381    pub write: Option<usize>,
382}
383
384impl L4BufferSettings {
385    /// Create settings with both read and write buffer sizes set explicitly.
386    pub fn new(read: usize, write: usize) -> Self {
387        Self {
388            read: Some(read),
389            write: Some(write),
390        }
391    }
392
393    /// Create settings that disable both read and write buffering.
394    pub fn unbuffered() -> Self {
395        Self::new(0, 0)
396    }
397
398    /// Set the read buffer size.
399    pub fn read(mut self, read: usize) -> Self {
400        self.read = Some(read);
401        self
402    }
403
404    /// Set the write buffer size.
405    pub fn write(mut self, write: usize) -> Self {
406        self.write = Some(write);
407        self
408    }
409
410    /// Resolved read buffer size after applying defaults.
411    pub fn read_capacity(&self) -> usize {
412        self.read.unwrap_or(DEFAULT_L4_READ_BUFFER_SIZE)
413    }
414
415    /// Resolved write buffer size after applying defaults.
416    pub fn write_capacity(&self) -> usize {
417        self.write.unwrap_or(DEFAULT_L4_WRITE_BUFFER_SIZE)
418    }
419}
420
421/// The L4 buffers in front of a [`RawStreamWrapper`]: a read buffer over a write
422/// buffer, the same layering as tokio's [`BufStream`](tokio::io::BufStream).
423///
424/// A zero read capacity leaves the read buffer out, because [`BufReader`] panics on
425/// a zero capacity. Reads then go straight to the raw stream, as they did through
426/// an empty `BufReader`. [`BufWriter`] accepts a zero capacity and writes straight
427/// through.
428#[derive(Debug)]
429enum BufferedStream {
430    UnbufferedRead(BufWriter<RawStreamWrapper>),
431    BufferedRead(BufReader<BufWriter<RawStreamWrapper>>),
432}
433
434impl BufferedStream {
435    fn with_capacity(read: usize, write: usize, stream: RawStreamWrapper) -> Self {
436        let writer = BufWriter::with_capacity(write, stream);
437        if read == 0 {
438            BufferedStream::UnbufferedRead(writer)
439        } else {
440            BufferedStream::BufferedRead(BufReader::with_capacity(read, writer))
441        }
442    }
443
444    fn writer(&self) -> &BufWriter<RawStreamWrapper> {
445        match self {
446            BufferedStream::UnbufferedRead(writer) => writer,
447            BufferedStream::BufferedRead(reader) => reader.get_ref(),
448        }
449    }
450
451    fn writer_mut(&mut self) -> &mut BufWriter<RawStreamWrapper> {
452        match self {
453            BufferedStream::UnbufferedRead(writer) => writer,
454            BufferedStream::BufferedRead(reader) => reader.get_mut(),
455        }
456    }
457
458    fn get_ref(&self) -> &RawStreamWrapper {
459        self.writer().get_ref()
460    }
461
462    fn get_mut(&mut self) -> &mut RawStreamWrapper {
463        self.writer_mut().get_mut()
464    }
465
466    /// Return the raw stream. Anything left in either buffer is lost.
467    fn into_inner(self) -> RawStreamWrapper {
468        match self {
469            BufferedStream::UnbufferedRead(writer) => writer.into_inner(),
470            BufferedStream::BufferedRead(reader) => reader.into_inner().into_inner(),
471        }
472    }
473}
474
475impl AsyncRead for BufferedStream {
476    fn poll_read(
477        mut self: Pin<&mut Self>,
478        cx: &mut Context<'_>,
479        buf: &mut ReadBuf<'_>,
480    ) -> Poll<io::Result<()>> {
481        match &mut *self {
482            BufferedStream::UnbufferedRead(writer) => Pin::new(writer).poll_read(cx, buf),
483            BufferedStream::BufferedRead(reader) => Pin::new(reader).poll_read(cx, buf),
484        }
485    }
486}
487
488// `BufReader` only forwards writes to the `BufWriter` under it, so write to the `BufWriter`
489// directly.
490impl AsyncWrite for BufferedStream {
491    fn poll_write(
492        mut self: Pin<&mut Self>,
493        cx: &mut Context,
494        buf: &[u8],
495    ) -> Poll<io::Result<usize>> {
496        Pin::new(self.writer_mut()).poll_write(cx, buf)
497    }
498
499    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
500        Pin::new(self.writer_mut()).poll_flush(cx)
501    }
502
503    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
504        Pin::new(self.writer_mut()).poll_shutdown(cx)
505    }
506
507    fn poll_write_vectored(
508        mut self: Pin<&mut Self>,
509        cx: &mut Context<'_>,
510        bufs: &[std::io::IoSlice<'_>],
511    ) -> Poll<io::Result<usize>> {
512        Pin::new(self.writer_mut()).poll_write_vectored(cx, bufs)
513    }
514
515    fn is_write_vectored(&self) -> bool {
516        self.writer().is_write_vectored()
517    }
518}
519
520// NOTE: with writer buffering, users need to call flush() to make sure the data is actually
521// sent. Otherwise data could be stuck in the buffer forever or get lost when stream is closed.
522
523/// A concrete type for transport layer connection + extra fields for logging
524#[derive(Debug)]
525pub struct Stream {
526    // Use `Option` to be able to swap to adjust the buffer size. Always safe to unwrap
527    stream: Option<BufferedStream>,
528    // the data put back at the front of the read buffer, in order to replay the read
529    rewind_read_buf: Vec<Vec<u8>>,
530    buffer_write: bool,
531    proxy_digest: Option<Arc<ProxyDigest>>,
532    socket_digest: Option<Arc<SocketDigest>>,
533    /// When this connection is established
534    pub established_ts: SystemTime,
535    establishment_duration: Option<Duration>,
536    offload_wait_duration: Option<Duration>,
537    /// The distributed tracing object for this stream
538    pub tracer: Option<Tracer>,
539    read_pending_time: AccumulatedDuration,
540    write_pending_time: AccumulatedDuration,
541    /// Last rx timestamp associated with the last recvmsg call.
542    pub rx_ts: Option<SystemTime>,
543}
544
545impl Stream {
546    fn stream(&self) -> &BufferedStream {
547        self.stream.as_ref().expect("stream should always be set")
548    }
549
550    fn stream_mut(&mut self) -> &mut BufferedStream {
551        self.stream.as_mut().expect("stream should always be set")
552    }
553
554    /// Record transport connection timing for this stream.
555    pub(crate) fn set_establishment_timing(
556        &mut self,
557        establishment_duration: Duration,
558        offload_wait_duration: Option<Duration>,
559    ) {
560        self.establishment_duration = Some(establishment_duration);
561        self.offload_wait_duration = offload_wait_duration;
562    }
563
564    /// set TCP nodelay for this connection if `self` is TCP
565    pub fn set_nodelay(&mut self) -> Result<()> {
566        match &self.stream_mut().get_mut().stream {
567            RawStream::Tcp(s) => {
568                s.set_nodelay(true)
569                    .or_err(ConnectError, "failed to set_nodelay")?;
570            }
571            RawStream::Virtual(s) => {
572                s.set_socket_option(virt::VirtualSockOpt::NoDelay)
573                    .or_err(ConnectError, "failed to set_nodelay on virtual socket")?;
574            }
575            _ => (),
576        }
577        Ok(())
578    }
579
580    /// set TCP keepalive settings for this connection if `self` is TCP
581    pub fn set_keepalive(&mut self, ka: &TcpKeepalive) -> Result<()> {
582        match &self.stream_mut().get_mut().stream {
583            RawStream::Tcp(s) => {
584                debug!("Setting tcp keepalive");
585                set_tcp_keepalive(s, ka)?;
586            }
587            RawStream::Virtual(s) => {
588                s.set_socket_option(virt::VirtualSockOpt::KeepAlive(ka.clone()))
589                    .or_err(ConnectError, "failed to set_keepalive on virtual socket")?;
590            }
591            _ => (),
592        }
593        Ok(())
594    }
595
596    #[cfg(target_os = "linux")]
597    pub fn set_rx_timestamp(&mut self) -> Result<()> {
598        use nix::sys::socket::{setsockopt, sockopt, TimestampingFlag};
599
600        if let RawStream::Tcp(s) = &self.stream_mut().get_mut().stream {
601            let timestamp_options = TimestampingFlag::SOF_TIMESTAMPING_RX_SOFTWARE
602                | TimestampingFlag::SOF_TIMESTAMPING_SOFTWARE;
603            setsockopt(&s, sockopt::Timestamping, &timestamp_options)
604                .or_err(InternalError, "failed to set SOF_TIMESTAMPING_RX_SOFTWARE")?;
605            self.stream_mut().get_mut().enable_rx_ts(true);
606        }
607
608        Ok(())
609    }
610
611    #[cfg(not(target_os = "linux"))]
612    pub fn set_rx_timestamp(&mut self) -> io::Result<()> {
613        Ok(())
614    }
615
616    /// Put some data back to the head of the stream to be read again.
617    ///
618    /// This is useful when you've read data to detect a protocol (e.g., PROXY protocol)
619    /// but the data wasn't what you expected, so you need to "unread" it.
620    pub fn rewind(&mut self, data: &[u8]) {
621        if !data.is_empty() {
622            self.rewind_read_buf.push(data.to_vec());
623        }
624    }
625
626    /// Set the read and write buffer sizes
627    /// It is only set later because of the malloc overhead in critical accept() path
628    pub(crate) fn set_buffer(&mut self, buffer: L4BufferSettings) {
629        use std::mem;
630        // Since the buffers can't be resized in place,
631        // we take the raw stream out of them and put it in new buffers with the size we want
632        let stream = mem::take(&mut self.stream);
633        let stream = stream.map(|s| {
634            BufferedStream::with_capacity(
635                buffer.read_capacity(),
636                buffer.write_capacity(),
637                s.into_inner(),
638            )
639        });
640        let _ = mem::replace(&mut self.stream, stream);
641    }
642}
643
644impl From<TcpStream> for Stream {
645    fn from(s: TcpStream) -> Self {
646        Stream {
647            stream: Some(BufferedStream::with_capacity(
648                0,
649                0,
650                RawStreamWrapper::new(RawStream::Tcp(s)),
651            )),
652            rewind_read_buf: Vec::new(),
653            buffer_write: true,
654            established_ts: SystemTime::now(),
655            establishment_duration: None,
656            offload_wait_duration: None,
657            proxy_digest: None,
658            socket_digest: None,
659            tracer: None,
660            read_pending_time: AccumulatedDuration::new(),
661            write_pending_time: AccumulatedDuration::new(),
662            rx_ts: None,
663        }
664    }
665}
666
667impl From<virt::VirtualSocketStream> for Stream {
668    fn from(s: virt::VirtualSocketStream) -> Self {
669        Stream {
670            stream: Some(BufferedStream::with_capacity(
671                0,
672                0,
673                RawStreamWrapper::new(RawStream::Virtual(s)),
674            )),
675            rewind_read_buf: Vec::new(),
676            buffer_write: true,
677            established_ts: SystemTime::now(),
678            establishment_duration: None,
679            offload_wait_duration: None,
680            proxy_digest: None,
681            socket_digest: None,
682            tracer: None,
683            read_pending_time: AccumulatedDuration::new(),
684            write_pending_time: AccumulatedDuration::new(),
685            rx_ts: None,
686        }
687    }
688}
689
690#[cfg(unix)]
691impl From<UnixStream> for Stream {
692    fn from(s: UnixStream) -> Self {
693        Stream {
694            stream: Some(BufferedStream::with_capacity(
695                0,
696                0,
697                RawStreamWrapper::new(RawStream::Unix(s)),
698            )),
699            rewind_read_buf: Vec::new(),
700            buffer_write: true,
701            established_ts: SystemTime::now(),
702            establishment_duration: None,
703            offload_wait_duration: None,
704            proxy_digest: None,
705            socket_digest: None,
706            tracer: None,
707            read_pending_time: AccumulatedDuration::new(),
708            write_pending_time: AccumulatedDuration::new(),
709            rx_ts: None,
710        }
711    }
712}
713
714#[cfg(unix)]
715impl AsRawFd for Stream {
716    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
717        self.stream().get_ref().as_raw_fd()
718    }
719}
720
721#[cfg(windows)]
722impl AsRawSocket for Stream {
723    fn as_raw_socket(&self) -> std::os::windows::io::RawSocket {
724        self.stream().get_ref().as_raw_socket()
725    }
726}
727
728#[cfg(unix)]
729impl UniqueID for Stream {
730    fn id(&self) -> UniqueIDType {
731        self.as_raw_fd()
732    }
733}
734
735#[cfg(windows)]
736impl UniqueID for Stream {
737    fn id(&self) -> usize {
738        self.as_raw_socket() as usize
739    }
740}
741
742impl Ssl for Stream {}
743
744#[async_trait]
745impl Peek for Stream {
746    async fn try_peek(&mut self, buf: &mut [u8]) -> std::io::Result<bool> {
747        use tokio::io::AsyncReadExt;
748        self.read_exact(buf).await?;
749        // rewind regardless of what is read
750        self.rewind(buf);
751        Ok(true)
752    }
753}
754
755#[async_trait]
756impl Shutdown for Stream {
757    async fn shutdown(&mut self) {
758        AsyncWriteExt::shutdown(self).await.unwrap_or_else(|e| {
759            debug!("Failed to shutdown connection: {:?}", e);
760        });
761    }
762}
763
764impl GetTimingDigest for Stream {
765    fn get_timing_digest(&self) -> Vec<Option<TimingDigest>> {
766        let mut digest = Vec::with_capacity(2); // expect to have both L4 stream and TLS layer
767        digest.push(Some(TimingDigest {
768            established_ts: self.established_ts,
769            establishment_duration: self.establishment_duration,
770            offload_wait_duration: self.offload_wait_duration,
771        }));
772        digest
773    }
774
775    fn get_read_pending_time(&self) -> Duration {
776        self.read_pending_time.total
777    }
778
779    fn get_write_pending_time(&self) -> Duration {
780        self.write_pending_time.total
781    }
782}
783
784impl GetProxyDigest for Stream {
785    fn get_proxy_digest(&self) -> Option<Arc<ProxyDigest>> {
786        self.proxy_digest.clone()
787    }
788
789    fn set_proxy_digest(&mut self, digest: ProxyDigest) {
790        self.proxy_digest = Some(Arc::new(digest));
791    }
792}
793
794impl GetSocketDigest for Stream {
795    fn get_socket_digest(&self) -> Option<Arc<SocketDigest>> {
796        self.socket_digest.clone()
797    }
798
799    fn set_socket_digest(&mut self, socket_digest: SocketDigest) {
800        self.socket_digest = Some(Arc::new(socket_digest))
801    }
802}
803
804impl Drop for Stream {
805    fn drop(&mut self) {
806        if let Some(t) = self.tracer.as_ref() {
807            t.0.on_disconnected();
808        }
809        /* use nodelay/local_addr function to detect socket status */
810        let ret = match &self.stream().get_ref().stream {
811            RawStream::Tcp(s) => s.nodelay().err(),
812            #[cfg(unix)]
813            RawStream::Unix(s) => s.local_addr().err(),
814            RawStream::Virtual(_) => {
815                // TODO: should this do something?
816                None
817            }
818        };
819        if let Some(e) = ret {
820            match e.kind() {
821                tokio::io::ErrorKind::Other => {
822                    if let Some(ecode) = e.raw_os_error() {
823                        if ecode == 9 {
824                            // Or we could panic here
825                            error!("Crit: socket {:?} is being double closed", self.stream);
826                        }
827                    }
828                }
829                _ => {
830                    debug!("Socket is already broken {:?}", e);
831                }
832            }
833        } else {
834            // try flush the write buffer. We use now_or_never() because
835            // 1. Drop cannot be async
836            // 2. write should usually be ready, unless the buf is full.
837            let _ = self.flush().now_or_never();
838        }
839        debug!("Dropping socket {:?}", self.stream);
840    }
841}
842
843impl AsyncRead for Stream {
844    fn poll_read(
845        mut self: Pin<&mut Self>,
846        cx: &mut Context<'_>,
847        buf: &mut ReadBuf<'_>,
848    ) -> Poll<io::Result<()>> {
849        let result = if !self.rewind_read_buf.is_empty() {
850            let data_to_read = self.rewind_read_buf.pop().unwrap(); // safe
851            let mut data_to_read = data_to_read.as_slice();
852            let result = Pin::new(&mut data_to_read).poll_read(cx, buf);
853            // return the remaining data back to the head of rewind_read_buf
854            if !data_to_read.is_empty() {
855                let remaining_buf = Vec::from(data_to_read);
856                self.rewind_read_buf.push(remaining_buf);
857            }
858            result
859        } else {
860            Pin::new(&mut self.stream_mut()).poll_read(cx, buf)
861        };
862        self.read_pending_time.poll_time(&result);
863        self.rx_ts = self.stream().get_ref().rx_ts;
864        result
865    }
866}
867
868impl AsyncWrite for Stream {
869    fn poll_write(
870        mut self: Pin<&mut Self>,
871        cx: &mut Context,
872        buf: &[u8],
873    ) -> Poll<io::Result<usize>> {
874        let result = if self.buffer_write {
875            Pin::new(&mut self.stream_mut()).poll_write(cx, buf)
876        } else {
877            Pin::new(&mut self.stream_mut().get_mut()).poll_write(cx, buf)
878        };
879        self.write_pending_time.poll_write_time(&result, buf.len());
880        result
881    }
882
883    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
884        let result = Pin::new(&mut self.stream_mut()).poll_flush(cx);
885        self.write_pending_time.poll_time(&result);
886        result
887    }
888
889    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
890        Pin::new(&mut self.stream_mut()).poll_shutdown(cx)
891    }
892
893    fn poll_write_vectored(
894        mut self: Pin<&mut Self>,
895        cx: &mut Context<'_>,
896        bufs: &[std::io::IoSlice<'_>],
897    ) -> Poll<io::Result<usize>> {
898        let total_size = bufs.iter().fold(0, |acc, s| acc + s.len());
899
900        let result = if self.buffer_write {
901            Pin::new(&mut self.stream_mut()).poll_write_vectored(cx, bufs)
902        } else {
903            Pin::new(&mut self.stream_mut().get_mut()).poll_write_vectored(cx, bufs)
904        };
905
906        self.write_pending_time.poll_write_time(&result, total_size);
907        result
908    }
909
910    fn is_write_vectored(&self) -> bool {
911        if self.buffer_write {
912            self.stream().is_write_vectored() // it is true
913        } else {
914            self.stream().get_ref().is_write_vectored()
915        }
916    }
917}
918
919#[derive(Debug)]
920struct AccumulatedDuration {
921    total: Duration,
922    last_start: Option<Instant>,
923}
924
925impl AccumulatedDuration {
926    fn new() -> Self {
927        AccumulatedDuration {
928            total: Duration::ZERO,
929            last_start: None,
930        }
931    }
932
933    fn start(&mut self) {
934        if self.last_start.is_none() {
935            self.last_start = Some(Instant::now());
936        }
937    }
938
939    fn stop(&mut self) {
940        if let Some(start) = self.last_start.take() {
941            self.total += start.elapsed();
942        }
943    }
944
945    fn poll_write_time(&mut self, result: &Poll<io::Result<usize>>, buf_size: usize) {
946        match result {
947            Poll::Ready(Ok(n)) => {
948                if *n == buf_size {
949                    self.stop();
950                } else {
951                    // partial write
952                    self.start();
953                }
954            }
955            Poll::Ready(Err(_)) => {
956                self.stop();
957            }
958            _ => self.start(),
959        }
960    }
961
962    fn poll_time(&mut self, result: &Poll<io::Result<()>>) {
963        match result {
964            Poll::Ready(_) => {
965                self.stop();
966            }
967            _ => self.start(),
968        }
969    }
970}
971
972#[cfg(test)]
973#[cfg(target_os = "linux")]
974mod tests {
975    use super::*;
976    use std::sync::Arc;
977    use tokio::io::AsyncReadExt;
978    use tokio::io::AsyncWriteExt;
979    use tokio::net::TcpListener;
980    use tokio::sync::Notify;
981
982    #[cfg(target_os = "linux")]
983    #[tokio::test]
984    async fn test_rx_timestamp() {
985        let message = "hello world".as_bytes();
986        let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
987        let addr = listener.local_addr().unwrap();
988        let notify = Arc::new(Notify::new());
989        let notify2 = notify.clone();
990
991        tokio::spawn(async move {
992            let (mut stream, _) = listener.accept().await.unwrap();
993            notify2.notified().await;
994            stream.write_all(message).await.unwrap();
995        });
996
997        let mut stream: Stream = TcpStream::connect(addr).await.unwrap().into();
998        stream.set_rx_timestamp().unwrap();
999        // Receive the message
1000        // setsockopt for SO_TIMESTAMPING is asynchronous so sleep a little bit
1001        // to let kernel do the work
1002        std::thread::sleep(Duration::from_micros(100));
1003        notify.notify_one();
1004
1005        let mut buffer = vec![0u8; message.len()];
1006        let n = stream.read(buffer.as_mut_slice()).await.unwrap();
1007        assert_eq!(n, message.len());
1008        assert!(stream.rx_ts.is_some());
1009    }
1010
1011    #[cfg(target_os = "linux")]
1012    #[tokio::test]
1013    async fn test_rx_timestamp_standard_path() {
1014        let message = "hello world".as_bytes();
1015        let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
1016        let addr = listener.local_addr().unwrap();
1017        let notify = Arc::new(Notify::new());
1018        let notify2 = notify.clone();
1019
1020        tokio::spawn(async move {
1021            let (mut stream, _) = listener.accept().await.unwrap();
1022            notify2.notified().await;
1023            stream.write_all(message).await.unwrap();
1024        });
1025
1026        let mut stream: Stream = TcpStream::connect(addr).await.unwrap().into();
1027        std::thread::sleep(Duration::from_micros(100));
1028        notify.notify_one();
1029
1030        let mut buffer = vec![0u8; message.len()];
1031        let n = stream.read(buffer.as_mut_slice()).await.unwrap();
1032        assert_eq!(n, message.len());
1033        assert!(stream.rx_ts.is_none());
1034    }
1035
1036    #[tokio::test]
1037    async fn test_stream_rewind() {
1038        let message = b"hello world";
1039        let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
1040        let addr = listener.local_addr().unwrap();
1041        let notify = Arc::new(Notify::new());
1042        let notify2 = notify.clone();
1043
1044        tokio::spawn(async move {
1045            let (mut stream, _) = listener.accept().await.unwrap();
1046            notify2.notified().await;
1047            stream.write_all(message).await.unwrap();
1048        });
1049
1050        let mut stream: Stream = TcpStream::connect(addr).await.unwrap().into();
1051
1052        let rewind_test = b"this is Sparta!";
1053        stream.rewind(rewind_test);
1054
1055        // partially read rewind_test because of the buffer size limit
1056        let mut buffer = vec![0u8; message.len()];
1057        let n = stream.read(buffer.as_mut_slice()).await.unwrap();
1058        assert_eq!(n, message.len());
1059        assert_eq!(buffer, rewind_test[..message.len()]);
1060
1061        // read the rest of rewind_test
1062        let n = stream.read(buffer.as_mut_slice()).await.unwrap();
1063        assert_eq!(n, rewind_test.len() - message.len());
1064        assert_eq!(buffer[..n], rewind_test[message.len()..]);
1065
1066        // read the actual data
1067        notify.notify_one();
1068        let n = stream.read(buffer.as_mut_slice()).await.unwrap();
1069        assert_eq!(n, message.len());
1070        assert_eq!(buffer, message);
1071    }
1072
1073    #[tokio::test]
1074    async fn test_stream_peek() {
1075        let message = b"hello world";
1076        dbg!("try peek");
1077        let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
1078        let addr = listener.local_addr().unwrap();
1079        let notify = Arc::new(Notify::new());
1080        let notify2 = notify.clone();
1081
1082        tokio::spawn(async move {
1083            let (mut stream, _) = listener.accept().await.unwrap();
1084            notify2.notified().await;
1085            stream.write_all(message).await.unwrap();
1086            drop(stream);
1087        });
1088
1089        notify.notify_one();
1090
1091        let mut stream: Stream = TcpStream::connect(addr).await.unwrap().into();
1092        let mut buffer = vec![0u8; 5];
1093        assert!(stream.try_peek(&mut buffer).await.unwrap());
1094        assert_eq!(buffer, message[0..5]);
1095        let mut buffer = vec![];
1096        stream.read_to_end(&mut buffer).await.unwrap();
1097        assert_eq!(buffer, message);
1098    }
1099
1100    #[tokio::test]
1101    async fn test_stream_two_subsequent_peek_calls_before_read() {
1102        let message = b"abcdefghijklmn";
1103
1104        let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
1105        let addr = listener.local_addr().unwrap();
1106        let notify = Arc::new(Notify::new());
1107        let notify2 = notify.clone();
1108
1109        tokio::spawn(async move {
1110            let (mut stream, _) = listener.accept().await.unwrap();
1111            notify2.notified().await;
1112            stream.write_all(message).await.unwrap();
1113            drop(stream);
1114        });
1115
1116        notify.notify_one();
1117
1118        let mut stream: Stream = TcpStream::connect(addr).await.unwrap().into();
1119
1120        // Peek 4 bytes
1121        let mut buffer = vec![0u8; 4];
1122        assert!(stream.try_peek(&mut buffer).await.unwrap());
1123        assert_eq!(buffer, message[0..4]);
1124
1125        // Peek 2 bytes
1126        let mut buffer = vec![0u8; 2];
1127        assert!(stream.try_peek(&mut buffer).await.unwrap());
1128        assert_eq!(buffer, message[0..2]);
1129
1130        // Read 1 byte: ['a']
1131        let mut buffer = vec![0u8; 1];
1132        stream.read_exact(&mut buffer).await.unwrap();
1133        assert_eq!(buffer, message[0..1]);
1134
1135        // Read as many bytes as possible, return 1 byte ['b']
1136        //  from the first retry buffer chunk
1137        let mut buffer = vec![0u8; 100];
1138        let n = stream.read(&mut buffer).await.unwrap();
1139        assert_eq!(n, 1);
1140        assert_eq!(buffer[..n], message[1..2]);
1141
1142        // Read the rest ['cdefghijklmn']
1143        let mut buffer = vec![];
1144        stream.read_to_end(&mut buffer).await.unwrap();
1145        assert_eq!(buffer, message[2..]);
1146    }
1147}