Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
005e946
add WebSocket endpoint support
heshammahamed Jun 28, 2026
6fa0377
implement WebSocket handler construction
heshammahamed Jun 28, 2026
1d9be51
Fix WebSocket handler generation in server.alusus
heshammahamed Jun 30, 2026
37b4ea0
Generate URI checks for @wsEndpoint paths in requestCallback
heshammahamed Jun 30, 2026
6ea9e7d
Replace shared connection Map with per-connection userData
heshammahamed Jul 5, 2026
66655c3
refactor(websocket): declare endpoint handlers per-function instead o…
heshammahamed Jul 6, 2026
df16361
map string to ptr -- map[String , ptr[TiObject]] -- instead of mappin…
heshammahamed Jul 7, 2026
39a8fee
correct sume bugs in function extractElementsWithGivenModifier inside…
heshammahamed Jul 7, 2026
ac575d0
feat(websocket): make onConnect/onReady/onData/onClose handlers optional
heshammahamed Jul 9, 2026
3fb6208
fix(websocket): remove trailing comma in setWebSocketHandler ast temp…
heshammahamed Jul 10, 2026
9d2d81b
feat(websocket): add handshake info snapshot to wsConnection
heshammahamed Jul 10, 2026
5d079af
feat(websocket): add maxMessageSize, fragmentation reassembly, and cl…
heshammahamed Jul 11, 2026
ca99d38
(websoxket) Capitalize class name from ws_connection to Ws_connection
heshammahamed Jul 11, 2026
76c7679
(websocket) : return back to classes
heshammahamed Jul 14, 2026
ee79a82
(websocket): instantiate user's WsRoute-derived class per endpoint
heshammahamed Jul 15, 2026
39a960a
(server): enable CivetWeb's built-in ping/pong handling
heshammahamed Jul 15, 2026
68d4b32
refactor(server): remove duplicate function, rename extractModifiersP…
heshammahamed Jul 15, 2026
e87eff2
feat(websocket): store close status code and reason for exposure via …
heshammahamed Jul 19, 2026
dc49adf
fix(websocket): segfault in close() methode when a reason message is…
heshammahamed Jul 19, 2026
6edc04b
feat(websocket): handle write failures in send/close, add request/web…
heshammahamed Jul 19, 2026
d9b2c14
feat(websocket): add getStatus() and CLOSING transition to close paths
heshammahamed Jul 19, 2026
ae4d794
fix(websocket): reject unrecognized/reserved opcodes as a protocol error
heshammahamed Jul 19, 2026
c239f2a
Clean up the design of web sockets
sarmadka Jul 30, 2026
a824d9a
fix(websocket): test and fix compiler crash and memory corruption aft…
heshammahamed Aug 2, 2026
5d15236
feat(websocket): expose connection pointer to onConnect handler for h…
heshammahamed Aug 2, 2026
2f8591f
fix(websocket): setMaxMessageSize handler failed to compile due to mi…
heshammahamed Aug 2, 2026
99ab063
docs(websocket): create Arabic and English documents
heshammahamed Aug 2, 2026
242de95
feat(websocket): add Arabic aliases for WsConnection and WsStatus
heshammahamed Aug 2, 2026
3a553d7
feat(websocket): add browser-side WebSocket client API
heshammahamed Aug 3, 2026
683f117
docs(websocket): fix wrong comment about websocket_timeout_ms
heshammahamed Aug 3, 2026
9865cef
refactor(websocket): rework browser client construction and error rep…
heshammahamed Aug 4, 2026
26f79d2
docs(websocket): add browser WebSocket client API (EN/AR)
heshammahamed Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
416 changes: 416 additions & 0 deletions Doc/webSocketApi.ar.md

Large diffs are not rendered by default.

227 changes: 227 additions & 0 deletions Doc/webSocketApi.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# WebSocket Browser Api

The browser-side counterpart to the server-side `WsConnection`.

Read the [MDN WebSocket API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) docs first
to understand the underlying browser object this class wraps.

#### construction of the object

```
class WebSocket {
def onOpen: Signal[WebSocket, Int];
def onMessage: Signal[WebSocket, WsMessageInfo];
def onError: Signal[WebSocket, Int];
def onClose: Signal[WebSocket, WsCloseInfo];

func create(url: ptr[Char], protocols: ptr[Char]): SrdRef[WebSocket];
func create(url: ptr[Char]): SrdRef[WebSocket];

handler this.sendText(data: ptr[Char]): ptr[array[Char]];
handler this.sendBinary(data: ptr[Char], dataLen: ArchWord): ptr[array[Char]];

handler this.close(): ptr[array[Char]];
handler this.close(code: Int): ptr[array[Char]];
handler this.close(code: Int, reason: ptr[Char]): ptr[array[Char]];

handler this.getState(): Int;
handler this.getUrl(): ptr[array[Char]];
handler this.getProtocol(): ptr[array[Char]];
handler this.getExtensions(): ptr[array[Char]];
handler this.getBufferedAmount(): ArchWord;
}
```

