8000 WebSocket continuation flag inverted for received fragments · Issue #15298 · curl/curl · GitHub
[go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebSocket continuation flag inverted for received fragments #15298

Open
polarina opened this issue Oct 14, 2024 · 2 comments
Open

WebSocket continuation flag inverted for received fragments #15298

polarina opened this issue Oct 14, 2024 · 2 comments

Comments

@polarina
Copy link
polarina commented Oct 14, 2024

I did this

The documentation has this to say about CURLWS_CONT:

CURLWS_CONT
This is not the final fragment of the message, it implies that there is another fragment coming as part of the same message.

This is neither the observed behaviour nor in accordance with RFC 6455.

RFC 6455 has this to say about fragmented messages:

A fragmented message consists of a single frame with the FIN bit
clear and an opcode other than 0, followed by zero or more frames
with the FIN bit clear and the opcode set to 0, and terminated by
a single frame with the FIN bit set and an opcode of 0.

A single text message split into three fragments, as received by the write callback, is reported by curl_ws_meta as follows:

  1. Only CURLWS_TEXT set in flags, FIN bit not set.
  2. Only CURLWS_CONT set in flags, FIN bit not set.
  3. Only CURLWS_CONT set in flags, FIN bit set.

The third fragment has the FIN bit set, but this is not exposed by libcurl. It is thus not possible for an application to determine which frame is the final fragment of a message.

I expected the following

I expected the fragments to be received as follows, to conform to what the libcurl documentation states:

  1. Both CURLWS_TEXT and CURLWS_CONT set.
  2. Both CURLWS_TEXT and CURLWS_CONT set.
  3. Only CURLWS_TEXT set.

curl/libcurl version

8.6.0

operating system

Fedora 40

@polarina
Copy link
Author

Workaround

The following snippet appears to "work" as a temporary workaround, as well as adjusting the usage of flags in the WebSocket write callback and checking is_fin accordingly.

static int mycurl_debugfunction(
	CURL *handle,
	curl_infotype type,
	char *data,
	size_t size,
	void *clientp)
{
	(void) handle;
	(void) type;

	bool *is_fin = clientp;

	const char prefix[] = "WS-DEC: decoded [";
	const char nonfinal[] = "NON-FINAL";

	if (size >= sizeof(prefix)-1 && memcmp(data, prefix, sizeof(prefix)-1) == 0) {
		bool is_nonfinal = memmem(data, size, nonfinal, sizeof(nonfinal)-1);
		*is_fin = !is_nonfinal;
	}

	return 0;
}
bool is_fin;

curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, mycurl_debugfunction);
curl_easy_setopt(curl, CURLOPT_DEBUGDATA, &is_fin);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

@curl curl deleted a comment Oct 28, 2024
@polarina
Copy link
Author
polarina commented Nov 6, 2024

Now that curl 8.11.0 is out with WebSocket support no longer marked as experimental, will it be possible to fix this bug without an API change? Receiving fragmented messages is broken as it stands, an application has no way to reassemble fragments into a message without parsing the debug log.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants
@polarina and others
0