Skip to content

permessage-deflate client offer is not honored when the server omits client_no_context_takeover #1193

Description

@jhugard

Summary

In the default WebSocket++ permessage-deflate client configuration, generate_offer() advertises client_no_context_takeover. If the server accepts permessage-deflate but omits client_no_context_takeover in the response, the client still reuses compressor context across messages.

That makes the client's outbound wire behavior depend on whether the server echoed the parameter back, even though the client had already advertised that it would not retain compression context.

According to RFC 7692 7.1.1.2:

By including this extension parameter in an extension negotiation offer,
a client informs the peer server of a hint that even if the server doesn't
include the "client_no_context_takeover" extension parameter in the
corresponding extension negotiation response to the offer, the client
is not going to use context takeover.

Therefore, a partially compliant server that is configured for no context takeover but omits the response parameter can fail to decompress messages sent by the client beyond the first.


Details

The issue shows up on the client send path. A client that offered client_no_context_takeover should emit each compressed message independently. In the current implementation, client-side no-context-takeover behavior is only enabled when client_no_context_takeover appears in the negotiated response attributes.

As a result, the client offer and the runtime behavior can diverge:

  • the opening handshake advertises client_no_context_takeover
  • later compressed messages may still depend on previous compression history

Reproduction (repo-local test)

This can be reproduced with an extension-level test in test/extension/permessage_deflate.cpp:

  1. Generate a client offer and confirm it contains client_no_context_takeover
  2. Accept permessage-deflate with an empty response attribute list
  3. Initialize the client extension
  4. Compress the same deterministic 4096-byte message twice
  5. Decompress the first output with one server-side extension instance
  6. Decompress the second output with a fresh server-side extension instance

Current behavior

  • the first message decompresses correctly
  • the second message assumes prior compressor history and does not decode correctly with a fresh receiver
  • identical inputs do not yield independently decodable outputs under the advertised no-context-takeover behavior

Expected behavior

If the client offers client_no_context_takeover and the extension is negotiated, each outbound compressed message should be independent of previous messages, even when the server omits client_no_context_takeover from the response.

In the repro above, both compressed outputs should decompress correctly when handled by separate fresh server-side extension instances.


Actual behavior

The client only switches to no-context-takeover behavior when the server response explicitly includes client_no_context_takeover. If the server accepts permessage-deflate without echoing that parameter, the client still reuses compression context across messages.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions