mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 10:14:35 +00:00
clippy all codes (#1214)
1. clippy code 2. add fmt and clippy check in ci
This commit is contained in:
@@ -178,6 +178,12 @@ impl AclLogContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub type SharedState = (
|
||||
Arc<DashMap<String, ConnTrackEntry>>,
|
||||
Arc<DashMap<RateLimitKey, Arc<TokenBucket>>>,
|
||||
Arc<DashMap<AclStatKey, u64>>,
|
||||
);
|
||||
|
||||
// High-performance ACL processor - No more internal locks!
|
||||
pub struct AclProcessor {
|
||||
// Immutable rule vectors - no locks needed since they're never modified after creation
|
||||
@@ -321,7 +327,7 @@ impl AclProcessor {
|
||||
.rules
|
||||
.iter()
|
||||
.filter(|rule| rule.enabled)
|
||||
.map(|rule| Self::convert_to_fast_lookup_rule(rule))
|
||||
.map(Self::convert_to_fast_lookup_rule)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Sort by priority (higher priority first)
|
||||
@@ -422,7 +428,7 @@ impl AclProcessor {
|
||||
|
||||
self.inc_cache_entry_stats(cache_entry, packet_info);
|
||||
|
||||
return cache_entry.acl_result.clone().unwrap();
|
||||
cache_entry.acl_result.clone().unwrap()
|
||||
}
|
||||
|
||||
fn inc_cache_entry_stats(&self, cache_entry: &AclCacheEntry, packet_info: &PacketInfo) {
|
||||
@@ -539,7 +545,7 @@ impl AclProcessor {
|
||||
cache_entry.rule_stats_vec.push(rule.rule_stats.clone());
|
||||
cache_entry.matched_rule = RuleId::Priority(rule.priority);
|
||||
cache_entry.acl_result = Some(AclResult {
|
||||
action: rule.action.clone(),
|
||||
action: rule.action,
|
||||
matched_rule: Some(RuleId::Priority(rule.priority)),
|
||||
should_log: false,
|
||||
log_context: Some(AclLogContext::RuleMatch {
|
||||
@@ -595,13 +601,7 @@ impl AclProcessor {
|
||||
}
|
||||
|
||||
/// Get shared state for preserving across hot reloads
|
||||
pub fn get_shared_state(
|
||||
&self,
|
||||
) -> (
|
||||
Arc<DashMap<String, ConnTrackEntry>>,
|
||||
Arc<DashMap<RateLimitKey, Arc<TokenBucket>>>,
|
||||
Arc<DashMap<AclStatKey, u64>>,
|
||||
) {
|
||||
pub fn get_shared_state(&self) -> SharedState {
|
||||
(
|
||||
self.conn_track.clone(),
|
||||
self.rate_limiters.clone(),
|
||||
@@ -698,9 +698,9 @@ impl AclProcessor {
|
||||
}
|
||||
|
||||
/// Check connection state for stateful rules
|
||||
fn check_connection_state(&self, conn_track_key: &String, packet_info: &PacketInfo) {
|
||||
fn check_connection_state(&self, conn_track_key: &str, packet_info: &PacketInfo) {
|
||||
self.conn_track
|
||||
.entry(conn_track_key.clone())
|
||||
.entry(conn_track_key.to_string())
|
||||
.and_modify(|x| {
|
||||
x.last_seen = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
@@ -764,13 +764,13 @@ impl AclProcessor {
|
||||
let src_ip_ranges = rule
|
||||
.source_ips
|
||||
.iter()
|
||||
.filter_map(|ip_inet| Self::convert_ip_inet_to_cidr(ip_inet))
|
||||
.filter_map(|x| Self::convert_ip_inet_to_cidr(x.as_str()))
|
||||
.collect();
|
||||
|
||||
let dst_ip_ranges = rule
|
||||
.destination_ips
|
||||
.iter()
|
||||
.filter_map(|ip_inet| Self::convert_ip_inet_to_cidr(ip_inet))
|
||||
.filter_map(|x| Self::convert_ip_inet_to_cidr(x.as_str()))
|
||||
.collect();
|
||||
|
||||
let src_port_ranges = rule
|
||||
@@ -820,8 +820,8 @@ impl AclProcessor {
|
||||
}
|
||||
|
||||
/// Convert IpInet to CIDR for fast lookup
|
||||
fn convert_ip_inet_to_cidr(input: &String) -> Option<cidr::IpCidr> {
|
||||
cidr::IpCidr::from_str(input.as_str()).ok()
|
||||
fn convert_ip_inet_to_cidr(input: &str) -> Option<cidr::IpCidr> {
|
||||
cidr::IpCidr::from_str(input).ok()
|
||||
}
|
||||
|
||||
/// Increment statistics counter
|
||||
@@ -898,17 +898,13 @@ impl AclProcessor {
|
||||
}
|
||||
|
||||
// 新增辅助函数
|
||||
fn parse_port_start(
|
||||
port_strs: &::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
||||
) -> Option<u16> {
|
||||
fn parse_port_start(port_strs: &[String]) -> Option<u16> {
|
||||
port_strs
|
||||
.iter()
|
||||
.filter_map(|s| parse_port_range(s).map(|(start, _)| start))
|
||||
.min()
|
||||
}
|
||||
fn parse_port_end(
|
||||
port_strs: &::prost::alloc::vec::Vec<::prost::alloc::string::String>,
|
||||
) -> Option<u16> {
|
||||
fn parse_port_end(port_strs: &[String]) -> Option<u16> {
|
||||
port_strs
|
||||
.iter()
|
||||
.filter_map(|s| parse_port_range(s).map(|(_, end)| end))
|
||||
@@ -1154,18 +1150,22 @@ mod tests {
|
||||
let mut acl_v1 = AclV1::default();
|
||||
|
||||
// Create inbound chain
|
||||
let mut chain = Chain::default();
|
||||
chain.name = "test_inbound".to_string();
|
||||
chain.chain_type = ChainType::Inbound as i32;
|
||||
chain.enabled = true;
|
||||
let mut chain = Chain {
|
||||
name: "test_inbound".to_string(),
|
||||
chain_type: ChainType::Inbound as i32,
|
||||
enabled: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Allow all rule
|
||||
let mut rule = Rule::default();
|
||||
rule.name = "allow_all".to_string();
|
||||
rule.priority = 100;
|
||||
rule.enabled = true;
|
||||
rule.action = Action::Allow as i32;
|
||||
rule.protocol = Protocol::Any as i32;
|
||||
let rule = Rule {
|
||||
name: "allow_all".to_string(),
|
||||
priority: 100,
|
||||
enabled: true,
|
||||
action: Action::Allow as i32,
|
||||
protocol: Protocol::Any as i32,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
chain.rules.push(rule);
|
||||
acl_v1.chains.push(chain);
|
||||
@@ -1278,12 +1278,14 @@ mod tests {
|
||||
// 创建新配置(模拟热加载)
|
||||
let mut new_config = create_test_acl_config();
|
||||
if let Some(ref mut acl_v1) = new_config.acl_v1 {
|
||||
let mut drop_rule = Rule::default();
|
||||
drop_rule.name = "drop_all".to_string();
|
||||
drop_rule.priority = 200;
|
||||
drop_rule.enabled = true;
|
||||
drop_rule.action = Action::Drop as i32;
|
||||
drop_rule.protocol = Protocol::Any as i32;
|
||||
let drop_rule = Rule {
|
||||
name: "drop_all".to_string(),
|
||||
priority: 200,
|
||||
enabled: true,
|
||||
action: Action::Drop as i32,
|
||||
protocol: Protocol::Any as i32,
|
||||
..Default::default()
|
||||
};
|
||||
acl_v1.chains[0].rules.push(drop_rule);
|
||||
}
|
||||
|
||||
@@ -1321,40 +1323,48 @@ mod tests {
|
||||
let mut acl_config = Acl::default();
|
||||
|
||||
let mut acl_v1 = AclV1::default();
|
||||
let mut chain = Chain::default();
|
||||
chain.name = "performance_test".to_string();
|
||||
chain.chain_type = ChainType::Inbound as i32;
|
||||
chain.enabled = true;
|
||||
let mut chain = Chain {
|
||||
name: "performance_test".to_string(),
|
||||
chain_type: ChainType::Inbound as i32,
|
||||
enabled: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// 1. High-priority simple rule for UDP (can be cached efficiently)
|
||||
let mut simple_rule = Rule::default();
|
||||
simple_rule.name = "simple_udp".to_string();
|
||||
simple_rule.priority = 300;
|
||||
simple_rule.enabled = true;
|
||||
simple_rule.action = Action::Allow as i32;
|
||||
simple_rule.protocol = Protocol::Udp as i32;
|
||||
let simple_rule = Rule {
|
||||
name: "simple_udp".to_string(),
|
||||
priority: 300,
|
||||
enabled: true,
|
||||
action: Action::Allow as i32,
|
||||
protocol: Protocol::Udp as i32,
|
||||
..Default::default()
|
||||
};
|
||||
// No stateful or rate limit - can benefit from full cache optimization
|
||||
chain.rules.push(simple_rule);
|
||||
|
||||
// 2. Medium-priority stateful + rate-limited rule for TCP (security critical)
|
||||
let mut security_rule = Rule::default();
|
||||
security_rule.name = "security_tcp".to_string();
|
||||
security_rule.priority = 200;
|
||||
security_rule.enabled = true;
|
||||
security_rule.action = Action::Allow as i32;
|
||||
security_rule.protocol = Protocol::Tcp as i32;
|
||||
security_rule.stateful = true;
|
||||
security_rule.rate_limit = 100; // 100 packets/sec
|
||||
security_rule.burst_limit = 200;
|
||||
let security_rule = Rule {
|
||||
name: "security_tcp".to_string(),
|
||||
priority: 200,
|
||||
enabled: true,
|
||||
action: Action::Allow as i32,
|
||||
protocol: Protocol::Tcp as i32,
|
||||
stateful: true,
|
||||
rate_limit: 100,
|
||||
burst_limit: 200,
|
||||
..Default::default()
|
||||
};
|
||||
chain.rules.push(security_rule);
|
||||
|
||||
// 3. Low-priority default allow rule for Any
|
||||
let mut default_rule = Rule::default();
|
||||
default_rule.name = "default_allow".to_string();
|
||||
default_rule.priority = 100;
|
||||
default_rule.enabled = true;
|
||||
default_rule.action = Action::Allow as i32;
|
||||
default_rule.protocol = Protocol::Any as i32;
|
||||
let default_rule = Rule {
|
||||
name: "default_allow".to_string(),
|
||||
priority: 100,
|
||||
enabled: true,
|
||||
action: Action::Allow as i32,
|
||||
protocol: Protocol::Any as i32,
|
||||
..Default::default()
|
||||
};
|
||||
chain.rules.push(default_rule);
|
||||
|
||||
acl_v1.chains.push(chain);
|
||||
@@ -1441,15 +1451,16 @@ mod tests {
|
||||
|
||||
// Create a very restrictive rate-limited rule
|
||||
if let Some(ref mut acl_v1) = acl_config.acl_v1 {
|
||||
let mut rule = Rule::default();
|
||||
rule.name = "strict_rate_limit".to_string();
|
||||
rule.priority = 200;
|
||||
rule.enabled = true;
|
||||
rule.action = Action::Allow as i32;
|
||||
rule.protocol = Protocol::Any as i32;
|
||||
rule.rate_limit = 1; // Allow only 1 packet per second
|
||||
rule.burst_limit = 1; // Burst of 1 packet
|
||||
|
||||
let rule = Rule {
|
||||
name: "strict_rate_limit".to_string(),
|
||||
priority: 200,
|
||||
enabled: true,
|
||||
action: Action::Allow as i32,
|
||||
protocol: Protocol::Any as i32,
|
||||
rate_limit: 1, // Allow only 1 packet per second
|
||||
burst_limit: 1, // Burst of 1 packet
|
||||
..Default::default()
|
||||
};
|
||||
acl_v1.chains[0].rules.push(rule);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ pub trait Compressor {
|
||||
|
||||
pub struct DefaultCompressor {}
|
||||
|
||||
impl Default for DefaultCompressor {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl DefaultCompressor {
|
||||
pub fn new() -> Self {
|
||||
DefaultCompressor {}
|
||||
@@ -195,11 +201,11 @@ pub mod tests {
|
||||
packet,
|
||||
packet.payload_len()
|
||||
);
|
||||
assert_eq!(packet.peer_manager_header().unwrap().is_compressed(), true);
|
||||
assert!(packet.peer_manager_header().unwrap().is_compressed());
|
||||
|
||||
compressor.decompress(&mut packet).await.unwrap();
|
||||
assert_eq!(packet.payload(), text);
|
||||
assert_eq!(packet.peer_manager_header().unwrap().is_compressed(), false);
|
||||
assert!(!packet.peer_manager_header().unwrap().is_compressed());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -215,10 +221,10 @@ pub mod tests {
|
||||
.compress(&mut packet, CompressorAlgo::ZstdDefault)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(packet.peer_manager_header().unwrap().is_compressed(), false);
|
||||
assert!(!packet.peer_manager_header().unwrap().is_compressed());
|
||||
|
||||
compressor.decompress(&mut packet).await.unwrap();
|
||||
assert_eq!(packet.payload(), text);
|
||||
assert_eq!(packet.peer_manager_header().unwrap().is_compressed(), false);
|
||||
assert!(!packet.peer_manager_header().unwrap().is_compressed());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::{
|
||||
hash::Hasher,
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
u64,
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
@@ -48,7 +48,7 @@ pub fn gen_default_flags() -> Flags {
|
||||
disable_quic_input: false,
|
||||
foreign_relay_bps_limit: u64::MAX,
|
||||
multi_thread_count: 2,
|
||||
encryption_algorithm: "".to_string(), // 空字符串表示使用默认的 AES-GCM
|
||||
encryption_algorithm: "aes-gcm".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ pub trait LoggingConfigLoader {
|
||||
|
||||
pub type NetworkSecretDigest = [u8; 32];
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, Default, Eq, Hash)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct NetworkIdentity {
|
||||
pub network_name: String,
|
||||
pub network_secret: Option<String>,
|
||||
@@ -218,27 +218,53 @@ pub struct NetworkIdentity {
|
||||
pub network_secret_digest: Option<NetworkSecretDigest>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash)]
|
||||
struct NetworkIdentityWithOnlyDigest {
|
||||
network_name: String,
|
||||
network_secret_digest: Option<NetworkSecretDigest>,
|
||||
}
|
||||
|
||||
impl From<NetworkIdentity> for NetworkIdentityWithOnlyDigest {
|
||||
fn from(identity: NetworkIdentity) -> Self {
|
||||
if identity.network_secret_digest.is_some() {
|
||||
Self {
|
||||
network_name: identity.network_name,
|
||||
network_secret_digest: identity.network_secret_digest,
|
||||
}
|
||||
} else if identity.network_secret.is_some() {
|
||||
let mut network_secret_digest = [0u8; 32];
|
||||
generate_digest_from_str(
|
||||
&identity.network_name,
|
||||
identity.network_secret.as_ref().unwrap(),
|
||||
&mut network_secret_digest,
|
||||
);
|
||||
Self {
|
||||
network_name: identity.network_name,
|
||||
network_secret_digest: Some(network_secret_digest),
|
||||
}
|
||||
} else {
|
||||
Self {
|
||||
network_name: identity.network_name,
|
||||
network_secret_digest: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for NetworkIdentity {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.network_name != other.network_name {
|
||||
return false;
|
||||
}
|
||||
let self_with_digest = NetworkIdentityWithOnlyDigest::from(self.clone());
|
||||
let other_with_digest = NetworkIdentityWithOnlyDigest::from(other.clone());
|
||||
self_with_digest == other_with_digest
|
||||
}
|
||||
}
|
||||
|
||||
if self.network_secret.is_some()
|
||||
&& other.network_secret.is_some()
|
||||
&& self.network_secret != other.network_secret
|
||||
{
|
||||
return false;
|
||||
}
|
||||
impl Eq for NetworkIdentity {}
|
||||
|
||||
if self.network_secret_digest.is_some()
|
||||
&& other.network_secret_digest.is_some()
|
||||
&& self.network_secret_digest != other.network_secret_digest
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
impl std::hash::Hash for NetworkIdentity {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
let self_with_digest = NetworkIdentityWithOnlyDigest::from(self.clone());
|
||||
self_with_digest.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,8 +279,10 @@ impl NetworkIdentity {
|
||||
network_secret_digest: Some(network_secret_digest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default() -> Self {
|
||||
impl Default for NetworkIdentity {
|
||||
fn default() -> Self {
|
||||
Self::new("default".to_string(), "".to_string())
|
||||
}
|
||||
}
|
||||
@@ -328,12 +356,12 @@ impl From<PortForwardConfigPb> for PortForwardConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<PortForwardConfigPb> for PortForwardConfig {
|
||||
fn into(self) -> PortForwardConfigPb {
|
||||
impl From<PortForwardConfig> for PortForwardConfigPb {
|
||||
fn from(val: PortForwardConfig) -> Self {
|
||||
PortForwardConfigPb {
|
||||
bind_addr: Some(self.bind_addr.into()),
|
||||
dst_addr: Some(self.dst_addr.into()),
|
||||
socket_type: match self.proto.to_lowercase().as_str() {
|
||||
bind_addr: Some(val.bind_addr.into()),
|
||||
dst_addr: Some(val.dst_addr.into()),
|
||||
socket_type: match val.proto.to_lowercase().as_str() {
|
||||
"tcp" => SocketType::Tcp as i32,
|
||||
"udp" => SocketType::Udp as i32,
|
||||
_ => SocketType::Tcp as i32,
|
||||
@@ -493,8 +521,7 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
locked_config
|
||||
.ipv4
|
||||
.as_ref()
|
||||
.map(|s| s.parse().ok())
|
||||
.flatten()
|
||||
.and_then(|s| s.parse().ok())
|
||||
.map(|c: cidr::Ipv4Inet| {
|
||||
if c.network_length() == 32 {
|
||||
cidr::Ipv4Inet::new(c.address(), 24).unwrap()
|
||||
@@ -505,28 +532,16 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
}
|
||||
|
||||
fn set_ipv4(&self, addr: Option<cidr::Ipv4Inet>) {
|
||||
self.config.lock().unwrap().ipv4 = if let Some(addr) = addr {
|
||||
Some(addr.to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.config.lock().unwrap().ipv4 = addr.map(|addr| addr.to_string());
|
||||
}
|
||||
|
||||
fn get_ipv6(&self) -> Option<cidr::Ipv6Inet> {
|
||||
let locked_config = self.config.lock().unwrap();
|
||||
locked_config
|
||||
.ipv6
|
||||
.as_ref()
|
||||
.map(|s| s.parse().ok())
|
||||
.flatten()
|
||||
locked_config.ipv6.as_ref().and_then(|s| s.parse().ok())
|
||||
}
|
||||
|
||||
fn set_ipv6(&self, addr: Option<cidr::Ipv6Inet>) {
|
||||
self.config.lock().unwrap().ipv6 = if let Some(addr) = addr {
|
||||
Some(addr.to_string())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
self.config.lock().unwrap().ipv6 = addr.map(|addr| addr.to_string());
|
||||
}
|
||||
|
||||
fn get_dhcp(&self) -> bool {
|
||||
@@ -600,7 +615,7 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
locked_config.instance_id = Some(id);
|
||||
id
|
||||
} else {
|
||||
locked_config.instance_id.as_ref().unwrap().clone()
|
||||
*locked_config.instance_id.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,7 +629,7 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
.unwrap()
|
||||
.network_identity
|
||||
.clone()
|
||||
.unwrap_or_else(NetworkIdentity::default)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn set_network_identity(&self, identity: NetworkIdentity) {
|
||||
|
||||
@@ -8,14 +8,14 @@ macro_rules! define_global_var {
|
||||
#[macro_export]
|
||||
macro_rules! use_global_var {
|
||||
($name:ident) => {
|
||||
crate::common::constants::$name.lock().unwrap().to_owned()
|
||||
$crate::common::constants::$name.lock().unwrap().to_owned()
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! set_global_var {
|
||||
($name:ident, $val:expr) => {
|
||||
*crate::common::constants::$name.lock().unwrap() = $val
|
||||
*$crate::common::constants::$name.lock().unwrap() = $val
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ impl<F: FnOnce()> Defer<F> {
|
||||
|
||||
impl<F: FnOnce()> Drop for Defer<F> {
|
||||
fn drop(&mut self) {
|
||||
self.func.take().map(|f| f());
|
||||
if let Some(f) = self.func.take() {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,19 +48,15 @@ pub static RESOLVER: Lazy<Arc<Resolver<GenericConnector<TokioRuntimeProvider>>>>
|
||||
|
||||
pub async fn resolve_txt_record(domain_name: &str) -> Result<String, Error> {
|
||||
let r = RESOLVER.clone();
|
||||
let response = r.txt_lookup(domain_name).await.with_context(|| {
|
||||
format!(
|
||||
"txt_lookup failed, domain_name: {}",
|
||||
domain_name.to_string()
|
||||
)
|
||||
})?;
|
||||
let response = r
|
||||
.txt_lookup(domain_name)
|
||||
.await
|
||||
.with_context(|| format!("txt_lookup failed, domain_name: {}", domain_name))?;
|
||||
|
||||
let txt_record = response.iter().next().with_context(|| {
|
||||
format!(
|
||||
"no txt record found, domain_name: {}",
|
||||
domain_name.to_string()
|
||||
)
|
||||
})?;
|
||||
let txt_record = response
|
||||
.iter()
|
||||
.next()
|
||||
.with_context(|| format!("no txt record found, domain_name: {}", domain_name))?;
|
||||
|
||||
let txt_data = String::from_utf8_lossy(&txt_record.txt_data()[0]);
|
||||
tracing::info!(?txt_data, ?domain_name, "get txt record");
|
||||
|
||||
@@ -104,7 +104,7 @@ impl std::fmt::Debug for GlobalCtx {
|
||||
pub type ArcGlobalCtx = std::sync::Arc<GlobalCtx>;
|
||||
|
||||
impl GlobalCtx {
|
||||
pub fn new(config_fs: impl ConfigLoader + 'static + Send + Sync) -> Self {
|
||||
pub fn new(config_fs: impl ConfigLoader + 'static) -> Self {
|
||||
let id = config_fs.get_id();
|
||||
let network = config_fs.get_network_identity();
|
||||
let net_ns = NetNS::new(config_fs.get_netns());
|
||||
@@ -118,9 +118,11 @@ impl GlobalCtx {
|
||||
let proxy_forward_by_system = config_fs.get_flags().proxy_forward_by_system;
|
||||
let no_tun = config_fs.get_flags().no_tun;
|
||||
|
||||
let mut feature_flags = PeerFeatureFlag::default();
|
||||
feature_flags.kcp_input = !config_fs.get_flags().disable_kcp_input;
|
||||
feature_flags.no_relay_kcp = config_fs.get_flags().disable_relay_kcp;
|
||||
let feature_flags = PeerFeatureFlag {
|
||||
kcp_input: !config_fs.get_flags().disable_kcp_input,
|
||||
no_relay_kcp: config_fs.get_flags().disable_relay_kcp,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
GlobalCtx {
|
||||
inst_name: config_fs.get_inst_name(),
|
||||
@@ -185,7 +187,7 @@ impl GlobalCtx {
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::anyhow!("network {} not in whitelist", network_name).into())
|
||||
Err(anyhow::anyhow!("network {} not in whitelist", network_name))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,8 +196,8 @@ impl GlobalCtx {
|
||||
return Some(ret);
|
||||
}
|
||||
let addr = self.config.get_ipv4();
|
||||
self.cached_ipv4.store(addr.clone());
|
||||
return addr;
|
||||
self.cached_ipv4.store(addr);
|
||||
addr
|
||||
}
|
||||
|
||||
pub fn set_ipv4(&self, addr: Option<cidr::Ipv4Inet>) {
|
||||
@@ -208,8 +210,8 @@ impl GlobalCtx {
|
||||
return Some(ret);
|
||||
}
|
||||
let addr = self.config.get_ipv6();
|
||||
self.cached_ipv6.store(addr.clone());
|
||||
return addr;
|
||||
self.cached_ipv6.store(addr);
|
||||
addr
|
||||
}
|
||||
|
||||
pub fn set_ipv6(&self, addr: Option<cidr::Ipv6Inet>) {
|
||||
@@ -376,18 +378,18 @@ pub mod tests {
|
||||
|
||||
let mut subscriber = global_ctx.subscribe();
|
||||
let peer_id = new_peer_id();
|
||||
global_ctx.issue_event(GlobalCtxEvent::PeerAdded(peer_id.clone()));
|
||||
global_ctx.issue_event(GlobalCtxEvent::PeerRemoved(peer_id.clone()));
|
||||
global_ctx.issue_event(GlobalCtxEvent::PeerAdded(peer_id));
|
||||
global_ctx.issue_event(GlobalCtxEvent::PeerRemoved(peer_id));
|
||||
global_ctx.issue_event(GlobalCtxEvent::PeerConnAdded(PeerConnInfo::default()));
|
||||
global_ctx.issue_event(GlobalCtxEvent::PeerConnRemoved(PeerConnInfo::default()));
|
||||
|
||||
assert_eq!(
|
||||
subscriber.recv().await.unwrap(),
|
||||
GlobalCtxEvent::PeerAdded(peer_id.clone())
|
||||
GlobalCtxEvent::PeerAdded(peer_id)
|
||||
);
|
||||
assert_eq!(
|
||||
subscriber.recv().await.unwrap(),
|
||||
GlobalCtxEvent::PeerRemoved(peer_id.clone())
|
||||
GlobalCtxEvent::PeerRemoved(peer_id)
|
||||
);
|
||||
assert_eq!(
|
||||
subscriber.recv().await.unwrap(),
|
||||
@@ -404,7 +406,7 @@ pub mod tests {
|
||||
) -> ArcGlobalCtx {
|
||||
let config_fs = TomlConfigLoader::default();
|
||||
config_fs.set_inst_name(format!("test_{}", config_fs.get_id()));
|
||||
config_fs.set_network_identity(network_identy.unwrap_or(NetworkIdentity::default()));
|
||||
config_fs.set_network_identity(network_identy.unwrap_or_default());
|
||||
|
||||
let ctx = Arc::new(GlobalCtx::new(config_fs));
|
||||
ctx.replace_stun_info_collector(Box::new(MockStunInfoCollector {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
mod darwin;
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
#[cfg(target_os = "linux")]
|
||||
mod netlink;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod win;
|
||||
@@ -141,7 +141,7 @@ pub struct DummyIfConfiger {}
|
||||
#[async_trait]
|
||||
impl IfConfiguerTrait for DummyIfConfiger {}
|
||||
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
#[cfg(target_os = "linux")]
|
||||
pub type IfConfiger = netlink::NetlinkIfConfiger;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
|
||||
|
||||
@@ -85,14 +85,14 @@ fn send_netlink_req_and_wait_one_resp<T: NetlinkDeserializable + NetlinkSerializ
|
||||
match ret.payload {
|
||||
NetlinkPayload::Error(e) => {
|
||||
if e.code == NonZero::new(0) {
|
||||
return Ok(());
|
||||
Ok(())
|
||||
} else {
|
||||
return Err(e.to_io().into());
|
||||
Err(e.to_io().into())
|
||||
}
|
||||
}
|
||||
p => {
|
||||
tracing::error!("Unexpected netlink response: {:?}", p);
|
||||
return Err(anyhow::anyhow!("Unexpected netlink response").into());
|
||||
Err(anyhow::anyhow!("Unexpected netlink response").into())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,8 +263,8 @@ impl NetlinkIfConfiger {
|
||||
|
||||
let (address, netmask) = match (address.family(), netmask.family()) {
|
||||
(Some(Inet), Some(Inet)) => (
|
||||
IpAddr::V4(address.as_sockaddr_in().unwrap().ip().into()),
|
||||
IpAddr::V4(netmask.as_sockaddr_in().unwrap().ip().into()),
|
||||
IpAddr::V4(address.as_sockaddr_in().unwrap().ip()),
|
||||
IpAddr::V4(netmask.as_sockaddr_in().unwrap().ip()),
|
||||
),
|
||||
(Some(Inet6), Some(Inet6)) => (
|
||||
IpAddr::V6(address.as_sockaddr_in6().unwrap().ip()),
|
||||
@@ -333,7 +333,7 @@ impl NetlinkIfConfiger {
|
||||
|
||||
let mut resp = Vec::<u8>::new();
|
||||
loop {
|
||||
if resp.len() == 0 {
|
||||
if resp.is_empty() {
|
||||
let (new_resp, _) = s.recv_from_full()?;
|
||||
resp = new_resp;
|
||||
}
|
||||
|
||||
@@ -727,7 +727,7 @@ impl InterfaceLuid {
|
||||
if family == (AF_INET6 as ADDRESS_FAMILY) {
|
||||
// ipv6 mtu must be at least 1280
|
||||
mtu = 1280.max(mtu);
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/54857292/setipinterfaceentry-returns-error-invalid-parameter
|
||||
row.SitePrefixLength = 0;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
pub mod luid;
|
||||
pub mod netsh;
|
||||
pub mod types;
|
||||
pub mod luid;
|
||||
@@ -115,4 +115,4 @@ pub fn add_dns_ipv6(if_index: u32, dnses: &[Ipv6Addr]) -> Result<(), String> {
|
||||
}
|
||||
let dnses_str: Vec<String> = dnses.iter().map(|addr| addr.to_string()).collect();
|
||||
add_dns(AF_INET6 as _, if_index, &dnses_str)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,4 +100,4 @@ pub fn u16_ptr_to_string(ptr: *const u16) -> String {
|
||||
let slice = unsafe { std::slice::from_raw_parts(ptr, len) };
|
||||
|
||||
String::from_utf16_lossy(slice)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,8 +140,8 @@ pub fn get_machine_id() -> uuid::Uuid {
|
||||
)))]
|
||||
let gen_mid = None;
|
||||
|
||||
if gen_mid.is_some() {
|
||||
return gen_mid.unwrap();
|
||||
if let Some(mid) = gen_mid {
|
||||
return mid;
|
||||
}
|
||||
|
||||
let gen_mid = uuid::Uuid::new_v4();
|
||||
|
||||
@@ -34,13 +34,12 @@ impl NetNSGuard {
|
||||
return;
|
||||
}
|
||||
|
||||
let ns_path: String;
|
||||
let name = name.unwrap();
|
||||
if name == ROOT_NETNS_NAME {
|
||||
ns_path = "/proc/1/ns/net".to_string();
|
||||
let ns_path: String = if name == ROOT_NETNS_NAME {
|
||||
"/proc/1/ns/net".to_string()
|
||||
} else {
|
||||
ns_path = format!("/var/run/netns/{}", name);
|
||||
}
|
||||
format!("/var/run/netns/{}", name)
|
||||
};
|
||||
|
||||
let ns = std::fs::File::open(ns_path).unwrap();
|
||||
tracing::info!(
|
||||
|
||||
@@ -211,7 +211,7 @@ impl IPCollector {
|
||||
cached_ip_list.read().await.public_ipv6
|
||||
);
|
||||
|
||||
let sleep_sec = if !cached_ip_list.read().await.public_ipv4.is_none() {
|
||||
let sleep_sec = if cached_ip_list.read().await.public_ipv4.is_some() {
|
||||
CACHED_IP_LIST_TIMEOUT_SEC
|
||||
} else {
|
||||
3
|
||||
@@ -252,14 +252,11 @@ impl IPCollector {
|
||||
for iface in ifaces {
|
||||
for ip in iface.ips {
|
||||
let ip: std::net::IpAddr = ip.ip();
|
||||
match ip {
|
||||
std::net::IpAddr::V4(v4) => {
|
||||
if ip.is_loopback() || ip.is_multicast() {
|
||||
continue;
|
||||
}
|
||||
ret.interface_ipv4s.push(v4.into());
|
||||
if let std::net::IpAddr::V4(v4) = ip {
|
||||
if ip.is_loopback() || ip.is_multicast() {
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
ret.interface_ipv4s.push(v4.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,14 +266,11 @@ impl IPCollector {
|
||||
for iface in ifaces {
|
||||
for ip in iface.ips {
|
||||
let ip: std::net::IpAddr = ip.ip();
|
||||
match ip {
|
||||
std::net::IpAddr::V6(v6) => {
|
||||
if v6.is_multicast() || v6.is_loopback() || v6.is_unicast_link_local() {
|
||||
continue;
|
||||
}
|
||||
ret.interface_ipv6s.push(v6.into());
|
||||
if let std::net::IpAddr::V6(v6) = ip {
|
||||
if v6.is_multicast() || v6.is_loopback() || v6.is_unicast_link_local() {
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
ret.interface_ipv6s.push(v6.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,6 +277,12 @@ pub struct UnsafeCounter {
|
||||
value: UnsafeCell<u64>,
|
||||
}
|
||||
|
||||
impl Default for UnsafeCounter {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl UnsafeCounter {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -396,14 +402,15 @@ impl MetricKey {
|
||||
fn new(name: MetricName, labels: LabelSet) -> Self {
|
||||
Self { name, labels }
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a string representation for this metric key
|
||||
fn to_string(&self) -> String {
|
||||
impl fmt::Display for MetricKey {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let label_str = self.labels.to_key();
|
||||
if label_str.is_empty() {
|
||||
self.name.to_string()
|
||||
f.write_str(self.name.to_string().as_str())
|
||||
} else {
|
||||
format!("{}[{}]", self.name, label_str)
|
||||
f.write_str(format!("{}[{}]", self.name, label_str).as_str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-28
@@ -282,9 +282,7 @@ impl StunClient {
|
||||
.with_context(|| "encode stun message")?;
|
||||
tids.push(tid);
|
||||
tracing::trace!(?message, ?msg, tid, "send stun request");
|
||||
self.socket
|
||||
.send_to(msg.as_slice().into(), &stun_host)
|
||||
.await?;
|
||||
self.socket.send_to(msg.as_slice(), &stun_host).await?;
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
@@ -372,7 +370,7 @@ impl StunClientBuilder {
|
||||
|
||||
pub async fn stop(&mut self) {
|
||||
self.task_set.abort_all();
|
||||
while let Some(_) = self.task_set.join_next().await {}
|
||||
while self.task_set.join_next().await.is_some() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +415,7 @@ impl UdpNatTypeDetectResult {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
false
|
||||
}
|
||||
|
||||
fn is_pat(&self) -> bool {
|
||||
@@ -457,16 +455,16 @@ impl UdpNatTypeDetectResult {
|
||||
if self.is_cone() {
|
||||
if self.has_ip_changed_resp() {
|
||||
if self.is_open_internet() {
|
||||
return NatType::OpenInternet;
|
||||
NatType::OpenInternet
|
||||
} else if self.is_pat() {
|
||||
return NatType::NoPat;
|
||||
NatType::NoPat
|
||||
} else {
|
||||
return NatType::FullCone;
|
||||
NatType::FullCone
|
||||
}
|
||||
} else if self.has_port_changed_resp() {
|
||||
return NatType::Restricted;
|
||||
NatType::Restricted
|
||||
} else {
|
||||
return NatType::PortRestricted;
|
||||
NatType::PortRestricted
|
||||
}
|
||||
} else if !self.stun_resps.is_empty() {
|
||||
if self.public_ips().len() != 1
|
||||
@@ -480,7 +478,7 @@ impl UdpNatTypeDetectResult {
|
||||
.mapped_socket_addr
|
||||
.is_none()
|
||||
{
|
||||
return NatType::Symmetric;
|
||||
NatType::Symmetric
|
||||
} else {
|
||||
let extra_bind_test = self.extra_bind_test.as_ref().unwrap();
|
||||
let extra_port = extra_bind_test.mapped_socket_addr.unwrap().port();
|
||||
@@ -488,15 +486,15 @@ impl UdpNatTypeDetectResult {
|
||||
let max_port_diff = extra_port.saturating_sub(self.max_port());
|
||||
let min_port_diff = self.min_port().saturating_sub(extra_port);
|
||||
if max_port_diff != 0 && max_port_diff < 100 {
|
||||
return NatType::SymmetricEasyInc;
|
||||
NatType::SymmetricEasyInc
|
||||
} else if min_port_diff != 0 && min_port_diff < 100 {
|
||||
return NatType::SymmetricEasyDec;
|
||||
NatType::SymmetricEasyDec
|
||||
} else {
|
||||
return NatType::Symmetric;
|
||||
NatType::Symmetric
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return NatType::Unknown;
|
||||
NatType::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,7 +677,7 @@ impl StunInfoCollectorTrait for StunInfoCollector {
|
||||
.unwrap()
|
||||
.clone()
|
||||
.map(|x| x.collect_available_stun_server())
|
||||
.unwrap_or(vec![]);
|
||||
.unwrap_or_default();
|
||||
|
||||
if stun_servers.is_empty() {
|
||||
let mut host_resolver =
|
||||
@@ -740,7 +738,7 @@ impl StunInfoCollector {
|
||||
pub fn get_default_servers() -> Vec<String> {
|
||||
// NOTICE: we may need to choose stun stun server based on geo location
|
||||
// stun server cross nation may return a external ip address with high latency and loss rate
|
||||
vec![
|
||||
[
|
||||
"txt:stun.easytier.cn",
|
||||
"stun.miwifi.com",
|
||||
"stun.chat.bilibili.com",
|
||||
@@ -752,16 +750,16 @@ impl StunInfoCollector {
|
||||
}
|
||||
|
||||
pub fn get_default_servers_v6() -> Vec<String> {
|
||||
vec!["txt:stun-v6.easytier.cn"]
|
||||
["txt:stun-v6.easytier.cn"]
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
async fn get_public_ipv6(servers: &Vec<String>) -> Option<Ipv6Addr> {
|
||||
async fn get_public_ipv6(servers: &[String]) -> Option<Ipv6Addr> {
|
||||
let mut ips = HostResolverIter::new(servers.to_vec(), 10, true);
|
||||
while let Some(ip) = ips.next().await {
|
||||
let Ok(udp_socket) = UdpSocket::bind(format!("[::]:0")).await else {
|
||||
let Ok(udp_socket) = UdpSocket::bind("[::]:0".to_string()).await else {
|
||||
break;
|
||||
};
|
||||
let udp = Arc::new(udp_socket);
|
||||
@@ -770,11 +768,8 @@ impl StunInfoCollector {
|
||||
.bind_request(false, false)
|
||||
.await;
|
||||
tracing::debug!(?ret, "finish ipv6 udp nat type detect");
|
||||
match ret.map(|x| x.mapped_socket_addr.map(|x| x.ip())) {
|
||||
Ok(Some(IpAddr::V6(v6))) => {
|
||||
return Some(v6);
|
||||
}
|
||||
_ => {}
|
||||
if let Ok(Some(IpAddr::V6(v6))) = ret.map(|x| x.mapped_socket_addr.map(|x| x.ip())) {
|
||||
return Some(v6);
|
||||
}
|
||||
}
|
||||
None
|
||||
@@ -854,9 +849,9 @@ impl StunInfoCollector {
|
||||
self.tasks.lock().unwrap().spawn(async move {
|
||||
loop {
|
||||
let servers = stun_servers.read().unwrap().clone();
|
||||
Self::get_public_ipv6(&servers)
|
||||
.await
|
||||
.map(|x| stored_ipv6.store(Some(x)));
|
||||
if let Some(x) = Self::get_public_ipv6(&servers).await {
|
||||
stored_ipv6.store(Some(x))
|
||||
}
|
||||
|
||||
let sleep_sec = if stored_ipv6.load().is_none() {
|
||||
60
|
||||
|
||||
@@ -34,7 +34,7 @@ impl From<LimiterConfig> for BucketConfig {
|
||||
.unwrap_or(Duration::from_millis(10));
|
||||
BucketConfig {
|
||||
capacity: burst_rate * fill_rate,
|
||||
fill_rate: fill_rate,
|
||||
fill_rate,
|
||||
refill_interval,
|
||||
}
|
||||
}
|
||||
@@ -162,6 +162,12 @@ pub struct TokenBucketManager {
|
||||
retain_task: ScopedTask<()>,
|
||||
}
|
||||
|
||||
impl Default for TokenBucketManager {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl TokenBucketManager {
|
||||
/// Creates a new TokenBucketManager
|
||||
pub fn new() -> Self {
|
||||
@@ -318,7 +324,7 @@ mod tests {
|
||||
// Should have accumulated about 100 tokens (10,000 tokens/s * 0.001s)
|
||||
let tokens = bucket.available_tokens.load(Ordering::Relaxed);
|
||||
assert!(
|
||||
tokens >= 100 && tokens <= 200,
|
||||
(100..=200).contains(&tokens),
|
||||
"Unexpected token count: {}",
|
||||
tokens
|
||||
);
|
||||
@@ -355,8 +361,7 @@ mod tests {
|
||||
.list_foreign_networks()
|
||||
.await
|
||||
.foreign_networks
|
||||
.len()
|
||||
== 0
|
||||
.is_empty()
|
||||
},
|
||||
Duration::from_secs(5),
|
||||
)
|
||||
@@ -370,8 +375,7 @@ mod tests {
|
||||
.get_global_ctx()
|
||||
.token_bucket_manager()
|
||||
.buckets
|
||||
.len()
|
||||
== 0
|
||||
.is_empty()
|
||||
},
|
||||
Duration::from_secs(10),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user