libp2prs_core/multistream/
mod.rs

1// Copyright 2020 Netwarps 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
21//! # Multistream-select Protocol Negotiation
22//!
23//! This crate implements the `multistream-select` protocol, which is the protocol
24//! used by libp2p to negotiate which application-layer protocol to use with the
25//! remote on a connection or substream.
26//!
27//! > **Note**: This crate is used primarily by core components of *libp2p* and it
28//! > is usually not used directly on its own.
29//!
30//! ## Roles
31//!
32//! Two peers using the multistream-select negotiation protocol on an I/O stream
33//! are distinguished by their role as a _dialer_ (or _initiator_) or as a _listener_
34//! (or _responder_). Thereby the dialer plays the active part, driving the protocol,
35//! whereas the listener reacts to the messages received.
36//!
37//! The dialer has two options: it can either pick a protocol from the complete list
38//! of protocols that the listener supports, or it can directly suggest a protocol.
39//! Either way, a selected protocol is sent to the listener who can either accept (by
40//! echoing the same protocol) or reject (by responding with a message stating
41//! "not available"). If a suggested protocol is not available, the dialer may
42//! suggest another protocol. This process continues until a protocol is agreed upon,
43//! yielding a [`Negotiated`](self::Negotiated) stream, or the dialer has run out of
44//! alternatives.
45//!
46//! See [`dialer_select_proto`](self::dialer_select_proto) and
47//! [`listener_select_proto`](self::listener_select_proto).
48//!
49//! ## [`Negotiated`](self::Negotiated)
50//!
51//! When a dialer or listener participating in a negotiation settles
52//! on a protocol to use, the [`DialerSelectFuture`] respectively
53//! [`ListenerSelectFuture`] yields a [`Negotiated`](self::Negotiated)
54//! I/O stream.
55//!
56//! Notably, when a `DialerSelectFuture` resolves to a `Negotiated`, it may not yet
57//! have written the last negotiation message to the underlying I/O stream and may
58//! still be expecting confirmation for that protocol, despite having settled on
59//! a protocol to use.
60//!
61//! Similarly, when a `ListenerSelectFuture` resolves to a `Negotiated`, it may not
62//! yet have sent the last negotiation message despite having settled on a protocol
63//! proposed by the dialer that it supports.
64//!
65//! This behaviour allows both the dialer and the listener to send data
66//! relating to the negotiated protocol together with the last negotiation
67//! message(s), which, in the case of the dialer only supporting a single
68//! protocol, results in 0-RTT negotiation. Note, however, that a dialer
69//! that performs multiple 0-RTT negotiations in sequence for different
70//! protocols layered on top of each other may trigger undesirable behaviour
71//! for a listener not supporting one of the intermediate protocols.
72//! See [`dialer_select_proto`](self::dialer_select_proto).
73
74// mod dialer_select;
75mod length_delimited;
76// mod listener_select;
77pub mod muxer;
78mod negotiator;
79mod protocol;
80mod tests;
81
82pub use self::negotiator::{NegotiationError, Negotiator};
83pub use self::protocol::{ProtocolError, Version};
84// pub use self::dialer_select::{dialer_select_proto, DialerSelectFuture};
85// pub use self::listener_select::{listener_select_proto, ListenerSelectFuture};
86
87#[cfg(test)]
88pub(self) use tests::Memory;