Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6e830c3
feat: Implement network migration Phase.1
hanatyan128 Mar 21, 2026
c9cb8f5
feat: Implement network migration Phase.2
hanatyan128 Mar 22, 2026
3da6687
feat: Implement network migration Phase.3
hanatyan128 Mar 22, 2026
e7ff0ee
feat: Implement network migration Phase.4
hanatyan128 Mar 22, 2026
0447ccd
fix: curl in obs-deps didn't support ws/wss
hanatyan128 Mar 22, 2026
a119d90
chore: Update buildspec (version & repository of prebuild,qt6)
hanatyan128 Mar 22, 2026
7bf7237
fix: Address code review findings for network migration
hanatyan128 Apr 5, 2026
62b8668
fix: Harden network migration shutdown, TLS, and lifetime safety
hanatyan128 Apr 26, 2026
a6a207f
fix: Drop Qt 6.6 floor and restore Ubuntu 22.04 CI target
hanatyan128 Apr 26, 2026
e0bdd53
feat: Make Linux CA path configurable via SRC_LINK_LINUX_CA_PATH
hanatyan128 Apr 26, 2026
491ff70
fix: Add <arpa/inet.h> include for htons() on Linux/macOS
hanatyan128 Apr 26, 2026
69536e7
fix: Build curl/mbedtls with -fPIC for the shared plugin module
hanatyan128 Apr 26, 2026
b5886b9
fix: Make vendored curl/mbedtls build cleanly on macOS CI
hanatyan128 Apr 27, 2026
941ab7f
fix: Tighten network stack lifetime, security, and CMake hygiene
hanatyan128 Apr 27, 2026
31c59e3
fix: Tighten WS protocol, OAuth2 redirect safety, and curl/CI hygiene
hanatyan128 Apr 28, 2026
8fa68ee
fix: Plug shutdown UAF, reset reconnect state, lock down OAuth/HTTP
hanatyan128 Apr 28, 2026
07ce6d0
fix: Harden WS framing, HTTP redirect handling, OAuth refresh, and re…
hanatyan128 Apr 29, 2026
594f991
build: Pin clang-format 17.0.3, tighten CMake guards, and refresh REA…
hanatyan128 Apr 29, 2026
eb054a3
fix: Tighten WS RFC compliance, OAuth2 reentry safety, and HTTP/CI hy…
hanatyan128 May 4, 2026
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
11 changes: 9 additions & 2 deletions .github/actions/run-clang-format/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ runs:
echo ::group::Install Dependencies
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
echo "/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin" >> $GITHUB_PATH
echo "/home/linuxbrew/.linuxbrew/opt/clang-format@17/bin" >> $GITHUB_PATH
brew install --quiet zsh
echo ::endgroup::

Expand All @@ -52,7 +51,15 @@ runs:

