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 
convert_poll_message( pseudo: Pseudo, fields: HeaderMap, stream_id: StreamId, ) -> Result<Self::Poll, Error>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 {
is_server(&self) -> bool51     pub fn is_server(&self) -> bool {
52         *self == Dyn::Server
53     }
54 
is_local_init(&self, id: StreamId) -> bool55     pub fn is_local_init(&self, id: StreamId) -> bool {
56         assert!(!id.is_zero());
57         self.is_server() == id.is_server_initiated()
58     }
59 
convert_poll_message( &self, pseudo: Pseudo, fields: HeaderMap, stream_id: StreamId, ) -> Result<PollMessage, Error>60     pub fn convert_poll_message(
61         &self,
62         pseudo: Pseudo,
63         fields: HeaderMap,
64         stream_id: StreamId,
65     ) -> Result<PollMessage, Error> {
66         if self.is_server() {
67             crate::server::Peer::convert_poll_message(pseudo, fields, stream_id)
68                 .map(PollMessage::Server)
69         } else {
70             crate::client::Peer::convert_poll_message(pseudo, fields, stream_id)
71                 .map(PollMessage::Client)
72         }
73     }
74 
75     /// Returns true if the remote peer can initiate a stream with the given ID.
ensure_can_open(&self, id: StreamId, mode: Open) -> Result<(), Error>76     pub fn ensure_can_open(&self, id: StreamId, mode: Open) -> Result<(), Error> {
77         if self.is_server() {
78             // Ensure that the ID is a valid client initiated ID
79             if mode.is_push_promise() || !id.is_client_initiated() {
80                 proto_err!(conn: "cannot open stream {:?} - not client initiated", id);
81                 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
82             }
83 
84             Ok(())
85         } else {
86             // Ensure that the ID is a valid server initiated ID
87             if !mode.is_push_promise() || !id.is_server_initiated() {
88                 proto_err!(conn: "cannot open stream {:?} - not server initiated", id);
89                 return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
90             }
91 
92             Ok(())
93         }
94     }
95 }
96