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

protocols/dcutr/examples: Wait to tell relay its public addr #2659

Merged
merged 5 commits into from
May 20, 2022

Conversation

mxinden
Copy link
Member

@mxinden mxinden commented May 19, 2022

Description

As a listening client, when requesting a reservation with a relay, the relay
responds with its public addresses. The listening client can then use the public
addresses of the relay to advertise itself as reachable under a relayed
address (/<public-relay-addr>/p2p-circuit/p2p/<listening-client-peer-id>).

The above operates under the assumption that the relay knows its public address.
A relay learns its public address from remote peers, via the identify protocol.
In the case where the relay just started up, the listening client might be the
very first node to connect to it.

Such scenario allows for a race condition. The listening client requests a
reservation from the relay, while the relay requests its public address from the
listening client. The former needs to contain the response from the latter.

This commit serializes the two requests, making sure, in the case of a freshly
started relay, that the listening client tells the relay its public address
before requesting a reservation from the relay.

Links to any relevant issues

Follow up to #2642. Suggested in #2621 (comment).

Note that hole punching is still broken due to #2651.

Open Questions

Change checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • A changelog entry has been made in the appropriate crates

As a listening client, when requesting a reservation with a relay, the relay
responds with its public addresses. The listening client can then use the public
addresses of the relay to advertise itself as reachable under a relayed
address (`/<public-relay-addr>/p2p-circuit/p2p/<listening-client-peer-id>`).

The above operates under the assumption that the relay knows its public address.
A relay learns its public address from remote peers, via the identify protocol.
In the case where the relay just started up, the listening client might be the
very first node to connect to it.

Such scenario allows for a race condition. The listening client requests a
reservation from the relay, while the relay requests its public address from the
listening client. The former needs to contain the response from the latter.

This commit serializes the two requests, making sure, in the case of a freshly
started relay, that the listening client tells the relay its public address
before requesting a reservation from the relay.
@mxinden
Copy link
Member Author

mxinden commented May 19, 2022

//CC @Foemass

Comment on lines 226 to 236
opts.relay_address
.clone()
.with(Protocol::P2pCircuit)
.with(Protocol::P2p(opts.remote_peer_id.unwrap().into())),
)
.unwrap();
}
Mode::Listen => {
swarm
.listen_on(opts.relay_address.clone().with(Protocol::P2pCircuit))
.unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
opts.relay_address
.clone()
.with(Protocol::P2pCircuit)
.with(Protocol::P2p(opts.remote_peer_id.unwrap().into())),
)
.unwrap();
}
Mode::Listen => {
swarm
.listen_on(opts.relay_address.clone().with(Protocol::P2pCircuit))
.unwrap();
opts.relay_address
.with(Protocol::P2pCircuit)
.with(Protocol::P2p(opts.remote_peer_id.unwrap().into())),
)
.unwrap();
}
Mode::Listen => {
swarm
.listen_on(opts.relay_address.with(Protocol::P2pCircuit))
.unwrap();

Nit: don't think we need to clone the address here; it's not used afterwards anymore.

Comment on lines 238 to 256
// Wait for relay to accept reservation request.
block_on(async {
loop {
match swarm.next().await.unwrap() {
SwarmEvent::NewListenAddr { .. } => {}
SwarmEvent::Dialing { .. } => {}
SwarmEvent::ConnectionEstablished { .. } => {}
SwarmEvent::Behaviour(Event::Ping(_)) => {}
SwarmEvent::Behaviour(Event::Relay(
client::Event::ReservationReqAccepted { .. },
)) => {
info!("Relay accepted our reservation request.");
break;
}
SwarmEvent::Behaviour(Event::Identify(_)) => {}
event => panic!("{:?}", event),
}
}
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to do a separate loop here to wait for the ReservationReqAccepted? We don't initiate any following action, but instead directly jump into the next loop below. Couldn't we just remove this block?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea!

protocols/dcutr/examples/client.rs Outdated Show resolved Hide resolved
@mxinden mxinden merged commit 1d6b08b into libp2p:master May 20, 2022
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.

3 participants