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:
@@ -144,11 +144,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proto_files = [
|
||||
"src/proto/error.proto",
|
||||
"src/proto/tests.proto",
|
||||
"src/proto/cli.proto",
|
||||
"src/proto/api_instance.proto",
|
||||
"src/proto/api_logger.proto",
|
||||
"src/proto/api_config.proto",
|
||||
"src/proto/api_manage.proto",
|
||||
"src/proto/web.proto",
|
||||
"src/proto/magic_dns.proto",
|
||||
"src/proto/acl.proto",
|
||||
"src/proto/config.proto",
|
||||
];
|
||||
|
||||
for proto_file in proto_files.iter().chain(proto_files_reflect.iter()) {
|
||||
@@ -161,7 +163,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.type_attribute(".acl", "#[derive(serde::Serialize, serde::Deserialize)]")
|
||||
.type_attribute(".common", "#[derive(serde::Serialize, serde::Deserialize)]")
|
||||
.type_attribute(".error", "#[derive(serde::Serialize, serde::Deserialize)]")
|
||||
.type_attribute(".cli", "#[derive(serde::Serialize, serde::Deserialize)]")
|
||||
.type_attribute(".api", "#[derive(serde::Serialize, serde::Deserialize)]")
|
||||
.type_attribute(".web", "#[derive(serde::Serialize, serde::Deserialize)]")
|
||||
.type_attribute(".config", "#[derive(serde::Serialize, serde::Deserialize)]")
|
||||
.type_attribute(
|
||||
@@ -180,7 +182,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
"#[derive(Hash, Eq, serde::Serialize, serde::Deserialize)]",
|
||||
)
|
||||
.type_attribute("common.RpcDescriptor", "#[derive(Hash, Eq)]")
|
||||
.field_attribute(".web.NetworkConfig", "#[serde(default)]")
|
||||
.field_attribute(".api.manage.NetworkConfig", "#[serde(default)]")
|
||||
.service_generator(Box::new(rpc_build::ServiceGenerator::new()))
|
||||
.btree_map(["."])
|
||||
.skip_debug([".common.Ipv4Addr", ".common.Ipv6Addr", ".common.UUID"]);
|
||||
|
||||
@@ -6,7 +6,6 @@ use std::{
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use cidr::IpCidr;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@@ -169,12 +168,6 @@ pub trait ConfigLoader: Send + Sync {
|
||||
fn get_mapped_listeners(&self) -> Vec<url::Url>;
|
||||
fn set_mapped_listeners(&self, listeners: Option<Vec<url::Url>>);
|
||||
|
||||
fn get_rpc_portal(&self) -> Option<SocketAddr>;
|
||||
fn set_rpc_portal(&self, addr: SocketAddr);
|
||||
|
||||
fn get_rpc_portal_whitelist(&self) -> Option<Vec<IpCidr>>;
|
||||
fn set_rpc_portal_whitelist(&self, whitelist: Option<Vec<IpCidr>>);
|
||||
|
||||
fn get_vpn_portal_config(&self) -> Option<VpnPortalConfig>;
|
||||
fn set_vpn_portal_config(&self, config: VpnPortalConfig);
|
||||
|
||||
@@ -398,9 +391,6 @@ struct Config {
|
||||
peer: Option<Vec<PeerConfig>>,
|
||||
proxy_network: Option<Vec<ProxyNetworkConfig>>,
|
||||
|
||||
rpc_portal: Option<SocketAddr>,
|
||||
rpc_portal_whitelist: Option<Vec<IpCidr>>,
|
||||
|
||||
vpn_portal_config: Option<VpnPortalConfig>,
|
||||
|
||||
routes: Option<Vec<cidr::Ipv4Cidr>>,
|
||||
@@ -692,22 +682,6 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
self.config.lock().unwrap().mapped_listeners = listeners;
|
||||
}
|
||||
|
||||
fn get_rpc_portal(&self) -> Option<SocketAddr> {
|
||||
self.config.lock().unwrap().rpc_portal
|
||||
}
|
||||
|
||||
fn set_rpc_portal(&self, addr: SocketAddr) {
|
||||
self.config.lock().unwrap().rpc_portal = Some(addr);
|
||||
}
|
||||
|
||||
fn get_rpc_portal_whitelist(&self) -> Option<Vec<IpCidr>> {
|
||||
self.config.lock().unwrap().rpc_portal_whitelist.clone()
|
||||
}
|
||||
|
||||
fn set_rpc_portal_whitelist(&self, whitelist: Option<Vec<IpCidr>>) {
|
||||
self.config.lock().unwrap().rpc_portal_whitelist = whitelist;
|
||||
}
|
||||
|
||||
fn get_vpn_portal_config(&self) -> Option<VpnPortalConfig> {
|
||||
self.config.lock().unwrap().vpn_portal_config.clone()
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ use crate::common::stats_manager::StatsManager;
|
||||
use crate::common::token_bucket::TokenBucketManager;
|
||||
use crate::peers::acl_filter::AclFilter;
|
||||
use crate::proto::acl::GroupIdentity;
|
||||
use crate::proto::cli::PeerConnInfo;
|
||||
use crate::proto::api::config::InstanceConfigPatch;
|
||||
use crate::proto::api::instance::PeerConnInfo;
|
||||
use crate::proto::common::{PeerFeatureFlag, PortForwardConfigPb};
|
||||
use crate::proto::config::InstanceConfigPatch;
|
||||
use crate::proto::peer_rpc::PeerGroupInfo;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
|
||||
|
||||
@@ -664,7 +664,7 @@ impl Default for StatsManager {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::common::stats_manager::{LabelSet, LabelType, MetricName, StatsManager};
|
||||
use crate::proto::cli::{
|
||||
use crate::proto::api::instance::{
|
||||
GetPrometheusStatsRequest, GetPrometheusStatsResponse, GetStatsRequest, GetStatsResponse,
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
@@ -818,16 +818,19 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_stats_rpc_data_structures() {
|
||||
// Test GetStatsRequest
|
||||
let request = GetStatsRequest {};
|
||||
assert_eq!(request, GetStatsRequest {});
|
||||
let request = GetStatsRequest { instance: None };
|
||||
assert_eq!(request, GetStatsRequest { instance: None });
|
||||
|
||||
// Test GetStatsResponse
|
||||
let response = GetStatsResponse { metrics: vec![] };
|
||||
assert!(response.metrics.is_empty());
|
||||
|
||||
// Test GetPrometheusStatsRequest
|
||||
let prometheus_request = GetPrometheusStatsRequest {};
|
||||
assert_eq!(prometheus_request, GetPrometheusStatsRequest {});
|
||||
let prometheus_request = GetPrometheusStatsRequest { instance: None };
|
||||
assert_eq!(
|
||||
prometheus_request,
|
||||
GetPrometheusStatsRequest { instance: None }
|
||||
);
|
||||
|
||||
// Test GetPrometheusStatsResponse
|
||||
let prometheus_response = GetPrometheusStatsResponse {
|
||||
@@ -867,7 +870,7 @@ mod tests {
|
||||
}
|
||||
|
||||
// This simulates what the RPC service would do
|
||||
let _metric_snapshot = crate::proto::cli::MetricSnapshot {
|
||||
let _metric_snapshot = crate::proto::api::instance::MetricSnapshot {
|
||||
name: metric.name.to_string(),
|
||||
value: metric.value,
|
||||
labels,
|
||||
|
||||
@@ -35,7 +35,7 @@ use crate::{
|
||||
use_global_var,
|
||||
};
|
||||
|
||||
use crate::proto::cli::PeerConnInfo;
|
||||
use crate::proto::api::instance::PeerConnInfo;
|
||||
use anyhow::Context;
|
||||
use rand::Rng;
|
||||
use tokio::{net::UdpSocket, task::JoinSet, time::timeout};
|
||||
|
||||
@@ -18,12 +18,14 @@ use crate::{
|
||||
common::{dns::socket_addrs, join_joinset_background, PeerId},
|
||||
peers::peer_conn::PeerConnId,
|
||||
proto::{
|
||||
cli::{
|
||||
ConnectorManageAction, ListConnectorResponse, ManageConnectorResponse, PeerConnInfo,
|
||||
api::instance::{
|
||||
Connector, ConnectorManageRpc, ConnectorStatus, ListConnectorRequest,
|
||||
ListConnectorResponse, PeerConnInfo,
|
||||
},
|
||||
rpc_types::{self, controller::BaseController},
|
||||
},
|
||||
tunnel::{IpVersion, TunnelConnector},
|
||||
utils::weak_upgrade,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -33,10 +35,6 @@ use crate::{
|
||||
netns::NetNS,
|
||||
},
|
||||
peers::peer_manager::PeerManager,
|
||||
proto::cli::{
|
||||
Connector, ConnectorManageRpc, ConnectorStatus, ListConnectorRequest,
|
||||
ManageConnectorRequest,
|
||||
},
|
||||
use_global_var,
|
||||
};
|
||||
|
||||
@@ -126,6 +124,14 @@ impl ManualConnectorManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn clear_connectors(&self) {
|
||||
self.list_connectors().await.iter().for_each(|x| {
|
||||
if let Some(url) = &x.url {
|
||||
self.data.removed_conn_urls.insert(url.to_string());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub async fn list_connectors(&self) -> Vec<Connector> {
|
||||
let conn_urls: BTreeSet<String> = self
|
||||
.data
|
||||
@@ -421,7 +427,7 @@ impl ManualConnectorManager {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ConnectorManagerRpcService(pub Arc<ManualConnectorManager>);
|
||||
pub struct ConnectorManagerRpcService(pub Weak<ManualConnectorManager>);
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ConnectorManageRpc for ConnectorManagerRpcService {
|
||||
@@ -433,31 +439,10 @@ impl ConnectorManageRpc for ConnectorManagerRpcService {
|
||||
_request: ListConnectorRequest,
|
||||
) -> Result<ListConnectorResponse, rpc_types::error::Error> {
|
||||
let mut ret = ListConnectorResponse::default();
|
||||
let connectors = self.0.list_connectors().await;
|
||||
let connectors = weak_upgrade(&self.0)?.list_connectors().await;
|
||||
ret.connectors = connectors;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
async fn manage_connector(
|
||||
&self,
|
||||
_: BaseController,
|
||||
req: ManageConnectorRequest,
|
||||
) -> Result<ManageConnectorResponse, rpc_types::error::Error> {
|
||||
let url: url::Url = req.url.ok_or(anyhow::anyhow!("url is empty"))?.into();
|
||||
if req.action == ConnectorManageAction::Remove as i32 {
|
||||
self.0
|
||||
.remove_connector(url.clone())
|
||||
.await
|
||||
.with_context(|| format!("remove connector failed: {:?}", url))?;
|
||||
return Ok(ManageConnectorResponse::default());
|
||||
} else {
|
||||
self.0
|
||||
.add_connector_by_url(url.as_str())
|
||||
.await
|
||||
.with_context(|| format!("add connector failed: {:?}", url))?;
|
||||
}
|
||||
Ok(ManageConnectorResponse::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -26,25 +26,32 @@ use easytier::{
|
||||
},
|
||||
peers,
|
||||
proto::{
|
||||
cli::{
|
||||
list_peer_route_pair, AclManageRpc, AclManageRpcClientFactory, ConnectorManageRpc,
|
||||
ConnectorManageRpcClientFactory, DumpRouteRequest, GetAclStatsRequest,
|
||||
GetLoggerConfigRequest, GetPrometheusStatsRequest, GetStatsRequest,
|
||||
GetVpnPortalInfoRequest, GetWhitelistRequest, ListConnectorRequest,
|
||||
ListForeignNetworkRequest, ListGlobalForeignNetworkRequest, ListMappedListenerRequest,
|
||||
ListPeerRequest, ListPeerResponse, ListPortForwardRequest, ListRouteRequest,
|
||||
ListRouteResponse, LogLevel, LoggerRpc, LoggerRpcClientFactory,
|
||||
MappedListenerManageRpc, MappedListenerManageRpcClientFactory, NodeInfo, PeerManageRpc,
|
||||
PeerManageRpcClientFactory, PortForwardManageRpc, PortForwardManageRpcClientFactory,
|
||||
SetLoggerConfigRequest, ShowNodeInfoRequest, StatsRpc, StatsRpcClientFactory,
|
||||
TcpProxyEntryState, TcpProxyEntryTransportType, TcpProxyRpc, TcpProxyRpcClientFactory,
|
||||
VpnPortalRpc, VpnPortalRpcClientFactory,
|
||||
api::{
|
||||
config::{
|
||||
AclPatch, ConfigPatchAction, ConfigRpc, ConfigRpcClientFactory,
|
||||
InstanceConfigPatch, PatchConfigRequest, PortForwardPatch, StringPatch, UrlPatch,
|
||||
},
|
||||
instance::{
|
||||
instance_identifier::{InstanceSelector, Selector},
|
||||
list_peer_route_pair, AclManageRpc, AclManageRpcClientFactory, ConnectorManageRpc,
|
||||
ConnectorManageRpcClientFactory, DumpRouteRequest, GetAclStatsRequest,
|
||||
GetPrometheusStatsRequest, GetStatsRequest, GetVpnPortalInfoRequest,
|
||||
GetWhitelistRequest, InstanceIdentifier, ListConnectorRequest,
|
||||
ListForeignNetworkRequest, ListGlobalForeignNetworkRequest,
|
||||
ListMappedListenerRequest, ListPeerRequest, ListPeerResponse,
|
||||
ListPortForwardRequest, ListRouteRequest, ListRouteResponse,
|
||||
MappedListenerManageRpc, MappedListenerManageRpcClientFactory, NodeInfo,
|
||||
PeerManageRpc, PeerManageRpcClientFactory, PortForwardManageRpc,
|
||||
PortForwardManageRpcClientFactory, ShowNodeInfoRequest, StatsRpc,
|
||||
StatsRpcClientFactory, TcpProxyEntryState, TcpProxyEntryTransportType, TcpProxyRpc,
|
||||
TcpProxyRpcClientFactory, VpnPortalRpc, VpnPortalRpcClientFactory,
|
||||
},
|
||||
logger::{
|
||||
GetLoggerConfigRequest, LogLevel, LoggerRpc, LoggerRpcClientFactory,
|
||||
SetLoggerConfigRequest,
|
||||
},
|
||||
},
|
||||
common::{NatType, PortForwardConfigPb, SocketType},
|
||||
config::{
|
||||
AclPatch, ConfigPatchAction, ConfigRpc, ConfigRpcClientFactory, InstanceConfigPatch,
|
||||
PatchConfigRequest, PortForwardPatch, StringPatch, UrlPatch,
|
||||
},
|
||||
peer_rpc::{GetGlobalPeerMapRequest, PeerCenterRpc, PeerCenterRpcClientFactory},
|
||||
rpc_impl::standalone::StandAloneClient,
|
||||
rpc_types::controller::BaseController,
|
||||
@@ -58,8 +65,12 @@ rust_i18n::i18n!("locales", fallback = "en");
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(name = "easytier-cli", author, version = EASYTIER_VERSION, about, long_about = None)]
|
||||
struct Cli {
|
||||
/// the instance name
|
||||
#[arg(short = 'p', long, default_value = "127.0.0.1:15888")]
|
||||
#[arg(
|
||||
short = 'p',
|
||||
long,
|
||||
default_value = "127.0.0.1:15888",
|
||||
help = "easytier-core rpc portal address"
|
||||
)]
|
||||
rpc_portal: SocketAddr,
|
||||
|
||||
#[arg(short, long, default_value = "false", help = "verbose output")]
|
||||
@@ -74,6 +85,9 @@ struct Cli {
|
||||
)]
|
||||
output_format: OutputFormat,
|
||||
|
||||
#[command(flatten)]
|
||||
instance_select: InstanceSelectArgs,
|
||||
|
||||
#[command(subcommand)]
|
||||
sub_command: SubCommand,
|
||||
}
|
||||
@@ -120,6 +134,28 @@ enum OutputFormat {
|
||||
Json,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
struct InstanceSelectArgs {
|
||||
#[arg(short = 'i', long = "instance-id", help = "the instance id")]
|
||||
id: Option<uuid::Uuid>,
|
||||
|
||||
#[arg(short = 'n', long = "instance-name", help = "the instance name")]
|
||||
name: Option<String>,
|
||||
}
|
||||
|
||||
impl From<&InstanceSelectArgs> for InstanceIdentifier {
|
||||
fn from(args: &InstanceSelectArgs) -> Self {
|
||||
InstanceIdentifier {
|
||||
selector: match args.id {
|
||||
Some(id) => Some(Selector::Id(id.into())),
|
||||
None => Some(Selector::InstanceSelector(InstanceSelector {
|
||||
name: args.name.clone(),
|
||||
})),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
struct PeerArgs {
|
||||
#[command(subcommand)]
|
||||
@@ -351,6 +387,7 @@ struct CommandHandler<'a> {
|
||||
client: tokio::sync::Mutex<RpcClient>,
|
||||
verbose: bool,
|
||||
output_format: &'a OutputFormat,
|
||||
instance_selector: InstanceIdentifier,
|
||||
}
|
||||
|
||||
type RpcClient = StandAloneClient<TcpTunnelConnector>;
|
||||
@@ -491,14 +528,18 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn list_peers(&self) -> Result<ListPeerResponse, Error> {
|
||||
let client = self.get_peer_manager_client().await?;
|
||||
let request = ListPeerRequest::default();
|
||||
let request = ListPeerRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client.list_peer(BaseController::default(), request).await?;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Result<ListRouteResponse, Error> {
|
||||
let client = self.get_peer_manager_client().await?;
|
||||
let request = ListRouteRequest::default();
|
||||
let request = ListRouteRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.list_route(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -618,7 +659,12 @@ impl CommandHandler<'_> {
|
||||
|
||||
let client = self.get_peer_manager_client().await?;
|
||||
let node_info = client
|
||||
.show_node_info(BaseController::default(), ShowNodeInfoRequest::default())
|
||||
.show_node_info(
|
||||
BaseController::default(),
|
||||
ShowNodeInfoRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
},
|
||||
)
|
||||
.await?
|
||||
.node_info
|
||||
.ok_or(anyhow::anyhow!("node info not found"))?;
|
||||
@@ -671,7 +717,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_route_dump(&self) -> Result<(), Error> {
|
||||
let client = self.get_peer_manager_client().await?;
|
||||
let request = DumpRouteRequest::default();
|
||||
let request = DumpRouteRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.dump_route(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -681,7 +729,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_foreign_network_list(&self) -> Result<(), Error> {
|
||||
let client = self.get_peer_manager_client().await?;
|
||||
let request = ListForeignNetworkRequest::default();
|
||||
let request = ListForeignNetworkRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.list_foreign_network(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -724,7 +774,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_global_foreign_network_list(&self) -> Result<(), Error> {
|
||||
let client = self.get_peer_manager_client().await?;
|
||||
let request = ListGlobalForeignNetworkRequest::default();
|
||||
let request = ListGlobalForeignNetworkRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.list_global_foreign_network(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -773,7 +825,12 @@ impl CommandHandler<'_> {
|
||||
let mut items: Vec<RouteTableItem> = vec![];
|
||||
let client = self.get_peer_manager_client().await?;
|
||||
let node_info = client
|
||||
.show_node_info(BaseController::default(), ShowNodeInfoRequest::default())
|
||||
.show_node_info(
|
||||
BaseController::default(),
|
||||
ShowNodeInfoRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
},
|
||||
)
|
||||
.await?
|
||||
.node_info
|
||||
.ok_or(anyhow::anyhow!("node info not found"))?;
|
||||
@@ -895,7 +952,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_connector_list(&self) -> Result<(), Error> {
|
||||
let client = self.get_connector_manager_client().await?;
|
||||
let request = ListConnectorRequest::default();
|
||||
let request = ListConnectorRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.list_connector(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -909,7 +968,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_acl_stats(&self) -> Result<(), Error> {
|
||||
let client = self.get_acl_manager_client().await?;
|
||||
let request = GetAclStatsRequest::default();
|
||||
let request = GetAclStatsRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.get_acl_stats(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -929,7 +990,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_mapped_listener_list(&self) -> Result<(), Error> {
|
||||
let client = self.get_mapped_listener_manager_client().await?;
|
||||
let request = ListMappedListenerRequest::default();
|
||||
let request = ListMappedListenerRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.list_mapped_listener(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -952,6 +1015,7 @@ impl CommandHandler<'_> {
|
||||
let url = Self::mapped_listener_validate_url(url)?;
|
||||
let client = self.get_config_client().await?;
|
||||
let request = PatchConfigRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
patch: Some(InstanceConfigPatch {
|
||||
mapped_listeners: vec![UrlPatch {
|
||||
action: action.into(),
|
||||
@@ -997,6 +1061,7 @@ impl CommandHandler<'_> {
|
||||
|
||||
let client = self.get_config_client().await?;
|
||||
let request = PatchConfigRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
patch: Some(InstanceConfigPatch {
|
||||
port_forwards: vec![PortForwardPatch {
|
||||
action: action.into(),
|
||||
@@ -1024,7 +1089,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_port_forward_list(&self) -> Result<(), Error> {
|
||||
let client = self.get_port_forward_manager_client().await?;
|
||||
let request = ListPortForwardRequest::default();
|
||||
let request = ListPortForwardRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.list_port_forward(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -1082,6 +1149,7 @@ impl CommandHandler<'_> {
|
||||
let client = self.get_config_client().await?;
|
||||
|
||||
let request = PatchConfigRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
patch: Some(InstanceConfigPatch {
|
||||
acl: Some(AclPatch {
|
||||
tcp_whitelist: whitelist,
|
||||
@@ -1116,6 +1184,7 @@ impl CommandHandler<'_> {
|
||||
let client = self.get_config_client().await?;
|
||||
|
||||
let request = PatchConfigRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
patch: Some(InstanceConfigPatch {
|
||||
acl: Some(AclPatch {
|
||||
udp_whitelist: whitelist,
|
||||
@@ -1136,6 +1205,7 @@ impl CommandHandler<'_> {
|
||||
let client = self.get_config_client().await?;
|
||||
|
||||
let request = PatchConfigRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
patch: Some(InstanceConfigPatch {
|
||||
acl: Some(AclPatch {
|
||||
tcp_whitelist: vec![StringPatch {
|
||||
@@ -1159,6 +1229,7 @@ impl CommandHandler<'_> {
|
||||
let client = self.get_config_client().await?;
|
||||
|
||||
let request = PatchConfigRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
patch: Some(InstanceConfigPatch {
|
||||
acl: Some(AclPatch {
|
||||
udp_whitelist: vec![StringPatch {
|
||||
@@ -1180,7 +1251,9 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_whitelist_show(&self) -> Result<(), Error> {
|
||||
let client = self.get_acl_manager_client().await?;
|
||||
let request = GetWhitelistRequest::default();
|
||||
let request = GetWhitelistRequest {
|
||||
instance: Some(self.instance_selector.clone()),
|
||||
};
|
||||
let response = client
|
||||
.get_whitelist(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -1213,7 +1286,7 @@ impl CommandHandler<'_> {
|
||||
|
||||
async fn handle_logger_get(&self) -> Result<(), Error> {
|
||||
let client = self.get_logger_client().await?;
|
||||
let request = GetLoggerConfigRequest {};
|
||||
let request = GetLoggerConfigRequest::default();
|
||||
let response = client
|
||||
.get_logger_config(BaseController::default(), request)
|
||||
.await?;
|
||||
@@ -1601,6 +1674,7 @@ async fn main() -> Result<(), Error> {
|
||||
client: tokio::sync::Mutex::new(client),
|
||||
verbose: cli.verbose,
|
||||
output_format: &cli.output_format,
|
||||
instance_selector: (&cli.instance_select).into(),
|
||||
};
|
||||
|
||||
match cli.sub_command {
|
||||
@@ -1700,7 +1774,12 @@ async fn main() -> Result<(), Error> {
|
||||
let node_info = handler
|
||||
.get_peer_manager_client()
|
||||
.await?
|
||||
.show_node_info(BaseController::default(), ShowNodeInfoRequest::default())
|
||||
.show_node_info(
|
||||
BaseController::default(),
|
||||
ShowNodeInfoRequest {
|
||||
instance: Some((&cli.instance_select).into()),
|
||||
},
|
||||
)
|
||||
.await?
|
||||
.node_info
|
||||
.ok_or(anyhow::anyhow!("node info not found"))?;
|
||||
@@ -1804,7 +1883,9 @@ async fn main() -> Result<(), Error> {
|
||||
let resp = vpn_portal_client
|
||||
.get_vpn_portal_info(
|
||||
BaseController::default(),
|
||||
GetVpnPortalInfoRequest::default(),
|
||||
GetVpnPortalInfoRequest {
|
||||
instance: Some((&cli.instance_select).into()),
|
||||
},
|
||||
)
|
||||
.await?
|
||||
.vpn_portal_info
|
||||
@@ -1823,7 +1904,12 @@ async fn main() -> Result<(), Error> {
|
||||
SubCommand::Node(sub_cmd) => {
|
||||
let client = handler.get_peer_manager_client().await?;
|
||||
let node_info = client
|
||||
.show_node_info(BaseController::default(), ShowNodeInfoRequest::default())
|
||||
.show_node_info(
|
||||
BaseController::default(),
|
||||
ShowNodeInfoRequest {
|
||||
instance: Some((&cli.instance_select).into()),
|
||||
},
|
||||
)
|
||||
.await?
|
||||
.node_info
|
||||
.ok_or(anyhow::anyhow!("node info not found"))?;
|
||||
@@ -2058,7 +2144,9 @@ async fn main() -> Result<(), Error> {
|
||||
SubCommand::Stats(stats_args) => match &stats_args.sub_command {
|
||||
Some(StatsSubCommand::Show) | None => {
|
||||
let client = handler.get_stats_client().await?;
|
||||
let request = GetStatsRequest {};
|
||||
let request = GetStatsRequest {
|
||||
instance: Some((&cli.instance_select).into()),
|
||||
};
|
||||
let response = client.get_stats(BaseController::default(), request).await?;
|
||||
|
||||
if cli.output_format == OutputFormat::Json {
|
||||
@@ -2110,7 +2198,9 @@ async fn main() -> Result<(), Error> {
|
||||
}
|
||||
Some(StatsSubCommand::Prometheus) => {
|
||||
let client = handler.get_stats_client().await?;
|
||||
let request = GetPrometheusStatsRequest {};
|
||||
let request = GetPrometheusStatsRequest {
|
||||
instance: Some((&cli.instance_select).into()),
|
||||
};
|
||||
let response = client
|
||||
.get_prometheus_stats(BaseController::default(), request)
|
||||
.await?;
|
||||
|
||||
@@ -30,6 +30,7 @@ use easytier::{
|
||||
instance_manager::NetworkInstanceManager,
|
||||
launcher::{add_proxy_network_to_config, ConfigSource},
|
||||
proto::common::{CompressionAlgoPb, NatType},
|
||||
rpc_service::ApiRpcServer,
|
||||
tunnel::{IpVersion, PROTO_PORT_OFFSET},
|
||||
utils::{init_logger, setup_panic_handler},
|
||||
web_client,
|
||||
@@ -130,6 +131,9 @@ struct Cli {
|
||||
#[command(flatten)]
|
||||
logging_options: LoggingOptions,
|
||||
|
||||
#[command(flatten)]
|
||||
rpc_portal_options: RpcPortalOptions,
|
||||
|
||||
#[clap(long, help = t!("core_clap.generate_completions").to_string())]
|
||||
gen_autocomplete: Option<Shell>,
|
||||
|
||||
@@ -205,22 +209,6 @@ struct NetworkOptions {
|
||||
)]
|
||||
proxy_networks: Vec<String>,
|
||||
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
env = "ET_RPC_PORTAL",
|
||||
help = t!("core_clap.rpc_portal").to_string(),
|
||||
)]
|
||||
rpc_portal: Option<String>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
env = "ET_RPC_PORTAL_WHITELIST",
|
||||
value_delimiter = ',',
|
||||
help = t!("core_clap.rpc_portal_whitelist").to_string(),
|
||||
)]
|
||||
rpc_portal_whitelist: Option<Vec<IpCidr>>,
|
||||
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
@@ -624,6 +612,25 @@ struct LoggingOptions {
|
||||
file_log_count: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
struct RpcPortalOptions {
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
env = "ET_RPC_PORTAL",
|
||||
help = t!("core_clap.rpc_portal").to_string(),
|
||||
)]
|
||||
rpc_portal: Option<String>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
env = "ET_RPC_PORTAL_WHITELIST",
|
||||
value_delimiter = ',',
|
||||
help = t!("core_clap.rpc_portal_whitelist").to_string(),
|
||||
)]
|
||||
rpc_portal_whitelist: Option<Vec<IpCidr>>,
|
||||
}
|
||||
|
||||
rust_i18n::i18n!("locales", fallback = "en");
|
||||
|
||||
impl Cli {
|
||||
@@ -671,14 +678,6 @@ impl Cli {
|
||||
|
||||
Ok(listeners)
|
||||
}
|
||||
|
||||
fn parse_rpc_portal(rpc_portal: String) -> anyhow::Result<SocketAddr> {
|
||||
if let Ok(port) = rpc_portal.parse::<u16>() {
|
||||
return Ok(format!("0.0.0.0:{}", port).parse().unwrap());
|
||||
}
|
||||
|
||||
Ok(rpc_portal.parse()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl NetworkOptions {
|
||||
@@ -786,24 +785,6 @@ impl NetworkOptions {
|
||||
add_proxy_network_to_config(n, cfg)?;
|
||||
}
|
||||
|
||||
let rpc_portal = if let Some(r) = &self.rpc_portal {
|
||||
Cli::parse_rpc_portal(r.clone())
|
||||
.with_context(|| format!("failed to parse rpc portal: {}", r))?
|
||||
} else if let Some(r) = cfg.get_rpc_portal() {
|
||||
r
|
||||
} else {
|
||||
Cli::parse_rpc_portal("0".into())?
|
||||
};
|
||||
cfg.set_rpc_portal(rpc_portal);
|
||||
|
||||
if let Some(rpc_portal_whitelist) = &self.rpc_portal_whitelist {
|
||||
let mut whitelist = cfg.get_rpc_portal_whitelist().unwrap_or_default();
|
||||
for cidr in rpc_portal_whitelist {
|
||||
whitelist.push(*cidr);
|
||||
}
|
||||
cfg.set_rpc_portal_whitelist(Some(whitelist));
|
||||
}
|
||||
|
||||
if let Some(external_nodes) = self.external_node.as_ref() {
|
||||
let mut old_peers = cfg.get_peers();
|
||||
old_peers.push(PeerConfig {
|
||||
@@ -1127,6 +1108,16 @@ fn win_service_main(arg: Vec<std::ffi::OsString>) {
|
||||
async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
||||
init_logger(&cli.logging_options, true)?;
|
||||
|
||||
let manager = Arc::new(NetworkInstanceManager::new());
|
||||
|
||||
let _rpc_server = ApiRpcServer::new(
|
||||
cli.rpc_portal_options.rpc_portal,
|
||||
cli.rpc_portal_options.rpc_portal_whitelist,
|
||||
manager.clone(),
|
||||
)?
|
||||
.serve()
|
||||
.await?;
|
||||
|
||||
if cli.config_server.is_some() {
|
||||
set_default_machine_id(cli.machine_id);
|
||||
let config_server_url_s = cli.config_server.clone().unwrap();
|
||||
@@ -1175,11 +1166,11 @@ async fn run_main(cli: Cli) -> anyhow::Result<()> {
|
||||
create_connector_by_url(c_url.as_str(), &global_ctx, IpVersion::Both).await?,
|
||||
token.to_string(),
|
||||
hostname,
|
||||
manager,
|
||||
);
|
||||
tokio::signal::ctrl_c().await.unwrap();
|
||||
return Ok(());
|
||||
}
|
||||
let manager = NetworkInstanceManager::new();
|
||||
let mut crate_cli_network =
|
||||
cli.config_file.is_none() || cli.network_options.network_name.is_some();
|
||||
if let Some(config_files) = cli.config_file {
|
||||
|
||||
@@ -40,7 +40,7 @@ use crate::{
|
||||
peers::{acl_filter::AclFilter, peer_manager::PeerManager, NicPacketFilter, PeerPacketFilter},
|
||||
proto::{
|
||||
acl::{Action, ChainType, Protocol},
|
||||
cli::{
|
||||
api::instance::{
|
||||
ListTcpProxyEntryRequest, ListTcpProxyEntryResponse, TcpProxyEntry, TcpProxyEntryState,
|
||||
TcpProxyEntryTransportType, TcpProxyRpc,
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@ use crate::gateway::tcp_proxy::{NatDstConnector, NatDstTcpConnector, TcpProxy};
|
||||
use crate::gateway::CidrSet;
|
||||
use crate::peers::peer_manager::PeerManager;
|
||||
use crate::proto::acl::{ChainType, Protocol};
|
||||
use crate::proto::cli::{
|
||||
use crate::proto::api::instance::{
|
||||
ListTcpProxyEntryRequest, ListTcpProxyEntryResponse, TcpProxyEntry, TcpProxyEntryState,
|
||||
TcpProxyEntryTransportType, TcpProxyRpc,
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ use crate::common::join_joinset_background;
|
||||
use crate::common::stats_manager::{LabelSet, LabelType, MetricName};
|
||||
use crate::peers::peer_manager::PeerManager;
|
||||
use crate::peers::{NicPacketFilter, PeerPacketFilter};
|
||||
use crate::proto::cli::{
|
||||
use crate::proto::api::instance::{
|
||||
ListTcpProxyEntryRequest, ListTcpProxyEntryResponse, TcpProxyEntry, TcpProxyEntryState,
|
||||
TcpProxyEntryTransportType, TcpProxyRpc,
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ use tokio::task::JoinSet;
|
||||
use crate::{
|
||||
peers::peer_manager::PeerManager,
|
||||
proto::{
|
||||
cli::Route,
|
||||
api::instance::Route,
|
||||
common::Void,
|
||||
magic_dns::{
|
||||
HandshakeRequest, MagicDnsServerRpc, MagicDnsServerRpcClientFactory,
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::{
|
||||
},
|
||||
peers::{peer_manager::PeerManager, NicPacketFilter},
|
||||
proto::{
|
||||
cli::Route,
|
||||
api::instance::Route,
|
||||
common::{TunnelInfo, Void},
|
||||
magic_dns::{
|
||||
dns_record::{self},
|
||||
|
||||
@@ -21,7 +21,7 @@ use crate::instance::virtual_nic::NicCtx;
|
||||
use crate::peers::peer_manager::{PeerManager, RouteAlgoType};
|
||||
|
||||
use crate::peers::create_packet_recv_chan;
|
||||
use crate::proto::cli::Route;
|
||||
use crate::proto::api::instance::Route;
|
||||
use crate::proto::common::NatType;
|
||||
|
||||
pub async fn prepare_env(dns_name: &str, tun_ip: Ipv4Inet) -> (Arc<PeerManager>, NicCtx) {
|
||||
|
||||
@@ -32,23 +32,22 @@ use crate::peers::peer_conn::PeerConnId;
|
||||
use crate::peers::peer_manager::{PeerManager, RouteAlgoType};
|
||||
use crate::peers::rpc_service::PeerManagerRpcService;
|
||||
use crate::peers::{create_packet_recv_chan, recv_packet_from_chan, PacketRecvChanReceiver};
|
||||
use crate::proto::cli::VpnPortalRpc;
|
||||
use crate::proto::cli::{
|
||||
use crate::proto::api::config::{
|
||||
ConfigPatchAction, ConfigRpc, PatchConfigRequest, PatchConfigResponse, PortForwardPatch,
|
||||
};
|
||||
use crate::proto::api::instance::{
|
||||
GetPrometheusStatsRequest, GetPrometheusStatsResponse, GetStatsRequest, GetStatsResponse,
|
||||
ListMappedListenerRequest, ListMappedListenerResponse, ListPortForwardRequest,
|
||||
ListPortForwardResponse, MappedListener, MappedListenerManageRpc, MetricSnapshot,
|
||||
PortForwardManageRpc, StatsRpc,
|
||||
GetVpnPortalInfoRequest, GetVpnPortalInfoResponse, ListMappedListenerRequest,
|
||||
ListMappedListenerResponse, ListPortForwardRequest, ListPortForwardResponse, MappedListener,
|
||||
MappedListenerManageRpc, MetricSnapshot, PortForwardManageRpc, StatsRpc, VpnPortalInfo,
|
||||
VpnPortalRpc,
|
||||
};
|
||||
use crate::proto::cli::{GetVpnPortalInfoRequest, GetVpnPortalInfoResponse, VpnPortalInfo};
|
||||
use crate::proto::common::{PortForwardConfigPb, TunnelInfo, Void};
|
||||
use crate::proto::config::{
|
||||
ConfigPatchAction, ConfigRpc, ConfigRpcServer, PatchConfigRequest, PortForwardPatch,
|
||||
};
|
||||
use crate::proto::peer_rpc::PeerCenterRpcServer;
|
||||
use crate::proto::rpc_impl::standalone::{RpcServerHook, StandAloneServer};
|
||||
use crate::proto::common::{PortForwardConfigPb, TunnelInfo};
|
||||
use crate::proto::rpc_impl::standalone::RpcServerHook;
|
||||
use crate::proto::rpc_types;
|
||||
use crate::proto::rpc_types::controller::BaseController;
|
||||
use crate::tunnel::tcp::TcpTunnelListener;
|
||||
use crate::rpc_service::InstanceRpcService;
|
||||
use crate::utils::weak_upgrade;
|
||||
use crate::vpn_portal::{self, VpnPortal};
|
||||
|
||||
use super::dns_server::runner::DnsRunner;
|
||||
@@ -229,15 +228,16 @@ impl RpcServerHook for InstanceRpcServerHook {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct InstanceConfigPatcher {
|
||||
global_ctx: ArcGlobalCtx,
|
||||
global_ctx: Weak<GlobalCtx>,
|
||||
socks5_server: Weak<Socks5Server>,
|
||||
peer_manager: Arc<PeerManager>,
|
||||
peer_manager: Weak<PeerManager>,
|
||||
conn_manager: Weak<ManualConnectorManager>,
|
||||
}
|
||||
|
||||
impl InstanceConfigPatcher {
|
||||
pub async fn apply_patch(
|
||||
&self,
|
||||
patch: crate::proto::config::InstanceConfigPatch,
|
||||
patch: crate::proto::api::config::InstanceConfigPatch,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let patch_for_event = patch.clone();
|
||||
|
||||
@@ -247,27 +247,32 @@ impl InstanceConfigPatcher {
|
||||
self.patch_routes(patch.routes).await?;
|
||||
self.patch_exit_nodes(patch.exit_nodes).await?;
|
||||
self.patch_mapped_listeners(patch.mapped_listeners).await?;
|
||||
self.patch_connector(patch.connectors).await?;
|
||||
|
||||
let global_ctx = weak_upgrade(&self.global_ctx)?;
|
||||
if let Some(hostname) = patch.hostname {
|
||||
self.global_ctx.set_hostname(hostname.clone());
|
||||
self.global_ctx.config.set_hostname(Some(hostname));
|
||||
global_ctx.set_hostname(hostname.clone());
|
||||
global_ctx.config.set_hostname(Some(hostname));
|
||||
}
|
||||
if let Some(ipv4) = patch.ipv4 {
|
||||
if !self.global_ctx.config.get_dhcp() {
|
||||
self.global_ctx.set_ipv4(Some(ipv4.into()));
|
||||
self.global_ctx.config.set_ipv4(Some(ipv4.into()));
|
||||
if !global_ctx.config.get_dhcp() {
|
||||
global_ctx.set_ipv4(Some(ipv4.into()));
|
||||
global_ctx.config.set_ipv4(Some(ipv4.into()));
|
||||
}
|
||||
}
|
||||
if let Some(ipv6) = patch.ipv6 {
|
||||
self.global_ctx.set_ipv6(Some(ipv6.into()));
|
||||
self.global_ctx.config.set_ipv6(Some(ipv6.into()));
|
||||
global_ctx.set_ipv6(Some(ipv6.into()));
|
||||
global_ctx.config.set_ipv6(Some(ipv6.into()));
|
||||
}
|
||||
self.global_ctx
|
||||
.issue_event(GlobalCtxEvent::ConfigPatched(patch_for_event));
|
||||
|
||||
global_ctx.issue_event(GlobalCtxEvent::ConfigPatched(patch_for_event));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn trace_patchables<T: std::fmt::Debug>(patches: &Vec<crate::proto::config::Patchable<T>>) {
|
||||
fn trace_patchables<T: std::fmt::Debug>(
|
||||
patches: &Vec<crate::proto::api::config::Patchable<T>>,
|
||||
) {
|
||||
for patch in patches {
|
||||
match patch.action {
|
||||
Some(ConfigPatchAction::Add) | Some(ConfigPatchAction::Remove) => {
|
||||
@@ -304,13 +309,14 @@ impl InstanceConfigPatcher {
|
||||
let Some(socks5_server) = self.socks5_server.upgrade() else {
|
||||
return Err(anyhow::anyhow!("socks5 server not available"));
|
||||
};
|
||||
let global_ctx = weak_upgrade(&self.global_ctx)?;
|
||||
|
||||
let mut current_forwards = self.global_ctx.config.get_port_forwards();
|
||||
let mut current_forwards = global_ctx.config.get_port_forwards();
|
||||
let patches = port_forwards.into_iter().map(Into::into).collect();
|
||||
InstanceConfigPatcher::trace_patchables(&patches);
|
||||
crate::proto::config::patch_vec(&mut current_forwards, patches);
|
||||
crate::proto::api::config::patch_vec(&mut current_forwards, patches);
|
||||
|
||||
self.global_ctx
|
||||
global_ctx
|
||||
.config
|
||||
.set_port_forwards(current_forwards.clone());
|
||||
socks5_server
|
||||
@@ -323,49 +329,51 @@ impl InstanceConfigPatcher {
|
||||
|
||||
async fn patch_acl(
|
||||
&self,
|
||||
acl_patch: Option<crate::proto::config::AclPatch>,
|
||||
acl_patch: Option<crate::proto::api::config::AclPatch>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let Some(acl_patch) = acl_patch else {
|
||||
return Ok(());
|
||||
};
|
||||
let global_ctx = weak_upgrade(&self.global_ctx)?;
|
||||
if let Some(acl) = acl_patch.acl {
|
||||
self.global_ctx.config.set_acl(Some(acl));
|
||||
global_ctx.config.set_acl(Some(acl));
|
||||
}
|
||||
if !acl_patch.tcp_whitelist.is_empty() {
|
||||
let mut current_whitelist = self.global_ctx.config.get_tcp_whitelist();
|
||||
let mut current_whitelist = global_ctx.config.get_tcp_whitelist();
|
||||
let patches = acl_patch
|
||||
.tcp_whitelist
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect();
|
||||
InstanceConfigPatcher::trace_patchables(&patches);
|
||||
crate::proto::config::patch_vec(&mut current_whitelist, patches);
|
||||
self.global_ctx.config.set_tcp_whitelist(current_whitelist);
|
||||
crate::proto::api::config::patch_vec(&mut current_whitelist, patches);
|
||||
global_ctx.config.set_tcp_whitelist(current_whitelist);
|
||||
}
|
||||
if !acl_patch.udp_whitelist.is_empty() {
|
||||
let mut current_whitelist = self.global_ctx.config.get_udp_whitelist();
|
||||
let mut current_whitelist = global_ctx.config.get_udp_whitelist();
|
||||
let patches = acl_patch
|
||||
.udp_whitelist
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect();
|
||||
InstanceConfigPatcher::trace_patchables(&patches);
|
||||
crate::proto::config::patch_vec(&mut current_whitelist, patches);
|
||||
self.global_ctx.config.set_udp_whitelist(current_whitelist);
|
||||
crate::proto::api::config::patch_vec(&mut current_whitelist, patches);
|
||||
global_ctx.config.set_udp_whitelist(current_whitelist);
|
||||
}
|
||||
self.global_ctx
|
||||
global_ctx
|
||||
.get_acl_filter()
|
||||
.reload_rules(AclRuleBuilder::build(&self.global_ctx)?.as_ref());
|
||||
.reload_rules(AclRuleBuilder::build(&global_ctx)?.as_ref());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn patch_proxy_networks(
|
||||
&self,
|
||||
proxy_networks: Vec<crate::proto::config::ProxyNetworkPatch>,
|
||||
proxy_networks: Vec<crate::proto::api::config::ProxyNetworkPatch>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if proxy_networks.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let global_ctx = weak_upgrade(&self.global_ctx)?;
|
||||
for proxy_network_patch in proxy_networks {
|
||||
let Some(cidr) = proxy_network_patch.cidr.map(|c| c.into()) else {
|
||||
tracing::warn!("Proxy network cidr is None, skipping.");
|
||||
@@ -376,15 +384,15 @@ impl InstanceConfigPatcher {
|
||||
match ConfigPatchAction::try_from(proxy_network_patch.action) {
|
||||
Ok(ConfigPatchAction::Add) => {
|
||||
tracing::info!("Proxy network added: {}", cidr);
|
||||
self.global_ctx.config.add_proxy_cidr(cidr, mapped_cidr)?;
|
||||
global_ctx.config.add_proxy_cidr(cidr, mapped_cidr)?;
|
||||
}
|
||||
Ok(ConfigPatchAction::Remove) => {
|
||||
tracing::info!("Proxy network removed: {}", cidr);
|
||||
self.global_ctx.config.remove_proxy_cidr(cidr);
|
||||
global_ctx.config.remove_proxy_cidr(cidr);
|
||||
}
|
||||
Ok(ConfigPatchAction::Clear) => {
|
||||
tracing::info!("Proxy networks cleared.");
|
||||
self.global_ctx.config.clear_proxy_cidrs();
|
||||
global_ctx.config.clear_proxy_cidrs();
|
||||
}
|
||||
Err(_) => {
|
||||
tracing::warn!(
|
||||
@@ -399,60 +407,98 @@ impl InstanceConfigPatcher {
|
||||
|
||||
async fn patch_routes(
|
||||
&self,
|
||||
routes: Vec<crate::proto::config::RoutePatch>,
|
||||
routes: Vec<crate::proto::api::config::RoutePatch>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if routes.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut current_routes = self.global_ctx.config.get_routes().unwrap_or_default();
|
||||
let global_ctx = weak_upgrade(&self.global_ctx)?;
|
||||
let mut current_routes = global_ctx.config.get_routes().unwrap_or_default();
|
||||
let patches = routes.into_iter().map(Into::into).collect();
|
||||
InstanceConfigPatcher::trace_patchables(&patches);
|
||||
crate::proto::config::patch_vec(&mut current_routes, patches);
|
||||
crate::proto::api::config::patch_vec(&mut current_routes, patches);
|
||||
if current_routes.is_empty() {
|
||||
self.global_ctx.config.set_routes(None);
|
||||
global_ctx.config.set_routes(None);
|
||||
} else {
|
||||
self.global_ctx.config.set_routes(Some(current_routes));
|
||||
global_ctx.config.set_routes(Some(current_routes));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn patch_exit_nodes(
|
||||
&self,
|
||||
exit_nodes: Vec<crate::proto::config::ExitNodePatch>,
|
||||
exit_nodes: Vec<crate::proto::api::config::ExitNodePatch>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if exit_nodes.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut current_exit_nodes = self.global_ctx.config.get_exit_nodes();
|
||||
let global_ctx = weak_upgrade(&self.global_ctx)?;
|
||||
let peer_manager = weak_upgrade(&self.peer_manager)?;
|
||||
let mut current_exit_nodes = global_ctx.config.get_exit_nodes();
|
||||
let patches = exit_nodes.into_iter().map(Into::into).collect();
|
||||
InstanceConfigPatcher::trace_patchables(&patches);
|
||||
crate::proto::config::patch_vec(&mut current_exit_nodes, patches);
|
||||
self.global_ctx.config.set_exit_nodes(current_exit_nodes);
|
||||
self.peer_manager.update_exit_nodes().await;
|
||||
crate::proto::api::config::patch_vec(&mut current_exit_nodes, patches);
|
||||
global_ctx.config.set_exit_nodes(current_exit_nodes);
|
||||
peer_manager.update_exit_nodes().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn patch_mapped_listeners(
|
||||
&self,
|
||||
mapped_listeners: Vec<crate::proto::config::UrlPatch>,
|
||||
mapped_listeners: Vec<crate::proto::api::config::UrlPatch>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if mapped_listeners.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let mut current_mapped_listeners = self.global_ctx.config.get_mapped_listeners();
|
||||
let global_ctx = weak_upgrade(&self.global_ctx)?;
|
||||
let mut current_mapped_listeners = global_ctx.config.get_mapped_listeners();
|
||||
let patches = mapped_listeners.into_iter().map(Into::into).collect();
|
||||
InstanceConfigPatcher::trace_patchables(&patches);
|
||||
crate::proto::config::patch_vec(&mut current_mapped_listeners, patches);
|
||||
crate::proto::api::config::patch_vec(&mut current_mapped_listeners, patches);
|
||||
if current_mapped_listeners.is_empty() {
|
||||
self.global_ctx.config.set_mapped_listeners(None);
|
||||
global_ctx.config.set_mapped_listeners(None);
|
||||
} else {
|
||||
self.global_ctx
|
||||
global_ctx
|
||||
.config
|
||||
.set_mapped_listeners(Some(current_mapped_listeners));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn patch_connector(
|
||||
&self,
|
||||
connectors: Vec<crate::proto::api::config::UrlPatch>,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
if connectors.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let conn_manager = weak_upgrade(&self.conn_manager)?;
|
||||
for connector in connectors {
|
||||
let Some(url) = connector.url.map(Into::<url::Url>::into) else {
|
||||
tracing::warn!("Connector url is None, skipping.");
|
||||
return Ok(());
|
||||
};
|
||||
match ConfigPatchAction::try_from(connector.action) {
|
||||
Ok(ConfigPatchAction::Add) => {
|
||||
tracing::info!("Connector added: {}", url);
|
||||
conn_manager.add_connector_by_url(url.as_str()).await?;
|
||||
}
|
||||
Ok(ConfigPatchAction::Remove) => {
|
||||
tracing::info!("Connector removed: {}", url);
|
||||
conn_manager.remove_connector(url).await?;
|
||||
}
|
||||
Ok(ConfigPatchAction::Clear) => {
|
||||
tracing::info!("Connectors cleared.");
|
||||
conn_manager.clear_connectors().await;
|
||||
}
|
||||
Err(_) => {
|
||||
tracing::warn!("Invalid connector action: {}", connector.action);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Instance {
|
||||
@@ -484,8 +530,6 @@ pub struct Instance {
|
||||
#[cfg(feature = "socks5")]
|
||||
socks5_server: Arc<Socks5Server>,
|
||||
|
||||
rpc_server: Option<StandAloneServer<TcpTunnelListener>>,
|
||||
|
||||
global_ctx: ArcGlobalCtx,
|
||||
}
|
||||
|
||||
@@ -536,12 +580,6 @@ impl Instance {
|
||||
#[cfg(feature = "socks5")]
|
||||
let socks5_server = Socks5Server::new(global_ctx.clone(), peer_manager.clone(), None);
|
||||
|
||||
let rpc_server = global_ctx.config.get_rpc_portal().map(|s| {
|
||||
StandAloneServer::new(TcpTunnelListener::new(
|
||||
format!("tcp://{}", s).parse().unwrap(),
|
||||
))
|
||||
});
|
||||
|
||||
Instance {
|
||||
inst_name: global_ctx.inst_name.clone(),
|
||||
id,
|
||||
@@ -569,8 +607,6 @@ impl Instance {
|
||||
#[cfg(feature = "socks5")]
|
||||
socks5_server,
|
||||
|
||||
rpc_server,
|
||||
|
||||
global_ctx,
|
||||
}
|
||||
}
|
||||
@@ -934,8 +970,6 @@ impl Instance {
|
||||
)
|
||||
.await?;
|
||||
|
||||
self.run_rpc_server().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1034,7 +1068,7 @@ impl Instance {
|
||||
&self,
|
||||
) -> impl MappedListenerManageRpc<Controller = BaseController> + Clone {
|
||||
#[derive(Clone)]
|
||||
pub struct MappedListenerManagerRpcService(Arc<GlobalCtx>);
|
||||
pub struct MappedListenerManagerRpcService(Weak<GlobalCtx>);
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl MappedListenerManageRpc for MappedListenerManagerRpcService {
|
||||
@@ -1046,7 +1080,7 @@ impl Instance {
|
||||
_request: ListMappedListenerRequest,
|
||||
) -> Result<ListMappedListenerResponse, rpc_types::error::Error> {
|
||||
let mut ret = ListMappedListenerResponse::default();
|
||||
let urls = self.0.config.get_mapped_listeners();
|
||||
let urls = weak_upgrade(&self.0)?.config.get_mapped_listeners();
|
||||
let mapped_listeners: Vec<MappedListener> = urls
|
||||
.into_iter()
|
||||
.map(|u| MappedListener {
|
||||
@@ -1058,7 +1092,7 @@ impl Instance {
|
||||
}
|
||||
}
|
||||
|
||||
MappedListenerManagerRpcService(self.global_ctx.clone())
|
||||
MappedListenerManagerRpcService(Arc::downgrade(&self.global_ctx))
|
||||
}
|
||||
|
||||
fn get_port_forward_manager_rpc_service(
|
||||
@@ -1066,7 +1100,7 @@ impl Instance {
|
||||
) -> impl PortForwardManageRpc<Controller = BaseController> + Clone {
|
||||
#[derive(Clone)]
|
||||
pub struct PortForwardManagerRpcService {
|
||||
global_ctx: ArcGlobalCtx,
|
||||
global_ctx: Weak<GlobalCtx>,
|
||||
socks5_server: Weak<Socks5Server>,
|
||||
}
|
||||
|
||||
@@ -1079,14 +1113,14 @@ impl Instance {
|
||||
_: BaseController,
|
||||
_request: ListPortForwardRequest,
|
||||
) -> Result<ListPortForwardResponse, rpc_types::error::Error> {
|
||||
let forwards = self.global_ctx.config.get_port_forwards();
|
||||
let forwards = weak_upgrade(&self.global_ctx)?.config.get_port_forwards();
|
||||
let cfgs: Vec<PortForwardConfigPb> = forwards.into_iter().map(Into::into).collect();
|
||||
Ok(ListPortForwardResponse { cfgs })
|
||||
}
|
||||
}
|
||||
|
||||
PortForwardManagerRpcService {
|
||||
global_ctx: self.global_ctx.clone(),
|
||||
global_ctx: Arc::downgrade(&self.global_ctx),
|
||||
socks5_server: Arc::downgrade(&self.socks5_server),
|
||||
}
|
||||
}
|
||||
@@ -1094,7 +1128,7 @@ impl Instance {
|
||||
fn get_stats_rpc_service(&self) -> impl StatsRpc<Controller = BaseController> + Clone {
|
||||
#[derive(Clone)]
|
||||
pub struct StatsRpcService {
|
||||
global_ctx: ArcGlobalCtx,
|
||||
global_ctx: Weak<GlobalCtx>,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -1106,8 +1140,9 @@ impl Instance {
|
||||
_: BaseController,
|
||||
_request: GetStatsRequest,
|
||||
) -> Result<GetStatsResponse, rpc_types::error::Error> {
|
||||
let stats_manager = self.global_ctx.stats_manager();
|
||||
let snapshots = stats_manager.get_all_metrics();
|
||||
let snapshots = weak_upgrade(&self.global_ctx)?
|
||||
.stats_manager()
|
||||
.get_all_metrics();
|
||||
|
||||
let metrics = snapshots
|
||||
.into_iter()
|
||||
@@ -1133,23 +1168,25 @@ impl Instance {
|
||||
_: BaseController,
|
||||
_request: GetPrometheusStatsRequest,
|
||||
) -> Result<GetPrometheusStatsResponse, rpc_types::error::Error> {
|
||||
let stats_manager = self.global_ctx.stats_manager();
|
||||
let prometheus_text = stats_manager.export_prometheus();
|
||||
let prometheus_text = weak_upgrade(&self.global_ctx)?
|
||||
.stats_manager()
|
||||
.export_prometheus();
|
||||
|
||||
Ok(GetPrometheusStatsResponse { prometheus_text })
|
||||
}
|
||||
}
|
||||
|
||||
StatsRpcService {
|
||||
global_ctx: self.global_ctx.clone(),
|
||||
global_ctx: Arc::downgrade(&self.global_ctx),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_config_patcher(&self) -> InstanceConfigPatcher {
|
||||
InstanceConfigPatcher {
|
||||
global_ctx: self.global_ctx.clone(),
|
||||
global_ctx: Arc::downgrade(&self.global_ctx),
|
||||
socks5_server: Arc::downgrade(&self.socks5_server),
|
||||
peer_manager: self.peer_manager.clone(),
|
||||
peer_manager: Arc::downgrade(&self.peer_manager),
|
||||
conn_manager: Arc::downgrade(&self.conn_manager),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,13 +1204,13 @@ impl Instance {
|
||||
&self,
|
||||
_: Self::Controller,
|
||||
request: PatchConfigRequest,
|
||||
) -> crate::proto::rpc_types::error::Result<Void> {
|
||||
) -> crate::proto::rpc_types::error::Result<PatchConfigResponse> {
|
||||
let Some(patch) = request.patch else {
|
||||
return Ok(Void::default());
|
||||
return Ok(PatchConfigResponse::default());
|
||||
};
|
||||
|
||||
self.patcher.apply_patch(patch).await?;
|
||||
Ok(Void::default())
|
||||
Ok(PatchConfigResponse::default())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1182,97 +1219,140 @@ impl Instance {
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_rpc_server(&mut self) -> Result<(), Error> {
|
||||
let Some(_) = self.global_ctx.config.get_rpc_portal() else {
|
||||
tracing::info!("rpc server not enabled, because rpc_portal is not set.");
|
||||
return Ok(());
|
||||
};
|
||||
pub fn get_api_rpc_service(&self) -> impl InstanceRpcService {
|
||||
use crate::proto::api::instance::*;
|
||||
|
||||
use crate::instance::logger_rpc_service::LoggerRpcService;
|
||||
use crate::proto::cli::*;
|
||||
|
||||
let peer_mgr = self.peer_manager.clone();
|
||||
let conn_manager = self.conn_manager.clone();
|
||||
let peer_center = self.peer_center.clone();
|
||||
let vpn_portal_rpc = self.get_vpn_portal_rpc_service();
|
||||
let mapped_listener_manager_rpc = self.get_mapped_listener_manager_rpc_service();
|
||||
let port_forward_manager_rpc = self.get_port_forward_manager_rpc_service();
|
||||
let stats_rpc_service = self.get_stats_rpc_service();
|
||||
let logger_rpc_service = LoggerRpcService::new();
|
||||
let config_rpc_service = self.get_config_service();
|
||||
|
||||
let s = self.rpc_server.as_mut().unwrap();
|
||||
let peer_mgr_rpc_service = PeerManagerRpcService::new(peer_mgr.clone());
|
||||
s.registry()
|
||||
.register(PeerManageRpcServer::new(peer_mgr_rpc_service.clone()), "");
|
||||
s.registry()
|
||||
.register(AclManageRpcServer::new(peer_mgr_rpc_service), "");
|
||||
s.registry().register(
|
||||
ConnectorManageRpcServer::new(ConnectorManagerRpcService(conn_manager)),
|
||||
"",
|
||||
);
|
||||
|
||||
s.registry()
|
||||
.register(PeerCenterRpcServer::new(peer_center.get_rpc_service()), "");
|
||||
s.registry()
|
||||
.register(VpnPortalRpcServer::new(vpn_portal_rpc), "");
|
||||
s.registry().register(
|
||||
MappedListenerManageRpcServer::new(mapped_listener_manager_rpc),
|
||||
"",
|
||||
);
|
||||
s.registry().register(
|
||||
PortForwardManageRpcServer::new(port_forward_manager_rpc),
|
||||
"",
|
||||
);
|
||||
s.registry().register(
|
||||
crate::proto::cli::StatsRpcServer::new(stats_rpc_service),
|
||||
"",
|
||||
);
|
||||
s.registry()
|
||||
.register(LoggerRpcServer::new(logger_rpc_service), "");
|
||||
s.registry()
|
||||
.register(ConfigRpcServer::new(config_rpc_service), "");
|
||||
|
||||
if let Some(ip_proxy) = self.ip_proxy.as_ref() {
|
||||
s.registry().register(
|
||||
TcpProxyRpcServer::new(TcpProxyRpcService::new(ip_proxy.tcp_proxy.clone())),
|
||||
"tcp",
|
||||
);
|
||||
}
|
||||
if let Some(kcp_proxy) = self.kcp_proxy_src.as_ref() {
|
||||
s.registry().register(
|
||||
TcpProxyRpcServer::new(TcpProxyRpcService::new(kcp_proxy.get_tcp_proxy())),
|
||||
"kcp_src",
|
||||
);
|
||||
#[derive(Clone)]
|
||||
struct ApiRpcServiceImpl<A, B, C, D, E, F, G, H> {
|
||||
peer_mgr_rpc_service: A,
|
||||
connector_mgr_rpc_service: B,
|
||||
mapped_listener_mgr_rpc_service: C,
|
||||
vpn_portal_rpc_service: D,
|
||||
tcp_proxy_rpc_services: dashmap::DashMap<
|
||||
String,
|
||||
Arc<dyn TcpProxyRpc<Controller = BaseController> + Send + Sync>,
|
||||
>,
|
||||
acl_manage_rpc_service: E,
|
||||
port_forward_manage_rpc_service: F,
|
||||
stats_rpc_service: G,
|
||||
config_rpc_service: H,
|
||||
}
|
||||
|
||||
if let Some(kcp_proxy) = self.kcp_proxy_dst.as_ref() {
|
||||
s.registry().register(
|
||||
TcpProxyRpcServer::new(KcpProxyDstRpcService::new(kcp_proxy)),
|
||||
"kcp_dst",
|
||||
);
|
||||
#[async_trait::async_trait]
|
||||
impl<
|
||||
A: PeerManageRpc<Controller = BaseController> + Send + Sync,
|
||||
B: ConnectorManageRpc<Controller = BaseController> + Send + Sync,
|
||||
C: MappedListenerManageRpc<Controller = BaseController> + Send + Sync,
|
||||
D: VpnPortalRpc<Controller = BaseController> + Send + Sync,
|
||||
E: AclManageRpc<Controller = BaseController> + Send + Sync,
|
||||
F: PortForwardManageRpc<Controller = BaseController> + Send + Sync,
|
||||
G: StatsRpc<Controller = BaseController> + Send + Sync,
|
||||
H: ConfigRpc<Controller = BaseController> + Send + Sync,
|
||||
> InstanceRpcService for ApiRpcServiceImpl<A, B, C, D, E, F, G, H>
|
||||
{
|
||||
fn get_peer_manage_service(&self) -> &dyn PeerManageRpc<Controller = BaseController> {
|
||||
&self.peer_mgr_rpc_service
|
||||
}
|
||||
|
||||
fn get_connector_manage_service(
|
||||
&self,
|
||||
) -> &dyn ConnectorManageRpc<Controller = BaseController> {
|
||||
&self.connector_mgr_rpc_service
|
||||
}
|
||||
|
||||
fn get_mapped_listener_manage_service(
|
||||
&self,
|
||||
) -> &dyn MappedListenerManageRpc<Controller = BaseController> {
|
||||
&self.mapped_listener_mgr_rpc_service
|
||||
}
|
||||
|
||||
fn get_vpn_portal_service(&self) -> &dyn VpnPortalRpc<Controller = BaseController> {
|
||||
&self.vpn_portal_rpc_service
|
||||
}
|
||||
|
||||
fn get_proxy_service(
|
||||
&self,
|
||||
client_type: &str,
|
||||
) -> Option<Arc<dyn TcpProxyRpc<Controller = BaseController> + Send + Sync>>
|
||||
{
|
||||
self.tcp_proxy_rpc_services
|
||||
.get(client_type)
|
||||
.map(|e| e.clone())
|
||||
}
|
||||
|
||||
fn get_acl_manage_service(&self) -> &dyn AclManageRpc<Controller = BaseController> {
|
||||
&self.acl_manage_rpc_service
|
||||
}
|
||||
|
||||
fn get_port_forward_manage_service(
|
||||
&self,
|
||||
) -> &dyn PortForwardManageRpc<Controller = BaseController> {
|
||||
&self.port_forward_manage_rpc_service
|
||||
}
|
||||
|
||||
fn get_stats_service(&self) -> &dyn StatsRpc<Controller = BaseController> {
|
||||
&self.stats_rpc_service
|
||||
}
|
||||
|
||||
fn get_config_service(&self) -> &dyn ConfigRpc<Controller = BaseController> {
|
||||
&self.config_rpc_service
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(quic_proxy) = self.quic_proxy_src.as_ref() {
|
||||
s.registry().register(
|
||||
TcpProxyRpcServer::new(TcpProxyRpcService::new(quic_proxy.get_tcp_proxy())),
|
||||
"quic_src",
|
||||
);
|
||||
ApiRpcServiceImpl {
|
||||
peer_mgr_rpc_service: PeerManagerRpcService::new(self.peer_manager.clone()),
|
||||
connector_mgr_rpc_service: ConnectorManagerRpcService(Arc::downgrade(
|
||||
&self.conn_manager,
|
||||
)),
|
||||
mapped_listener_mgr_rpc_service: self.get_mapped_listener_manager_rpc_service(),
|
||||
vpn_portal_rpc_service: self.get_vpn_portal_rpc_service(),
|
||||
tcp_proxy_rpc_services: {
|
||||
let tcp_proxy_rpc_services: dashmap::DashMap<
|
||||
String,
|
||||
Arc<dyn TcpProxyRpc<Controller = BaseController> + Send + Sync>,
|
||||
> = dashmap::DashMap::new();
|
||||
|
||||
if let Some(ip_proxy) = self.ip_proxy.as_ref() {
|
||||
tcp_proxy_rpc_services.insert(
|
||||
"tcp".to_string(),
|
||||
Arc::new(TcpProxyRpcService::new(ip_proxy.tcp_proxy.clone())),
|
||||
);
|
||||
}
|
||||
if let Some(kcp_proxy) = self.kcp_proxy_src.as_ref() {
|
||||
tcp_proxy_rpc_services.insert(
|
||||
"kcp_src".to_string(),
|
||||
Arc::new(TcpProxyRpcService::new(kcp_proxy.get_tcp_proxy())),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(kcp_proxy) = self.kcp_proxy_dst.as_ref() {
|
||||
tcp_proxy_rpc_services.insert(
|
||||
"kcp_dst".to_string(),
|
||||
Arc::new(KcpProxyDstRpcService::new(kcp_proxy)),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(quic_proxy) = self.quic_proxy_src.as_ref() {
|
||||
tcp_proxy_rpc_services.insert(
|
||||
"quic_src".to_string(),
|
||||
Arc::new(TcpProxyRpcService::new(quic_proxy.get_tcp_proxy())),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(quic_proxy) = self.quic_proxy_dst.as_ref() {
|
||||
tcp_proxy_rpc_services.insert(
|
||||
"quic_dst".to_string(),
|
||||
Arc::new(QUICProxyDstRpcService::new(quic_proxy)),
|
||||
);
|
||||
}
|
||||
|
||||
tcp_proxy_rpc_services
|
||||
},
|
||||
acl_manage_rpc_service: PeerManagerRpcService::new(self.peer_manager.clone()),
|
||||
port_forward_manage_rpc_service: self.get_port_forward_manager_rpc_service(),
|
||||
stats_rpc_service: self.get_stats_rpc_service(),
|
||||
config_rpc_service: self.get_config_service(),
|
||||
}
|
||||
|
||||
if let Some(quic_proxy) = self.quic_proxy_dst.as_ref() {
|
||||
s.registry().register(
|
||||
TcpProxyRpcServer::new(QUICProxyDstRpcService::new(quic_proxy)),
|
||||
"quic_dst",
|
||||
);
|
||||
}
|
||||
|
||||
s.set_hook(Arc::new(InstanceRpcServerHook::new(
|
||||
self.global_ctx.config.get_rpc_portal_whitelist(),
|
||||
)));
|
||||
|
||||
let _g = self.global_ctx.net_ns.guard();
|
||||
Ok(s.serve().await.with_context(|| "rpc server start failed")?)
|
||||
}
|
||||
|
||||
pub fn get_global_ctx(&self) -> ArcGlobalCtx {
|
||||
@@ -1328,9 +1408,6 @@ impl Instance {
|
||||
pub async fn clear_resources(&mut self) {
|
||||
self.peer_manager.clear_resources().await;
|
||||
let _ = self.nic_ctx.lock().await.take();
|
||||
if let Some(rpc_server) = self.rpc_server.take() {
|
||||
rpc_server.registry().unregister_all();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1339,9 +1416,6 @@ impl Drop for Instance {
|
||||
let my_peer_id = self.peer_manager.my_peer_id();
|
||||
let pm = Arc::downgrade(&self.peer_manager);
|
||||
let nic_ctx = self.nic_ctx.clone();
|
||||
if let Some(rpc_server) = self.rpc_server.take() {
|
||||
rpc_server.registry().unregister_all();
|
||||
};
|
||||
tokio::spawn(async move {
|
||||
nic_ctx.lock().await.take();
|
||||
if let Some(pm) = pm.upgrade() {
|
||||
|
||||
@@ -6,5 +6,3 @@ pub mod listeners;
|
||||
|
||||
#[cfg(feature = "tun")]
|
||||
pub mod virtual_nic;
|
||||
|
||||
pub mod logger_rpc_service;
|
||||
|
||||
@@ -9,7 +9,8 @@ use crate::{
|
||||
scoped_task::ScopedTask,
|
||||
},
|
||||
launcher::{ConfigSource, NetworkInstance, NetworkInstanceRunningInfo},
|
||||
proto,
|
||||
proto::{self},
|
||||
rpc_service::InstanceRpcService,
|
||||
};
|
||||
|
||||
pub struct NetworkInstanceManager {
|
||||
@@ -150,6 +151,26 @@ impl NetworkInstanceManager {
|
||||
.map(|instance| instance.value().get_inst_name())
|
||||
}
|
||||
|
||||
pub fn filter_network_instance(
|
||||
&self,
|
||||
filter: impl Fn(&uuid::Uuid, &NetworkInstance) -> bool,
|
||||
) -> Vec<uuid::Uuid> {
|
||||
self.instance_map
|
||||
.iter()
|
||||
.filter(|item| filter(item.key(), item.value()))
|
||||
.map(|item| *item.key())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_instance_service(
|
||||
&self,
|
||||
instance_id: &uuid::Uuid,
|
||||
) -> Option<Arc<dyn InstanceRpcService>> {
|
||||
self.instance_map
|
||||
.get(instance_id)
|
||||
.and_then(|instance| instance.value().get_api_service())
|
||||
}
|
||||
|
||||
pub fn set_tun_fd(&self, instance_id: &uuid::Uuid, fd: i32) -> Result<(), anyhow::Error> {
|
||||
let mut instance = self
|
||||
.instance_map
|
||||
@@ -340,7 +361,7 @@ fn print_event(instance_id: uuid::Uuid, msg: String) {
|
||||
);
|
||||
}
|
||||
|
||||
fn peer_conn_info_to_string(p: proto::cli::PeerConnInfo) -> String {
|
||||
fn peer_conn_info_to_string(p: proto::api::instance::PeerConnInfo) -> String {
|
||||
format!(
|
||||
"my_peer_id: {}, dst_peer_id: {}, tunnel_info: {:?}",
|
||||
p.my_peer_id, p.peer_id, p.tunnel
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::common::config::PortForwardConfig;
|
||||
use crate::proto::api::manage;
|
||||
use crate::proto::peer_rpc::RouteForeignNetworkSummary;
|
||||
use crate::proto::web;
|
||||
use crate::rpc_service::InstanceRpcService;
|
||||
use crate::{
|
||||
common::{
|
||||
config::{
|
||||
@@ -13,7 +14,7 @@ use crate::{
|
||||
},
|
||||
instance::instance::Instance,
|
||||
peers::rpc_service::PeerManagerRpcService,
|
||||
proto::cli::{list_peer_route_pair, PeerInfo, Route},
|
||||
proto::api::instance::{list_peer_route_pair, PeerInfo, Route},
|
||||
};
|
||||
use anyhow::Context;
|
||||
use chrono::{DateTime, Local};
|
||||
@@ -24,7 +25,9 @@ use std::{
|
||||
};
|
||||
use tokio::{sync::broadcast, task::JoinSet};
|
||||
|
||||
pub type MyNodeInfo = crate::proto::web::MyNodeInfo;
|
||||
pub type MyNodeInfo = crate::proto::api::manage::MyNodeInfo;
|
||||
|
||||
type ArcMutApiService = Arc<RwLock<Option<Arc<dyn InstanceRpcService>>>>;
|
||||
|
||||
#[derive(serde::Serialize, Clone)]
|
||||
pub struct Event {
|
||||
@@ -65,6 +68,7 @@ pub struct EasyTierLauncher {
|
||||
instance_alive: Arc<AtomicBool>,
|
||||
stop_flag: Arc<AtomicBool>,
|
||||
thread_handle: Option<std::thread::JoinHandle<()>>,
|
||||
api_service: ArcMutApiService,
|
||||
running_cfg: String,
|
||||
fetch_node_info: bool,
|
||||
|
||||
@@ -78,6 +82,7 @@ impl EasyTierLauncher {
|
||||
Self {
|
||||
instance_alive,
|
||||
thread_handle: None,
|
||||
api_service: Arc::new(RwLock::new(None)),
|
||||
error_msg: Arc::new(RwLock::new(None)),
|
||||
running_cfg: String::new(),
|
||||
fetch_node_info,
|
||||
@@ -136,12 +141,19 @@ impl EasyTierLauncher {
|
||||
async fn easytier_routine(
|
||||
cfg: TomlConfigLoader,
|
||||
stop_signal: Arc<tokio::sync::Notify>,
|
||||
api_service: ArcMutApiService,
|
||||
data: Arc<EasyTierData>,
|
||||
fetch_node_info: bool,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let mut instance = Instance::new(cfg);
|
||||
let mut tasks = JoinSet::new();
|
||||
|
||||
api_service
|
||||
.write()
|
||||
.unwrap()
|
||||
.replace(Arc::new(instance.get_api_rpc_service()));
|
||||
drop(api_service);
|
||||
|
||||
// Subscribe to global context events
|
||||
let global_ctx = instance.get_global_ctx();
|
||||
let data_c = data.clone();
|
||||
@@ -220,21 +232,6 @@ impl EasyTierLauncher {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn select_proper_rpc_port(cfg: &TomlConfigLoader) {
|
||||
let Some(mut f) = cfg.get_rpc_portal() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if f.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;
|
||||
};
|
||||
f.set_port(port);
|
||||
cfg.set_rpc_portal(f);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start<F>(&mut self, cfg_generator: F)
|
||||
where
|
||||
F: FnOnce() -> Result<TomlConfigLoader, anyhow::Error> + Send + Sync,
|
||||
@@ -250,8 +247,6 @@ impl EasyTierLauncher {
|
||||
|
||||
self.running_cfg = cfg.dump();
|
||||
|
||||
Self::select_proper_rpc_port(&cfg);
|
||||
|
||||
let stop_flag = self.stop_flag.clone();
|
||||
|
||||
let instance_alive = self.instance_alive.clone();
|
||||
@@ -259,6 +254,7 @@ impl EasyTierLauncher {
|
||||
|
||||
let data = self.data.clone();
|
||||
let fetch_node_info = self.fetch_node_info;
|
||||
let api_service = self.api_service.clone();
|
||||
|
||||
self.thread_handle = Some(std::thread::spawn(move || {
|
||||
let rt = if cfg.get_flags().multi_thread {
|
||||
@@ -288,6 +284,7 @@ impl EasyTierLauncher {
|
||||
let ret = rt.block_on(Self::easytier_routine(
|
||||
cfg,
|
||||
stop_notifier.clone(),
|
||||
api_service,
|
||||
data,
|
||||
fetch_node_info,
|
||||
));
|
||||
@@ -332,6 +329,16 @@ impl EasyTierLauncher {
|
||||
pub fn get_foreign_network_summary(&self) -> RouteForeignNetworkSummary {
|
||||
self.data.foreign_network_summary.read().unwrap().clone()
|
||||
}
|
||||
|
||||
pub fn get_api_service(&self) -> Option<Arc<dyn InstanceRpcService>> {
|
||||
match self.api_service.read() {
|
||||
Ok(guard) => guard.clone(),
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to acquire read lock for api_service: {:?}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EasyTierLauncher {
|
||||
@@ -346,7 +353,7 @@ impl Drop for EasyTierLauncher {
|
||||
}
|
||||
}
|
||||
|
||||
pub type NetworkInstanceRunningInfo = crate::proto::web::NetworkInstanceRunningInfo;
|
||||
pub type NetworkInstanceRunningInfo = crate::proto::api::manage::NetworkInstanceRunningInfo;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ConfigSource {
|
||||
@@ -460,6 +467,12 @@ impl NetworkInstance {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_api_service(&self) -> Option<Arc<dyn InstanceRpcService>> {
|
||||
self.launcher
|
||||
.as_ref()
|
||||
.and_then(|launcher| launcher.get_api_service())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_proxy_network_to_config(
|
||||
@@ -492,8 +505,8 @@ pub fn add_proxy_network_to_config(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub type NetworkingMethod = crate::proto::web::NetworkingMethod;
|
||||
pub type NetworkConfig = crate::proto::web::NetworkConfig;
|
||||
pub type NetworkingMethod = crate::proto::api::manage::NetworkingMethod;
|
||||
pub type NetworkConfig = crate::proto::api::manage::NetworkConfig;
|
||||
|
||||
impl NetworkConfig {
|
||||
pub fn gen_config(&self) -> Result<TomlConfigLoader, anyhow::Error> {
|
||||
@@ -574,26 +587,6 @@ impl NetworkConfig {
|
||||
add_proxy_network_to_config(n, &cfg)?;
|
||||
}
|
||||
|
||||
cfg.set_rpc_portal(
|
||||
format!("0.0.0.0:{}", self.rpc_port.unwrap_or_default())
|
||||
.parse()
|
||||
.with_context(|| format!("failed to parse rpc portal port: {:?}", self.rpc_port))?,
|
||||
);
|
||||
|
||||
if self.rpc_portal_whitelists.is_empty() {
|
||||
cfg.set_rpc_portal_whitelist(None);
|
||||
} else {
|
||||
cfg.set_rpc_portal_whitelist(Some(
|
||||
self.rpc_portal_whitelists
|
||||
.iter()
|
||||
.map(|s| {
|
||||
s.parse()
|
||||
.with_context(|| format!("failed to parse rpc portal whitelist: {}", s))
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
));
|
||||
}
|
||||
|
||||
if !self.port_forwards.is_empty() {
|
||||
cfg.set_port_forwards(
|
||||
self.port_forwards
|
||||
@@ -848,19 +841,11 @@ impl NetworkConfig {
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Some(rpc_portal) = config.get_rpc_portal() {
|
||||
result.rpc_port = Some(rpc_portal.port() as i32);
|
||||
}
|
||||
|
||||
if let Some(whitelist) = config.get_rpc_portal_whitelist() {
|
||||
result.rpc_portal_whitelists = whitelist.iter().map(|w| w.to_string()).collect();
|
||||
}
|
||||
|
||||
let port_forwards = config.get_port_forwards();
|
||||
if !port_forwards.is_empty() {
|
||||
result.port_forwards = port_forwards
|
||||
.iter()
|
||||
.map(|f| web::PortForwardConfig {
|
||||
.map(|f| manage::PortForwardConfig {
|
||||
proto: f.proto.clone(),
|
||||
bind_ip: f.bind_addr.ip().to_string(),
|
||||
bind_port: f.bind_addr.port() as u32,
|
||||
@@ -949,7 +934,6 @@ mod tests {
|
||||
config.set_dhcp(false);
|
||||
config.set_inst_name("default".to_string());
|
||||
config.set_listeners(vec![]);
|
||||
config.set_rpc_portal(std::net::SocketAddr::from(([0, 0, 0, 0], 0)));
|
||||
config
|
||||
}
|
||||
|
||||
@@ -1061,27 +1045,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
if rng.gen_bool(0.8) {
|
||||
let port = rng.gen_range(0..65535);
|
||||
config.set_rpc_portal(std::net::SocketAddr::from(([0, 0, 0, 0], port)));
|
||||
|
||||
if rng.gen_bool(0.6) {
|
||||
let whitelist_count = rng.gen_range(1..3);
|
||||
let mut whitelist = Vec::new();
|
||||
for _ in 0..whitelist_count {
|
||||
let ip = Ipv4Addr::new(
|
||||
rng.gen_range(1..254),
|
||||
rng.gen_range(0..255),
|
||||
rng.gen_range(0..255),
|
||||
rng.gen_range(0..255),
|
||||
);
|
||||
let cidr = format!("{}/32", ip);
|
||||
whitelist.push(cidr.parse().unwrap());
|
||||
}
|
||||
config.set_rpc_portal_whitelist(Some(whitelist));
|
||||
}
|
||||
}
|
||||
|
||||
if rng.gen_bool(0.5) {
|
||||
let vpn_network = format!(
|
||||
"{}.{}.{}.0/{}",
|
||||
|
||||
@@ -17,6 +17,7 @@ pub mod instance_manager;
|
||||
pub mod launcher;
|
||||
pub mod peers;
|
||||
pub mod proto;
|
||||
pub mod rpc_service;
|
||||
pub mod tunnel;
|
||||
pub mod utils;
|
||||
pub mod web_client;
|
||||
|
||||
@@ -39,7 +39,7 @@ pub trait PeerCenterPeerManagerTrait: Send + Sync + 'static {
|
||||
fn my_peer_id(&self) -> PeerId;
|
||||
fn get_global_ctx(&self) -> Arc<GlobalCtx>;
|
||||
fn get_rpc_mgr(&self) -> Weak<PeerRpcManager>;
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route>;
|
||||
async fn list_routes(&self) -> Vec<crate::proto::api::instance::Route>;
|
||||
}
|
||||
|
||||
struct PeerCenterBase {
|
||||
@@ -426,7 +426,7 @@ impl PeerCenterPeerManagerTrait for PeerManager {
|
||||
Arc::downgrade(&self.get_peer_rpc_mgr())
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route> {
|
||||
async fn list_routes(&self) -> Vec<crate::proto::api::instance::Route> {
|
||||
self.list_routes().await
|
||||
}
|
||||
}
|
||||
@@ -478,7 +478,7 @@ impl PeerCenterPeerManagerTrait for PeerMapWithPeerRpcManager {
|
||||
Arc::downgrade(&self.rpc_mgr)
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route> {
|
||||
async fn list_routes(&self) -> Vec<crate::proto::api::instance::Route> {
|
||||
self.peer_map.list_route_infos().await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::proto::cli::PeerInfo;
|
||||
use crate::proto::api::instance::PeerInfo;
|
||||
use crate::proto::peer_rpc::{DirectConnectedPeerInfo, PeerInfoForGlobalMap};
|
||||
|
||||
pub mod instance;
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::{
|
||||
peer_center::instance::{PeerCenterInstance, PeerMapWithPeerRpcManager},
|
||||
peers::route_trait::{Route, RouteInterface},
|
||||
proto::{
|
||||
cli::{ForeignNetworkEntryPb, ListForeignNetworkResponse, PeerInfo},
|
||||
api::instance::{ForeignNetworkEntryPb, ListForeignNetworkResponse, PeerInfo},
|
||||
common::LimiterConfig,
|
||||
peer_rpc::DirectConnectorRpcServer,
|
||||
},
|
||||
|
||||
@@ -11,7 +11,7 @@ use super::{
|
||||
peer_conn::{PeerConn, PeerConnId},
|
||||
PacketRecvChan,
|
||||
};
|
||||
use crate::{common::scoped_task::ScopedTask, proto::cli::PeerConnInfo};
|
||||
use crate::{common::scoped_task::ScopedTask, proto::api::instance::PeerConnInfo};
|
||||
use crate::{
|
||||
common::{
|
||||
error::Error,
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::{
|
||||
PeerId,
|
||||
},
|
||||
proto::{
|
||||
cli::{PeerConnInfo, PeerConnStats},
|
||||
api::instance::{PeerConnInfo, PeerConnStats},
|
||||
common::TunnelInfo,
|
||||
peer_rpc::HandshakeRequest,
|
||||
},
|
||||
|
||||
@@ -36,7 +36,7 @@ use crate::{
|
||||
PeerPacketFilter,
|
||||
},
|
||||
proto::{
|
||||
cli::{
|
||||
api::instance::{
|
||||
self, list_global_foreign_network_response::OneForeignNetwork,
|
||||
ListGlobalForeignNetworkResponse,
|
||||
},
|
||||
@@ -920,7 +920,7 @@ impl PeerManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_routes(&self) -> Vec<cli::Route> {
|
||||
pub async fn list_routes(&self) -> Vec<instance::Route> {
|
||||
self.get_route().list_routes().await
|
||||
}
|
||||
|
||||
@@ -1305,8 +1305,8 @@ impl PeerManager {
|
||||
self.foreign_network_client.clone()
|
||||
}
|
||||
|
||||
pub async fn get_my_info(&self) -> cli::NodeInfo {
|
||||
cli::NodeInfo {
|
||||
pub async fn get_my_info(&self) -> instance::NodeInfo {
|
||||
instance::NodeInfo {
|
||||
peer_id: self.my_peer_id,
|
||||
ipv4_addr: self
|
||||
.global_ctx
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::{
|
||||
PeerId,
|
||||
},
|
||||
proto::{
|
||||
cli::{self, PeerConnInfo},
|
||||
api::instance::{self, PeerConnInfo},
|
||||
peer_rpc::RoutePeerInfo,
|
||||
},
|
||||
tunnel::{packet_def::ZCPacket, TunnelError},
|
||||
@@ -336,7 +336,7 @@ impl PeerMap {
|
||||
route_map
|
||||
}
|
||||
|
||||
pub async fn list_route_infos(&self) -> Vec<cli::Route> {
|
||||
pub async fn list_route_infos(&self) -> Vec<instance::Route> {
|
||||
if let Some(route) = self.routes.read().await.iter().next() {
|
||||
return route.list_routes().await;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ impl RoutePeerInfo {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RoutePeerInfo> for crate::proto::cli::Route {
|
||||
impl From<RoutePeerInfo> for crate::proto::api::instance::Route {
|
||||
fn from(val: RoutePeerInfo) -> Self {
|
||||
let network_length = if val.network_length == 0 {
|
||||
24
|
||||
@@ -201,7 +201,7 @@ impl From<RoutePeerInfo> for crate::proto::cli::Route {
|
||||
val.network_length
|
||||
};
|
||||
|
||||
crate::proto::cli::Route {
|
||||
crate::proto::api::instance::Route {
|
||||
peer_id: val.peer_id,
|
||||
ipv4_addr: val.ipv4_addr.map(|ipv4_addr| Ipv4Inet {
|
||||
address: Some(ipv4_addr),
|
||||
@@ -2361,7 +2361,7 @@ impl Route for PeerRoute {
|
||||
.map(|x| x.next_hop_peer_id)
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route> {
|
||||
async fn list_routes(&self) -> Vec<crate::proto::api::instance::Route> {
|
||||
let route_table = &self.service_impl.route_table;
|
||||
let route_table_with_cost = &self.service_impl.route_table_with_cost;
|
||||
let mut routes = Vec::new();
|
||||
@@ -2373,7 +2373,7 @@ impl Route for PeerRoute {
|
||||
continue;
|
||||
};
|
||||
let next_hop_peer_latency_first = route_table_with_cost.get_next_hop(*item.key());
|
||||
let mut route: crate::proto::cli::Route = item.value().clone().into();
|
||||
let mut route: crate::proto::api::instance::Route = item.value().clone().into();
|
||||
route.next_hop_peer_id = next_hop_peer.next_hop_peer_id;
|
||||
route.cost = next_hop_peer.path_len as i32;
|
||||
route.path_latency = next_hop_peer.path_latency;
|
||||
|
||||
@@ -74,7 +74,7 @@ pub trait Route {
|
||||
self.get_next_hop(peer_id).await
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route>;
|
||||
async fn list_routes(&self) -> Vec<crate::proto::api::instance::Route>;
|
||||
|
||||
async fn get_peer_id_by_ipv4(&self, _ipv4: &Ipv4Addr) -> Option<PeerId> {
|
||||
None
|
||||
@@ -161,7 +161,7 @@ impl Route for MockRoute {
|
||||
panic!("mock route")
|
||||
}
|
||||
|
||||
async fn list_routes(&self) -> Vec<crate::proto::cli::Route> {
|
||||
async fn list_routes(&self) -> Vec<crate::proto::api::instance::Route> {
|
||||
panic!("mock route")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,34 @@
|
||||
use std::sync::Arc;
|
||||
use std::{
|
||||
ops::Deref,
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
use crate::proto::{
|
||||
cli::{
|
||||
AclManageRpc, DumpRouteRequest, DumpRouteResponse, GetAclStatsRequest, GetAclStatsResponse,
|
||||
GetWhitelistRequest, GetWhitelistResponse, ListForeignNetworkRequest,
|
||||
ListForeignNetworkResponse, ListGlobalForeignNetworkRequest,
|
||||
ListGlobalForeignNetworkResponse, ListPeerRequest, ListPeerResponse, ListRouteRequest,
|
||||
ListRouteResponse, PeerInfo, PeerManageRpc, ShowNodeInfoRequest, ShowNodeInfoResponse,
|
||||
use crate::{
|
||||
proto::{
|
||||
api::instance::{
|
||||
AclManageRpc, DumpRouteRequest, DumpRouteResponse, GetAclStatsRequest,
|
||||
GetAclStatsResponse, GetWhitelistRequest, GetWhitelistResponse,
|
||||
ListForeignNetworkRequest, ListForeignNetworkResponse, ListGlobalForeignNetworkRequest,
|
||||
ListGlobalForeignNetworkResponse, ListPeerRequest, ListPeerResponse, ListRouteRequest,
|
||||
ListRouteResponse, PeerInfo, PeerManageRpc, ShowNodeInfoRequest, ShowNodeInfoResponse,
|
||||
},
|
||||
rpc_types::{self, controller::BaseController},
|
||||
},
|
||||
rpc_types::{self, controller::BaseController},
|
||||
utils::weak_upgrade,
|
||||
};
|
||||
|
||||
use super::peer_manager::PeerManager;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PeerManagerRpcService {
|
||||
peer_manager: Arc<PeerManager>,
|
||||
peer_manager: Weak<PeerManager>,
|
||||
}
|
||||
|
||||
impl PeerManagerRpcService {
|
||||
pub fn new(peer_manager: Arc<PeerManager>) -> Self {
|
||||
PeerManagerRpcService { peer_manager }
|
||||
PeerManagerRpcService {
|
||||
peer_manager: Arc::downgrade(&peer_manager),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_peers(peer_manager: &PeerManager) -> Vec<PeerInfo> {
|
||||
@@ -78,7 +86,8 @@ impl PeerManageRpc for PeerManagerRpcService {
|
||||
) -> Result<ListPeerResponse, rpc_types::error::Error> {
|
||||
let mut reply = ListPeerResponse::default();
|
||||
|
||||
let peers = PeerManagerRpcService::list_peers(&self.peer_manager).await;
|
||||
let peers =
|
||||
PeerManagerRpcService::list_peers(weak_upgrade(&self.peer_manager)?.deref()).await;
|
||||
for peer in peers {
|
||||
reply.peer_infos.push(peer);
|
||||
}
|
||||
@@ -92,7 +101,7 @@ impl PeerManageRpc for PeerManagerRpcService {
|
||||
_request: ListRouteRequest, // Accept request of type HelloRequest
|
||||
) -> Result<ListRouteResponse, rpc_types::error::Error> {
|
||||
let reply = ListRouteResponse {
|
||||
routes: self.peer_manager.list_routes().await,
|
||||
routes: weak_upgrade(&self.peer_manager)?.list_routes().await,
|
||||
};
|
||||
Ok(reply)
|
||||
}
|
||||
@@ -103,7 +112,7 @@ impl PeerManageRpc for PeerManagerRpcService {
|
||||
_request: DumpRouteRequest, // Accept request of type HelloRequest
|
||||
) -> Result<DumpRouteResponse, rpc_types::error::Error> {
|
||||
let reply = DumpRouteResponse {
|
||||
result: self.peer_manager.dump_route().await,
|
||||
result: weak_upgrade(&self.peer_manager)?.dump_route().await,
|
||||
};
|
||||
Ok(reply)
|
||||
}
|
||||
@@ -113,8 +122,7 @@ impl PeerManageRpc for PeerManagerRpcService {
|
||||
_: BaseController,
|
||||
_request: ListForeignNetworkRequest, // Accept request of type HelloRequest
|
||||
) -> Result<ListForeignNetworkResponse, rpc_types::error::Error> {
|
||||
let reply = self
|
||||
.peer_manager
|
||||
let reply = weak_upgrade(&self.peer_manager)?
|
||||
.get_foreign_network_manager()
|
||||
.list_foreign_networks()
|
||||
.await;
|
||||
@@ -126,7 +134,9 @@ impl PeerManageRpc for PeerManagerRpcService {
|
||||
_: BaseController,
|
||||
_request: ListGlobalForeignNetworkRequest,
|
||||
) -> Result<ListGlobalForeignNetworkResponse, rpc_types::error::Error> {
|
||||
Ok(self.peer_manager.list_global_foreign_network().await)
|
||||
Ok(weak_upgrade(&self.peer_manager)?
|
||||
.list_global_foreign_network()
|
||||
.await)
|
||||
}
|
||||
|
||||
async fn show_node_info(
|
||||
@@ -135,7 +145,7 @@ impl PeerManageRpc for PeerManagerRpcService {
|
||||
_request: ShowNodeInfoRequest, // Accept request of type HelloRequest
|
||||
) -> Result<ShowNodeInfoResponse, rpc_types::error::Error> {
|
||||
Ok(ShowNodeInfoResponse {
|
||||
node_info: Some(self.peer_manager.get_my_info().await),
|
||||
node_info: Some(weak_upgrade(&self.peer_manager)?.get_my_info().await),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -149,8 +159,7 @@ impl AclManageRpc for PeerManagerRpcService {
|
||||
_: BaseController,
|
||||
_request: GetAclStatsRequest,
|
||||
) -> Result<GetAclStatsResponse, rpc_types::error::Error> {
|
||||
let acl_stats = self
|
||||
.peer_manager
|
||||
let acl_stats = weak_upgrade(&self.peer_manager)?
|
||||
.get_global_ctx()
|
||||
.get_acl_filter()
|
||||
.get_stats();
|
||||
@@ -164,7 +173,7 @@ impl AclManageRpc for PeerManagerRpcService {
|
||||
_: BaseController,
|
||||
_request: GetWhitelistRequest,
|
||||
) -> Result<GetWhitelistResponse, rpc_types::error::Error> {
|
||||
let global_ctx = self.peer_manager.get_global_ctx();
|
||||
let global_ctx = weak_upgrade(&self.peer_manager)?.get_global_ctx();
|
||||
let tcp_ports = global_ctx.config.get_tcp_whitelist();
|
||||
let udp_ports = global_ctx.config.get_udp_whitelist();
|
||||
tracing::info!(
|
||||
|
||||
262
easytier/src/proto/api.rs
Normal file
262
easytier/src/proto/api.rs
Normal file
@@ -0,0 +1,262 @@
|
||||
pub mod config {
|
||||
include!(concat!(env!("OUT_DIR"), "/api.config.rs"));
|
||||
pub struct Patchable<T> {
|
||||
pub action: Option<ConfigPatchAction>,
|
||||
pub value: Option<T>,
|
||||
}
|
||||
|
||||
impl From<PortForwardPatch> for Patchable<crate::common::config::PortForwardConfig> {
|
||||
fn from(patch: PortForwardPatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(patch.action).ok(),
|
||||
value: patch.cfg.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RoutePatch> for Patchable<cidr::Ipv4Cidr> {
|
||||
fn from(value: RoutePatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: value.cidr.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ExitNodePatch> for Patchable<std::net::IpAddr> {
|
||||
fn from(value: ExitNodePatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: value.node.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StringPatch> for Patchable<String> {
|
||||
fn from(value: StringPatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: Some(value.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UrlPatch> for Patchable<url::Url> {
|
||||
fn from(value: UrlPatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: value.url.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn patch_vec<T>(v: &mut Vec<T>, patches: Vec<Patchable<T>>)
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
for patch in patches {
|
||||
match patch.action {
|
||||
Some(ConfigPatchAction::Add) => {
|
||||
if let Some(value) = patch.value {
|
||||
v.push(value);
|
||||
}
|
||||
}
|
||||
Some(ConfigPatchAction::Remove) => {
|
||||
if let Some(value) = patch.value {
|
||||
v.retain(|x| x != &value);
|
||||
}
|
||||
}
|
||||
Some(ConfigPatchAction::Clear) => {
|
||||
v.clear();
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod instance {
|
||||
include!(concat!(env!("OUT_DIR"), "/api.instance.rs"));
|
||||
|
||||
impl PeerRoutePair {
|
||||
pub fn get_latency_ms(&self) -> Option<f64> {
|
||||
let mut ret = u64::MAX;
|
||||
let p = self.peer.as_ref()?;
|
||||
let default_conn_id = p.default_conn_id.map(|id| id.to_string());
|
||||
for conn in p.conns.iter() {
|
||||
let Some(stats) = &conn.stats else {
|
||||
continue;
|
||||
};
|
||||
if default_conn_id == Some(conn.conn_id.to_string()) {
|
||||
return Some(f64::from(stats.latency_us as u32) / 1000.0);
|
||||
}
|
||||
ret = ret.min(stats.latency_us);
|
||||
}
|
||||
|
||||
if ret == u64::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(f64::from(ret as u32) / 1000.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_rx_bytes(&self) -> Option<u64> {
|
||||
let mut ret = 0;
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
let Some(stats) = &conn.stats else {
|
||||
continue;
|
||||
};
|
||||
ret += stats.rx_bytes;
|
||||
}
|
||||
|
||||
if ret == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_tx_bytes(&self) -> Option<u64> {
|
||||
let mut ret = 0;
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
let Some(stats) = &conn.stats else {
|
||||
continue;
|
||||
};
|
||||
ret += stats.tx_bytes;
|
||||
}
|
||||
|
||||
if ret == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_loss_rate(&self) -> Option<f64> {
|
||||
let mut ret = 0.0;
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
ret += conn.loss_rate;
|
||||
}
|
||||
|
||||
if ret == 0.0 {
|
||||
None
|
||||
} else {
|
||||
Some(ret as f64)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_tunnel_ipv6(tunnel_info: &super::super::common::TunnelInfo) -> bool {
|
||||
let Some(local_addr) = &tunnel_info.local_addr else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let u: url::Url = local_addr.clone().into();
|
||||
u.host()
|
||||
.map(|h| matches!(h, url::Host::Ipv6(_)))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn get_tunnel_proto_str(tunnel_info: &super::super::common::TunnelInfo) -> String {
|
||||
if Self::is_tunnel_ipv6(tunnel_info) {
|
||||
format!("{}6", tunnel_info.tunnel_type)
|
||||
} else {
|
||||
tunnel_info.tunnel_type.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_conn_protos(&self) -> Option<Vec<String>> {
|
||||
let mut ret = vec![];
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
let Some(tunnel_info) = &conn.tunnel else {
|
||||
continue;
|
||||
};
|
||||
// insert if not exists
|
||||
let tunnel_type = Self::get_tunnel_proto_str(tunnel_info);
|
||||
if !ret.contains(&tunnel_type) {
|
||||
ret.push(tunnel_type);
|
||||
}
|
||||
}
|
||||
|
||||
if ret.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_udp_nat_type(&self) -> String {
|
||||
use crate::proto::common::NatType;
|
||||
let mut ret = NatType::Unknown;
|
||||
if let Some(r) = &self.route.clone().unwrap_or_default().stun_info {
|
||||
ret = NatType::try_from(r.udp_nat_type).unwrap();
|
||||
}
|
||||
format!("{:?}", ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list_peer_route_pair(peers: Vec<PeerInfo>, routes: Vec<Route>) -> Vec<PeerRoutePair> {
|
||||
let mut pairs: Vec<PeerRoutePair> = vec![];
|
||||
|
||||
for route in routes.iter() {
|
||||
let peer = peers.iter().find(|peer| peer.peer_id == route.peer_id);
|
||||
let pair = PeerRoutePair {
|
||||
route: Some(route.clone()),
|
||||
peer: peer.cloned(),
|
||||
};
|
||||
|
||||
pairs.push(pair);
|
||||
}
|
||||
|
||||
pairs.sort_by(|a, b| {
|
||||
let a_is_public_server = a
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.feature_flag.as_ref())
|
||||
.is_some_and(|f| f.is_public_server);
|
||||
|
||||
let b_is_public_server = b
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.feature_flag.as_ref())
|
||||
.is_some_and(|f| f.is_public_server);
|
||||
|
||||
if a_is_public_server != b_is_public_server {
|
||||
return if a_is_public_server {
|
||||
std::cmp::Ordering::Less
|
||||
} else {
|
||||
std::cmp::Ordering::Greater
|
||||
};
|
||||
}
|
||||
|
||||
let a_ip = a
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.ipv4_addr.as_ref())
|
||||
.and_then(|ipv4| ipv4.address.as_ref())
|
||||
.map_or(0, |addr| addr.addr);
|
||||
|
||||
let b_ip = b
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.ipv4_addr.as_ref())
|
||||
.and_then(|ipv4| ipv4.address.as_ref())
|
||||
.map_or(0, |addr| addr.addr);
|
||||
|
||||
a_ip.cmp(&b_ip)
|
||||
});
|
||||
|
||||
pairs
|
||||
}
|
||||
}
|
||||
|
||||
pub mod logger {
|
||||
include!(concat!(env!("OUT_DIR"), "/api.logger.rs"));
|
||||
}
|
||||
|
||||
pub mod manage {
|
||||
include!(concat!(env!("OUT_DIR"), "/api.manage.rs"));
|
||||
}
|
||||
@@ -2,8 +2,9 @@ syntax = "proto3";
|
||||
|
||||
import "common.proto";
|
||||
import "acl.proto";
|
||||
import "api_instance.proto";
|
||||
|
||||
package config;
|
||||
package api.config;
|
||||
|
||||
enum ConfigPatchAction {
|
||||
ADD = 0;
|
||||
@@ -21,6 +22,7 @@ message InstanceConfigPatch {
|
||||
repeated RoutePatch routes = 7;
|
||||
repeated ExitNodePatch exit_nodes = 8;
|
||||
repeated UrlPatch mapped_listeners = 9;
|
||||
repeated UrlPatch connectors = 10;
|
||||
}
|
||||
|
||||
message PortForwardPatch {
|
||||
@@ -60,6 +62,13 @@ message ExitNodePatch {
|
||||
common.IpAddr node = 2;
|
||||
}
|
||||
|
||||
message PatchConfigRequest { InstanceConfigPatch patch = 1; }
|
||||
message PatchConfigRequest {
|
||||
InstanceConfigPatch patch = 1;
|
||||
api.instance.InstanceIdentifier instance = 2;
|
||||
}
|
||||
|
||||
service ConfigRpc { rpc PatchConfig(PatchConfigRequest) returns (common.Void); }
|
||||
message PatchConfigResponse {}
|
||||
|
||||
service ConfigRpc {
|
||||
rpc PatchConfig(PatchConfigRequest) returns (PatchConfigResponse);
|
||||
}
|
||||
@@ -4,7 +4,16 @@ import "common.proto";
|
||||
import "peer_rpc.proto";
|
||||
import "acl.proto";
|
||||
|
||||
package cli;
|
||||
package api.instance;
|
||||
|
||||
message InstanceIdentifier {
|
||||
message InstanceSelector { optional string name = 1; }
|
||||
|
||||
oneof selector {
|
||||
common.UUID id = 1;
|
||||
InstanceSelector instance_selector = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message Status {
|
||||
int32 code = 1;
|
||||
@@ -41,7 +50,7 @@ message PeerInfo {
|
||||
repeated common.UUID directly_connected_conns = 4;
|
||||
}
|
||||
|
||||
message ListPeerRequest {}
|
||||
message ListPeerRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ListPeerResponse {
|
||||
repeated PeerInfo peer_infos = 1;
|
||||
@@ -89,19 +98,19 @@ message NodeInfo {
|
||||
peer_rpc.GetIpListResponse ip_list = 11;
|
||||
}
|
||||
|
||||
message ShowNodeInfoRequest {}
|
||||
message ShowNodeInfoRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ShowNodeInfoResponse { NodeInfo node_info = 1; }
|
||||
|
||||
message ListRouteRequest {}
|
||||
message ListRouteRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ListRouteResponse { repeated Route routes = 1; }
|
||||
|
||||
message DumpRouteRequest {}
|
||||
message DumpRouteRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message DumpRouteResponse { string result = 1; }
|
||||
|
||||
message ListForeignNetworkRequest {}
|
||||
message ListForeignNetworkRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ForeignNetworkEntryPb {
|
||||
repeated PeerInfo peers = 1;
|
||||
@@ -114,7 +123,7 @@ message ListForeignNetworkResponse {
|
||||
map<string, ForeignNetworkEntryPb> foreign_networks = 1;
|
||||
}
|
||||
|
||||
message ListGlobalForeignNetworkRequest {}
|
||||
message ListGlobalForeignNetworkRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ListGlobalForeignNetworkResponse {
|
||||
// foreign network in the entire network
|
||||
@@ -152,37 +161,25 @@ message Connector {
|
||||
ConnectorStatus status = 2;
|
||||
}
|
||||
|
||||
message ListConnectorRequest {}
|
||||
message ListConnectorRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ListConnectorResponse { repeated Connector connectors = 1; }
|
||||
|
||||
enum ConnectorManageAction {
|
||||
ADD = 0;
|
||||
REMOVE = 1;
|
||||
}
|
||||
|
||||
message ManageConnectorRequest {
|
||||
ConnectorManageAction action = 1;
|
||||
common.Url url = 2;
|
||||
}
|
||||
|
||||
message ManageConnectorResponse {}
|
||||
|
||||
service ConnectorManageRpc {
|
||||
rpc ListConnector(ListConnectorRequest) returns (ListConnectorResponse);
|
||||
rpc ManageConnector(ManageConnectorRequest) returns (ManageConnectorResponse);
|
||||
}
|
||||
|
||||
message MappedListener {
|
||||
common.Url url = 1;
|
||||
message MappedListener { common.Url url = 1; }
|
||||
|
||||
message ListMappedListenerRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ListMappedListenerResponse {
|
||||
repeated MappedListener mappedlisteners = 1;
|
||||
}
|
||||
|
||||
message ListMappedListenerRequest {}
|
||||
|
||||
message ListMappedListenerResponse { repeated MappedListener mappedlisteners = 1; }
|
||||
|
||||
service MappedListenerManageRpc {
|
||||
rpc ListMappedListener(ListMappedListenerRequest) returns (ListMappedListenerResponse);
|
||||
rpc ListMappedListener(ListMappedListenerRequest)
|
||||
returns (ListMappedListenerResponse);
|
||||
}
|
||||
|
||||
message VpnPortalInfo {
|
||||
@@ -191,7 +188,7 @@ message VpnPortalInfo {
|
||||
repeated string connected_clients = 3;
|
||||
}
|
||||
|
||||
message GetVpnPortalInfoRequest {}
|
||||
message GetVpnPortalInfoRequest { InstanceIdentifier instance = 1; }
|
||||
message GetVpnPortalInfoResponse { VpnPortalInfo vpn_portal_info = 1; }
|
||||
|
||||
service VpnPortalRpc {
|
||||
@@ -206,19 +203,19 @@ enum TcpProxyEntryTransportType {
|
||||
}
|
||||
|
||||
enum TcpProxyEntryState {
|
||||
Unknown = 0;
|
||||
// receive syn packet but not start connecting to dst
|
||||
SynReceived = 1;
|
||||
// connecting to dst
|
||||
ConnectingDst = 2;
|
||||
// connected to dst
|
||||
Connected = 3;
|
||||
// connection closed
|
||||
Closed = 4;
|
||||
// closing src
|
||||
ClosingSrc = 5;
|
||||
// closing dst
|
||||
ClosingDst = 6;
|
||||
Unknown = 0;
|
||||
// receive syn packet but not start connecting to dst
|
||||
SynReceived = 1;
|
||||
// connecting to dst
|
||||
ConnectingDst = 2;
|
||||
// connected to dst
|
||||
Connected = 3;
|
||||
// connection closed
|
||||
Closed = 4;
|
||||
// closing src
|
||||
ClosingSrc = 5;
|
||||
// closing dst
|
||||
ClosingDst = 6;
|
||||
}
|
||||
|
||||
message TcpProxyEntry {
|
||||
@@ -229,36 +226,32 @@ message TcpProxyEntry {
|
||||
TcpProxyEntryTransportType transport_type = 5;
|
||||
}
|
||||
|
||||
message ListTcpProxyEntryRequest {}
|
||||
message ListTcpProxyEntryRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ListTcpProxyEntryResponse {
|
||||
repeated TcpProxyEntry entries = 1;
|
||||
}
|
||||
message ListTcpProxyEntryResponse { repeated TcpProxyEntry entries = 1; }
|
||||
|
||||
service TcpProxyRpc {
|
||||
rpc ListTcpProxyEntry(ListTcpProxyEntryRequest)
|
||||
returns (ListTcpProxyEntryResponse);
|
||||
}
|
||||
|
||||
message GetAclStatsRequest {}
|
||||
message GetAclStatsRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message GetAclStatsResponse {
|
||||
acl.AclStats acl_stats = 1;
|
||||
}
|
||||
message GetAclStatsResponse { acl.AclStats acl_stats = 1; }
|
||||
|
||||
service AclManageRpc {
|
||||
rpc GetAclStats(GetAclStatsRequest) returns (GetAclStatsResponse);
|
||||
rpc GetWhitelist(GetWhitelistRequest) returns (GetWhitelistResponse);
|
||||
}
|
||||
|
||||
message GetWhitelistRequest {}
|
||||
message GetWhitelistRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message GetWhitelistResponse {
|
||||
repeated string tcp_ports = 1;
|
||||
repeated string udp_ports = 2;
|
||||
}
|
||||
|
||||
message ListPortForwardRequest {}
|
||||
message ListPortForwardRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message ListPortForwardResponse {
|
||||
repeated common.PortForwardConfigPb cfgs = 1;
|
||||
@@ -274,47 +267,16 @@ message MetricSnapshot {
|
||||
map<string, string> labels = 3;
|
||||
}
|
||||
|
||||
message GetStatsRequest {}
|
||||
message GetStatsRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message GetStatsResponse {
|
||||
repeated MetricSnapshot metrics = 1;
|
||||
}
|
||||
message GetStatsResponse { repeated MetricSnapshot metrics = 1; }
|
||||
|
||||
message GetPrometheusStatsRequest {}
|
||||
message GetPrometheusStatsRequest { InstanceIdentifier instance = 1; }
|
||||
|
||||
message GetPrometheusStatsResponse {
|
||||
string prometheus_text = 1;
|
||||
}
|
||||
message GetPrometheusStatsResponse { string prometheus_text = 1; }
|
||||
|
||||
service StatsRpc {
|
||||
rpc GetStats(GetStatsRequest) returns (GetStatsResponse);
|
||||
rpc GetPrometheusStats(GetPrometheusStatsRequest) returns (GetPrometheusStatsResponse);
|
||||
}
|
||||
|
||||
enum LogLevel {
|
||||
DISABLED = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
INFO = 3;
|
||||
DEBUG = 4;
|
||||
TRACE = 5;
|
||||
}
|
||||
|
||||
message SetLoggerConfigRequest {
|
||||
LogLevel level = 1;
|
||||
}
|
||||
|
||||
message SetLoggerConfigResponse {
|
||||
}
|
||||
|
||||
message GetLoggerConfigRequest {
|
||||
}
|
||||
|
||||
message GetLoggerConfigResponse {
|
||||
LogLevel level = 1;
|
||||
}
|
||||
|
||||
service LoggerRpc {
|
||||
rpc SetLoggerConfig(SetLoggerConfigRequest) returns (SetLoggerConfigResponse);
|
||||
rpc GetLoggerConfig(GetLoggerConfigRequest) returns (GetLoggerConfigResponse);
|
||||
rpc GetPrometheusStats(GetPrometheusStatsRequest)
|
||||
returns (GetPrometheusStatsResponse);
|
||||
}
|
||||
24
easytier/src/proto/api_logger.proto
Normal file
24
easytier/src/proto/api_logger.proto
Normal file
@@ -0,0 +1,24 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package api.logger;
|
||||
|
||||
enum LogLevel {
|
||||
DISABLED = 0;
|
||||
ERROR = 1;
|
||||
WARNING = 2;
|
||||
INFO = 3;
|
||||
DEBUG = 4;
|
||||
TRACE = 5;
|
||||
}
|
||||
|
||||
message SetLoggerConfigRequest { LogLevel level = 1; }
|
||||
|
||||
message SetLoggerConfigResponse {}
|
||||
|
||||
message GetLoggerConfigRequest {}
|
||||
|
||||
message GetLoggerConfigResponse { LogLevel level = 1; }
|
||||
service LoggerRpc {
|
||||
rpc SetLoggerConfig(SetLoggerConfigRequest) returns (SetLoggerConfigResponse);
|
||||
rpc GetLoggerConfig(GetLoggerConfigRequest) returns (GetLoggerConfigResponse);
|
||||
}
|
||||
157
easytier/src/proto/api_manage.proto
Normal file
157
easytier/src/proto/api_manage.proto
Normal file
@@ -0,0 +1,157 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "common.proto";
|
||||
import "peer_rpc.proto";
|
||||
import "api_instance.proto";
|
||||
|
||||
package api.manage;
|
||||
|
||||
enum NetworkingMethod {
|
||||
PublicServer = 0;
|
||||
Manual = 1;
|
||||
Standalone = 2;
|
||||
}
|
||||
|
||||
message NetworkConfig {
|
||||
optional string instance_id = 1;
|
||||
|
||||
optional bool dhcp = 2;
|
||||
optional string virtual_ipv4 = 3;
|
||||
optional int32 network_length = 4;
|
||||
optional string hostname = 5;
|
||||
optional string network_name = 6;
|
||||
optional string network_secret = 7;
|
||||
optional NetworkingMethod networking_method = 8;
|
||||
|
||||
optional string public_server_url = 9;
|
||||
repeated string peer_urls = 10;
|
||||
|
||||
repeated string proxy_cidrs = 11;
|
||||
|
||||
optional bool enable_vpn_portal = 12;
|
||||
optional int32 vpn_portal_listen_port = 13;
|
||||
optional string vpn_portal_client_network_addr = 14;
|
||||
optional int32 vpn_portal_client_network_len = 15;
|
||||
|
||||
optional bool advanced_settings = 16;
|
||||
|
||||
repeated string listener_urls = 17;
|
||||
// optional int32 rpc_port = 18;
|
||||
optional bool latency_first = 19;
|
||||
|
||||
optional string dev_name = 20;
|
||||
|
||||
optional bool use_smoltcp = 21;
|
||||
optional bool disable_ipv6 = 47;
|
||||
optional bool enable_kcp_proxy = 22;
|
||||
optional bool disable_kcp_input = 23;
|
||||
optional bool disable_p2p = 24;
|
||||
optional bool bind_device = 25;
|
||||
optional bool no_tun = 26;
|
||||
|
||||
optional bool enable_exit_node = 27;
|
||||
optional bool relay_all_peer_rpc = 28;
|
||||
optional bool multi_thread = 29;
|
||||
optional bool enable_relay_network_whitelist = 30;
|
||||
repeated string relay_network_whitelist = 31;
|
||||
optional bool enable_manual_routes = 32;
|
||||
repeated string routes = 33;
|
||||
repeated string exit_nodes = 34;
|
||||
optional bool proxy_forward_by_system = 35;
|
||||
optional bool disable_encryption = 36;
|
||||
optional bool enable_socks5 = 37;
|
||||
optional int32 socks5_port = 38;
|
||||
optional bool disable_udp_hole_punching = 39;
|
||||
optional int32 mtu = 40;
|
||||
repeated string mapped_listeners = 41;
|
||||
|
||||
optional bool enable_magic_dns = 42;
|
||||
optional bool enable_private_mode = 43;
|
||||
|
||||
// repeated string rpc_portal_whitelists = 44;
|
||||
|
||||
optional bool enable_quic_proxy = 45;
|
||||
optional bool disable_quic_input = 46;
|
||||
repeated PortForwardConfig port_forwards = 48;
|
||||
|
||||
optional bool disable_sym_hole_punching = 49;
|
||||
}
|
||||
|
||||
message PortForwardConfig {
|
||||
string bind_ip = 1;
|
||||
uint32 bind_port = 2;
|
||||
string dst_ip = 3;
|
||||
uint32 dst_port = 4;
|
||||
string proto = 5;
|
||||
}
|
||||
|
||||
message MyNodeInfo {
|
||||
common.Ipv4Inet virtual_ipv4 = 1;
|
||||
string hostname = 2;
|
||||
string version = 3;
|
||||
peer_rpc.GetIpListResponse ips = 4;
|
||||
common.StunInfo stun_info = 5;
|
||||
repeated common.Url listeners = 6;
|
||||
optional string vpn_portal_cfg = 7;
|
||||
}
|
||||
|
||||
message NetworkInstanceRunningInfo {
|
||||
string dev_name = 1;
|
||||
MyNodeInfo my_node_info = 2;
|
||||
repeated string events = 3;
|
||||
repeated api.instance.Route routes = 4;
|
||||
repeated api.instance.PeerInfo peers = 5;
|
||||
repeated api.instance.PeerRoutePair peer_route_pairs = 6;
|
||||
bool running = 7;
|
||||
optional string error_msg = 8;
|
||||
peer_rpc.RouteForeignNetworkSummary foreign_network_summary = 9;
|
||||
}
|
||||
|
||||
message NetworkInstanceRunningInfoMap {
|
||||
map<string, NetworkInstanceRunningInfo> map = 1;
|
||||
}
|
||||
|
||||
message ValidateConfigRequest { NetworkConfig config = 1; }
|
||||
|
||||
message ValidateConfigResponse { string toml_config = 1; }
|
||||
|
||||
message RunNetworkInstanceRequest {
|
||||
common.UUID inst_id = 1;
|
||||
NetworkConfig config = 2;
|
||||
}
|
||||
|
||||
message RunNetworkInstanceResponse { common.UUID inst_id = 1; }
|
||||
|
||||
message RetainNetworkInstanceRequest { repeated common.UUID inst_ids = 1; }
|
||||
|
||||
message RetainNetworkInstanceResponse {
|
||||
repeated common.UUID remain_inst_ids = 1;
|
||||
}
|
||||
|
||||
message CollectNetworkInfoRequest { repeated common.UUID inst_ids = 1; }
|
||||
|
||||
message CollectNetworkInfoResponse { NetworkInstanceRunningInfoMap info = 1; }
|
||||
|
||||
message ListNetworkInstanceRequest {}
|
||||
|
||||
message ListNetworkInstanceResponse { repeated common.UUID inst_ids = 1; }
|
||||
|
||||
message DeleteNetworkInstanceRequest { repeated common.UUID inst_ids = 1; }
|
||||
|
||||
message DeleteNetworkInstanceResponse {
|
||||
repeated common.UUID remain_inst_ids = 1;
|
||||
}
|
||||
|
||||
service WebClientService {
|
||||
rpc ValidateConfig(ValidateConfigRequest) returns (ValidateConfigResponse) {}
|
||||
rpc RunNetworkInstance(RunNetworkInstanceRequest)
|
||||
returns (RunNetworkInstanceResponse) {}
|
||||
rpc RetainNetworkInstance(RetainNetworkInstanceRequest)
|
||||
returns (RetainNetworkInstanceResponse) {}
|
||||
rpc CollectNetworkInfo(CollectNetworkInfoRequest)
|
||||
returns (CollectNetworkInfoResponse) {}
|
||||
rpc ListNetworkInstance(ListNetworkInstanceRequest)
|
||||
returns (ListNetworkInstanceResponse) {}
|
||||
rpc DeleteNetworkInstance(DeleteNetworkInstanceRequest)
|
||||
returns (DeleteNetworkInstanceResponse) {}
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
use url::Host;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/cli.rs"));
|
||||
|
||||
impl PeerRoutePair {
|
||||
pub fn get_latency_ms(&self) -> Option<f64> {
|
||||
let mut ret = u64::MAX;
|
||||
let p = self.peer.as_ref()?;
|
||||
let default_conn_id = p.default_conn_id.map(|id| id.to_string());
|
||||
for conn in p.conns.iter() {
|
||||
let Some(stats) = &conn.stats else {
|
||||
continue;
|
||||
};
|
||||
if default_conn_id == Some(conn.conn_id.to_string()) {
|
||||
return Some(f64::from(stats.latency_us as u32) / 1000.0);
|
||||
}
|
||||
ret = ret.min(stats.latency_us);
|
||||
}
|
||||
|
||||
if ret == u64::MAX {
|
||||
None
|
||||
} else {
|
||||
Some(f64::from(ret as u32) / 1000.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_rx_bytes(&self) -> Option<u64> {
|
||||
let mut ret = 0;
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
let Some(stats) = &conn.stats else {
|
||||
continue;
|
||||
};
|
||||
ret += stats.rx_bytes;
|
||||
}
|
||||
|
||||
if ret == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_tx_bytes(&self) -> Option<u64> {
|
||||
let mut ret = 0;
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
let Some(stats) = &conn.stats else {
|
||||
continue;
|
||||
};
|
||||
ret += stats.tx_bytes;
|
||||
}
|
||||
|
||||
if ret == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_loss_rate(&self) -> Option<f64> {
|
||||
let mut ret = 0.0;
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
ret += conn.loss_rate;
|
||||
}
|
||||
|
||||
if ret == 0.0 {
|
||||
None
|
||||
} else {
|
||||
Some(ret as f64)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_tunnel_ipv6(tunnel_info: &super::common::TunnelInfo) -> bool {
|
||||
let Some(local_addr) = &tunnel_info.local_addr else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let u: url::Url = local_addr.clone().into();
|
||||
u.host()
|
||||
.map(|h| matches!(h, Host::Ipv6(_)))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn get_tunnel_proto_str(tunnel_info: &super::common::TunnelInfo) -> String {
|
||||
if Self::is_tunnel_ipv6(tunnel_info) {
|
||||
format!("{}6", tunnel_info.tunnel_type)
|
||||
} else {
|
||||
tunnel_info.tunnel_type.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_conn_protos(&self) -> Option<Vec<String>> {
|
||||
let mut ret = vec![];
|
||||
let p = self.peer.as_ref()?;
|
||||
for conn in p.conns.iter() {
|
||||
let Some(tunnel_info) = &conn.tunnel else {
|
||||
continue;
|
||||
};
|
||||
// insert if not exists
|
||||
let tunnel_type = Self::get_tunnel_proto_str(tunnel_info);
|
||||
if !ret.contains(&tunnel_type) {
|
||||
ret.push(tunnel_type);
|
||||
}
|
||||
}
|
||||
|
||||
if ret.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_udp_nat_type(&self) -> String {
|
||||
use crate::proto::common::NatType;
|
||||
let mut ret = NatType::Unknown;
|
||||
if let Some(r) = &self.route.clone().unwrap_or_default().stun_info {
|
||||
ret = NatType::try_from(r.udp_nat_type).unwrap();
|
||||
}
|
||||
format!("{:?}", ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list_peer_route_pair(peers: Vec<PeerInfo>, routes: Vec<Route>) -> Vec<PeerRoutePair> {
|
||||
let mut pairs: Vec<PeerRoutePair> = vec![];
|
||||
|
||||
for route in routes.iter() {
|
||||
let peer = peers.iter().find(|peer| peer.peer_id == route.peer_id);
|
||||
let pair = PeerRoutePair {
|
||||
route: Some(route.clone()),
|
||||
peer: peer.cloned(),
|
||||
};
|
||||
|
||||
pairs.push(pair);
|
||||
}
|
||||
|
||||
pairs.sort_by(|a, b| {
|
||||
let a_is_public_server = a
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.feature_flag.as_ref())
|
||||
.is_some_and(|f| f.is_public_server);
|
||||
|
||||
let b_is_public_server = b
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.feature_flag.as_ref())
|
||||
.is_some_and(|f| f.is_public_server);
|
||||
|
||||
if a_is_public_server != b_is_public_server {
|
||||
return if a_is_public_server {
|
||||
std::cmp::Ordering::Less
|
||||
} else {
|
||||
std::cmp::Ordering::Greater
|
||||
};
|
||||
}
|
||||
|
||||
let a_ip = a
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.ipv4_addr.as_ref())
|
||||
.and_then(|ipv4| ipv4.address.as_ref())
|
||||
.map_or(0, |addr| addr.addr);
|
||||
|
||||
let b_ip = b
|
||||
.route
|
||||
.as_ref()
|
||||
.and_then(|r| r.ipv4_addr.as_ref())
|
||||
.and_then(|ipv4| ipv4.address.as_ref())
|
||||
.map_or(0, |addr| addr.addr);
|
||||
|
||||
a_ip.cmp(&b_ip)
|
||||
});
|
||||
|
||||
pairs
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
include!(concat!(env!("OUT_DIR"), "/config.rs"));
|
||||
|
||||
pub struct Patchable<T> {
|
||||
pub action: Option<ConfigPatchAction>,
|
||||
pub value: Option<T>,
|
||||
}
|
||||
|
||||
impl From<PortForwardPatch> for Patchable<crate::common::config::PortForwardConfig> {
|
||||
fn from(patch: PortForwardPatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(patch.action).ok(),
|
||||
value: patch.cfg.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RoutePatch> for Patchable<cidr::Ipv4Cidr> {
|
||||
fn from(value: RoutePatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: value.cidr.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ExitNodePatch> for Patchable<std::net::IpAddr> {
|
||||
fn from(value: ExitNodePatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: value.node.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StringPatch> for Patchable<String> {
|
||||
fn from(value: StringPatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: Some(value.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UrlPatch> for Patchable<url::Url> {
|
||||
fn from(value: UrlPatch) -> Self {
|
||||
Patchable {
|
||||
action: ConfigPatchAction::try_from(value.action).ok(),
|
||||
value: value.url.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn patch_vec<T>(v: &mut Vec<T>, patches: Vec<Patchable<T>>)
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
for patch in patches {
|
||||
match patch.action {
|
||||
Some(ConfigPatchAction::Add) => {
|
||||
if let Some(value) = patch.value {
|
||||
v.push(value);
|
||||
}
|
||||
}
|
||||
Some(ConfigPatchAction::Remove) => {
|
||||
if let Some(value) = patch.value {
|
||||
v.retain(|x| x != &value);
|
||||
}
|
||||
}
|
||||
Some(ConfigPatchAction::Clear) => {
|
||||
v.clear();
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ syntax = "proto3";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "common.proto";
|
||||
import "cli.proto";
|
||||
import "api_instance.proto";
|
||||
|
||||
package magic_dns;
|
||||
|
||||
@@ -30,7 +30,7 @@ message DnsRecordList {
|
||||
|
||||
message UpdateDnsRecordRequest {
|
||||
string zone = 1;
|
||||
repeated cli.Route routes = 2;
|
||||
repeated api.instance.Route routes = 2;
|
||||
}
|
||||
|
||||
message GetDnsRecordResponse {
|
||||
|
||||
@@ -2,9 +2,8 @@ pub mod rpc_impl;
|
||||
pub mod rpc_types;
|
||||
|
||||
pub mod acl;
|
||||
pub mod cli;
|
||||
pub mod api;
|
||||
pub mod common;
|
||||
pub mod config;
|
||||
pub mod error;
|
||||
pub mod magic_dns;
|
||||
pub mod peer_rpc;
|
||||
|
||||
@@ -6,7 +6,7 @@ use thiserror;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("rust tun error {0}")]
|
||||
#[error("Rust error: {0}")]
|
||||
ExecutionError(#[from] anyhow::Error),
|
||||
|
||||
#[error("Decode error: {0}")]
|
||||
|
||||
@@ -1,188 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "common.proto";
|
||||
import "peer_rpc.proto";
|
||||
import "cli.proto";
|
||||
|
||||
package web;
|
||||
|
||||
enum NetworkingMethod {
|
||||
PublicServer = 0;
|
||||
Manual = 1;
|
||||
Standalone = 2;
|
||||
}
|
||||
|
||||
message NetworkConfig {
|
||||
optional string instance_id = 1;
|
||||
|
||||
optional bool dhcp = 2;
|
||||
optional string virtual_ipv4 = 3;
|
||||
optional int32 network_length = 4;
|
||||
optional string hostname = 5;
|
||||
optional string network_name = 6;
|
||||
optional string network_secret = 7;
|
||||
optional NetworkingMethod networking_method = 8;
|
||||
|
||||
optional string public_server_url = 9;
|
||||
repeated string peer_urls = 10;
|
||||
|
||||
repeated string proxy_cidrs = 11;
|
||||
|
||||
optional bool enable_vpn_portal = 12;
|
||||
optional int32 vpn_portal_listen_port = 13;
|
||||
optional string vpn_portal_client_network_addr = 14;
|
||||
optional int32 vpn_portal_client_network_len = 15;
|
||||
|
||||
optional bool advanced_settings = 16;
|
||||
|
||||
repeated string listener_urls = 17;
|
||||
optional int32 rpc_port = 18;
|
||||
optional bool latency_first = 19;
|
||||
|
||||
optional string dev_name = 20;
|
||||
|
||||
optional bool use_smoltcp = 21;
|
||||
optional bool disable_ipv6 = 47;
|
||||
optional bool enable_kcp_proxy = 22;
|
||||
optional bool disable_kcp_input = 23;
|
||||
optional bool disable_p2p = 24;
|
||||
optional bool bind_device = 25;
|
||||
optional bool no_tun = 26;
|
||||
|
||||
optional bool enable_exit_node = 27;
|
||||
optional bool relay_all_peer_rpc = 28;
|
||||
optional bool multi_thread = 29;
|
||||
optional bool enable_relay_network_whitelist = 30;
|
||||
repeated string relay_network_whitelist = 31;
|
||||
optional bool enable_manual_routes = 32;
|
||||
repeated string routes = 33;
|
||||
repeated string exit_nodes = 34;
|
||||
optional bool proxy_forward_by_system = 35;
|
||||
optional bool disable_encryption = 36;
|
||||
optional bool enable_socks5 = 37;
|
||||
optional int32 socks5_port = 38;
|
||||
optional bool disable_udp_hole_punching = 39;
|
||||
optional int32 mtu = 40;
|
||||
repeated string mapped_listeners = 41;
|
||||
|
||||
optional bool enable_magic_dns = 42;
|
||||
optional bool enable_private_mode = 43;
|
||||
|
||||
repeated string rpc_portal_whitelists = 44;
|
||||
|
||||
optional bool enable_quic_proxy = 45;
|
||||
optional bool disable_quic_input = 46;
|
||||
repeated PortForwardConfig port_forwards = 48;
|
||||
|
||||
optional bool disable_sym_hole_punching = 49;
|
||||
}
|
||||
|
||||
message PortForwardConfig {
|
||||
string bind_ip = 1;
|
||||
uint32 bind_port = 2;
|
||||
string dst_ip = 3;
|
||||
uint32 dst_port = 4;
|
||||
string proto = 5;
|
||||
}
|
||||
|
||||
message MyNodeInfo {
|
||||
common.Ipv4Inet virtual_ipv4 = 1;
|
||||
string hostname = 2;
|
||||
string version = 3;
|
||||
peer_rpc.GetIpListResponse ips = 4;
|
||||
common.StunInfo stun_info = 5;
|
||||
repeated common.Url listeners = 6;
|
||||
optional string vpn_portal_cfg = 7;
|
||||
}
|
||||
|
||||
message NetworkInstanceRunningInfo {
|
||||
string dev_name = 1;
|
||||
MyNodeInfo my_node_info = 2;
|
||||
repeated string events = 3;
|
||||
repeated cli.Route routes = 4;
|
||||
repeated cli.PeerInfo peers = 5;
|
||||
repeated cli.PeerRoutePair peer_route_pairs = 6;
|
||||
bool running = 7;
|
||||
optional string error_msg = 8;
|
||||
peer_rpc.RouteForeignNetworkSummary foreign_network_summary = 9;
|
||||
}
|
||||
|
||||
message NetworkInstanceRunningInfoMap {
|
||||
map<string, NetworkInstanceRunningInfo> map = 1;
|
||||
}
|
||||
|
||||
message HeartbeatRequest {
|
||||
common.UUID machine_id = 1;
|
||||
common.UUID inst_id = 2;
|
||||
string user_token = 3;
|
||||
common.UUID machine_id = 1;
|
||||
common.UUID inst_id = 2;
|
||||
string user_token = 3;
|
||||
|
||||
string easytier_version = 4;
|
||||
string report_time = 5;
|
||||
string hostname = 6;
|
||||
string easytier_version = 4;
|
||||
string report_time = 5;
|
||||
string hostname = 6;
|
||||
|
||||
repeated common.UUID running_network_instances = 7;
|
||||
repeated common.UUID running_network_instances = 7;
|
||||
}
|
||||
|
||||
message HeartbeatResponse {
|
||||
}
|
||||
message HeartbeatResponse {}
|
||||
|
||||
service WebServerService {
|
||||
rpc Heartbeat(HeartbeatRequest) returns (HeartbeatResponse) {}
|
||||
}
|
||||
|
||||
message ValidateConfigRequest {
|
||||
NetworkConfig config = 1;
|
||||
}
|
||||
|
||||
message ValidateConfigResponse {
|
||||
string toml_config = 1;
|
||||
}
|
||||
|
||||
message RunNetworkInstanceRequest {
|
||||
common.UUID inst_id = 1;
|
||||
NetworkConfig config = 2;
|
||||
}
|
||||
|
||||
message RunNetworkInstanceResponse {
|
||||
common.UUID inst_id = 1;
|
||||
}
|
||||
|
||||
message RetainNetworkInstanceRequest {
|
||||
repeated common.UUID inst_ids = 1;
|
||||
}
|
||||
|
||||
message RetainNetworkInstanceResponse {
|
||||
repeated common.UUID remain_inst_ids = 1;
|
||||
}
|
||||
|
||||
message CollectNetworkInfoRequest {
|
||||
repeated common.UUID inst_ids = 1;
|
||||
}
|
||||
|
||||
message CollectNetworkInfoResponse {
|
||||
NetworkInstanceRunningInfoMap info = 1;
|
||||
}
|
||||
|
||||
message ListNetworkInstanceRequest {
|
||||
}
|
||||
|
||||
message ListNetworkInstanceResponse {
|
||||
repeated common.UUID inst_ids = 1;
|
||||
}
|
||||
|
||||
message DeleteNetworkInstanceRequest {
|
||||
repeated common.UUID inst_ids = 1;
|
||||
}
|
||||
|
||||
message DeleteNetworkInstanceResponse {
|
||||
repeated common.UUID remain_inst_ids = 1;
|
||||
}
|
||||
|
||||
service WebClientService {
|
||||
rpc ValidateConfig(ValidateConfigRequest) returns (ValidateConfigResponse) {}
|
||||
rpc RunNetworkInstance(RunNetworkInstanceRequest) returns (RunNetworkInstanceResponse) {}
|
||||
rpc RetainNetworkInstance(RetainNetworkInstanceRequest) returns (RetainNetworkInstanceResponse) {}
|
||||
rpc CollectNetworkInfo(CollectNetworkInfoRequest) returns (CollectNetworkInfoResponse) {}
|
||||
rpc ListNetworkInstance(ListNetworkInstanceRequest) returns (ListNetworkInstanceResponse) {}
|
||||
rpc DeleteNetworkInstance(DeleteNetworkInstanceRequest) returns (DeleteNetworkInstanceResponse) {}
|
||||
}
|
||||
rpc Heartbeat(HeartbeatRequest) returns (HeartbeatResponse);
|
||||
}
|
||||
50
easytier/src/rpc_service/acl_manage.rs
Normal file
50
easytier/src/rpc_service/acl_manage.rs
Normal 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
easytier/src/rpc_service/api.rs
Normal file
164
easytier/src/rpc_service/api.rs
Normal 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
easytier/src/rpc_service/config.rs
Normal file
36
easytier/src/rpc_service/config.rs
Normal 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
|
||||
}
|
||||
}
|
||||
36
easytier/src/rpc_service/connector_manage.rs
Normal file
36
easytier/src/rpc_service/connector_manage.rs
Normal file
@@ -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
easytier/src/rpc_service/instance_manage.rs
Normal file
135
easytier/src/rpc_service/instance_manage.rs
Normal 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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::sync::{mpsc::Sender, Mutex, OnceLock};
|
||||
|
||||
use crate::proto::{
|
||||
cli::{
|
||||
api::logger::{
|
||||
GetLoggerConfigRequest, GetLoggerConfigResponse, LogLevel, LoggerRpc,
|
||||
SetLoggerConfigRequest, SetLoggerConfigResponse,
|
||||
},
|
||||
@@ -11,14 +11,10 @@ use crate::proto::{
|
||||
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)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct LoggerRpcService;
|
||||
|
||||
impl LoggerRpcService {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
fn log_level_to_string(level: LogLevel) -> String {
|
||||
match level {
|
||||
LogLevel::Disabled => "off".to_string(),
|
||||
38
easytier/src/rpc_service/mapped_listener_manage.rs
Normal file
38
easytier/src/rpc_service/mapped_listener_manage.rs
Normal file
@@ -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
easytier/src/rpc_service/mod.rs
Normal file
108
easytier/src/rpc_service/mod.rs
Normal 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
easytier/src/rpc_service/peer_manage.rs
Normal file
91
easytier/src/rpc_service/peer_manage.rs
Normal 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
|
||||
}
|
||||
}
|
||||
36
easytier/src/rpc_service/port_forward_manage.rs
Normal file
36
easytier/src/rpc_service/port_forward_manage.rs
Normal file
@@ -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
easytier/src/rpc_service/proxy.rs
Normal file
41
easytier/src/rpc_service/proxy.rs
Normal 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
easytier/src/rpc_service/stats.rs
Normal file
50
easytier/src/rpc_service/stats.rs
Normal 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
easytier/src/rpc_service/vpn_portal.rs
Normal file
36
easytier/src/rpc_service/vpn_portal.rs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ pub fn enable_log() {
|
||||
.init();
|
||||
}
|
||||
|
||||
fn check_route(ipv4: &str, dst_peer_id: PeerId, routes: Vec<crate::proto::cli::Route>) {
|
||||
fn check_route(ipv4: &str, dst_peer_id: PeerId, routes: Vec<crate::proto::api::instance::Route>) {
|
||||
let mut found = false;
|
||||
for r in routes.iter() {
|
||||
if r.ipv4_addr == Some(ipv4.parse().unwrap()) {
|
||||
@@ -148,9 +148,9 @@ fn check_route(ipv4: &str, dst_peer_id: PeerId, routes: Vec<crate::proto::cli::R
|
||||
}
|
||||
|
||||
fn check_route_ex(
|
||||
routes: Vec<crate::proto::cli::Route>,
|
||||
routes: Vec<crate::proto::api::instance::Route>,
|
||||
peer_id: PeerId,
|
||||
checker: impl Fn(&crate::proto::cli::Route) -> bool,
|
||||
checker: impl Fn(&crate::proto::api::instance::Route) -> bool,
|
||||
) {
|
||||
let mut found = false;
|
||||
for r in routes.iter() {
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::{
|
||||
stats_manager::{LabelType, MetricName},
|
||||
},
|
||||
instance::instance::Instance,
|
||||
proto::{cli::TcpProxyEntryTransportType, common::CompressionAlgoPb},
|
||||
proto::{api::instance::TcpProxyEntryTransportType, common::CompressionAlgoPb},
|
||||
tunnel::{
|
||||
common::tests::{_tunnel_bench_netns, wait_for_condition},
|
||||
ring::RingTunnelConnector,
|
||||
@@ -2100,8 +2100,10 @@ pub async fn acl_group_based_test(
|
||||
#[serial_test::serial]
|
||||
pub async fn config_patch_test() {
|
||||
use crate::proto::{
|
||||
api::config::{
|
||||
ConfigPatchAction, InstanceConfigPatch, PortForwardPatch, ProxyNetworkPatch,
|
||||
},
|
||||
common::{PortForwardConfigPb, SocketType},
|
||||
config::{ConfigPatchAction, InstanceConfigPatch, PortForwardPatch, ProxyNetworkPatch},
|
||||
};
|
||||
use crate::tunnel::common::tests::_tunnel_pingpong_netns_with_timeout;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::common::{
|
||||
config::LoggingConfigLoader, get_logger_timer_rfc3339, tracing_rolling_appender::*,
|
||||
};
|
||||
|
||||
pub type PeerRoutePair = crate::proto::cli::PeerRoutePair;
|
||||
pub type PeerRoutePair = crate::proto::api::instance::PeerRoutePair;
|
||||
|
||||
pub fn cost_to_str(cost: i32) -> String {
|
||||
if cost == 1 {
|
||||
@@ -30,7 +30,7 @@ pub fn init_logger(
|
||||
config: impl LoggingConfigLoader,
|
||||
need_reload: bool,
|
||||
) -> Result<Option<NewFilterSender>, anyhow::Error> {
|
||||
use crate::instance::logger_rpc_service::{CURRENT_LOG_LEVEL, LOGGER_LEVEL_SENDER};
|
||||
use crate::rpc_service::logger::{CURRENT_LOG_LEVEL, LOGGER_LEVEL_SENDER};
|
||||
|
||||
let file_config = config.get_file_logger_config();
|
||||
let file_level = file_config
|
||||
@@ -254,6 +254,11 @@ pub fn find_free_tcp_port(mut range: std::ops::Range<u16>) -> Option<u16> {
|
||||
range.find(|&port| check_tcp_available(port))
|
||||
}
|
||||
|
||||
pub fn weak_upgrade<T>(weak: &std::sync::Weak<T>) -> anyhow::Result<std::sync::Arc<T>> {
|
||||
weak.upgrade()
|
||||
.ok_or_else(|| anyhow::anyhow!("{} not available", std::any::type_name::<T>()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::common::config::{self};
|
||||
|
||||
@@ -1,31 +1,22 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
common::config::ConfigLoader,
|
||||
instance_manager::NetworkInstanceManager,
|
||||
launcher::ConfigSource,
|
||||
proto::{
|
||||
rpc_types::{self, controller::BaseController},
|
||||
web::{
|
||||
CollectNetworkInfoRequest, CollectNetworkInfoResponse, DeleteNetworkInstanceRequest,
|
||||
DeleteNetworkInstanceResponse, ListNetworkInstanceRequest, ListNetworkInstanceResponse,
|
||||
NetworkInstanceRunningInfoMap, RetainNetworkInstanceRequest,
|
||||
RetainNetworkInstanceResponse, RunNetworkInstanceRequest, RunNetworkInstanceResponse,
|
||||
ValidateConfigRequest, ValidateConfigResponse, WebClientService,
|
||||
},
|
||||
},
|
||||
rpc_service::instance_manage::InstanceManageRpcService,
|
||||
};
|
||||
|
||||
pub struct Controller {
|
||||
token: String,
|
||||
hostname: String,
|
||||
manager: NetworkInstanceManager,
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
}
|
||||
|
||||
impl Controller {
|
||||
pub fn new(token: String, hostname: String) -> Self {
|
||||
pub fn new(token: String, hostname: String, manager: Arc<NetworkInstanceManager>) -> Self {
|
||||
Controller {
|
||||
token,
|
||||
hostname,
|
||||
manager: NetworkInstanceManager::new(),
|
||||
manager,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,117 +31,8 @@ impl Controller {
|
||||
pub fn hostname(&self) -> String {
|
||||
self.hostname.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl WebClientService for Controller {
|
||||
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(),
|
||||
})
|
||||
pub fn get_rpc_service(&self) -> InstanceManageRpcService {
|
||||
InstanceManageRpcService::new(self.manager.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::{common::scoped_task::ScopedTask, tunnel::TunnelConnector};
|
||||
use crate::{
|
||||
common::scoped_task::ScopedTask, instance_manager::NetworkInstanceManager,
|
||||
tunnel::TunnelConnector,
|
||||
};
|
||||
|
||||
pub mod controller;
|
||||
pub mod session;
|
||||
@@ -15,10 +18,12 @@ impl WebClient {
|
||||
connector: T,
|
||||
token: S,
|
||||
hostname: H,
|
||||
manager: Arc<NetworkInstanceManager>,
|
||||
) -> Self {
|
||||
let controller = Arc::new(controller::Controller::new(
|
||||
token.to_string(),
|
||||
hostname.to_string(),
|
||||
manager,
|
||||
));
|
||||
|
||||
let controller_clone = controller.clone();
|
||||
|
||||
@@ -9,12 +9,10 @@ use tokio::{
|
||||
use crate::{
|
||||
common::{constants::EASYTIER_VERSION, get_machine_id},
|
||||
proto::{
|
||||
api::manage::WebClientServiceServer,
|
||||
rpc_impl::bidirect::BidirectRpcManager,
|
||||
rpc_types::controller::BaseController,
|
||||
web::{
|
||||
HeartbeatRequest, HeartbeatResponse, WebClientServiceServer,
|
||||
WebServerServiceClientFactory,
|
||||
},
|
||||
web::{HeartbeatRequest, HeartbeatResponse, WebServerServiceClientFactory},
|
||||
},
|
||||
tunnel::Tunnel,
|
||||
};
|
||||
@@ -41,10 +39,10 @@ impl Session {
|
||||
let rpc_mgr = BidirectRpcManager::new();
|
||||
rpc_mgr.run_with_tunnel(tunnel);
|
||||
|
||||
rpc_mgr
|
||||
.rpc_server()
|
||||
.registry()
|
||||
.register(WebClientServiceServer::new(controller.clone()), "");
|
||||
rpc_mgr.rpc_server().registry().register(
|
||||
WebClientServiceServer::new(controller.get_rpc_service()),
|
||||
"",
|
||||
);
|
||||
|
||||
let mut tasks: JoinSet<()> = JoinSet::new();
|
||||
let heartbeat_ctx =
|
||||
|
||||
Reference in New Issue
Block a user