Coverage Report

Created: 2025-07-11 06:53

/src/h2/src/proto/peer.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::error::Reason;
2
use crate::frame::{Pseudo, StreamId};
3
use crate::proto::{Error, Open};
4
5
use http::{HeaderMap, Request, Response};
6
7
use std::fmt;
8
9
/// Either a Client or a Server
10
pub(crate) trait Peer {
11
    /// Message type polled from the transport
12
    type Poll: fmt::Debug;
13
    const NAME: &'static str;
14
15
    fn r#dyn() -> Dyn;
16
17
    //fn is_server() -> bool;
18
19
    fn convert_poll_message(
20
        pseudo: Pseudo,
21
        fields: HeaderMap,
22
        stream_id: StreamId,
23
    ) -> Result<Self::Poll, Error>;
24
25
    /*
26
    fn is_local_init(id: StreamId) -> bool {
27
        assert!(!id.is_zero());
28
        Self::is_server() == id.is_server_initiated()
29
    }
30
    */
31
}
32
33
/// A dynamic representation of `Peer`.
34
///
35
/// This is used internally to avoid incurring a generic on all internal types.
36
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
37
pub(crate) enum Dyn {
38
    Client,
39
    Server,
40
}
41
42
#[derive(Debug)]
43
pub enum PollMessage {
44
    Client(Response<()>),
45
    Server(Request<()>),
46
}
47
48
// ===== impl Dyn =====
49
50
impl Dyn {
51
1.23M
    pub fn is_server(&self) -> bool {
52
1.23M
        *self == Dyn::Server
53
1.23M
    }
54
55
717k
    pub fn is_local_init(&self, id: StreamId) -> bool {
56
717k
        assert!(!id.is_zero());
57
717k
        self.is_server() == id.is_server_initiated()
58
717k
    }
59
60
1.23k
    pub fn convert_poll_message(
61
1.23k
        &self,
62
1.23k
        pseudo: Pseudo,
63
1.23k
        fields: HeaderMap,
64
1.23k
        stream_id: StreamId,
65
1.23k
    ) -> Result<PollMessage, Error> {
66
1.23k
        if self.is_server() {
67
0
            crate::server::Peer::convert_poll_message(pseudo, fields, stream_id)
68
0
                .map(PollMessage::Server)
69
        } else {
70
1.23k
            crate::client::Peer::convert_poll_message(pseudo, fields, stream_id)
71
1.23k
                .map(PollMessage::Client)
72
        }
73
1.23k
    }
74
75
    /// Returns true if the remote peer can initiate a stream with the given ID.
76
1.36k
    pub fn ensure_can_open(&self, id: StreamId, mode: Open) -> Result<(), Error> {
77
1.36k
        if self.is_server() {
78
            // Ensure that the ID is a valid client initiated ID
79
0
            if mode.is_push_promise() || !id.is_client_initiated() {
80
0
                proto_err!(conn: "cannot open stream {:?} - not client initiated", id);
81
0
                return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
82
0
            }
83
0
84
0
            Ok(())
85
        } else {
86
            // Ensure that the ID is a valid server initiated ID
87
1.36k
            if !mode.is_push_promise() || !id.is_server_initiated() {
88
235
                proto_err!(conn: "cannot open stream {:?} - not server initiated", id);
89
235
                return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
90
1.12k
            }
91
1.12k
92
1.12k
            Ok(())
93
        }
94
1.36k
    }
95
}