mirror of
https://github.com/games-on-whales/wolf.git
synced 2026-10-15 13:02:03 +00:00
[PR #475] feat(api): add POST /api/v1/sessions/resume to re-key a paused session #490
Labels
No labels
🧠 1 - 🤖 999
AMD
bug
bug
cannot reproduce
documentation
duplicate
easy
enhancement
enhancement
enhancement
fixed?
fixed?
good first issue
hard
help wanted
Intel
invalid
LXC
medium
moonlight-protocol
Multi GPU
nixos
not a bug
nvidia
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
games-on-whales/wolf#490
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/games-on-whales/wolf/pull/475
Author: @darrengruber
Created: 8/10/2026
Status: 🔄 Open
Base:
beta← Head:api-session-resume📝 Commits (1)
02b472dfeat(api): add POST /api/v1/sessions/resume to re-key a paused session📊 Changes
3 files changed (+62 additions, -0 deletions)
View changed files
📝
src/moonlight-server/api/api.hpp(+8 -0)📝
src/moonlight-server/api/endpoints.cpp(+38 -0)📝
src/moonlight-server/api/unix_socket_server.cpp(+16 -0)📄 Description
Problem
A Moonlight client generates a new rikey every time it reconnects, but a
StreamSessionkeeps the AES key it was created with and decrypts the ENet control stream with it. A client that reconnects through the socket API therefore fails every control message withEVP_DecryptFinal_ex, never completes a ping, and reports a dead network to the user — while the server logs a clean 200 and the app keeps running happily.Observed against 1.26.7/
stable: three reconnects, three different rikeys, and a wall ofWhy the existing endpoints can't express it
The HTTPS server doesn't have this problem —
resume()inrest/endpoints.hpprebuilds the session from the new rikey and carries the Wayland display and virtual input devices across. There is no socket equivalent, and it can't be assembled from what's there:/sessions/addappends a new session and can't carry over the display, so it rebuilds the compositor and restarts the app — the opposite of resuming./sessions/startonly fires theVideoSessionandAudioSessionevents; it never touches the session key.get_session_by_idtakes the first match, so adding a duplicate session id just resolves back to the stale one.The change
Adds the missing primitive: copy the
StreamSession, replaceaes_key/aes_iv, swap it intorunning_sessions. The display, input devices and audio sink are allshared_ptrmembers, so the copy keeps the same desktop and the same devices already plugged into the container — which is what separates a resume from a launch.rtsp_fake_ipand the RTP/ENet secret payloads are deliberately preserved: Wolf generates those rather than the client, andrtsp_fake_ipis how the RTSP thread identifies the session.Verified
On a live session, pause → resume:
aes_key3ACACAEE…0675ADA28680…1FC3sway/steam10921006191092100619The key rotates while the desktop and the running app stay exactly as they were.
Found while adding resume support to fenrir, a Kubernetes operator that drives Wolf entirely through the socket API.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.