PermessageDeflateConfig
struct PermessageDeflateConfig
Per-side knobs for the permessage-deflate extension.
All four RFC 7692 §7.1 parameters are surfaced for negotiation
- symmetry, even though the codec implementation always
runs with
no_context_takeover on both sides (see module
docstring). max_window_bits <= 15 is accepted; the codec
never produces output that violates the cap because raw
deflate with windowBits = -15 already keeps the window at
most 32 KiB.
Implements Copyable, Defaultable, Movable
- Fields
enabled: Bool: Master switch. False (the default) means the extension is neither offered (client) nor accepted (server) during the handshake.server_no_context_takeover: Bool: Whether the server MUST reset its LZ77 context at the end of each message. The codec always enforces True regardless of this value -- surfaced for handshake honesty.client_no_context_takeover: Bool: Whether the client MUST reset its LZ77 context at the end of each message. The codec always enforces True regardless of this value -- surfaced for handshake honesty.server_max_window_bits: Int: Max bits in the LZ77 sliding window the server is willing to use. Range 8..15; the codec always operates at 15.client_max_window_bits: Int: Same as :attr:server_max_window_bits for the client side.compression_level: Int: zlib compression level for outgoing messages (1..9, 0 = no compression, -1 = zlib default). Defaults to :data:DEFAULT_DEFLATE_LEVEL.max_decompressed_bytes: Int: Per-message decompressed-size cap (bytes). Defaults to :data:DEFAULT_MAX_DECOMPRESSED_BYTES (16 MiB). Set to a smaller value on memory-constrained servers; do not raise above 64 MiB without first auditing the rest of the request-pipeline for unbounded buffering.
PermessageDeflateContext
struct PermessageDeflateContext
Persistent compressor + decompressor for permessage-deflate with context-takeover (RFC 7692 §7.1).
Owns one z_stream per direction; the LZ77 sliding window
survives across :meth:compress / :meth:decompress calls
so subsequent messages benefit from the dictionary built up
by earlier ones. This is the default mode of RFC 7692 -- the
server_no_context_takeover / client_no_context_takeover
extension parameters are the opt-out knobs.
Lifetime: one instance per direction-pair per connection.
The destructor calls deflateEnd / inflateEnd and
free so leaking an instance leaks ~256 KiB of zlib state
plus the LZ77 dictionary. The struct is :class:Movable but
deliberately not :class:Copyable: copying a live handle
would double-free.
Single-threaded per instance. Two threads calling
:meth:compress simultaneously is undefined behaviour
(matches zlib's own contract). The WebSocket adapter
serialises send + receive per-connection, so this constraint
is cheap to honour.
Implements Movable
- Fields
max_decompressed_bytes: Int: Per-message decompressed-size cap. Set at construction; enforced on every :meth:decompress call.
__init__
def __init__(out self, level: Int = Int(6), window_bits: Int = Int(-15), max_decompressed_bytes: Int = Int(16777216))
Allocate a persistent compressor + decompressor pair.
- Args
level: zlib compression level (1..9; 0 = no
compression; -1 = zlib default).window_bits: Negative for raw deflate, matching the
RFC 7692 §7.1.2.1 negotiated max-window-bits
value. Default -15 = 32 KiB sliding window.max_decompressed_bytes: Per-message decompressed-size
cap; defaults to
:data:DEFAULT_MAX_DECOMPRESSED_BYTES (16 MiB).
Raises Error: If either flare_pmd_*_new returns a zlib
error code, or the heap allocation fails.
__deinit__
def __deinit__(deinit self)
Release both z_streams through the FFI; safe to call on a moved-from instance (handles are zero).
compress
def compress(mut self, data: Span[UInt8]) -> List[UInt8]
Compress one message fragment with context-takeover.
The LZ77 dictionary built up by prior calls is preserved,
so subsequent messages benefit from cross-message
repetition. The trailing 0x00 0x00 0xff 0xff sync
marker is stripped before return per RFC 7692 §7.2.1.
- Args
data: Plaintext bytes.
Raises Error: If zlib returns a negative error code.
decompress
def decompress(mut self, data: Span[UInt8]) -> List[UInt8]
Decompress one message fragment with context-takeover.
Re-appends the 0x00 0x00 0xff 0xff sync marker the
encoder stripped, then inflates against the persistent
z_stream. The output is capped at
:attr:max_decompressed_bytes to defuse zip-bomb /
compression-oracle payloads.
- Args
data: On-wire compressed payload (sync marker
stripped).
Raises Error: If the cap is exceeded or zlib reports a
non-recoverable error.