Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c5174ac
feat(moonlight): vendor the cgutman ENet fork (MIT)
emir-hasanbegovic Aug 25, 2026
8ee5630
feat(moonlight): Qt-free protocol core: wire, crypto, pairing, RTSP, …
emir-hasanbegovic Aug 25, 2026
d83a8f1
feat(moonlight): transports, session coordinator, repositories and bu…
emir-hasanbegovic Aug 25, 2026
6880dea
feat(moonlight): wire the host subsystem into AppModel, the view mode…
emir-hasanbegovic Aug 25, 2026
9a40a4e
fix(moonlight): echo X-SS-Ping-Payload in the RTP pings, and re-send …
emir-hasanbegovic Aug 25, 2026
ce951ee
fix(ci): clang-tidy clean the Moonlight wiring, and libssl-dev for th…
emir-hasanbegovic Aug 25, 2026
eaaffe7
fix(moonlight): clear the rest of the clang-tidy sweep
emir-hasanbegovic Aug 25, 2026
3527e20
fix(moonlight): the protocol faults a live Sunshine host found
emir-hasanbegovic Aug 26, 2026
b557810
test(moonlight): drop the unused listener-close seam from the RTSP fi…
emir-hasanbegovic Aug 26, 2026
2e985b0
test(moonlight): pin that no TLS session is ever offered for resumption
emir-hasanbegovic Aug 26, 2026
bf8ded1
feat(moonlight): connecting is pairing, and the session moves into th…
emir-hasanbegovic Aug 26, 2026
b021dc5
fix(moonlight): count the session's pads through the slot table, not …
emir-hasanbegovic Aug 26, 2026
db8f8f5
fix(tests): use the house signal spy, and let a titled state carry it…
emir-hasanbegovic Aug 26, 2026
fe8480c
fix(moonlight): let a refusing host say why in its own words
emir-hasanbegovic Aug 26, 2026
e6851b0
fix(moonlight): forget takes the whole host with it, and nothing fail…
emir-hasanbegovic Aug 26, 2026
6d7e6e6
fix(moonlight): trust needs both halves, and a Forget names what it t…
emir-hasanbegovic Aug 26, 2026
c012c6e
fix(moonlight): dismissing the PIN sheet cancels the pairing behind it
emir-hasanbegovic Aug 26, 2026
4160bb1
test(moonlight): assert the in-flight pairing through the residue enu…
emir-hasanbegovic Aug 26, 2026
ba22e1a
fix(moonlight): the row and the section read one rule, not two spelli…
emir-hasanbegovic Aug 26, 2026
6e1d82f
fix(moonlight): a forget finishes its bookkeeping before the session …
emir-hasanbegovic Aug 26, 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
2 changes: 1 addition & 1 deletion .github/actions/setup-build-deps/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ runs:
# shellcheck disable=SC2086
sudo apt-get install -y --no-install-recommends \
build-essential cmake ninja-build pkg-config ccache \
libsodium-dev libsdl2-dev \
libsodium-dev libsdl2-dev libssl-dev \
catch2 clang-tidy ${EXTRA_PACKAGES}

- name: Restore compiler cache
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
build-essential cmake ninja-build pkg-config \
libsodium-dev libsdl2-dev
libsodium-dev libsdl2-dev libssl-dev

# Not apt: noble ships Qt 6.4.2 and this project's floor is 6.7. The
# action pulls the official binaries and exports CMAKE_PREFIX_PATH.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/linux-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ jobs:
build-essential cmake ninja-build pkg-config \
qt6-base-dev qt6-base-dev-tools qt6-declarative-dev qt6-svg-dev \
qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools \
libsodium-dev libsdl2-dev libdbus-1-dev \
libsodium-dev libsdl2-dev libssl-dev libdbus-1-dev \
dpkg-dev fakeroot file gzip \
librsvg2-bin desktop-file-utils appstream lintian

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ jobs:
build-essential cmake ninja-build pkg-config \
qt6-base-dev qt6-base-dev-tools qt6-declarative-dev qt6-svg-dev \
qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools \
libsodium-dev libsdl2-dev libdbus-1-dev \
libsodium-dev libsdl2-dev libssl-dev libdbus-1-dev \
dpkg-dev fakeroot file gzip \
librsvg2-bin desktop-file-utils appstream lintian

Expand Down Expand Up @@ -323,7 +323,7 @@ jobs:
git-core ca-certificates \
gcc-c++ cmake ninja-build pkgconf-pkg-config rpm-build \
qt6-qtbase-devel qt6-qtdeclarative-devel qt6-qtsvg-devel qt6-qttools-devel \
libsodium-devel SDL2-devel dbus-devel \
libsodium-devel SDL2-devel openssl-devel dbus-devel \
librsvg2-tools desktop-file-utils libappstream-glib gzip

- name: Checkout
Expand Down Expand Up @@ -466,7 +466,7 @@ jobs:
# resolve on the build host.
sudo apt-get install -y --no-install-recommends \
build-essential cmake ninja-build pkg-config \
libsodium-dev libudev-dev libusb-1.0-0-dev \
libsodium-dev libssl-dev libudev-dev libusb-1.0-0-dev \
libxkbcommon-x11-0 libxcb-cursor0 libxcb-icccm4 libxcb-image0 \
libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-shape0 \
libxcb-xinerama0 libxcb-xkb1 \
Expand Down
65 changes: 62 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ cmake_minimum_required(VERSION 3.21)
project(Dish
VERSION 0.2.0
DESCRIPTION "Dish Linux client for the Satellite gamepad-over-LAN protocol"
LANGUAGES CXX)
# C for the vendored ENet fork (third_party/enet), the transport under the
# Moonlight-host control stream.
LANGUAGES C CXX)

# --------------------------------------------------------------------------
# Global build settings
Expand Down Expand Up @@ -126,7 +128,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# Dependencies
# --------------------------------------------------------------------------
find_package(Threads REQUIRED)
find_package(Qt6 6.7 REQUIRED COMPONENTS Core Gui Network DBus Svg Quick Qml QuickControls2)
find_package(Qt6 6.7 REQUIRED COMPONENTS Core Gui Network DBus Svg Quick Qml QuickControls2 Concurrent)
qt_standard_project_setup(REQUIRES 6.7)
# Optional: without qttools the .ts → .qm step is skipped and every qsTr()
# falls back to its English source string, which still builds a working app.
Expand All @@ -135,6 +137,14 @@ find_package(Qt6 6.7 QUIET OPTIONAL_COMPONENTS LinguistTools)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SODIUM REQUIRED IMPORTED_TARGET libsodium)
pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)
# OpenSSL's libcrypto backs the Moonlight-host pairing (AES-128, RSA, self-
# signed X.509) and the control-stream AES-GCM, none of which libsodium offers.
# Only libcrypto is used; the TLS client itself is Qt Network's.
find_package(OpenSSL REQUIRED)

# The vendored ENet fork (MIT), the transport Moonlight hosts speak on the
# control stream. See THIRD_PARTY.md.
add_subdirectory(third_party/enet)


# --------------------------------------------------------------------------
Expand All @@ -151,6 +161,24 @@ set(DISH_CORE_SOURCES
src/core/AsyncState.h
src/core/wire/SessionCrypto.h
src/core/wire/SessionCrypto.cpp
# Moonlight (Sunshine/Apollo/Wolf) host protocol: the Qt-free core.
src/core/moonlight/MoonlightProtocol.h
src/core/moonlight/MoonlightWire.h
src/core/moonlight/MoonlightWire.cpp
src/core/moonlight/MoonlightControlCipher.h
src/core/moonlight/MoonlightControlCipher.cpp
src/core/moonlight/MoonlightPairingCrypto.h
src/core/moonlight/MoonlightPairingCrypto.cpp
src/core/moonlight/MoonlightPairing.h
src/core/moonlight/MoonlightPairing.cpp
src/core/moonlight/MoonlightXml.h
src/core/moonlight/MoonlightXml.cpp
src/core/moonlight/MoonlightRtsp.h
src/core/moonlight/MoonlightRtsp.cpp
src/core/moonlight/MoonlightSessionMachine.h
src/core/moonlight/MoonlightPadSlots.h
src/core/moonlight/MoonlightSessionUi.h
src/core/moonlight/MoonlightButtonMap.h
src/core/model/Protocol.h
src/core/model/IdentityKey.h
src/core/net/Tofu.h
Expand Down Expand Up @@ -252,6 +280,24 @@ set(DISH_CORE_SOURCES
src/source/connection/MdnsDiscovery.cpp
src/source/connection/DiscoveryGateway.h
src/source/connection/DiscoveryGateway.cpp
# Moonlight-host IO edge: HTTP/RTSP/ENet transports, discovery, pairing,
# the session coordinator and the subsystem manager.
src/source/moonlight/MoonlightLog.h
src/source/moonlight/MoonlightLog.cpp
src/source/moonlight/MoonlightHttp.h
src/source/moonlight/MoonlightHttp.cpp
src/source/moonlight/MoonlightRtspClient.h
src/source/moonlight/MoonlightRtspClient.cpp
src/source/moonlight/MoonlightControlStream.h
src/source/moonlight/MoonlightControlStream.cpp
src/source/moonlight/MoonlightDiscovery.h
src/source/moonlight/MoonlightDiscovery.cpp
src/source/moonlight/MoonlightPairingFlow.h
src/source/moonlight/MoonlightPairingFlow.cpp
src/source/moonlight/MoonlightSession.h
src/source/moonlight/MoonlightSession.cpp
src/source/moonlight/MoonlightManager.h
src/source/moonlight/MoonlightManager.cpp
src/source/http/SatelliteTlsVerifier.h
src/source/http/SatelliteTlsVerifier.cpp
# An ETag cache over HTTPClient::getCatalog, not a durable Repository,
Expand Down Expand Up @@ -330,6 +376,10 @@ set(DISH_CORE_SOURCES
src/repository/SatelliteSharedKeyRepository.cpp
src/repository/RememberedSatelliteRepository.h
src/repository/RememberedSatelliteRepository.cpp
src/repository/MoonlightIdentityRepository.h
src/repository/MoonlightIdentityRepository.cpp
src/repository/MoonlightHostRepository.h
src/repository/MoonlightHostRepository.cpp
src/repository/ConnectionStore.h
src/UI/CrashReport.cpp
src/repository/AppSettings.cpp
Expand Down Expand Up @@ -411,13 +461,20 @@ target_link_libraries(dish_core
Qt6::Gui
# ScreenSaver inhibit, the BlueZ adapter probe and the appearance portal.
Qt6::DBus
# The Moonlight mDNS scan runs off the GUI thread via QtConcurrent::run.
Qt6::Concurrent
PkgConfig::SODIUM
PkgConfig::SDL2
Threads::Threads
PRIVATE
dish_warnings
dish_strict
dish_hardened)
dish_hardened
# The Moonlight-host pairing/control crypto and the vendored ENet
# transport. PRIVATE: no dish_core header exposes an OpenSSL or ENet
# type across the library boundary.
OpenSSL::Crypto
dish_enet)

# --------------------------------------------------------------------------
# UI executable
Expand Down Expand Up @@ -504,6 +561,7 @@ qt_add_qml_module(Dish
src/qml/pages/LicensesPage.qml
src/qml/pages/ControlsRemapPage.qml
src/qml/pages/ConfigureBindingPage.qml
src/qml/pages/MoonlightHostsPage.qml
src/qml/pages/PairingDialog.qml
src/qml/onboarding/OnboardingFlow.qml
src/qml/onboarding/WelcomeScreen.qml
Expand All @@ -512,6 +570,7 @@ qt_add_qml_module(Dish
src/qml/wizard/WizardInputPage.qml
src/qml/wizard/WizardDestinationPage.qml
src/qml/wizard/WizardTypePage.qml
src/qml/wizard/WizardSessionPage.qml
src/qml/wizard/WizardFeelPage.qml
src/qml/wizard/WizardReviewPage.qml)

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ it in place. What the check sends is spelled out in [`PRIVACY.md`](PRIVACY.md).
- GCC 12+ or Clang 15+, CMake 3.21+, Ninja
- Qt 6.7+ (Core, Gui, Network, DBus, Svg, Quick, Qml, QuickControls2; Linguist
tools for the translation catalogues)
- libsodium, SDL2, Catch2 v3
- libsodium, SDL2, OpenSSL (libcrypto), Catch2 v3
- Optional: `rsvg-convert`, which renders the rest of the launcher-icon ladder
from the SVG. Without it the build says so and installs only the scalable and
512x512 icons, which is enough for a working menu entry.
Expand All @@ -114,7 +114,7 @@ On Debian and Ubuntu:
sudo apt install build-essential cmake ninja-build pkg-config \
qt6-base-dev qt6-base-dev-tools qt6-declarative-dev qt6-svg-dev \
qt6-tools-dev qt6-l10n-tools \
libsodium-dev libsdl2-dev libdbus-1-dev catch2 \
libsodium-dev libsdl2-dev libssl-dev libdbus-1-dev catch2 \
librsvg2-bin
```

Expand Down
75 changes: 75 additions & 0 deletions THIRD_PARTY.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,22 @@ today.
| [libsodium](#libsodium) | >= 1.0.18 | `ISC` | Dynamically linked against the system libsodium. | Keep the copyright and permission notice |
| [Inter](#4-inter) | 4.001 | `OFL-1.1` | Four `.ttf` faces embedded in `dish` as Qt resources under `:/fonts/`. | Ship the license text with every copy. See section 4. |
| [Catch2](#5-catch2) | 3.x | `BSL-1.0` | Test binary only. Not linked into `dish`. | None for redistributors of the app |
| [ENet (cgutman fork)](#9-enet) | commit `4cde9cc` | `MIT` | Vendored C sources under `third_party/enet/`, compiled into `dish`. | Ship the copyright + permission notice |
| [OpenSSL libcrypto](#10-openssl-libcrypto) | system | `Apache-2.0` | Dynamically linked against the system libcrypto for the Moonlight-host crypto. | Keep the notice; nothing bundled |

Two further items are reuse of published facts rather than of code, and are
covered in [section 6](#6-reused-facts-not-reused-code): SDL's default Switch Pro
motion scaling constants, and the HID input-report byte layouts documented in the
Linux kernel's PlayStation and Nintendo HID drivers.

The Moonlight (GameStream) host protocol support under `src/core/moonlight/` and
`src/source/moonlight/` is an original implementation. Its wire framing, crypto
construction and pairing algorithm were learned from the documentation and the
MIT-licensed host implementation of Wolf (games-on-whales/wolf); that reuse of
adapted logic is recorded in [section 11](#11-wolf-moonlight-protocol-reference).
No GPL-licensed Moonlight code (moonlight-common-c, moonlight-qt, Sunshine,
Apollo) was consulted or copied.

Everything under `resources/brand/` and `packaging/dish.svg` is original
TinkerNorth artwork, covered by this repository's own license. See
[section 8](#8-first-party-artwork).
Expand Down Expand Up @@ -274,6 +284,71 @@ license and carry no third-party attribution.

---

## 9. ENet

The cgutman fork of ENet, SPDX `MIT`. Upstream:
<https://github.com/cgutman/enet>, vendored at commit
`4cde9cc3dcc5c30775a80da1de87f39f98672a31` (the commit Wolf and the Moonlight
ecosystem pin). Original ENet by Lee Salzman: <https://github.com/lsalzman/enet>.

The Moonlight control stream runs over this reliable-UDP library. The unmodified
upstream C sources live under [`third_party/enet/`](third_party/enet/) and are
compiled into `dish` as the static `dish_enet` library. Because the sources are
bundled and redistributed inside the binary, the MIT copyright and permission
notice ([`third_party/enet/LICENSE`](third_party/enet/LICENSE)) must travel with
any copy.

```
Copyright (c) 2002-2020 Lee Salzman

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction ... THE SOFTWARE IS PROVIDED "AS IS".
```

The fork adds IPv4/IPv6 dual-stack support over upstream ENet; no local
modifications were made to the vendored sources.

---

## 10. OpenSSL libcrypto

OpenSSL, SPDX `Apache-2.0`. Upstream: <https://www.openssl.org/>.

The Moonlight-host support needs AES-128 (ECB and GCM), RSA sign/verify and
self-signed X.509 generation — primitives libsodium deliberately does not
provide — so `dish` links the system OpenSSL's `libcrypto` for them (only
`libcrypto`; the TLS client itself remains Qt Network's). Nothing is bundled:
this is your distribution's OpenSSL, and its notice travels with that package,
as it already does for the Qt build `Qt6::Network` runs against.

---

## 11. Wolf (Moonlight protocol reference)

Wolf, SPDX `MIT`. Upstream: <https://github.com/games-on-whales/wolf>.

**No Wolf source is compiled into `dish`.** Wolf is an MIT-licensed Moonlight
*host*; its protocol documentation and source were the reference for this
project's own Moonlight *client* implementation under `src/core/moonlight/` and
`src/source/moonlight/`. Adapted logic includes the control-packet AES-GCM IV
construction, the 5-phase PIN pairing algorithm, the CONTROLLER_* wire struct
layouts and the RTSP request/response shapes. These were re-implemented against
Dish's own architecture; the byte-exact test fixtures are derived from Wolf's
protocol docs and its published test vectors.

```
Copyright (c) 2021-2024 Games on Whales

Permission is hereby granted, free of charge ... THE SOFTWARE IS PROVIDED "AS IS".
```

Deliberately NOT consulted, to keep this LGPL-3.0 project clear of GPL-3.0
Moonlight code: moonlight-common-c, moonlight-qt, moonlight-android, Sunshine,
Apollo. Wolf's documentation and MIT source were sufficient.

---

## Keeping this in sync

[`assets/licenses/licenses.json`](assets/licenses/licenses.json) is the manifest
Expand Down
Loading
Loading