Skip to content
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

Merged
merged 15 commits into from
May 11, 2021

Conversation

vyzo
Copy link
Contributor

@vyzo vyzo commented Jul 29, 2019

To unblock hole punching protocols.

@vyzo vyzo requested review from Stebalien and raulk July 29, 2019 09:31
@raulk raulk changed the title multistream simultaneous open protocol multistream simultaneous open protocol extension Jul 29, 2019
@raulk raulk changed the title multistream simultaneous open protocol extension multistream-select 1.0: simultaneous open protocol extension Jul 29, 2019
Copy link
Member

@raulk raulk left a 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:

  1. Make this an exceptional pathway. When multistream detects a collision, start this process to deduplicate the initiator role.
  2. 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.

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.
Copy link
Member

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.

@vyzo
Copy link
Contributor Author

vyzo commented Jul 29, 2019

We discussed a simple solution with @Stebalien , to basically pipeline multistream,iamclient:random-id,protocol in a single packet so as to avoid the negotiation altogether.
The only problem is the miniscule probability of selecting the same random integer, but we can throw our hands in the air in that case.
I will update the spec to reflect this.

@vyzo
Copy link
Contributor Author

vyzo commented Jul 29, 2019

The second, more robust solution, is to use a prefix for the integer when both sides declare iamclient and ignore protocols that are piggybacked (we discussed this also with @Stebalien).
Spec update forthcoming.

@@ -0,0 +1,72 @@
# Simultaneous Open for multistream-select
Copy link
Member

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.

Copy link
Contributor Author

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!

Copy link
Contributor Author

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!

@raulk
Copy link
Member

raulk commented Jul 29, 2019

@vyzo Yup, I think that pipelining sequence could work. I'll continue reviewing tomorrow; thanks!

@vyzo
Copy link
Contributor Author

vyzo commented Jul 30, 2019

I pushed an update, which resolves the issues with pipelining.
The solution adopted was option 2, in which case the peers use a prefix for the random integer and can ignore the pipelined security protocol.

@vyzo
Copy link
Contributor Author

vyzo commented Jul 30, 2019

summoning @raulk @Stebalien for a second round of review.

connections/simopen.md Outdated Show resolved Hide resolved
connections/simopen.md Outdated Show resolved Hide resolved
Co-Authored-By: Jacob Heun <jacobheun@gmail.com>
Copy link
Member

@vasco-santos vasco-santos left a 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 Show resolved Hide resolved
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
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to mandate base64.

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.
Copy link
Contributor

@aarshkshah1992 aarshkshah1992 Jan 7, 2021

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 ?

Copy link
Contributor

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).

Copy link
Member

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.

I think it would be //////////8=

Copy link
Contributor

@marten-seemann marten-seemann Jan 13, 2021

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?

Copy link
Member

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.

Copy link
Contributor

@marten-seemann marten-seemann Jan 13, 2021

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?

Copy link
Contributor

@marten-seemann marten-seemann left a 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.

@aarshkshah1992
Copy link
Contributor

aarshkshah1992 commented Jan 13, 2021

@marten-seemann

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?

We will NOT end up with an extra roundtrip because the client sends a pipelined multistream1.0|iamclient|noise message to the remote peer and the remote peer will write a multistream,na, noise message back if it is NOT a simultaneous open.
If it is a simultaneous open and the remote peer does NOT support the iamclient protocol, things will fail just as they do today.

  • 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.

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".
Any thoughts @Stebalien @jacobheun ?

@vyzo
Copy link
Contributor Author

vyzo commented Mar 11, 2021

@aarshkshah1992 @marten-seemann the go implementation has diverged from the spec; can you please update it to match what was implemented?

connections/simopen.md Outdated Show resolved Hide resolved
@mxinden
Copy link
Member

mxinden commented Apr 19, 2021

@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.

@mxinden mxinden mentioned this pull request Apr 20, 2021
14 tasks
mxinden and others added 2 commits April 27, 2021 19:10
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 '/'
mxinden added a commit to mxinden/rust-libp2p that referenced this pull request May 5, 2021
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`.
mxinden added a commit to mxinden/rust-libp2p that referenced this pull request May 5, 2021
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`.
Copy link
Member

@mxinden mxinden left a 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.


| Lifecycle Stage | Maturity | Status | Latest Revision |
|-----------------|---------------|--------|-----------------|
| 1A | Working Draft | Active | DRAFT |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| 1A | Working Draft | Active | DRAFT |
| 1A | Working Draft | Active | r0, 2021-05-06 |

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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)

https://github.com/multiformats/go-multistream/blob/4e1d9a7e25b067b7527ca2af72ce9c06529ebfb7/client.go#L167

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`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))

https://github.com/multiformats/go-multistream/blob/4e1d9a7e25b067b7527ca2af72ce9c06529ebfb7/client.go#L171

Comment on lines 69 to 72
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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).

@@ -0,0 +1,89 @@
# Simultaneous Open for bootstrapping connections in multistream-select
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Simultaneous Open for bootstrapping connections in multistream-select
# Connection bootstrapping: Handling simultaneous open in multistream-select.

As per @raulk's comment in #196 (comment).

Copy link
Member

@mxinden mxinden left a 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.

@mxinden mxinden merged commit 9274d30 into master May 11, 2021
canewsin added a commit to decentnetwork/rust-libp2p that referenced this pull request Nov 21, 2021
* 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>
canewsin added a commit to decentnetwork/rust-libp2p that referenced this pull request Nov 25, 2021
* 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>
canewsin added a commit to decentnetwork/rust-libp2p that referenced this pull request Dec 6, 2021
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.