Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,4 @@ FptnLib/build*
.env.local.bak.*
.gh_secrets.bak.*
secrets/*
**/Cpp/fptn_native_lib.build-manifest.json
23 changes: 12 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Codex (Codex.ai/code) when working with code in t

## Project Overview

FptnVPN is an iOS VPN client app that connects to FPTN servers. It uses a pre-built C++ native framework (`fptn_native_lib.framework`) for HTTPS and WebSocket communication, wrapped through an Objective-C++ bridge layer.
FptnVPN is an iOS VPN client app that connects to FPTN servers. It uses a pre-built C++ native framework (`fptn_native_lib.framework`) for HTTPS and WebSocket communication, accessed via Swift C++ interop (C++23, `SWIFT_OBJC_INTEROP_MODE: objcxx`).

## Build

Expand Down Expand Up @@ -57,8 +57,8 @@ Open `FptnVPN.xcodeproj` in Xcode. Tests are in `FptnVPNTests` (Swift Testing fr

### App Targets

- **FptnVPN** — Main SwiftUI app. Bundle ID: `org.fptn.FptnVPN`
- **FptnVPNTunnel** — `NEAppProxyProvider` network extension. Bundle ID: `org.fptn.FptnVPN.FptnVPNTunnel`. Currently a stub — VPN traffic is handled in the main app via WebSocket.
- **FptnVPN** — Main SwiftUI app. Bundle ID: `net.mrmidi.FptnVPN`
- **FptnVPNTunnel** — `NEPacketTunnelProvider` network extension. Bundle ID: `net.mrmidi.FptnVPN.FptnVPNTunnel`. Handles VPN traffic via WebSocket through the native C++ bridge.
- **FptnLib** — C++ shared library (`fptn_native_lib.framework`). Built with CMake/Conan; not a Swift package.

### Authentication & Token Format
Expand All @@ -75,15 +75,16 @@ Users receive a token from `@fptn_bot` (Telegram). Token format: `fptn:<base64-e

### C++ Bridge Layer

The native library is accessed through a two-level bridge:
The native library is accessed through Swift C++ interop (no Objective-C++ `.mm` files). C++ classes are imported via bridging headers and used directly from Swift:

- **Obj-C++ layer** (`FptnVPN/Cpp/Bridges/*.mm`): wraps C API from `fptn_native_lib` headers
- `HttpsClientBridge.mm` — wraps `WrapperHttpsClientBridge.h`
- `WebsocketClientBridge.mm` — wraps `WrapperWebsocketClientBridge.h`
- **Swift wrapper layer** (`FptnVPN/Cpp/Wrappers/*.swift`): exposes Obj-C++ classes to Swift
- `HttpsClientSwift.swift` — thin Swift class over the Obj-C `HttpsClientSwift`
- `WebScoketClientBridge.swift` — Swift `WebsocketClientBridge` + private `NativeWebsocketClientBridge`
- **Bridging header**: `FptnVPN/Cpp/FptnVPN-Bridging-Header.h` imports framework headers
- **C++ classes** (compiled into `fptn_native_lib.framework`):
- `SwiftApiClient` (`FptnLib/src/https/SwiftApiClient.h`) — HTTPS API client
- `WebsocketSwiftBridge` (`FptnLib/src/websocket/WrapperWebsocketClientBridge.h`) — WebSocket transport with C function-pointer callbacks
- **Swift wrapper layer** (`FptnVPN/Cpp/Wrappers/*.swift`, `FptnVPNTunnel/Cpp/*.swift`):
- `ApiClientBridge.swift` — Swift wrapper over `SwiftApiClient`
- `WebScoketClientBridge.swift` — Swift `WebsocketClientBridge` wrapping `WebsocketSwiftBridge`, passes `Unmanaged` context pointers for C callbacks
- **Bridging headers**: `FptnVPN/Cpp/FptnVPN-Bridging-Header.h` (app), `FptnVPNTunnel/Cpp/FptnVPNTunnel-Bridging-Header.h` (tunnel) — `#include` the C++ headers from the framework
- Both C++ classes are annotated `SWIFT_NONCOPYABLE` (move-only, imported as `~Copyable` in Swift)

### Key Models

Expand Down
45 changes: 23 additions & 22 deletions FptnLib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
cmake_minimum_required(VERSION 3.16)
project(fptn_native_lib VERSION 1.0.0 LANGUAGES CXX C)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Ensure C++20 even if Conan's toolchain tries to override
add_compile_options(-std=c++20)
# PR0: C++23 across the stack. Aligned with Conan profiles
# (compiler.cppstd=23) and the fptn submodule (C++23 + YAFF patch).
add_compile_options(-std=c++23)

# Platform-specific deployment target defaults
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
Expand All @@ -29,19 +30,22 @@ add_compile_definitions(FPTN_IP_ADDRESS_WITHOUT_PCAP)

# include(${CMAKE_BINARY_DIR}/build/generators/conan_toolchain.cmake)

# Dependencies and compile options
add_definitions(
-DNDEBUG
-DO3
-DWSP_GGML_USE_CPU
-DWSP_GGML_USE_ACCELERATE
-DWSP_GGML_USE_METAL
-DWSP_GGML_METAL_USE_BF16
)
# PR0: removed -DO3 (was a preprocessor macro, not an optimization flag),
# all WSP_GGML_* defines (zero references in any source file — vestigial
# from an unrelated whisper project), and the arm64 WSP_GGML_CPU_GENERIC.
# -DNDEBUG is now configuration-specific: disabled in Debug so assertions
# remain active during development.
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions(-DNDEBUG)
endif()

if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
add_definitions(-DWSP_GGML_CPU_GENERIC)
endif ()
# PR0: size-oriented flags for MinSizeRel/Release iOS builds.
# -Oz minimises code size; -ffunction-sections/-fdata-sections +
# -Wl,-dead_strip let the linker discard unreferenced code and data.
if(CMAKE_BUILD_TYPE STREQUAL "MinSizeRel" OR CMAKE_BUILD_TYPE STREQUAL "Release")
add_compile_options(-Oz -ffunction-sections -fdata-sections)
add_link_options(-Wl,-dead_strip)
endif()

# Find packages
find_package(fptn REQUIRED)
Expand All @@ -58,24 +62,21 @@ add_library(fptn_native_lib SHARED
src/websocket/WrapperWebsocketClientBridge.cpp src/websocket/WrapperWebsocketClientBridge.h
)

target_compile_features(fptn_native_lib PRIVATE cxx_std_20)
target_compile_features(fptn_native_lib PRIVATE cxx_std_23)
target_compile_definitions(fptn_native_lib PRIVATE
BOOST_ASIO_HAS_CO_AWAIT
BOOST_ASIO_HAS_CO_SPAWN
BOOST_ASIO_HAS_COROUTINES
)

# Link required frameworks
# PR0: removed -framework Accelerate, Metal, MetalKit (zero references
# in any source file) and duplicate raw -lssl/-lcrypto (OpenSSL::SSL and
# OpenSSL::Crypto already resolve to BoringSSL via Conan).
target_link_libraries(fptn_native_lib PRIVATE
"-framework Accelerate"
"-framework Foundation"
"-framework Metal"
"-framework MetalKit"
fptn::fptn
OpenSSL::SSL
OpenSSL::Crypto
"-lssl"
"-lcrypto"
)

file(GLOB_RECURSE ALL_HEADERS
Expand Down
9 changes: 4 additions & 5 deletions FptnLib/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ def build_requirements(self):

def generate(self):
tc = CMakeToolchain(self)
# Force C++20 — upstream fptn uses coroutines (co_await/co_return)
# and abseil requires std::partial_ordering (C++20). CMake's
# variable_watch can't prevent CMakeLists.txt from overriding
# CMAKE_CXX_STANDARD via set(), so we inject -std=c++20 into the
# C compiler flags that Conan generates and remove the watch.
# PR0: CMakeLists.txt sets -std=c++23, aligned with Conan
# profiles (compiler.cppstd=23) and the fptn submodule.
# Remove Conan's cmake_std_management block so it does not fight
# the explicit standard selection in CMakeLists.txt.
try:
tc.blocks.remove("cmake_std_management")
except KeyError:
Expand Down
5 changes: 4 additions & 1 deletion FptnLib/src/https/SwiftApiClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ Distributed under the MIT License (https://opensource.org/licenses/MIT)
#include <string>
#include <cstdint>
#include <stdbool.h>
#include <swift/bridging>

namespace fptn::protocol::https { class ApiClient; }

class SwiftApiClient {
// PR0: SWIFT_NONCOPYABLE makes Swift import this as ~Copyable,
// removing the implicitly-unwrapped-optional workaround in Swift wrappers.
class SWIFT_NONCOPYABLE SwiftApiClient {
public:
struct Response {
std::string body;
Expand Down
5 changes: 4 additions & 1 deletion FptnLib/src/websocket/WrapperWebsocketClientBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Distributed under the MIT License (https://opensource.org/licenses/MIT)
#include <stdbool.h>
#include <stdint.h>
#include <string>
#include <swift/bridging>

// Forward declaration of internal wrapper implementation
struct WebsocketClientWrapper;
Expand All @@ -30,7 +31,9 @@ struct WebsocketClientBridgeStatus {
bool in_packet_callback;
};

class WebsocketSwiftBridge {
// PR0: SWIFT_NONCOPYABLE makes Swift import this as ~Copyable,
// removing the implicitly-unwrapped-optional workaround in Swift wrappers.
class SWIFT_NONCOPYABLE WebsocketSwiftBridge {
public:
// Callbacks
using IPPacketCallback = void (*)(const uint8_t* packet_data, uint32_t length, void* context);
Expand Down
2 changes: 1 addition & 1 deletion Tools/FptnCLI/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ settings:
base:
SWIFT_CXX_INTEROPERABILITY_MODE: default
SWIFT_OBJC_INTEROP_MODE: objcxx
CLANG_CXX_LANGUAGE_STANDARD: c++20
CLANG_CXX_LANGUAGE_STANDARD: c++23

configs:
Debug: debug
Expand Down
Loading
Loading