# flare.ws.server_reactor

> A module of flare_mlake's API.

Event-driven WebSocket handlers for HTTP/1.1 upgrades on the reactor.

``WsUpgrade.on_reactor(handler)`` keeps an upgraded connection on the
reactor worker that accepted it: the worker reads it without blocking,
runs the RFC 6455 rules in :class:`flare.ws.protocol.WsProtocol`, and
calls the handler once per event. No thread is spawned per connection,
and a client that stops reading is cut off at the session's outbox
bound instead of growing memory.

Each connection gets its own copy of the handler, made from the one the
server was configured with, so per-connection state can live on
``self``; the copy is destroyed when the connection ends.

## Structs

### `WsSession`

```mojo
struct WsSession
```

One upgraded connection as a handler sees it.

Implements: `Movable`

Fields:

- `proto: WsProtocol`
- `peer: SocketAddr`
- `origin: String`: The handshake's ``Origin`` (the last one if repeated), or ``""``.

#### `__init__`

```mojo
def __init__(out self, peer: SocketAddr, var origin: String, max_message: Int, max_outbox: Int)
```

#### `send_text`

```mojo
def send_text(mut self, msg: String)
```

Queue a TEXT message. Raises after a CLOSE, and when the peer is too far behind (the session then closes with 1008).

#### `send_binary`

```mojo
def send_binary(mut self, data: List[UInt8])
```

Queue a BINARY message; raises as :meth:`send_text` does.

#### `close`

```mojo
def close(mut self, code: UInt16 = UInt16(1000))
```

Start the closing handshake.

### `WsReactorHooks`

```mojo
struct WsReactorHooks
```

A boxed handler prototype and its monomorphised thunks.

The prototype is never called; each connection gets a clone
(:meth:`clone_handler`) and destroys it on teardown. The prototype
lives as long as the server configuration that holds it.

Implements: `Copyable`, `Movable`

Fields:

- `addr: Int`
- `open_thunk: def(Int, mut WsSession) raises thin -> None`
- `msg_thunk: def(Int, mut WsSession, var WsMessage) raises thin -> None`
- `close_thunk: def(Int, mut WsSession, Int) thin -> None`
- `destroy_thunk: def(Int) thin -> None`
- `clone_thunk: def(Int) raises thin -> Int`
- `max_message: Int`
- `max_outbox: Int`
- `idle_timeout_ms: Int`

#### `__init__`

```mojo
def __init__(out self, addr: Int, open_thunk: def(Int, mut WsSession) raises thin -> None, msg_thunk: def(Int, mut WsSession, var WsMessage) raises thin -> None, close_thunk: def(Int, mut WsSession, Int) thin -> None, destroy_thunk: def(Int) thin -> None, clone_thunk: def(Int) raises thin -> Int, max_message: Int, max_outbox: Int, idle_timeout_ms: Int)
```

#### `clone_handler`

```mojo
def clone_handler(self) -> Int
```

## Traits

### `WsReactorHandler`

```mojo
undefined
```

Edge-driven handler for HTTP/1.1 WebSocket connections.

Implements: `Copyable`, `Movable`

#### `on_open`

```mojo
def on_open(mut self, mut ws: WsSession)
```

Called once, right after the upgrade.

#### `on_message`

```mojo
def on_message(mut self, mut ws: WsSession, var msg: WsMessage)
```

Called per complete message (fragments already reassembled, text already validated as UTF-8).

#### `on_close`

```mojo
def on_close(mut self, mut ws: WsSession, code: Int)
```

Called once when the connection ends, whichever side ended it: the code from the closing handshake, or 1006 when the connection dropped without one.

## Functions

### `make_ws_reactor_hooks`

```mojo
def make_ws_reactor_hooks[W: WsReactorHandler](var handler: W, max_message: Int = Int(16777216), max_outbox: Int = Int(4194304), idle_timeout_ms: Int = Int(60000)) -> WsReactorHooks
```

Box ``handler`` as the prototype for every connection's copy.
