152 lines
4.7 KiB
Typst
152 lines
4.7 KiB
Typst
#import "@preview/ilm:1.4.1": *
|
|
#import "@preview/fletcher:0.5.8" as fletcher: diagram, node, edge, shapes
|
|
|
|
#show link: underline
|
|
#show link: set text(fill: blue)
|
|
|
|
#set text(lang: "en")
|
|
|
|
#show: ilm.with(
|
|
title: [SchoolBOX WS],
|
|
author: "Jurn Wubben",
|
|
date: datetime.today(),
|
|
abstract: [Websocket comminucation between the SchoolBox device and the associated server.],
|
|
figure-index: (enabled: false),
|
|
table-index: (enabled: false),
|
|
listing-index: (enabled: false)
|
|
)
|
|
|
|
= Messages
|
|
== Heartbeat
|
|
=== Server
|
|
- ```json
|
|
{"c": "ping"}
|
|
```<ping>
|
|
- ```json
|
|
{"e": 0, "info": "Pong missed"}
|
|
```<pongmissed>
|
|
|
|
=== Device
|
|
- ```json
|
|
{"c": "pong"}
|
|
```<pong>
|
|
|
|
== Registration
|
|
=== Server
|
|
- ```json
|
|
{"c": "reg_pin", "d": {"pin": 1234}} // Pin is a random integer. Length doesn't really matter, as long as it fits on the screen.
|
|
```<reg_pin>
|
|
- ```json
|
|
{"c": "reg_ok"}
|
|
```<reg_ok>
|
|
|
|
=== Device
|
|
- ```json
|
|
{"c": "reg_start"}
|
|
```<reg_start>
|
|
|
|
|
|
== Authentication
|
|
=== Server
|
|
- ```json
|
|
{"c": "auth_nonce", "d": {"nonce": "random_string"}} // Should be a long, random generated string.
|
|
```<auth_nonce>
|
|
- ```json
|
|
{"c": "auth_ok"}
|
|
```<auth_ok>
|
|
- ```json
|
|
{"e": 1, "info": "Invalid packet, wrong ID."}
|
|
```<auth_error_id>
|
|
- ```json
|
|
{"e": 2, "info": "Invalid signature."} // the info doesn't matter
|
|
```<auth_error_sig>
|
|
- ```json
|
|
{"e": 3, "info": "Logged in at other place."} // the info doesn't matter
|
|
```<auth_error_takeover>
|
|
|
|
=== Device
|
|
- ```json
|
|
{"c": "auth_start", "d": {"id": "id"}} // Id that is provided with registration.
|
|
```<auth_start>
|
|
- ```json
|
|
{"c": "auth_validate", "d": {"signature": "HMAC hash of nonce"}}
|
|
```<auth_validate>
|
|
- The HMAC is a SHA256 with the password as the key, and the nonce as the data.
|
|
- The returned signature is encoded as hex.
|
|
- #link("https://git.jsw.tf/jsw/schoolbox-ws/src/commit/6acc935609d5c0de52aa752b69ccbaea84301b87/src/auth.ts#L9-L32")[Example implementation in JS.]
|
|
== Session
|
|
=== Server
|
|
- ```json
|
|
{"c": "session_start", "d": {"text": "Question?"}}
|
|
```<session_start>
|
|
- ```json
|
|
{"c": "session_stop"}
|
|
```<session_stop>
|
|
|
|
=== Device
|
|
- ```json
|
|
{"c": "session_vote", "d": {"vote": 1}} // Vote is an integer in the range of 1..5
|
|
```<session_vote>
|
|
|
|
|
|
= General flow
|
|
#let arrLine = (arr) => {
|
|
for (i, el) in arr.enumerate() {
|
|
if i == 0 or i == arr.len() {
|
|
continue
|
|
}
|
|
edge(arr.at(i - 1), el, "-|>")
|
|
}
|
|
}
|
|
|
|
#let l = link;
|
|
|
|
#align(center, diagram(
|
|
node-stroke: 1pt,
|
|
|
|
node((1,0), [New connection], corner-radius: 2pt, extrude: (0, 3), name: <flow_new>),
|
|
|
|
node((3, 0), l(<ping>)[ping], name: <flow_ping>),
|
|
node((3, 1), l(<pong>)[pong], stroke: blue, name: <flow_pong>),
|
|
|
|
node((0,1), l(<reg_start>)[reg_start], name: <flow_reg_start>, stroke: blue),
|
|
node((0,2), l(<reg_pin>)[reg_pin], name: <flow_reg_pin>),
|
|
node((0,3), l(<reg_ok>)[reg_ok], name: <flow_reg_ok>),
|
|
node((0,4), [Disconnect], name: <flow_disconnect>, corner-radius: 2pt, extrude: (0, 3)),
|
|
|
|
node((2,1), l(<auth_start>)[auth_start], name: <flow_auth_start>, stroke: blue),
|
|
node((1,1), l(<auth_error_id>)[auth error id], name: <flow_auth_error_id>),
|
|
node((2,2), l(<auth_nonce>)[auth_nonce], name: <flow_auth_nonce>),
|
|
node((1,3), l(<auth_error_sig>)[auth error signature], name: <flow_auth_error_sig>),
|
|
node((2,3), l(<auth_validate>)[auth_validate], name: <flow_auth_validate>, stroke: blue),
|
|
node((2,4), l(<auth_ok>)[auth_ok], name: <flow_auth_ok>),
|
|
node((1,5), [Logged in], corner-radius: 2pt, extrude: (0, 3), name: <flow_loggedin>),
|
|
|
|
edge(<flow_ping>, <flow_pong>, "<|-|>", label: [Every 30s]),
|
|
|
|
edge(<flow_new>, "l", <flow_reg_start>, "-|>"),
|
|
edge(<flow_new>, "r", <flow_auth_start>, "-|>"),
|
|
edge(<flow_auth_start>, <flow_auth_error_id>, "-|>"),
|
|
edge(<flow_auth_error_id>, <flow_auth_start>, "-|>", bend: 18deg),
|
|
edge(<flow_auth_validate>, <flow_auth_error_sig>, "-|>"),
|
|
edge(<flow_auth_error_sig>, <flow_auth_start>, "-|>", bend: 23deg),
|
|
edge(<flow_auth_ok>, "d", <flow_loggedin>, "-|>"),
|
|
|
|
arrLine((<flow_reg_start>, <flow_reg_pin>, <flow_reg_ok>, <flow_disconnect>)),
|
|
arrLine((<flow_auth_start>, <flow_auth_nonce>, <flow_auth_validate>, <flow_auth_ok>)),
|
|
|
|
node((0,6), l(<session_start>)[session_start], name: <flow_session_start>),
|
|
node((0,7), l(<session_vote>)[session_vote], name: <flow_session_vote>),
|
|
node((0,8), l(<session_stop>)[session_stop], name: <flow_session_stop>),
|
|
|
|
node((2, 6), l(<auth_error_takeover>)[auth takeover error], corner-radius: 2pt, extrude: (0, 3), name: <flow_session_takeover>),
|
|
|
|
edge(<flow_loggedin>, "l", <flow_session_start>, "-|>"),
|
|
edge(<flow_session_start>, <flow_session_vote>, "-|>"),
|
|
edge(<flow_session_vote>, <flow_session_stop>, "-|>"),
|
|
edge((0, 7), (0, 7), "--|>", bend: 300deg, loop-angle: 200deg),
|
|
edge(<flow_session_stop>, "r", <flow_loggedin>, "-|>"),
|
|
|
|
edge(<flow_loggedin>, "r", <flow_session_takeover>, "-|>")
|
|
|
|
))
|