Skip to content

GUACAMOLE-2307: Add opt-in raw text-output mode for terminal protocols (SSH/telnet/Kubernetes) - #697

Open
ciroiriarte wants to merge 1 commit into
apache:mainfrom
ciroiriarte:feature/3-text-output-mode-apache
Open

GUACAMOLE-2307: Add opt-in raw text-output mode for terminal protocols (SSH/telnet/Kubernetes)#697
ciroiriarte wants to merge 1 commit into
apache:mainfrom
ciroiriarte:feature/3-text-output-mode-apache

Conversation

@ciroiriarte

Copy link
Copy Markdown

Implements GUACAMOLE-2307.

What

Adds an opt-in per-connection parameter, text-output, that tees the raw remote
PTY byte stream (including ANSI/CSI/OSC sequences) to an outbound Guacamole pipe
stream named STDOUT, for the SSH, telnet, and Kubernetes protocols. A
non-graphical / native CLI client can then present a terminal session as true
in-terminal text instead of decoding rasterized glyphs. Default off; existing
connections are unaffected.

Modes

  • text-output=truetee: raw bytes go to STDOUT and the graphical
    display is still rendered for browser users.
  • text-output=rawheadless: graphical rendering is skipped entirely; bytes
    are delivered only via STDOUT.
  • anything else, including false or omitted — disabled.

Design notes for review

  • The tee is taken at the protocol source — each protocol's PTY read path,
    upstream of the terminal emulator — rather than via guac_terminal_echo(),
    which strips escape sequences.
  • The pipe uses mimetype application/octet-stream (base64 blobs, binary-safe,
    charset-agnostic) and is allocated on the connection owner's user socket (an
    even, ack-routable index), not broadcast.
  • Additive public API: guac_terminal_text_output_{open,write,flush,close}.
  • Flow control: clients must ack every blob; the unacknowledged backlog is
    bounded by bytes (256 KB). On a stalled consumer, tee mode drops buffered
    output (its read loop is shared with the graphical display, so blocking would
    stall co-attached browser users), while raw mode throttles the read loop,
    propagating backpressure to the remote program through the PTY, and disconnects
    only after 15 s with no acks.
  • Gated behind disable-copy: guacd refuses to open the pipe when copying from the
    terminal is disabled. Pipe contents are not logged or recorded by default.

Compatibility

Additive and opt-in, default off. No new protocol instruction (reuses
pipe/blob/end/ack), no schema change, no ABI break. An unmodified
guacamole-client already passes the parameter through.

Testing

  • CUnit coverage for the text-output paths (disable-copy gating, ack routing,
    tee-drop, raw throttle/abort, the byte bound, disconnect). make check green on
    Debian 12 and openSUSE Leap 16.
  • Direct-to-guacd manual e2e harness across SSH/telnet/Kubernetes
    (util/manual-tests/).
  • Validated live through an unmodified guacamole-client gateway with a native CLI
    client in both modes, including a 20,000-line flood.

Coordinated PRs

Add an opt-in per-connection parameter, "text-output", that tees the raw
remote PTY byte stream (including ANSI/CSI/OSC sequences) to an outbound
Guacamole "pipe" stream named STDOUT, for the SSH, telnet, and Kubernetes
protocols. This lets a non-graphical / native CLI client present a terminal
session as true in-terminal text instead of decoding rasterized glyphs.
Default off; existing connections are unaffected.

The parameter is a string enum: "true" tees the raw bytes while the graphical
display is still rendered for browser users; "raw" additionally skips graphical
rendering entirely (headless); any other value, including "false" or omission,
leaves it disabled. The pipe is named STDOUT with mimetype
application/octet-stream (base64 blobs, binary-safe, charset-agnostic).

The tee is taken at the protocol source -- each protocol's PTY read path,
upstream of the terminal emulator -- rather than via guac_terminal_echo(),
which strips escape sequences. The stream is allocated on the connection
owner's user socket (an even, ack-routable index), not broadcast. New additive
public API: guac_terminal_text_output_{open,write,flush,close}.

Flow control: clients must ack every blob; the unacknowledged backlog is bounded
by bytes (256 KB). On a stalled consumer, tee mode drops buffered output (its
read loop is shared with the graphical display, so blocking would stall
co-attached browser users), while raw mode throttles the read loop, propagating
backpressure to the remote program through the PTY, and disconnects only after
15 s with no acks.

Gated behind disable-copy: guacd refuses to open the pipe when copying from the
terminal is disabled. Pipe contents are not logged or recorded by default.

Additive and opt-in: no new protocol instruction (reuses pipe/blob/end/ack), no
schema change, no ABI break. Includes CUnit coverage for the text-output paths
and a direct-to-guacd manual e2e harness for SSH/telnet/Kubernetes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant