Skip to content

ws: do not auto-pong in raw mode - #23040

Closed
filtede98 wants to merge 1 commit into
curl:masterfrom
filtede98:fix-ws-raw-mode-auto-pong
Closed

filtede98 wants to merge 1 commit into
curl:masterfrom
filtede98:fix-ws-raw-mode-auto-pong

Conversation

@filtede98

Copy link
Copy Markdown
Contributor

Summary

According to CURLOPT_WS_OPTIONS(3):

"In raw mode, libcurl does not handle pings or any other frame for the application."

However, in lib/ws.c (ws_cw_dec_next() and ws_client_collect()), auto_pong was computed as:

bool auto_pong = !data->set.ws_no_auto_pong;

which omitted checking data->set.ws_raw_mode.

Consequence

When receiving a WebSocket PING frame while CURLWS_RAW_MODE is enabled:

  1. auto_pong evaluates to true, causing libcurl to intercept the PING frame and discard it from the application stream (ctx.written remains unset).
  2. libcurl enqueues an automatic PONG into ws->pending.
  3. In curl_ws_recv(), line 1689 checks if(!data->set.ws_raw_mode && ws->pending.type), intentionally skipping flushing pending control frames in raw mode. Consequently, the peer never receives a pong reply and may timeout.
  4. When the application subsequently sends raw frames using curl_ws_send(), ws_flush() calls ws_enc_add_pending(), injecting the queued PONG control frame directly into the application's raw stream, corrupting user frame boundaries and protocol state.

Fix

Disable auto_pong whenever ws_raw_mode is active:

bool auto_pong = !data->set.ws_raw_mode && !data->set.ws_no_auto_pong;

Verified with checksrc.pl (0 warnings).

CURLOPT_WS_OPTIONS(3) documents that in raw mode (CURLWS_RAW_MODE),
libcurl does not handle pings or any other frame for the application.

Previously, auto_pong only checked !data->set.ws_no_auto_pong, ignoring
data->set.ws_raw_mode. As a result, receiving a PING in raw mode caused
libcurl to intercept the frame, discard it from the application stream,
and queue an automatic PONG into ws->pending. When sending raw data via
curl_ws_send(), ws_flush() would inject this unexpected PONG control frame
into the application's raw stream, corrupting message framing.

Disable auto_pong whenever ws_raw_mode is active.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The connect-only raw-mode regression needs automated test coverage.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
What changed in this PR

Prevents automatic WebSocket PONG handling in raw mode.

Changes:

  • Disables auto-PONG in callback and curl_ws_recv() paths when raw mode is enabled.
File Description
lib/​ws.c Adds raw-mode checks to auto-PONG logic.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/ws.c
struct ws_collect *ctx = userp;
struct Curl_easy *data = ctx->data;
bool auto_pong = !data->set.ws_no_auto_pong;
bool auto_pong = !data->set.ws_raw_mode && !data->set.ws_no_auto_pong;
@filtede98
filtede98 force-pushed the fix-ws-raw-mode-auto-pong branch from 30089cd to 73fdcde Compare September 22, 2026 12:55
@github-actions github-actions Bot added the tests label Sep 22, 2026
@filtede98
filtede98 force-pushed the fix-ws-raw-mode-auto-pong branch from 73fdcde to 30089cd Compare September 22, 2026 13:27
@bagder bagder closed this in 664d00d Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants