11#pragma once
22#include < string>
3- #include < map >
3+ #include < unordered_map >
44#include < mutex>
5+ #include < vector>
56#include < winsock2.h>
67#include < ws2tcpip.h>
8+ #include < sstream>
79#include " ../core/Config.hpp"
810#include " ../core/Logger.hpp"
911
1012namespace Network {
1113
12- // FakeIP 管理器
13- // 用于将域名映射到虚拟 IP (10.x.x.x),并在 connect 时还原
14+ // FakeIP 管理器 (Ring Buffer 策略)
15+ // 默认使用 198.18.0.0/15 (保留用于基准测试的网络,不容易冲突)
1416 class FakeIP {
15- std::map <uint32_t , std::string> m_ipToDomain; // IP -> Domain 映射
16- std::map <std::string, uint32_t > m_domainToIp; // Domain -> IP 映射 (反向查找 )
17+ std::unordered_map <uint32_t , std::string> m_ipToDomain; // IP(host order) -> Domain
18+ std::unordered_map <std::string, uint32_t > m_domainToIp; // Domain -> IP(host order )
1719 std::mutex m_mtx;
18- uint32_t m_nextIp; // 下一个可分配的 IP (主机字节序)
20+
21+ uint32_t m_baseIp; // 网段起始 IP (host order)
22+ uint32_t m_mask; // 子网掩码 (host order)
23+ uint32_t m_networkSize; // 可用 IP 数量
24+ uint32_t m_cursor; // 当前分配游标 (0 ~ networkSize-1)
25+ bool m_initialized;
26+
27+ // CIDR 解析: "198.18.0.0/15" -> baseIp, mask
28+ bool ParseCidr (const std::string& cidr, uint32_t & outBase, uint32_t & outMask) {
29+ size_t slashPos = cidr.find (' /' );
30+ if (slashPos == std::string::npos) return false ;
31+
32+ std::string ipPart = cidr.substr (0 , slashPos);
33+ std::string bitsPart = cidr.substr (slashPos + 1 );
34+
35+ int bits = std::stoi (bitsPart);
36+ if (bits < 0 || bits > 32 ) return false ;
37+
38+ in_addr addr;
39+ if (inet_pton (AF_INET, ipPart.c_str (), &addr) != 1 ) return false ;
40+
41+ outBase = ntohl (addr.s_addr );
42+ // 这里处理 bits=0 的边界情况
43+ if (bits == 0 ) outMask = 0 ;
44+ else outMask = 0xFFFFFFFF << (32 - bits);
45+
46+ // 确保 base 是网段首地址
47+ outBase &= outMask;
48+ return true ;
49+ }
1950
2051 public:
21- FakeIP () : m_nextIp( 0x0A000001 ) {} // 10.0.0.1 开始
52+ FakeIP () : m_baseIp( 0 ), m_mask( 0 ), m_networkSize( 0 ), m_cursor( 1 ), m_initialized( false ) {}
2253
2354 static FakeIP& Instance () {
2455 static FakeIP instance;
56+ // 延迟初始化,确保 Config 已加载
57+ if (!instance.m_initialized ) {
58+ instance.Init ();
59+ }
2560 return instance;
2661 }
2762
28- // 检查是否为虚拟 IP (10.0.0.0/8 范围)
63+ void Init () {
64+ std::lock_guard<std::mutex> lock (m_mtx);
65+ if (m_initialized) return ;
66+
67+ auto & config = Core::Config::Instance ();
68+ std::string cidr = config.fakeIp .cidr ;
69+ if (cidr.empty ()) cidr = " 198.18.0.0/15" ;
70+
71+ if (ParseCidr (cidr, m_baseIp, m_mask)) {
72+ m_networkSize = ~m_mask + 1 ; // e.g. /24 -> 256
73+ // 保留 .0 和 .255 (广播) ? 在 FakeIP 场景下其实通常都可以用,
74+ // 但为了规避某些系统行为,跳过第0个和最后一个是个好习惯。
75+ // 简单起见,我们从 offset 1 开始使用。
76+
77+ Core::Logger::Info (" FakeIP: 初始化成功, CIDR=" + cidr +
78+ " , 容量=" + std::to_string (m_networkSize));
79+ } else {
80+ Core::Logger::Error (" FakeIP: CIDR 解析失败 (" + cidr + " ),回退到 198.18.0.0/15" );
81+ ParseCidr (" 198.18.0.0/15" , m_baseIp, m_mask);
82+ m_networkSize = ~m_mask + 1 ;
83+ }
84+ m_initialized = true ;
85+ }
86+
87+ // 检查是否为虚拟 IP
2988 bool IsFakeIP (uint32_t ipNetworkOrder) {
89+ if (!m_initialized) Init ();
3090 uint32_t ip = ntohl (ipNetworkOrder);
31- return (ip & 0xFF000000 ) == 0x0A000000 ; // 10.x.x.x
91+ return (ip & m_mask ) == m_baseIp;
3292 }
3393
34- // 为域名分配虚拟 IP (如果已分配则返回现有 IP)
94+ // 为域名分配虚拟 IP (Ring Buffer 策略)
95+ // 返回网络字节序 IP
3596 uint32_t Alloc (const std::string& domain) {
3697 std::lock_guard<std::mutex> lock (m_mtx);
98+ if (!m_initialized) Init ();
3799
38- // 检查是否已分配
100+ // 1. 如果已存在映射,直接返回
39101 auto it = m_domainToIp.find (domain);
40102 if (it != m_domainToIp.end ()) {
103+ // 可选:更新 LRU?Ring Buffer 不需要 LRU,由于空间只要够大,复用率低
41104 return htonl (it->second );
42105 }
43106
44- // 限制缓存规模,避免无限增长
45- int maxEntries = Core::Config::Instance (). fakeIp . max_entries ;
46- if (maxEntries > 0 && m_domainToIp. size () >= static_cast < size_t >(maxEntries)) {
47- static bool s_limitLogged = false ;
48- if (!s_limitLogged) {
49- Core::Logger::Warn ( " FakeIP: 映射已达上限,后续域名将回退原始解析 " );
50- s_limitLogged = true ;
51- }
52- return 0 ;
107+ // 2. 分配新 IP
108+ if (m_networkSize <= 2 ) return 0 ; // 防御性检查
109+
110+ // 游标移动
111+ uint32_t offset = m_cursor++;
112+ // 简单的 Ring Buffer: 超过范围回到 1
113+ if (m_cursor >= m_networkSize - 1 ) {
114+ m_cursor = 1 ;
115+ Core::Logger::Info ( " FakeIP: 地址池循环回绕 " ) ;
53116 }
117+
118+ uint32_t newIp = m_baseIp | offset;
119+
120+ // 3. 检查并清理旧映射 (Collision handling)
121+ auto oldIt = m_ipToDomain.find (newIp);
122+ if (oldIt != m_ipToDomain.end ()) {
123+ // 把旧域名从反向表中移除
124+ m_domainToIp.erase (oldIt->second );
125+ // Core::Logger::Debug("FakeIP: 回收 IP " + IpToString(htonl(newIp)) + " (原域名: " + oldIt->second + ")");
126+ }
127+
128+ // 4. 建立新映射
129+ m_ipToDomain[newIp] = domain;
130+ m_domainToIp[domain] = newIp;
54131
55- // 分配新 IP
56- uint32_t ip = m_nextIp++;
57- m_ipToDomain[ip] = domain;
58- m_domainToIp[domain] = ip;
59-
60- Core::Logger::Info (" FakeIP: 已分配 " + IpToString (htonl (ip)) + " 给域名 " + domain);
61- return htonl (ip); // 返回网络字节序
132+ Core::Logger::Info (" FakeIP: 分配 " + IpToString (htonl (newIp)) + " -> " + domain);
133+ return htonl (newIp);
62134 }
63135
64136 // 根据虚拟 IP 获取域名
@@ -78,8 +150,10 @@ namespace Network {
78150 char buf[INET_ADDRSTRLEN];
79151 in_addr addr;
80152 addr.s_addr = ipNetworkOrder;
81- inet_ntop (AF_INET, &addr, buf, sizeof (buf));
82- return std::string (buf);
153+ if (inet_ntop (AF_INET, &addr, buf, sizeof (buf))) {
154+ return std::string (buf);
155+ }
156+ return " " ;
83157 }
84158 };
85159}
0 commit comments