VNC currently routes to UnsupportedSessionBackend with an explicit not-implemented message. This milestone was deferred; reopening as a tracked issue so it isn't lost.
Planned scope (per docs/PROGRESS.md Milestone 6):
Replace the unsupported VNC path with a complete VNC implementation
Deliver usable in-app VNC session behavior aligned to SSH/RDP UX
Extend profile/session connect options needed by VNC
Standardize event log and error mapping behavior with SSH/RDP
VNC currently routes to `UnsupportedSessionBackend` with an explicit not-implemented message. This milestone was deferred; reopening as a tracked issue so it isn't lost.
Planned scope (per docs/PROGRESS.md Milestone 6):
- Replace the unsupported VNC path with a complete VNC implementation
- Deliver usable in-app VNC session behavior aligned to SSH/RDP UX
- Implement VNC connect/disconnect/reconnect lifecycle handling
- Extend profile/session connect options needed by VNC
- Standardize event log and error mapping behavior with SSH/RDP
No permissively licensed VNC client library exists to vendor the way FreeRDP was for RDP -- LibVNCClient is GPLv2, gtk-vnc is LGPL but GTK-tied, and vendoring either would force a licensing decision on the whole (MIT) project. Per discussion, this is an original RFB (RFC 6143) implementation directly against QTcpSocket instead, in VncSessionBackend/VncDisplayWidget, threaded like SshSessionBackend (a QObject on its own QThread, driven by Qt's async socket signals) rather than RdpSessionBackend's manual worker-thread pattern, since there's no legacy synchronous C API here to wrangle.
Delivered:
Full connect/disconnect/reconnect lifecycle
RFB protocol-version negotiation, handling the real 3.3/3.7/3.8 handshake differences explicitly (the SecurityResult message only exists in 3.8 -- pre-3.8 servers signal auth failure by just closing the socket)
VNC Authentication (DES challenge-response, via OpenSSL's classic DES API, key-prep verified against an independently documented test vector) and no-auth security types
Raw + CopyRect framebuffer decoding, keyboard (Qt key -> X11 keysym) and mouse/wheel input forwarding
Wired into the same SessionTab/session_backend_factory dispatch SSH and RDP already use
Tested:
19 unit tests against a scripted in-process fake RFB server (all three handshake versions, auth success/failure, unsupported security types, pixel-accurate decoding) -- caught and fixed a real re-entrancy bug (QAbstractSocket::abort() synchronously re-firing disconnected() before returning, silently overwriting a specific error message with a generic one)
Verified live against a real, independently implemented VNC server (TightVNC on Windows, at the user's suggestion): connect with VNC Authentication, correct framebuffer dimensions and pixel data, clean disconnect, reconnect -- all confirmed working
Explicit gaps (not oversights -- tracked here for follow-up)
Apple Screen Sharing authentication (Diffie-Hellman + AES, security type 30) isn't implemented, so this can't yet reach macOS's built-in VNC server. Only standard VNC Authentication (type 2) and no-auth (type 1).
Raw + CopyRect encodings only -- no Hextile/ZRLE/Tight compression, so bandwidth usage is higher than a full VNC client over slow links.
No dynamic resize -- connects at the server's native resolution, scaled to fit locally (matches how RdpDisplayWidget already renders regardless of server resolution, so not a UX regression vs. RDP).
No remote cursor shape sync -- local default cursor only.
No clipboard sync.
Closing this as the initial VNC milestone is complete; happy to open follow-up issues for any of the above gaps if/when they become worth doing.
## Implemented (initial scope)
No permissively licensed VNC client library exists to vendor the way FreeRDP was for RDP -- LibVNCClient is GPLv2, gtk-vnc is LGPL but GTK-tied, and vendoring either would force a licensing decision on the whole (MIT) project. Per discussion, this is an original RFB (RFC 6143) implementation directly against `QTcpSocket` instead, in `VncSessionBackend`/`VncDisplayWidget`, threaded like `SshSessionBackend` (a `QObject` on its own `QThread`, driven by Qt's async socket signals) rather than `RdpSessionBackend`'s manual worker-thread pattern, since there's no legacy synchronous C API here to wrangle.
**Delivered:**
- Full connect/disconnect/reconnect lifecycle
- RFB protocol-version negotiation, handling the real 3.3/3.7/3.8 handshake differences explicitly (the `SecurityResult` message only exists in 3.8 -- pre-3.8 servers signal auth failure by just closing the socket)
- VNC Authentication (DES challenge-response, via OpenSSL's classic DES API, key-prep verified against an independently documented test vector) and no-auth security types
- Raw + CopyRect framebuffer decoding, keyboard (Qt key -> X11 keysym) and mouse/wheel input forwarding
- Wired into the same `SessionTab`/`session_backend_factory` dispatch SSH and RDP already use
**Tested:**
- 19 unit tests against a scripted in-process fake RFB server (all three handshake versions, auth success/failure, unsupported security types, pixel-accurate decoding) -- caught and fixed a real re-entrancy bug (`QAbstractSocket::abort()` synchronously re-firing `disconnected()` before returning, silently overwriting a specific error message with a generic one)
- Verified live against a real, independently implemented VNC server (TightVNC on Windows, at the user's suggestion): connect with VNC Authentication, correct framebuffer dimensions and pixel data, clean disconnect, reconnect -- all confirmed working
## Explicit gaps (not oversights -- tracked here for follow-up)
- **Apple Screen Sharing authentication** (Diffie-Hellman + AES, security type 30) isn't implemented, so this can't yet reach macOS's built-in VNC server. Only standard VNC Authentication (type 2) and no-auth (type 1).
- **Raw + CopyRect encodings only** -- no Hextile/ZRLE/Tight compression, so bandwidth usage is higher than a full VNC client over slow links.
- **No dynamic resize** -- connects at the server's native resolution, scaled to fit locally (matches how `RdpDisplayWidget` already renders regardless of server resolution, so not a UX regression vs. RDP).
- **No remote cursor shape sync** -- local default cursor only.
- **No clipboard sync.**
Closing this as the initial VNC milestone is complete; happy to open follow-up issues for any of the above gaps if/when they become worth doing.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
VNC currently routes to
UnsupportedSessionBackendwith an explicit not-implemented message. This milestone was deferred; reopening as a tracked issue so it isn't lost.Planned scope (per docs/PROGRESS.md Milestone 6):
Implemented (initial scope)
No permissively licensed VNC client library exists to vendor the way FreeRDP was for RDP -- LibVNCClient is GPLv2, gtk-vnc is LGPL but GTK-tied, and vendoring either would force a licensing decision on the whole (MIT) project. Per discussion, this is an original RFB (RFC 6143) implementation directly against
QTcpSocketinstead, inVncSessionBackend/VncDisplayWidget, threaded likeSshSessionBackend(aQObjecton its ownQThread, driven by Qt's async socket signals) rather thanRdpSessionBackend's manual worker-thread pattern, since there's no legacy synchronous C API here to wrangle.Delivered:
SecurityResultmessage only exists in 3.8 -- pre-3.8 servers signal auth failure by just closing the socket)SessionTab/session_backend_factorydispatch SSH and RDP already useTested:
QAbstractSocket::abort()synchronously re-firingdisconnected()before returning, silently overwriting a specific error message with a generic one)Explicit gaps (not oversights -- tracked here for follow-up)
RdpDisplayWidgetalready renders regardless of server resolution, so not a UX regression vs. RDP).Closing this as the initial VNC milestone is complete; happy to open follow-up issues for any of the above gaps if/when they become worth doing.