|
| 1 | +--- |
| 2 | +title: "Early Multiplexer Negotiation" |
| 3 | +description: "Early stream multiplexer negotiation is an optimization in libp2p where peers can negotiate which multiplexer to use during the security protocol handshake, saving one round trip." |
| 4 | +weight: 162 |
| 5 | +--- |
| 6 | + |
| 7 | +## Vanilla stream multiplexer selection process |
| 8 | + |
| 9 | +One of libp2p's main guarantees is that no data sent over the wire is unencrypted. |
| 10 | +This means that transport protocols, like TCP or WebSocket, that don't support encryption |
| 11 | +by default must complete a cryptographic handshake. This process of adding the secure channel |
| 12 | +on top of the raw transport is called upgrading the connections and happens via the |
| 13 | +[multistream-select protocol](https://github.com/multiformats/multistream-select). |
| 14 | + |
| 15 | +In the unoptimized libp2p connection upgrade process, the security or encryption is negotiated |
| 16 | +first. After that is agreed upon, the stream multiplexer is negotiated. Again this only happens |
| 17 | +for transports that don't have native stream multiplexing. |
| 18 | + |
| 19 | +A standard connection upgrade process that negotiates the secure channel first and the multiplexer |
| 20 | +second |
| 21 | +[is shown in a diagram here](https://github.com/libp2p/specs/tree/master/connections#upgrading-connections). |
| 22 | + |
| 23 | +First, the security protocol is negotiated, then this protocol is used to perform a cryptographic |
| 24 | +handshake. libp2p currently supports [Noise](../secure-comm/noise) and [TLS 1.3](../secure-comm/tls). |
| 25 | +Once the cryptographic handshake completes, multistream-select runs again on top of |
| 26 | +the secured connection to negotiate a steam multiplexer, like [yamux](yamux) or [mplex](mplex). |
| 27 | + |
| 28 | +<!-- ADD DIAGRAM --> |
| 29 | + |
| 30 | +## Early muxer negotiation |
| 31 | + |
| 32 | +The libp2p project eliminates an unnecessary round trip in the standard negotiation protocol |
| 33 | +for selecting a stream multiplexer. This is achieved by combining the steps of agreeing on a |
| 34 | +secure channel and multiplexer. This is called "early" or "inlined" muxer negotiation. |
| 35 | + |
| 36 | +Early muxer negotiation is a feature in libp2p that allows for the simultaneous selection of a |
| 37 | +stream multiplexer during the cryptographic handshake of the TLS and Noise security protocols. |
| 38 | +This is achieved by sharing a list of supported muxer protocols as a part of the handshake payload. |
| 39 | + |
| 40 | +For example, if a libp2p node supports mplex and yamux, it will advertise both in the list. |
| 41 | +This **eliminates an extra round trip**, improving TTFB (time to first byte) in the libp2p handshake. |
| 42 | +Currently, this feature is only supported in go-libp2p and for TCP and WebSocket transports that do |
| 43 | +not have native encryption or multiplexing. |
| 44 | + |
| 45 | +<!-- ADD DIAGRAM --> |
| 46 | + |
| 47 | +### ALPN extension in TLS |
| 48 | + |
| 49 | +The [Application-Layer Protocol Negotiation (ALPN) extension](https://datatracker.ietf.org/doc/html/rfc7301) |
| 50 | +is a feature of TLS that allows for the negotiation of application-layer protocols during the TLS handshake. |
| 51 | +This allows the client and server to agree on the application-layer protocol for the rest of the TLS session. |
| 52 | +ALPN is typically used to negotiate the application-layer protocol for applications that use TLS, such as HTTP/2 |
| 53 | +or QUIC. libp2p uses ALPN to negotiate the stream muxer and saves a roundtrip when upgrading a raw connection. |
| 54 | + |
| 55 | +### Extension registry in Noise |
| 56 | + |
| 57 | +Since there's no commonly used extension mechanism in Noise, libp2p defines an extension registry. |
| 58 | +We then defined an extension to negotiate the stream multiplexer, that is conceptually the equivalent |
| 59 | +of the ALPN extension in TLS. |
| 60 | + |
| 61 | +> The extension registry is modeled after |
| 62 | +> [RFC 6066](https://www.rfc-editor.org/rfc/rfc6066) (for TLS) and |
| 63 | +> [RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000#section-19.21) |
| 64 | +> (for QUIC). |
| 65 | +
|
| 66 | +More information is available in the |
| 67 | +[Noise specification](https://github.com/libp2p/specs/blob/master/noise/README.md#libp2p-data-in-handshake-messages). |
| 68 | + |
| 69 | +{{< alert icon="💡" context="note" text="See the inclined muxer negotiation <a class=\"text-muted\" href=\"https://github.com/libp2p/specs/blob/master/connections/inlined-muxer-negotiation.md\">specification</a> for more details." />}} |
0 commit comments