151 lines
4.6 KiB
Rust
151 lines
4.6 KiB
Rust
use jsonrpc_core::Error;
|
|
use std::net::{IpAddr, SocketAddr};
|
|
use std::sync::Arc;
|
|
use v1::helpers::errors;
|
|
use v1::traits::Network as NetworkRpc;
|
|
use v1::types::{AddNodeOperation, NodeInfo};
|
|
use zebra_p2p;
|
|
|
|
pub trait NetworkApi: Send + Sync + 'static {
|
|
fn add_node(&self, socket_addr: SocketAddr) -> Result<(), zebra_p2p::NodeTableError>;
|
|
fn remove_node(&self, socket_addr: SocketAddr) -> Result<(), zebra_p2p::NodeTableError>;
|
|
fn connect(&self, socket_addr: SocketAddr);
|
|
fn node_info(&self, node_addr: IpAddr) -> Result<NodeInfo, zebra_p2p::NodeTableError>;
|
|
fn nodes_info(&self) -> Vec<NodeInfo>;
|
|
fn connection_count(&self) -> usize;
|
|
}
|
|
|
|
impl<T> NetworkRpc for NetworkClient<T>
|
|
where
|
|
T: NetworkApi,
|
|
{
|
|
fn add_node(&self, node: String, operation: AddNodeOperation) -> Result<(), Error> {
|
|
let addr = try!(node.parse().map_err(|_| errors::invalid_params(
|
|
"node",
|
|
"Invalid socket address format, should be ip:port (127.0.0.1:8008)"
|
|
)));
|
|
match operation {
|
|
AddNodeOperation::Add => self
|
|
.api
|
|
.add_node(addr)
|
|
.map_err(|_| errors::node_already_added()),
|
|
AddNodeOperation::Remove => self
|
|
.api
|
|
.remove_node(addr)
|
|
.map_err(|_| errors::node_not_added()),
|
|
AddNodeOperation::OneTry => {
|
|
self.api.connect(addr);
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
fn node_info(&self, _dns: bool, node_addr: Option<String>) -> Result<Vec<NodeInfo>, Error> {
|
|
let node_addr: Option<String> = node_addr.into();
|
|
Ok(match node_addr {
|
|
None => self.api.nodes_info(),
|
|
Some(node_addr) => {
|
|
let addr = try!(node_addr.parse().map_err(|_| errors::invalid_params(
|
|
"node",
|
|
"Invalid ip address format, should be ip address (127.0.0.1)"
|
|
)));
|
|
let node_info = try!(self
|
|
.api
|
|
.node_info(addr)
|
|
.map_err(|_| errors::node_not_added()));
|
|
vec![node_info]
|
|
}
|
|
})
|
|
}
|
|
|
|
fn connection_count(&self) -> Result<usize, Error> {
|
|
Ok(self.api.connection_count())
|
|
}
|
|
}
|
|
|
|
pub struct NetworkClient<T: NetworkApi> {
|
|
api: T,
|
|
}
|
|
|
|
impl<T> NetworkClient<T>
|
|
where
|
|
T: NetworkApi,
|
|
{
|
|
pub fn new(api: T) -> Self {
|
|
NetworkClient { api: api }
|
|
}
|
|
}
|
|
|
|
pub struct NetworkClientCore {
|
|
p2p: Arc<zebra_p2p::Context>,
|
|
}
|
|
|
|
impl NetworkClientCore {
|
|
pub fn new(p2p: Arc<zebra_p2p::Context>) -> Self {
|
|
NetworkClientCore { p2p: p2p }
|
|
}
|
|
}
|
|
|
|
impl NetworkApi for NetworkClientCore {
|
|
fn add_node(&self, socket_addr: SocketAddr) -> Result<(), zebra_p2p::NodeTableError> {
|
|
self.p2p.add_node(socket_addr)
|
|
}
|
|
|
|
fn remove_node(&self, socket_addr: SocketAddr) -> Result<(), zebra_p2p::NodeTableError> {
|
|
self.p2p.remove_node(socket_addr)
|
|
}
|
|
|
|
fn connect(&self, socket_addr: SocketAddr) {
|
|
zebra_p2p::Context::connect_normal(self.p2p.clone(), socket_addr);
|
|
}
|
|
|
|
fn node_info(&self, node_addr: IpAddr) -> Result<NodeInfo, zebra_p2p::NodeTableError> {
|
|
let exact_node = try!(self
|
|
.p2p
|
|
.nodes()
|
|
.iter()
|
|
.find(|n| n.address().ip() == node_addr)
|
|
.cloned()
|
|
.ok_or(zebra_p2p::NodeTableError::NoAddressInTable));
|
|
|
|
let peers: Vec<zebra_p2p::PeerInfo> = self
|
|
.p2p
|
|
.connections()
|
|
.info()
|
|
.into_iter()
|
|
.filter(|p| p.address == exact_node.address())
|
|
.collect();
|
|
|
|
Ok(NodeInfo {
|
|
addednode: format!("{}", exact_node.address()),
|
|
connected: !peers.is_empty(),
|
|
addresses: peers.into_iter().map(|p| p.into()).collect(),
|
|
})
|
|
}
|
|
|
|
fn nodes_info(&self) -> Vec<NodeInfo> {
|
|
let peers: Vec<zebra_p2p::PeerInfo> = self.p2p.connections().info();
|
|
|
|
self.p2p
|
|
.nodes()
|
|
.iter()
|
|
.map(|n| {
|
|
let node_peers: Vec<zebra_p2p::PeerInfo> = peers
|
|
.iter()
|
|
.filter(|p| p.address == n.address())
|
|
.cloned()
|
|
.collect();
|
|
NodeInfo {
|
|
addednode: format!("{}", n.address()),
|
|
connected: !node_peers.is_empty(),
|
|
addresses: node_peers.into_iter().map(|p| p.into()).collect(),
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
fn connection_count(&self) -> usize {
|
|
self.p2p.connections().count()
|
|
}
|
|
}
|