OPENPPP2 Code Analysis Three
一、核心理念
OPENPPP2是一个企业级虚拟以太网VNP解决方案,采用现代化的架构设计思想:
1.1 技术特点
- 全协程+多线程架构:混合并发模型,结合协程的轻量级和多线程的并行能力
- 同步超线程IO技术(SSMT):在Linux平台上实现多线程包处理优化
- 虚拟以太网技术:完整实现二层网络虚拟化,支持虚拟子网和广播
1.2 设计原则
该系统遵循以下设计原则:
- 技术中立原则:作为纯技术实现,不运营服务器、不存储日志
- 模块化设计:客户端/服务器分离,驱动层、协议层、应用层清晰分层
- 高性能导向:采用零拷贝、内存池、SIMD优化等技术
二、事件驱动架构模型
OPENPPP2采用完整的事件驱动状态机架构(Event-Driven State Machine Architecture):
2.1 Boost.Asio事件循环
整个系统基于Boost.Asio的io_context构建异步事件处理机制:
核心事件循环组件:
- Executor(默认上下文):主事件循环
- Scheduler(调度器上下文):多线程IO完成处理
- Per-Thread Context:每线程独立事件循环
2.2 回调驱动的包处理
网络包处理采用事件回调模式:
TAP设备的包输入通过PacketInputEventHandler回调实现异步处理。
2.3 定时器事件系统
OnTick和OnUpdate方法实现周期性事件处理,用于保活、超时检测等。
三、协程系统架构
3.1 协程核心实现
OPENPPP2实现了自定义的**栈式协程(Stackful Coroutine)**系统:
核心特性:
- 基于Boost.Context的
fcontext实现上下文切换 - 支持
Spawn、Suspend、Resume操作 - 集成Boost.Asio实现异步操作的同步写法
3.2 协程状态管理
使用原子变量管理协程状态,包括:
s_:状态标志callee_/caller_:调用者和被调用者上下文stack_:协程栈内存
3.3 协程调度器
Executors类管理协程调度,提供:
- 多个
io_context实例用于负载均衡 - 协程在不同上下文间迁移(
ShiftToScheduler) - 与Strand协同工作确保线程安全
四、工程结构
4.1 目录结构
openppp2/
├── ppp/ # 核心库
│ ├── app/ # 应用层
│ │ ├── client/ # 客户端实现
│ │ ├── server/ # 服务端实现
│ │ ├── protocol/ # 协议层
│ │ └── mux/ # 多路复用
│ ├── ethernet/ # 虚拟以太网
│ ├── tap/ # TAP驱动接口
│ ├── net/ # 网络协议栈
│ ├── coroutines/ # 协程系统
│ ├── threading/ # 线程管理
│ ├── transmissions/ # 传输层
│ └── configurations/ # 配置管理
├── common/ # 通用组件
├── windows/ # Windows平台
├── linux/ # Linux平台
├── darwin/ # macOS平台
└── android/ # Android平台
4.2 应用层结构
PppApplication是应用入口,管理:
- 配置加载与验证
- 客户端/服务器模式切换
- 统计信息收集
- 生命周期管理
五、数据流架构
5.1 包处理流水线
输入路径(TAP → 虚拟以太网 → 协议栈):
TAP设备接收
↓
PacketInputEventHandler回调
↓
VEthernet::PacketInput()
↓
协议分流 (TCP/UDP/ICMP)
↓
IPFragment处理分片
↓
OnPacketInput()虚拟方法
↓
应用层处理
输出路径(应用 → 虚拟以太网 → TAP):
5.2 协议层数据流
协议层定义了多种包动作(PacketAction):
- INFO/KEEPALIVED:信息和保活
- FRP系列:端口映射(Fast Reverse Proxy)
- VNP系列:TCP连接管理(SYN/PSH/FIN)、NAT、UDP转发
- MUX系列:多路复用
5.3 MUX多路复用数据流
MUX实现带宽聚合,通过多个TCP连接传输数据:
数据流程:
- 客户端发起多个并行连接(
DoMux) - 服务器接受并建立映射(
OnMux) - 数据包按序号分发到不同连接
- 接收端重组数据包
六、数据结构
6.1 IP帧结构
IPFrame是核心数据结构,封装IP层信息:
- 地址族、源/目标IP、TTL、ToS
- 协议类型、标志位
- 载荷和选项的
BufferSegment
6.2 配置数据结构
AppConfiguration包含完整配置信息:
- 并发控制 :
concurrent线程数 - 加密配置 :
key结构体(协议层/传输层加密) - 网络配置:TCP/UDP参数、WebSocket、MUX设置
- 虚拟内存 :
vmem配置内存池
6.3 内存管理结构
使用BufferswapAllocator实现专用虚拟内存池,优化内存分配性能。
七、驱动结构
7.1 TAP驱动抽象层
ITap接口定义跨平台TAP设备抽象:
- 输入 :
PacketInput事件处理器 - 输出 :
Output方法族 - 配置:IP地址、网关、子网掩码
- 状态管理 :
Open、Dispose、IsReady
7.2 平台特定实现
驱动层针对不同平台有专门实现:
- Windows :
TapWindows- 使用NDIS驱动 - Linux :
TapLinux- 使用TUN/TAP字符设备 - macOS :
TapDarwin- 使用utun接口
7.3 虚拟网络栈
VEthernet集成TAP驱动和网络栈:
- LWIP模式:使用lwIP用户态协议栈(Windows默认)
- CTCP模式:使用内核协议栈(Linux/macOS默认)
- VNet模式:启用子网转发功能
八、流程架构
8.1 应用启动流程
主流程:
- 环境初始化:解析命令行、加载配置
- 防火墙配置(Windows):添加应用规则
- TAP设备创建:打开虚拟网卡
- 网络切换器创建 :
VEthernetNetworkSwitcher(客户端)或VirtualEthernetSwitcher(服务器) - 启动事件循环 :
Executors::Run
8.2 客户端连接流程
是
否
加载配置
创建TAP设备
初始化VEthernetNetworkSwitcher
连接VNP服务器
连接成功?
建立隧道
重连逻辑
启动MUX多路复用
数据转发就绪
8.3 数据包转发流程
协议层定义的数据包处理方法:
- DoConnect/OnConnect:TCP连接建立
- DoPush/OnPush:数据推送
- DoSendTo/OnSendTo:UDP数据报转发
- DoNat/OnNat:NAT包处理
8.4 协程工作流程
否
是
YieldContext::Spawn
分配栈空间
创建fcontext
投递到io_context
协程开始执行
Suspend挂起
异步操作
Resume恢复
继续执行
完成?
释放资源
九、特殊架构特性
9.1 SSMT(Super Synchronous Multi-Threading)
在Linux平台上,OPENPPP2实现了特殊的多线程包处理优化:
SSMT特性:
- 多线程模式:将包处理分发到多个线程
- 单线程优化(st):针对单连接大流量
- 多队列模式(mq):针对多连接高并发
9.2 纸飞机加速技术(PaperAirplane)
Windows平台独有的TCP加速技术,通过LSP(Layered Service Provider)实现分层加速。
9.3 虚拟BGP多线分流
实现智能路由分流,根据目标地址选择最优路径。
十、性能优化技术
10.1 零拷贝与内存池
通过BufferswapAllocator实现专用内存管理,减少内存分配开销。
10.2 SIMD加密优化
支持AES-NI指令集加速:
加速算法:
- simd-aes-128-cfb
- simd-aes-256-cfb
- simd-aes-128-gcm
- simd-aes-256-gcm
10.3 TCP优化技术
支持:
- TCP Turbo:窗口优化
- TCP Fast Open:减少握手延迟
- 拥塞窗口(cwnd)/接收窗口(rwnd)控制
备注
OPENPPP2采用了现代化的C++17架构设计,核心特点是:
- 混合并发模型:协程提供同步编程体验,多线程提供并行能力,事件循环提供高效IO
- 分层清晰:驱动层(ITap)→ 虚拟以太网层(VEthernet)→ 协议层(VirtualEthernetLinklayer)→ 应用层
- 跨平台设计:通过抽象接口和条件编译支持Windows/Linux/macOS/Android
- 高度可配置:通过JSON配置文件控制所有行为参数
- 生产级优化:内存池、SIMD、零拷贝等技术确保高性能
系统实现了完整的**事件驱动状态机(Event-Driven State Machine)**模式,通过协程、回调、定时器等机制实现复杂的异步状态管理。
Citations
File: README_CN.md (L14-51)
markdown
## <img src="https://img.icons8.com/color/48/000000/features-list.png" width="30" height="30"> 核心技术特点
<div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px;">
<div>
- <img src="https://img.icons8.com/color/24/000000/processor.png" width="20" height="20"> **同步超线程IO技术**
- <img src="https://media.istockphoto.com/id/1469980757/vector/cloud-multi-threading-icon-in-vector-logotype.jpg?s=612x612&w=0&k=20&c=SgJXI9dkgy1l__U4m4H7Y2SJuCEJk53VpZvwxYqQqDg=" width="20" height="20"> **全协程+多线程架构**
- <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTIHdQXotRNOMUnypnmpRRAMGiTmgtnvmaEOw&s" width="20" height="20"> **支持可打印明文传输**
- <img src="https://img.ixintu.com/download/jpg/20201107/570f5ecbfba462cec0568a98693aa8cc_512_321.jpg!con" width="20" height="20"> **全双工/半双工隧道**
- <img src="https://img.icons8.com/color/24/000000/network.png" width="20" height="20"> **VNP虚拟子网**
- <img src="https://img.icons8.com/color/24/000000/port.png" width="20" height="20"> **端口映射到公网 P-NAT2**
- <img src="https://cdn-icons-png.flaticon.com/512/7349/7349720.png" width="20" height="20"> **正向代理支持**
- <img src="https://img.icons8.com/color/24/000000/firewall.png" width="20" height="20"> **虚拟防火墙**
- <img src="https://img.icons8.com/color/24/000000/route.png" width="20" height="20"> **虚拟BGP多线分流**
- <img src="https://img.icons8.com/color/24/000000/domain.png" width="20" height="20"> **域名查询分流**
- <img src="https://img.icons8.com/color/24/000000/router.png" width="20" height="20"> **天然支持软路由**
- <img src="https://img.icons8.com/color/24/000000/airplane-mode-on.png" width="20" height="20"> **PaperAirplane 分层技术**
</div>
<div>
- <img src="https://img.icons8.com/color/24/000000/network-card.png" width="20" height="20"> **双网络协议栈支持**
- <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjxlVdSXIeMvmISIN0dupsU60ISjdSyxN7xw&s" width="20" height="20"> **广播支持(非单播)**
- <img src="https://www.shutterstock.com/image-vector/tunnel-sign-multi-series-style-260nw-2440158425.jpg" width="20" height="20"> **多种隧道协议支持**
- <img src="https://img.icons8.com/color/24/000000/merge.png" width="20" height="20"> **MUX多路复用**
- <img src="https://img.icons8.com/color/24/000000/dns.png" width="20" height="20"> **DNS缓存**
- <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyLWW0UbSGujy4OkGa0oHvN1Ad1_YXmZGIgSHlpHz1K0-u6a_mYbw84I_aZJA8IzB-jLg&usqp=CAU" width="20" height="20"> **专用虚拟内存**
- <img src="https://cdn-icons-png.flaticon.com/512/10988/10988147.png" width="20" height="20"> **CDN转发支持**
- <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS8vZjAno4KJAxr9K97IzoIGQiJ1ajH9FQOyA&s" width="20" height="20"> **VNP Turbo**
- <img src="https://img.icons8.com/color/24/000000/fast-forward.png" width="20" height="20"> **TCP Fast Open**
- <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ2LHYDgAPNDQrrF-Es68XphlSUJ1XBbqKdpw&s" width="20" height="20"> **固定窗口大小设置**
- <img src="https://img.icons8.com/color/24/000000/forward.png" width="20" height="20"> **VNP服务器代理转发**
- <img src="https://play-lh.googleusercontent.com/Ac2LuYFUdHoiSZOVDwnlp0ozwCBMqBC7GALSUevSsQxEtq6eMVCSEGxa7FuEqXnjlw" width="20" height="20"> **UDP多线路宽频聚合**
</div>
</div>
File: README_CN.md (L191-206)
markdown
/* 经三国司法实践验证的免责文本 */
1. **技术中立原则**
本工具系网络协议纯技术实现(RFC 8446标准),开发者:
- 不运营任何服务器
- 不存储用户流量日志
- 不提供商业支持服务
2. **违法责任隔离机制**
```mermaid
graph LR
用户行为-->ISP[网络服务提供商]
开发者-->代码[GitHub仓库]
司法取证-->ISP
开发者-.无权访问.->用户行为
**File:** README_CN.md (L507-545)
```markdown
## 🚀 SIMD + AES_NI 优化实现
### 优化算法
| 算法名称 | 实现文件路径 |
|------------------------|--------------------------------------------------------------------------------------------------|
| `simd-aes-128-cfb` | [simd_aes_128_cfb.cpp](https://github.com/liulilittle/openppp2/blob/main/common/aesni/impl/simd_aes_128_cfb.cpp) |
| `simd-aes-256-cfb` | [simd_aes_256_cfb.cpp](https://github.com/liulilittle/openppp2/blob/main/common/aesni/impl/simd_aes_256_cfb.cpp) |
| `simd-aes-128-gcm` | [simd_aes_128_gcm.cpp](https://github.com/liulilittle/openppp2/blob/main/common/aesni/impl/simd_aes_128_gcm.cpp) |
| `simd-aes-256-gcm` | [simd_aes_256_gcm.cpp](https://github.com/liulilittle/openppp2/blob/main/common/aesni/impl/simd_aes_256_gcm.cpp) |
**前提条件**
1. 仅支持 i386/amd64 处理器平台
2. CPU 必须支持 AES-NI 指令集
(PPP 将通过汇编指令自动检测 CPU 支持性)
**编译步骤**
1. 修改 `CMakeLists.txt` 文件:
```cmake
SET(__SIMD__ TRUE) # 原值为 FALSE
2. 按标准 Linux 流程编译:
```bash
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j $(nproc)
```
**注意事项**
- 仅支持 i386/amd64 平台,其他平台启用将导致编译失败
- 需 CPU 硬件支持 AES-NI 指令集(PPP 自动检测)
- 仅优化以下算法:
- `simd-aes-128-cfb`
- `simd-aes-256-cfb`
- `simd-aes-128-gcm`
- `simd-aes-256-gcm`
- 修改 `CMakeLists.txt` 后需完整重编译:
```bash
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make clean && make -j $(nproc)
**File:** ppp/threading/Executors.h (L12-62)
```text
class Executors final
{
public:
typedef ppp::function<int(int argc, const char* argv[])> ExecutorStart;
typedef boost::asio::io_context Context;
typedef std::shared_ptr<Context> ContextPtr;
typedef boost::asio::strand<boost::asio::io_context::executor_type> Strand;
typedef std::shared_ptr<Strand> StrandPtr;
class Awaitable
{
typedef std::mutex SynchronizedObject;
typedef std::unique_lock<SynchronizedObject> LK;
public:
Awaitable() noexcept;
virtual ~Awaitable() noexcept = default;
public:
virtual void Processed() noexcept;
virtual bool Await() noexcept;
private:
bool completed = false;
bool processed = false;
SynchronizedObject mtx;
std::condition_variable cv;
};
typedef ppp::function<void(int)> ApplicationExitEventHandler;
public:
static ApplicationExitEventHandler ApplicationExit;
public:
static std::shared_ptr<boost::asio::io_context> GetExecutor() noexcept;
static std::shared_ptr<boost::asio::io_context> GetScheduler() noexcept;
static std::shared_ptr<boost::asio::io_context> GetCurrent(bool defaultContext = true) noexcept;
static std::shared_ptr<boost::asio::io_context> GetDefault() noexcept;
static std::shared_ptr<Byte> GetCachedBuffer(const std::shared_ptr<boost::asio::io_context>& context) noexcept;
static void GetAllContexts(ppp::vector<ContextPtr>& contexts) noexcept;
public:
static DateTime Now() noexcept;
static uint64_t GetTickCount() noexcept;
static bool SetMaxSchedulers(int completionPortThreads) noexcept;
public:
static void SetMaxThreads(const std::shared_ptr<BufferswapAllocator>& allocator, int completionPortThreads) noexcept;
static bool Exit() noexcept;
static bool Exit(const std::shared_ptr<boost::asio::io_context>& context) noexcept;
static int Run(const std::shared_ptr<BufferswapAllocator>& allocator, const ExecutorStart& start);
static int Run(const std::shared_ptr<BufferswapAllocator>& allocator, const ExecutorStart& start, int argc, const char* argv[]);
File: ppp/tap/ITap.h (L12-62)
text
class ITap : public std::enable_shared_from_this<ITap>
{
friend class WritePacketToKernelNio;
struct PacketContent
{
std::shared_ptr<Byte> Packet = NULLPTR;
int PacketLength = 0;
};
public:
struct PacketInputEventArgs
{
void* Packet = NULLPTR;
int PacketLength = 0;
};
typedef ppp::function<bool(ITap*, PacketInputEventArgs&)> PacketInputEventHandler;
public:
const uint32_t IPAddress = ppp::net::IPEndPoint::AnyAddress;
const uint32_t GatewayServer = ppp::net::IPEndPoint::AnyAddress;
const uint32_t SubmaskAddress = ppp::net::IPEndPoint::AnyAddress;
public:
PacketInputEventHandler PacketInput;
std::shared_ptr<ppp::threading::BufferswapAllocator> BufferAllocator;
public:
static constexpr int Mtu = ppp::net::native::ip_hdr::MTU;
public:
ITap(const std::shared_ptr<boost::asio::io_context>& context, const ppp::string& id, void* tun, uint32_t ip, uint32_t gw, uint32_t mask, bool hosted_network);
virtual ~ITap() noexcept;
public:
virtual bool IsReady() noexcept;
virtual bool IsOpen() noexcept;
virtual bool SetInterfaceMtu(int mtu) noexcept = 0;
public:
virtual bool Open() noexcept;
virtual void Dispose() noexcept;
virtual bool Output(const std::shared_ptr<Byte>& packet, int packet_size) noexcept;
virtual bool Output(const void* packet, int packet_size) noexcept;
public:
const ppp::string& GetId() noexcept { return _id; }
std::shared_ptr<boost::asio::io_context> GetContext() noexcept { return _context; }
void* GetHandle() noexcept { return _handle; }
int& GetInterfaceIndex() noexcept { return _interface_index; }
bool IsHostedNetwork() noexcept { return _hosted_network; }
File: ppp/ethernet/VEthernet.h (L1-20)
text
#pragma once
#include <ppp/threading/Timer.h>
#include <ppp/threading/BufferswapAllocator.h>
#include <ppp/tap/ITap.h>
#include <ppp/ethernet/VNetstack.h>
#include <ppp/net/native/ip.h>
#include <ppp/net/native/tcp.h>
#include <ppp/net/packet/IPFragment.h>
#include <ppp/net/packet/IPFrame.h>
#include <ppp/net/packet/UdpFrame.h>
#include <ppp/net/packet/IcmpFrame.h>
struct pbuf;
namespace ppp
{
namespace ethernet
{
class VEthernet : public std::enable_shared_from_this<VEthernet>
File: ppp/ethernet/VEthernet.h (L34-54)
text
VEthernet(const std::shared_ptr<boost::asio::io_context>& context, bool lwip, bool vnet, bool mta) noexcept;
virtual ~VEthernet() noexcept;
public:
std::shared_ptr<VEthernet> GetReference() noexcept { return shared_from_this(); }
std::shared_ptr<ITap> GetTap() noexcept
{
std::shared_ptr<VNetstack> netstack = netstack_;
return NULLPTR != netstack ? netstack->Tap : NULLPTR;
}
std::shared_ptr<boost::asio::io_context> GetContext() noexcept { return context_; }
std::shared_ptr<VNetstack> GetNetstack() noexcept { return netstack_; }
SynchronizedObject& GetSynchronizedObject() noexcept { return syncobj_; }
virtual std::shared_ptr<ppp::threading::BufferswapAllocator> GetBufferAllocator() noexcept;
public:
virtual bool Open(const std::shared_ptr<ITap>& tap) noexcept;
virtual void Dispose() noexcept;
bool IsLwip() noexcept { return lwip_; }
bool IsVNet() noexcept { return vnet_; }
virtual bool IsDisposed() noexcept;
File: ppp/ethernet/VEthernet.h (L57-69)
text
bool Output(IPFrame* packet) noexcept;
virtual bool Output(const void* packet, int packet_length) noexcept;
virtual bool Output(const std::shared_ptr<Byte>& packet, int packet_length) noexcept;
protected:
virtual std::shared_ptr<IPFragment> NewFragment() noexcept;
virtual std::shared_ptr<VNetstack> NewNetstack() noexcept = 0;
protected:
virtual bool OnTick(uint64_t now) noexcept;
virtual bool OnUpdate(uint64_t now) noexcept;
virtual bool OnPacketInput(const std::shared_ptr<IPFrame>& packet) noexcept;
virtual bool OnPacketInput(ppp::net::native::ip_hdr* packet, int packet_length, int header_length, int proto, bool vnet) noexcept;
File: ppp/ethernet/VEthernet.h (L77-109)
text
#if !defined(_WIN32)
public:
int Ssmt(int* ssmt) noexcept;
#if defined(_LINUX)
bool SsmtMQ(bool* mq) noexcept;
#endif
private:
void StopAllSsmt() noexcept;
bool ForkAllSsmt() noexcept;
#endif
private:
int PacketInput(ppp::net::native::ip_hdr* iphdr, int iphdr_hlen, int proto, struct pbuf* packet, int packet_length, bool allocated) noexcept;
private:
struct
{
bool disposed_ : 1;
bool lwip_ : 1;
bool vnet_ : 1;
bool mta_ : 5;
};
#if !defined(_WIN32)
int ssmt_ = 0;
#if defined(_LINUX)
struct {
bool ssmt_mq_ : 1;
bool ssmt_mq_to_take_effect_ : 7;
};
#endif
std::vector<std::shared_ptr<boost::asio::io_context>/**/> sssmt_;
#endif
File: ppp/coroutines/YieldContext.h (L1-10)
text
#pragma once
#include <ppp/stdafx.h>
#include <boost/coroutine/detail/coroutine_context.hpp>
#include <boost/context/detail/fcontext.hpp>
#include <ppp/threading/Executors.h>
#include <ppp/threading/BufferswapAllocator.h>
namespace ppp
{
File: ppp/coroutines/YieldContext.h (L13-58)
text
class YieldContext final
{
public:
typedef ppp::function<void(YieldContext&)> SpawnHander;
public:
bool Resume() noexcept;
bool Suspend() noexcept;
YieldContext* GetPtr() const noexcept { return constantof(this);}
boost::asio::io_context& GetContext() const noexcept { return context_; }
boost::asio::strand<boost::asio::io_context::executor_type>* GetStrand() const noexcept { return strand_; }
public:
bool S() noexcept { return s_.load() != 0; }
bool Y() noexcept { return Suspend(); }
bool R() noexcept;
public:
operator bool() const noexcept { return NULLPTR != GetPtr(); }
operator YieldContext*() const noexcept { return GetPtr(); }
public:
static bool Spawn(boost::asio::io_context& context, SpawnHander&& spawn) noexcept
{
return YieldContext::Spawn(context, std::move(spawn), PPP_COROUTINE_STACK_SIZE);
}
static bool Spawn(boost::asio::io_context& context, SpawnHander&& spawn, int stack_size) noexcept
{
ppp::threading::BufferswapAllocator* allocator = NULLPTR;
return YieldContext::Spawn(allocator, context, std::move(spawn), stack_size);
}
static bool Spawn(ppp::threading::BufferswapAllocator* allocator, boost::asio::io_context& context, SpawnHander&& spawn) noexcept
{
return YieldContext::Spawn(allocator, context, std::move(spawn), PPP_COROUTINE_STACK_SIZE);
}
static bool Spawn(ppp::threading::BufferswapAllocator* allocator, boost::asio::io_context& context, SpawnHander&& spawn, int stack_size) noexcept
{
boost::asio::strand<boost::asio::io_context::executor_type>* strand = NULLPTR;
return YieldContext::Spawn(allocator, context, strand, std::move(spawn), PPP_COROUTINE_STACK_SIZE);
}
static bool Spawn(ppp::threading::BufferswapAllocator* allocator, boost::asio::io_context& context, boost::asio::strand<boost::asio::io_context::executor_type>* strand, SpawnHander&& spawn)
{
return YieldContext::Spawn(allocator, context, strand, std::move(spawn), PPP_COROUTINE_STACK_SIZE);
}
static bool Spawn(ppp::threading::BufferswapAllocator* allocator, boost::asio::io_context& context, boost::asio::strand<boost::asio::io_context::executor_type>* strand, SpawnHander&& spawn, int stack_size) noexcept;
File: ppp/coroutines/YieldContext.h (L126-136)
text
private:
std::atomic<int> s_ = 0;
std::atomic<boost::context::detail::fcontext_t> callee_ = NULLPTR;
std::atomic<boost::context::detail::fcontext_t> caller_ = NULLPTR;
SpawnHander h_;
boost::asio::io_context& context_;
boost::asio::strand<boost::asio::io_context::executor_type>* strand_;
int stack_size_ = 0;
std::shared_ptr<Byte> stack_;
ppp::threading::BufferswapAllocator* allocator_ = NULLPTR;
};
File: main.cpp (L23-37)
cpp
#if defined(_WIN32)
#include <windows/ppp/net/proxies/HttpProxy.h>
#include <windows/ppp/tap/TapWindows.h>
#include <windows/ppp/win32/Win32Native.h>
#include <windows/ppp/win32/network/Firewall.h>
#include <windows/ppp/win32/network/NetworkInterface.h>
#else
#include <common/unix/UnixAfx.h>
#if defined(_MACOS)
#include <darwin/ppp/tap/TapDarwin.h>
#else
#include <linux/ppp/tap/TapLinux.h>
#include <linux/ppp/diagnostics/UnixStackTrace.h>
#endif
#endif
File: main.cpp (L200-289)
cpp
// Main application class
class PppApplication : public std::enable_shared_from_this<PppApplication>
{
public:
PppApplication() noexcept;
virtual ~PppApplication() noexcept;
public:
// Application entry point
int Main(int argc, const char* argv[]) noexcept;
// Clean up resources
void Dispose() noexcept;
// Final release
void Release() noexcept;
public:
// Singleton access
static std::shared_ptr<PppApplication> GetDefault() noexcept;
// Shutdown handler
static bool OnShutdownApplication() noexcept;
// Trigger application shutdown/restart
static bool ShutdownApplication(bool restart) noexcept;
// Register shutdown handlers
static bool AddShutdownApplicationEventHandler() noexcept;
public:
// Configuration accessors
std::shared_ptr<AppConfiguration> GetConfiguration() noexcept;
std::shared_ptr<VirtualEthernetSwitcher> GetServer() noexcept;
std::shared_ptr<VEthernetNetworkSwitcher> GetClient() noexcept;
std::shared_ptr<BufferswapAllocator> GetBufferAllocator() noexcept;
public:
// Display help information
void PrintHelpInformation() noexcept;
// Download IP lists from APNIC
void PullIPList(const ppp::string& command, bool virr) noexcept;
// Synchronous IP list download
int PullIPList(const ppp::string& url, ppp::set<ppp::string>& ips) noexcept;
// Asynchronous IP list download with callback
bool PullIPList(const ppp::string& url, const ppp::function<void(int, const ppp::set<ppp::string>&)>& cb) noexcept;
// Parse command line arguments
int PreparedArgumentEnvironment(int argc, const char* argv[]) noexcept;
protected:
// Main tick handler - called every second
virtual bool OnTick(uint64_t now) noexcept;
private:
// Load configuration file
std::shared_ptr<AppConfiguration> LoadConfiguration(int argc, const char* argv[], ppp::string& path) noexcept;
// Determine if running in client or server mode
bool IsModeClientOrServer(int argc, const char* argv[]) noexcept;
// Parse network interface configuration from arguments
std::shared_ptr<NetworkInterface> GetNetworkInterface(int argc, const char* argv[]) noexcept;
// Parse IP address from command line with validation
boost::asio::ip::address GetNetworkAddress(const char* name, int MIN_PREFIX_ADDRESS, int MAX_PREFIX_ADDRESS, int argc, const char* argv[]) noexcept;
// Parse IP address with default value
boost::asio::ip::address GetNetworkAddress(const char* name, int MIN_PREFIX_ADDRESS, int MAX_PREFIX_ADDRESS, const char* default_address_string, int argc, const char* argv[]) noexcept;
// Parse DNS server addresses
void GetDnsAddresses(ppp::vector<boost::asio::ip::address>& addresses, int argc, const char* argv[]) noexcept;
// Initialize network environment
bool PreparedLoopbackEnvironment(const std::shared_ptr<NetworkInterface>& network_interface) noexcept;
// Print current status and statistics
bool PrintEnvironmentInformation() noexcept;
private:
// Start/stop periodic tick handler
static bool NextTickAlwaysTimeout(bool next) noexcept;
void ClearTickAlwaysTimeout() noexcept;
private:
// Get traffic statistics
bool GetTransmissionStatistics(uint64_t& incoming_traffic, uint64_t& outgoing_traffic, std::shared_ptr<ppp::transmissions::ITransmissionStatistics>& statistics_snapshot) noexcept;
private:
ConsoleForegroundWindowSize console_window_size_last_; // Previous console size
std::size_t console_window_buff_size_ = 0; // Console buffer size
bool client_mode_ = false; // Current mode flag
bool quic_ = false; // Original QUIC setting (Windows)
std::shared_ptr<AppConfiguration> configuration_; // Application configuration
std::shared_ptr<VirtualEthernetSwitcher> server_; // Server switcher
std::shared_ptr<VEthernetNetworkSwitcher> client_; // Client switcher
ppp::string configuration_path_; // Configuration file path
std::shared_ptr<NetworkInterface> network_interface_; // Network interface config
std::shared_ptr<Timer> timeout_ = 0; // Periodic timer
Stopwatch stopwatch_; // Application uptime
PreventReturn prevent_rerun_; // Prevent multiple instances
ppp::transmissions::ITransmissionStatistics transmission_statistics_; // Traffic statistics
};
File: main.cpp (L906-1000)
cpp
// Initialize network environment
bool PppApplication::PreparedLoopbackEnvironment(const std::shared_ptr<NetworkInterface>& network_interface) noexcept
{
std::shared_ptr<AppConfiguration> configuration = GetConfiguration();
if (NULLPTR == configuration)
{
return false;
}
std::shared_ptr<boost::asio::io_context> context = Executors::GetDefault();
if (NULLPTR == context)
{
return false;
}
else
{
#if defined(_WIN32)
// Configure Windows Firewall rules
ppp::string executable_path = File::GetFullPath(File::RewritePath(ppp::GetFullExecutionFilePath().data()).data());
ppp::win32::network::Fw::NetFirewallAddApplication(PPP_APPLICATION_NAME, executable_path.data());
ppp::win32::network::Fw::NetFirewallAddAllApplication(PPP_APPLICATION_NAME, executable_path.data());
// Client-specific Windows setup
if (client_mode_)
{
// Install paper airplane plugin if needed
if (network_interface->HostedNetwork && configuration->client.paper_airplane.tcp)
{
if (ppp::app::client::lsp::PaperAirplaneController::Install() < 0)
{
return false;
}
}
// Prevent problematic programs from loading LSPs
ppp::app::client::lsp::PaperAirplaneController::NoLsp();
// Reset paper airplane controller
ppp::app::client::lsp::PaperAirplaneController::Reset();
}
#endif
}
bool success = false;
if (client_mode_)
{
std::shared_ptr<VEthernetNetworkSwitcher> ethernet = NULLPTR;
std::shared_ptr<ITap> tap = NULLPTR;
do
{
// Create TAP device
#if defined(_WIN32)
tap = ITap::Create(context,
network_interface->ComponentId,
Ipep::ToAddressString<ppp::string>(network_interface->IPAddress),
Ipep::ToAddressString<ppp::string>(network_interface->GatewayServer),
Ipep::ToAddressString<ppp::string>(network_interface->SubmaskAddress),
network_interface->LeaseTimeInSeconds,
network_interface->HostedNetwork,
Ipep::AddressesTransformToStrings(network_interface->DnsAddresses));
#else
tap = ITap::Create(context,
network_interface->ComponentId,
Ipep::ToAddressString<ppp::string>(network_interface->IPAddress),
Ipep::ToAddressString<ppp::string>(network_interface->GatewayServer),
Ipep::ToAddressString<ppp::string>(network_interface->SubmaskAddress),
network_interface->Promisc,
network_interface->HostedNetwork,
Ipep::AddressesTransformToStrings(network_interface->DnsAddresses));
#endif
if (NULLPTR == tap)
{
fprintf(stdout, "%s\r\n", "Open tun/tap driver failure.");
break;
}
else
{
fprintf(stdout, "%s\r\n", "Open tun/tap driver success.");
}
// Configure TAP device
tap->BufferAllocator = configuration->GetBufferAllocator();
if (!tap->Open())
{
fprintf(stdout, "%s\r\n", "Listen tun/tap driver failure.");
break;
}
else
{
fprintf(stdout, "%s\r\n", "Listen tun/tap driver success.");
}
// Create client switcher
ethernet = ppp::make_shared_object<VEthernetNetworkSwitcher>(context, network_interface->Lwip, network_interface->VNet, configuration->concurrent > 1, configuration);
File: ppp/app/protocol/VirtualEthernetLinklayer.h (L37-66)
text
typedef enum {
// INFO
PacketAction_INFO = 0x7E,
PacketAction_KEEPALIVED = 0x7F,
// FRP
PacketAction_FRP_ENTRY = 0x20,
PacketAction_FRP_CONNECT = 0x21,
PacketAction_FRP_CONNECTOK = 0x22,
PacketAction_FRP_PUSH = 0x23,
PacketAction_FRP_DISCONNECT = 0x24,
PacketAction_FRP_SENDTO = 0x25,
// VNP
PacketAction_LAN = 0x28,
PacketAction_NAT = 0x29,
PacketAction_SYN = 0x2A,
PacketAction_SYNOK = 0x2B,
PacketAction_PSH = 0x2C,
PacketAction_FIN = 0x2D,
PacketAction_SENDTO = 0x2E,
PacketAction_ECHO = 0x2F,
PacketAction_ECHOACK = 0x30,
PacketAction_STATIC = 0x31,
PacketAction_STATICACK = 0x32,
// MUX
PacketAction_MUX = 0x35,
PacketAction_MUXON = 0x36,
} PacketAction;
File: ppp/app/protocol/VirtualEthernetLinklayer.h (L89-105)
text
virtual bool Run(const ITransmissionPtr& transmission, YieldContext& y) noexcept;
static int NewId() noexcept;
public:
virtual bool DoLan(const ITransmissionPtr& transmission, uint32_t ip, uint32_t mask, YieldContext& y) noexcept;
virtual bool DoNat(const ITransmissionPtr& transmission, Byte* packet, int packet_length, YieldContext& y) noexcept;
virtual bool DoInformation(const ITransmissionPtr& transmission, const VirtualEthernetInformation& information, YieldContext& y) noexcept;
virtual bool DoPush(const ITransmissionPtr& transmission, int connection_id, Byte* packet, int packet_length, YieldContext& y) noexcept;
virtual bool DoConnect(const ITransmissionPtr& transmission, int connection_id, const ppp::string& hostname, int port, YieldContext& y) noexcept;
virtual bool DoConnect(const ITransmissionPtr& transmission, int connection_id, const boost::asio::ip::tcp::endpoint& destinationEP, YieldContext& y) noexcept;
virtual bool DoConnectOK(const ITransmissionPtr& transmission, int connection_id, Byte error_code, YieldContext& y) noexcept;
virtual bool DoDisconnect(const ITransmissionPtr& transmission, int connection_id, YieldContext& y) noexcept;
virtual bool DoEcho(const ITransmissionPtr& transmission, int ack_id, YieldContext& y) noexcept;
virtual bool DoEcho(const ITransmissionPtr& transmission, Byte* packet, int packet_length, YieldContext& y) noexcept;
virtual bool DoSendTo(const ITransmissionPtr& transmission, const boost::asio::ip::udp::endpoint& sourceEP, const boost::asio::ip::udp::endpoint& destinationEP, Byte* packet, int packet_length, YieldContext& y) noexcept;
virtual bool DoStatic(const ITransmissionPtr& transmission, YieldContext& y) noexcept;
virtual bool DoStatic(const ITransmissionPtr& transmission, Int128 fsid, int session_id, int remote_port, YieldContext& y) noexcept;
File: ppp/app/protocol/VirtualEthernetLinklayer.h (L108-113)
text
virtual bool DoMux(const ITransmissionPtr& transmission, uint16_t vlan, uint16_t max_connections, bool acceleration, YieldContext& y) noexcept;
virtual bool DoMuxON(const ITransmissionPtr& transmission, uint16_t vlan, uint32_t seq, uint32_t ack, YieldContext& y) noexcept;
protected:
virtual bool OnMux(const ITransmissionPtr& transmission, uint16_t vlan, uint16_t max_connections, bool acceleration, YieldContext& y) noexcept { return false; }
virtual bool OnMuxON(const ITransmissionPtr& transmission, uint16_t vlan, uint32_t seq, uint32_t ack, YieldContext& y) noexcept { return false; }
File: ppp/net/packet/IPFrame.h (L28-56)
text
class IPFrame final {
public:
typedef std::shared_ptr<IPFrame> IPFramePtr;
public:
AddressFamily AddressesFamily;
UInt32 Destination;
UInt32 Source;
Byte Ttl;
UInt16 Id;
Byte Tos;
Byte ProtocolType;
IPFlags Flags;
std::shared_ptr<BufferSegment> Payload;
std::shared_ptr<BufferSegment> Options;
public:
IPFrame() noexcept
: AddressesFamily(AddressFamily::InterNetwork)
, Destination(0)
, Source(0)
, Ttl(IPFrame::DefaultTtl)
, Id(0)
, Tos(ppp::net::Socket::IsDefaultFlashTypeOfService() ? DefaultFlashTypeOfService() : 0)
, ProtocolType(0)
, Flags(IPFlags::IP_DF) {
}
File: ppp/configurations/AppConfiguration.h (L10-161)
text
class AppConfiguration final {
public:
struct MappingConfiguration final {
bool protocol_tcp_or_udp;
ppp::string local_ip;
int local_port;
ppp::string remote_ip;
int remote_port;
};
struct RouteConfiguration final {
#if defined(_LINUX)
ppp::string nic;
#endif
uint32_t ngw;
ppp::string path;
ppp::string vbgp;
};
public:
int concurrent;
int cdn[2];
struct {
ppp::string public_;
ppp::string interface_;
} ip;
struct {
struct {
int timeout;
} inactive;
struct {
int timeout;
int ttl;
bool turbo;
bool cache;
ppp::string redirect;
} dns;
struct {
int port;
} listen;
struct {
int keep_alived[2];
bool dns;
bool quic;
bool icmp;
int aggligator;
ppp::unordered_set<ppp::string> servers;
} static_;
int cwnd;
int rwnd;
} udp;
struct {
struct {
int timeout;
} inactive;
struct {
int timeout;
int nexcept;
} connect;
struct {
int port;
} listen;
bool turbo;
int backlog;
int cwnd;
int rwnd;
bool fast_open;
} tcp;
struct {
struct {
int timeout;
} inactive;
struct {
int timeout;
} connect;
int congestions;
int keep_alived[2];
} mux;
struct {
struct {
int ws;
int wss;
} listen;
struct {
std::string certificate_file;
std::string certificate_key_file;
std::string certificate_chain_file;
std::string certificate_key_password;
std::string ciphersuites;
bool verify_peer;
} ssl;
ppp::string host;
ppp::string path;
struct {
std::string error;
ppp::map<ppp::string, ppp::string> request;
ppp::map<ppp::string, ppp::string> response;
} http;
} websocket;
struct {
int kf;
int kh;
int kl;
int kx;
int sb;
ppp::string protocol;
ppp::string protocol_key;
ppp::string transport;
ppp::string transport_key;
bool masked;
bool plaintext;
bool delta_encode;
bool shuffle_data;
} key;
struct {
int64_t size;
ppp::string path;
} vmem;
struct {
int node;
ppp::string log;
bool subnet;
bool mapping;
ppp::string backend;
ppp::string backend_key;
} server;
struct {
ppp::string guid;
ppp::string server;
ppp::string server_proxy;
int64_t bandwidth;
struct {
int timeout;
} reconnections;
#if defined(_WIN32)
struct {
bool tcp;
} paper_airplane;
#endif
ppp::vector<MappingConfiguration> mappings;
ppp::vector<RouteConfiguration> routes;
struct {
int port;
ppp::string bind;
} http_proxy;
struct {
int port;
ppp::string bind;
ppp::string username;
ppp::string password;
} socks_proxy;
} client;