Skip to content

blackbull.client.websocket_h2

blackbull.client.websocket_h2

WebSocket-over-HTTP/2 client (RFC 8441).

Mirrors the HTTP/1.1 :class:blackbull.client.WebSocketClient / :class:blackbull.client.WebSocketSession pair: the Client owns the TLS + HTTP/2 transport and runs the Extended CONNECT handshake; the Session owns the post-handshake WebSocket frame loop on one H2 stream.

Flow control: outgoing WS frames are dispatched as http.response.body events through the per-stream :class:blackbull.server.sender.HTTP2Sender, which splits payloads across multiple DATA frames at max_frame_size and respects send windows. Incoming DATA payloads are tracked per stream + at the connection level; WINDOW_UPDATE frames are emitted when received bytes accumulate past :data:_WINDOW_UPDATE_THRESHOLD.

Example::

import ssl
from blackbull.client import WebSocketH2Client

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
ctx.set_alpn_protocols(['h2'])

async with WebSocketH2Client('localhost', 8443, ssl=ctx) as c:
    ws = await c.connect('/ws')
    await ws.send_bytes(b'hello')
    opcode, payload = await ws.receive()
    await ws.close()

The peer server must advertise SETTINGS_ENABLE_CONNECT_PROTOCOL=1; BlackBull's own server does so when BB_H2_ENABLE_WEBSOCKET=1.

RFC 8441 is an experimental surface in BlackBull — both the server gate and this client may change shape until the feature is declared default-on.

WebSocketH2Client

Async WebSocket-over-HTTP/2 client (RFC 8441).

Owns the TLS + HTTP/2 connection; performs the Extended CONNECT handshake (:method=CONNECT, :protocol=websocket) on :meth:connect and returns a :class:WebSocketH2Session for post-handshake frame I/O.

The peer server must advertise SETTINGS_ENABLE_CONNECT_PROTOCOL=1; BlackBull's server does so when BB_H2_ENABLE_WEBSOCKET=1.

connect_status property

:status from the last Extended CONNECT response, or None if :meth:connect has not run yet.

connect(path='/', *, response_timeout=5.0) async

Run the RFC 8441 Extended CONNECT handshake on this connection.

Returns a :class:WebSocketH2Session bound to the new H2 stream. Raises :class:HandshakeError on a non-200 :status response or :class:TimeoutError if no response arrives within response_timeout.

WebSocketH2Session

Frame-level WebSocket session over one HTTP/2 stream.

Outgoing frames are masked (RFC 6455 §5.1) and wrapped in H2 DATA frames. Incoming H2 DATA frame payloads are reassembled into WebSocket frames in an internal buffer.

close(code=_CLOSE_CODE_NORMAL) async

Send a WebSocket close frame with the requested code and END_STREAM on the carrying H2 DATA frame. Idempotent.

receive(timeout=5.0) async

Return (opcode, payload) for the next complete WebSocket frame on this stream.

Raises :class:TimeoutError if no frame arrives within timeout. Returned opcodes match :class:blackbull.server.ws_codec.WSOpcode.