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