node: Add support for multiple address types

Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
Alexis Sellier 2022-08-30 16:27:35 +02:00
parent 92f17d71c3
commit b78bbc4ecc
No known key found for this signature in database
3 changed files with 49 additions and 7 deletions

View File

@ -2,6 +2,7 @@
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::{collections::VecDeque, fmt, io, net, net::IpAddr}; use std::{collections::VecDeque, fmt, io, net, net::IpAddr};
use ed25519_consensus::VerificationKey;
use fastrand::Rng; use fastrand::Rng;
use git_url::Url; use git_url::Url;
use log::*; use log::*;
@ -27,6 +28,14 @@ pub type Routing = HashMap<ProjId, HashSet<PeerId>>;
/// Seconds since epoch. /// Seconds since epoch.
pub type Timestamp = u64; pub type Timestamp = u64;
/// Peer public protocol address.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum Address {
Tor { key: VerificationKey, port: u16 },
Tcp { addr: net::SocketAddr },
Dns { host: String, port: u16 },
}
pub const NETWORK_MAGIC: u32 = 0x819b43d9; pub const NETWORK_MAGIC: u32 = 0x819b43d9;
pub const DEFAULT_PORT: u16 = 8776; pub const DEFAULT_PORT: u16 = 8776;
pub const PROTOCOL_VERSION: u32 = 1; pub const PROTOCOL_VERSION: u32 = 1;
@ -62,6 +71,7 @@ pub enum Message {
Hello { Hello {
timestamp: Timestamp, timestamp: Timestamp,
version: u32, version: u32,
addrs: Vec<Address>,
git: Url, git: Url,
}, },
/// Get node addresses from a peer. /// Get node addresses from a peer.
@ -91,10 +101,11 @@ impl From<Message> for Envelope {
} }
impl Message { impl Message {
pub fn hello(timestamp: Timestamp, git: Url) -> Self { pub fn hello(timestamp: Timestamp, addrs: Vec<Address>, git: Url) -> Self {
Self::Hello { Self::Hello {
timestamp, timestamp,
version: PROTOCOL_VERSION, version: PROTOCOL_VERSION,
addrs,
git, git,
} }
} }
@ -159,6 +170,8 @@ pub struct Config {
pub remote_tracking: RemoteTracking, pub remote_tracking: RemoteTracking,
/// Whether or not our node should relay inventories. /// Whether or not our node should relay inventories.
pub relay: bool, pub relay: bool,
/// List of addresses to listen on for protocol connections.
pub listen: Vec<Address>,
/// Our Git URL for fetching projects. /// Our Git URL for fetching projects.
pub git_url: Url, pub git_url: Url,
} }
@ -170,6 +183,7 @@ impl Default for Config {
project_tracking: ProjectTracking::default(), project_tracking: ProjectTracking::default(),
remote_tracking: RemoteTracking::default(), remote_tracking: RemoteTracking::default(),
relay: true, relay: true,
listen: vec![],
git_url: Url::default(), git_url: Url::default(),
} }
} }
@ -504,7 +518,11 @@ where
self.context.write_all( self.context.write_all(
peer.addr, peer.addr,
[ [
Message::hello(self.context.timestamp(), git), Message::hello(
self.context.timestamp(),
self.context.config.listen.clone(),
git,
),
Message::get_inventory([]), Message::get_inventory([]),
], ],
); );
@ -818,7 +836,12 @@ enum PeerState {
#[default] #[default]
Initial, Initial,
/// State after successful handshake. /// State after successful handshake.
Negotiated { since: LocalTime, git: Url }, Negotiated {
since: LocalTime,
/// Addresses this peer is reachable on.
addrs: Vec<Address>,
git: Url,
},
/// When a peer is disconnected. /// When a peer is disconnected.
Disconnected { since: LocalTime }, Disconnected { since: LocalTime },
} }
@ -896,6 +919,7 @@ impl Peer {
Message::Hello { Message::Hello {
timestamp, timestamp,
version, version,
addrs,
git, git,
}, },
) => { ) => {
@ -913,7 +937,10 @@ impl Peer {
let git = ctx.config.git_url.clone(); let git = ctx.config.git_url.clone();
ctx.write_all( ctx.write_all(
self.addr, self.addr,
[Message::hello(now, git), Message::get_inventory([])], [
Message::hello(now, ctx.config.listen.clone(), git),
Message::get_inventory([]),
],
); );
} }
// Nb. we don't set the peer timestamp here, since it is going to be // Nb. we don't set the peer timestamp here, since it is going to be
@ -921,6 +948,7 @@ impl Peer {
// mean that messages received right after the handshake could be ignored. // mean that messages received right after the handshake could be ignored.
self.state = PeerState::Negotiated { self.state = PeerState::Negotiated {
since: ctx.clock.local_time(), since: ctx.clock.local_time(),
addrs,
git, git,
}; };
} }

View File

@ -137,7 +137,14 @@ where
self.initialize(); self.initialize();
self.protocol.connected(*remote, &local, Link::Inbound); self.protocol.connected(*remote, &local, Link::Inbound);
self.receive(remote, Message::hello(self.local_time().as_secs(), git)); self.receive(
remote,
Message::hello(
self.local_time().as_secs(),
vec![Address::Tcp { addr: *remote }],
git,
),
);
let mut msgs = self.messages(remote); let mut msgs = self.messages(remote);
msgs.find(|m| matches!(m, Message::Hello { .. })) msgs.find(|m| matches!(m, Message::Hello { .. }))
@ -161,7 +168,14 @@ where
.expect("`get-inventory` is sent"); .expect("`get-inventory` is sent");
let git = peer.config().git_url.clone(); let git = peer.config().git_url.clone();
self.receive(&remote, Message::hello(self.local_time().as_secs(), git)); self.receive(
&remote,
Message::hello(
self.local_time().as_secs(),
peer.config().listen.clone(),
git,
),
);
} }
/// Drain outgoing messages sent from this peer to the remote address. /// Drain outgoing messages sent from this peer to the remote address.

View File

@ -108,7 +108,7 @@ fn test_handshake_invalid_timestamp() {
alice.connected(bob.addr(), &local, Link::Inbound); alice.connected(bob.addr(), &local, Link::Inbound);
alice.receive( alice.receive(
&bob.addr(), &bob.addr(),
Message::hello(alice.timestamp() - time_delta, bob.git_url()), Message::hello(alice.timestamp() - time_delta, vec![], bob.git_url()),
); );
assert_matches!(alice.outbox().next(), Some(Io::Disconnect(addr, _)) if addr == bob.addr()); assert_matches!(alice.outbox().next(), Some(Io::Disconnect(addr, _)) if addr == bob.addr());
} }