diff --git a/node/src/protocol.rs b/node/src/protocol.rs index 9b6fb7e3..0845ef6f 100644 --- a/node/src/protocol.rs +++ b/node/src/protocol.rs @@ -2,6 +2,7 @@ use std::ops::{Deref, DerefMut}; use std::{collections::VecDeque, fmt, io, net, net::IpAddr}; +use ed25519_consensus::VerificationKey; use fastrand::Rng; use git_url::Url; use log::*; @@ -27,6 +28,14 @@ pub type Routing = HashMap>; /// Seconds since epoch. 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 DEFAULT_PORT: u16 = 8776; pub const PROTOCOL_VERSION: u32 = 1; @@ -62,6 +71,7 @@ pub enum Message { Hello { timestamp: Timestamp, version: u32, + addrs: Vec
, git: Url, }, /// Get node addresses from a peer. @@ -91,10 +101,11 @@ impl From for Envelope { } impl Message { - pub fn hello(timestamp: Timestamp, git: Url) -> Self { + pub fn hello(timestamp: Timestamp, addrs: Vec
, git: Url) -> Self { Self::Hello { timestamp, version: PROTOCOL_VERSION, + addrs, git, } } @@ -159,6 +170,8 @@ pub struct Config { pub remote_tracking: RemoteTracking, /// Whether or not our node should relay inventories. pub relay: bool, + /// List of addresses to listen on for protocol connections. + pub listen: Vec
, /// Our Git URL for fetching projects. pub git_url: Url, } @@ -170,6 +183,7 @@ impl Default for Config { project_tracking: ProjectTracking::default(), remote_tracking: RemoteTracking::default(), relay: true, + listen: vec![], git_url: Url::default(), } } @@ -504,7 +518,11 @@ where self.context.write_all( peer.addr, [ - Message::hello(self.context.timestamp(), git), + Message::hello( + self.context.timestamp(), + self.context.config.listen.clone(), + git, + ), Message::get_inventory([]), ], ); @@ -818,7 +836,12 @@ enum PeerState { #[default] Initial, /// State after successful handshake. - Negotiated { since: LocalTime, git: Url }, + Negotiated { + since: LocalTime, + /// Addresses this peer is reachable on. + addrs: Vec
, + git: Url, + }, /// When a peer is disconnected. Disconnected { since: LocalTime }, } @@ -896,6 +919,7 @@ impl Peer { Message::Hello { timestamp, version, + addrs, git, }, ) => { @@ -913,7 +937,10 @@ impl Peer { let git = ctx.config.git_url.clone(); ctx.write_all( 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 @@ -921,6 +948,7 @@ impl Peer { // mean that messages received right after the handshake could be ignored. self.state = PeerState::Negotiated { since: ctx.clock.local_time(), + addrs, git, }; } diff --git a/node/src/test/peer.rs b/node/src/test/peer.rs index bafff94f..02bf012b 100644 --- a/node/src/test/peer.rs +++ b/node/src/test/peer.rs @@ -137,7 +137,14 @@ where self.initialize(); 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); msgs.find(|m| matches!(m, Message::Hello { .. })) @@ -161,7 +168,14 @@ where .expect("`get-inventory` is sent"); 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. diff --git a/node/src/test/tests.rs b/node/src/test/tests.rs index f83cf13d..3fc8e8f8 100644 --- a/node/src/test/tests.rs +++ b/node/src/test/tests.rs @@ -108,7 +108,7 @@ fn test_handshake_invalid_timestamp() { alice.connected(bob.addr(), &local, Link::Inbound); alice.receive( &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()); }