curl icon indicating copy to clipboard operation
curl copied to clipboard

WebSocket: with CURLWS_NOAUTOPONG, incoming zero-payload PING is neither delivered to WRITEFUNCTION nor auto-responded (8.14.1)

Open cyanide-burnout opened this issue 1 month ago • 2 comments

I did this

Mode: multi + write-callback (not CONNECT_ONLY), CURLOPT_WS_OPTIONS = CURLWS_NOAUTOPONG Server: wss://zello.io/ws (servers sends PING with payload=0)

Observed: When the server sends a WebSocket PING with payload length 0, libcurl does not invoke the CURLOPT_WRITEFUNCTION at all (so curl_ws_meta() can’t be used). Since CURLWS_NOAUTOPONG is set, libcurl does not auto-reply either. The application has no way to learn about the PING in the write-callback model and cannot send PONG; the server disconnects.

I expected the following

If CURLWS_NOAUTOPONG is set, libcurl should always deliver PING to the application — even with len==0 — e.g. by calling the write callback with size*nmemb==0 and curl_ws_meta()->flags & CURLWS_PING, or provide an officially supported non-blocking way to retrieve such control frames in the write-callback model.

curl/libcurl version

curl 8.14.1 (x86_64-pc-linux-gnu) libcurl/8.14.1 OpenSSL/3.5.1 zlib/1.3.1 brotli/1.1.0 zstd/1.5.7 libidn2/2.3.8 libpsl/0.21.2 libssh2/1.11.1 nghttp2/1.64.0 nghttp3/1.8.0 librtmp/2.3 OpenLDAP/2.6.10 Release-Date: 2025-06-04, security patched: 8.14.1-2 Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTP3 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd

operating system

Linux a 6.12.38+deb13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.38-1 (2025-07-16) x86_64 GNU/Linux

cyanide-burnout avatar Nov 16 '25 16:11 cyanide-burnout

It also seems like CURLOPT_WRITEFUNCTION doesn’t handle empty CURLWS_PONG

cyanide-burnout avatar Nov 17 '25 08:11 cyanide-burnout

@cyanide-burnout we improved curl's websocket in fa3baabbd81ab9f0aa50bc6335a3e315be0e3009, which has been released in curl 8.16.0. Could you check with a recent curl? Best would be 8.17 or the master branch.

As to sending PONG replies, this indeed cannot be done from the WRITEFUNCTION. You would need to add a READFUNCTION and use the new curl_ws_start_frame() from there. See https://curl.se/libcurl/c/curl_ws_start_frame.html

icing avatar Nov 18 '25 12:11 icing