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:
Mg Pig
2025-10-02 20:30:39 +08:00
committed by GitHub
parent d2efbbef04
commit 841d525913
65 changed files with 1953 additions and 1153 deletions
+50
View File
@@ -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
}
}
+164
View File
@@ -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(())
}
}
}
+36
View File
@@ -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
}
}
+135
View File
@@ -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(),
})
}
}
+105
View File
@@ -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(&current_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
}
}
+108
View File
@@ -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"))
}
+91
View File
@@ -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
}
}
+41
View File
@@ -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
}
}
+50
View File
@@ -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
}
}
+36
View File
@@ -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
}
}