mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 10:14:35 +00:00
refactor(rpc): Centralize RPC service and unify API (#1427)
This change introduces a major refactoring of the RPC service layer to improve modularity, unify the API, and simplify the overall architecture. Key changes: - Replaced per-network-instance RPC services with a single global RPC server, reducing resource usage and simplifying management. - All clients (CLI, Web UI, etc.) now interact with EasyTier core through a unified RPC entrypoint, enabling consistent authentication and control. - RPC implementation logic has been moved to `easytier/src/rpc_service/` and organized by functionality (e.g., `instance_manage.rs`, `peer_manage.rs`, `config.rs`) for better maintainability. - Standardized Protobuf API definitions under `easytier/src/proto/` with an `api_` prefix (e.g., `cli.proto` → `api_instance.proto`) to provide a consistent interface. - CLI commands now require explicit `--instance-id` or `--instance-name` when multiple network instances are running; the parameter is optional when only one instance exists. BREAKING CHANGE: RPC portal configuration (`rpc_portal` and `rpc_portal_whitelist`) has been removed from per-instance configs and the Web UI. The RPC listen address must now be specified globally via the `--rpc-portal` command-line flag or the `ET_RPC_PORTAL` environment variable, as there is only one RPC service for the entire application.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{
|
||||
AclManageRpc, GetAclStatsRequest, GetAclStatsResponse, GetWhitelistRequest,
|
||||
GetWhitelistResponse,
|
||||
},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AclManageRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl AclManageRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl AclManageRpc for AclManageRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn get_acl_stats(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: GetAclStatsRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<GetAclStatsResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_acl_manage_service()
|
||||
.get_acl_stats(ctrl, req)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_whitelist(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: GetWhitelistRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<GetWhitelistResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_acl_manage_service()
|
||||
.get_whitelist(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use anyhow::Context;
|
||||
use cidr::IpCidr;
|
||||
|
||||
use crate::{
|
||||
instance::instance::InstanceRpcServerHook,
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::{
|
||||
config::ConfigRpcServer,
|
||||
instance::{
|
||||
AclManageRpcServer, ConnectorManageRpcServer, MappedListenerManageRpcServer,
|
||||
PeerManageRpcServer, PortForwardManageRpcServer, StatsRpcServer, TcpProxyRpcServer,
|
||||
VpnPortalRpcServer,
|
||||
},
|
||||
logger::LoggerRpcServer,
|
||||
manage::WebClientServiceServer,
|
||||
},
|
||||
rpc_impl::{service_registry::ServiceRegistry, standalone::StandAloneServer},
|
||||
rpc_types::error::Error,
|
||||
},
|
||||
rpc_service::{
|
||||
acl_manage::AclManageRpcService, config::ConfigRpcService,
|
||||
connector_manage::ConnectorManageRpcService, instance_manage::InstanceManageRpcService,
|
||||
logger::LoggerRpcService, mapped_listener_manage::MappedListenerManageRpcService,
|
||||
peer_manage::PeerManageRpcService, port_forward_manage::PortForwardManageRpcService,
|
||||
proxy::TcpProxyRpcService, stats::StatsRpcService, vpn_portal::VpnPortalRpcService,
|
||||
},
|
||||
tunnel::tcp::TcpTunnelListener,
|
||||
};
|
||||
|
||||
pub struct ApiRpcServer {
|
||||
rpc_server: StandAloneServer<TcpTunnelListener>,
|
||||
}
|
||||
|
||||
impl ApiRpcServer {
|
||||
pub fn new(
|
||||
rpc_portal: Option<String>,
|
||||
rpc_portal_whitelist: Option<Vec<IpCidr>>,
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
) -> anyhow::Result<Self> {
|
||||
let mut rpc_server = StandAloneServer::new(TcpTunnelListener::new(
|
||||
format!("tcp://{}", parse_rpc_portal(rpc_portal)?)
|
||||
.parse()
|
||||
.context("failed to parse rpc portal address")?,
|
||||
));
|
||||
rpc_server.set_hook(Arc::new(InstanceRpcServerHook::new(rpc_portal_whitelist)));
|
||||
register_api_rpc_service(&instance_manager, rpc_server.registry());
|
||||
Ok(Self { rpc_server })
|
||||
}
|
||||
|
||||
pub async fn serve(mut self) -> Result<Self, Error> {
|
||||
self.rpc_server.serve().await?;
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ApiRpcServer {
|
||||
fn drop(&mut self) {
|
||||
self.rpc_server.registry().unregister_all();
|
||||
}
|
||||
}
|
||||
|
||||
fn register_api_rpc_service(
|
||||
instance_manager: &Arc<NetworkInstanceManager>,
|
||||
registry: &ServiceRegistry,
|
||||
) {
|
||||
registry.register(
|
||||
PeerManageRpcServer::new(PeerManageRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
|
||||
registry.register(
|
||||
ConnectorManageRpcServer::new(ConnectorManageRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
|
||||
registry.register(
|
||||
MappedListenerManageRpcServer::new(MappedListenerManageRpcService::new(
|
||||
instance_manager.clone(),
|
||||
)),
|
||||
"",
|
||||
);
|
||||
|
||||
registry.register(
|
||||
VpnPortalRpcServer::new(VpnPortalRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
|
||||
for client_type in ["tcp", "kcp_src", "kcp_dst", "quic_src", "quic_dst"] {
|
||||
registry.register(
|
||||
TcpProxyRpcServer::new(TcpProxyRpcService::new(
|
||||
instance_manager.clone(),
|
||||
client_type,
|
||||
)),
|
||||
client_type,
|
||||
);
|
||||
}
|
||||
|
||||
registry.register(
|
||||
AclManageRpcServer::new(AclManageRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
|
||||
registry.register(
|
||||
PortForwardManageRpcServer::new(PortForwardManageRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
|
||||
registry.register(
|
||||
StatsRpcServer::new(StatsRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
|
||||
registry.register(LoggerRpcServer::new(LoggerRpcService), "");
|
||||
|
||||
registry.register(
|
||||
ConfigRpcServer::new(ConfigRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
|
||||
registry.register(
|
||||
WebClientServiceServer::new(InstanceManageRpcService::new(instance_manager.clone())),
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
fn parse_rpc_portal(rpc_portal: Option<String>) -> anyhow::Result<SocketAddr> {
|
||||
if let Some(Ok(port)) = rpc_portal.as_ref().map(|s| s.parse::<u16>()) {
|
||||
Ok(SocketAddr::from(([0, 0, 0, 0], port)))
|
||||
} else {
|
||||
let mut rpc_addr = rpc_portal
|
||||
.map(|addr| {
|
||||
addr.parse::<SocketAddr>()
|
||||
.context("failed to parse rpc portal address")
|
||||
})
|
||||
.transpose()?;
|
||||
select_proper_rpc_port(&mut rpc_addr)?;
|
||||
rpc_addr.ok_or_else(|| anyhow::anyhow!("failed to parse rpc portal address"))
|
||||
}
|
||||
}
|
||||
|
||||
fn select_proper_rpc_port(addr: &mut Option<SocketAddr>) -> anyhow::Result<()> {
|
||||
match addr {
|
||||
None => {
|
||||
*addr = Some(SocketAddr::from(([0, 0, 0, 0], 0)));
|
||||
select_proper_rpc_port(addr)?;
|
||||
Ok(())
|
||||
}
|
||||
Some(addr) => {
|
||||
if addr.port() == 0 {
|
||||
let Some(port) = crate::utils::find_free_tcp_port(15888..15900) else {
|
||||
tracing::warn!(
|
||||
"No free port found for RPC portal, skipping setting RPC portal"
|
||||
);
|
||||
return Err(anyhow::anyhow!("No free port found for RPC portal"));
|
||||
};
|
||||
addr.set_port(port);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::config::{ConfigRpc, PatchConfigRequest, PatchConfigResponse},
|
||||
rpc_types::{self, controller::BaseController},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConfigRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl ConfigRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ConfigRpc for ConfigRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn patch_config(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
input: PatchConfigRequest,
|
||||
) -> Result<PatchConfigResponse, rpc_types::error::Error> {
|
||||
super::get_instance_service(&self.instance_manager, &input.instance)?
|
||||
.get_config_service()
|
||||
.patch_config(ctrl, input)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{ConnectorManageRpc, ListConnectorRequest, ListConnectorResponse},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConnectorManageRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl ConnectorManageRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ConnectorManageRpc for ConnectorManageRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn list_connector(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: ListConnectorRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<ListConnectorResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_connector_manage_service()
|
||||
.list_connector(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
common::config::ConfigLoader,
|
||||
instance_manager::NetworkInstanceManager,
|
||||
launcher::ConfigSource,
|
||||
proto::{
|
||||
api::manage::*,
|
||||
rpc_types::{self, controller::BaseController},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InstanceManageRpcService {
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl InstanceManageRpcService {
|
||||
pub fn new(manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl WebClientService for InstanceManageRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn validate_config(
|
||||
&self,
|
||||
_: BaseController,
|
||||
req: ValidateConfigRequest,
|
||||
) -> Result<ValidateConfigResponse, rpc_types::error::Error> {
|
||||
let toml_config = req.config.unwrap_or_default().gen_config()?.dump();
|
||||
Ok(ValidateConfigResponse { toml_config })
|
||||
}
|
||||
|
||||
async fn run_network_instance(
|
||||
&self,
|
||||
_: BaseController,
|
||||
req: RunNetworkInstanceRequest,
|
||||
) -> Result<RunNetworkInstanceResponse, rpc_types::error::Error> {
|
||||
if req.config.is_none() {
|
||||
return Err(anyhow::anyhow!("config is required").into());
|
||||
}
|
||||
let cfg = req.config.unwrap().gen_config()?;
|
||||
let id = cfg.get_id();
|
||||
if let Some(inst_id) = req.inst_id {
|
||||
cfg.set_id(inst_id.into());
|
||||
}
|
||||
self.manager.run_network_instance(cfg, ConfigSource::Web)?;
|
||||
println!("instance {} started", id);
|
||||
Ok(RunNetworkInstanceResponse {
|
||||
inst_id: Some(id.into()),
|
||||
})
|
||||
}
|
||||
|
||||
async fn retain_network_instance(
|
||||
&self,
|
||||
_: BaseController,
|
||||
req: RetainNetworkInstanceRequest,
|
||||
) -> Result<RetainNetworkInstanceResponse, rpc_types::error::Error> {
|
||||
let remain = self
|
||||
.manager
|
||||
.retain_network_instance(req.inst_ids.into_iter().map(Into::into).collect())?;
|
||||
println!("instance {:?} retained", remain);
|
||||
Ok(RetainNetworkInstanceResponse {
|
||||
remain_inst_ids: remain.iter().map(|item| (*item).into()).collect(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn collect_network_info(
|
||||
&self,
|
||||
_: BaseController,
|
||||
req: CollectNetworkInfoRequest,
|
||||
) -> Result<CollectNetworkInfoResponse, rpc_types::error::Error> {
|
||||
let mut ret = NetworkInstanceRunningInfoMap {
|
||||
map: self
|
||||
.manager
|
||||
.collect_network_infos()?
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k.to_string(), v))
|
||||
.collect(),
|
||||
};
|
||||
let include_inst_ids = req
|
||||
.inst_ids
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|id| id.to_string())
|
||||
.collect::<Vec<_>>();
|
||||
if !include_inst_ids.is_empty() {
|
||||
let mut to_remove = Vec::new();
|
||||
for (k, _) in ret.map.iter() {
|
||||
if !include_inst_ids.contains(k) {
|
||||
to_remove.push(k.clone());
|
||||
}
|
||||
}
|
||||
|
||||
for k in to_remove {
|
||||
ret.map.remove(&k);
|
||||
}
|
||||
}
|
||||
Ok(CollectNetworkInfoResponse { info: Some(ret) })
|
||||
}
|
||||
|
||||
// rpc ListNetworkInstance(ListNetworkInstanceRequest) returns (ListNetworkInstanceResponse) {}
|
||||
async fn list_network_instance(
|
||||
&self,
|
||||
_: BaseController,
|
||||
_: ListNetworkInstanceRequest,
|
||||
) -> Result<ListNetworkInstanceResponse, rpc_types::error::Error> {
|
||||
Ok(ListNetworkInstanceResponse {
|
||||
inst_ids: self
|
||||
.manager
|
||||
.list_network_instance_ids()
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
|
||||
// rpc DeleteNetworkInstance(DeleteNetworkInstanceRequest) returns (DeleteNetworkInstanceResponse) {}
|
||||
async fn delete_network_instance(
|
||||
&self,
|
||||
_: BaseController,
|
||||
req: DeleteNetworkInstanceRequest,
|
||||
) -> Result<DeleteNetworkInstanceResponse, rpc_types::error::Error> {
|
||||
let remain_inst_ids = self
|
||||
.manager
|
||||
.delete_network_instance(req.inst_ids.into_iter().map(Into::into).collect())?;
|
||||
println!("instance {:?} retained", remain_inst_ids);
|
||||
Ok(DeleteNetworkInstanceResponse {
|
||||
remain_inst_ids: remain_inst_ids.into_iter().map(Into::into).collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
use std::sync::{mpsc::Sender, Mutex, OnceLock};
|
||||
|
||||
use crate::proto::{
|
||||
api::logger::{
|
||||
GetLoggerConfigRequest, GetLoggerConfigResponse, LogLevel, LoggerRpc,
|
||||
SetLoggerConfigRequest, SetLoggerConfigResponse,
|
||||
},
|
||||
rpc_types::{self, controller::BaseController},
|
||||
};
|
||||
|
||||
pub static LOGGER_LEVEL_SENDER: std::sync::OnceLock<Mutex<Sender<String>>> = OnceLock::new();
|
||||
pub static CURRENT_LOG_LEVEL: std::sync::OnceLock<Mutex<String>> = OnceLock::new();
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct LoggerRpcService;
|
||||
|
||||
impl LoggerRpcService {
|
||||
fn log_level_to_string(level: LogLevel) -> String {
|
||||
match level {
|
||||
LogLevel::Disabled => "off".to_string(),
|
||||
LogLevel::Error => "error".to_string(),
|
||||
LogLevel::Warning => "warn".to_string(),
|
||||
LogLevel::Info => "info".to_string(),
|
||||
LogLevel::Debug => "debug".to_string(),
|
||||
LogLevel::Trace => "trace".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn string_to_log_level(level_str: &str) -> LogLevel {
|
||||
match level_str.to_lowercase().as_str() {
|
||||
"off" | "disabled" => LogLevel::Disabled,
|
||||
"error" => LogLevel::Error,
|
||||
"warn" | "warning" => LogLevel::Warning,
|
||||
"info" => LogLevel::Info,
|
||||
"debug" => LogLevel::Debug,
|
||||
"trace" => LogLevel::Trace,
|
||||
_ => LogLevel::Info, // 默认为 Info 级别
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl LoggerRpc for LoggerRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn set_logger_config(
|
||||
&self,
|
||||
_: BaseController,
|
||||
request: SetLoggerConfigRequest,
|
||||
) -> Result<SetLoggerConfigResponse, rpc_types::error::Error> {
|
||||
let level_str = Self::log_level_to_string(request.level());
|
||||
|
||||
// 更新当前日志级别
|
||||
if let Some(current_level) = CURRENT_LOG_LEVEL.get() {
|
||||
if let Ok(mut level) = current_level.lock() {
|
||||
*level = level_str.clone();
|
||||
}
|
||||
}
|
||||
|
||||
// 发送新的日志级别到 logger 重载器
|
||||
if let Some(sender) = LOGGER_LEVEL_SENDER.get() {
|
||||
if let Ok(sender) = sender.lock() {
|
||||
if let Err(e) = sender.send(level_str) {
|
||||
tracing::warn!("Failed to send new log level to reloader: {}", e);
|
||||
return Err(rpc_types::error::Error::ExecutionError(anyhow::anyhow!(
|
||||
"Failed to update log level: {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
return Err(rpc_types::error::Error::ExecutionError(anyhow::anyhow!(
|
||||
"Logger sender is not available"
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
return Err(rpc_types::error::Error::ExecutionError(anyhow::anyhow!(
|
||||
"Logger reloader is not initialized"
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(SetLoggerConfigResponse {})
|
||||
}
|
||||
|
||||
async fn get_logger_config(
|
||||
&self,
|
||||
_: BaseController,
|
||||
_request: GetLoggerConfigRequest,
|
||||
) -> Result<GetLoggerConfigResponse, rpc_types::error::Error> {
|
||||
let current_level_str = if let Some(current_level) = CURRENT_LOG_LEVEL.get() {
|
||||
if let Ok(level) = current_level.lock() {
|
||||
level.clone()
|
||||
} else {
|
||||
"info".to_string() // 默认级别
|
||||
}
|
||||
} else {
|
||||
"info".to_string() // 默认级别
|
||||
};
|
||||
|
||||
let level = Self::string_to_log_level(¤t_level_str);
|
||||
|
||||
Ok(GetLoggerConfigResponse {
|
||||
level: level.into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{
|
||||
ListMappedListenerRequest, ListMappedListenerResponse, MappedListenerManageRpc,
|
||||
},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MappedListenerManageRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl MappedListenerManageRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MappedListenerManageRpc for MappedListenerManageRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn list_mapped_listener(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: ListMappedListenerRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<ListMappedListenerResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_mapped_listener_manage_service()
|
||||
.list_mapped_listener(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
mod acl_manage;
|
||||
mod api;
|
||||
mod config;
|
||||
mod connector_manage;
|
||||
mod mapped_listener_manage;
|
||||
mod peer_manage;
|
||||
mod port_forward_manage;
|
||||
mod proxy;
|
||||
mod stats;
|
||||
mod vpn_portal;
|
||||
|
||||
pub mod instance_manage;
|
||||
pub mod logger;
|
||||
|
||||
pub type ApiRpcServer = self::api::ApiRpcServer;
|
||||
|
||||
pub trait InstanceRpcService: Sync + Send {
|
||||
fn get_peer_manage_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::instance::PeerManageRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
fn get_connector_manage_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::instance::ConnectorManageRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
fn get_mapped_listener_manage_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::instance::MappedListenerManageRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
fn get_vpn_portal_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::instance::VpnPortalRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
fn get_proxy_service(
|
||||
&self,
|
||||
client_type: &str,
|
||||
) -> Option<
|
||||
std::sync::Arc<
|
||||
dyn crate::proto::api::instance::TcpProxyRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
> + Send
|
||||
+ Sync,
|
||||
>,
|
||||
>;
|
||||
fn get_acl_manage_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::instance::AclManageRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
fn get_port_forward_manage_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::instance::PortForwardManageRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
fn get_stats_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::instance::StatsRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
fn get_config_service(
|
||||
&self,
|
||||
) -> &dyn crate::proto::api::config::ConfigRpc<
|
||||
Controller = crate::proto::rpc_types::controller::BaseController,
|
||||
>;
|
||||
}
|
||||
|
||||
fn get_instance_service(
|
||||
instance_manager: &std::sync::Arc<crate::instance_manager::NetworkInstanceManager>,
|
||||
identifier: &Option<crate::proto::api::instance::InstanceIdentifier>,
|
||||
) -> Result<std::sync::Arc<dyn InstanceRpcService>, anyhow::Error> {
|
||||
use crate::proto::api;
|
||||
let selector = identifier.as_ref().and_then(|s| s.selector.as_ref());
|
||||
|
||||
let id = if let Some(api::instance::instance_identifier::Selector::Id(id)) = selector {
|
||||
(*id).into()
|
||||
} else {
|
||||
let ids = instance_manager.filter_network_instance(|_, i| {
|
||||
if let Some(api::instance::instance_identifier::Selector::InstanceSelector(selector)) =
|
||||
selector
|
||||
{
|
||||
if let Some(name) = selector.name.as_ref() {
|
||||
if i.get_inst_name() != *name {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
match ids.len() {
|
||||
0 => return Err(anyhow::anyhow!("No instance matches the selector")),
|
||||
1 => ids[0],
|
||||
_ => {
|
||||
return Err(anyhow::anyhow!(
|
||||
"{} instances match the selector, please specify the instance ID",
|
||||
ids.len()
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
instance_manager
|
||||
.get_instance_service(&id)
|
||||
.ok_or_else(|| anyhow::anyhow!("Instance not found or API service not available"))
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{self, ListPeerRequest, ListPeerResponse, PeerManageRpc},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PeerManageRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl PeerManageRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl PeerManageRpc for PeerManageRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn list_peer(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: ListPeerRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<ListPeerResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_peer_manage_service()
|
||||
.list_peer(ctrl, req)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_route(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: crate::proto::api::instance::ListRouteRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<instance::ListRouteResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_peer_manage_service()
|
||||
.list_route(ctrl, req)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn dump_route(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: crate::proto::api::instance::DumpRouteRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<instance::DumpRouteResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_peer_manage_service()
|
||||
.dump_route(ctrl, req)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_foreign_network(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: crate::proto::api::instance::ListForeignNetworkRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<instance::ListForeignNetworkResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_peer_manage_service()
|
||||
.list_foreign_network(ctrl, req)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn list_global_foreign_network(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: crate::proto::api::instance::ListGlobalForeignNetworkRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<instance::ListGlobalForeignNetworkResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_peer_manage_service()
|
||||
.list_global_foreign_network(ctrl, req)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn show_node_info(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: crate::proto::api::instance::ShowNodeInfoRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<instance::ShowNodeInfoResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_peer_manage_service()
|
||||
.show_node_info(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{ListPortForwardRequest, ListPortForwardResponse, PortForwardManageRpc},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PortForwardManageRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl PortForwardManageRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl PortForwardManageRpc for PortForwardManageRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn list_port_forward(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: ListPortForwardRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<ListPortForwardResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_port_forward_manage_service()
|
||||
.list_port_forward(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{ListTcpProxyEntryRequest, ListTcpProxyEntryResponse, TcpProxyRpc},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TcpProxyRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
client_type: &'static str,
|
||||
}
|
||||
|
||||
impl TcpProxyRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>, client_type: &'static str) -> Self {
|
||||
Self {
|
||||
instance_manager,
|
||||
client_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl TcpProxyRpc for TcpProxyRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn list_tcp_proxy_entry(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: ListTcpProxyEntryRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<ListTcpProxyEntryResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_proxy_service(self.client_type)
|
||||
.ok_or_else(|| anyhow::anyhow!("TCP proxy service not found for {}", self.client_type))?
|
||||
.list_tcp_proxy_entry(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{
|
||||
GetPrometheusStatsRequest, GetPrometheusStatsResponse, GetStatsRequest,
|
||||
GetStatsResponse, StatsRpc,
|
||||
},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct StatsRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl StatsRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl StatsRpc for StatsRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn get_stats(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: GetStatsRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<GetStatsResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_stats_service()
|
||||
.get_stats(ctrl, req)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_prometheus_stats(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: GetPrometheusStatsRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<GetPrometheusStatsResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_stats_service()
|
||||
.get_prometheus_stats(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
proto::{
|
||||
api::instance::{GetVpnPortalInfoRequest, GetVpnPortalInfoResponse, VpnPortalRpc},
|
||||
rpc_types::controller::BaseController,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct VpnPortalRpcService {
|
||||
instance_manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl VpnPortalRpcService {
|
||||
pub fn new(instance_manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Self { instance_manager }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl VpnPortalRpc for VpnPortalRpcService {
|
||||
type Controller = BaseController;
|
||||
|
||||
async fn get_vpn_portal_info(
|
||||
&self,
|
||||
ctrl: Self::Controller,
|
||||
req: GetVpnPortalInfoRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<GetVpnPortalInfoResponse> {
|
||||
super::get_instance_service(&self.instance_manager, &req.instance)?
|
||||
.get_vpn_portal_service()
|
||||
.get_vpn_portal_info(ctrl, req)
|
||||
.await
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user