-
Notifications
You must be signed in to change notification settings - Fork 275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
multistream-select 1.0: simultaneous open protocol extension #196
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this! <3
This is indeed in line with what we discussed privately. I'm worried about introducing an extra, unavoidable round trip though.
rust-libp2p, and go-libp2p support optimistic, eager protocol selection.
IUC, sending the iamclient
protocol in the manner suggested here will add one more step in the connection bootstrapping flow, preceding encryption negotiation.
Two options come to mind:
- Make this an exceptional pathway. When multistream detects a collision, start this process to deduplicate the initiator role.
- Make this strategy opt-in, so that only speculative connections opened by hole punching will be affected by the extra round trip. This has the downside that we won't fix simultaneous open in the wild.
connections/simopen.md
Outdated
The protocol is simple to implement and is backwards compatible with | ||
vanilla multistream-select. In the common case of a single initiator, | ||
we can ensure that there there is no latency overhead by sending the | ||
`iamclient` message together with the multistream header. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC the latency is unavoidable if the deduplication is conducted in this way. We are adding one more exchange to the flow (in the optimistic scenario). Without this message, the piggybacked protocol would be the security handshake protocol proposal -- which actually makes forward progress in the state machine.
We discussed a simple solution with @Stebalien , to basically pipeline |
The second, more robust solution, is to use a prefix for the integer when both sides declare |
connections/simopen.md
Outdated
@@ -0,0 +1,72 @@ | |||
# Simultaneous Open for multistream-select |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This spec only applies to connection bootstrapping, whereas multistream-select is used in other contexts too (stream-level protocol negotiation). So I'd title this differently, e.g.:
# Connection bootstrapping: handling TCP simultaneous open in multistream-select.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can change the title. Go ahead and pick something you like!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, this works for UDP too!
@vyzo Yup, I think that pipelining sequence could work. I'll continue reviewing tomorrow; thanks! |
I pushed an update, which resolves the issues with pipelining. |
summoning @raulk @Stebalien for a second round of review. |
Co-Authored-By: Jacob Heun <jacobheun@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice draft!
connections/simopen.md
Outdated
phase, where one of the peers is selected to act as the initiator. In | ||
order to do so, they both generate a random 256-bit integer and send | ||
it as response to the `iamclient` directive, prefixed with the | ||
`select:` string. The peer with the highest integer is selected to act |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how should we encode this int? b64?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, this needs to be encoded! Let's do base64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated to mandate base64.
Co-Authored-By: bigs <cole@protocol.ai>
connections/simopen.md
Outdated
phase, where one of the peers is selected to act as the initiator. In | ||
order to do so, they both generate a random 256-bit integer and send | ||
it as response to the `iamclient` directive, prefixed with the | ||
`select:` string. The integer is in big-endian format, encoded in base64. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vyzo Why do we need to encode to base64 here ? Why not simply append the 256 bits ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd assume it's because multistream 1 is a text-based, human-readable protocol (with all the pros and cons that come with it).
That said, base64 seems like a suboptimal choice here. I propose switching to hexadecimal encoding. Encoding math.MaxUint64
(18446744073709551615) is 0xFFFFFFFFFFFFFFFF
in hex and MTg0NDY3NDQwNzM3MDk1NTE2MTU=
in base64.
Also, 256 bits seem excessive here. I think we can live with a collision probability of 2^-64, which would allow implementations to use a regular uint64
instead of math/big.Int
. We might even want to limit this to 52 (?) bits to make things easier in JavaScript (but I'm no expert on that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Encoding math.MaxUint64 (18446744073709551615) is 0xFFFFFFFFFFFFFFFF in hex and MTg0NDY3NDQwNzM3MDk1NTE2MTU= in base64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it? I used https://www.base64encode.net/, and that gives the same result (except for the last character?) as echo 18446744073709551615 | base64
. But maybe that's decoding the string "18446744073709551615" and not the number?
As /
is a separator we use in multistream, so base64 encoding might get us into trouble, if we don't escape it, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I guess you're encoding the string.
It doesn't make sense that encoding something in base64 would give something longer than encoding that same thing in base16
I think that /
isn't a problem because of the select:
prefix. Otherwise I'd suggest base58.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not opposed to base58, but also not sure if it's easily accessible in all the languages we care about. In Go, we'd have to import a third-party library (it's not in the standard library).
Any thoughts on the length of this value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One question and one proposal:
- Do I understand correctly that we’ll end up with an additional round trip if the peer doesn’t support the
iamclient
protocol? - Why don't we coalesce the initiator selection phase, i.e. send
iamclient/<random int>
? This would allow the peers to immediately assign roles when a simultaneous open occurs, saving one roundtrip.
We will NOT end up with an extra roundtrip because the client sends a pipelined
I think this is extremely hacky. Multistream is supposed to be "yes"/"no" protocol. If we do this, we'd have to add special logic for the "iamclient" protocol where we say "hey multistream, read the integer after the / if you see the iamclient thing". |
@aarshkshah1992 @marten-seemann the go implementation has diverged from the spec; can you please update it to match what was implemented? |
@aarshkshah1992 @marten-seemann any updates here? Having an up-to-date spec would make it a lot easier to implement this extension in rust-libp2p. |
In order to be backwards compatible with vanilla multistream-select the simultaneous open extension disguises its identifier as a protocol ID. According to the protocol negotiation specification protocol IDs can use any string, though by convention they are prefixed with a '/'. > Each protocol supported by a peer is identified using a unique string called a protocol id. While any string can be used, the conventional format is a path-like structure containing a short name and a version number, separated by / characters. For example: /mplex/1.0.0 identifies version 1.0.0 of the mplex stream multiplexing protocol. multistream-select itself has a protocol id of /multistream/1.0.0. https://github.com/libp2p/specs/tree/master/connections#protocol-negotiation This commit replace the `iamclient` identifier with `/libp2p/simultaneous-connect` to comply with the convention.
connections/simopen: Prefix fake protocol ID with a '/'
From the multistream-select 1.0 simultaneous open protocol extension specification: > In order to support direct connections through NATs with hole punching, we need to account for simultaneous open. In such cases, there is no single initiator and responder, but instead both peers act as initiators. This breaks protocol negotiation in multistream-select, which assumes a single initator. > This draft proposes a simple extension to the multistream protocol negotiation in order to select a single initator when both peers are acting as such. See libp2p/specs#196 for details. This commit implements the above specification, available via `Version::V1SimOpen`.
From the multistream-select 1.0 simultaneous open protocol extension specification: > In order to support direct connections through NATs with hole punching, we need to account for simultaneous open. In such cases, there is no single initiator and responder, but instead both peers act as initiators. This breaks protocol negotiation in multistream-select, which assumes a single initator. > This draft proposes a simple extension to the multistream protocol negotiation in order to select a single initator when both peers are acting as such. See libp2p/specs#196 for details. This commit implements the above specification, available via `Version::V1SimOpen`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have implemented simultaneous open for rust-libp2p (libp2p/rust-libp2p#2066) with the help of this specification and the Golang implementation. I have treated the Golang implementation as a source of truth. According to basic smoke tests the Rust and Golang implementations are interoperable now. Below comments highlight the inconsistencies between the specification and the Golang implementation.
With the upcoming go-libp2p release (libp2p/go-libp2p#1090) this spec (+ the comments below) will be deployed in the wild.
That in mind, unless there are any objections, I will commit the change-suggestions below and try to get this specification merged.
Let me know what you think.
connections/simopen.md
Outdated
|
||
| Lifecycle Stage | Maturity | Status | Latest Revision | | ||
|-----------------|---------------|--------|-----------------| | ||
| 1A | Working Draft | Active | DRAFT | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 1A | Working Draft | Active | DRAFT | | |
| 1A | Working Draft | Active | r0, 2021-05-06 | |
connections/simopen.md
Outdated
If both peers believe they are the initiator, then they both send | ||
`/libp2p/simultaneous-connect`. If this is the case, they enter an initiator | ||
selection phase, where one of the peers is selected to act as the initiator. In | ||
order to do so, they both generate a random 256-bit integer and send it as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
order to do so, they both generate a random 256-bit integer and send it as | |
order to do so, they both generate a random 64-bit integer and send it as |
The Golang implementation is using a 64-bit integer:
myNonce := binary.LittleEndian.Uint64(randBytes)
connections/simopen.md
Outdated
selection phase, where one of the peers is selected to act as the initiator. In | ||
order to do so, they both generate a random 256-bit integer and send it as | ||
response to the `/libp2p/simultaneous-connect` directive, prefixed with the | ||
`select:` string. The integer is in big-endian format, encoded in base64. The |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`select:` string. The integer is in big-endian format, encoded in base64. The | |
`select:` string. The integer is send in its base-10 string representation. The |
The Golang implementation is sending the nonce in the base-10 string representation.
myselect := []byte(tieBreakerPrefix + strconv.FormatUint(myNonce, 10))
connections/simopen.md
Outdated
In the unlikely case where both peers selected the same integer, they | ||
generate a fresh one and enter another round of the protocol. If | ||
multiple rounds of the protocol result in the same integers, this is | ||
indicative of a bug and both peers should abort the connection. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the unlikely case where both peers selected the same integer, they | |
generate a fresh one and enter another round of the protocol. If | |
multiple rounds of the protocol result in the same integers, this is | |
indicative of a bug and both peers should abort the connection. | |
In the unlikely case where both peers selected the same integer, connection establishment fails. |
The Golang implementation does not retry. See multiformats/go-multistream#42 (comment).
connections/simopen.md
Outdated
@@ -0,0 +1,89 @@ | |||
# Simultaneous Open for bootstrapping connections in multistream-select |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Simultaneous Open for bootstrapping connections in multistream-select | |
# Connection bootstrapping: Handling simultaneous open in multistream-select. |
As per @raulk's comment in #196 (comment).
The Golang implementation is using a 64-bit integer: ``` Golang myNonce := binary.LittleEndian.Uint64(randBytes) ``` https://github.com/multiformats/go-multistream/blob/4e1d9a7e25b067b7527ca2af72ce9c06529ebfb7/client.go#L167
The Golang implementation is sending the nonce in the base-10 string representation. ```Golang myselect := []byte(tieBreakerPrefix + strconv.FormatUint(myNonce, 10)) ``` https://github.com/multiformats/go-multistream/blob/4e1d9a7e25b067b7527ca2af72ce9c06529ebfb7/client.go#L171
The Golang implementation does not retry. See multiformats/go-multistream#42 (comment).
As per Raúl's comment in #196 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the most recent commits the spec, the Golang implementation and the Rustlang implementation are now consistent (to the best of my knowledge).
Unless there are any objections I suggest to merge this pull request as-is sometime next week.
* protocols/relay: Implement circuit relay v2 protocol This commit adds an implementation for the circuit relay v2 protocol to be used as a relay server, i.e. it supports incoming HOP requests and outgoing STOP requests. Future commits will add support for clients, i.e. outgoing HOP requests and incoming STOP requests. The existing circuit relay v1 protocol implementation is moved to protocols/relay/src/v1. * misc/multistream-select: Ignore simultaneous open 'iamclient' * protocols/relay: Ensure connections of HOP connect are kept alive * protocols/relay: Improve documentation * misc/multistream-select: Implement simultaneous open extension From the multistream-select 1.0 simultaneous open protocol extension specification: > In order to support direct connections through NATs with hole punching, we need to account for simultaneous open. In such cases, there is no single initiator and responder, but instead both peers act as initiators. This breaks protocol negotiation in multistream-select, which assumes a single initator. > This draft proposes a simple extension to the multistream protocol negotiation in order to select a single initator when both peers are acting as such. See libp2p/specs#196 for details. This commit implements the above specification, available via `Version::V1SimOpen`. * protocols/relay: Implement v2 client logic * protocols/relay: Handle dial failure * protocols/relay: Reuse connection * protocols/relay: Rename Connection to RelayedConnection * protocols/relay: Update transport doc examples * protocols/relay: Pass relay addr to transport * protocols/relay: Implement inbound stop denial * protocols/relay: Renew reservations * protocols/relay: Handle invalid expiration in the past * protocols/relay: Handle in and outbound failure * protocols/relay: Implement client handler keep alive * protocols/relay: Handle handler listener closed channel * protocols/relay: Handle handler to listener failure * protocols/relay: Return all new listener addresses * protocols/dcutr: Implement Direct Connection Upgrade through Relay * protocols/dcutr: Carry observed addresses in Connect * protocols/dcutr: Reply to Syn * protocols/dcutr: Dial as initiator * core/: Integrate Simultaneous Open extension * protocols/relay/v2: Update to latest protobuf definition * protocols/dcutr/examples: Add client * Revert "misc/multistream-select: Ignore simultaneous open 'iamclient'" This reverts commit 125e3c3. * core/src/transport/upgrade: Make DialFuture aware of SimOpenRole * core/src/transport: Use Transport::and_then for Authenticated::apply * core/: Clean type structure * core/: Enforce upgrade version at compile time * misc/multistream-select: Document V1SimOpen * *: Rename V1SimOpen to V1SimultaneousOpen * misc/multistream-select: Document SimOpenRole * *: Rename SimOpenRole to Role * misc/multistream-select: Document reponder role process * misc/multistream-select: Bump version and add changelog entry * core/CHANGELOG: Add entry * core/src/upgrade: Assert Initiator when not using SimOpen * core/upgrade/apply: Document different versions * misc/multistream-select: Derive Eq for Role * *: Fix documentation links * misc/multistream-select: Fix doc link * src/lib: Call upgrade without Version * protocols/relay/v2: Report back to transport * protocols/relay/v2: Disconnect when stop protocol not supported * protocols/relay/v2: Document max_duration not exceed u32::MAX * protocols/relay/v2: Don't append p2p-circuit as relay * protocols/relay/v2: Implement rate limiter * protocols/relay/v2: Document caveats on rate limiter with high volume * protocols/relay: Prevent possible false positive in quickcheck * protocols/relay: Reword Prost error message * protocols/relay: Allow users to specify generic rate limiters * protocols/relay: Move rate limiting logic into module * protocols/relay: Prevent reservation and connection over relayed conn * protocols/relay: Add circuit src rate limiting * protocols/relay/v2: Simplify example * protocols/relay: Add myself to authors * protocols/relay: Use thiserror * protocols/relay/v2: Set rate limits * protocols/relay: Use wasm_timer::Instant * protocols/relay/v2: Apply clippy suggestions * protocols/relay: Fix intra doc link * protocols/dcutr/tests: Fix connect test * protocols/dcutr: Run cargo fix * protocols/dcutr: Attempt direct connection upgrade as listener only * protocols/dcutr: Emit event when attempting direct connection upgrade * protocols/dcutr: Emit event when remote initiates direct connection up * protocols/relay: Fix clippy warnings * protocols/dcutr: Extend with TODOs * swarm/src/behaviour: Update DialAddress doc comment With 45f07bf `Network::dial` accepts a `Multiaddr` with a `PeerId`. With that in mind the doc comment on `NetworkBehaviourAction::DialAddress` is outdated. * swarm/src/protocols_handler: Add EitherHandler Add implementation of a ProtocolsHandler that represents either of two ProtocolsHandler implementations. * protocols/dcutr: Deny upgrades on non-relayed connections * protocols/dcutr: Properly expect size of data container * protocols/dcutr: Enforce maximum message size on incoming msgs * *: Format with rustfmt * protocols/dcutr: Tell handler what it is going to be used for * misc/metrics: Add basic instrumentation for libp2p-relay * protocols/dcutr: Report successful connection upgrade * protocols/dcutr/examples: Use structopts * protocols/dcutr: Do not panic on connection closing * protocols/relay: Return NetworkBehaviourAction::NotifyHandler right away * protocols/dcutr/src/behaviour: Do not send relayed addresses * protocols/dcutr/examples: Log on info level * protocols/relay: Run rust fmt * protocols/relay/src/v2/relay: Accept mutable config * misc/multistream-select/src/protocol.rs: Fix typo * protocols/dcutr/build: Run rust fmt * protocols/dcutr/src/behaviour: Remove outdated comment * misc/multistream-select: Supress needless collect warning * protocols/dcutr/: Do not attempt upgrade if direct connection exists * protocols/dcutr/src/handler: Remove DirectConnection Prototype variant * protocols/dcutr: Deny incoming substreams as dialer * protocols/dcutr/src/handler: Split into relayed and direct * protocols/dcutr: Don't abbreviate negotiated with neg * protocols/dcutr/src/protocol: Use correct protocol name * protocols/dcutr/src/message.proto: Make type field required * protocols/dcutr/src/protocol: Use thiserror * protocols/dcutr/src/handler/relayed: Refine keep alive handling * protocols/dcutr/src/protocol: Split into outbound and inbound * protocols/dcutr/src/handler/relayed: Handle stream upgrade errors Co-authored-by: Max Inden <mail@max-inden.de>
* protocols/relay: Implement circuit relay v2 protocol This commit adds an implementation for the circuit relay v2 protocol to be used as a relay server, i.e. it supports incoming HOP requests and outgoing STOP requests. Future commits will add support for clients, i.e. outgoing HOP requests and incoming STOP requests. The existing circuit relay v1 protocol implementation is moved to protocols/relay/src/v1. * misc/multistream-select: Ignore simultaneous open 'iamclient' * protocols/relay: Ensure connections of HOP connect are kept alive * protocols/relay: Improve documentation * misc/multistream-select: Implement simultaneous open extension From the multistream-select 1.0 simultaneous open protocol extension specification: > In order to support direct connections through NATs with hole punching, we need to account for simultaneous open. In such cases, there is no single initiator and responder, but instead both peers act as initiators. This breaks protocol negotiation in multistream-select, which assumes a single initator. > This draft proposes a simple extension to the multistream protocol negotiation in order to select a single initator when both peers are acting as such. See libp2p/specs#196 for details. This commit implements the above specification, available via `Version::V1SimOpen`. * protocols/relay: Implement v2 client logic * protocols/relay: Handle dial failure * protocols/relay: Reuse connection * protocols/relay: Rename Connection to RelayedConnection * protocols/relay: Update transport doc examples * protocols/relay: Pass relay addr to transport * protocols/relay: Implement inbound stop denial * protocols/relay: Renew reservations * protocols/relay: Handle invalid expiration in the past * protocols/relay: Handle in and outbound failure * protocols/relay: Implement client handler keep alive * protocols/relay: Handle handler listener closed channel * protocols/relay: Handle handler to listener failure * protocols/relay: Return all new listener addresses * protocols/dcutr: Implement Direct Connection Upgrade through Relay * protocols/dcutr: Carry observed addresses in Connect * protocols/dcutr: Reply to Syn * protocols/dcutr: Dial as initiator * core/: Integrate Simultaneous Open extension * protocols/relay/v2: Update to latest protobuf definition * protocols/dcutr/examples: Add client * Revert "misc/multistream-select: Ignore simultaneous open 'iamclient'" This reverts commit 125e3c3. * core/src/transport/upgrade: Make DialFuture aware of SimOpenRole * core/src/transport: Use Transport::and_then for Authenticated::apply * core/: Clean type structure * core/: Enforce upgrade version at compile time * misc/multistream-select: Document V1SimOpen * *: Rename V1SimOpen to V1SimultaneousOpen * misc/multistream-select: Document SimOpenRole * *: Rename SimOpenRole to Role * misc/multistream-select: Document reponder role process * misc/multistream-select: Bump version and add changelog entry * core/CHANGELOG: Add entry * core/src/upgrade: Assert Initiator when not using SimOpen * core/upgrade/apply: Document different versions * misc/multistream-select: Derive Eq for Role * *: Fix documentation links * misc/multistream-select: Fix doc link * src/lib: Call upgrade without Version * protocols/relay/v2: Report back to transport * protocols/relay/v2: Disconnect when stop protocol not supported * protocols/relay/v2: Document max_duration not exceed u32::MAX * protocols/relay/v2: Don't append p2p-circuit as relay * protocols/relay/v2: Implement rate limiter * protocols/relay/v2: Document caveats on rate limiter with high volume * protocols/relay: Prevent possible false positive in quickcheck * protocols/relay: Reword Prost error message * protocols/relay: Allow users to specify generic rate limiters * protocols/relay: Move rate limiting logic into module * protocols/relay: Prevent reservation and connection over relayed conn * protocols/relay: Add circuit src rate limiting * protocols/relay/v2: Simplify example * protocols/relay: Add myself to authors * protocols/relay: Use thiserror * protocols/relay/v2: Set rate limits * protocols/relay: Use wasm_timer::Instant * protocols/relay/v2: Apply clippy suggestions * protocols/relay: Fix intra doc link * protocols/dcutr/tests: Fix connect test * protocols/dcutr: Run cargo fix * protocols/dcutr: Attempt direct connection upgrade as listener only * protocols/dcutr: Emit event when attempting direct connection upgrade * protocols/dcutr: Emit event when remote initiates direct connection up * protocols/relay: Fix clippy warnings * protocols/dcutr: Extend with TODOs * swarm/src/behaviour: Update DialAddress doc comment With 45f07bf `Network::dial` accepts a `Multiaddr` with a `PeerId`. With that in mind the doc comment on `NetworkBehaviourAction::DialAddress` is outdated. * swarm/src/protocols_handler: Add EitherHandler Add implementation of a ProtocolsHandler that represents either of two ProtocolsHandler implementations. * protocols/dcutr: Deny upgrades on non-relayed connections * protocols/dcutr: Properly expect size of data container * protocols/dcutr: Enforce maximum message size on incoming msgs * *: Format with rustfmt * protocols/dcutr: Tell handler what it is going to be used for * misc/metrics: Add basic instrumentation for libp2p-relay * protocols/dcutr: Report successful connection upgrade * protocols/dcutr/examples: Use structopts * protocols/dcutr: Do not panic on connection closing * protocols/relay: Return NetworkBehaviourAction::NotifyHandler right away * protocols/dcutr/src/behaviour: Do not send relayed addresses * protocols/dcutr/examples: Log on info level * protocols/relay: Run rust fmt * protocols/relay/src/v2/relay: Accept mutable config * misc/multistream-select/src/protocol.rs: Fix typo * protocols/dcutr/build: Run rust fmt * protocols/dcutr/src/behaviour: Remove outdated comment * misc/multistream-select: Supress needless collect warning * protocols/dcutr/: Do not attempt upgrade if direct connection exists * protocols/dcutr/src/handler: Remove DirectConnection Prototype variant * protocols/dcutr: Deny incoming substreams as dialer * protocols/dcutr/src/handler: Split into relayed and direct * protocols/dcutr: Don't abbreviate negotiated with neg * protocols/dcutr/src/protocol: Use correct protocol name * protocols/dcutr/src/message.proto: Make type field required * protocols/dcutr/src/protocol: Use thiserror * protocols/dcutr/src/handler/relayed: Refine keep alive handling * protocols/dcutr/src/protocol: Split into outbound and inbound * protocols/dcutr/src/handler/relayed: Handle stream upgrade errors Co-authored-by: Max Inden <mail@max-inden.de>
* DCUtR (#4) * protocols/relay: Implement circuit relay v2 protocol This commit adds an implementation for the circuit relay v2 protocol to be used as a relay server, i.e. it supports incoming HOP requests and outgoing STOP requests. Future commits will add support for clients, i.e. outgoing HOP requests and incoming STOP requests. The existing circuit relay v1 protocol implementation is moved to protocols/relay/src/v1. * misc/multistream-select: Ignore simultaneous open 'iamclient' * protocols/relay: Ensure connections of HOP connect are kept alive * protocols/relay: Improve documentation * misc/multistream-select: Implement simultaneous open extension From the multistream-select 1.0 simultaneous open protocol extension specification: > In order to support direct connections through NATs with hole punching, we need to account for simultaneous open. In such cases, there is no single initiator and responder, but instead both peers act as initiators. This breaks protocol negotiation in multistream-select, which assumes a single initator. > This draft proposes a simple extension to the multistream protocol negotiation in order to select a single initator when both peers are acting as such. See libp2p/specs#196 for details. This commit implements the above specification, available via `Version::V1SimOpen`. * protocols/relay: Implement v2 client logic * protocols/relay: Handle dial failure * protocols/relay: Reuse connection * protocols/relay: Rename Connection to RelayedConnection * protocols/relay: Update transport doc examples * protocols/relay: Pass relay addr to transport * protocols/relay: Implement inbound stop denial * protocols/relay: Renew reservations * protocols/relay: Handle invalid expiration in the past * protocols/relay: Handle in and outbound failure * protocols/relay: Implement client handler keep alive * protocols/relay: Handle handler listener closed channel * protocols/relay: Handle handler to listener failure * protocols/relay: Return all new listener addresses * protocols/dcutr: Implement Direct Connection Upgrade through Relay * protocols/dcutr: Carry observed addresses in Connect * protocols/dcutr: Reply to Syn * protocols/dcutr: Dial as initiator * core/: Integrate Simultaneous Open extension * protocols/relay/v2: Update to latest protobuf definition * protocols/dcutr/examples: Add client * Revert "misc/multistream-select: Ignore simultaneous open 'iamclient'" This reverts commit 125e3c3. * core/src/transport/upgrade: Make DialFuture aware of SimOpenRole * core/src/transport: Use Transport::and_then for Authenticated::apply * core/: Clean type structure * core/: Enforce upgrade version at compile time * misc/multistream-select: Document V1SimOpen * *: Rename V1SimOpen to V1SimultaneousOpen * misc/multistream-select: Document SimOpenRole * *: Rename SimOpenRole to Role * misc/multistream-select: Document reponder role process * misc/multistream-select: Bump version and add changelog entry * core/CHANGELOG: Add entry * core/src/upgrade: Assert Initiator when not using SimOpen * core/upgrade/apply: Document different versions * misc/multistream-select: Derive Eq for Role * *: Fix documentation links * misc/multistream-select: Fix doc link * src/lib: Call upgrade without Version * protocols/relay/v2: Report back to transport * protocols/relay/v2: Disconnect when stop protocol not supported * protocols/relay/v2: Document max_duration not exceed u32::MAX * protocols/relay/v2: Don't append p2p-circuit as relay * protocols/relay/v2: Implement rate limiter * protocols/relay/v2: Document caveats on rate limiter with high volume * protocols/relay: Prevent possible false positive in quickcheck * protocols/relay: Reword Prost error message * protocols/relay: Allow users to specify generic rate limiters * protocols/relay: Move rate limiting logic into module * protocols/relay: Prevent reservation and connection over relayed conn * protocols/relay: Add circuit src rate limiting * protocols/relay/v2: Simplify example * protocols/relay: Add myself to authors * protocols/relay: Use thiserror * protocols/relay/v2: Set rate limits * protocols/relay: Use wasm_timer::Instant * protocols/relay/v2: Apply clippy suggestions * protocols/relay: Fix intra doc link * protocols/dcutr/tests: Fix connect test * protocols/dcutr: Run cargo fix * protocols/dcutr: Attempt direct connection upgrade as listener only * protocols/dcutr: Emit event when attempting direct connection upgrade * protocols/dcutr: Emit event when remote initiates direct connection up * protocols/relay: Fix clippy warnings * protocols/dcutr: Extend with TODOs * swarm/src/behaviour: Update DialAddress doc comment With 45f07bf `Network::dial` accepts a `Multiaddr` with a `PeerId`. With that in mind the doc comment on `NetworkBehaviourAction::DialAddress` is outdated. * swarm/src/protocols_handler: Add EitherHandler Add implementation of a ProtocolsHandler that represents either of two ProtocolsHandler implementations. * protocols/dcutr: Deny upgrades on non-relayed connections * protocols/dcutr: Properly expect size of data container * protocols/dcutr: Enforce maximum message size on incoming msgs * *: Format with rustfmt * protocols/dcutr: Tell handler what it is going to be used for * misc/metrics: Add basic instrumentation for libp2p-relay * protocols/dcutr: Report successful connection upgrade * protocols/dcutr/examples: Use structopts * protocols/dcutr: Do not panic on connection closing * protocols/relay: Return NetworkBehaviourAction::NotifyHandler right away * protocols/dcutr/src/behaviour: Do not send relayed addresses * protocols/dcutr/examples: Log on info level * protocols/relay: Run rust fmt * protocols/relay/src/v2/relay: Accept mutable config * misc/multistream-select/src/protocol.rs: Fix typo * protocols/dcutr/build: Run rust fmt * protocols/dcutr/src/behaviour: Remove outdated comment * misc/multistream-select: Supress needless collect warning * protocols/dcutr/: Do not attempt upgrade if direct connection exists * protocols/dcutr/src/handler: Remove DirectConnection Prototype variant * protocols/dcutr: Deny incoming substreams as dialer * protocols/dcutr/src/handler: Split into relayed and direct * protocols/dcutr: Don't abbreviate negotiated with neg * protocols/dcutr/src/protocol: Use correct protocol name * protocols/dcutr/src/message.proto: Make type field required * protocols/dcutr/src/protocol: Use thiserror * protocols/dcutr/src/handler/relayed: Refine keep alive handling * protocols/dcutr/src/protocol: Split into outbound and inbound * protocols/dcutr/src/handler/relayed: Handle stream upgrade errors Co-authored-by: Max Inden <mail@max-inden.de> * z Co-authored-by: Max Inden <mail@max-inden.de>
To unblock hole punching protocols.