if (( ${changes[(I)(*.c|*.h|*.cpp|*.hpp|*.m|*.mm)]} )) {
echo ::group::Install clang-format-17
brew install --quiet obsproject/tools/clang-format@17
# PyPI `clang-format` (ssciwr/clang-format-wheel) ships the upstream
# LLVM 17.0.3 binary, so pinning the version here pins the tool exactly.
python3 -m pip install --quiet --user --break-system-packages 'clang-format==17.0.3'
export PATH="$(python3 -m site --user-base)/bin:${PATH}"
echo "Resolved clang-format: $(command -v clang-format)"
clang-format --version
clang-format --version | grep -qE 'version 17\.0\.3([[:space:]]|$)' || {
echo "::error::clang-format is not pinned to 17.0.3"; exit 1;
}
echo ::endgroup::

echo ::group::Run clang-format-17
Expand Down
8 changes: 7 additions & 1 deletion .github/actions/run-cmake-format/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ runs:

if (( ${changes[(I)*.cmake|*CMakeLists.txt]} )) {
echo ::group::Install cmakelang
pip3 install cmakelang
python3 -m pip install --quiet --user --break-system-packages 'cmakelang==0.6.13'
export PATH="$(python3 -m site --user-base)/bin:${PATH}"
echo "Resolved cmake-format: $(command -v cmake-format)"
cmake-format --version
cmake-format --version | grep -qE '^0\.6\.13$' || {
echo "::error::cmake-format is not pinned to 0.6.13"; exit 1;
}
echo ::endgroup::
echo ::group::Run cmake-format
./build-aux/run-cmake-format --fail-${{ inputs.failCondition }} --check
Expand Down
1 change: 0 additions & 1 deletion .github/scripts/utils.zsh/setup_linux
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ if (( ! (${skips[(Ie)all]} + ${skips[(Ie)deps]}) )) {
qt6-base-dev${suffix}
libqt6svg6-dev${suffix}
qt6-base-private-dev${suffix}
libqt6websockets6-dev${suffix}
)
}

Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
# Except additional project files
!src-link_usage_image.jpg
!/srtrelay
!Frameworks.cmake.in
!README_ja.md
!/mediamtx
!/AGENTS.md
Expand Down
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[submodule "lib/o2"]
path = lib/o2
url = https://github.com/OPENSPHERE-Inc/o2.git
[submodule "lib/json"]
path = lib/json
url = https://github.com/nlohmann/json.git
Expand Down
33 changes: 20 additions & 13 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ control, and connection management with team operations.
It is developed and maintained by **OPENSPHERE Inc.** under the GPLv2+ license.

- Repository language: **C++ 17** with **Qt 6** for UI
- Build system: **CMake** (≥ 3.16, ≤ 3.26)
- Build system: **CMake** (≥ 3.22, ≤ 3.26)
- Based on the official [obs-plugintemplate](https://github.com/obsproject/obs-plugintemplate)
- Target OBS Studio version: **≥ 30.1.0** (Qt6, x64 / ARM64 / Apple Silicon)
- Current version: **0.7.6**
- Current version: **0.8.0**

---

Expand All @@ -24,7 +24,6 @@ src-link/
├── CMakePresets.json # CMake presets (windows-x64, macos, linux-x86_64, linux-aarch64, CI variants)
├── buildspec.json # Build specification (name, version, dependencies, UUIDs)
├── build.ps1 # Local Windows build script (RelWithDebInfo)
├── Frameworks.cmake.in # macOS framework configuration
├── .clang-format # C++ code style (clang-format ≥ 16)
├── .cmake-format.json # CMake code style
├── .github/
Expand All @@ -41,7 +40,15 @@ src-link/
│ ├── plugin-main.cpp # Plugin entry point (module load/unload)
│ ├── api-client.hpp / .cpp # SRCLinkApiClient: central orchestrator, OAuth, REST API, WebSocket
│ ├── api-websocket.hpp / .cpp # SRCLinkWebSocketClient: control API WebSocket client
│ ├── request-invoker.hpp / .cpp # HTTP request sequencing (OAuth2 via o2 library)
│ ├── net/
│ │ ├── http-request-invoker.hpp / .cpp # OAuth2-aware HTTP request invoker
│ │ ├── http-response.hpp # HTTP response struct
│ │ ├── http-error.hpp / .cpp # HTTP error mapping helpers
│ │ ├── curl-http-client.hpp / .cpp # libcurl-based HTTP client
│ │ ├── ws-client.hpp / .cpp # libcurl-based WebSocket client
│ │ ├── oauth2-client.hpp / .cpp # OAuth2 authorization-code flow client
│ │ ├── local-http-server.hpp / .cpp # OAuth2 redirect-uri loopback server
│ │ └── linux-ca-locations.hpp / .cpp # Linux CA bundle path discovery
│ ├── settings.hpp / .cpp # SRCLinkSettingsStore: persistent settings (OBS profile INI)
│ ├── schema.hpp # JSON data schemas (Account, Party, Stage, Uplink, Downlink, etc.)
│ ├── utils.hpp / .cpp # Utility functions, encoder helpers, network helpers
Expand All @@ -68,7 +75,6 @@ src-link/
│ └── event-handler.hpp / .cpp # OBS event broadcasting to WebSocket clients
├── lib/
│ ├── json/ # nlohmann/json (bundled)
│ ├── o2/ # OAuth2 client library (bundled)
│ └── obs-websocket/ # OBS WebSocket library (bundled)
├── shared/
│ ├── properties-view/ # Custom OBS properties UI helpers
Expand All @@ -86,11 +92,11 @@ src-link/

| Platform | Toolchain |
|----------|-----------|
| Windows | Visual Studio 17 2022, CMake ≥ 3.16, Qt 6 |
| macOS | Xcode ≤ 16.4.0 (macOS SDK ≤ 15.5), CMake ≥ 3.16, Qt 6 |
| Linux | GCC / Clang, CMake ≥ 3.16, Qt 6 |
| Windows | Visual Studio 17 2022, CMake ≥ 3.22 (≤ 3.26), Qt 6 |
| macOS | Xcode ≤ 16.4.0 (CI pins Xcode 15.2 on macos-14), macOS SDK ≤ 15.5, CMake ≥ 3.22 (≤ 3.26), Qt 6 |
| Linux | GCC / Clang, CMake ≥ 3.22 (≤ 3.26), Qt 6 |

> **Note (macOS):** This project requires **Xcode 16.4.0 (macOS 15.5 SDK) or below**. Xcode 26 / macOS SDK 26 and later are currently unsupported due to compatibility constraints with OBS Studio's build dependencies.
> **Note (macOS):** This project requires **Xcode 16.4.0 (macOS 15.5 SDK) or below**. Xcode 26 / macOS SDK 26 and later are currently unsupported due to compatibility constraints with OBS Studio's build dependencies. CI runs on `macos-14` with Xcode 15.2 explicitly selected; local development should target an Xcode within this supported range to keep parity with CI.

OBS Studio sources and pre-built dependencies are fetched automatically via `buildspec.json`
(obs-studio 30.1.2, obs-deps, Qt6).
Expand Down Expand Up @@ -215,7 +221,7 @@ The plugin registers via `obs_module_load()` in `plugin-main.cpp`. It creates:
| **Event Handler** | `WsPortalEventHandler` | Singleton OBS event broadcaster for WebSocket Portal clients. |
| **Audio Capture** | `SourceAudioCapture` | Abstract audio buffer with format conversion. Extended by `OutputAudioSource` for OBS audio output binding. |
| **Image Renderer** | `ImageRenderer` | Renders placeholder images (filler, connecting, error states) for sources. |
| **Request Invoker** | `RequestInvoker` / `RequestSequencer` | HTTP request pipelining with OAuth2 token management via o2 library. Sequential queuing and parallel invocation support. |
| **Request Invoker** | `RequestInvoker` / `RequestSequencer` | HTTP request pipelining with OAuth2 token management via the in-tree `src/net/` stack. Sequential queuing and parallel invocation support. |
| **Settings Store** | `SRCLinkSettingsStore` | Persistent key-value settings stored in OBS profile INI. |
| **JSON Schemas** | `schema.hpp` | Typed data classes: `AccountInfo`, `PartyArray`, `StageArray`, `UplinkInfo`, `DownlinkInfo`, `WsPortalArray`, `SubscriptionFeatures`, etc. |

Expand All @@ -235,7 +241,7 @@ The plugin registers via `obs_module_load()` in `plugin-main.cpp`. It creates:
- **UI Thread**: Qt event loop — main window, dialogs, docks, API client.
- **OBS Callbacks**: Video render, audio filter, video tick — may run on different threads from the UI thread.
- **Audio Thread**: `SourceAudioThread` — dedicated thread for source audio processing in `IngressLinkSource`.
- **Network**: Qt networking runs on the default Qt event loop.
- **Network**: HTTP / WebSocket I/O is driven by the in-tree `src/net/` stack (libcurl + custom OAuth2 / WebSocket clients) on the Qt event loop. Qt Network is no longer used.

**Synchronization**:
- `QMutex` protects audio buffers in `SourceAudioCapture`.
Expand All @@ -246,7 +252,7 @@ The plugin registers via `obs_module_load()` in `plugin-main.cpp`. It creates:
### Network & API Architecture

**Authentication**:
- OAuth2 flow via the o2 library (browser-based approval).
- OAuth2 flow implemented in `src/net/oauth2-client.cpp` (browser-based approval; loopback HTTP server for the redirect).
- Tokens stored in OBS profile settings via `SRCLinkSettingsStore`.
- Automatic token refresh on expiry.
- UUID-based client identification.
Expand Down Expand Up @@ -432,7 +438,8 @@ Release tags follow semver: `X.Y.Z` for stable, `X.Y.Z-beta`/`X.Y.Z-rc` for pre-
- **Memory management** — Use OBS RAII wrappers. Raw `bfree()` / `obs_data_release()` calls are error-prone.
- **`.gitignore` uses allowlist pattern** — New top-level files/directories must be explicitly un-ignored with `!` prefix.
- **Port management** — Ingress ports must be within the configured range and not conflict with other instances. The API client manages port allocation.
- **Bundled libraries** (`lib/`) — `nlohmann/json`, `o2`, and `obs-websocket` are vendored. Update with caution.
- **Bundled libraries** (`lib/`) — `nlohmann/json` and `obs-websocket` are vendored. Update with caution.
- **Network stack dependencies (FetchContent)** — `libcurl` (static, WebSocket-enabled) is fetched at configure time by `CMakeLists.txt`. On Linux, `mbedtls` is fetched and linked statically as the TLS backend; Windows uses Schannel and macOS uses Secure Transport. Because curl/mbedtls are now built in-tree, `buildspec.json` pins `obs-deps` / `qt6` to upstream `obsproject/obs-deps@2024-03-19` (ships Qt 6.6.2, sufficient for `Qt::SingleShotConnection`) — the OPENSPHERE-Inc fork that previously supplied a WebSocket-enabled curl is no longer required.
- **Encoder presets** (`data/presets/`) — Hardware encoder presets are platform-specific. Test on target hardware when modifying.

---
Expand Down
Loading
Loading