1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# keks-meet
a web conferencing application
## Features
- Rooms
- Different stream types
- Camera
- Microphone
- Screen capture
- Multiple streams
- Noise suppression (rnnoise)
- End-to-end-encryption
- Chat (text and images)
## Licence
Licensed under the terms of the GNU Affero General Public License version 3 only. See [COPYING](./COPYING).
## Security
keks-meet _tries_ to be secure. However I am not a security expert. The current system works as follows:
- The room name is set in the section of the URL which is not sent to the server.
- The server receives a salted SHA-256 hash of the room name to group clients of a room.
- The client uses PBKDF2 (constant salt; 250000 iterations) to derive a 256-bit AES-GCM key from the room name.
- All relayed message contents are encrypted with this key.
- Message recipient is visible to the server
- The server assigns user ids
## Usage
For trying it out, a hosted version is available on [my server](https://meet.metamuffin.org/).
For self-hosting, this should help:
```
pacman -S --needed deno rustup make coreutils; rustup install stable
git clone https://codeberg.org/metamuffin/keks-meet.git
cd keks-meet
make run
```
When changing code, use `make watch` to re-build things automatically as needed.
Because of a current compiler bug, the nightly rustc crashes during codegen - use the stable channel instead.
If you use this project or have any suggestions, please [contact me](https://metamuffin.org/contact)
## Keybinds
| Keybind | Action |
| --------- | ------------------------------------------------------- |
| `RET` | Toggle chat |
| `SPC M` | Add microphone track |
| `SPC R` | Add microphone track (but with your left hand) |
| `SPC C` | Add camera track |
| `SPC S` | Add screencast track |
| `SPC C-c` | End all tracks |
| `C-v`\* | Paste image in chat (does not require chat to be shown) |
## Parameters
Some configuration parameters can be added like query params but **after** the section. (e.g `/room#mymeeting?username=alice`)
The page will not automatically reload if the section changes.
Booleans can be either `1`, `true`, `yes` or their opposites. I convenience function for changing params is also exported: `window.change_pref(key, value)`
| Option name | Type | Default | Description |
| -------------------------- | ------- | ----------- | -------------------------------------------------------------------- |
| `username` | string | `"guest-…"` | Username |
| `warn_redirect` | boolean | `false` | Internal option that is set by a server redirect. |
| `image_view_popup` | boolean | `true` | Open image in popup instead of new tab |
| `microphone_enabled` | boolean | `false` | Add one microphone track on startup |
| `screencast_enabled` | boolean | `false` | Add one screencast track on startup |
| `camera_enabled` | boolean | `false` | Add one camera track on startup |
| `rnnoise` | boolean | `true` | Use RNNoise for noise suppression |
| `native_noise_suppression` | boolean | `false` | Suggest the browser to do noise suppression |
| `microphone_gain` | number | `1` | Amplify microphone volume |
| `video_fps` | number | - | Preferred framerate (in 1/s) for screencast and camera |
| `video_resolution` | number | - | Preferred width for screencast and camera |
| `camera_facing_mode` | string | - | Prefer user-facing or env-facing camera (`"environment"` / `"user"`) |
| `auto_gain_control` | boolean | - | Automatically adjust mic gain |
| `echo_cancellation` | boolean | - | Cancel echo |
| `notify_chat` | boolean | `true` | Send notifications for incoming chat messages |
| `notify_join` | boolean | `true` | Send notifications when users join |
| `notify_leave` | boolean | `true` | Send notifications when users leave |
## Todo-List
- Optionally enable video streams
- Native client
- Prevent server from changing message sender
- Have a security professional look at the code
- Test some options like `camera_facing_mode`
- Signing key for each user
- Built-in storage for known keys
- Relay RTC when there are a lot of clients
- Save permissions to locale storage
- Prevent join notification bypass by not identifying
- Dont use websocket to send images to not block anything else
- How do we implement global hotkeys?
- Tray icon for native
- Pin js by bookmarking data:text/html loader page
## Protocol
The protocol packets are defined in [packets.d.ts](./common/packets.d.ts). Here is an (simplified) example of how the protocol is used.
**THIS IS OBSOLETE! The new protocol is quite similar but uses encryption**
```
S->C { init: { your_id: 5, version: "..." } }
---- # Your join packet will be the first one.
S->C { client_join: { id: 5, name: "bob" } }
S->C { client_join: { id: 3, name: "alice" } }
---- # Now publish your ICE candidates
C->S { relay: { message: { ice_candiate: <RTCIceCandidateInit> } } }
---- # Whenever you change your streams change:
---- # Send an offer to everybody
C->S { relay: { recipient: 3, offer: <RTCSessionDescriptionInit> } }
---- # Alice answers
S->C { message: { sender: 3, message: { offer: <RTCSessionDescriptionInit> } } }
---- # In case the server uses a reverse-proxy that disconnects inactive connections: Ping every 30s
C->S { ping: null }
```
|