#### create a websocket instance

```
func create(url: ptr[Char], protocols: ptr[Char]): SrdRef[WebSocket];
func create(url: ptr[Char]): SrdRef[WebSocket];
```

You get an instance by calling `WebSocket.create(url)` (or `WebSocket.create(url, protocols)` to
offer subprotocols) — this is the *only* way to get one; there is no public constructor. It returns
a `SrdRef[WebSocket]`.

Always check whether the returned `SrdRef[WebSocket]` `.isNull()` before using it. It will be null if
something went wrong constructing the underlying browser WebSocket object — an invalid URL, a bad
scheme, malformed protocols, a URL containing a fragment, etc.

See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket#exceptions) for the
exact list of exception cases.
This mirrors the real API: if the browser constructor throws, you never get an object back, so this
library never hands you a broken instance either — `create()` builds the object, attempts the
connection, and releases it again before returning if that attempt failed synchronously.

```
def ws: SrdRef[WebSocket] = WebSocket.create("ws://localhost:8060/echo");
if ws.isNull() {
// bad URL/protocols - the connection never started
}
```

A `true` return from `create()`/a non-null `SrdRef` only means the connection attempt has started —
it does **not** mean the connection is open yet. Wait for `onOpen` for that.

### events

#### onOpen

```
def onOpen: Signal[WebSocket, Int];
```

Fires once the connection is established. Payload is unused (`Int`, always `0`).

See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/open_event) for exactly when
this event fires.

#### onMessage

```
def onMessage: Signal[WebSocket, WsMessageInfo];
```

Fires once per received message. Payload is a `WsMessageInfo`, carrying the message's type (text or
binary) and its data:

```
class WsMessageInfo {
def data: String;
def isBinary: Bool;
}
```

* `data`: the message content. For text messages, the text itself. For binary messages, the raw bytes wrapped in a `String`.
* `isBinary`: `true` if the message was sent as binary, `false` if sent as text.

See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event) for exactly when
this event fires.

#### onError

```
def onError: Signal[WebSocket, Int];
```

Fires on a genuine connection-level error. Payload is unused (`Int`, always `0`).

See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event) for exactly when
this event fires.

#### onClose

```
def onClose: Signal[WebSocket, WsCloseInfo];
```

Fires once the connection is fully closed, whether initiated locally or by the server. Payload is a
`WsCloseInfo`:

```
class WsCloseInfo {
def code: Int;
def reason: String;
def wasClean: Bool;
}
```

* `code`: the WebSocket close code.
* `reason`: the close reason string, if any.
* `wasClean`: whether the closing handshake completed cleanly.

See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close_event) for exactly when
this event fires.

## websocket object methodes

#### sendText

```
handler this.sendText(data: ptr[Char]): ptr[array[Char]];
```

Sends a text message.

Returns a null pointer if the browser doesn't throw an exception,
or returns a pointer to the error message if an exception is thrown.

See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send#exceptions) for exactly
when the underlying exception is raised.

#### sendBinary

```
handler this.sendBinary(data: ptr[Char], dataLen: ArchWord): ptr[array[Char]];
```

Sends `dataLen` raw bytes starting at `data`. Same return convention as `sendText`.

## close

```
handler this.close(): ptr[array[Char]];
handler this.close(code: Int): ptr[array[Char]];
handler this.close(code: Int, reason: ptr[Char]): ptr[array[Char]];
```

Closes the connection. The no-argument form uses code `1000` (normal closure) with no reason; the
other overloads let you specify a code and/or reason.

Returns a null pointer if the browser doesn't throw an exception,
or returns a pointer to the error message if an exception is thrown.

See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#exceptions) for exactly
when the underlying exception is raised.

## state

these methodes return the properties in the [Websocket browser API object](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).

They all keep working after the connection has closed, same as the real `WebSocket` object does —
closing a connection doesn't make it stop being queryable. They only stop being valid once the
`WebSocket` object itself is destroyed.

#### getState

```
handler this.getState(): Int;
```

return the [readyState](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState) prop on the Websocket browser object.

#### getUrl

```
handler this.getUrl(): ptr[array[Char]];
```
return the [url](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/url) prop on the Websocket browser object.

#### getProtocol

```
handler this.getProtocol(): ptr[array[Char]];
```

return the [protocol](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/protocol) prop on the Websocket browser object.

#### getExtensions

```
handler this.getExtensions(): ptr[array[Char]];
```
return the [extensions](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/extensions) prop on the Websocket browser object.

#### getBufferedAmount

```
handler this.getBufferedAmount(): ArchWord;
```

return the [bufferedAmount](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount) prop on the Websocket browser object.

## lifetime

There's no explicit "disconnect and free" method — destroying the `SrdRef[WebSocket]` (it going out
of scope, being reassigned, or `.release()` being called on it) closes the connection with status code (1000) and cleans
everything up automatically.
Loading