This library implements the subset of RFC 6143 listed below. Anything not listed is not implemented.
| Version | Supported |
|---|---|
| RFB 003.003 | Yes (handshake bytes only; the rest of the wire is the same as 003.008) |
| RFB 003.007 | Yes |
| RFB 003.008 | Yes (preferred) |
The server always advertises 003.008 in its initial banner. Clients
that speak an older version simply send back their highest supported
version string and the rest of the handshake matches.
| Type | Name | Supported |
|---|---|---|
| 1 | None | Yes (when agfy_rfb_set_password is unset or empty) |
| 2 | VncAuth | Yes (DES challenge / response per §7.2.2) |
| 5 | RA2 | No |
| 16 | Tight | No |
| 18 | TLS / VeNCrypt | No (terminate TLS in front of the server) |
VncAuth uses 8-byte passwords; longer values are silently truncated to 8 bytes (RFC 6143 Appendix A.1). The DES key is bit-reversed per byte before use, matching the historical RFB convention.
A custom agfy_rfb_password_check hook can replace the default DES
verifier or layer additional policy on top of it (per-client allow
lists, rate limiting, external auth).
| Type | Name | Implemented |
|---|---|---|
| 0 | FramebufferUpdate | Yes |
| 1 | SetColourMapEntries | No (the server is true-colour only) |
| 2 | Bell | No |
| 3 | ServerCutText (latin1) | Yes |
ExtendedServerCutText (-1024 pseudo-encoding) is not implemented;
non-Latin clipboard content is passed through as-is and may render
lossily on strict latin1 clients.
| Type | Name | Implemented |
|---|---|---|
| 0 | SetPixelFormat | Yes (32-bit true-colour only; non-conforming requests close the connection) |
| 2 | SetEncodings | Yes |
| 3 | FramebufferUpdateRequest | Yes (incremental and non-incremental) |
| 4 | KeyEvent | Yes |
| 5 | PointerEvent | Yes |
| 6 | ClientCutText | Yes (forwarded to the cuttext hook as latin1) |
Unknown message types close the connection rather than risk losing sync on a multi-byte message of unknown length.
| Code | Name | Implemented |
|---|---|---|
| 0 | Raw | Yes (mandatory per spec) |
| 1 | CopyRect | Yes |
| 2 | RRE | No |
| 4 | CoRRE | No |
| 5 | Hextile | No |
| 6 | zlib | No |
| 7 | Tight | Yes — FillCompression and JpegCompression special subtypes |
| 16 | ZRLE | No |
Tight is implemented in its "special subtype only" form. Solid rectangles collapse to a 4–6 byte FillCompression message; everything else goes through libjpeg-turbo at quality 80 as a JpegCompression message. The basic, zlib-stream, palette and gradient subtypes are intentionally omitted; that drops several hundred lines of state machine and removes the per-client zlib history buffers, at the cost of slightly worse compression on hand-crafted dithered content.
| Code | Name | Implemented |
|---|---|---|
| -223 | DesktopSize | Yes (sent on agfy_rfb_set_size) |
| -239 | Cursor | Reserved API; not pushed to clients |
| -240 | RichCursor | Reserved API; not pushed to clients |
| -1024 | ExtendedServerCutText | No |
| -307 | DesktopName (RFB extension) | No |
The server always announces 32-bit / depth-24 / true-colour in
ServerInit. The framebuffer is one of:
AGFY_RFB_PIXFMT_BGRA8888—red_shift=16, green_shift=8, blue_shift=0AGFY_RFB_PIXFMT_RGBA8888—red_shift=0, green_shift=8, blue_shift=16
Clients are free to negotiate their own format via SetPixelFormat;
the encoder converts on the fly. A fast path takes a per-row memcpy
when the client's negotiated format matches the server's native
format; everything else goes through a shift-and-mask pixel converter.
The CI suite runs the in-process round-trip and VncAuth tests. Beyond the regression suite, the implementation has been exercised against:
| Client | Version | Notes |
|---|---|---|
| noVNC | 1.7.0+ | Primary regression target — Raw, CopyRect, Tight all tested |
| TigerVNC Viewer | 1.13.x | Works |
| TightVNC Viewer | 2.x | Works |
| RealVNC Viewer | 7.x | Works for No-Auth and VncAuth |
Other clients implementing RFB 003.008 with No-Auth or VncAuth and the Raw / CopyRect / Tight encoding subset should work but are not part of the regression suite; bug reports against any RFC 6143 client are welcome.
For implementers who want to compare against the source:
- Maximum framebuffer dimension:
8192 × 8192. - Maximum incoming message size (per client):
256 KiB. - Maximum cut-text payload:
64 KiB. - Maximum advertised encodings count:
1024. - DES key length: 8 bytes (bit-reversed password, NUL-padded).