summaryrefslogtreecommitdiffstats
path: root/third_party/rust/h2/src/proto/peer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/h2/src/proto/peer.rs')
-rw-r--r--third_party/rust/h2/src/proto/peer.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/third_party/rust/h2/src/proto/peer.rs b/third_party/rust/h2/src/proto/peer.rs
new file mode 100644
index 0000000000..d62d9e24e0
--- /dev/null
+++ b/third_party/rust/h2/src/proto/peer.rs
@@ -0,0 +1,93 @@
+use crate::error::Reason;
+use crate::frame::{Pseudo, StreamId};
+use crate::proto::{Error, Open};
+
+use http::{HeaderMap, Request, Response};
+
+use std::fmt;
+
+/// Either a Client or a Server
+pub(crate) trait Peer {
+ /// Message type polled from the transport
+ type Poll: fmt::Debug;
+ const NAME: &'static str;
+
+ fn r#dyn() -> Dyn;
+
+ fn is_server() -> bool;
+
+ fn convert_poll_message(
+ pseudo: Pseudo,
+ fields: HeaderMap,
+ stream_id: StreamId,
+ ) -> Result<Self::Poll, Error>;
+
+ fn is_local_init(id: StreamId) -> bool {
+ assert!(!id.is_zero());
+ Self::is_server() == id.is_server_initiated()
+ }
+}
+
+/// A dynamic representation of `Peer`.
+///
+/// This is used internally to avoid incurring a generic on all internal types.
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+pub(crate) enum Dyn {
+ Client,
+ Server,
+}
+
+#[derive(Debug)]
+pub enum PollMessage {
+ Client(Response<()>),
+ Server(Request<()>),
+}
+
+// ===== impl Dyn =====
+
+impl Dyn {
+ pub fn is_server(&self) -> bool {
+ *self == Dyn::Server
+ }
+
+ pub fn is_local_init(&self, id: StreamId) -> bool {
+ assert!(!id.is_zero());
+ self.is_server() == id.is_server_initiated()
+ }
+
+ pub fn convert_poll_message(
+ &self,
+ pseudo: Pseudo,
+ fields: HeaderMap,
+ stream_id: StreamId,
+ ) -> Result<PollMessage, Error> {
+ if self.is_server() {
+ crate::server::Peer::convert_poll_message(pseudo, fields, stream_id)
+ .map(PollMessage::Server)
+ } else {
+ crate::client::Peer::convert_poll_message(pseudo, fields, stream_id)
+ .map(PollMessage::Client)
+ }
+ }
+
+ /// Returns true if the remote peer can initiate a stream with the given ID.
+ pub fn ensure_can_open(&self, id: StreamId, mode: Open) -> Result<(), Error> {
+ if self.is_server() {
+ // Ensure that the ID is a valid client initiated ID
+ if mode.is_push_promise() || !id.is_client_initiated() {
+ proto_err!(conn: "cannot open stream {:?} - not client initiated", id);
+ return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
+ }
+
+ Ok(())
+ } else {
+ // Ensure that the ID is a valid server initiated ID
+ if !mode.is_push_promise() || !id.is_server_initiated() {
+ proto_err!(conn: "cannot open stream {:?} - not server initiated", id);
+ return Err(Error::library_go_away(Reason::PROTOCOL_ERROR));
+ }
+
+ Ok(())
+ }
+ }
+}