WIP - register/re-register logic fixes

The logic should be fixed (i.e. initial registration vs. refresh and knowing the connection state to not constantly trigger new connections), but we don't receive the registration on the rendezvous node.
rendezvous-asb-refactor
Daniel Karzel 3 years ago
parent dd933fc78b
commit b0645bb96e
No known key found for this signature in database
GPG Key ID: 30C3FC2E438ADB6E

@ -149,9 +149,7 @@ where
loop {
// rendezvous node re-registration
if let Some(rendezvous_behaviour) = self.swarm.behaviour_mut().rendezvous.as_mut() {
if let Err(error) = rendezvous_behaviour.refresh_registration() {
tracing::error!("Failed to register with rendezvous point: {:#}", error);
}
rendezvous_behaviour.refresh();
}
tokio::select! {

@ -1,5 +1,4 @@
use crate::rendezvous::XmrBtcNamespace;
use anyhow::Result;
use libp2p::core::connection::ConnectionId;
use libp2p::identity::Keypair;
use libp2p::multiaddr::Protocol;
@ -12,6 +11,13 @@ use libp2p::{Multiaddr, PeerId};
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
#[derive(Debug)]
enum ConnectionState {
Dialed,
Connected,
Disconnected,
}
/// A `NetworkBehaviour` that handles registration of the xmr-btc swap service
/// with a rendezvous point
pub struct Behaviour {
@ -20,7 +26,8 @@ pub struct Behaviour {
rendezvous_point_addr: Multiaddr,
rendezvous_namespace: XmrBtcNamespace,
rendezvous_reregister_timestamp: Option<Instant>,
is_connected: bool,
rendezvous_node_connection: ConnectionState,
is_initial_registration: bool,
events: Vec<NetworkBehaviourAction<BehaviourInEvent, ()>>,
}
@ -40,46 +47,58 @@ impl Behaviour {
rendezvous_point_addr: addr,
rendezvous_namespace: namespace,
rendezvous_reregister_timestamp: None,
is_connected: false,
rendezvous_node_connection: ConnectionState::Disconnected,
is_initial_registration: true,
events: vec![],
}
}
pub fn refresh_registration(&mut self) -> Result<()> {
if self.is_connected {
if let Some(rendezvous_reregister_timestamp) = self.rendezvous_reregister_timestamp {
if Instant::now() > rendezvous_reregister_timestamp {
self.rendezvous_behaviour.register(
Namespace::new(self.rendezvous_namespace.to_string())
.expect("our namespace to be a correct string"),
self.rendezvous_point_peer_id,
None,
);
fn register(&mut self) {
self.rendezvous_behaviour.register(
Namespace::new(self.rendezvous_namespace.to_string())
.expect("our namespace to be a correct string"),
self.rendezvous_point_peer_id,
None,
);
}
pub fn refresh(&mut self) {
match self.rendezvous_node_connection {
ConnectionState::Dialed => {} /* we are waiting for a connection to be established,
* no refresh */
ConnectionState::Connected => {
if let Some(rendezvous_reregister_timestamp) = self.rendezvous_reregister_timestamp
{
if Instant::now() > rendezvous_reregister_timestamp
&& !self.is_initial_registration
{
tracing::debug!("Sending re-registration to rendezvous node");
self.register();
}
} else if self.is_initial_registration {
tracing::debug!("Sending initial registration to rendezvous node");
self.is_initial_registration = false;
self.register();
}
}
} else {
// TODO: The refresh has to be tied to a refersh time that is tied to us having
// gotten a Ttl! We should not be able to refresh like this,
// because it may result in constant retry (with new connections) if there is an
// error on the rendezvous side and the connection is closed.
// In such an error scenario the initial dial to the rendezvous node should
// just fail and then we get an error on the ASB and don't try again. (pointless
// to try again anyway if the rendezvous server is broken / not available)
let p2p_suffix = Protocol::P2p(self.rendezvous_point_peer_id.into());
let address_with_p2p = if !self
.rendezvous_point_addr
.ends_with(&Multiaddr::empty().with(p2p_suffix.clone()))
{
self.rendezvous_point_addr.clone().with(p2p_suffix)
} else {
self.rendezvous_point_addr.clone()
};
self.events.push(NetworkBehaviourAction::DialAddress {
address: address_with_p2p,
})
ConnectionState::Disconnected => {
let p2p_suffix = Protocol::P2p(self.rendezvous_point_peer_id.into());
let address_with_p2p = if !self
.rendezvous_point_addr
.ends_with(&Multiaddr::empty().with(p2p_suffix.clone()))
{
self.rendezvous_point_addr.clone().with(p2p_suffix)
} else {
self.rendezvous_point_addr.clone()
};
self.events.push(NetworkBehaviourAction::DialAddress {
address: address_with_p2p,
});
self.rendezvous_node_connection = ConnectionState::Dialed;
}
}
Ok(())
}
}
@ -100,13 +119,14 @@ impl NetworkBehaviour for Behaviour {
fn inject_connected(&mut self, peer_id: &PeerId) {
if *peer_id == self.rendezvous_point_peer_id {
self.is_connected = true;
self.rendezvous_node_connection = ConnectionState::Connected;
}
}
fn inject_disconnected(&mut self, peer_id: &PeerId) {
if *peer_id == self.rendezvous_point_peer_id {
self.is_connected = false;
self.rendezvous_node_connection = ConnectionState::Disconnected;
self.is_initial_registration = false;
}
}
@ -134,16 +154,16 @@ impl NetworkBehaviourEventProcess<libp2p::rendezvous::Event> for Behaviour {
fn inject_event(&mut self, event: Event) {
match event {
Event::RegisterFailed(error) => {
self.is_initial_registration = false;
tracing::error!(rendezvous_node=%self.rendezvous_point_peer_id, "Registration with rendezvous node failed: {:#}", error);
}
Event::RegistrationExpired(registration) => {
tracing::warn!("Registation expired: {:?}", registration)
}
Event::Registered {
rendezvous_node,
ttl,
namespace,
} => {
self.is_initial_registration = false;
// TODO: this can most likely not happen at all, potentially remove these checks
if rendezvous_node != self.rendezvous_point_peer_id {
tracing::error!(peer_id=%rendezvous_node, "Ignoring message from unknown rendezvous node");
@ -157,6 +177,8 @@ impl NetworkBehaviourEventProcess<libp2p::rendezvous::Event> for Behaviour {
// record re-registration after half the ttl has expired
self.rendezvous_reregister_timestamp =
Some(Instant::now() + Duration::from_secs(ttl) / 2);
tracing::info!("Registration with rendezvous node successfull")
}
_ => {}
}

Loading…
Cancel
Save