mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 10:14:35 +00:00
chore: update Rust to 2024 edition (#2066)
This commit is contained in:
@@ -507,7 +507,7 @@ impl AclProcessor {
|
||||
matched_rule: Some(RuleId::Default),
|
||||
should_log: false,
|
||||
log_context: Some(AclLogContext::UnsupportedChainType),
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -679,28 +679,28 @@ impl AclProcessor {
|
||||
}
|
||||
|
||||
// Source port check
|
||||
if let Some(src_port) = packet_info.src_port {
|
||||
if !rule.src_port_ranges.is_empty() {
|
||||
let matches = rule
|
||||
.src_port_ranges
|
||||
.iter()
|
||||
.any(|(start, end)| src_port >= *start && src_port <= *end);
|
||||
if !matches {
|
||||
return false;
|
||||
}
|
||||
if let Some(src_port) = packet_info.src_port
|
||||
&& !rule.src_port_ranges.is_empty()
|
||||
{
|
||||
let matches = rule
|
||||
.src_port_ranges
|
||||
.iter()
|
||||
.any(|(start, end)| src_port >= *start && src_port <= *end);
|
||||
if !matches {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Destination port check
|
||||
if let Some(dst_port) = packet_info.dst_port {
|
||||
if !rule.dst_port_ranges.is_empty() {
|
||||
let matches = rule
|
||||
.dst_port_ranges
|
||||
.iter()
|
||||
.any(|(start, end)| dst_port >= *start && dst_port <= *end);
|
||||
if !matches {
|
||||
return false;
|
||||
}
|
||||
if let Some(dst_port) = packet_info.dst_port
|
||||
&& !rule.dst_port_ranges.is_empty()
|
||||
{
|
||||
let matches = rule
|
||||
.dst_port_ranges
|
||||
.iter()
|
||||
.any(|(start, end)| dst_port >= *start && dst_port <= *end);
|
||||
if !matches {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use zstd::bulk;
|
||||
|
||||
use zerocopy::{AsBytes as _, FromBytes as _};
|
||||
|
||||
use crate::tunnel::packet_def::{CompressorAlgo, CompressorTail, ZCPacket, COMPRESSOR_TAIL_SIZE};
|
||||
use crate::tunnel::packet_def::{COMPRESSOR_TAIL_SIZE, CompressorAlgo, CompressorTail, ZCPacket};
|
||||
|
||||
type Error = anyhow::Error;
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ use std::{
|
||||
};
|
||||
|
||||
use anyhow::Context;
|
||||
use base64::{prelude::BASE64_STANDARD, Engine as _};
|
||||
use base64::{Engine as _, prelude::BASE64_STANDARD};
|
||||
use cfg_if::cfg_if;
|
||||
use clap::builder::PossibleValue;
|
||||
use clap::ValueEnum;
|
||||
use clap::builder::PossibleValue;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumString, VariantArray};
|
||||
use tokio::io::AsyncReadExt as _;
|
||||
@@ -621,14 +621,14 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
if locked_config.proxy_network.is_none() {
|
||||
locked_config.proxy_network = Some(vec![]);
|
||||
}
|
||||
if let Some(mapped_cidr) = mapped_cidr.as_ref() {
|
||||
if cidr.network_length() != mapped_cidr.network_length() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Mapped CIDR must have the same network length as the original CIDR: {} != {}",
|
||||
cidr.network_length(),
|
||||
mapped_cidr.network_length()
|
||||
));
|
||||
}
|
||||
if let Some(mapped_cidr) = mapped_cidr.as_ref()
|
||||
&& cidr.network_length() != mapped_cidr.network_length()
|
||||
{
|
||||
return Err(anyhow::anyhow!(
|
||||
"Mapped CIDR must have the same network length as the original CIDR: {} != {}",
|
||||
cidr.network_length(),
|
||||
mapped_cidr.network_length()
|
||||
));
|
||||
}
|
||||
// insert if no duplicate
|
||||
if !locked_config
|
||||
@@ -881,10 +881,10 @@ impl ConfigLoader for TomlConfigLoader {
|
||||
|
||||
let mut flag_map: serde_json::Map<String, serde_json::Value> = Default::default();
|
||||
for (key, value) in default_flags_hashmap {
|
||||
if let Some(v) = cur_flags_hashmap.get(&key) {
|
||||
if *v != value {
|
||||
flag_map.insert(key, v.clone());
|
||||
}
|
||||
if let Some(v) = cur_flags_hashmap.get(&key)
|
||||
&& *v != value
|
||||
{
|
||||
flag_map.insert(key, v.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1089,6 +1089,7 @@ pub async fn load_config_from_file(
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::tests::{remove_env_var, set_env_var};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use tempfile::NamedTempFile;
|
||||
@@ -1212,8 +1213,8 @@ proto = "tcp"
|
||||
#[tokio::test]
|
||||
async fn test_env_var_expansion_and_readonly_flag() {
|
||||
// 设置测试环境变量
|
||||
std::env::set_var("TEST_SECRET", "my-test-secret-123");
|
||||
std::env::set_var("TEST_NETWORK", "test-network");
|
||||
set_env_var("TEST_SECRET", "my-test-secret-123");
|
||||
set_env_var("TEST_NETWORK", "test-network");
|
||||
|
||||
// 创建临时配置文件,包含环境变量占位符
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
@@ -1253,8 +1254,8 @@ network_secret = "${TEST_SECRET}"
|
||||
);
|
||||
|
||||
// 清理环境变量
|
||||
std::env::remove_var("TEST_SECRET");
|
||||
std::env::remove_var("TEST_NETWORK");
|
||||
remove_env_var("TEST_SECRET");
|
||||
remove_env_var("TEST_NETWORK");
|
||||
}
|
||||
|
||||
/// RPC API 安全测试(只读配置保护)
|
||||
@@ -1267,7 +1268,7 @@ network_secret = "${TEST_SECRET}"
|
||||
/// `easytier/src/rpc_service/instance_manage.rs` 中实现
|
||||
#[tokio::test]
|
||||
async fn test_readonly_config_api_protection() {
|
||||
std::env::set_var("API_TEST_SECRET", "secret-value");
|
||||
set_env_var("API_TEST_SECRET", "secret-value");
|
||||
|
||||
// 创建包含环境变量的配置
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
@@ -1298,7 +1299,7 @@ network_secret = "${API_TEST_SECRET}"
|
||||
"Permission flag should be set correctly"
|
||||
);
|
||||
|
||||
std::env::remove_var("API_TEST_SECRET");
|
||||
remove_env_var("API_TEST_SECRET");
|
||||
}
|
||||
|
||||
/// CLI 参数测试(--disable-env-parsing 开关)
|
||||
@@ -1308,7 +1309,7 @@ network_secret = "${API_TEST_SECRET}"
|
||||
/// - 配置不会被标记为只读
|
||||
#[tokio::test]
|
||||
async fn test_disable_env_parsing_flag() {
|
||||
std::env::set_var("DISABLED_TEST_VAR", "should-not-expand");
|
||||
set_env_var("DISABLED_TEST_VAR", "should-not-expand");
|
||||
|
||||
// 创建包含环境变量占位符的配置
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
@@ -1346,7 +1347,7 @@ network_secret = "${DISABLED_TEST_VAR}"
|
||||
"Config should be NO_DELETE due to no config_dir, not env vars"
|
||||
);
|
||||
|
||||
std::env::remove_var("DISABLED_TEST_VAR");
|
||||
remove_env_var("DISABLED_TEST_VAR");
|
||||
}
|
||||
|
||||
/// 多实例隔离测试
|
||||
@@ -1357,8 +1358,8 @@ network_secret = "${DISABLED_TEST_VAR}"
|
||||
#[tokio::test]
|
||||
async fn test_multiple_instances_with_different_env_vars() {
|
||||
// 实例1:使用第一组环境变量
|
||||
std::env::set_var("INSTANCE_SECRET", "instance1-secret");
|
||||
std::env::set_var("INSTANCE_NAME", "instance-one");
|
||||
set_env_var("INSTANCE_SECRET", "instance1-secret");
|
||||
set_env_var("INSTANCE_NAME", "instance-one");
|
||||
|
||||
let mut temp_file1 = NamedTempFile::new().unwrap();
|
||||
let config_content = r#"
|
||||
@@ -1388,8 +1389,8 @@ network_secret = "${INSTANCE_SECRET}"
|
||||
);
|
||||
|
||||
// 实例2:修改环境变量后加载同一模板
|
||||
std::env::set_var("INSTANCE_SECRET", "instance2-secret");
|
||||
std::env::set_var("INSTANCE_NAME", "instance-two");
|
||||
set_env_var("INSTANCE_SECRET", "instance2-secret");
|
||||
set_env_var("INSTANCE_NAME", "instance-two");
|
||||
|
||||
let mut temp_file2 = NamedTempFile::new().unwrap();
|
||||
temp_file2.write_all(config_content.as_bytes()).unwrap();
|
||||
@@ -1419,8 +1420,8 @@ network_secret = "${INSTANCE_SECRET}"
|
||||
);
|
||||
|
||||
// 清理
|
||||
std::env::remove_var("INSTANCE_SECRET");
|
||||
std::env::remove_var("INSTANCE_NAME");
|
||||
remove_env_var("INSTANCE_SECRET");
|
||||
remove_env_var("INSTANCE_NAME");
|
||||
}
|
||||
|
||||
/// 实际配置字段测试(network_secret、peer.uri 等)
|
||||
@@ -1433,11 +1434,11 @@ network_secret = "${INSTANCE_SECRET}"
|
||||
#[tokio::test]
|
||||
async fn test_real_config_fields_expansion() {
|
||||
// 设置各种实际场景的环境变量
|
||||
std::env::set_var("ET_SECRET", "production-secret-key");
|
||||
std::env::set_var("PEER_HOST", "peer.example.com");
|
||||
std::env::set_var("PEER_PORT", "11011");
|
||||
std::env::set_var("LISTEN_PORT", "11010");
|
||||
std::env::set_var("NETWORK_NAME", "prod-network");
|
||||
set_env_var("ET_SECRET", "production-secret-key");
|
||||
set_env_var("PEER_HOST", "peer.example.com");
|
||||
set_env_var("PEER_PORT", "11011");
|
||||
set_env_var("LISTEN_PORT", "11010");
|
||||
set_env_var("NETWORK_NAME", "prod-network");
|
||||
|
||||
// 创建包含多个实际字段的完整配置
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
@@ -1485,11 +1486,11 @@ uri = "tcp://${PEER_HOST}:${PEER_PORT}"
|
||||
assert!(control.is_no_delete());
|
||||
|
||||
// 清理环境变量
|
||||
std::env::remove_var("ET_SECRET");
|
||||
std::env::remove_var("PEER_HOST");
|
||||
std::env::remove_var("PEER_PORT");
|
||||
std::env::remove_var("LISTEN_PORT");
|
||||
std::env::remove_var("NETWORK_NAME");
|
||||
remove_env_var("ET_SECRET");
|
||||
remove_env_var("PEER_HOST");
|
||||
remove_env_var("PEER_PORT");
|
||||
remove_env_var("LISTEN_PORT");
|
||||
remove_env_var("NETWORK_NAME");
|
||||
}
|
||||
|
||||
/// 带默认值的环境变量
|
||||
@@ -1499,8 +1500,8 @@ uri = "tcp://${PEER_HOST}:${PEER_PORT}"
|
||||
#[tokio::test]
|
||||
async fn test_env_var_with_default_value() {
|
||||
// 确保变量未定义
|
||||
std::env::remove_var("UNDEFINED_PORT");
|
||||
std::env::remove_var("UNDEFINED_SECRET");
|
||||
remove_env_var("UNDEFINED_PORT");
|
||||
remove_env_var("UNDEFINED_SECRET");
|
||||
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
let config_content = r#"
|
||||
@@ -1541,7 +1542,7 @@ network_secret = "${UNDEFINED_SECRET:-default-secret}"
|
||||
/// - 未定义的环境变量保持原样(shellexpand 的默认行为)
|
||||
#[tokio::test]
|
||||
async fn test_undefined_env_var_without_default() {
|
||||
std::env::remove_var("COMPLETELY_UNDEFINED");
|
||||
remove_env_var("COMPLETELY_UNDEFINED");
|
||||
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
let config_content = r#"
|
||||
@@ -1571,6 +1572,8 @@ network_secret = "${COMPLETELY_UNDEFINED}"
|
||||
|
||||
// 注意:由于没有实际替换发生,控制标记不应因环境变量而设置
|
||||
// 但会因为其他原因(如没有 config_dir)被标记为 NO_DELETE
|
||||
// 这里我们主要验证 NO_DELETE 标记的逻辑
|
||||
// 由于没有 config_dir,文件会被标记为 NO_DELETE,但不是因为环境变量
|
||||
assert!(control.is_no_delete());
|
||||
}
|
||||
|
||||
@@ -1582,9 +1585,9 @@ network_secret = "${COMPLETELY_UNDEFINED}"
|
||||
#[tokio::test]
|
||||
async fn test_boolean_type_env_vars() {
|
||||
// 设置布尔类型的环境变量
|
||||
std::env::set_var("ENABLE_DHCP", "true");
|
||||
std::env::set_var("ENABLE_ENCRYPTION", "false");
|
||||
std::env::set_var("ENABLE_IPV6", "true");
|
||||
set_env_var("ENABLE_DHCP", "true");
|
||||
set_env_var("ENABLE_ENCRYPTION", "false");
|
||||
set_env_var("ENABLE_IPV6", "true");
|
||||
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
let config_content = r#"
|
||||
@@ -1622,9 +1625,9 @@ enable_ipv6 = ${ENABLE_IPV6}
|
||||
assert!(control.is_no_delete());
|
||||
|
||||
// 清理
|
||||
std::env::remove_var("ENABLE_DHCP");
|
||||
std::env::remove_var("ENABLE_ENCRYPTION");
|
||||
std::env::remove_var("ENABLE_IPV6");
|
||||
remove_env_var("ENABLE_DHCP");
|
||||
remove_env_var("ENABLE_ENCRYPTION");
|
||||
remove_env_var("ENABLE_IPV6");
|
||||
}
|
||||
|
||||
/// 数字类型环境变量
|
||||
@@ -1635,8 +1638,8 @@ enable_ipv6 = ${ENABLE_IPV6}
|
||||
#[tokio::test]
|
||||
async fn test_numeric_type_env_vars() {
|
||||
// 设置数字类型的环境变量
|
||||
std::env::set_var("MTU_VALUE", "1400");
|
||||
std::env::set_var("THREAD_COUNT", "4");
|
||||
set_env_var("MTU_VALUE", "1400");
|
||||
set_env_var("THREAD_COUNT", "4");
|
||||
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
let config_content = r#"
|
||||
@@ -1671,8 +1674,8 @@ multi_thread_count = ${THREAD_COUNT}
|
||||
assert!(control.is_no_delete());
|
||||
|
||||
// 清理
|
||||
std::env::remove_var("MTU_VALUE");
|
||||
std::env::remove_var("THREAD_COUNT");
|
||||
remove_env_var("MTU_VALUE");
|
||||
remove_env_var("THREAD_COUNT");
|
||||
}
|
||||
|
||||
/// 混合类型环境变量
|
||||
@@ -1684,12 +1687,12 @@ multi_thread_count = ${THREAD_COUNT}
|
||||
#[tokio::test]
|
||||
async fn test_mixed_type_env_vars() {
|
||||
// 设置不同类型的环境变量
|
||||
std::env::set_var("MIXED_SECRET", "mixed-secret-key");
|
||||
std::env::set_var("MIXED_NETWORK", "production");
|
||||
std::env::set_var("MIXED_DHCP", "true");
|
||||
std::env::set_var("MIXED_MTU", "1500");
|
||||
std::env::set_var("MIXED_ENCRYPTION", "false");
|
||||
std::env::set_var("MIXED_LISTEN_PORT", "12345");
|
||||
set_env_var("MIXED_SECRET", "mixed-secret-key");
|
||||
set_env_var("MIXED_NETWORK", "production");
|
||||
set_env_var("MIXED_DHCP", "true");
|
||||
set_env_var("MIXED_MTU", "1500");
|
||||
set_env_var("MIXED_ENCRYPTION", "false");
|
||||
set_env_var("MIXED_LISTEN_PORT", "12345");
|
||||
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
let config_content = r#"
|
||||
@@ -1741,11 +1744,11 @@ enable_encryption = ${MIXED_ENCRYPTION}
|
||||
assert!(control.is_no_delete());
|
||||
|
||||
// 清理
|
||||
std::env::remove_var("MIXED_SECRET");
|
||||
std::env::remove_var("MIXED_NETWORK");
|
||||
std::env::remove_var("MIXED_DHCP");
|
||||
std::env::remove_var("MIXED_MTU");
|
||||
std::env::remove_var("MIXED_ENCRYPTION");
|
||||
std::env::remove_var("MIXED_LISTEN_PORT");
|
||||
remove_env_var("MIXED_SECRET");
|
||||
remove_env_var("MIXED_NETWORK");
|
||||
remove_env_var("MIXED_DHCP");
|
||||
remove_env_var("MIXED_MTU");
|
||||
remove_env_var("MIXED_ENCRYPTION");
|
||||
remove_env_var("MIXED_LISTEN_PORT");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
use anyhow::Context;
|
||||
use hickory_proto::runtime::TokioRuntimeProvider;
|
||||
|
||||
@@ -42,10 +42,11 @@ pub fn expand_env_vars(text: &str) -> (String, bool) {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::tests::{remove_env_var, set_env_var};
|
||||
|
||||
#[test]
|
||||
fn test_expand_standard_syntax() {
|
||||
std::env::set_var("TEST_VAR_STANDARD", "test_value");
|
||||
set_env_var("TEST_VAR_STANDARD", "test_value");
|
||||
let (result, changed) = expand_env_vars("secret=${TEST_VAR_STANDARD}");
|
||||
assert_eq!(result, "secret=test_value");
|
||||
assert!(changed);
|
||||
@@ -53,7 +54,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_expand_short_syntax() {
|
||||
std::env::set_var("TEST_VAR_SHORT", "short_value");
|
||||
set_env_var("TEST_VAR_SHORT", "short_value");
|
||||
let (result, changed) = expand_env_vars("key=$TEST_VAR_SHORT");
|
||||
assert_eq!(result, "key=short_value");
|
||||
assert!(changed);
|
||||
@@ -62,7 +63,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_expand_with_default() {
|
||||
// 确保变量未定义
|
||||
std::env::remove_var("UNDEFINED_VAR_WITH_DEFAULT");
|
||||
remove_env_var("UNDEFINED_VAR_WITH_DEFAULT");
|
||||
let (result, changed) = expand_env_vars("port=${UNDEFINED_VAR_WITH_DEFAULT:-8080}");
|
||||
assert_eq!(result, "port=8080");
|
||||
assert!(changed);
|
||||
@@ -84,8 +85,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_multiple_vars() {
|
||||
std::env::set_var("VAR1", "value1");
|
||||
std::env::set_var("VAR2", "value2");
|
||||
set_env_var("VAR1", "value1");
|
||||
set_env_var("VAR2", "value2");
|
||||
let (result, changed) = expand_env_vars("${VAR1} and ${VAR2}");
|
||||
assert_eq!(result, "value1 and value2");
|
||||
assert!(changed);
|
||||
@@ -94,7 +95,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_undefined_var_without_default() {
|
||||
// 确保变量未定义
|
||||
std::env::remove_var("COMPLETELY_UNDEFINED_VAR");
|
||||
remove_env_var("COMPLETELY_UNDEFINED_VAR");
|
||||
let (result, changed) = expand_env_vars("value=${COMPLETELY_UNDEFINED_VAR}");
|
||||
// shellexpand::env 对未定义的变量会保持原样
|
||||
assert_eq!(result, "value=${COMPLETELY_UNDEFINED_VAR}");
|
||||
@@ -103,8 +104,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_complex_toml_config() {
|
||||
std::env::set_var("ET_SECRET", "my-secret-key");
|
||||
std::env::set_var("ET_PORT", "11010");
|
||||
set_env_var("ET_SECRET", "my-secret-key");
|
||||
set_env_var("ET_PORT", "11010");
|
||||
|
||||
let config = r#"
|
||||
[network_identity]
|
||||
@@ -123,7 +124,7 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_escape_syntax_double_dollar() {
|
||||
std::env::set_var("ESCAPED_VAR", "should_not_expand");
|
||||
set_env_var("ESCAPED_VAR", "should_not_expand");
|
||||
// shellexpand 使用 $$ 作为转义序列,表示字面量的单个 $
|
||||
// $$ 会被转义为单个 $,不会触发变量扩展
|
||||
let (result, changed) = expand_env_vars("value=$${ESCAPED_VAR}");
|
||||
@@ -133,7 +134,7 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_escape_syntax_backslash() {
|
||||
std::env::set_var("ESCAPED_VAR", "should_not_expand");
|
||||
set_env_var("ESCAPED_VAR", "should_not_expand");
|
||||
// shellexpand 中反斜杠转义的行为:\$ 会展开为 \<变量值>
|
||||
// 这不是推荐的转义方式,此测试仅为记录实际行为
|
||||
let (result, changed) = expand_env_vars(r"value=\${ESCAPED_VAR}");
|
||||
@@ -143,7 +144,7 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_multiple_dollar_signs() {
|
||||
std::env::set_var("TEST_VAR", "value");
|
||||
set_env_var("TEST_VAR", "value");
|
||||
// 测试多个连续的 $ 符号
|
||||
let (result1, changed1) = expand_env_vars("$$");
|
||||
assert_eq!(result1, "$");
|
||||
@@ -161,7 +162,7 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_empty_var_value() {
|
||||
std::env::set_var("EMPTY_VAR", "");
|
||||
set_env_var("EMPTY_VAR", "");
|
||||
let (result, changed) = expand_env_vars("value=${EMPTY_VAR}");
|
||||
// 变量存在但值为空
|
||||
assert_eq!(result, "value=");
|
||||
@@ -170,7 +171,7 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_default_with_special_chars() {
|
||||
std::env::remove_var("UNDEFINED_SPECIAL");
|
||||
remove_env_var("UNDEFINED_SPECIAL");
|
||||
// 测试默认值包含冒号、等号、空格等特殊字符
|
||||
let (result, changed) = expand_env_vars("url=${UNDEFINED_SPECIAL:-http://localhost:8080}");
|
||||
assert_eq!(result, "url=http://localhost:8080");
|
||||
@@ -187,9 +188,9 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_var_name_with_numbers_underscores() {
|
||||
std::env::set_var("VAR_123", "num_value");
|
||||
std::env::set_var("_VAR", "underscore_prefix");
|
||||
std::env::set_var("VAR_", "underscore_suffix");
|
||||
set_env_var("VAR_123", "num_value");
|
||||
set_env_var("_VAR", "underscore_prefix");
|
||||
set_env_var("VAR_", "underscore_suffix");
|
||||
|
||||
let (result1, changed1) = expand_env_vars("${VAR_123}");
|
||||
assert_eq!(result1, "num_value");
|
||||
@@ -214,7 +215,7 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
// 注意:未闭合的 ${VAR 实际上 shellexpand 会当作普通文本处理
|
||||
// 它会尝试查找名为 "VAR" 的环境变量(到字符串末尾)
|
||||
std::env::remove_var("VAR");
|
||||
remove_env_var("VAR");
|
||||
let (result2, _changed2) = expand_env_vars("incomplete ${VAR");
|
||||
// 如果 VAR 未定义,shellexpand 会返回错误或保持原样
|
||||
assert_eq!(result2, "incomplete ${VAR");
|
||||
@@ -224,8 +225,8 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_mixed_defined_undefined_vars() {
|
||||
std::env::set_var("DEFINED_VAR", "defined");
|
||||
std::env::remove_var("UNDEFINED_VAR");
|
||||
set_env_var("DEFINED_VAR", "defined");
|
||||
remove_env_var("UNDEFINED_VAR");
|
||||
|
||||
// 混合已定义和未定义的变量
|
||||
// shellexpand::env 在遇到未定义变量时会返回错误(默认行为)
|
||||
@@ -237,7 +238,7 @@ uri = "tcp://127.0.0.1:${ET_PORT}"
|
||||
|
||||
#[test]
|
||||
fn test_nested_braces() {
|
||||
std::env::set_var("OUTER", "outer_value");
|
||||
set_env_var("OUTER", "outer_value");
|
||||
// 嵌套的大括号是无效语法,shellexpand::env 会返回错误
|
||||
let (result, changed) = expand_env_vars("${OUTER} and ${{INNER}}");
|
||||
// 由于语法错误,整个字符串保持不变
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
collections::{hash_map::DefaultHasher, HashMap},
|
||||
collections::{HashMap, hash_map::DefaultHasher},
|
||||
hash::Hasher,
|
||||
net::{IpAddr, SocketAddr},
|
||||
sync::{Arc, Mutex},
|
||||
@@ -10,11 +10,11 @@ use arc_swap::ArcSwap;
|
||||
use dashmap::DashMap;
|
||||
|
||||
use super::{
|
||||
PeerId,
|
||||
config::{ConfigLoader, Flags},
|
||||
netns::NetNS,
|
||||
network::IPCollector,
|
||||
stun::{StunInfoCollector, StunInfoCollectorTrait},
|
||||
PeerId,
|
||||
};
|
||||
use crate::{
|
||||
common::{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use super::{cidr_to_subnet_mask, run_shell_cmd, Error, IfConfiguerTrait};
|
||||
use super::{Error, IfConfiguerTrait, cidr_to_subnet_mask, run_shell_cmd};
|
||||
use async_trait::async_trait;
|
||||
use cidr::{Ipv4Inet, Ipv6Inet};
|
||||
|
||||
|
||||
@@ -10,27 +10,27 @@ use anyhow::Context;
|
||||
use async_trait::async_trait;
|
||||
use cidr::{IpInet, Ipv4Inet, Ipv6Inet};
|
||||
use netlink_packet_core::{
|
||||
NetlinkDeserializable, NetlinkHeader, NetlinkMessage, NetlinkPayload, NetlinkSerializable,
|
||||
NLM_F_ACK, NLM_F_CREATE, NLM_F_DUMP, NLM_F_EXCL, NLM_F_REQUEST,
|
||||
NLM_F_ACK, NLM_F_CREATE, NLM_F_DUMP, NLM_F_EXCL, NLM_F_REQUEST, NetlinkDeserializable,
|
||||
NetlinkHeader, NetlinkMessage, NetlinkPayload, NetlinkSerializable,
|
||||
};
|
||||
use netlink_packet_route::{
|
||||
AddressFamily, RouteNetlinkMessage,
|
||||
address::{AddressAttribute, AddressMessage},
|
||||
route::{
|
||||
RouteAddress, RouteAttribute, RouteHeader, RouteMessage, RouteProtocol, RouteScope,
|
||||
RouteType,
|
||||
},
|
||||
AddressFamily, RouteNetlinkMessage,
|
||||
};
|
||||
use netlink_sys::{protocols::NETLINK_ROUTE, Socket, SocketAddr};
|
||||
use netlink_sys::{Socket, SocketAddr, protocols::NETLINK_ROUTE};
|
||||
use nix::{
|
||||
ifaddrs::getifaddrs,
|
||||
libc::{self, ifreq, ioctl, Ioctl, SIOCGIFFLAGS, SIOCGIFMTU, SIOCSIFFLAGS, SIOCSIFMTU},
|
||||
libc::{self, Ioctl, SIOCGIFFLAGS, SIOCGIFMTU, SIOCSIFFLAGS, SIOCSIFMTU, ifreq, ioctl},
|
||||
net::if_::InterfaceFlags,
|
||||
sys::socket::SockaddrLike as _,
|
||||
};
|
||||
use pnet::ipnetwork::ip_mask_to_prefix;
|
||||
|
||||
use super::{route::Route, Error, IfConfiguerTrait};
|
||||
use super::{Error, IfConfiguerTrait, route::Route};
|
||||
|
||||
pub(crate) fn dummy_socket() -> Result<std::net::UdpSocket, Error> {
|
||||
Ok(std::net::UdpSocket::bind("0:0")?)
|
||||
|
||||
@@ -740,10 +740,6 @@ impl InterfaceLuid {
|
||||
|
||||
// SAFETY: TODO
|
||||
let ret = unsafe { SetIpInterfaceEntry(&mut row) };
|
||||
if NO_ERROR == ret {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ret)
|
||||
}
|
||||
if NO_ERROR == ret { Ok(()) } else { Err(ret) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,14 @@ use std::{
|
||||
};
|
||||
use windows_sys::Win32::{
|
||||
Foundation::NO_ERROR,
|
||||
NetworkManagement::IpHelper::{GetIfEntry, SetIfEntry, MIB_IFROW},
|
||||
NetworkManagement::IpHelper::{GetIfEntry, MIB_IFROW, SetIfEntry},
|
||||
System::Diagnostics::Debug::{
|
||||
FormatMessageW, FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
FORMAT_MESSAGE_FROM_SYSTEM, FORMAT_MESSAGE_IGNORE_INSERTS, FormatMessageW,
|
||||
},
|
||||
};
|
||||
use winreg::{
|
||||
enums::{HKEY_LOCAL_MACHINE, KEY_READ, KEY_WRITE},
|
||||
RegKey,
|
||||
enums::{HKEY_LOCAL_MACHINE, KEY_READ, KEY_WRITE},
|
||||
};
|
||||
|
||||
use super::{Error, IfConfiguerTrait};
|
||||
@@ -331,7 +331,7 @@ impl RegistryManager {
|
||||
r"SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\Tcpip_";
|
||||
|
||||
pub fn reg_delete_obsoleted_items(dev_name: &str) -> io::Result<()> {
|
||||
use winreg::{enums::HKEY_LOCAL_MACHINE, enums::KEY_ALL_ACCESS, RegKey};
|
||||
use winreg::{RegKey, enums::HKEY_LOCAL_MACHINE, enums::KEY_ALL_ACCESS};
|
||||
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
|
||||
let profiles_key = hklm.open_subkey_with_flags(
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles",
|
||||
@@ -405,7 +405,7 @@ impl RegistryManager {
|
||||
}
|
||||
|
||||
pub fn reg_change_catrgory_in_profile(dev_name: &str) -> io::Result<()> {
|
||||
use winreg::{enums::HKEY_LOCAL_MACHINE, enums::KEY_ALL_ACCESS, RegKey};
|
||||
use winreg::{RegKey, enums::HKEY_LOCAL_MACHINE, enums::KEY_ALL_ACCESS};
|
||||
let hklm = RegKey::predef(HKEY_LOCAL_MACHINE);
|
||||
let profiles_key = hklm.open_subkey_with_flags(
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles",
|
||||
|
||||
@@ -9,11 +9,11 @@ use paste::paste;
|
||||
use regex::Regex;
|
||||
use tracing::level_filters::LevelFilter;
|
||||
use tracing::{Level, Metadata};
|
||||
use tracing_subscriber::filter::{filter_fn, FilterExt};
|
||||
use tracing_subscriber::Registry;
|
||||
use tracing_subscriber::filter::{FilterExt, filter_fn};
|
||||
use tracing_subscriber::fmt::layer;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::Registry;
|
||||
use tracing_subscriber::{EnvFilter, Layer};
|
||||
|
||||
macro_rules! __log__ {
|
||||
|
||||
@@ -41,8 +41,8 @@ pub fn get_logger_timer<F: time::formatting::Formattable>(
|
||||
tracing_subscriber::fmt::time::OffsetTime::new(local_offset, format)
|
||||
}
|
||||
|
||||
pub fn get_logger_timer_rfc3339(
|
||||
) -> tracing_subscriber::fmt::time::OffsetTime<time::format_description::well_known::Rfc3339> {
|
||||
pub fn get_logger_timer_rfc3339()
|
||||
-> tracing_subscriber::fmt::time::OffsetTime<time::format_description::well_known::Rfc3339> {
|
||||
get_logger_timer(time::format_description::well_known::Rfc3339)
|
||||
}
|
||||
|
||||
@@ -117,10 +117,10 @@ pub fn get_machine_id() -> uuid::Uuid {
|
||||
.unwrap_or_else(|_| std::path::PathBuf::from("et_machine_id"));
|
||||
|
||||
// try load from local file
|
||||
if let Ok(mid) = std::fs::read_to_string(&machine_id_file) {
|
||||
if let Ok(mid) = uuid::Uuid::parse_str(mid.trim()) {
|
||||
return mid;
|
||||
}
|
||||
if let Ok(mid) = std::fs::read_to_string(&machine_id_file)
|
||||
&& let Ok(mid) = uuid::Uuid::parse_str(mid.trim())
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use futures::Future;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use nix::sched::{setns, CloneFlags};
|
||||
use nix::sched::{CloneFlags, setns};
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::os::fd::AsFd;
|
||||
|
||||
|
||||
@@ -374,7 +374,9 @@ impl UnsafeCounter {
|
||||
/// that no other thread is accessing this counter simultaneously.
|
||||
pub unsafe fn add(&self, delta: u64) {
|
||||
let ptr = self.value.get();
|
||||
*ptr = (*ptr).saturating_add(delta);
|
||||
unsafe {
|
||||
*ptr = (*ptr).saturating_add(delta);
|
||||
}
|
||||
}
|
||||
|
||||
/// Increment the counter by 1
|
||||
@@ -382,7 +384,9 @@ impl UnsafeCounter {
|
||||
/// This method is unsafe because it uses UnsafeCell. The caller must ensure
|
||||
/// that no other thread is accessing this counter simultaneously.
|
||||
pub unsafe fn inc(&self) {
|
||||
self.add(1);
|
||||
unsafe {
|
||||
self.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current value of the counter
|
||||
@@ -391,7 +395,7 @@ impl UnsafeCounter {
|
||||
/// that no other thread is modifying this counter simultaneously.
|
||||
pub unsafe fn get(&self) -> u64 {
|
||||
let ptr = self.value.get();
|
||||
*ptr
|
||||
unsafe { *ptr }
|
||||
}
|
||||
|
||||
/// Reset the counter to zero
|
||||
@@ -400,7 +404,9 @@ impl UnsafeCounter {
|
||||
/// that no other thread is accessing this counter simultaneously.
|
||||
pub unsafe fn reset(&self) {
|
||||
let ptr = self.value.get();
|
||||
*ptr = 0;
|
||||
unsafe {
|
||||
*ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the counter to a specific value
|
||||
@@ -409,7 +415,9 @@ impl UnsafeCounter {
|
||||
/// that no other thread is accessing this counter simultaneously.
|
||||
pub unsafe fn set(&self, value: u64) {
|
||||
let ptr = self.value.get();
|
||||
*ptr = value;
|
||||
unsafe {
|
||||
*ptr = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +454,9 @@ impl MetricData {
|
||||
/// that no other thread is accessing this timestamp simultaneously.
|
||||
unsafe fn touch(&self) {
|
||||
let ptr = self.last_updated.get();
|
||||
*ptr = Instant::now();
|
||||
unsafe {
|
||||
*ptr = Instant::now();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the last updated timestamp
|
||||
@@ -455,7 +465,7 @@ impl MetricData {
|
||||
/// that no other thread is modifying this timestamp simultaneously.
|
||||
unsafe fn get_last_updated(&self) -> Instant {
|
||||
let ptr = self.last_updated.get();
|
||||
*ptr
|
||||
unsafe { *ptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ use crossbeam::atomic::AtomicCell;
|
||||
use rand::seq::IteratorRandom;
|
||||
use socket2::{SockAddr, SockRef};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::{lookup_host, UdpSocket};
|
||||
use tokio::sync::{broadcast, Mutex};
|
||||
use tokio::net::{UdpSocket, lookup_host};
|
||||
use tokio::sync::{Mutex, broadcast};
|
||||
use tokio::task::JoinSet;
|
||||
use tracing::{Instrument, Level};
|
||||
|
||||
@@ -1340,7 +1340,7 @@ impl StunInfoCollectorTrait for MockStunInfoCollector {
|
||||
mod tests {
|
||||
use crate::{
|
||||
common::scoped_task::ScopedTask,
|
||||
tunnel::{udp::UdpTunnelListener, TunnelListener},
|
||||
tunnel::{TunnelListener, udp::UdpTunnelListener},
|
||||
};
|
||||
use tokio::time::{sleep, timeout};
|
||||
|
||||
@@ -1404,10 +1404,10 @@ mod tests {
|
||||
loop {
|
||||
let ret = detector.detect_nat_type(0).await;
|
||||
println!("{:#?}, {:?}", ret, ret.as_ref().map(|x| x.nat_type()));
|
||||
if let Ok(resp) = ret {
|
||||
if !resp.stun_resps.is_empty() {
|
||||
return;
|
||||
}
|
||||
if let Ok(resp) = ret
|
||||
&& !resp.stun_resps.is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use bytecodec::fixnum::{U32beDecoder, U32beEncoder};
|
||||
use stun_codec::net::{socket_addr_xor, SocketAddrDecoder, SocketAddrEncoder};
|
||||
use stun_codec::net::{SocketAddrDecoder, SocketAddrEncoder, socket_addr_xor};
|
||||
|
||||
use stun_codec::rfc5389::attributes::{
|
||||
MappedAddress, Software, XorMappedAddress, XorMappedAddress2,
|
||||
};
|
||||
use stun_codec::rfc5780::attributes::{OtherAddress, ResponseOrigin};
|
||||
use stun_codec::{define_attribute_enums, AttributeType, Message, TransactionId};
|
||||
use stun_codec::{AttributeType, Message, TransactionId, define_attribute_enums};
|
||||
|
||||
use bytecodec::{ByteCount, Decode, Encode, Eos, Result, SizedEncode, TryTaggedDecode};
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ mod tests {
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use tokio::time::{sleep, Duration};
|
||||
use tokio::time::{Duration, sleep};
|
||||
|
||||
/// Test initial state after creation
|
||||
#[tokio::test]
|
||||
|
||||
@@ -57,17 +57,16 @@ impl Default for RollingConditionBase {
|
||||
impl RollingCondition for RollingConditionBase {
|
||||
fn should_rollover(&mut self, now: &DateTime<Local>, current_filesize: u64) -> bool {
|
||||
let mut rollover = false;
|
||||
if let Some(frequency) = self.frequency_opt.as_ref() {
|
||||
if let Some(last_write) = self.last_write_opt.as_ref() {
|
||||
if frequency.equivalent_datetime(now) != frequency.equivalent_datetime(last_write) {
|
||||
rollover = true;
|
||||
}
|
||||
}
|
||||
if let Some(frequency) = self.frequency_opt.as_ref()
|
||||
&& let Some(last_write) = self.last_write_opt.as_ref()
|
||||
&& frequency.equivalent_datetime(now) != frequency.equivalent_datetime(last_write)
|
||||
{
|
||||
rollover = true;
|
||||
}
|
||||
if let Some(max_size) = self.max_size_opt.as_ref() {
|
||||
if current_filesize >= *max_size {
|
||||
rollover = true;
|
||||
}
|
||||
if let Some(max_size) = self.max_size_opt.as_ref()
|
||||
&& current_filesize >= *max_size
|
||||
{
|
||||
rollover = true;
|
||||
}
|
||||
self.last_write_opt = Some(*now);
|
||||
rollover
|
||||
|
||||
@@ -81,11 +81,7 @@ where
|
||||
/// Determines the final filename, where n==0 indicates the current file
|
||||
fn filename_for(&self, n: usize) -> String {
|
||||
let f = self.filename.clone();
|
||||
if n > 0 {
|
||||
format!("{}.{}", f, n)
|
||||
} else {
|
||||
f
|
||||
}
|
||||
if n > 0 { format!("{}.{}", f, n) } else { f }
|
||||
}
|
||||
|
||||
/// Rotates old files to make room for a new one.
|
||||
@@ -145,14 +141,14 @@ where
|
||||
|
||||
/// Writes data using the given datetime to calculate the rolling condition
|
||||
pub fn write_with_datetime(&mut self, buf: &[u8], now: &DateTime<Local>) -> io::Result<usize> {
|
||||
if self.condition.should_rollover(now, self.current_filesize) {
|
||||
if let Err(e) = self.rollover() {
|
||||
// If we can't rollover, just try to continue writing anyway
|
||||
// (better than missing data).
|
||||
// This will likely used to implement logging, so
|
||||
// avoid using log::warn and log to stderr directly
|
||||
eprintln!("WARNING: Failed to rotate logfile {}: {}", self.filename, e);
|
||||
}
|
||||
if self.condition.should_rollover(now, self.current_filesize)
|
||||
&& let Err(e) = self.rollover()
|
||||
{
|
||||
// If we can't rollover, just try to continue writing anyway
|
||||
// (better than missing data).
|
||||
// This will likely used to implement logging, so
|
||||
// avoid using log::warn and log to stderr directly
|
||||
eprintln!("WARNING: Failed to rotate logfile {}: {}", self.filename, e);
|
||||
}
|
||||
self.open_writer_if_needed()?;
|
||||
if let Some(writer) = self.writer_opt.as_mut() {
|
||||
|
||||
Reference in New Issue
Block a user