node: Expose listen addresses
This commit is contained in:
parent
d86d99e002
commit
9c9bbbe7bb
|
|
@ -15,7 +15,7 @@ node status` command (or just `rad node` for short):
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad node status
|
$ rad node status
|
||||||
✓ Node is running.
|
✓ Node is running and listening on [..].
|
||||||
```
|
```
|
||||||
|
|
||||||
The node also allows us to query data that it has access to such as
|
The node also allows us to query data that it has access to such as
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,21 @@ pub fn connect(
|
||||||
|
|
||||||
pub fn status(node: &Node, profile: &Profile) -> anyhow::Result<()> {
|
pub fn status(node: &Node, profile: &Profile) -> anyhow::Result<()> {
|
||||||
if node.is_running() {
|
if node.is_running() {
|
||||||
term::success!("Node is {}.", term::format::positive("running"));
|
let listen = node
|
||||||
|
.listen_addrs()?
|
||||||
|
.into_iter()
|
||||||
|
.map(|addr| addr.to_string())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if listen.is_empty() {
|
||||||
|
term::success!("Node is {}.", term::format::positive("running"));
|
||||||
|
} else {
|
||||||
|
term::success!(
|
||||||
|
"Node is {} and listening on {}.",
|
||||||
|
term::format::positive("running"),
|
||||||
|
listen.join(", ")
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
term::info!("Node is {}.", term::format::negative("stopped"));
|
term::info!("Node is {}.", term::format::negative("stopped"));
|
||||||
term::info!(
|
term::info!(
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,11 @@ where
|
||||||
|
|
||||||
CommandResult::Okay(config).to_writer(writer)?;
|
CommandResult::Okay(config).to_writer(writer)?;
|
||||||
}
|
}
|
||||||
|
Command::ListenAddrs => {
|
||||||
|
let addrs = handle.listen_addrs()?;
|
||||||
|
|
||||||
|
CommandResult::Okay(addrs).to_writer(writer)?;
|
||||||
|
}
|
||||||
Command::Seeds { rid } => {
|
Command::Seeds { rid } => {
|
||||||
let seeds = handle.seeds(rid)?;
|
let seeds = handle.seeds(rid)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,8 +244,6 @@ impl Runtime {
|
||||||
|
|
||||||
local_addrs.push(local_addr);
|
local_addrs.push(local_addr);
|
||||||
wire.listen(listener);
|
wire.listen(listener);
|
||||||
|
|
||||||
log::info!(target: "node", "Listening on {local_addr}..");
|
|
||||||
}
|
}
|
||||||
let reactor = Reactor::named(wire, popol::Poller::new(), thread::name(&id, "service"))?;
|
let reactor = Reactor::named(wire, popol::Poller::new(), thread::name(&id, "service"))?;
|
||||||
let handle = Handle::new(home.clone(), reactor.controller(), emitter);
|
let handle = Handle::new(home.clone(), reactor.controller(), emitter);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::net;
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
@ -190,6 +191,12 @@ impl radicle::node::Handle for Handle {
|
||||||
receiver.recv().map_err(Error::from)
|
receiver.recv().map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn listen_addrs(&self) -> Result<Vec<net::SocketAddr>, Self::Error> {
|
||||||
|
let (sender, receiver) = chan::bounded(1);
|
||||||
|
self.command(service::Command::ListenAddrs(sender))?;
|
||||||
|
receiver.recv().map_err(Error::from)
|
||||||
|
}
|
||||||
|
|
||||||
fn fetch(
|
fn fetch(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: RepoId,
|
id: RepoId,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use std::collections::hash_map::Entry;
|
||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{HashMap, HashSet, VecDeque};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{fmt, time};
|
use std::{fmt, net, time};
|
||||||
|
|
||||||
use crossbeam_channel as chan;
|
use crossbeam_channel as chan;
|
||||||
use fastrand::Rng;
|
use fastrand::Rng;
|
||||||
|
|
@ -179,6 +179,8 @@ pub enum Command {
|
||||||
Disconnect(NodeId),
|
Disconnect(NodeId),
|
||||||
/// Get the node configuration.
|
/// Get the node configuration.
|
||||||
Config(chan::Sender<Config>),
|
Config(chan::Sender<Config>),
|
||||||
|
/// Get the node's listen addresses.
|
||||||
|
ListenAddrs(chan::Sender<Vec<std::net::SocketAddr>>),
|
||||||
/// Lookup seeds for the given repository in the routing table.
|
/// Lookup seeds for the given repository in the routing table.
|
||||||
Seeds(RepoId, chan::Sender<Seeds>),
|
Seeds(RepoId, chan::Sender<Seeds>),
|
||||||
/// Fetch the given repository from the network.
|
/// Fetch the given repository from the network.
|
||||||
|
|
@ -204,6 +206,7 @@ impl fmt::Debug for Command {
|
||||||
Self::Connect(id, addr, opts) => write!(f, "Connect({id}, {addr}, {opts:?})"),
|
Self::Connect(id, addr, opts) => write!(f, "Connect({id}, {addr}, {opts:?})"),
|
||||||
Self::Disconnect(id) => write!(f, "Disconnect({id})"),
|
Self::Disconnect(id) => write!(f, "Disconnect({id})"),
|
||||||
Self::Config(_) => write!(f, "Config"),
|
Self::Config(_) => write!(f, "Config"),
|
||||||
|
Self::ListenAddrs(_) => write!(f, "ListenAddrs"),
|
||||||
Self::Seeds(id, _) => write!(f, "Seeds({id})"),
|
Self::Seeds(id, _) => write!(f, "Seeds({id})"),
|
||||||
Self::Fetch(id, node, _, _) => write!(f, "Fetch({id}, {node})"),
|
Self::Fetch(id, node, _, _) => write!(f, "Fetch({id}, {node})"),
|
||||||
Self::Seed(id, scope, _) => write!(f, "Seed({id}, {scope})"),
|
Self::Seed(id, scope, _) => write!(f, "Seed({id}, {scope})"),
|
||||||
|
|
@ -370,6 +373,8 @@ pub struct Service<D, S, G> {
|
||||||
started_at: Option<LocalTime>,
|
started_at: Option<LocalTime>,
|
||||||
/// Publishes events to subscribers.
|
/// Publishes events to subscribers.
|
||||||
emitter: Emitter<Event>,
|
emitter: Emitter<Event>,
|
||||||
|
/// Local listening addresses.
|
||||||
|
listening: Vec<net::SocketAddr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, S, G> Service<D, S, G>
|
impl<D, S, G> Service<D, S, G>
|
||||||
|
|
@ -427,6 +432,7 @@ where
|
||||||
last_announce: LocalTime::default(),
|
last_announce: LocalTime::default(),
|
||||||
started_at: None,
|
started_at: None,
|
||||||
emitter,
|
emitter,
|
||||||
|
listening: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -705,6 +711,9 @@ where
|
||||||
Command::Config(resp) => {
|
Command::Config(resp) => {
|
||||||
resp.send(self.config.clone()).ok();
|
resp.send(self.config.clone()).ok();
|
||||||
}
|
}
|
||||||
|
Command::ListenAddrs(resp) => {
|
||||||
|
resp.send(self.listening.clone()).ok();
|
||||||
|
}
|
||||||
Command::Seeds(rid, resp) => match self.seeds(&rid) {
|
Command::Seeds(rid, resp) => match self.seeds(&rid) {
|
||||||
Ok(seeds) => {
|
Ok(seeds) => {
|
||||||
let (connected, disconnected) = seeds.partition();
|
let (connected, disconnected) = seeds.partition();
|
||||||
|
|
@ -1077,6 +1086,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn listening(&mut self, local_addr: net::SocketAddr) {
|
||||||
|
log::info!(target: "node", "Listening on {local_addr}..");
|
||||||
|
|
||||||
|
self.listening.push(local_addr);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn connected(&mut self, remote: NodeId, addr: Address, link: Link) {
|
pub fn connected(&mut self, remote: NodeId, addr: Address, link: Link) {
|
||||||
info!(target: "service", "Connected to {} ({:?})", remote, link);
|
info!(target: "service", "Connected to {} ({:?})", remote, link);
|
||||||
self.emitter.emit(Event::PeerConnected { nid: remote });
|
self.emitter.emit(Event::PeerConnected { nid: remote });
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,10 @@ impl radicle::node::Handle for Handle {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn listen_addrs(&self) -> Result<Vec<std::net::SocketAddr>, Self::Error> {
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
|
||||||
fn config(&self) -> Result<Config, Self::Error> {
|
fn config(&self) -> Result<Config, Self::Error> {
|
||||||
Ok(Config::new(Alias::new("acme")))
|
Ok(Config::new(Alias::new("acme")))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,8 @@ pub struct Wire<D, S, G: Signer + Ecdh> {
|
||||||
outbound: RandomMap<RawFd, Outbound>,
|
outbound: RandomMap<RawFd, Outbound>,
|
||||||
/// Inbound peers without a session.
|
/// Inbound peers without a session.
|
||||||
inbound: RandomMap<RawFd, Inbound>,
|
inbound: RandomMap<RawFd, Inbound>,
|
||||||
|
/// Listening addresses that are not yet registered.
|
||||||
|
listening: RandomMap<RawFd, net::SocketAddr>,
|
||||||
/// Peer (established) sessions.
|
/// Peer (established) sessions.
|
||||||
peers: Peers,
|
peers: Peers,
|
||||||
/// SOCKS5 proxy address.
|
/// SOCKS5 proxy address.
|
||||||
|
|
@ -320,11 +322,14 @@ where
|
||||||
actions: VecDeque::new(),
|
actions: VecDeque::new(),
|
||||||
inbound: RandomMap::default(),
|
inbound: RandomMap::default(),
|
||||||
outbound: RandomMap::default(),
|
outbound: RandomMap::default(),
|
||||||
|
listening: RandomMap::default(),
|
||||||
peers: Peers(RandomMap::default()),
|
peers: Peers(RandomMap::default()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen(&mut self, socket: NetAccept<WireSession<G>>) {
|
pub fn listen(&mut self, socket: NetAccept<WireSession<G>>) {
|
||||||
|
self.listening
|
||||||
|
.insert(socket.as_raw_fd(), socket.local_addr());
|
||||||
self.actions.push_back(Action::RegisterListener(socket));
|
self.actions.push_back(Action::RegisterListener(socket));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,18 +500,23 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_registered(&mut self, fd: RawFd, id: ResourceId, typ: ResourceType) {
|
fn handle_registered(&mut self, fd: RawFd, id: ResourceId, typ: ResourceType) {
|
||||||
if typ == ResourceType::Listener {
|
match typ {
|
||||||
// Not interested in listener resource registration.
|
ResourceType::Listener => {
|
||||||
return;
|
if let Some(local_addr) = self.listening.remove(&fd) {
|
||||||
}
|
self.service.listening(local_addr);
|
||||||
if let Some(outbound) = self.outbound.get_mut(&fd) {
|
}
|
||||||
log::debug!(target: "wire", "Outbound peer resource registered for {} with id={id} (fd={fd})", outbound.nid);
|
}
|
||||||
outbound.id = Some(id);
|
ResourceType::Transport => {
|
||||||
} else if let Some(inbound) = self.inbound.get_mut(&fd) {
|
if let Some(outbound) = self.outbound.get_mut(&fd) {
|
||||||
log::debug!(target: "wire", "Inbound peer resource registered with id={id} (fd={fd})");
|
log::debug!(target: "wire", "Outbound peer resource registered for {} with id={id} (fd={fd})", outbound.nid);
|
||||||
inbound.id = Some(id);
|
outbound.id = Some(id);
|
||||||
} else {
|
} else if let Some(inbound) = self.inbound.get_mut(&fd) {
|
||||||
log::warn!(target: "wire", "Unknown peer registered with fd={fd} and id={id}");
|
log::debug!(target: "wire", "Inbound peer resource registered with id={id} (fd={fd})");
|
||||||
|
inbound.id = Some(id);
|
||||||
|
} else {
|
||||||
|
log::warn!(target: "wire", "Unknown peer registered with fd={fd} and id={id}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -435,6 +435,9 @@ pub enum Command {
|
||||||
/// Get the current node condiguration.
|
/// Get the current node condiguration.
|
||||||
Config,
|
Config,
|
||||||
|
|
||||||
|
/// Get the node's listen addresses.
|
||||||
|
ListenAddrs,
|
||||||
|
|
||||||
/// Connect to node with the given address.
|
/// Connect to node with the given address.
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
Connect {
|
Connect {
|
||||||
|
|
@ -808,8 +811,10 @@ pub trait Handle: Clone + Sync + Send {
|
||||||
|
|
||||||
/// Get the local Node ID.
|
/// Get the local Node ID.
|
||||||
fn nid(&self) -> Result<NodeId, Self::Error>;
|
fn nid(&self) -> Result<NodeId, Self::Error>;
|
||||||
/// Check if the node is running. to a peer.
|
/// Check if the node is running.
|
||||||
fn is_running(&self) -> bool;
|
fn is_running(&self) -> bool;
|
||||||
|
/// Get the node's bound listen addresses.
|
||||||
|
fn listen_addrs(&self) -> Result<Vec<net::SocketAddr>, Self::Error>;
|
||||||
/// Get the current node configuration.
|
/// Get the current node configuration.
|
||||||
fn config(&self) -> Result<config::Config, Self::Error>;
|
fn config(&self) -> Result<config::Config, Self::Error>;
|
||||||
/// Connect to a peer.
|
/// Connect to a peer.
|
||||||
|
|
@ -970,6 +975,13 @@ impl Handle for Node {
|
||||||
.map_err(Error::from)
|
.map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn listen_addrs(&self) -> Result<Vec<net::SocketAddr>, Error> {
|
||||||
|
self.call::<Vec<net::SocketAddr>>(Command::ListenAddrs, DEFAULT_TIMEOUT)?
|
||||||
|
.next()
|
||||||
|
.ok_or(Error::EmptyResponse)?
|
||||||
|
.map_err(Error::from)
|
||||||
|
}
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
let Ok(mut lines) = self.call::<Success>(Command::Status, DEFAULT_TIMEOUT) else {
|
let Ok(mut lines) = self.call::<Success>(Command::Status, DEFAULT_TIMEOUT) else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue