mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-13 17:35:37 +00:00
use customized rpc implementation, remove Tarpc & Tonic (#348)
This patch removes Tarpc & Tonic GRPC and implements a customized rpc framework, which can be used by peer rpc and cli interface. web config server can also use this rpc framework. moreover, rewrite the public server logic, use ospf route to implement public server based networking. this make public server mesh possible.
This commit is contained in:
@@ -1,27 +1,11 @@
|
||||
use std::{
|
||||
sync::Arc,
|
||||
time::{Duration, SystemTime},
|
||||
};
|
||||
|
||||
use dashmap::DashMap;
|
||||
use tokio::{sync::Mutex, task::JoinSet};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
error::Error,
|
||||
global_ctx::{ArcGlobalCtx, NetworkIdentity},
|
||||
PeerId,
|
||||
},
|
||||
common::{error::Error, global_ctx::ArcGlobalCtx, scoped_task::ScopedTask, PeerId},
|
||||
tunnel::packet_def::ZCPacket,
|
||||
};
|
||||
|
||||
use super::{
|
||||
foreign_network_manager::{ForeignNetworkServiceClient, FOREIGN_NETWORK_SERVICE_ID},
|
||||
peer_conn::PeerConn,
|
||||
peer_map::PeerMap,
|
||||
peer_rpc::PeerRpcManager,
|
||||
PacketRecvChan,
|
||||
};
|
||||
use super::{peer_conn::PeerConn, peer_map::PeerMap, peer_rpc::PeerRpcManager, PacketRecvChan};
|
||||
|
||||
pub struct ForeignNetworkClient {
|
||||
global_ctx: ArcGlobalCtx,
|
||||
@@ -29,9 +13,7 @@ pub struct ForeignNetworkClient {
|
||||
my_peer_id: PeerId,
|
||||
|
||||
peer_map: Arc<PeerMap>,
|
||||
|
||||
next_hop: Arc<DashMap<PeerId, PeerId>>,
|
||||
tasks: Mutex<JoinSet<()>>,
|
||||
task: Mutex<Option<ScopedTask<()>>>,
|
||||
}
|
||||
|
||||
impl ForeignNetworkClient {
|
||||
@@ -46,17 +28,13 @@ impl ForeignNetworkClient {
|
||||
global_ctx.clone(),
|
||||
my_peer_id,
|
||||
));
|
||||
let next_hop = Arc::new(DashMap::new());
|
||||
|
||||
Self {
|
||||
global_ctx,
|
||||
peer_rpc,
|
||||
my_peer_id,
|
||||
|
||||
peer_map,
|
||||
|
||||
next_hop,
|
||||
tasks: Mutex::new(JoinSet::new()),
|
||||
task: Mutex::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,91 +43,19 @@ impl ForeignNetworkClient {
|
||||
self.peer_map.add_new_peer_conn(peer_conn).await
|
||||
}
|
||||
|
||||
async fn collect_next_hop_in_foreign_network_task(
|
||||
network_identity: NetworkIdentity,
|
||||
peer_map: Arc<PeerMap>,
|
||||
peer_rpc: Arc<PeerRpcManager>,
|
||||
next_hop: Arc<DashMap<PeerId, PeerId>>,
|
||||
) {
|
||||
loop {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
|
||||
peer_map.clean_peer_without_conn().await;
|
||||
|
||||
let new_next_hop = Self::collect_next_hop_in_foreign_network(
|
||||
network_identity.clone(),
|
||||
peer_map.clone(),
|
||||
peer_rpc.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
next_hop.clear();
|
||||
for (k, v) in new_next_hop.into_iter() {
|
||||
next_hop.insert(k, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn collect_next_hop_in_foreign_network(
|
||||
network_identity: NetworkIdentity,
|
||||
peer_map: Arc<PeerMap>,
|
||||
peer_rpc: Arc<PeerRpcManager>,
|
||||
) -> DashMap<PeerId, PeerId> {
|
||||
let peers = peer_map.list_peers().await;
|
||||
let mut tasks = JoinSet::new();
|
||||
if !peers.is_empty() {
|
||||
tracing::warn!(?peers, my_peer_id = ?peer_rpc.my_peer_id(), "collect next hop in foreign network");
|
||||
}
|
||||
for peer in peers {
|
||||
let peer_rpc = peer_rpc.clone();
|
||||
let network_identity = network_identity.clone();
|
||||
tasks.spawn(async move {
|
||||
let Ok(Some(peers_in_foreign)) = peer_rpc
|
||||
.do_client_rpc_scoped(FOREIGN_NETWORK_SERVICE_ID, peer, |c| async {
|
||||
let c =
|
||||
ForeignNetworkServiceClient::new(tarpc::client::Config::default(), c)
|
||||
.spawn();
|
||||
let mut rpc_ctx = tarpc::context::current();
|
||||
rpc_ctx.deadline = SystemTime::now() + Duration::from_secs(2);
|
||||
let ret = c.list_network_peers(rpc_ctx, network_identity).await;
|
||||
ret
|
||||
})
|
||||
.await
|
||||
else {
|
||||
return (peer, vec![]);
|
||||
};
|
||||
|
||||
(peer, peers_in_foreign)
|
||||
});
|
||||
}
|
||||
|
||||
let new_next_hop = DashMap::new();
|
||||
while let Some(join_ret) = tasks.join_next().await {
|
||||
let Ok((gateway, peer_ids)) = join_ret else {
|
||||
tracing::error!(?join_ret, "collect next hop in foreign network failed");
|
||||
continue;
|
||||
};
|
||||
for ret in peer_ids {
|
||||
new_next_hop.insert(ret, gateway);
|
||||
}
|
||||
}
|
||||
|
||||
new_next_hop
|
||||
}
|
||||
|
||||
pub fn has_next_hop(&self, peer_id: PeerId) -> bool {
|
||||
self.get_next_hop(peer_id).is_some()
|
||||
}
|
||||
|
||||
pub fn is_peer_public_node(&self, peer_id: &PeerId) -> bool {
|
||||
self.peer_map.has_peer(*peer_id)
|
||||
pub async fn list_public_peers(&self) -> Vec<PeerId> {
|
||||
self.peer_map.list_peers().await
|
||||
}
|
||||
|
||||
pub fn get_next_hop(&self, peer_id: PeerId) -> Option<PeerId> {
|
||||
if self.peer_map.has_peer(peer_id) {
|
||||
return Some(peer_id.clone());
|
||||
}
|
||||
self.next_hop.get(&peer_id).map(|v| v.clone())
|
||||
None
|
||||
}
|
||||
|
||||
pub async fn send_msg(&self, msg: ZCPacket, peer_id: PeerId) -> Result<(), Error> {
|
||||
@@ -162,40 +68,32 @@ impl ForeignNetworkClient {
|
||||
?next_hop,
|
||||
"foreign network client send msg failed"
|
||||
);
|
||||
} else {
|
||||
tracing::info!(
|
||||
?peer_id,
|
||||
?next_hop,
|
||||
"foreign network client send msg success"
|
||||
);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
Err(Error::RouteError(Some("no next hop".to_string())))
|
||||
}
|
||||
|
||||
pub fn list_foreign_peers(&self) -> Vec<PeerId> {
|
||||
let mut peers = vec![];
|
||||
for item in self.next_hop.iter() {
|
||||
if item.key() != &self.my_peer_id {
|
||||
peers.push(item.key().clone());
|
||||
}
|
||||
}
|
||||
peers
|
||||
}
|
||||
|
||||
pub async fn run(&self) {
|
||||
self.tasks
|
||||
.lock()
|
||||
.await
|
||||
.spawn(Self::collect_next_hop_in_foreign_network_task(
|
||||
self.global_ctx.get_network_identity(),
|
||||
self.peer_map.clone(),
|
||||
self.peer_rpc.clone(),
|
||||
self.next_hop.clone(),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn get_next_hop_table(&self) -> DashMap<PeerId, PeerId> {
|
||||
let next_hop = DashMap::new();
|
||||
for item in self.next_hop.iter() {
|
||||
next_hop.insert(item.key().clone(), item.value().clone());
|
||||
}
|
||||
next_hop
|
||||
let peer_map = Arc::downgrade(&self.peer_map);
|
||||
*self.task.lock().unwrap() = Some(
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||
let Some(peer_map) = peer_map.upgrade() else {
|
||||
break;
|
||||
};
|
||||
peer_map.clean_peer_without_conn().await;
|
||||
}
|
||||
})
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn get_peer_map(&self) -> Arc<PeerMap> {
|
||||
|
||||
@@ -5,12 +5,12 @@ only forward packets of peers that directly connected to this node.
|
||||
in future, with the help wo peer center we can forward packets of peers that
|
||||
connected to any node in the local network.
|
||||
*/
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use dashmap::DashMap;
|
||||
use tokio::{
|
||||
sync::{
|
||||
mpsc::{self, unbounded_channel, UnboundedReceiver, UnboundedSender},
|
||||
mpsc::{self, UnboundedReceiver, UnboundedSender},
|
||||
Mutex,
|
||||
},
|
||||
task::JoinSet,
|
||||
@@ -18,26 +18,35 @@ use tokio::{
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
config::{ConfigLoader, TomlConfigLoader},
|
||||
error::Error,
|
||||
global_ctx::{ArcGlobalCtx, GlobalCtxEvent, NetworkIdentity},
|
||||
global_ctx::{ArcGlobalCtx, GlobalCtx, GlobalCtxEvent, NetworkIdentity},
|
||||
stun::MockStunInfoCollector,
|
||||
PeerId,
|
||||
},
|
||||
rpc::{ForeignNetworkEntryPb, ListForeignNetworkResponse, PeerInfo},
|
||||
peers::route_trait::{Route, RouteInterface},
|
||||
proto::{
|
||||
cli::{ForeignNetworkEntryPb, ListForeignNetworkResponse, PeerInfo},
|
||||
common::NatType,
|
||||
},
|
||||
tunnel::packet_def::{PacketType, ZCPacket},
|
||||
};
|
||||
|
||||
use super::{
|
||||
peer_conn::PeerConn,
|
||||
peer_map::PeerMap,
|
||||
peer_ospf_route::PeerRoute,
|
||||
peer_rpc::{PeerRpcManager, PeerRpcManagerTransport},
|
||||
route_trait::NextHopPolicy,
|
||||
route_trait::{ArcRoute, NextHopPolicy},
|
||||
PacketRecvChan, PacketRecvChanReceiver,
|
||||
};
|
||||
|
||||
struct ForeignNetworkEntry {
|
||||
global_ctx: ArcGlobalCtx,
|
||||
network: NetworkIdentity,
|
||||
peer_map: Arc<PeerMap>,
|
||||
relay_data: bool,
|
||||
route: ArcRoute,
|
||||
}
|
||||
|
||||
impl ForeignNetworkEntry {
|
||||
@@ -47,19 +56,70 @@ impl ForeignNetworkEntry {
|
||||
global_ctx: ArcGlobalCtx,
|
||||
my_peer_id: PeerId,
|
||||
relay_data: bool,
|
||||
peer_rpc: Arc<PeerRpcManager>,
|
||||
) -> Self {
|
||||
let peer_map = Arc::new(PeerMap::new(packet_sender, global_ctx, my_peer_id));
|
||||
let config = TomlConfigLoader::default();
|
||||
config.set_network_identity(network.clone());
|
||||
config.set_hostname(Some(format!("PublicServer_{}", global_ctx.get_hostname())));
|
||||
let foreign_global_ctx = Arc::new(GlobalCtx::new(config));
|
||||
foreign_global_ctx.replace_stun_info_collector(Box::new(MockStunInfoCollector {
|
||||
udp_nat_type: NatType::Unknown,
|
||||
}));
|
||||
|
||||
let peer_map = Arc::new(PeerMap::new(
|
||||
packet_sender,
|
||||
foreign_global_ctx.clone(),
|
||||
my_peer_id,
|
||||
));
|
||||
|
||||
let route = PeerRoute::new(my_peer_id, foreign_global_ctx.clone(), peer_rpc);
|
||||
|
||||
Self {
|
||||
global_ctx: foreign_global_ctx,
|
||||
network,
|
||||
peer_map,
|
||||
relay_data,
|
||||
route: Arc::new(Box::new(route)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn prepare(&self, my_peer_id: PeerId) {
|
||||
struct Interface {
|
||||
my_peer_id: PeerId,
|
||||
peer_map: Weak<PeerMap>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl RouteInterface for Interface {
|
||||
async fn list_peers(&self) -> Vec<PeerId> {
|
||||
let Some(peer_map) = self.peer_map.upgrade() else {
|
||||
return vec![];
|
||||
};
|
||||
|
||||
peer_map.list_peers_with_conn().await
|
||||
}
|
||||
|
||||
fn my_peer_id(&self) -> PeerId {
|
||||
self.my_peer_id
|
||||
}
|
||||
}
|
||||
|
||||
self.route
|
||||
.open(Box::new(Interface {
|
||||
my_peer_id,
|
||||
peer_map: Arc::downgrade(&self.peer_map),
|
||||
}))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
self.peer_map.add_route(self.route.clone()).await;
|
||||
}
|
||||
}
|
||||
|
||||
struct ForeignNetworkManagerData {
|
||||
network_peer_maps: DashMap<String, Arc<ForeignNetworkEntry>>,
|
||||
peer_network_map: DashMap<PeerId, String>,
|
||||
lock: std::sync::Mutex<()>,
|
||||
}
|
||||
|
||||
impl ForeignNetworkManagerData {
|
||||
@@ -88,18 +148,27 @@ impl ForeignNetworkManagerData {
|
||||
self.network_peer_maps.get(network_name).map(|v| v.clone())
|
||||
}
|
||||
|
||||
fn remove_peer(&self, peer_id: PeerId) {
|
||||
fn remove_peer(&self, peer_id: PeerId, network_name: &String) {
|
||||
let _l = self.lock.lock().unwrap();
|
||||
self.peer_network_map.remove(&peer_id);
|
||||
self.network_peer_maps.retain(|_, v| !v.peer_map.is_empty());
|
||||
self.network_peer_maps
|
||||
.remove_if(network_name, |_, v| v.peer_map.is_empty());
|
||||
}
|
||||
|
||||
fn clear_no_conn_peer(&self) {
|
||||
for item in self.network_peer_maps.iter() {
|
||||
let peer_map = item.value().peer_map.clone();
|
||||
tokio::spawn(async move {
|
||||
peer_map.clean_peer_without_conn().await;
|
||||
});
|
||||
}
|
||||
async fn clear_no_conn_peer(&self, network_name: &String) {
|
||||
let peer_map = self
|
||||
.network_peer_maps
|
||||
.get(network_name)
|
||||
.unwrap()
|
||||
.peer_map
|
||||
.clone();
|
||||
peer_map.clean_peer_without_conn().await;
|
||||
}
|
||||
|
||||
fn remove_network(&self, network_name: &String) {
|
||||
let _l = self.lock.lock().unwrap();
|
||||
self.peer_network_map.retain(|_, v| v != network_name);
|
||||
self.network_peer_maps.remove(network_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,11 +186,16 @@ impl PeerRpcManagerTransport for RpcTransport {
|
||||
}
|
||||
|
||||
async fn send(&self, msg: ZCPacket, dst_peer_id: PeerId) -> Result<(), Error> {
|
||||
tracing::debug!(
|
||||
"foreign network manager send rpc to peer: {:?}",
|
||||
dst_peer_id
|
||||
);
|
||||
self.data.send_msg(msg, dst_peer_id).await
|
||||
}
|
||||
|
||||
async fn recv(&self) -> Result<ZCPacket, Error> {
|
||||
if let Some(o) = self.packet_recv.lock().await.recv().await {
|
||||
tracing::info!("recv rpc packet in foreign network manager rpc transport");
|
||||
Ok(o)
|
||||
} else {
|
||||
Err(Error::Unknown)
|
||||
@@ -131,23 +205,6 @@ impl PeerRpcManagerTransport for RpcTransport {
|
||||
|
||||
pub const FOREIGN_NETWORK_SERVICE_ID: u32 = 1;
|
||||
|
||||
#[tarpc::service]
|
||||
pub trait ForeignNetworkService {
|
||||
async fn list_network_peers(network_identy: NetworkIdentity) -> Option<Vec<PeerId>>;
|
||||
}
|
||||
|
||||
#[tarpc::server]
|
||||
impl ForeignNetworkService for Arc<ForeignNetworkManagerData> {
|
||||
async fn list_network_peers(
|
||||
self,
|
||||
_: tarpc::context::Context,
|
||||
network_identy: NetworkIdentity,
|
||||
) -> Option<Vec<PeerId>> {
|
||||
let entry = self.network_peer_maps.get(&network_identy.network_name)?;
|
||||
Some(entry.peer_map.list_peers().await)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ForeignNetworkManager {
|
||||
my_peer_id: PeerId,
|
||||
global_ctx: ArcGlobalCtx,
|
||||
@@ -175,6 +232,7 @@ impl ForeignNetworkManager {
|
||||
let data = Arc::new(ForeignNetworkManagerData {
|
||||
network_peer_maps: DashMap::new(),
|
||||
peer_network_map: DashMap::new(),
|
||||
lock: std::sync::Mutex::new(()),
|
||||
});
|
||||
|
||||
// handle rpc from foreign networks
|
||||
@@ -225,25 +283,39 @@ impl ForeignNetworkManager {
|
||||
return ret;
|
||||
}
|
||||
|
||||
let entry = self
|
||||
.data
|
||||
.network_peer_maps
|
||||
.entry(peer_conn.get_network_identity().network_name.clone())
|
||||
.or_insert_with(|| {
|
||||
Arc::new(ForeignNetworkEntry::new(
|
||||
peer_conn.get_network_identity(),
|
||||
self.packet_sender.clone(),
|
||||
self.global_ctx.clone(),
|
||||
self.my_peer_id,
|
||||
!ret.is_err(),
|
||||
))
|
||||
})
|
||||
.clone();
|
||||
let mut new_added = false;
|
||||
|
||||
self.data.peer_network_map.insert(
|
||||
peer_conn.get_peer_id(),
|
||||
peer_conn.get_network_identity().network_name.clone(),
|
||||
);
|
||||
let entry = {
|
||||
let _l = self.data.lock.lock().unwrap();
|
||||
let entry = self
|
||||
.data
|
||||
.network_peer_maps
|
||||
.entry(peer_conn.get_network_identity().network_name.clone())
|
||||
.or_insert_with(|| {
|
||||
new_added = true;
|
||||
Arc::new(ForeignNetworkEntry::new(
|
||||
peer_conn.get_network_identity(),
|
||||
self.packet_sender.clone(),
|
||||
self.global_ctx.clone(),
|
||||
self.my_peer_id,
|
||||
!ret.is_err(),
|
||||
self.rpc_mgr.clone(),
|
||||
))
|
||||
})
|
||||
.clone();
|
||||
|
||||
self.data.peer_network_map.insert(
|
||||
peer_conn.get_peer_id(),
|
||||
peer_conn.get_network_identity().network_name.clone(),
|
||||
);
|
||||
|
||||
entry
|
||||
};
|
||||
|
||||
if new_added {
|
||||
entry.prepare(self.my_peer_id).await;
|
||||
self.start_event_handler(&entry).await;
|
||||
}
|
||||
|
||||
if entry.network != peer_conn.get_network_identity() {
|
||||
return Err(anyhow::anyhow!(
|
||||
@@ -257,28 +329,26 @@ impl ForeignNetworkManager {
|
||||
Ok(entry.peer_map.add_new_peer_conn(peer_conn).await)
|
||||
}
|
||||
|
||||
async fn start_global_event_handler(&self) {
|
||||
async fn start_event_handler(&self, entry: &ForeignNetworkEntry) {
|
||||
let data = self.data.clone();
|
||||
let mut s = self.global_ctx.subscribe();
|
||||
let (ev_tx, mut ev_rx) = unbounded_channel();
|
||||
let network_name = entry.network.network_name.clone();
|
||||
let mut s = entry.global_ctx.subscribe();
|
||||
self.tasks.lock().await.spawn(async move {
|
||||
while let Ok(e) = s.recv().await {
|
||||
ev_tx.send(e).unwrap();
|
||||
}
|
||||
panic!("global event handler at foreign network manager exit");
|
||||
});
|
||||
|
||||
self.tasks.lock().await.spawn(async move {
|
||||
while let Some(e) = ev_rx.recv().await {
|
||||
if let GlobalCtxEvent::PeerRemoved(peer_id) = &e {
|
||||
tracing::info!(?e, "remove peer from foreign network manager");
|
||||
data.remove_peer(*peer_id);
|
||||
data.remove_peer(*peer_id, &network_name);
|
||||
} else if let GlobalCtxEvent::PeerConnRemoved(..) = &e {
|
||||
tracing::info!(?e, "clear no conn peer from foreign network manager");
|
||||
data.clear_no_conn_peer();
|
||||
data.clear_no_conn_peer(&network_name).await;
|
||||
}
|
||||
}
|
||||
// if lagged or recv done just remove the network
|
||||
tracing::error!("global event handler at foreign network manager exit");
|
||||
data.remove_network(&network_name);
|
||||
});
|
||||
|
||||
self.tasks.lock().await.spawn(async move {});
|
||||
}
|
||||
|
||||
async fn start_packet_recv(&self) {
|
||||
@@ -294,10 +364,14 @@ impl ForeignNetworkManager {
|
||||
tracing::warn!("invalid packet, skip");
|
||||
continue;
|
||||
};
|
||||
tracing::info!(?hdr, "recv packet in foreign network manager");
|
||||
let from_peer_id = hdr.from_peer_id.get();
|
||||
let to_peer_id = hdr.to_peer_id.get();
|
||||
if to_peer_id == my_node_id {
|
||||
if hdr.packet_type == PacketType::TaRpc as u8 {
|
||||
if hdr.packet_type == PacketType::TaRpc as u8
|
||||
|| hdr.packet_type == PacketType::RpcReq as u8
|
||||
|| hdr.packet_type == PacketType::RpcResp as u8
|
||||
{
|
||||
rpc_sender.send(packet_bytes).unwrap();
|
||||
continue;
|
||||
}
|
||||
@@ -335,16 +409,9 @@ impl ForeignNetworkManager {
|
||||
});
|
||||
}
|
||||
|
||||
async fn register_peer_rpc_service(&self) {
|
||||
self.rpc_mgr.run();
|
||||
self.rpc_mgr
|
||||
.run_service(FOREIGN_NETWORK_SERVICE_ID, self.data.clone().serve())
|
||||
}
|
||||
|
||||
pub async fn run(&self) {
|
||||
self.start_global_event_handler().await;
|
||||
self.start_packet_recv().await;
|
||||
self.register_peer_rpc_service().await;
|
||||
self.rpc_mgr.run();
|
||||
}
|
||||
|
||||
pub async fn list_foreign_networks(&self) -> ListForeignNetworkResponse {
|
||||
@@ -380,8 +447,17 @@ impl ForeignNetworkManager {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ForeignNetworkManager {
|
||||
fn drop(&mut self) {
|
||||
self.data.peer_network_map.clear();
|
||||
self.data.network_peer_maps.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{
|
||||
common::global_ctx::tests::get_mock_global_ctx_with_network,
|
||||
connector::udp_hole_punch::tests::{
|
||||
@@ -391,7 +467,8 @@ mod tests {
|
||||
peer_manager::{PeerManager, RouteAlgoType},
|
||||
tests::{connect_peer_manager, wait_route_appear},
|
||||
},
|
||||
rpc::NatType,
|
||||
proto::common::NatType,
|
||||
tunnel::common::tests::wait_for_condition,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
@@ -413,7 +490,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn foreign_network_basic() {
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(crate::rpc::NatType::Unknown).await;
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
tracing::debug!("pm_center: {:?}", pm_center.my_peer_id());
|
||||
|
||||
let pma_net1 = create_mock_peer_manager_for_foreign_network("net1").await;
|
||||
@@ -428,8 +505,10 @@ mod tests {
|
||||
wait_route_appear(pma_net1.clone(), pmb_net1.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(1, pma_net1.list_routes().await.len());
|
||||
assert_eq!(1, pmb_net1.list_routes().await.len());
|
||||
assert_eq!(2, pma_net1.list_routes().await.len());
|
||||
assert_eq!(2, pmb_net1.list_routes().await.len());
|
||||
|
||||
println!("{:?}", pmb_net1.list_routes().await);
|
||||
|
||||
let rpc_resp = pm_center
|
||||
.get_foreign_network_manager()
|
||||
@@ -440,7 +519,7 @@ mod tests {
|
||||
}
|
||||
|
||||
async fn foreign_network_whitelist_helper(name: String) {
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(crate::rpc::NatType::Unknown).await;
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
tracing::debug!("pm_center: {:?}", pm_center.my_peer_id());
|
||||
let mut flag = pm_center.get_global_ctx().get_flags();
|
||||
flag.foreign_network_whitelist = vec!["net1".to_string(), "net2*".to_string()].join(" ");
|
||||
@@ -466,7 +545,7 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn only_relay_peer_rpc() {
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(crate::rpc::NatType::Unknown).await;
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
let mut flag = pm_center.get_global_ctx().get_flags();
|
||||
flag.foreign_network_whitelist = "".to_string();
|
||||
flag.relay_all_peer_rpc = true;
|
||||
@@ -485,8 +564,8 @@ mod tests {
|
||||
wait_route_appear(pma_net1.clone(), pmb_net1.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(1, pma_net1.list_routes().await.len());
|
||||
assert_eq!(1, pmb_net1.list_routes().await.len());
|
||||
assert_eq!(2, pma_net1.list_routes().await.len());
|
||||
assert_eq!(2, pmb_net1.list_routes().await.len());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -497,9 +576,8 @@ mod tests {
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_foreign_network_manager() {
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(crate::rpc::NatType::Unknown).await;
|
||||
let pm_center2 =
|
||||
create_mock_peer_manager_with_mock_stun(crate::rpc::NatType::Unknown).await;
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
let pm_center2 = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
connect_peer_manager(pm_center.clone(), pm_center2.clone()).await;
|
||||
|
||||
tracing::debug!(
|
||||
@@ -519,17 +597,9 @@ mod tests {
|
||||
pmb_net1.my_peer_id()
|
||||
);
|
||||
|
||||
let now = std::time::Instant::now();
|
||||
let mut succ = false;
|
||||
while now.elapsed().as_secs() < 10 {
|
||||
let table = pma_net1.get_foreign_network_client().get_next_hop_table();
|
||||
if table.len() >= 1 {
|
||||
succ = true;
|
||||
break;
|
||||
}
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
}
|
||||
assert!(succ);
|
||||
wait_route_appear(pma_net1.clone(), pmb_net1.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
vec![pm_center.my_peer_id()],
|
||||
@@ -547,11 +617,9 @@ mod tests {
|
||||
.list_peers()
|
||||
.await
|
||||
);
|
||||
wait_route_appear(pma_net1.clone(), pmb_net1.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(1, pma_net1.list_routes().await.len());
|
||||
assert_eq!(1, pmb_net1.list_routes().await.len());
|
||||
|
||||
assert_eq!(2, pma_net1.list_routes().await.len());
|
||||
assert_eq!(2, pmb_net1.list_routes().await.len());
|
||||
|
||||
let pmc_net1 = create_mock_peer_manager_for_foreign_network("net1").await;
|
||||
connect_peer_manager(pmc_net1.clone(), pm_center.clone()).await;
|
||||
@@ -561,7 +629,7 @@ mod tests {
|
||||
wait_route_appear(pmb_net1.clone(), pmc_net1.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(2, pmc_net1.list_routes().await.len());
|
||||
assert_eq!(3, pmc_net1.list_routes().await.len());
|
||||
|
||||
tracing::debug!("pmc_net1: {:?}", pmc_net1.my_peer_id());
|
||||
|
||||
@@ -577,8 +645,8 @@ mod tests {
|
||||
wait_route_appear(pma_net2.clone(), pmb_net2.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(1, pma_net2.list_routes().await.len());
|
||||
assert_eq!(1, pmb_net2.list_routes().await.len());
|
||||
assert_eq!(2, pma_net2.list_routes().await.len());
|
||||
assert_eq!(2, pmb_net2.list_routes().await.len());
|
||||
|
||||
assert_eq!(
|
||||
5,
|
||||
@@ -635,4 +703,27 @@ mod tests {
|
||||
.len()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_disconnect_foreign_network() {
|
||||
let pm_center = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
tracing::debug!("pm_center: {:?}", pm_center.my_peer_id());
|
||||
let pma_net1 = create_mock_peer_manager_for_foreign_network("net1").await;
|
||||
tracing::debug!("pma_net1: {:?}", pma_net1.my_peer_id(),);
|
||||
|
||||
connect_peer_manager(pma_net1.clone(), pm_center.clone()).await;
|
||||
|
||||
wait_for_condition(
|
||||
|| async { pma_net1.list_routes().await.len() == 1 },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
|
||||
drop(pm_center);
|
||||
wait_for_condition(
|
||||
|| async { pma_net1.list_routes().await.len() == 0 },
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ pub mod peer_conn_ping;
|
||||
pub mod peer_manager;
|
||||
pub mod peer_map;
|
||||
pub mod peer_ospf_route;
|
||||
pub mod peer_rip_route;
|
||||
pub mod peer_rpc;
|
||||
pub mod route_trait;
|
||||
pub mod rpc_service;
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::{
|
||||
peer_conn::{PeerConn, PeerConnId},
|
||||
PacketRecvChan,
|
||||
};
|
||||
use crate::rpc::PeerConnInfo;
|
||||
use crate::proto::cli::PeerConnInfo;
|
||||
use crate::{
|
||||
common::{
|
||||
error::Error,
|
||||
|
||||
@@ -29,8 +29,18 @@ use crate::{
|
||||
global_ctx::ArcGlobalCtx,
|
||||
PeerId,
|
||||
},
|
||||
rpc::{HandshakeRequest, PeerConnInfo, PeerConnStats, TunnelInfo},
|
||||
tunnel::{filter::{StatsRecorderTunnelFilter, TunnelFilter, TunnelWithFilter}, mpsc::{MpscTunnel, MpscTunnelSender}, packet_def::{PacketType, ZCPacket}, stats::{Throughput, WindowLatency}, Tunnel, TunnelError, ZCPacketStream},
|
||||
proto::{
|
||||
cli::{PeerConnInfo, PeerConnStats},
|
||||
common::TunnelInfo,
|
||||
peer_rpc::HandshakeRequest,
|
||||
},
|
||||
tunnel::{
|
||||
filter::{StatsRecorderTunnelFilter, TunnelFilter, TunnelWithFilter},
|
||||
mpsc::{MpscTunnel, MpscTunnelSender},
|
||||
packet_def::{PacketType, ZCPacket},
|
||||
stats::{Throughput, WindowLatency},
|
||||
Tunnel, TunnelError, ZCPacketStream,
|
||||
},
|
||||
};
|
||||
|
||||
use super::{peer_conn_ping::PeerConnPinger, PacketRecvChan};
|
||||
|
||||
@@ -17,7 +17,6 @@ use tokio::{
|
||||
task::JoinSet,
|
||||
};
|
||||
use tokio_stream::wrappers::ReceiverStream;
|
||||
use tokio_util::bytes::Bytes;
|
||||
|
||||
use crate::{
|
||||
common::{error::Error, global_ctx::ArcGlobalCtx, stun::StunInfoCollectorTrait, PeerId},
|
||||
@@ -27,6 +26,7 @@ use crate::{
|
||||
route_trait::{NextHopPolicy, RouteInterface},
|
||||
PeerPacketFilter,
|
||||
},
|
||||
proto::cli,
|
||||
tunnel::{
|
||||
self,
|
||||
packet_def::{PacketType, ZCPacket},
|
||||
@@ -41,7 +41,6 @@ use super::{
|
||||
peer_conn::PeerConnId,
|
||||
peer_map::PeerMap,
|
||||
peer_ospf_route::PeerRoute,
|
||||
peer_rip_route::BasicRoute,
|
||||
peer_rpc::PeerRpcManager,
|
||||
route_trait::{ArcRoute, Route},
|
||||
BoxNicPacketFilter, BoxPeerPacketFilter, PacketRecvChanReceiver,
|
||||
@@ -75,7 +74,15 @@ impl PeerRpcManagerTransport for RpcTransport {
|
||||
.ok_or(Error::Unknown)?;
|
||||
let peers = self.peers.upgrade().ok_or(Error::Unknown)?;
|
||||
|
||||
if let Some(gateway_id) = peers
|
||||
if foreign_peers.has_next_hop(dst_peer_id) {
|
||||
// do not encrypt for data sending to public server
|
||||
tracing::debug!(
|
||||
?dst_peer_id,
|
||||
?self.my_peer_id,
|
||||
"failed to send msg to peer, try foreign network",
|
||||
);
|
||||
foreign_peers.send_msg(msg, dst_peer_id).await
|
||||
} else if let Some(gateway_id) = peers
|
||||
.get_gateway_peer_id(dst_peer_id, NextHopPolicy::LeastHop)
|
||||
.await
|
||||
{
|
||||
@@ -88,20 +95,11 @@ impl PeerRpcManagerTransport for RpcTransport {
|
||||
self.encryptor
|
||||
.encrypt(&mut msg)
|
||||
.with_context(|| "encrypt failed")?;
|
||||
peers.send_msg_directly(msg, gateway_id).await
|
||||
} else if foreign_peers.has_next_hop(dst_peer_id) {
|
||||
if !foreign_peers.is_peer_public_node(&dst_peer_id) {
|
||||
// do not encrypt for msg sending to public node
|
||||
self.encryptor
|
||||
.encrypt(&mut msg)
|
||||
.with_context(|| "encrypt failed")?;
|
||||
if peers.has_peer(gateway_id) {
|
||||
peers.send_msg_directly(msg, gateway_id).await
|
||||
} else {
|
||||
foreign_peers.send_msg(msg, gateway_id).await
|
||||
}
|
||||
tracing::debug!(
|
||||
?dst_peer_id,
|
||||
?self.my_peer_id,
|
||||
"failed to send msg to peer, try foreign network",
|
||||
);
|
||||
foreign_peers.send_msg(msg, dst_peer_id).await
|
||||
} else {
|
||||
Err(Error::RouteError(Some(format!(
|
||||
"peermgr RpcTransport no route for dst_peer_id: {}",
|
||||
@@ -120,13 +118,11 @@ impl PeerRpcManagerTransport for RpcTransport {
|
||||
}
|
||||
|
||||
pub enum RouteAlgoType {
|
||||
Rip,
|
||||
Ospf,
|
||||
None,
|
||||
}
|
||||
|
||||
enum RouteAlgoInst {
|
||||
Rip(Arc<BasicRoute>),
|
||||
Ospf(Arc<PeerRoute>),
|
||||
None,
|
||||
}
|
||||
@@ -217,9 +213,6 @@ impl PeerManager {
|
||||
let peer_rpc_mgr = Arc::new(PeerRpcManager::new(rpc_tspt.clone()));
|
||||
|
||||
let route_algo_inst = match route_algo {
|
||||
RouteAlgoType::Rip => {
|
||||
RouteAlgoInst::Rip(Arc::new(BasicRoute::new(my_peer_id, global_ctx.clone())))
|
||||
}
|
||||
RouteAlgoType::Ospf => RouteAlgoInst::Ospf(PeerRoute::new(
|
||||
my_peer_id,
|
||||
global_ctx.clone(),
|
||||
@@ -438,7 +431,10 @@ impl PeerManager {
|
||||
impl PeerPacketFilter for PeerRpcPacketProcessor {
|
||||
async fn try_process_packet_from_peer(&self, packet: ZCPacket) -> Option<ZCPacket> {
|
||||
let hdr = packet.peer_manager_header().unwrap();
|
||||
if hdr.packet_type == PacketType::TaRpc as u8 {
|
||||
if hdr.packet_type == PacketType::TaRpc as u8
|
||||
|| hdr.packet_type == PacketType::RpcReq as u8
|
||||
|| hdr.packet_type == PacketType::RpcResp as u8
|
||||
{
|
||||
self.peer_rpc_tspt_sender.send(packet).unwrap();
|
||||
None
|
||||
} else {
|
||||
@@ -477,33 +473,11 @@ impl PeerManager {
|
||||
return vec![];
|
||||
};
|
||||
|
||||
let mut peers = foreign_client.list_foreign_peers();
|
||||
let mut peers = foreign_client.list_public_peers().await;
|
||||
peers.extend(peer_map.list_peers_with_conn().await);
|
||||
peers
|
||||
}
|
||||
async fn send_route_packet(
|
||||
&self,
|
||||
msg: Bytes,
|
||||
_route_id: u8,
|
||||
dst_peer_id: PeerId,
|
||||
) -> Result<(), Error> {
|
||||
let foreign_client = self
|
||||
.foreign_network_client
|
||||
.upgrade()
|
||||
.ok_or(Error::Unknown)?;
|
||||
let peer_map = self.peers.upgrade().ok_or(Error::Unknown)?;
|
||||
let mut zc_packet = ZCPacket::new_with_payload(&msg);
|
||||
zc_packet.fill_peer_manager_hdr(
|
||||
self.my_peer_id,
|
||||
dst_peer_id,
|
||||
PacketType::Route as u8,
|
||||
);
|
||||
if foreign_client.has_next_hop(dst_peer_id) {
|
||||
foreign_client.send_msg(zc_packet, dst_peer_id).await
|
||||
} else {
|
||||
peer_map.send_msg_directly(zc_packet, dst_peer_id).await
|
||||
}
|
||||
}
|
||||
|
||||
fn my_peer_id(&self) -> PeerId {
|
||||
self.my_peer_id
|
||||
}
|
||||
@@ -525,13 +499,12 @@ impl PeerManager {
|
||||
|
||||
pub fn get_route(&self) -> Box<dyn Route + Send + Sync + 'static> {
|
||||
match &self.route_algo_inst {
|
||||
RouteAlgoInst::Rip(route) => Box::new(route.clone()),
|
||||
RouteAlgoInst::Ospf(route) => Box::new(route.clone()),
|
||||
RouteAlgoInst::None => panic!("no route"),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_routes(&self) -> Vec<crate::rpc::Route> {
|
||||
pub async fn list_routes(&self) -> Vec<cli::Route> {
|
||||
self.get_route().list_routes().await
|
||||
}
|
||||
|
||||
@@ -649,13 +622,23 @@ impl PeerManager {
|
||||
.get_gateway_peer_id(*peer_id, next_hop_policy.clone())
|
||||
.await
|
||||
{
|
||||
if let Err(e) = self.peers.send_msg_directly(msg, gateway).await {
|
||||
errs.push(e);
|
||||
}
|
||||
} else if self.foreign_network_client.has_next_hop(*peer_id) {
|
||||
if let Err(e) = self.foreign_network_client.send_msg(msg, *peer_id).await {
|
||||
errs.push(e);
|
||||
if self.peers.has_peer(gateway) {
|
||||
if let Err(e) = self.peers.send_msg_directly(msg, gateway).await {
|
||||
errs.push(e);
|
||||
}
|
||||
} else if self.foreign_network_client.has_next_hop(gateway) {
|
||||
if let Err(e) = self.foreign_network_client.send_msg(msg, gateway).await {
|
||||
errs.push(e);
|
||||
}
|
||||
} else {
|
||||
tracing::warn!(
|
||||
?gateway,
|
||||
?peer_id,
|
||||
"cannot send msg to peer through gateway"
|
||||
);
|
||||
}
|
||||
} else {
|
||||
tracing::debug!(?peer_id, "no gateway for peer");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,7 +676,6 @@ impl PeerManager {
|
||||
pub async fn run(&self) -> Result<(), Error> {
|
||||
match &self.route_algo_inst {
|
||||
RouteAlgoInst::Ospf(route) => self.add_route(route.clone()).await,
|
||||
RouteAlgoInst::Rip(route) => self.add_route(route.clone()).await,
|
||||
RouteAlgoInst::None => {}
|
||||
};
|
||||
|
||||
@@ -732,13 +714,6 @@ impl PeerManager {
|
||||
self.nic_channel.clone()
|
||||
}
|
||||
|
||||
pub fn get_basic_route(&self) -> Arc<BasicRoute> {
|
||||
match &self.route_algo_inst {
|
||||
RouteAlgoInst::Rip(route) => route.clone(),
|
||||
_ => panic!("not rip route"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_foreign_network_manager(&self) -> Arc<ForeignNetworkManager> {
|
||||
self.foreign_network_manager.clone()
|
||||
}
|
||||
@@ -747,8 +722,8 @@ impl PeerManager {
|
||||
self.foreign_network_client.clone()
|
||||
}
|
||||
|
||||
pub fn get_my_info(&self) -> crate::rpc::NodeInfo {
|
||||
crate::rpc::NodeInfo {
|
||||
pub fn get_my_info(&self) -> cli::NodeInfo {
|
||||
cli::NodeInfo {
|
||||
peer_id: self.my_peer_id,
|
||||
ipv4_addr: self
|
||||
.global_ctx
|
||||
@@ -774,6 +749,12 @@ impl PeerManager {
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait(&self) {
|
||||
while !self.tasks.lock().await.is_empty() {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -789,12 +770,11 @@ mod tests {
|
||||
instance::listeners::get_listener_by_url,
|
||||
peers::{
|
||||
peer_manager::RouteAlgoType,
|
||||
peer_rpc::tests::{MockService, TestRpcService, TestRpcServiceClient},
|
||||
peer_rpc::tests::register_service,
|
||||
tests::{connect_peer_manager, wait_route_appear},
|
||||
},
|
||||
rpc::NatType,
|
||||
tunnel::common::tests::wait_for_condition,
|
||||
tunnel::{TunnelConnector, TunnelListener},
|
||||
proto::common::NatType,
|
||||
tunnel::{common::tests::wait_for_condition, TunnelConnector, TunnelListener},
|
||||
};
|
||||
|
||||
use super::PeerManager;
|
||||
@@ -857,25 +837,18 @@ mod tests {
|
||||
#[values("tcp", "udp", "wg", "quic")] proto1: &str,
|
||||
#[values("tcp", "udp", "wg", "quic")] proto2: &str,
|
||||
) {
|
||||
use crate::proto::{
|
||||
rpc_impl::RpcController,
|
||||
tests::{GreetingClientFactory, SayHelloRequest},
|
||||
};
|
||||
|
||||
let peer_mgr_a = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
peer_mgr_a.get_peer_rpc_mgr().run_service(
|
||||
100,
|
||||
MockService {
|
||||
prefix: "hello a".to_owned(),
|
||||
}
|
||||
.serve(),
|
||||
);
|
||||
register_service(&peer_mgr_a.peer_rpc_mgr, "", 0, "hello a");
|
||||
|
||||
let peer_mgr_b = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
|
||||
let peer_mgr_c = create_mock_peer_manager_with_mock_stun(NatType::Unknown).await;
|
||||
peer_mgr_c.get_peer_rpc_mgr().run_service(
|
||||
100,
|
||||
MockService {
|
||||
prefix: "hello c".to_owned(),
|
||||
}
|
||||
.serve(),
|
||||
);
|
||||
register_service(&peer_mgr_c.peer_rpc_mgr, "", 0, "hello c");
|
||||
|
||||
let mut listener1 = get_listener_by_url(
|
||||
&format!("{}://0.0.0.0:31013", proto1).parse().unwrap(),
|
||||
@@ -913,16 +886,26 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let ret = peer_mgr_a
|
||||
.get_peer_rpc_mgr()
|
||||
.do_client_rpc_scoped(100, peer_mgr_c.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), "abc".to_owned()).await;
|
||||
ret
|
||||
})
|
||||
let stub = peer_mgr_a
|
||||
.peer_rpc_mgr
|
||||
.rpc_client()
|
||||
.scoped_client::<GreetingClientFactory<RpcController>>(
|
||||
peer_mgr_a.my_peer_id,
|
||||
peer_mgr_c.my_peer_id,
|
||||
"".to_string(),
|
||||
);
|
||||
|
||||
let ret = stub
|
||||
.say_hello(
|
||||
RpcController {},
|
||||
SayHelloRequest {
|
||||
name: "abc".to_string(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(ret, "hello c abc");
|
||||
|
||||
assert_eq!(ret.greeting, "hello c abc!");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
global_ctx::{ArcGlobalCtx, GlobalCtxEvent},
|
||||
PeerId,
|
||||
},
|
||||
rpc::PeerConnInfo,
|
||||
proto::cli::PeerConnInfo,
|
||||
tunnel::packet_def::ZCPacket,
|
||||
tunnel::TunnelError,
|
||||
};
|
||||
@@ -66,7 +66,7 @@ impl PeerMap {
|
||||
}
|
||||
|
||||
pub fn has_peer(&self, peer_id: PeerId) -> bool {
|
||||
self.peer_map.contains_key(&peer_id)
|
||||
peer_id == self.my_peer_id || self.peer_map.contains_key(&peer_id)
|
||||
}
|
||||
|
||||
pub async fn send_msg_directly(&self, msg: ZCPacket, dst_peer_id: PeerId) -> Result<(), Error> {
|
||||
@@ -113,10 +113,8 @@ impl PeerMap {
|
||||
.get_next_hop_with_policy(dst_peer_id, policy.clone())
|
||||
.await
|
||||
{
|
||||
// for foreign network, gateway_peer_id may not connect to me
|
||||
if self.has_peer(gateway_peer_id) {
|
||||
return Some(gateway_peer_id);
|
||||
}
|
||||
// NOTIC: for foreign network, gateway_peer_id may not connect to me
|
||||
return Some(gateway_peer_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,18 @@ use tokio::{
|
||||
use crate::{
|
||||
common::{global_ctx::ArcGlobalCtx, stun::StunInfoCollectorTrait, PeerId},
|
||||
peers::route_trait::{Route, RouteInterfaceBox},
|
||||
rpc::{NatType, StunInfo},
|
||||
proto::common::{NatType, StunInfo},
|
||||
proto::{
|
||||
peer_rpc::{
|
||||
OspfRouteRpc, OspfRouteRpcClientFactory, OspfRouteRpcServer, PeerIdVersion,
|
||||
RoutePeerInfo, RoutePeerInfos, SyncRouteInfoError, SyncRouteInfoRequest,
|
||||
SyncRouteInfoResponse,
|
||||
},
|
||||
rpc_types::{
|
||||
self,
|
||||
controller::{BaseController, Controller},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -76,31 +87,17 @@ impl From<Version> for AtomicVersion {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
|
||||
struct RoutePeerInfo {
|
||||
// means next hop in route table.
|
||||
peer_id: PeerId,
|
||||
inst_id: uuid::Uuid,
|
||||
cost: u8,
|
||||
ipv4_addr: Option<Ipv4Addr>,
|
||||
proxy_cidrs: Vec<String>,
|
||||
hostname: Option<String>,
|
||||
udp_stun_info: i8,
|
||||
last_update: SystemTime,
|
||||
version: Version,
|
||||
}
|
||||
|
||||
impl RoutePeerInfo {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
peer_id: 0,
|
||||
inst_id: uuid::Uuid::nil(),
|
||||
inst_id: Some(uuid::Uuid::nil().into()),
|
||||
cost: 0,
|
||||
ipv4_addr: None,
|
||||
proxy_cidrs: Vec::new(),
|
||||
hostname: None,
|
||||
udp_stun_info: 0,
|
||||
last_update: SystemTime::now(),
|
||||
last_update: Some(SystemTime::now().into()),
|
||||
version: 0,
|
||||
}
|
||||
}
|
||||
@@ -108,9 +105,9 @@ impl RoutePeerInfo {
|
||||
pub fn update_self(&self, my_peer_id: PeerId, global_ctx: &ArcGlobalCtx) -> Self {
|
||||
let mut new = Self {
|
||||
peer_id: my_peer_id,
|
||||
inst_id: global_ctx.get_id(),
|
||||
inst_id: Some(global_ctx.get_id().into()),
|
||||
cost: 0,
|
||||
ipv4_addr: global_ctx.get_ipv4(),
|
||||
ipv4_addr: global_ctx.get_ipv4().map(|x| x.into()),
|
||||
proxy_cidrs: global_ctx
|
||||
.get_proxy_cidrs()
|
||||
.iter()
|
||||
@@ -121,20 +118,22 @@ impl RoutePeerInfo {
|
||||
udp_stun_info: global_ctx
|
||||
.get_stun_info_collector()
|
||||
.get_stun_info()
|
||||
.udp_nat_type as i8,
|
||||
.udp_nat_type,
|
||||
// following fields do not participate in comparison.
|
||||
last_update: self.last_update,
|
||||
version: self.version,
|
||||
};
|
||||
|
||||
let need_update_periodically = if let Ok(d) = new.last_update.elapsed() {
|
||||
let need_update_periodically = if let Ok(Ok(d)) =
|
||||
SystemTime::try_from(new.last_update.unwrap()).map(|x| x.elapsed())
|
||||
{
|
||||
d > UPDATE_PEER_INFO_PERIOD
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if new != *self || need_update_periodically {
|
||||
new.last_update = SystemTime::now();
|
||||
new.last_update = Some(SystemTime::now().into());
|
||||
new.version += 1;
|
||||
}
|
||||
|
||||
@@ -142,9 +141,9 @@ impl RoutePeerInfo {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<crate::rpc::Route> for RoutePeerInfo {
|
||||
fn into(self) -> crate::rpc::Route {
|
||||
crate::rpc::Route {
|
||||
impl Into<crate::proto::cli::Route> for RoutePeerInfo {
|
||||
fn into(self) -> crate::proto::cli::Route {
|
||||
crate::proto::cli::Route {
|
||||
peer_id: self.peer_id,
|
||||
ipv4_addr: if let Some(ipv4_addr) = self.ipv4_addr {
|
||||
ipv4_addr.to_string()
|
||||
@@ -162,7 +161,7 @@ impl Into<crate::rpc::Route> for RoutePeerInfo {
|
||||
}
|
||||
Some(stun_info)
|
||||
},
|
||||
inst_id: self.inst_id.to_string(),
|
||||
inst_id: self.inst_id.map(|x| x.to_string()).unwrap_or_default(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
}
|
||||
}
|
||||
@@ -174,6 +173,35 @@ struct RouteConnBitmap {
|
||||
bitmap: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Into<crate::proto::peer_rpc::RouteConnBitmap> for RouteConnBitmap {
|
||||
fn into(self) -> crate::proto::peer_rpc::RouteConnBitmap {
|
||||
crate::proto::peer_rpc::RouteConnBitmap {
|
||||
peer_ids: self
|
||||
.peer_ids
|
||||
.into_iter()
|
||||
.map(|x| PeerIdVersion {
|
||||
peer_id: x.0,
|
||||
version: x.1,
|
||||
})
|
||||
.collect(),
|
||||
bitmap: self.bitmap,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::proto::peer_rpc::RouteConnBitmap> for RouteConnBitmap {
|
||||
fn from(v: crate::proto::peer_rpc::RouteConnBitmap) -> Self {
|
||||
RouteConnBitmap {
|
||||
peer_ids: v
|
||||
.peer_ids
|
||||
.into_iter()
|
||||
.map(|x| (x.peer_id, x.version))
|
||||
.collect(),
|
||||
bitmap: v.bitmap,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RouteConnBitmap {
|
||||
fn new() -> Self {
|
||||
RouteConnBitmap {
|
||||
@@ -200,28 +228,7 @@ impl RouteConnBitmap {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
enum Error {
|
||||
DuplicatePeerId,
|
||||
Stopped,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
struct SyncRouteInfoResponse {
|
||||
is_initiator: bool,
|
||||
session_id: SessionId,
|
||||
}
|
||||
|
||||
#[tarpc::service]
|
||||
trait RouteService {
|
||||
async fn sync_route_info(
|
||||
my_peer_id: PeerId,
|
||||
my_session_id: SessionId,
|
||||
is_initiator: bool,
|
||||
peer_infos: Option<Vec<RoutePeerInfo>>,
|
||||
conn_bitmap: Option<RouteConnBitmap>,
|
||||
) -> Result<SyncRouteInfoResponse, Error>;
|
||||
}
|
||||
type Error = SyncRouteInfoError;
|
||||
|
||||
// constructed with all infos synced from all peers.
|
||||
#[derive(Debug)]
|
||||
@@ -299,7 +306,7 @@ impl SyncedRouteInfo {
|
||||
for mut route_info in peer_infos.iter().map(Clone::clone) {
|
||||
// time between peers may not be synchronized, so update last_update to local now.
|
||||
// note only last_update with larger version will be updated to local saved peer info.
|
||||
route_info.last_update = SystemTime::now();
|
||||
route_info.last_update = Some(SystemTime::now().into());
|
||||
|
||||
self.peer_infos
|
||||
.entry(route_info.peer_id)
|
||||
@@ -581,7 +588,7 @@ impl RouteTable {
|
||||
let info = item.value();
|
||||
|
||||
if let Some(ipv4_addr) = info.ipv4_addr {
|
||||
self.ipv4_peer_id_map.insert(ipv4_addr, *peer_id);
|
||||
self.ipv4_peer_id_map.insert(ipv4_addr.into(), *peer_id);
|
||||
}
|
||||
|
||||
for cidr in info.proxy_cidrs.iter() {
|
||||
@@ -996,7 +1003,8 @@ impl PeerRouteServiceImpl {
|
||||
let now = SystemTime::now();
|
||||
let mut to_remove = Vec::new();
|
||||
for item in self.synced_route_info.peer_infos.iter() {
|
||||
if let Ok(d) = now.duration_since(item.value().last_update) {
|
||||
if let Ok(d) = now.duration_since(item.value().last_update.unwrap().try_into().unwrap())
|
||||
{
|
||||
if d > REMOVE_DEAD_PEER_INFO_AFTER {
|
||||
to_remove.push(*item.key());
|
||||
}
|
||||
@@ -1021,7 +1029,7 @@ impl PeerRouteServiceImpl {
|
||||
let my_peer_id = self.my_peer_id;
|
||||
|
||||
let (peer_infos, conn_bitmap) = self.build_sync_request(&session);
|
||||
tracing::info!("my_id {:?}, pper_id: {:?}, peer_infos: {:?}, conn_bitmap: {:?}, synced_route_info: {:?} session: {:?}",
|
||||
tracing::info!("building sync_route request. my_id {:?}, pper_id: {:?}, peer_infos: {:?}, conn_bitmap: {:?}, synced_route_info: {:?} session: {:?}",
|
||||
my_peer_id, dst_peer_id, peer_infos, conn_bitmap, self.synced_route_info, session);
|
||||
|
||||
if peer_infos.is_none()
|
||||
@@ -1035,33 +1043,60 @@ impl PeerRouteServiceImpl {
|
||||
.need_sync_initiator_info
|
||||
.store(false, Ordering::Relaxed);
|
||||
|
||||
let ret = peer_rpc
|
||||
.do_client_rpc_scoped(SERVICE_ID, dst_peer_id, |c| async {
|
||||
let client = RouteServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let mut rpc_ctx = tarpc::context::current();
|
||||
rpc_ctx.deadline = SystemTime::now() + Duration::from_secs(3);
|
||||
client
|
||||
.sync_route_info(
|
||||
rpc_ctx,
|
||||
my_peer_id,
|
||||
session.my_session_id.load(Ordering::Relaxed),
|
||||
session.we_are_initiator.load(Ordering::Relaxed),
|
||||
peer_infos.clone(),
|
||||
conn_bitmap.clone(),
|
||||
)
|
||||
.await
|
||||
})
|
||||
let rpc_stub = peer_rpc
|
||||
.rpc_client()
|
||||
.scoped_client::<OspfRouteRpcClientFactory<BaseController>>(
|
||||
self.my_peer_id,
|
||||
dst_peer_id,
|
||||
self.global_ctx.get_network_name(),
|
||||
);
|
||||
|
||||
let mut ctrl = BaseController {};
|
||||
ctrl.set_timeout_ms(3000);
|
||||
let ret = rpc_stub
|
||||
.sync_route_info(
|
||||
ctrl,
|
||||
SyncRouteInfoRequest {
|
||||
my_peer_id,
|
||||
my_session_id: session.my_session_id.load(Ordering::Relaxed),
|
||||
is_initiator: session.we_are_initiator.load(Ordering::Relaxed),
|
||||
peer_infos: peer_infos.clone().map(|x| RoutePeerInfos { items: x }),
|
||||
conn_bitmap: conn_bitmap.clone().map(Into::into),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
match ret {
|
||||
Ok(Ok(ret)) => {
|
||||
if let Err(e) = &ret {
|
||||
tracing::error!(
|
||||
?ret,
|
||||
?my_peer_id,
|
||||
?dst_peer_id,
|
||||
?e,
|
||||
"sync_route_info failed"
|
||||
);
|
||||
session
|
||||
.need_sync_initiator_info
|
||||
.store(true, Ordering::Relaxed);
|
||||
} else {
|
||||
let resp = ret.as_ref().unwrap();
|
||||
if resp.error.is_some() {
|
||||
let err = resp.error.unwrap();
|
||||
if err == Error::DuplicatePeerId as i32 {
|
||||
panic!("duplicate peer id");
|
||||
} else {
|
||||
tracing::error!(?ret, ?my_peer_id, ?dst_peer_id, "sync_route_info failed");
|
||||
session
|
||||
.need_sync_initiator_info
|
||||
.store(true, Ordering::Relaxed);
|
||||
}
|
||||
} else {
|
||||
session.rpc_tx_count.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
session
|
||||
.dst_is_initiator
|
||||
.store(ret.is_initiator, Ordering::Relaxed);
|
||||
.store(resp.is_initiator, Ordering::Relaxed);
|
||||
|
||||
session.update_dst_session_id(ret.session_id);
|
||||
session.update_dst_session_id(resp.session_id);
|
||||
|
||||
if let Some(peer_infos) = &peer_infos {
|
||||
session.update_dst_saved_peer_info_version(&peer_infos);
|
||||
@@ -1071,17 +1106,6 @@ impl PeerRouteServiceImpl {
|
||||
session.update_dst_saved_conn_bitmap_version(&conn_bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Err(Error::DuplicatePeerId)) => {
|
||||
panic!("duplicate peer id");
|
||||
}
|
||||
|
||||
_ => {
|
||||
tracing::error!(?ret, ?my_peer_id, ?dst_peer_id, "sync_route_info failed");
|
||||
session
|
||||
.need_sync_initiator_info
|
||||
.store(true, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1103,59 +1127,37 @@ impl Debug for RouteSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
#[tarpc::server]
|
||||
impl RouteService for RouteSessionManager {
|
||||
#[async_trait::async_trait]
|
||||
impl OspfRouteRpc for RouteSessionManager {
|
||||
type Controller = BaseController;
|
||||
async fn sync_route_info(
|
||||
self,
|
||||
_: tarpc::context::Context,
|
||||
from_peer_id: PeerId,
|
||||
from_session_id: SessionId,
|
||||
is_initiator: bool,
|
||||
peer_infos: Option<Vec<RoutePeerInfo>>,
|
||||
conn_bitmap: Option<RouteConnBitmap>,
|
||||
) -> Result<SyncRouteInfoResponse, Error> {
|
||||
let Some(service_impl) = self.service_impl.upgrade() else {
|
||||
return Err(Error::Stopped);
|
||||
};
|
||||
&self,
|
||||
_ctrl: BaseController,
|
||||
request: SyncRouteInfoRequest,
|
||||
) -> Result<SyncRouteInfoResponse, rpc_types::error::Error> {
|
||||
let from_peer_id = request.my_peer_id;
|
||||
let from_session_id = request.my_session_id;
|
||||
let is_initiator = request.is_initiator;
|
||||
let peer_infos = request.peer_infos.map(|x| x.items);
|
||||
let conn_bitmap = request.conn_bitmap.map(Into::into);
|
||||
|
||||
let my_peer_id = service_impl.my_peer_id;
|
||||
let session = self.get_or_start_session(from_peer_id)?;
|
||||
|
||||
session.rpc_rx_count.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
session.update_dst_session_id(from_session_id);
|
||||
|
||||
if let Some(peer_infos) = &peer_infos {
|
||||
service_impl.synced_route_info.update_peer_infos(
|
||||
my_peer_id,
|
||||
let ret = self
|
||||
.do_sync_route_info(
|
||||
from_peer_id,
|
||||
from_session_id,
|
||||
is_initiator,
|
||||
peer_infos,
|
||||
)?;
|
||||
session.update_dst_saved_peer_info_version(peer_infos);
|
||||
}
|
||||
conn_bitmap,
|
||||
)
|
||||
.await;
|
||||
|
||||
if let Some(conn_bitmap) = &conn_bitmap {
|
||||
service_impl.synced_route_info.update_conn_map(&conn_bitmap);
|
||||
session.update_dst_saved_conn_bitmap_version(conn_bitmap);
|
||||
}
|
||||
|
||||
service_impl.update_route_table_and_cached_local_conn_bitmap();
|
||||
|
||||
tracing::info!(
|
||||
"sync_route_info: from_peer_id: {:?}, is_initiator: {:?}, peer_infos: {:?}, conn_bitmap: {:?}, synced_route_info: {:?} session: {:?}, new_route_table: {:?}",
|
||||
from_peer_id, is_initiator, peer_infos, conn_bitmap, service_impl.synced_route_info, session, service_impl.route_table);
|
||||
|
||||
session
|
||||
.dst_is_initiator
|
||||
.store(is_initiator, Ordering::Relaxed);
|
||||
let is_initiator = session.we_are_initiator.load(Ordering::Relaxed);
|
||||
let session_id = session.my_session_id.load(Ordering::Relaxed);
|
||||
|
||||
self.sync_now("sync_route_info");
|
||||
|
||||
Ok(SyncRouteInfoResponse {
|
||||
is_initiator,
|
||||
session_id,
|
||||
Ok(match ret {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
let mut resp = SyncRouteInfoResponse::default();
|
||||
resp.error = Some(e as i32);
|
||||
resp
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1366,6 +1368,60 @@ impl RouteSessionManager {
|
||||
let ret = self.sync_now_broadcast.send(());
|
||||
tracing::debug!(?ret, ?reason, "sync_now_broadcast.send");
|
||||
}
|
||||
|
||||
async fn do_sync_route_info(
|
||||
&self,
|
||||
from_peer_id: PeerId,
|
||||
from_session_id: SessionId,
|
||||
is_initiator: bool,
|
||||
peer_infos: Option<Vec<RoutePeerInfo>>,
|
||||
conn_bitmap: Option<RouteConnBitmap>,
|
||||
) -> Result<SyncRouteInfoResponse, Error> {
|
||||
let Some(service_impl) = self.service_impl.upgrade() else {
|
||||
return Err(Error::Stopped);
|
||||
};
|
||||
|
||||
let my_peer_id = service_impl.my_peer_id;
|
||||
let session = self.get_or_start_session(from_peer_id)?;
|
||||
|
||||
session.rpc_rx_count.fetch_add(1, Ordering::Relaxed);
|
||||
|
||||
session.update_dst_session_id(from_session_id);
|
||||
|
||||
if let Some(peer_infos) = &peer_infos {
|
||||
service_impl.synced_route_info.update_peer_infos(
|
||||
my_peer_id,
|
||||
from_peer_id,
|
||||
peer_infos,
|
||||
)?;
|
||||
session.update_dst_saved_peer_info_version(peer_infos);
|
||||
}
|
||||
|
||||
if let Some(conn_bitmap) = &conn_bitmap {
|
||||
service_impl.synced_route_info.update_conn_map(&conn_bitmap);
|
||||
session.update_dst_saved_conn_bitmap_version(conn_bitmap);
|
||||
}
|
||||
|
||||
service_impl.update_route_table_and_cached_local_conn_bitmap();
|
||||
|
||||
tracing::info!(
|
||||
"handling sync_route_info rpc: from_peer_id: {:?}, is_initiator: {:?}, peer_infos: {:?}, conn_bitmap: {:?}, synced_route_info: {:?} session: {:?}, new_route_table: {:?}",
|
||||
from_peer_id, is_initiator, peer_infos, conn_bitmap, service_impl.synced_route_info, session, service_impl.route_table);
|
||||
|
||||
session
|
||||
.dst_is_initiator
|
||||
.store(is_initiator, Ordering::Relaxed);
|
||||
let is_initiator = session.we_are_initiator.load(Ordering::Relaxed);
|
||||
let session_id = session.my_session_id.load(Ordering::Relaxed);
|
||||
|
||||
self.sync_now("sync_route_info");
|
||||
|
||||
Ok(SyncRouteInfoResponse {
|
||||
is_initiator,
|
||||
session_id,
|
||||
error: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PeerRoute {
|
||||
@@ -1415,7 +1471,7 @@ impl PeerRoute {
|
||||
tokio::time::sleep(Duration::from_secs(60)).await;
|
||||
service_impl.clear_expired_peer();
|
||||
// TODO: use debug log level for this.
|
||||
tracing::info!(?service_impl, "clear_expired_peer");
|
||||
tracing::debug!(?service_impl, "clear_expired_peer");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1453,8 +1509,10 @@ impl PeerRoute {
|
||||
}
|
||||
|
||||
async fn start(&self) {
|
||||
self.peer_rpc
|
||||
.run_service(SERVICE_ID, RouteService::serve(self.session_mgr.clone()));
|
||||
self.peer_rpc.rpc_server().registry().register(
|
||||
OspfRouteRpcServer::new(self.session_mgr.clone()),
|
||||
&self.global_ctx.get_network_name(),
|
||||
);
|
||||
|
||||
self.tasks
|
||||
.lock()
|
||||
@@ -1479,6 +1537,15 @@ impl PeerRoute {
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PeerRoute {
|
||||
fn drop(&mut self) {
|
||||
self.peer_rpc.rpc_server().registry().unregister(
|
||||
OspfRouteRpcServer::new(self.session_mgr.clone()),
|
||||
&self.global_ctx.get_network_name(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Route for PeerRoute {
|
||||
async fn open(&self, interface: RouteInterfaceBox) -> Result<u8, ()> {
|
||||
@@ -1507,7 +1574,7 @@ impl Route for PeerRoute {
|
||||
route_table.get_next_hop(dst_peer_id).map(|x| x.0)
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::rpc::Route> {
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route> {
|
||||
let route_table = &self.service_impl.route_table;
|
||||
let mut routes = Vec::new();
|
||||
for item in route_table.peer_infos.iter() {
|
||||
@@ -1517,7 +1584,7 @@ impl Route for PeerRoute {
|
||||
let Some(next_hop_peer) = route_table.get_next_hop(*item.key()) else {
|
||||
continue;
|
||||
};
|
||||
let mut route: crate::rpc::Route = item.value().clone().into();
|
||||
let mut route: crate::proto::cli::Route = item.value().clone().into();
|
||||
route.next_hop_peer_id = next_hop_peer.0;
|
||||
route.cost = next_hop_peer.1;
|
||||
routes.push(route);
|
||||
@@ -1567,7 +1634,7 @@ mod tests {
|
||||
route_trait::{NextHopPolicy, Route, RouteCostCalculatorInterface},
|
||||
tests::connect_peer_manager,
|
||||
},
|
||||
rpc::NatType,
|
||||
proto::common::NatType,
|
||||
tunnel::common::tests::wait_for_condition,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,753 +0,0 @@
|
||||
use std::{
|
||||
net::Ipv4Addr,
|
||||
sync::{atomic::AtomicU32, Arc},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use dashmap::DashMap;
|
||||
use tokio::{
|
||||
sync::{Mutex, RwLock},
|
||||
task::JoinSet,
|
||||
};
|
||||
use tokio_util::bytes::Bytes;
|
||||
use tracing::Instrument;
|
||||
|
||||
use crate::{
|
||||
common::{error::Error, global_ctx::ArcGlobalCtx, stun::StunInfoCollectorTrait, PeerId},
|
||||
peers::route_trait::{Route, RouteInterfaceBox},
|
||||
rpc::{NatType, StunInfo},
|
||||
tunnel::packet_def::{PacketType, ZCPacket},
|
||||
};
|
||||
|
||||
use super::PeerPacketFilter;
|
||||
|
||||
const SEND_ROUTE_PERIOD_SEC: u64 = 60;
|
||||
const SEND_ROUTE_FAST_REPLY_SEC: u64 = 5;
|
||||
const ROUTE_EXPIRED_SEC: u64 = 70;
|
||||
|
||||
type Version = u32;
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, PartialEq)]
|
||||
// Derives can be passed through to the generated type:
|
||||
pub struct SyncPeerInfo {
|
||||
// means next hop in route table.
|
||||
pub peer_id: PeerId,
|
||||
pub cost: u32,
|
||||
pub ipv4_addr: Option<Ipv4Addr>,
|
||||
pub proxy_cidrs: Vec<String>,
|
||||
pub hostname: Option<String>,
|
||||
pub udp_stun_info: i8,
|
||||
}
|
||||
|
||||
impl SyncPeerInfo {
|
||||
pub fn new_self(from_peer: PeerId, global_ctx: &ArcGlobalCtx) -> Self {
|
||||
SyncPeerInfo {
|
||||
peer_id: from_peer,
|
||||
cost: 0,
|
||||
ipv4_addr: global_ctx.get_ipv4(),
|
||||
proxy_cidrs: global_ctx
|
||||
.get_proxy_cidrs()
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
.chain(global_ctx.get_vpn_portal_cidr().map(|x| x.to_string()))
|
||||
.collect(),
|
||||
hostname: Some(global_ctx.get_hostname()),
|
||||
udp_stun_info: global_ctx
|
||||
.get_stun_info_collector()
|
||||
.get_stun_info()
|
||||
.udp_nat_type as i8,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone_for_route_table(&self, next_hop: PeerId, cost: u32, from: &Self) -> Self {
|
||||
SyncPeerInfo {
|
||||
peer_id: next_hop,
|
||||
cost,
|
||||
ipv4_addr: from.ipv4_addr.clone(),
|
||||
proxy_cidrs: from.proxy_cidrs.clone(),
|
||||
hostname: from.hostname.clone(),
|
||||
udp_stun_info: from.udp_stun_info,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug)]
|
||||
pub struct SyncPeer {
|
||||
pub myself: SyncPeerInfo,
|
||||
pub neighbors: Vec<SyncPeerInfo>,
|
||||
// the route table version of myself
|
||||
pub version: Version,
|
||||
// the route table version of peer that we have received last time
|
||||
pub peer_version: Option<Version>,
|
||||
// if we do not have latest peer version, need_reply is true
|
||||
pub need_reply: bool,
|
||||
}
|
||||
|
||||
impl SyncPeer {
|
||||
pub fn new(
|
||||
from_peer: PeerId,
|
||||
_to_peer: PeerId,
|
||||
neighbors: Vec<SyncPeerInfo>,
|
||||
global_ctx: ArcGlobalCtx,
|
||||
version: Version,
|
||||
peer_version: Option<Version>,
|
||||
need_reply: bool,
|
||||
) -> Self {
|
||||
SyncPeer {
|
||||
myself: SyncPeerInfo::new_self(from_peer, &global_ctx),
|
||||
neighbors,
|
||||
version,
|
||||
peer_version,
|
||||
need_reply,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SyncPeerFromRemote {
|
||||
packet: SyncPeer,
|
||||
last_update: std::time::Instant,
|
||||
}
|
||||
|
||||
type SyncPeerFromRemoteMap = Arc<DashMap<PeerId, SyncPeerFromRemote>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RouteTable {
|
||||
route_info: DashMap<PeerId, SyncPeerInfo>,
|
||||
ipv4_peer_id_map: DashMap<Ipv4Addr, PeerId>,
|
||||
cidr_peer_id_map: DashMap<cidr::IpCidr, PeerId>,
|
||||
}
|
||||
|
||||
impl RouteTable {
|
||||
fn new() -> Self {
|
||||
RouteTable {
|
||||
route_info: DashMap::new(),
|
||||
ipv4_peer_id_map: DashMap::new(),
|
||||
cidr_peer_id_map: DashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_from(&self, other: &Self) {
|
||||
self.route_info.clear();
|
||||
for item in other.route_info.iter() {
|
||||
let (k, v) = item.pair();
|
||||
self.route_info.insert(*k, v.clone());
|
||||
}
|
||||
|
||||
self.ipv4_peer_id_map.clear();
|
||||
for item in other.ipv4_peer_id_map.iter() {
|
||||
let (k, v) = item.pair();
|
||||
self.ipv4_peer_id_map.insert(*k, *v);
|
||||
}
|
||||
|
||||
self.cidr_peer_id_map.clear();
|
||||
for item in other.cidr_peer_id_map.iter() {
|
||||
let (k, v) = item.pair();
|
||||
self.cidr_peer_id_map.insert(*k, *v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct RouteVersion(Arc<AtomicU32>);
|
||||
|
||||
impl RouteVersion {
|
||||
fn new() -> Self {
|
||||
// RouteVersion(Arc::new(AtomicU32::new(rand::random())))
|
||||
RouteVersion(Arc::new(AtomicU32::new(0)))
|
||||
}
|
||||
|
||||
fn get(&self) -> Version {
|
||||
self.0.load(std::sync::atomic::Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn inc(&self) {
|
||||
self.0.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BasicRoute {
|
||||
my_peer_id: PeerId,
|
||||
global_ctx: ArcGlobalCtx,
|
||||
interface: Arc<Mutex<Option<RouteInterfaceBox>>>,
|
||||
|
||||
route_table: Arc<RouteTable>,
|
||||
|
||||
sync_peer_from_remote: SyncPeerFromRemoteMap,
|
||||
|
||||
tasks: Mutex<JoinSet<()>>,
|
||||
|
||||
need_sync_notifier: Arc<tokio::sync::Notify>,
|
||||
|
||||
version: RouteVersion,
|
||||
myself: Arc<RwLock<SyncPeerInfo>>,
|
||||
last_send_time_map: Arc<DashMap<PeerId, (Version, Option<Version>, Instant)>>,
|
||||
}
|
||||
|
||||
impl BasicRoute {
|
||||
pub fn new(my_peer_id: PeerId, global_ctx: ArcGlobalCtx) -> Self {
|
||||
BasicRoute {
|
||||
my_peer_id,
|
||||
global_ctx: global_ctx.clone(),
|
||||
interface: Arc::new(Mutex::new(None)),
|
||||
|
||||
route_table: Arc::new(RouteTable::new()),
|
||||
|
||||
sync_peer_from_remote: Arc::new(DashMap::new()),
|
||||
tasks: Mutex::new(JoinSet::new()),
|
||||
|
||||
need_sync_notifier: Arc::new(tokio::sync::Notify::new()),
|
||||
|
||||
version: RouteVersion::new(),
|
||||
myself: Arc::new(RwLock::new(SyncPeerInfo::new_self(
|
||||
my_peer_id.into(),
|
||||
&global_ctx,
|
||||
))),
|
||||
last_send_time_map: Arc::new(DashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_route_table(
|
||||
my_id: PeerId,
|
||||
sync_peer_reqs: SyncPeerFromRemoteMap,
|
||||
route_table: Arc<RouteTable>,
|
||||
) {
|
||||
tracing::trace!(my_id = ?my_id, route_table = ?route_table, "update route table");
|
||||
|
||||
let new_route_table = Arc::new(RouteTable::new());
|
||||
for item in sync_peer_reqs.iter() {
|
||||
Self::update_route_table_with_req(my_id, &item.value().packet, new_route_table.clone());
|
||||
}
|
||||
|
||||
route_table.copy_from(&new_route_table);
|
||||
}
|
||||
|
||||
async fn update_myself(
|
||||
my_peer_id: PeerId,
|
||||
myself: &Arc<RwLock<SyncPeerInfo>>,
|
||||
global_ctx: &ArcGlobalCtx,
|
||||
) -> bool {
|
||||
let new_myself = SyncPeerInfo::new_self(my_peer_id, &global_ctx);
|
||||
if *myself.read().await != new_myself {
|
||||
*myself.write().await = new_myself;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn update_route_table_with_req(my_id: PeerId, packet: &SyncPeer, route_table: Arc<RouteTable>) {
|
||||
let peer_id = packet.myself.peer_id.clone();
|
||||
let update = |cost: u32, peer_info: &SyncPeerInfo| {
|
||||
let node_id: PeerId = peer_info.peer_id.into();
|
||||
let ret = route_table
|
||||
.route_info
|
||||
.entry(node_id.clone().into())
|
||||
.and_modify(|info| {
|
||||
if info.cost > cost {
|
||||
*info = info.clone_for_route_table(peer_id, cost, &peer_info);
|
||||
}
|
||||
})
|
||||
.or_insert(
|
||||
peer_info
|
||||
.clone()
|
||||
.clone_for_route_table(peer_id, cost, &peer_info),
|
||||
)
|
||||
.value()
|
||||
.clone();
|
||||
|
||||
if ret.cost > 6 {
|
||||
tracing::error!(
|
||||
"cost too large: {}, may lost connection, remove it",
|
||||
ret.cost
|
||||
);
|
||||
route_table.route_info.remove(&node_id);
|
||||
}
|
||||
|
||||
tracing::trace!(
|
||||
"update route info, to: {:?}, gateway: {:?}, cost: {}, peer: {:?}",
|
||||
node_id,
|
||||
peer_id,
|
||||
cost,
|
||||
&peer_info
|
||||
);
|
||||
|
||||
if let Some(ipv4) = peer_info.ipv4_addr {
|
||||
route_table
|
||||
.ipv4_peer_id_map
|
||||
.insert(ipv4.clone(), node_id.clone().into());
|
||||
}
|
||||
|
||||
for cidr in peer_info.proxy_cidrs.iter() {
|
||||
let cidr: cidr::IpCidr = cidr.parse().unwrap();
|
||||
route_table
|
||||
.cidr_peer_id_map
|
||||
.insert(cidr, node_id.clone().into());
|
||||
}
|
||||
};
|
||||
|
||||
for neighbor in packet.neighbors.iter() {
|
||||
if neighbor.peer_id == my_id {
|
||||
continue;
|
||||
}
|
||||
update(neighbor.cost + 1, &neighbor);
|
||||
tracing::trace!("route info: {:?}", neighbor);
|
||||
}
|
||||
|
||||
// add the sender peer to route info
|
||||
update(1, &packet.myself);
|
||||
|
||||
tracing::trace!("my_id: {:?}, current route table: {:?}", my_id, route_table);
|
||||
}
|
||||
|
||||
async fn send_sync_peer_request(
|
||||
interface: &RouteInterfaceBox,
|
||||
my_peer_id: PeerId,
|
||||
global_ctx: ArcGlobalCtx,
|
||||
peer_id: PeerId,
|
||||
route_table: Arc<RouteTable>,
|
||||
my_version: Version,
|
||||
peer_version: Option<Version>,
|
||||
need_reply: bool,
|
||||
) -> Result<(), Error> {
|
||||
let mut route_info_copy: Vec<SyncPeerInfo> = Vec::new();
|
||||
// copy the route info
|
||||
for item in route_table.route_info.iter() {
|
||||
let (k, v) = item.pair();
|
||||
route_info_copy.push(v.clone().clone_for_route_table(*k, v.cost, &v));
|
||||
}
|
||||
let msg = SyncPeer::new(
|
||||
my_peer_id,
|
||||
peer_id,
|
||||
route_info_copy,
|
||||
global_ctx,
|
||||
my_version,
|
||||
peer_version,
|
||||
need_reply,
|
||||
);
|
||||
// TODO: this may exceed the MTU of the tunnel
|
||||
interface
|
||||
.send_route_packet(postcard::to_allocvec(&msg).unwrap().into(), 1, peer_id)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn sync_peer_periodically(&self) {
|
||||
let route_table = self.route_table.clone();
|
||||
let global_ctx = self.global_ctx.clone();
|
||||
let my_peer_id = self.my_peer_id.clone();
|
||||
let interface = self.interface.clone();
|
||||
let notifier = self.need_sync_notifier.clone();
|
||||
let sync_peer_from_remote = self.sync_peer_from_remote.clone();
|
||||
let myself = self.myself.clone();
|
||||
let version = self.version.clone();
|
||||
let last_send_time_map = self.last_send_time_map.clone();
|
||||
self.tasks.lock().await.spawn(
|
||||
async move {
|
||||
loop {
|
||||
if Self::update_myself(my_peer_id,&myself, &global_ctx).await {
|
||||
version.inc();
|
||||
tracing::info!(
|
||||
my_id = ?my_peer_id,
|
||||
version = version.get(),
|
||||
"update route table version when myself changed"
|
||||
);
|
||||
}
|
||||
|
||||
let lockd_interface = interface.lock().await;
|
||||
let interface = lockd_interface.as_ref().unwrap();
|
||||
let last_send_time_map_new = DashMap::new();
|
||||
let peers = interface.list_peers().await;
|
||||
for peer in peers.iter() {
|
||||
let last_send_time = last_send_time_map.get(peer).map(|v| *v).unwrap_or((0, None, Instant::now() - Duration::from_secs(3600)));
|
||||
let my_version_peer_saved = sync_peer_from_remote.get(peer).and_then(|v| v.packet.peer_version);
|
||||
let peer_have_latest_version = my_version_peer_saved == Some(version.get());
|
||||
if peer_have_latest_version && last_send_time.2.elapsed().as_secs() < SEND_ROUTE_PERIOD_SEC {
|
||||
last_send_time_map_new.insert(*peer, last_send_time);
|
||||
continue;
|
||||
}
|
||||
|
||||
tracing::trace!(
|
||||
my_id = ?my_peer_id,
|
||||
dst_peer_id = ?peer,
|
||||
version = version.get(),
|
||||
?my_version_peer_saved,
|
||||
last_send_version = ?last_send_time.0,
|
||||
last_send_peer_version = ?last_send_time.1,
|
||||
last_send_elapse = ?last_send_time.2.elapsed().as_secs(),
|
||||
"need send route info"
|
||||
);
|
||||
let peer_version_we_saved = sync_peer_from_remote.get(&peer).and_then(|v| Some(v.packet.version));
|
||||
last_send_time_map_new.insert(*peer, (version.get(), peer_version_we_saved, Instant::now()));
|
||||
let ret = Self::send_sync_peer_request(
|
||||
interface,
|
||||
my_peer_id.clone(),
|
||||
global_ctx.clone(),
|
||||
*peer,
|
||||
route_table.clone(),
|
||||
version.get(),
|
||||
peer_version_we_saved,
|
||||
!peer_have_latest_version,
|
||||
)
|
||||
.await;
|
||||
|
||||
match &ret {
|
||||
Ok(_) => {
|
||||
tracing::trace!("send sync peer request to peer: {}", peer);
|
||||
}
|
||||
Err(Error::PeerNoConnectionError(_)) => {
|
||||
tracing::trace!("peer {} no connection", peer);
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
"send sync peer request to peer: {} error: {:?}",
|
||||
peer,
|
||||
e
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
last_send_time_map.clear();
|
||||
for item in last_send_time_map_new.iter() {
|
||||
let (k, v) = item.pair();
|
||||
last_send_time_map.insert(*k, *v);
|
||||
}
|
||||
|
||||
tokio::select! {
|
||||
_ = notifier.notified() => {
|
||||
tracing::trace!("sync peer request triggered by notifier");
|
||||
}
|
||||
_ = tokio::time::sleep(Duration::from_secs(1)) => {
|
||||
tracing::trace!("sync peer request triggered by timeout");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.instrument(
|
||||
tracing::info_span!("sync_peer_periodically", my_id = ?self.my_peer_id, global_ctx = ?self.global_ctx),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
async fn check_expired_sync_peer_from_remote(&self) {
|
||||
let route_table = self.route_table.clone();
|
||||
let my_peer_id = self.my_peer_id.clone();
|
||||
let sync_peer_from_remote = self.sync_peer_from_remote.clone();
|
||||
let notifier = self.need_sync_notifier.clone();
|
||||
let interface = self.interface.clone();
|
||||
let version = self.version.clone();
|
||||
self.tasks.lock().await.spawn(async move {
|
||||
loop {
|
||||
let mut need_update_route = false;
|
||||
let now = std::time::Instant::now();
|
||||
let mut need_remove = Vec::new();
|
||||
let connected_peers = interface.lock().await.as_ref().unwrap().list_peers().await;
|
||||
for item in sync_peer_from_remote.iter() {
|
||||
let (k, v) = item.pair();
|
||||
if now.duration_since(v.last_update).as_secs() > ROUTE_EXPIRED_SEC
|
||||
|| !connected_peers.contains(k)
|
||||
{
|
||||
need_update_route = true;
|
||||
need_remove.insert(0, k.clone());
|
||||
}
|
||||
}
|
||||
|
||||
for k in need_remove.iter() {
|
||||
tracing::warn!("remove expired sync peer: {:?}", k);
|
||||
sync_peer_from_remote.remove(k);
|
||||
}
|
||||
|
||||
if need_update_route {
|
||||
Self::update_route_table(
|
||||
my_peer_id,
|
||||
sync_peer_from_remote.clone(),
|
||||
route_table.clone(),
|
||||
);
|
||||
version.inc();
|
||||
tracing::info!(
|
||||
my_id = ?my_peer_id,
|
||||
version = version.get(),
|
||||
"update route table when check expired peer"
|
||||
);
|
||||
notifier.notify_one();
|
||||
}
|
||||
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn get_peer_id_for_proxy(&self, ipv4: &Ipv4Addr) -> Option<PeerId> {
|
||||
let ipv4 = std::net::IpAddr::V4(*ipv4);
|
||||
for item in self.route_table.cidr_peer_id_map.iter() {
|
||||
let (k, v) = item.pair();
|
||||
if k.contains(&ipv4) {
|
||||
return Some(*v);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, packet), fields(my_id = ?self.my_peer_id, ctx = ?self.global_ctx))]
|
||||
async fn handle_route_packet(&self, src_peer_id: PeerId, packet: Bytes) {
|
||||
let packet = postcard::from_bytes::<SyncPeer>(&packet).unwrap();
|
||||
let p = &packet;
|
||||
let mut updated = true;
|
||||
assert_eq!(packet.myself.peer_id, src_peer_id);
|
||||
self.sync_peer_from_remote
|
||||
.entry(packet.myself.peer_id.into())
|
||||
.and_modify(|v| {
|
||||
if v.packet.myself == p.myself && v.packet.neighbors == p.neighbors {
|
||||
updated = false;
|
||||
} else {
|
||||
v.packet = p.clone();
|
||||
}
|
||||
v.packet.version = p.version;
|
||||
v.packet.peer_version = p.peer_version;
|
||||
v.last_update = std::time::Instant::now();
|
||||
})
|
||||
.or_insert(SyncPeerFromRemote {
|
||||
packet: p.clone(),
|
||||
last_update: std::time::Instant::now(),
|
||||
});
|
||||
|
||||
if updated {
|
||||
Self::update_route_table(
|
||||
self.my_peer_id.clone(),
|
||||
self.sync_peer_from_remote.clone(),
|
||||
self.route_table.clone(),
|
||||
);
|
||||
self.version.inc();
|
||||
tracing::info!(
|
||||
my_id = ?self.my_peer_id,
|
||||
?p,
|
||||
version = self.version.get(),
|
||||
"update route table when receive route packet"
|
||||
);
|
||||
}
|
||||
|
||||
if packet.need_reply {
|
||||
self.last_send_time_map
|
||||
.entry(packet.myself.peer_id.into())
|
||||
.and_modify(|v| {
|
||||
const FAST_REPLY_DURATION: u64 =
|
||||
SEND_ROUTE_PERIOD_SEC - SEND_ROUTE_FAST_REPLY_SEC;
|
||||
if v.0 != self.version.get() || v.1 != Some(p.version) {
|
||||
v.2 = Instant::now() - Duration::from_secs(3600);
|
||||
} else if v.2.elapsed().as_secs() < FAST_REPLY_DURATION {
|
||||
// do not send same version route info too frequently
|
||||
v.2 = Instant::now() - Duration::from_secs(FAST_REPLY_DURATION);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if updated || packet.need_reply {
|
||||
self.need_sync_notifier.notify_one();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Route for BasicRoute {
|
||||
async fn open(&self, interface: RouteInterfaceBox) -> Result<u8, ()> {
|
||||
*self.interface.lock().await = Some(interface);
|
||||
self.sync_peer_periodically().await;
|
||||
self.check_expired_sync_peer_from_remote().await;
|
||||
Ok(1)
|
||||
}
|
||||
|
||||
async fn close(&self) {}
|
||||
|
||||
async fn get_next_hop(&self, dst_peer_id: PeerId) -> Option<PeerId> {
|
||||
match self.route_table.route_info.get(&dst_peer_id) {
|
||||
Some(info) => {
|
||||
return Some(info.peer_id.clone().into());
|
||||
}
|
||||
None => {
|
||||
tracing::error!("no route info for dst_peer_id: {}", dst_peer_id);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::rpc::Route> {
|
||||
let mut routes = Vec::new();
|
||||
|
||||
let parse_route_info = |real_peer_id: PeerId, route_info: &SyncPeerInfo| {
|
||||
let mut route = crate::rpc::Route::default();
|
||||
route.ipv4_addr = if let Some(ipv4_addr) = route_info.ipv4_addr {
|
||||
ipv4_addr.to_string()
|
||||
} else {
|
||||
"".to_string()
|
||||
};
|
||||
route.peer_id = real_peer_id;
|
||||
route.next_hop_peer_id = route_info.peer_id;
|
||||
route.cost = route_info.cost as i32;
|
||||
route.proxy_cidrs = route_info.proxy_cidrs.clone();
|
||||
route.hostname = route_info.hostname.clone().unwrap_or_default();
|
||||
|
||||
let mut stun_info = StunInfo::default();
|
||||
if let Ok(udp_nat_type) = NatType::try_from(route_info.udp_stun_info as i32) {
|
||||
stun_info.set_udp_nat_type(udp_nat_type);
|
||||
}
|
||||
route.stun_info = Some(stun_info);
|
||||
|
||||
route
|
||||
};
|
||||
|
||||
self.route_table.route_info.iter().for_each(|item| {
|
||||
routes.push(parse_route_info(*item.key(), item.value()));
|
||||
});
|
||||
|
||||
routes
|
||||
}
|
||||
|
||||
async fn get_peer_id_by_ipv4(&self, ipv4_addr: &Ipv4Addr) -> Option<PeerId> {
|
||||
if let Some(peer_id) = self.route_table.ipv4_peer_id_map.get(ipv4_addr) {
|
||||
return Some(*peer_id);
|
||||
}
|
||||
|
||||
if let Some(peer_id) = self.get_peer_id_for_proxy(ipv4_addr) {
|
||||
return Some(peer_id);
|
||||
}
|
||||
|
||||
tracing::info!("no peer id for ipv4: {}", ipv4_addr);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl PeerPacketFilter for BasicRoute {
|
||||
async fn try_process_packet_from_peer(&self, packet: ZCPacket) -> Option<ZCPacket> {
|
||||
let hdr = packet.peer_manager_header().unwrap();
|
||||
if hdr.packet_type == PacketType::Route as u8 {
|
||||
let b = packet.payload().to_vec();
|
||||
self.handle_route_packet(hdr.from_peer_id.get(), b.into())
|
||||
.await;
|
||||
None
|
||||
} else {
|
||||
Some(packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
common::{global_ctx::tests::get_mock_global_ctx, PeerId},
|
||||
connector::udp_hole_punch::tests::replace_stun_info_collector,
|
||||
peers::{
|
||||
peer_manager::{PeerManager, RouteAlgoType},
|
||||
peer_rip_route::Version,
|
||||
tests::{connect_peer_manager, wait_route_appear},
|
||||
},
|
||||
rpc::NatType,
|
||||
};
|
||||
|
||||
async fn create_mock_pmgr() -> Arc<PeerManager> {
|
||||
let (s, _r) = tokio::sync::mpsc::channel(1000);
|
||||
let peer_mgr = Arc::new(PeerManager::new(
|
||||
RouteAlgoType::Rip,
|
||||
get_mock_global_ctx(),
|
||||
s,
|
||||
));
|
||||
replace_stun_info_collector(peer_mgr.clone(), NatType::Unknown);
|
||||
peer_mgr.run().await.unwrap();
|
||||
peer_mgr
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_rip_route() {
|
||||
let peer_mgr_a = create_mock_pmgr().await;
|
||||
let peer_mgr_b = create_mock_pmgr().await;
|
||||
let peer_mgr_c = create_mock_pmgr().await;
|
||||
connect_peer_manager(peer_mgr_a.clone(), peer_mgr_b.clone()).await;
|
||||
connect_peer_manager(peer_mgr_b.clone(), peer_mgr_c.clone()).await;
|
||||
wait_route_appear(peer_mgr_a.clone(), peer_mgr_b.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
wait_route_appear(peer_mgr_a.clone(), peer_mgr_c.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mgrs = vec![peer_mgr_a.clone(), peer_mgr_b.clone(), peer_mgr_c.clone()];
|
||||
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(4)).await;
|
||||
|
||||
let check_version = |version: Version, peer_id: PeerId, mgrs: &Vec<Arc<PeerManager>>| {
|
||||
for mgr in mgrs.iter() {
|
||||
tracing::warn!(
|
||||
"check version: {:?}, {:?}, {:?}, {:?}",
|
||||
version,
|
||||
peer_id,
|
||||
mgr,
|
||||
mgr.get_basic_route().sync_peer_from_remote
|
||||
);
|
||||
assert_eq!(
|
||||
version,
|
||||
mgr.get_basic_route()
|
||||
.sync_peer_from_remote
|
||||
.get(&peer_id)
|
||||
.unwrap()
|
||||
.packet
|
||||
.version,
|
||||
);
|
||||
assert_eq!(
|
||||
mgr.get_basic_route()
|
||||
.sync_peer_from_remote
|
||||
.get(&peer_id)
|
||||
.unwrap()
|
||||
.packet
|
||||
.peer_version
|
||||
.unwrap(),
|
||||
mgr.get_basic_route().version.get()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let check_sanity = || {
|
||||
// check peer version in other peer mgr are correct.
|
||||
check_version(
|
||||
peer_mgr_b.get_basic_route().version.get(),
|
||||
peer_mgr_b.my_peer_id(),
|
||||
&vec![peer_mgr_a.clone(), peer_mgr_c.clone()],
|
||||
);
|
||||
|
||||
check_version(
|
||||
peer_mgr_a.get_basic_route().version.get(),
|
||||
peer_mgr_a.my_peer_id(),
|
||||
&vec![peer_mgr_b.clone()],
|
||||
);
|
||||
|
||||
check_version(
|
||||
peer_mgr_c.get_basic_route().version.get(),
|
||||
peer_mgr_c.my_peer_id(),
|
||||
&vec![peer_mgr_b.clone()],
|
||||
);
|
||||
};
|
||||
|
||||
check_sanity();
|
||||
|
||||
let versions = mgrs
|
||||
.iter()
|
||||
.map(|x| x.get_basic_route().version.get())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||
|
||||
let versions2 = mgrs
|
||||
.iter()
|
||||
.map(|x| x.get_basic_route().version.get())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(versions, versions2);
|
||||
check_sanity();
|
||||
|
||||
assert!(peer_mgr_a.get_basic_route().version.get() <= 3);
|
||||
assert!(peer_mgr_b.get_basic_route().version.get() <= 6);
|
||||
assert!(peer_mgr_c.get_basic_route().version.get() <= 3);
|
||||
}
|
||||
}
|
||||
+144
-600
@@ -1,27 +1,10 @@
|
||||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU32, Ordering},
|
||||
Arc,
|
||||
},
|
||||
time::Instant,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use dashmap::DashMap;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use prost::Message;
|
||||
|
||||
use tarpc::{server::Channel, transport::channel::UnboundedChannel};
|
||||
use tokio::{
|
||||
sync::mpsc::{self, UnboundedSender},
|
||||
task::JoinSet,
|
||||
};
|
||||
|
||||
use tracing::Instrument;
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::{
|
||||
common::{error::Error, PeerId},
|
||||
rpc::TaRpcPacket,
|
||||
proto::rpc_impl,
|
||||
tunnel::packet_def::{PacketType, ZCPacket},
|
||||
};
|
||||
|
||||
@@ -38,33 +21,11 @@ pub trait PeerRpcManagerTransport: Send + Sync + 'static {
|
||||
async fn recv(&self) -> Result<ZCPacket, Error>;
|
||||
}
|
||||
|
||||
type PacketSender = UnboundedSender<ZCPacket>;
|
||||
|
||||
struct PeerRpcEndPoint {
|
||||
peer_id: PeerId,
|
||||
packet_sender: PacketSender,
|
||||
create_time: AtomicCell<Instant>,
|
||||
finished: Arc<AtomicBool>,
|
||||
tasks: JoinSet<()>,
|
||||
}
|
||||
|
||||
type PeerRpcEndPointCreator =
|
||||
Box<dyn Fn(PeerId, PeerRpcTransactId) -> PeerRpcEndPoint + Send + Sync + 'static>;
|
||||
#[derive(Hash, Eq, PartialEq, Clone)]
|
||||
struct PeerRpcClientCtxKey(PeerId, PeerRpcServiceId, PeerRpcTransactId);
|
||||
|
||||
// handle rpc request from one peer
|
||||
pub struct PeerRpcManager {
|
||||
service_map: Arc<DashMap<PeerRpcServiceId, PacketSender>>,
|
||||
tasks: JoinSet<()>,
|
||||
tspt: Arc<Box<dyn PeerRpcManagerTransport>>,
|
||||
|
||||
service_registry: Arc<DashMap<PeerRpcServiceId, PeerRpcEndPointCreator>>,
|
||||
|
||||
peer_rpc_endpoints: Arc<DashMap<PeerRpcClientCtxKey, PeerRpcEndPoint>>,
|
||||
client_resp_receivers: Arc<DashMap<PeerRpcClientCtxKey, PacketSender>>,
|
||||
|
||||
transact_id: AtomicU32,
|
||||
rpc_client: rpc_impl::client::Client,
|
||||
rpc_server: rpc_impl::server::Server,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PeerRpcManager {
|
||||
@@ -75,293 +36,55 @@ impl std::fmt::Debug for PeerRpcManager {
|
||||
}
|
||||
}
|
||||
|
||||
struct PacketMerger {
|
||||
first_piece: Option<TaRpcPacket>,
|
||||
pieces: Vec<TaRpcPacket>,
|
||||
}
|
||||
|
||||
impl PacketMerger {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
first_piece: None,
|
||||
pieces: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn try_merge_pieces(&self) -> Option<TaRpcPacket> {
|
||||
if self.first_piece.is_none() || self.pieces.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
for p in &self.pieces {
|
||||
// some piece is missing
|
||||
if p.total_pieces == 0 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
// all pieces are received
|
||||
let mut content = Vec::new();
|
||||
for p in &self.pieces {
|
||||
content.extend_from_slice(&p.content);
|
||||
}
|
||||
|
||||
let mut tmpl_packet = self.first_piece.as_ref().unwrap().clone();
|
||||
tmpl_packet.total_pieces = 1;
|
||||
tmpl_packet.piece_idx = 0;
|
||||
tmpl_packet.content = content;
|
||||
|
||||
Some(tmpl_packet)
|
||||
}
|
||||
|
||||
fn feed(
|
||||
&mut self,
|
||||
packet: ZCPacket,
|
||||
expected_tid: Option<PeerRpcTransactId>,
|
||||
) -> Result<Option<TaRpcPacket>, Error> {
|
||||
let payload = packet.payload();
|
||||
let rpc_packet =
|
||||
TaRpcPacket::decode(payload).map_err(|e| Error::MessageDecodeError(e.to_string()))?;
|
||||
|
||||
if expected_tid.is_some() && rpc_packet.transact_id != expected_tid.unwrap() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let total_pieces = rpc_packet.total_pieces;
|
||||
let piece_idx = rpc_packet.piece_idx;
|
||||
|
||||
// for compatibility with old version
|
||||
if total_pieces == 0 && piece_idx == 0 {
|
||||
return Ok(Some(rpc_packet));
|
||||
}
|
||||
|
||||
if total_pieces > 100 || total_pieces == 0 {
|
||||
return Err(Error::MessageDecodeError(format!(
|
||||
"total_pieces is invalid: {}",
|
||||
total_pieces
|
||||
)));
|
||||
}
|
||||
|
||||
if piece_idx >= total_pieces {
|
||||
return Err(Error::MessageDecodeError(
|
||||
"piece_idx >= total_pieces".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
if self.first_piece.is_none()
|
||||
|| self.first_piece.as_ref().unwrap().transact_id != rpc_packet.transact_id
|
||||
|| self.first_piece.as_ref().unwrap().from_peer != rpc_packet.from_peer
|
||||
{
|
||||
self.first_piece = Some(rpc_packet.clone());
|
||||
self.pieces.clear();
|
||||
}
|
||||
|
||||
self.pieces
|
||||
.resize(total_pieces as usize, Default::default());
|
||||
self.pieces[piece_idx as usize] = rpc_packet;
|
||||
|
||||
Ok(self.try_merge_pieces())
|
||||
}
|
||||
}
|
||||
|
||||
impl PeerRpcManager {
|
||||
pub fn new(tspt: impl PeerRpcManagerTransport) -> Self {
|
||||
Self {
|
||||
service_map: Arc::new(DashMap::new()),
|
||||
tasks: JoinSet::new(),
|
||||
tspt: Arc::new(Box::new(tspt)),
|
||||
|
||||
service_registry: Arc::new(DashMap::new()),
|
||||
peer_rpc_endpoints: Arc::new(DashMap::new()),
|
||||
|
||||
client_resp_receivers: Arc::new(DashMap::new()),
|
||||
|
||||
transact_id: AtomicU32::new(0),
|
||||
rpc_client: rpc_impl::client::Client::new(),
|
||||
rpc_server: rpc_impl::server::Server::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_service<S, Req>(self: &Self, service_id: PeerRpcServiceId, s: S) -> ()
|
||||
where
|
||||
S: tarpc::server::Serve<Req> + Clone + Send + Sync + 'static,
|
||||
Req: Send + 'static + serde::Serialize + for<'a> serde::Deserialize<'a>,
|
||||
S::Resp:
|
||||
Send + std::fmt::Debug + 'static + serde::Serialize + for<'a> serde::Deserialize<'a>,
|
||||
S::Fut: Send + 'static,
|
||||
{
|
||||
let tspt = self.tspt.clone();
|
||||
let creator = Box::new(move |peer_id: PeerId, transact_id: PeerRpcTransactId| {
|
||||
let mut tasks = JoinSet::new();
|
||||
let (packet_sender, mut packet_receiver) = mpsc::unbounded_channel();
|
||||
let (mut client_transport, server_transport) = tarpc::transport::channel::unbounded();
|
||||
let server = tarpc::server::BaseChannel::with_defaults(server_transport);
|
||||
let finished = Arc::new(AtomicBool::new(false));
|
||||
|
||||
let my_peer_id_clone = tspt.my_peer_id();
|
||||
let peer_id_clone = peer_id.clone();
|
||||
|
||||
let o = server.execute(s.clone());
|
||||
tasks.spawn(o);
|
||||
|
||||
let tspt = tspt.clone();
|
||||
let finished_clone = finished.clone();
|
||||
tasks.spawn(async move {
|
||||
let mut packet_merger = PacketMerger::new();
|
||||
loop {
|
||||
tokio::select! {
|
||||
Some(resp) = client_transport.next() => {
|
||||
tracing::debug!(resp = ?resp, ?transact_id, ?peer_id, "server recv packet from service provider");
|
||||
if resp.is_err() {
|
||||
tracing::warn!(err = ?resp.err(),
|
||||
"[PEER RPC MGR] client_transport in server side got channel error, ignore it.");
|
||||
continue;
|
||||
}
|
||||
let resp = resp.unwrap();
|
||||
|
||||
let serialized_resp = postcard::to_allocvec(&resp);
|
||||
if serialized_resp.is_err() {
|
||||
tracing::error!(error = ?serialized_resp.err(), "serialize resp failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
let msgs = Self::build_rpc_packet(
|
||||
tspt.my_peer_id(),
|
||||
peer_id,
|
||||
service_id,
|
||||
transact_id,
|
||||
false,
|
||||
serialized_resp.as_ref().unwrap(),
|
||||
);
|
||||
|
||||
for msg in msgs {
|
||||
if let Err(e) = tspt.send(msg, peer_id).await {
|
||||
tracing::error!(error = ?e, peer_id = ?peer_id, service_id = ?service_id, "send resp to peer failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
finished_clone.store(true, Ordering::Relaxed);
|
||||
}
|
||||
Some(packet) = packet_receiver.recv() => {
|
||||
tracing::trace!("recv packet from peer, packet: {:?}", packet);
|
||||
|
||||
let info = match packet_merger.feed(packet, None) {
|
||||
Err(e) => {
|
||||
tracing::error!(error = ?e, "feed packet to merger failed");
|
||||
continue;
|
||||
},
|
||||
Ok(None) => {
|
||||
continue;
|
||||
},
|
||||
Ok(Some(info)) => {
|
||||
info
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(info.service_id, service_id);
|
||||
assert_eq!(info.from_peer, peer_id);
|
||||
assert_eq!(info.transact_id, transact_id);
|
||||
|
||||
let decoded_ret = postcard::from_bytes(&info.content.as_slice());
|
||||
if let Err(e) = decoded_ret {
|
||||
tracing::error!(error = ?e, "decode rpc packet failed");
|
||||
continue;
|
||||
}
|
||||
let decoded: tarpc::ClientMessage<Req> = decoded_ret.unwrap();
|
||||
|
||||
if let Err(e) = client_transport.send(decoded).await {
|
||||
tracing::error!(error = ?e, "send to req to client transport failed");
|
||||
}
|
||||
}
|
||||
else => {
|
||||
tracing::warn!("[PEER RPC MGR] service runner destroy, peer_id: {}, service_id: {}", peer_id, service_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.instrument(tracing::info_span!("service_runner", my_id = ?my_peer_id_clone, peer_id = ?peer_id_clone, service_id = ?service_id)));
|
||||
|
||||
tracing::info!(
|
||||
"[PEER RPC MGR] create new service endpoint for peer {}, service {}",
|
||||
peer_id,
|
||||
service_id
|
||||
);
|
||||
|
||||
return PeerRpcEndPoint {
|
||||
peer_id,
|
||||
packet_sender,
|
||||
create_time: AtomicCell::new(Instant::now()),
|
||||
finished,
|
||||
tasks,
|
||||
};
|
||||
// let resp = client_transport.next().await;
|
||||
});
|
||||
|
||||
if let Some(_) = self.service_registry.insert(service_id, creator) {
|
||||
panic!(
|
||||
"[PEER RPC MGR] service {} is already registered",
|
||||
service_id
|
||||
);
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
"[PEER RPC MGR] register service {} succeed, my_node_id {}",
|
||||
service_id,
|
||||
self.tspt.my_peer_id()
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_rpc_packet(packet: &ZCPacket) -> Result<TaRpcPacket, Error> {
|
||||
let payload = packet.payload();
|
||||
TaRpcPacket::decode(payload).map_err(|e| Error::MessageDecodeError(e.to_string()))
|
||||
}
|
||||
|
||||
fn build_rpc_packet(
|
||||
from_peer: PeerId,
|
||||
to_peer: PeerId,
|
||||
service_id: PeerRpcServiceId,
|
||||
transact_id: PeerRpcTransactId,
|
||||
is_req: bool,
|
||||
content: &Vec<u8>,
|
||||
) -> Vec<ZCPacket> {
|
||||
let mut ret = Vec::new();
|
||||
let content_mtu = RPC_PACKET_CONTENT_MTU;
|
||||
let total_pieces = (content.len() + content_mtu - 1) / content_mtu;
|
||||
let mut cur_offset = 0;
|
||||
while cur_offset < content.len() {
|
||||
let mut cur_len = content_mtu;
|
||||
if cur_offset + cur_len > content.len() {
|
||||
cur_len = content.len() - cur_offset;
|
||||
}
|
||||
|
||||
let mut cur_content = Vec::new();
|
||||
cur_content.extend_from_slice(&content[cur_offset..cur_offset + cur_len]);
|
||||
|
||||
let cur_packet = TaRpcPacket {
|
||||
from_peer,
|
||||
to_peer,
|
||||
service_id,
|
||||
transact_id,
|
||||
is_req,
|
||||
total_pieces: total_pieces as u32,
|
||||
piece_idx: (cur_offset / content_mtu) as u32,
|
||||
content: cur_content,
|
||||
};
|
||||
cur_offset += cur_len;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
cur_packet.encode(&mut buf).unwrap();
|
||||
let mut zc_packet = ZCPacket::new_with_payload(&buf);
|
||||
zc_packet.fill_peer_manager_hdr(from_peer, to_peer, PacketType::TaRpc as u8);
|
||||
ret.push(zc_packet);
|
||||
}
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn run(&self) {
|
||||
self.rpc_client.run();
|
||||
self.rpc_server.run();
|
||||
|
||||
let (server_tx, mut server_rx) = (
|
||||
self.rpc_server.get_transport_sink(),
|
||||
self.rpc_server.get_transport_stream(),
|
||||
);
|
||||
let (client_tx, mut client_rx) = (
|
||||
self.rpc_client.get_transport_sink(),
|
||||
self.rpc_client.get_transport_stream(),
|
||||
);
|
||||
|
||||
let tspt = self.tspt.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
let packet = tokio::select! {
|
||||
Some(Ok(packet)) = server_rx.next() => {
|
||||
tracing::trace!(?packet, "recv rpc packet from server");
|
||||
packet
|
||||
}
|
||||
Some(Ok(packet)) = client_rx.next() => {
|
||||
tracing::trace!(?packet, "recv rpc packet from client");
|
||||
packet
|
||||
}
|
||||
else => {
|
||||
tracing::warn!("rpc transport read aborted, exiting");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let dst_peer_id = packet.peer_manager_header().unwrap().to_peer_id.into();
|
||||
if let Err(e) = tspt.send(packet, dst_peer_id).await {
|
||||
tracing::error!(error = ?e, dst_peer_id = ?dst_peer_id, "send to peer failed");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let tspt = self.tspt.clone();
|
||||
let service_registry = self.service_registry.clone();
|
||||
let peer_rpc_endpoints = self.peer_rpc_endpoints.clone();
|
||||
let client_resp_receivers = self.client_resp_receivers.clone();
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
let Ok(o) = tspt.recv().await else {
|
||||
@@ -369,176 +92,24 @@ impl PeerRpcManager {
|
||||
break;
|
||||
};
|
||||
|
||||
let info = Self::parse_rpc_packet(&o).unwrap();
|
||||
tracing::debug!(?info, "recv rpc packet from peer");
|
||||
|
||||
if info.is_req {
|
||||
if !service_registry.contains_key(&info.service_id) {
|
||||
tracing::warn!(
|
||||
"service {} not found, my_node_id: {}",
|
||||
info.service_id,
|
||||
tspt.my_peer_id()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let endpoint = peer_rpc_endpoints
|
||||
.entry(PeerRpcClientCtxKey(
|
||||
info.from_peer,
|
||||
info.service_id,
|
||||
info.transact_id,
|
||||
))
|
||||
.or_insert_with(|| {
|
||||
service_registry.get(&info.service_id).unwrap()(
|
||||
info.from_peer,
|
||||
info.transact_id,
|
||||
)
|
||||
});
|
||||
|
||||
endpoint.packet_sender.send(o).unwrap();
|
||||
} else {
|
||||
if let Some(a) = client_resp_receivers.get(&PeerRpcClientCtxKey(
|
||||
info.from_peer,
|
||||
info.service_id,
|
||||
info.transact_id,
|
||||
)) {
|
||||
tracing::trace!("recv resp: {:?}", info);
|
||||
if let Err(e) = a.send(o) {
|
||||
tracing::error!(error = ?e, "send resp to client failed");
|
||||
}
|
||||
} else {
|
||||
tracing::warn!("client resp receiver not found, info: {:?}", info);
|
||||
}
|
||||
if o.peer_manager_header().unwrap().packet_type == PacketType::RpcReq as u8 {
|
||||
server_tx.send(o).await.unwrap();
|
||||
continue;
|
||||
} else if o.peer_manager_header().unwrap().packet_type == PacketType::RpcResp as u8
|
||||
{
|
||||
client_tx.send(o).await.unwrap();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let peer_rpc_endpoints = self.peer_rpc_endpoints.clone();
|
||||
tokio::spawn(async move {
|
||||
loop {
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||
peer_rpc_endpoints.retain(|_, v| {
|
||||
v.create_time.load().elapsed().as_secs() < 30
|
||||
&& !v.finished.load(Ordering::Relaxed)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(f))]
|
||||
pub async fn do_client_rpc_scoped<Resp, Req, RpcRet, Fut>(
|
||||
&self,
|
||||
service_id: PeerRpcServiceId,
|
||||
dst_peer_id: PeerId,
|
||||
f: impl FnOnce(UnboundedChannel<Resp, Req>) -> Fut,
|
||||
) -> RpcRet
|
||||
where
|
||||
Resp: serde::Serialize
|
||||
+ for<'a> serde::Deserialize<'a>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ std::fmt::Debug
|
||||
+ 'static,
|
||||
Req: serde::Serialize
|
||||
+ for<'a> serde::Deserialize<'a>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ std::fmt::Debug
|
||||
+ 'static,
|
||||
Fut: std::future::Future<Output = RpcRet>,
|
||||
{
|
||||
let mut tasks = JoinSet::new();
|
||||
let (packet_sender, mut packet_receiver) = mpsc::unbounded_channel();
|
||||
pub fn rpc_client(&self) -> &rpc_impl::client::Client {
|
||||
&self.rpc_client
|
||||
}
|
||||
|
||||
let (client_transport, server_transport) =
|
||||
tarpc::transport::channel::unbounded::<Resp, Req>();
|
||||
|
||||
let (mut server_s, mut server_r) = server_transport.split();
|
||||
|
||||
let transact_id = self
|
||||
.transact_id
|
||||
.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
let tspt = self.tspt.clone();
|
||||
tasks.spawn(async move {
|
||||
while let Some(a) = server_r.next().await {
|
||||
if a.is_err() {
|
||||
tracing::error!(error = ?a.err(), "channel error");
|
||||
continue;
|
||||
}
|
||||
|
||||
let req = postcard::to_allocvec(&a.unwrap());
|
||||
if req.is_err() {
|
||||
tracing::error!(error = ?req.err(), "bincode serialize failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
let packets = Self::build_rpc_packet(
|
||||
tspt.my_peer_id(),
|
||||
dst_peer_id,
|
||||
service_id,
|
||||
transact_id,
|
||||
true,
|
||||
req.as_ref().unwrap(),
|
||||
);
|
||||
|
||||
tracing::debug!(?packets, ?req, ?transact_id, "client send rpc packet to peer");
|
||||
|
||||
for packet in packets {
|
||||
if let Err(e) = tspt.send(packet, dst_peer_id).await {
|
||||
tracing::error!(error = ?e, dst_peer_id = ?dst_peer_id, "send to peer failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tracing::warn!("[PEER RPC MGR] server trasport read aborted");
|
||||
});
|
||||
|
||||
tasks.spawn(async move {
|
||||
let mut packet_merger = PacketMerger::new();
|
||||
while let Some(packet) = packet_receiver.recv().await {
|
||||
tracing::trace!("tunnel recv: {:?}", packet);
|
||||
|
||||
let info = match packet_merger.feed(packet, Some(transact_id)) {
|
||||
Err(e) => {
|
||||
tracing::error!(error = ?e, "feed packet to merger failed");
|
||||
continue;
|
||||
}
|
||||
Ok(None) => {
|
||||
continue;
|
||||
}
|
||||
Ok(Some(info)) => info,
|
||||
};
|
||||
|
||||
let decoded = postcard::from_bytes(&info.content.as_slice());
|
||||
|
||||
tracing::debug!(?info, ?decoded, "client recv rpc packet from peer");
|
||||
assert_eq!(info.transact_id, transact_id);
|
||||
|
||||
if let Err(e) = decoded {
|
||||
tracing::error!(error = ?e, "decode rpc packet failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Err(e) = server_s.send(decoded.unwrap()).await {
|
||||
tracing::error!(error = ?e, "send to rpc server channel failed");
|
||||
}
|
||||
}
|
||||
|
||||
tracing::warn!("[PEER RPC MGR] server packet read aborted");
|
||||
});
|
||||
|
||||
let key = PeerRpcClientCtxKey(dst_peer_id, service_id, transact_id);
|
||||
let _insert_ret = self
|
||||
.client_resp_receivers
|
||||
.insert(key.clone(), packet_sender);
|
||||
|
||||
let ret = f(client_transport).await;
|
||||
|
||||
self.client_resp_receivers.remove(&key);
|
||||
|
||||
ret
|
||||
pub fn rpc_server(&self) -> &rpc_impl::server::Server {
|
||||
&self.rpc_server
|
||||
}
|
||||
|
||||
pub fn my_peer_id(&self) -> PeerId {
|
||||
@@ -548,7 +119,7 @@ impl PeerRpcManager {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use std::{pin::Pin, sync::Arc, time::Duration};
|
||||
use std::{pin::Pin, sync::Arc};
|
||||
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use tokio::sync::Mutex;
|
||||
@@ -559,31 +130,18 @@ pub mod tests {
|
||||
peer_rpc::PeerRpcManager,
|
||||
tests::{connect_peer_manager, create_mock_peer_manager, wait_route_appear},
|
||||
},
|
||||
proto::{
|
||||
rpc_impl::RpcController,
|
||||
tests::{GreetingClientFactory, GreetingServer, GreetingService, SayHelloRequest},
|
||||
},
|
||||
tunnel::{
|
||||
common::tests::wait_for_condition, packet_def::ZCPacket, ring::create_ring_tunnel_pair,
|
||||
Tunnel, ZCPacketSink, ZCPacketStream,
|
||||
packet_def::ZCPacket, ring::create_ring_tunnel_pair, Tunnel,
|
||||
ZCPacketSink, ZCPacketStream,
|
||||
},
|
||||
};
|
||||
|
||||
use super::PeerRpcManagerTransport;
|
||||
|
||||
#[tarpc::service]
|
||||
pub trait TestRpcService {
|
||||
async fn hello(s: String) -> String;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MockService {
|
||||
pub prefix: String,
|
||||
}
|
||||
|
||||
#[tarpc::server]
|
||||
impl TestRpcService for MockService {
|
||||
async fn hello(self, _: tarpc::context::Context, s: String) -> String {
|
||||
format!("{} {}", self.prefix, s)
|
||||
}
|
||||
}
|
||||
|
||||
fn random_string(len: usize) -> String {
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::Rng;
|
||||
@@ -595,6 +153,16 @@ pub mod tests {
|
||||
String::from_utf8(s).unwrap()
|
||||
}
|
||||
|
||||
pub fn register_service(rpc_mgr: &PeerRpcManager, domain: &str, delay_ms: u64, prefix: &str) {
|
||||
rpc_mgr.rpc_server().registry().register(
|
||||
GreetingServer::new(GreetingService {
|
||||
delay_ms,
|
||||
prefix: prefix.to_string(),
|
||||
}),
|
||||
domain,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn peer_rpc_basic_test() {
|
||||
struct MockTransport {
|
||||
@@ -630,10 +198,7 @@ pub mod tests {
|
||||
my_peer_id: new_peer_id(),
|
||||
});
|
||||
server_rpc_mgr.run();
|
||||
let s = MockService {
|
||||
prefix: "hello".to_owned(),
|
||||
};
|
||||
server_rpc_mgr.run_service(1, s.serve());
|
||||
register_service(&server_rpc_mgr, "test", 0, "Hello");
|
||||
|
||||
let client_rpc_mgr = PeerRpcManager::new(MockTransport {
|
||||
sink: Arc::new(Mutex::new(stsr)),
|
||||
@@ -642,35 +207,27 @@ pub mod tests {
|
||||
});
|
||||
client_rpc_mgr.run();
|
||||
|
||||
let stub = client_rpc_mgr
|
||||
.rpc_client()
|
||||
.scoped_client::<GreetingClientFactory<RpcController>>(1, 1, "test".to_string());
|
||||
|
||||
let msg = random_string(8192);
|
||||
let ret = client_rpc_mgr
|
||||
.do_client_rpc_scoped(1, server_rpc_mgr.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), msg.clone()).await;
|
||||
ret
|
||||
})
|
||||
.await;
|
||||
let ret = stub
|
||||
.say_hello(RpcController {}, SayHelloRequest { name: msg.clone() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("ret: {:?}", ret);
|
||||
assert_eq!(ret.unwrap(), format!("hello {}", msg));
|
||||
assert_eq!(ret.greeting, format!("Hello {}!", msg));
|
||||
|
||||
let msg = random_string(10);
|
||||
let ret = client_rpc_mgr
|
||||
.do_client_rpc_scoped(1, server_rpc_mgr.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), msg.clone()).await;
|
||||
ret
|
||||
})
|
||||
.await;
|
||||
let ret = stub
|
||||
.say_hello(RpcController {}, SayHelloRequest { name: msg.clone() })
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("ret: {:?}", ret);
|
||||
assert_eq!(ret.unwrap(), format!("hello {}", msg));
|
||||
|
||||
wait_for_condition(
|
||||
|| async { server_rpc_mgr.peer_rpc_endpoints.is_empty() },
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(ret.greeting, format!("Hello {}!", msg));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -680,6 +237,7 @@ pub mod tests {
|
||||
let peer_mgr_c = create_mock_peer_manager().await;
|
||||
connect_peer_manager(peer_mgr_a.clone(), peer_mgr_b.clone()).await;
|
||||
connect_peer_manager(peer_mgr_b.clone(), peer_mgr_c.clone()).await;
|
||||
|
||||
wait_route_appear(peer_mgr_a.clone(), peer_mgr_b.clone())
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -699,51 +257,42 @@ pub mod tests {
|
||||
peer_mgr_b.my_peer_id()
|
||||
);
|
||||
|
||||
let s = MockService {
|
||||
prefix: "hello".to_owned(),
|
||||
};
|
||||
peer_mgr_b.get_peer_rpc_mgr().run_service(1, s.serve());
|
||||
register_service(&peer_mgr_b.get_peer_rpc_mgr(), "test", 0, "Hello");
|
||||
|
||||
let msg = random_string(16 * 1024);
|
||||
let ip_list = peer_mgr_a
|
||||
let stub = peer_mgr_a
|
||||
.get_peer_rpc_mgr()
|
||||
.do_client_rpc_scoped(1, peer_mgr_b.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), msg.clone()).await;
|
||||
ret
|
||||
})
|
||||
.await;
|
||||
println!("ip_list: {:?}", ip_list);
|
||||
assert_eq!(ip_list.unwrap(), format!("hello {}", msg));
|
||||
.rpc_client()
|
||||
.scoped_client::<GreetingClientFactory<RpcController>>(
|
||||
peer_mgr_a.my_peer_id(),
|
||||
peer_mgr_b.my_peer_id(),
|
||||
"test".to_string(),
|
||||
);
|
||||
|
||||
let ret = stub
|
||||
.say_hello(RpcController {}, SayHelloRequest { name: msg.clone() })
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(ret.greeting, format!("Hello {}!", msg));
|
||||
|
||||
// call again
|
||||
let msg = random_string(16 * 1024);
|
||||
let ip_list = peer_mgr_a
|
||||
.get_peer_rpc_mgr()
|
||||
.do_client_rpc_scoped(1, peer_mgr_b.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), msg.clone()).await;
|
||||
ret
|
||||
})
|
||||
.await;
|
||||
println!("ip_list: {:?}", ip_list);
|
||||
assert_eq!(ip_list.unwrap(), format!("hello {}", msg));
|
||||
let ret = stub
|
||||
.say_hello(RpcController {}, SayHelloRequest { name: msg.clone() })
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(ret.greeting, format!("Hello {}!", msg));
|
||||
|
||||
let msg = random_string(16 * 1024);
|
||||
let ip_list = peer_mgr_c
|
||||
.get_peer_rpc_mgr()
|
||||
.do_client_rpc_scoped(1, peer_mgr_b.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), msg.clone()).await;
|
||||
ret
|
||||
})
|
||||
.await;
|
||||
println!("ip_list: {:?}", ip_list);
|
||||
assert_eq!(ip_list.unwrap(), format!("hello {}", msg));
|
||||
let ret = stub
|
||||
.say_hello(RpcController {}, SayHelloRequest { name: msg.clone() })
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(ret.greeting, format!("Hello {}!", msg));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_multi_service_with_peer_manager() {
|
||||
async fn test_multi_domain_with_peer_manager() {
|
||||
let peer_mgr_a = create_mock_peer_manager().await;
|
||||
let peer_mgr_b = create_mock_peer_manager().await;
|
||||
connect_peer_manager(peer_mgr_a.clone(), peer_mgr_b.clone()).await;
|
||||
@@ -757,42 +306,37 @@ pub mod tests {
|
||||
peer_mgr_b.my_peer_id()
|
||||
);
|
||||
|
||||
let s = MockService {
|
||||
prefix: "hello_a".to_owned(),
|
||||
};
|
||||
peer_mgr_b.get_peer_rpc_mgr().run_service(1, s.serve());
|
||||
let b = MockService {
|
||||
prefix: "hello_b".to_owned(),
|
||||
};
|
||||
peer_mgr_b.get_peer_rpc_mgr().run_service(2, b.serve());
|
||||
register_service(&peer_mgr_b.get_peer_rpc_mgr(), "test1", 0, "Hello");
|
||||
register_service(&peer_mgr_b.get_peer_rpc_mgr(), "test2", 20000, "Hello2");
|
||||
|
||||
let stub1 = peer_mgr_a
|
||||
.get_peer_rpc_mgr()
|
||||
.rpc_client()
|
||||
.scoped_client::<GreetingClientFactory<RpcController>>(
|
||||
peer_mgr_a.my_peer_id(),
|
||||
peer_mgr_b.my_peer_id(),
|
||||
"test1".to_string(),
|
||||
);
|
||||
|
||||
let stub2 = peer_mgr_a
|
||||
.get_peer_rpc_mgr()
|
||||
.rpc_client()
|
||||
.scoped_client::<GreetingClientFactory<RpcController>>(
|
||||
peer_mgr_a.my_peer_id(),
|
||||
peer_mgr_b.my_peer_id(),
|
||||
"test2".to_string(),
|
||||
);
|
||||
|
||||
let msg = random_string(16 * 1024);
|
||||
let ip_list = peer_mgr_a
|
||||
.get_peer_rpc_mgr()
|
||||
.do_client_rpc_scoped(1, peer_mgr_b.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), msg.clone()).await;
|
||||
ret
|
||||
})
|
||||
let ret = stub1
|
||||
.say_hello(RpcController {}, SayHelloRequest { name: msg.clone() })
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(ret.greeting, format!("Hello {}!", msg));
|
||||
|
||||
let ret = stub2
|
||||
.say_hello(RpcController {}, SayHelloRequest { name: msg.clone() })
|
||||
.await;
|
||||
assert_eq!(ip_list.unwrap(), format!("hello_a {}", msg));
|
||||
|
||||
let msg = random_string(16 * 1024);
|
||||
let ip_list = peer_mgr_a
|
||||
.get_peer_rpc_mgr()
|
||||
.do_client_rpc_scoped(2, peer_mgr_b.my_peer_id(), |c| async {
|
||||
let c = TestRpcServiceClient::new(tarpc::client::Config::default(), c).spawn();
|
||||
let ret = c.hello(tarpc::context::current(), msg.clone()).await;
|
||||
ret
|
||||
})
|
||||
.await;
|
||||
|
||||
assert_eq!(ip_list.unwrap(), format!("hello_b {}", msg));
|
||||
|
||||
wait_for_condition(
|
||||
|| async { peer_mgr_b.get_peer_rpc_mgr().peer_rpc_endpoints.is_empty() },
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
.await;
|
||||
assert!(ret.is_err() && ret.unwrap_err().to_string().contains("Timeout"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
use std::{net::Ipv4Addr, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use tokio_util::bytes::Bytes;
|
||||
|
||||
use crate::common::{error::Error, PeerId};
|
||||
use crate::common::PeerId;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum NextHopPolicy {
|
||||
@@ -17,15 +14,9 @@ impl Default for NextHopPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait::async_trait]
|
||||
pub trait RouteInterface {
|
||||
async fn list_peers(&self) -> Vec<PeerId>;
|
||||
async fn send_route_packet(
|
||||
&self,
|
||||
msg: Bytes,
|
||||
route_id: u8,
|
||||
dst_peer_id: PeerId,
|
||||
) -> Result<(), Error>;
|
||||
fn my_peer_id(&self) -> PeerId;
|
||||
}
|
||||
|
||||
@@ -56,7 +47,7 @@ impl RouteCostCalculatorInterface for DefaultRouteCostCalculator {}
|
||||
|
||||
pub type RouteCostCalculator = Box<dyn RouteCostCalculatorInterface>;
|
||||
|
||||
#[async_trait]
|
||||
#[async_trait::async_trait]
|
||||
#[auto_impl::auto_impl(Box, Arc)]
|
||||
pub trait Route {
|
||||
async fn open(&self, interface: RouteInterfaceBox) -> Result<u8, ()>;
|
||||
@@ -71,7 +62,7 @@ pub trait Route {
|
||||
self.get_next_hop(peer_id).await
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::rpc::Route>;
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route>;
|
||||
|
||||
async fn get_peer_id_by_ipv4(&self, _ipv4: &Ipv4Addr) -> Option<PeerId> {
|
||||
None
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::rpc::{
|
||||
cli::PeerInfo, peer_manage_rpc_server::PeerManageRpc, DumpRouteRequest, DumpRouteResponse,
|
||||
ListForeignNetworkRequest, ListForeignNetworkResponse, ListPeerRequest, ListPeerResponse,
|
||||
ListRouteRequest, ListRouteResponse, ShowNodeInfoRequest, ShowNodeInfoResponse,
|
||||
use crate::proto::{
|
||||
cli::{
|
||||
DumpRouteRequest, DumpRouteResponse, ListForeignNetworkRequest, ListForeignNetworkResponse,
|
||||
ListPeerRequest, ListPeerResponse, ListRouteRequest, ListRouteResponse, PeerInfo,
|
||||
PeerManageRpc, ShowNodeInfoRequest, ShowNodeInfoResponse,
|
||||
},
|
||||
rpc_types::{self, controller::BaseController},
|
||||
};
|
||||
use tonic::{Request, Response, Status};
|
||||
|
||||
use super::peer_manager::PeerManager;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PeerManagerRpcService {
|
||||
peer_manager: Arc<PeerManager>,
|
||||
}
|
||||
@@ -36,12 +39,14 @@ impl PeerManagerRpcService {
|
||||
}
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
#[async_trait::async_trait]
|
||||
impl PeerManageRpc for PeerManagerRpcService {
|
||||
type Controller = BaseController;
|
||||
async fn list_peer(
|
||||
&self,
|
||||
_request: Request<ListPeerRequest>, // Accept request of type HelloRequest
|
||||
) -> Result<Response<ListPeerResponse>, Status> {
|
||||
_: BaseController,
|
||||
_request: ListPeerRequest, // Accept request of type HelloRequest
|
||||
) -> Result<ListPeerResponse, rpc_types::error::Error> {
|
||||
let mut reply = ListPeerResponse::default();
|
||||
|
||||
let peers = self.list_peers().await;
|
||||
@@ -49,45 +54,49 @@ impl PeerManageRpc for PeerManagerRpcService {
|
||||
reply.peer_infos.push(peer);
|
||||
}
|
||||
|
||||
Ok(Response::new(reply))
|
||||
Ok(reply)
|
||||
}
|
||||
|
||||
async fn list_route(
|
||||
&self,
|
||||
_request: Request<ListRouteRequest>, // Accept request of type HelloRequest
|
||||
) -> Result<Response<ListRouteResponse>, Status> {
|
||||
_: BaseController,
|
||||
_request: ListRouteRequest, // Accept request of type HelloRequest
|
||||
) -> Result<ListRouteResponse, rpc_types::error::Error> {
|
||||
let mut reply = ListRouteResponse::default();
|
||||
reply.routes = self.peer_manager.list_routes().await;
|
||||
Ok(Response::new(reply))
|
||||
Ok(reply)
|
||||
}
|
||||
|
||||
async fn dump_route(
|
||||
&self,
|
||||
_request: Request<DumpRouteRequest>, // Accept request of type HelloRequest
|
||||
) -> Result<Response<DumpRouteResponse>, Status> {
|
||||
_: BaseController,
|
||||
_request: DumpRouteRequest, // Accept request of type HelloRequest
|
||||
) -> Result<DumpRouteResponse, rpc_types::error::Error> {
|
||||
let mut reply = DumpRouteResponse::default();
|
||||
reply.result = self.peer_manager.dump_route().await;
|
||||
Ok(Response::new(reply))
|
||||
Ok(reply)
|
||||
}
|
||||
|
||||
async fn list_foreign_network(
|
||||
&self,
|
||||
_request: Request<ListForeignNetworkRequest>, // Accept request of type HelloRequest
|
||||
) -> Result<Response<ListForeignNetworkResponse>, Status> {
|
||||
_: BaseController,
|
||||
_request: ListForeignNetworkRequest, // Accept request of type HelloRequest
|
||||
) -> Result<ListForeignNetworkResponse, rpc_types::error::Error> {
|
||||
let reply = self
|
||||
.peer_manager
|
||||
.get_foreign_network_manager()
|
||||
.list_foreign_networks()
|
||||
.await;
|
||||
Ok(Response::new(reply))
|
||||
Ok(reply)
|
||||
}
|
||||
|
||||
async fn show_node_info(
|
||||
&self,
|
||||
_request: Request<ShowNodeInfoRequest>, // Accept request of type HelloRequest
|
||||
) -> Result<Response<ShowNodeInfoResponse>, Status> {
|
||||
Ok(Response::new(ShowNodeInfoResponse {
|
||||
_: BaseController,
|
||||
_request: ShowNodeInfoRequest, // Accept request of type HelloRequest
|
||||
) -> Result<ShowNodeInfoResponse, rpc_types::error::Error> {
|
||||
Ok(ShowNodeInfoResponse {
|
||||
node_info: Some(self.peer_manager.get_my_info()),
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user