|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +**wsnet** is a cross-platform C++17 networking library for Windscribe VPN clients (Windows/Mac/Linux/Android/iOS). It provides unified access to Windscribe's server APIs with built-in anti-censorship bypass methods, along with DNS resolution, HTTP networking, and ping functionality. |
| 8 | + |
| 9 | +The library uses: |
| 10 | +- **Boost.ASIO** for async I/O (single io_context thread model) |
| 11 | +- **libcurl** (with ECH patches) for HTTP requests |
| 12 | +- **c-ares** for asynchronous DNS resolution |
| 13 | +- **OpenSSL** (with ECH patches) for TLS |
| 14 | +- **Scapix** for automatic C++ → Java/Swift bindings on mobile platforms |
| 15 | +- **vcpkg** for dependency management |
| 16 | + |
| 17 | +## Building |
| 18 | + |
| 19 | +### Desktop (Windows/Mac/Linux) |
| 20 | + |
| 21 | +The library integrates via vcpkg. CMake must be installed along with platform-specific C++ compiler (Visual C++/XCode/clang). |
| 22 | + |
| 23 | +**Build with tests (desktop only):** |
| 24 | +```bash |
| 25 | +cmake -B build -S . \ |
| 26 | + -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \ |
| 27 | + -DIS_BUILD_TESTS=ON |
| 28 | +cmake --build build |
| 29 | +``` |
| 30 | + |
| 31 | +**Run tests:** |
| 32 | +```bash |
| 33 | +./build/test/wsnet_test |
| 34 | +``` |
| 35 | + |
| 36 | +Tests use Google Test and are located in `src/private/tests/`. Tests are only built when `IS_BUILD_TESTS` is defined and are excluded from mobile builds. |
| 37 | + |
| 38 | +### Android |
| 39 | + |
| 40 | +**Requirements:** Android Studio, `$VCPKG_ROOT` and `$JAVA_HOME` environment variables set. |
| 41 | + |
| 42 | +```bash |
| 43 | +cd tools |
| 44 | +./build_android.sh |
| 45 | +``` |
| 46 | + |
| 47 | +Output: `wsnet.aar` (Android Archive ready for integration) |
| 48 | + |
| 49 | +### iOS |
| 50 | + |
| 51 | +**Requirements:** XCode, `$VCPKG_ROOT` environment variable set. |
| 52 | + |
| 53 | +```bash |
| 54 | +cd tools |
| 55 | +./build_ios.sh |
| 56 | +``` |
| 57 | + |
| 58 | +Output: `build/WSNet.xcframework` (supports iOS, iOS Simulator, tvOS, tvOS Simulator) |
| 59 | + |
| 60 | +## Architecture |
| 61 | + |
| 62 | +### Core Components |
| 63 | + |
| 64 | +The library is accessed through a singleton `WSNet::instance()` after initialization. Main components: |
| 65 | + |
| 66 | +- **ServerAPI** - Main Windscribe API access (login, session, server locations, WireGuard configs, etc.) with full failover support |
| 67 | +- **BridgeAPI** - Legacy Bridge protocol API (IP rotation, simple session-based, no failover) |
| 68 | +- **DnsResolver** - Async DNS with custom server support and caching |
| 69 | +- **HttpNetworkManager** - HTTP client with custom DNS integration and TLS modifications (SNI spoofing, ECH) |
| 70 | +- **EmergencyConnect** - Fallback connectivity via hardcoded OpenVPN endpoints |
| 71 | +- **PingManager** - ICMP and HTTP ping functionality |
| 72 | +- **DecoyTraffic** - Traffic obfuscation features |
| 73 | +- **ApiResourcesManager** - Manages API resources like server lists |
| 74 | + |
| 75 | +All async operations return `shared_ptr<WSNetCancelableCallback>` for cancellation and use callback pattern. |
| 76 | + |
| 77 | +### Public/Private Build System |
| 78 | + |
| 79 | +The codebase has a **dual-build configuration**: |
| 80 | + |
| 81 | +- **`src/private/`** - Production build with proprietary censorship bypass methods (16+ failover strategies including ECH, CDN fronting, dynamic domains). Contains `privatesettings.h` with hardcoded (obfuscated) endpoints and credentials. |
| 82 | + |
| 83 | +- **`src/public/`** - Open-source fallback with minimal failover (only hardcoded domains). |
| 84 | + |
| 85 | +CMake automatically selects private if it exists, otherwise uses public. Both implement the same `IFailoverContainer` interface. |
| 86 | + |
| 87 | +### Failover Mechanism |
| 88 | + |
| 89 | +ServerAPI uses a **hierarchical failover system** to bypass censorship: |
| 90 | + |
| 91 | +1. Each request goes through `RequestExecutorViaFailover` |
| 92 | +2. Tries failovers sequentially (tracked by UUID to prevent loops) |
| 93 | +3. Each `BaseFailover` returns `FailoverData` containing: |
| 94 | + - `domain` - Target domain |
| 95 | + - `sniDomain` - SNI for domain fronting |
| 96 | + - `echConfig` - Encrypted Client Hello configuration |
| 97 | + - `ttl` - Time-to-live for dynamic failovers |
| 98 | +4. If all failovers fail → returns `ApiRetCode::kFailoverFailed` |
| 99 | + |
| 100 | +Failover types (private build): hardcoded domains → ECH with Cloudflare → dynamic Cloudflare → dynamic Google DoH → direct IP access → CDN fronting (Fastly/Yelp/PyPI). |
| 101 | + |
| 102 | +### Mobile Bindings (Scapix) |
| 103 | + |
| 104 | +For Android/iOS builds, Scapix automatically generates Java/Swift bindings from C++ headers: |
| 105 | + |
| 106 | +- All public headers in `include/wsnet/WSNet*.h` are bridged |
| 107 | +- Each header must contain exactly one class matching the filename (Java requirement) |
| 108 | +- All public classes inherit from `scapix_object<T>` (empty on desktop, actual bridge on mobile) |
| 109 | +- Generated code: `generated/bridge/java/com/wsnet/lib/` (Android) or `generated/bridge/objc/` (iOS) |
| 110 | + |
| 111 | +Android-specific: Custom JNI with thread auto-attach and class loader caching. |
| 112 | + |
| 113 | +iOS-specific: Builds as framework with Objective-C bridge headers. |
| 114 | + |
| 115 | +### Threading Model |
| 116 | + |
| 117 | +- Single worker thread runs Boost.ASIO `io_context` |
| 118 | +- All callbacks dispatched to this thread |
| 119 | +- Thread-safe from client perspective (can call from any thread) |
| 120 | +- Protected by mutexes where needed (e.g., `PersistentSettings`) |
| 121 | + |
| 122 | +### Key Patterns |
| 123 | + |
| 124 | +1. **Pimpl** - Public interfaces delegate to `*_impl` classes for ABI stability |
| 125 | +2. **Async callbacks** - All I/O returns cancelable callbacks with guaranteed invocation (unless canceled) |
| 126 | +3. **Request queueing** - ServerAPI queues requests during failover attempts |
| 127 | +4. **Persistent state** - Client must save/restore settings via `serverAPI()->currentSettings()` for optimal failover performance |
| 128 | +5. **State management** - `ConnectState` tracks device online/offline and VPN connection status |
| 129 | + |
| 130 | +## Common Development Tasks |
| 131 | + |
| 132 | +### Adding a new ServerAPI endpoint |
| 133 | + |
| 134 | +1. Add method signature to `include/wsnet/WSNetServerAPI.h` |
| 135 | +2. Implement in `src/api/serverapi/serverapi_impl.h` and `.cpp` |
| 136 | +3. Create a `Request` subclass (e.g., `MyIPRequest`) that inherits from `BaseRequest` |
| 137 | +4. Override `getUrl()`, `getPlatformNamePostfix()`, and optionally `execute()` |
| 138 | +5. Use `RequestExecutorViaFailover` helper for automatic failover handling |
| 139 | + |
| 140 | +### Running a single test |
| 141 | + |
| 142 | +Tests are Google Test based: |
| 143 | + |
| 144 | +```bash |
| 145 | +./build/test/wsnet_test --gtest_filter=TestSuiteName.TestName |
| 146 | +``` |
| 147 | + |
| 148 | +Test files are in `src/private/tests/` and named `*.test.cpp`. |
| 149 | + |
| 150 | +### Code Coverage |
| 151 | + |
| 152 | +Coverage is enabled automatically when building with tests on non-Windows platforms: |
| 153 | + |
| 154 | +```bash |
| 155 | +# Build with coverage |
| 156 | +cmake -B build -S . -DIS_BUILD_TESTS=ON \ |
| 157 | + -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake |
| 158 | +cmake --build build |
| 159 | + |
| 160 | +# Run tests |
| 161 | +./build/test/wsnet_test |
| 162 | + |
| 163 | +# Generate coverage report (requires lcov) |
| 164 | +lcov --capture --directory build --output-file coverage.info |
| 165 | +lcov --remove coverage.info '/usr/*' --output-file coverage.info # Remove system files |
| 166 | +genhtml coverage.info --output-directory coverage_report |
| 167 | +``` |
| 168 | + |
| 169 | +## Important Constraints |
| 170 | + |
| 171 | +### ServerAPI State Management |
| 172 | + |
| 173 | +Clients **must**: |
| 174 | +1. Call `serverAPI()->setConnectivityState(bool)` when device connectivity changes |
| 175 | +2. Call `serverAPI()->setIsConnectedToVpnState(bool)` when VPN state changes |
| 176 | +3. Save `serverAPI()->currentSettings()` to persistent storage before shutdown |
| 177 | +4. Restore settings via `WSNet::initialize(..., serverApiSettings)` on startup |
| 178 | + |
| 179 | +This enables the library to remember the last working failover method for faster recovery. |
| 180 | + |
| 181 | +### Request Behavior |
| 182 | + |
| 183 | +- Requests can be called from any thread in any order |
| 184 | +- Callbacks are **always** invoked unless explicitly canceled |
| 185 | +- Callback timing is unpredictable (can be long during failover attempts) |
| 186 | +- Return codes: |
| 187 | + - `kSuccess = 0` - JSON data is valid and usable |
| 188 | + - `kNetworkError = 1`, `kNoNetworkConnection = 2` - Retry recommended |
| 189 | + - `kFailoverFailed = 3` - All bypass methods failed; recommend user enable "ignore SSL errors" |
| 190 | + |
| 191 | +### Public Headers |
| 192 | + |
| 193 | +When adding new public APIs: |
| 194 | +- Filename must start with `WSNet` prefix |
| 195 | +- Filename must match class name exactly (e.g., `WSNetFoo.h` → `class WSNetFoo`) |
| 196 | +- Must be in `include/wsnet/` directory |
| 197 | +- Must inherit from `scapix_object<ClassName>` for mobile compatibility |
| 198 | + |
| 199 | +## File Locations |
| 200 | + |
| 201 | +- **Public API**: `include/wsnet/WSNet*.h` |
| 202 | +- **Implementation**: `src/api/`, `src/httpnetworkmanager/`, `src/dnsresolver/`, etc. |
| 203 | +- **Failover logic**: `src/private/failover/` or `src/public/failover/` |
| 204 | +- **Tests**: `src/private/tests/*.test.cpp` |
| 205 | +- **Resources**: `resources/` (embedded via CMakeRC as `wsnet::rc`) |
| 206 | +- **Build scripts**: `tools/build_android.sh`, `tools/build_ios.sh` |
| 207 | + |
| 208 | +## Dependencies (vcpkg) |
| 209 | + |
| 210 | +Main dependencies managed via vcpkg: |
| 211 | +- `c-ares` - DNS resolution |
| 212 | +- `curl` - HTTP (with ECH patches from private vcpkg registry) |
| 213 | +- `openssl` - TLS (with ECH patches from private vcpkg registry) |
| 214 | +- `spdlog` - Logging |
| 215 | +- `rapidjson` - JSON parsing |
| 216 | +- `skyr-url` - URL parsing |
| 217 | +- `boost-filesystem` - File operations |
| 218 | +- `gtest` - Testing |
| 219 | +- `scapix` - Mobile bindings (Android/iOS only) |
| 220 | +- `cmakerc` - Resource embedding |
| 221 | + |
| 222 | +Custom patches for curl/openssl are in the private vcpkg registry: `ws/client/client-libs/ws-vcpkg-registry.git` |
0 commit comments