1 use codec::RecvError; 2 use error::Reason; 3 use frame::{Pseudo, StreamId}; 4 use 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 dyn() -> Dyn15 fn 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, fields: HeaderMap, stream_id: StreamId 21 ) -> Result<Self::Poll, RecvError>; 22 is_local_init(id: StreamId) -> bool23 fn is_local_init(id: StreamId) -> bool { 24 assert!(!id.is_zero()); 25 Self::is_server() == id.is_server_initiated() 26 } 27 } 28 29 /// A dynamic representation of `Peer`. 30 /// 31 /// This is used internally to avoid incurring a generic on all internal types. 32 #[derive(Debug, Copy, Clone, Eq, PartialEq)] 33 pub(crate) enum Dyn { 34 Client, 35 Server, 36 } 37 38 #[derive(Debug)] 39 pub enum PollMessage { 40 Client(Response<()>), 41 Server(Request<()>), 42 } 43 44 // ===== impl Dyn ===== 45 46 impl Dyn { is_server(&self) -> bool47 pub fn is_server(&self) -> bool { 48 *self == Dyn::Server 49 } 50 is_local_init(&self, id: StreamId) -> bool51 pub fn is_local_init(&self, id: StreamId) -> bool { 52 assert!(!id.is_zero()); 53 self.is_server() == id.is_server_initiated() 54 } 55 convert_poll_message( &self, pseudo: Pseudo, fields: HeaderMap, stream_id: StreamId ) -> Result<PollMessage, RecvError>56 pub fn convert_poll_message( 57 &self, pseudo: Pseudo, fields: HeaderMap, stream_id: StreamId 58 ) -> Result<PollMessage, RecvError> { 59 if self.is_server() { 60 ::server::Peer::convert_poll_message(pseudo, fields, stream_id) 61 .map(PollMessage::Server) 62 } else { 63 ::client::Peer::convert_poll_message(pseudo, fields, stream_id) 64 .map(PollMessage::Client) 65 } 66 } 67 68 /// Returns true if the remote peer can initiate a stream with the given ID. ensure_can_open(&self, id: StreamId, mode: Open) -> Result<(), RecvError>69 pub fn ensure_can_open(&self, id: StreamId, mode: Open) -> Result<(), RecvError> { 70 if self.is_server() { 71 // Ensure that the ID is a valid client initiated ID 72 if mode.is_push_promise() || !id.is_client_initiated() { 73 proto_err!(conn: "cannot open stream {:?} - not client initiated", id); 74 return Err(RecvError::Connection(Reason::PROTOCOL_ERROR)); 75 } 76 77 Ok(()) 78 } else { 79 // Ensure that the ID is a valid server initiated ID 80 if !mode.is_push_promise() || !id.is_server_initiated() { 81 proto_err!(conn: "cannot open stream {:?} - not server initiated", id); 82 return Err(RecvError::Connection(Reason::PROTOCOL_ERROR)); 83 } 84 85 Ok(()) 86 } 87 } 88 } 89