规则更新
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#include "Proxy_Ping0_Labeler.h"
|
||||
#include "Async_Blocking.h"
|
||||
#include "Ping0_Html_Parser.h"
|
||||
#include "config.h"
|
||||
#include "Public_Ip_Config.h"
|
||||
#include "export.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -39,15 +39,47 @@ struct Node_Route {
|
||||
std::string username;
|
||||
std::string proxy_name;
|
||||
};
|
||||
std::string query_public_ip_by_user(std::string_view username, uint16_t mixed_port, std::string_view host);
|
||||
template <int cache_ttl_seconds, bool radical>
|
||||
struct Public_Ip {
|
||||
std::optional<std::string> ip;
|
||||
std::optional<std::string> expired_ip;
|
||||
std::optional<std::string> ip_error;
|
||||
std::optional<std::chrono::system_clock::time_point> ip_cached_at_utc;
|
||||
bool is_expired() const {
|
||||
if (cache_ttl_seconds <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (!ip_cached_at_utc) {
|
||||
return true;
|
||||
}
|
||||
return std::chrono::system_clock::now() - *ip_cached_at_utc >= std::chrono::seconds(cache_ttl_seconds);
|
||||
}
|
||||
bool should_refresh() const {
|
||||
const bool expired = is_expired();
|
||||
return radical ? expired : expired && !ip.has_value();
|
||||
}
|
||||
std::optional<std::string> get_ip() const {
|
||||
return ip ? ip : expired_ip;
|
||||
}
|
||||
void refresh(std::string_view username, uint16_t mixed_port, std::string_view host) {
|
||||
const auto old_ip = get_ip();
|
||||
ip.reset();
|
||||
ip_error.reset();
|
||||
ip_cached_at_utc = std::chrono::system_clock::now();
|
||||
try {
|
||||
ip = query_public_ip_by_user(username, mixed_port, host);
|
||||
expired_ip.reset();
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
expired_ip = old_ip;
|
||||
ip_error = error_text_to_utf8(error.what());
|
||||
}
|
||||
}
|
||||
};
|
||||
struct Public_Ip_Cache {
|
||||
std::optional<std::string> ipv4;
|
||||
std::optional<std::string> ipv6;
|
||||
std::optional<std::string> expired_ipv4;
|
||||
std::optional<std::string> expired_ipv6;
|
||||
std::optional<std::string> ipv4_error;
|
||||
std::optional<std::string> ipv6_error;
|
||||
std::optional<std::chrono::system_clock::time_point> ipv4_cached_at_utc;
|
||||
std::optional<std::chrono::system_clock::time_point> ipv6_cached_at_utc;
|
||||
Public_Ip<public_ipv4_cache_ttl_seconds, radical_ipv4> ipv4;
|
||||
Public_Ip<public_ipv6_cache_ttl_seconds, radical_ipv6> ipv6;
|
||||
};
|
||||
struct Node_Ping0_Result {
|
||||
std::string name;
|
||||
@@ -251,20 +283,20 @@ Public_Ip_Cache load_cached_public_ips(const fs::path& path) {
|
||||
return result;
|
||||
}
|
||||
const auto cache = load_yaml_file(path);
|
||||
result.ipv4 = read_optional_string(cache, "public_ipv4");
|
||||
if (!result.ipv4) {
|
||||
result.ipv4 = read_optional_string(cache, "public_ip");
|
||||
result.ipv4.ip = read_optional_string(cache, "public_ipv4");
|
||||
if (!result.ipv4.ip) {
|
||||
result.ipv4.ip = read_optional_string(cache, "public_ip");
|
||||
}
|
||||
result.ipv6 = read_optional_string(cache, "public_ipv6");
|
||||
result.expired_ipv4 = read_optional_string(cache, "expired_public_ipv4");
|
||||
result.expired_ipv6 = read_optional_string(cache, "expired_public_ipv6");
|
||||
result.ipv4_error = read_optional_string(cache, "public_ipv4_error");
|
||||
result.ipv6_error = read_optional_string(cache, "public_ipv6_error");
|
||||
result.ipv6.ip = read_optional_string(cache, "public_ipv6");
|
||||
result.ipv4.expired_ip = read_optional_string(cache, "expired_public_ipv4");
|
||||
result.ipv6.expired_ip = read_optional_string(cache, "expired_public_ipv6");
|
||||
result.ipv4.ip_error = read_optional_string(cache, "public_ipv4_error");
|
||||
result.ipv6.ip_error = read_optional_string(cache, "public_ipv6_error");
|
||||
if (const auto cached_at = read_optional_string(cache, "public_ipv4_cached_at_utc")) {
|
||||
result.ipv4_cached_at_utc = parse_utc_time(*cached_at);
|
||||
result.ipv4.ip_cached_at_utc = parse_utc_time(*cached_at);
|
||||
}
|
||||
if (const auto cached_at = read_optional_string(cache, "public_ipv6_cached_at_utc")) {
|
||||
result.ipv6_cached_at_utc = parse_utc_time(*cached_at);
|
||||
result.ipv6.ip_cached_at_utc = parse_utc_time(*cached_at);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -296,30 +328,30 @@ void save_public_ip_cache(const fs::path& path, const Node_Route& route, const P
|
||||
node["proxy_name"] = route.proxy_name;
|
||||
node["username"] = route.username;
|
||||
node["mixed_port"] = mixed_port;
|
||||
if (cache.ipv4) {
|
||||
node["public_ip"] = *cache.ipv4;
|
||||
node["public_ipv4"] = *cache.ipv4;
|
||||
if (cache.ipv4.ip) {
|
||||
node["public_ip"] = *cache.ipv4.ip;
|
||||
node["public_ipv4"] = *cache.ipv4.ip;
|
||||
}
|
||||
if (cache.ipv6) {
|
||||
node["public_ipv6"] = *cache.ipv6;
|
||||
if (cache.ipv6.ip) {
|
||||
node["public_ipv6"] = *cache.ipv6.ip;
|
||||
}
|
||||
if (cache.expired_ipv4) {
|
||||
node["expired_public_ipv4"] = *cache.expired_ipv4;
|
||||
if (cache.ipv4.expired_ip) {
|
||||
node["expired_public_ipv4"] = *cache.ipv4.expired_ip;
|
||||
}
|
||||
if (cache.expired_ipv6) {
|
||||
node["expired_public_ipv6"] = *cache.expired_ipv6;
|
||||
if (cache.ipv6.expired_ip) {
|
||||
node["expired_public_ipv6"] = *cache.ipv6.expired_ip;
|
||||
}
|
||||
if (cache.ipv4_error) {
|
||||
node["public_ipv4_error"] = *cache.ipv4_error;
|
||||
if (cache.ipv4.ip_error) {
|
||||
node["public_ipv4_error"] = *cache.ipv4.ip_error;
|
||||
}
|
||||
if (cache.ipv6_error) {
|
||||
node["public_ipv6_error"] = *cache.ipv6_error;
|
||||
if (cache.ipv6.ip_error) {
|
||||
node["public_ipv6_error"] = *cache.ipv6.ip_error;
|
||||
}
|
||||
if (cache.ipv4_cached_at_utc) {
|
||||
node["public_ipv4_cached_at_utc"] = make_utc_time(*cache.ipv4_cached_at_utc);
|
||||
if (cache.ipv4.ip_cached_at_utc) {
|
||||
node["public_ipv4_cached_at_utc"] = make_utc_time(*cache.ipv4.ip_cached_at_utc);
|
||||
}
|
||||
if (cache.ipv6_cached_at_utc) {
|
||||
node["public_ipv6_cached_at_utc"] = make_utc_time(*cache.ipv6_cached_at_utc);
|
||||
if (cache.ipv6.ip_cached_at_utc) {
|
||||
node["public_ipv6_cached_at_utc"] = make_utc_time(*cache.ipv6.ip_cached_at_utc);
|
||||
}
|
||||
node["ipv4_source"] = source_url(ipv4_query_url_host);
|
||||
node["ipv6_source"] = source_url(ipv6_query_url_host);
|
||||
@@ -331,65 +363,20 @@ void save_public_ip_cache(const fs::path& path, const Node_Route& route, const P
|
||||
}
|
||||
write_file_atomic(path, std::string_view(emitter.c_str(), emitter.size()));
|
||||
}
|
||||
bool public_ip_cache_expired(const std::optional<std::chrono::system_clock::time_point>& cached_at_utc, int ttl_seconds) {
|
||||
if (ttl_seconds <= 0) {
|
||||
return false;
|
||||
}
|
||||
if (!cached_at_utc) {
|
||||
return true;
|
||||
}
|
||||
return std::chrono::system_clock::now() - *cached_at_utc >= std::chrono::seconds(ttl_seconds);
|
||||
}
|
||||
void refresh_public_ipv4(Public_Ip_Cache& cache, std::string_view username, uint16_t mixed_port) {
|
||||
const auto old_ipv4 = cache.ipv4 ? cache.ipv4 : cache.expired_ipv4;
|
||||
cache.ipv4.reset();
|
||||
cache.ipv4_error.reset();
|
||||
cache.ipv4_cached_at_utc = std::chrono::system_clock::now();
|
||||
try {
|
||||
cache.ipv4 = query_public_ip_by_user(username, mixed_port, ipv4_query_url_host);
|
||||
cache.expired_ipv4.reset();
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
cache.expired_ipv4 = old_ipv4;
|
||||
cache.ipv4_error = error_text_to_utf8(error.what());
|
||||
}
|
||||
}
|
||||
void refresh_public_ipv6(Public_Ip_Cache& cache, std::string_view username, uint16_t mixed_port) {
|
||||
const auto old_ipv6 = cache.ipv6 ? cache.ipv6 : cache.expired_ipv6;
|
||||
cache.ipv6.reset();
|
||||
cache.ipv6_error.reset();
|
||||
cache.ipv6_cached_at_utc = std::chrono::system_clock::now();
|
||||
try {
|
||||
cache.ipv6 = query_public_ip_by_user(username, mixed_port, ipv6_query_url_host);
|
||||
cache.expired_ipv6.reset();
|
||||
}
|
||||
catch (const std::exception& error) {
|
||||
cache.expired_ipv6 = old_ipv6;
|
||||
cache.ipv6_error = error_text_to_utf8(error.what());
|
||||
}
|
||||
}
|
||||
std::optional<std::string> usable_ipv4(const Public_Ip_Cache& cache) {
|
||||
return cache.ipv4 ? cache.ipv4 : cache.expired_ipv4;
|
||||
}
|
||||
std::optional<std::string> usable_ipv6(const Public_Ip_Cache& cache) {
|
||||
return cache.ipv6 ? cache.ipv6 : cache.expired_ipv6;
|
||||
}
|
||||
Public_Ip_Cache get_public_ips(const Node_Route& route, const fs::path& cache_dir, std::optional<uint16_t> mixed_port) {
|
||||
const auto cache_path = make_ip_cache_path(cache_dir, route.proxy_name);
|
||||
std::lock_guard lock(public_ip_cache_lock(cache_path));
|
||||
Public_Ip_Cache cache = load_cached_public_ips(cache_path);
|
||||
const bool ipv4_expired = public_ip_cache_expired(cache.ipv4_cached_at_utc, public_ipv4_cache_ttl_seconds);
|
||||
const bool ipv6_expired = public_ip_cache_expired(cache.ipv6_cached_at_utc, public_ipv6_cache_ttl_seconds);
|
||||
bool changed = false;
|
||||
if (!mixed_port) {
|
||||
return cache;
|
||||
}
|
||||
if (radical_ipv4 ? ipv4_expired : ipv4_expired && !cache.ipv4.has_value()) {
|
||||
refresh_public_ipv4(cache, route.username, *mixed_port);
|
||||
if (cache.ipv4.should_refresh()) {
|
||||
cache.ipv4.refresh(route.username, *mixed_port, ipv4_query_url_host);
|
||||
changed = true;
|
||||
}
|
||||
if (radical_ipv6 ? ipv6_expired : ipv6_expired && !cache.ipv6.has_value()) {
|
||||
refresh_public_ipv6(cache, route.username, *mixed_port);
|
||||
if (cache.ipv6.should_refresh()) {
|
||||
cache.ipv6.refresh(route.username, *mixed_port, ipv6_query_url_host);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
@@ -538,7 +525,7 @@ void print_ping0_info(const Node_Route& route, const Node_Ping0_Result& result)
|
||||
}
|
||||
std::optional<Node_Ping0_Result> load_node_ping0_result(const Node_Route& route, const fs::path& ip_cache_dir, const fs::path& html_cache_dir, std::optional<uint16_t> mixed_port) {
|
||||
const auto public_ips = get_public_ips(route, ip_cache_dir, mixed_port);
|
||||
const auto public_ipv4 = usable_ipv4(public_ips);
|
||||
const auto public_ipv4 = public_ips.ipv4.get_ip();
|
||||
if (!public_ipv4) {
|
||||
std::cerr << std::format("Ping0 标注跳过:节点 {} 没有 IPv4 出口缓存\n", route.proxy_name);
|
||||
return std::nullopt;
|
||||
@@ -549,7 +536,7 @@ std::optional<Node_Ping0_Result> load_node_ping0_result(const Node_Route& route,
|
||||
return std::nullopt;
|
||||
}
|
||||
auto info = Ping0::parse_file(*html_path);
|
||||
return Node_Ping0_Result{route.proxy_name, *public_ipv4, usable_ipv6(public_ips), make_ip_cache_path(ip_cache_dir, route.proxy_name), *html_path, std::move(info), route.index, std::nullopt};
|
||||
return Node_Ping0_Result{route.proxy_name, *public_ipv4, public_ips.ipv6.get_ip(), make_ip_cache_path(ip_cache_dir, route.proxy_name), *html_path, std::move(info), route.index, std::nullopt};
|
||||
}
|
||||
void record_ai_node_info(Node_Ping0_Result result, const fs::path& node_state_dir) {
|
||||
const auto ai_score = ai_scene_score(result.info);
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
#pragma once
|
||||
// 出口 IPv4 缓存有效期,单位秒;0 表示永不过期。
|
||||
inline constexpr int public_ipv4_cache_ttl_seconds = 7 * 24 * 60 * 60;
|
||||
// 出口 IPv6 缓存有效期,单位秒;0 表示永不过期。
|
||||
inline constexpr int public_ipv6_cache_ttl_seconds = 7 * 24 * 60 * 60;
|
||||
// true 表示对应缓存过期就重查;false 表示过期且缺少对应 IP 才重查。
|
||||
inline constexpr bool radical_ipv4 = true;
|
||||
inline constexpr bool radical_ipv6 = true;
|
||||
|
||||
Reference in New Issue
Block a user