Coverage Report

Created: 2024-12-17 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/h2-0.3.26/src/frame/ping.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::frame::{Error, Frame, Head, Kind, StreamId};
2
use bytes::BufMut;
3
4
const ACK_FLAG: u8 = 0x1;
5
6
pub type Payload = [u8; 8];
7
8
#[derive(Debug, Eq, PartialEq)]
9
pub struct Ping {
10
    ack: bool,
11
    payload: Payload,
12
}
13
14
// This was just 8 randomly generated bytes. We use something besides just
15
// zeroes to distinguish this specific PING from any other.
16
const SHUTDOWN_PAYLOAD: Payload = [0x0b, 0x7b, 0xa2, 0xf0, 0x8b, 0x9b, 0xfe, 0x54];
17
const USER_PAYLOAD: Payload = [0x3b, 0x7c, 0xdb, 0x7a, 0x0b, 0x87, 0x16, 0xb4];
18
19
impl Ping {
20
    #[cfg(feature = "unstable")]
21
    pub const SHUTDOWN: Payload = SHUTDOWN_PAYLOAD;
22
23
    #[cfg(not(feature = "unstable"))]
24
    pub(crate) const SHUTDOWN: Payload = SHUTDOWN_PAYLOAD;
25
26
    #[cfg(feature = "unstable")]
27
    pub const USER: Payload = USER_PAYLOAD;
28
29
    #[cfg(not(feature = "unstable"))]
30
    pub(crate) const USER: Payload = USER_PAYLOAD;
31
32
0
    pub fn new(payload: Payload) -> Ping {
33
0
        Ping {
34
0
            ack: false,
35
0
            payload,
36
0
        }
37
0
    }
Unexecuted instantiation: <h2::frame::ping::Ping>::new
Unexecuted instantiation: <h2::frame::ping::Ping>::new
Unexecuted instantiation: <h2::frame::ping::Ping>::new
38
39
0
    pub fn pong(payload: Payload) -> Ping {
40
0
        Ping { ack: true, payload }
41
0
    }
Unexecuted instantiation: <h2::frame::ping::Ping>::pong
Unexecuted instantiation: <h2::frame::ping::Ping>::pong
Unexecuted instantiation: <h2::frame::ping::Ping>::pong
42
43
0
    pub fn is_ack(&self) -> bool {
44
0
        self.ack
45
0
    }
Unexecuted instantiation: <h2::frame::ping::Ping>::is_ack
Unexecuted instantiation: <h2::frame::ping::Ping>::is_ack
Unexecuted instantiation: <h2::frame::ping::Ping>::is_ack
46
47
0
    pub fn payload(&self) -> &Payload {
48
0
        &self.payload
49
0
    }
Unexecuted instantiation: <h2::frame::ping::Ping>::payload
Unexecuted instantiation: <h2::frame::ping::Ping>::payload
Unexecuted instantiation: <h2::frame::ping::Ping>::payload
50
51
0
    pub fn into_payload(self) -> Payload {
52
0
        self.payload
53
0
    }
Unexecuted instantiation: <h2::frame::ping::Ping>::into_payload
Unexecuted instantiation: <h2::frame::ping::Ping>::into_payload
Unexecuted instantiation: <h2::frame::ping::Ping>::into_payload
54
55
    /// Builds a `Ping` frame from a raw frame.
56
0
    pub fn load(head: Head, bytes: &[u8]) -> Result<Ping, Error> {
57
0
        debug_assert_eq!(head.kind(), crate::frame::Kind::Ping);
58
59
        // PING frames are not associated with any individual stream. If a PING
60
        // frame is received with a stream identifier field value other than
61
        // 0x0, the recipient MUST respond with a connection error
62
        // (Section 5.4.1) of type PROTOCOL_ERROR.
63
0
        if !head.stream_id().is_zero() {
64
0
            return Err(Error::InvalidStreamId);
65
0
        }
66
0
67
0
        // In addition to the frame header, PING frames MUST contain 8 octets of opaque
68
0
        // data in the payload.
69
0
        if bytes.len() != 8 {
70
0
            return Err(Error::BadFrameSize);
71
0
        }
72
0
73
0
        let mut payload = [0; 8];
74
0
        payload.copy_from_slice(bytes);
75
0
76
0
        // The PING frame defines the following flags:
77
0
        //
78
0
        // ACK (0x1): When set, bit 0 indicates that this PING frame is a PING
79
0
        //    response. An endpoint MUST set this flag in PING responses. An
80
0
        //    endpoint MUST NOT respond to PING frames containing this flag.
81
0
        let ack = head.flag() & ACK_FLAG != 0;
82
0
83
0
        Ok(Ping { ack, payload })
84
0
    }
Unexecuted instantiation: <h2::frame::ping::Ping>::load
Unexecuted instantiation: <h2::frame::ping::Ping>::load
Unexecuted instantiation: <h2::frame::ping::Ping>::load
85
86
0
    pub fn encode<B: BufMut>(&self, dst: &mut B) {
87
0
        let sz = self.payload.len();
88
0
        tracing::trace!("encoding PING; ack={} len={}", self.ack, sz);
89
90
0
        let flags = if self.ack { ACK_FLAG } else { 0 };
91
0
        let head = Head::new(Kind::Ping, flags, StreamId::zero());
92
0
93
0
        head.encode(sz, dst);
94
0
        dst.put_slice(&self.payload);
95
0
    }
Unexecuted instantiation: <h2::frame::ping::Ping>::encode::<_>
Unexecuted instantiation: <h2::frame::ping::Ping>::encode::<bytes::bytes_mut::BytesMut>
Unexecuted instantiation: <h2::frame::ping::Ping>::encode::<_>
Unexecuted instantiation: <h2::frame::ping::Ping>::encode::<_>
96
}
97
98
impl<T> From<Ping> for Frame<T> {
99
0
    fn from(src: Ping) -> Frame<T> {
100
0
        Frame::Ping(src)
101
0
    }
Unexecuted instantiation: <h2::frame::Frame as core::convert::From<h2::frame::ping::Ping>>::from
Unexecuted instantiation: <h2::frame::Frame<h2::proto::streams::prioritize::Prioritized<hyper::proto::h2::SendBuf<linkerd_http_box::body::Data>>> as core::convert::From<h2::frame::ping::Ping>>::from
Unexecuted instantiation: <h2::frame::Frame<h2::proto::streams::prioritize::Prioritized<hyper::proto::h2::SendBuf<bytes::bytes::Bytes>>> as core::convert::From<h2::frame::ping::Ping>>::from
Unexecuted instantiation: <h2::frame::Frame as core::convert::From<h2::frame::ping::Ping>>::from
Unexecuted instantiation: <h2::frame::Frame as core::convert::From<h2::frame::ping::Ping>>::from
102
}