WsConnection
struct WsConnectionAn accepted WebSocket connection (server side).
Server-side frames MUST NOT be masked (RFC 6455 §5.3).
Client-side frames MUST be masked; recv unmasks them automatically.
This type is Movable but not Copyable.
A CLOSE received by :meth:recv is answered here (RFC 6455 sec
5.5.1), and once a CLOSE has been sent, by that reply or by
:meth:close, every send_* raises: an endpoint MUST NOT send
data after its CLOSE.
Fields:
_stream: The underlying TCP stream.
_peer: The remote socket address.
origin: The handshake Origin header (empty when absent).
Example:
def on_connect(conn: WsConnection) raises:
var frame = conn.recv()
conn.send_text(frame.text_payload()) # echo back
var srv = WsServer.bind(SocketAddr.localhost(9001))
srv.serve(on_connect)
Implements Movable
- Fields
origin: String: TheOriginheader sent with the upgrade handshake, or empty when the client sent none.max_frame_size: Int: Largest frame payload :meth:recvaccepts. A client frame that declares more is answered with CLOSE 1009 (MESSAGE_TOO_BIG) and :meth:recvraises, before any of the payload is buffered. Defaults to :data:DEFAULT_MAX_FRAME_BYTES; set it in the handler before the firstrecvto change it.
__init__
def __init__(out self, var stream: TcpStream, peer: SocketAddr, var origin: String = "") def __init__(out self, var stream: TcpStream, peer: SocketAddr, var prebuf: List[UInt8], var origin: String = "") Construct a WsConnection seeded with already-buffered post-handshake bytes.
Used by the HttpServer WebSocket-upgrade seam to hand off
any frame bytes the HTTP reactor had already read past the
upgrade request. prebuf is consumed by the first
recv/_recv_one before any socket read.
- Args
stream: The upgraded connection, already in blocking mode.peer: Remote address, for :attr:peer.prebuf: Bytes the reactor read past the upgrade request.origin: The handshake'sOrigin, for :attr:origin.
__deinit__
def __deinit__(deinit self) send_text
def send_text(self, msg: String) Send a UTF-8 text message to the client.
Server-to-client frames are NOT masked (RFC 6455 §5.3).
- Args
msg: The UTF-8 string to send.
Raises NetworkError: On I/O failure, or if a CLOSE was already sent.
send_binary
def send_binary(self, data: List[UInt8]) Send a binary message to the client.
Server-to-client frames are NOT masked (RFC 6455 §5.3).
- Args
data: The raw binary payload.
Raises NetworkError: On I/O failure, or if a CLOSE was already sent.
send_frame
def send_frame(mut self, frame: WsFrame) Send an already-constructed frame (server, no masking).
Sending a CLOSE frame marks the closing handshake as started, the
same as :meth:close; a second CLOSE is dropped.
- Args
frame: Frame to send. Themaskbit is alwaysFalse.
Raises NetworkError: On I/O failure, or if a CLOSE was already sent.
recv
def recv(mut self) -> WsFrame Receive the next data frame from the client.
Automatically replies to PING frames with an unmasked PONG and
continues reading. Returns TEXT or BINARY frames. Client frames
are unmasked by WsFrame.decode_one automatically.
A CLOSE frame is answered before it is returned (RFC 6455 sec
5.5.1): with the received status code, with an empty CLOSE when
the body is empty, or with 1002 when the body is invalid (a
1-byte body, a code that may not be sent, a reason that is not
UTF-8). The reply is skipped if :meth:close already sent a
CLOSE. The frame is still returned, so a handler can leave its
loop; later send_* calls raise.
A frame that violates the protocol fails the connection after a
best-effort CLOSE: an unmasked client frame with 1002 (RFC 6455
sec 5.1), a final TEXT frame whose payload is not valid UTF-8
with 1007 (sec 8.1), an oversized frame with 1009. recv
raises in each case and later send_* calls raise too.
Raises WsProtocolError: If the client sends an unmasked frame, or a final TEXT frame that is not valid UTF-8. NetworkError: On I/O failure.
recv_message
def recv_message(mut self) -> WsMessage Receive the next complete message, reassembled.
A fragmented message (a TEXT or BINARY frame without FIN, then
CONTINUATION frames up to one with FIN, RFC 6455 sec 5.4) comes
back whole; :meth:recv returns its pieces one by one. PING is
answered and PONG skipped, between fragments too. A text message
is checked for UTF-8 as a whole, so a code point may be split
across fragments. The reassembled payload is bounded by
max_frame_size.
Raises NetworkError: If the client sent CLOSE (already answered by
:meth:recv), or on I/O failure.
WsProtocolError: After failing the connection with 1002 for a
CONTINUATION with no message to continue or a new data
frame inside a fragmented one, 1007 for a text message
that is not UTF-8, 1009 for a message over
max_frame_size.
close
def close(mut self, code: UInt16 = UInt16(1000), reason: String = "") Send a CLOSE frame, once.
Starts the closing handshake (RFC 6455 sec 7.1.2) and does not
wait for the peer's CLOSE: call :meth:recv to read it. A second
call, or a call after :meth:recv has already answered the
client's CLOSE, sends nothing. After this every send_* raises.
- Args
code: Close status code (seeWsCloseCode.*).reason: Optional UTF-8 reason phrase (≤123 bytes).
peer_addr
def peer_addr(self) -> SocketAddr Return the remote socket address.