curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Detecting final frame of a received WebSocket message.

From: Paul Fotheringham via curl-library <>
Date: Wed, 13 Sep 2023 20:52:11 +0100


I posted back in July asking about how to detect the final frame in a
fragmented WebSocket message because I couldn't see how it was exposed
in the libcurl API. Daniel, you asked some questions so apologies for
the delay.

I can confirm that the received frames in my own set-up were all
received as complete frames i.e. the bytesleft field was set to zero
in each.

You were looking for a simple example. I've had a look at the libtest
stuff and was going to put one together when I noticed that the
existing test case libtest/lib2305.c is a perfect example!

In 2305 the server is told to send a 12291 byte message over 3 frames
each containing 4097 bytes of the message. The frame headers in hex
(all 4 bytes) are (from data/test2305):

frame 1 header: 01 7e 10 01
frame 2 header: 01 7e 10 01
frame 3 header: 81 7e 10 01

where the first byte determines the FIN bit and the opcode. The
remaining three bytes are all payload size-related so can be ignored.
The first bit of the first byte is the FIN flag so it is unset in the
first two frames and set in the last which would indicate to me that
this is a genuine, complete multi-frame message.

The last four bits of the first byte are the opcode so it is
CURLWS_TEXT in each. This is not what the websocket standard describes
for a fragmented message though. The first frame should be
CURLWS_TEXT, but the second and third should both be CURLWS_CONT i.e.
4 rather than 1.

Regardless of the opcode mix-up there is still no way AFAICS see to
detect the final frame via the API as the FIN bit is not exposed in
the curl_ws_frame meta structure. The test code simply counts the
bytes received and stops when it hits 12291 but that will not work in
general as the size of a fragmented message never appears on the wire
at any point (as part of the protocol) and may not even be known by
the sender at the point the first frame is sent.

I also now realise that sending a fragmented message seems to be
impossible too for a varietly of reasons but I can go into that in a
further post.

For this receiving issue (and ultimately the sending issue) can I
propose that we add an int into the curl_ws_frame to correspond to the
FIN bit (in future this can also house the three other reserved flag

If that sounds okay then I am happy to create a PR for it including
updating test 2305 to use it.

Received on 2023-09-13