libp2p_core/connection/handler.rs
1// Copyright 2018 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use crate::Multiaddr;
22use std::{task::Context, task::Poll};
23use super::{Connected, SubstreamEndpoint};
24
25/// The interface of a connection handler.
26///
27/// Each handler is responsible for a single connection.
28pub trait ConnectionHandler {
29 /// The inbound type of events used to notify the handler through the `Network`.
30 ///
31 /// See also [`EstablishedConnection::notify_handler`](super::EstablishedConnection::notify_handler)
32 /// and [`ConnectionHandler::inject_event`].
33 type InEvent;
34 /// The outbound type of events that the handler emits to the `Network`
35 /// through [`ConnectionHandler::poll`].
36 ///
37 /// See also [`NetworkEvent::ConnectionEvent`](crate::network::NetworkEvent::ConnectionEvent).
38 type OutEvent;
39 /// The type of errors that the handler can produce when polled by the `Network`.
40 type Error;
41 /// The type of the substream containing the data.
42 type Substream;
43 /// Information about a substream. Can be sent to the handler through a `SubstreamEndpoint`,
44 /// and will be passed back in `inject_substream` or `inject_outbound_closed`.
45 type OutboundOpenInfo;
46
47 /// Sends a new substream to the handler.
48 ///
49 /// The handler is responsible for upgrading the substream to whatever protocol it wants.
50 ///
51 /// # Panic
52 ///
53 /// Implementations are allowed to panic in the case of dialing if the `user_data` in
54 /// `endpoint` doesn't correspond to what was returned earlier when polling, or is used
55 /// multiple times.
56 fn inject_substream(&mut self, substream: Self::Substream, endpoint: SubstreamEndpoint<Self::OutboundOpenInfo>);
57
58 /// Notifies the handler of an event.
59 fn inject_event(&mut self, event: Self::InEvent);
60
61 /// Notifies the handler of a change in the address of the remote.
62 fn inject_address_change(&mut self, new_address: &Multiaddr);
63
64 /// Polls the handler for events.
65 ///
66 /// Returning an error will close the connection to the remote.
67 fn poll(&mut self, cx: &mut Context<'_>)
68 -> Poll<Result<ConnectionHandlerEvent<Self::OutboundOpenInfo, Self::OutEvent>, Self::Error>>;
69}
70
71/// Prototype for a `ConnectionHandler`.
72pub trait IntoConnectionHandler {
73 /// The node handler.
74 type Handler: ConnectionHandler;
75
76 /// Builds the node handler.
77 ///
78 /// The implementation is given a `Connected` value that holds information about
79 /// the newly established connection for which a handler should be created.
80 fn into_handler(self, connected: &Connected) -> Self::Handler;
81}
82
83impl<T> IntoConnectionHandler for T
84where
85 T: ConnectionHandler
86{
87 type Handler = Self;
88
89 fn into_handler(self, _: &Connected) -> Self {
90 self
91 }
92}
93
94/// Event produced by a handler.
95#[derive(Debug, Copy, Clone, PartialEq, Eq)]
96pub enum ConnectionHandlerEvent<TOutboundOpenInfo, TCustom> {
97 /// Require a new outbound substream to be opened with the remote.
98 OutboundSubstreamRequest(TOutboundOpenInfo),
99
100 /// Other event.
101 Custom(TCustom),
102}
103
104/// Event produced by a handler.
105impl<TOutboundOpenInfo, TCustom> ConnectionHandlerEvent<TOutboundOpenInfo, TCustom> {
106 /// If this is `OutboundSubstreamRequest`, maps the content to something else.
107 pub fn map_outbound_open_info<F, I>(self, map: F) -> ConnectionHandlerEvent<I, TCustom>
108 where F: FnOnce(TOutboundOpenInfo) -> I
109 {
110 match self {
111 ConnectionHandlerEvent::OutboundSubstreamRequest(val) => {
112 ConnectionHandlerEvent::OutboundSubstreamRequest(map(val))
113 },
114 ConnectionHandlerEvent::Custom(val) => ConnectionHandlerEvent::Custom(val),
115 }
116 }
117
118 /// If this is `Custom`, maps the content to something else.
119 pub fn map_custom<F, I>(self, map: F) -> ConnectionHandlerEvent<TOutboundOpenInfo, I>
120 where F: FnOnce(TCustom) -> I
121 {
122 match self {
123 ConnectionHandlerEvent::OutboundSubstreamRequest(val) => {
124 ConnectionHandlerEvent::OutboundSubstreamRequest(val)
125 },
126 ConnectionHandlerEvent::Custom(val) => ConnectionHandlerEvent::Custom(map(val)),
127 }
128 }
129}
130