|
2 | 2 |
|
3 | 3 | ## Why
|
4 | 4 |
|
5 |
| -`SFU-to-SFU` is an example of a cascaded decentralised SFU. The intention is to be a implementation of Matrix's [MSC3401: Native Group VoIP signalling](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/group-voip/proposals/3401-group-voip.md). |
6 |
| -This example is self contained and doesn't require any external software. The project was informed by the following goals. |
7 |
| - |
8 |
| -* **Easy Scaling** - SFU count can be grown/shrunk as users arrive. We don't scale on the dimension of calls making things easier. |
9 |
| -* **Shorter Last Mile** - Users can connect to SFUs closest to them. Links `SFU <-> SFU` are higher quality then public hops. |
10 |
| -* **Flexibility in WebRTC server choice** - All communication takes place using standard protocols/formats. You can use whatever server software best fits your needs. |
11 |
| -* **Client Simplicity** - Clients will need to be created on lots of platforms. We should aim to use native WebRTC features as much as possible. |
12 |
| - |
13 |
| -The SFUs themselves have no concept of conference calls/rooms etc... All of this is communicated in the Matrix room. The SFUs themselves just operate off of |
14 |
| -pub/sub semantics. The pub/sub streams are keyed by `foci`, `call_id`, `device_id` and `purpose` these keys come from [MSC3401](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/group-voip/proposals/3401-group-voip.md). |
15 |
| - |
16 |
| -Lets say you have a Matrix room where user `Alice` wishes to publish a screenshare to `Bob` and `Charlie`. |
17 |
| - |
18 |
| -``` |
19 |
| -* `Alice` establishes a session with a SFU |
20 |
| -* `Alice` publishes a screenshare feed with `call_id`, `device_id` and `purpose` |
21 |
| -* `Alice` publishes to the matrix room with the values `foci`, `call_id`, `device_id` and `purpose` |
22 |
| -
|
23 |
| -# Connecting directly to publishers FOCI |
24 |
| -* `Bob` connects directly to `foci` and establishes a session. |
25 |
| -* `Bob` requests a stream with values `foci`, `call_id`, `device_id` and `purpose`. |
26 |
| -
|
27 |
| -# Connect to FOCI through different SFU |
28 |
| -* `Charlie` connects to a SFU they run on a remote host. |
29 |
| -* `Charlie` requests a stream with values `foci`, `call_id`, `device_id` and `purpose`. |
30 |
| -* `Charlie`'s SFU connects to `foci` and requests the stream. |
31 |
| -* `Alice`'s stream arrives to Charlie via `Alice -> FOCI -> Charlie's SFU -> Charlie` |
32 |
| -``` |
| 5 | +`SFU-to-SFU` is an example of a cascaded decentralised SFU. The intention is to |
| 6 | +be a implementation of Matrix's [MSC3401: Native Group VoIP |
| 7 | +signalling](https://github.com/matrix-org/matrix-spec-proposals/blob/matthew/group-voip/proposals/3401-group-voip.md). |
| 8 | +This example is self contained and doesn't require any external software. The |
| 9 | +project was informed by the following goals. |
| 10 | + |
| 11 | +* **Easy Scaling** - SFU count can be grown/shrunk as users arrive. We don't |
| 12 | + scale on the dimension of calls making things easier. |
| 13 | +* **Shorter Last Mile** - Users can connect to SFUs closest to them. Links `SFU |
| 14 | + <-> SFU` are higher quality then public hops. |
| 15 | +* **Flexibility in WebRTC server choice** - All communication takes place using |
| 16 | + standard protocols/formats. You can use whatever server software best fits |
| 17 | + your needs. |
| 18 | +* **Client Simplicity** - Clients will need to be created on lots of platforms. |
| 19 | + We should aim to use native WebRTC features as much as possible. |
| 20 | + |
| 21 | +This implements the MSC only roughly - given the current experimental nature of |
| 22 | +this projects, it deviates in certain areas from the MSC. |
33 | 23 |
|
34 | 24 | ## How
|
35 |
| -### Establishing a session |
36 |
| -Client sends a POST with a WebRTC Offer that is datachannel only. Server responds with Answer. |
37 |
| - |
38 |
| -Server will open a datachannel called `signaling`. Clients can send publish/subscribe now. |
39 |
| - |
40 |
| -`POST /createSession` |
41 |
| - |
42 |
| -`Request` |
43 |
| -``` |
44 |
| -o=- 6685856480478485828 2 IN IP4 127.0.0.1 |
45 |
| -s=- |
46 |
| -t=0 0 |
47 |
| -a=group:BUNDLE 0 |
48 |
| -a=extmap-allow-mixed |
49 |
| -a=msid-semantic: WMS |
50 |
| -m=application 9 UDP/DTLS/SCTP webrtc-datachannel |
51 |
| -c=IN IP4 0.0.0.0 |
52 |
| -a=ice-ufrag:gLSF |
53 |
| -a=ice-pwd:xuxSHK0uJuSb607uYunnzlCQ |
54 |
| -a=ice-options:trickle |
55 |
| -a=fingerprint:sha-256 C2:1F:9B:A1:C2:DF:7E:13:E4:F9:64:F5:EC:4D:17:A1:89:21:0E:32:61:2A:B7:A5:A7:2A:7C:06:AC:FB:B2:A1 |
56 |
| -a=setup:actpass |
57 |
| -a=mid:0 |
58 |
| -a=sctp-port:5000 |
59 |
| -a=max-message-size:262144 |
60 |
| -``` |
61 |
| - |
62 |
| -`Response` |
63 |
| -``` |
64 |
| -o=- 1712750552704711910 2 IN IP4 127.0.0.1 |
65 |
| -s=- |
66 |
| -t=0 0 |
67 |
| -a=group:BUNDLE 0 |
68 |
| -a=extmap-allow-mixed |
69 |
| -a=msid-semantic: WMS |
70 |
| -m=application 9 UDP/DTLS/SCTP webrtc-datachannel |
71 |
| -c=IN IP4 0.0.0.0 |
72 |
| -a=ice-ufrag:90cu |
73 |
| -a=ice-pwd:PARVC6h9kLvvgCqxSocjrXYZ |
74 |
| -a=ice-options:trickle |
75 |
| -a=fingerprint:sha-256 7F:79:0F:50:FF:D1:3F:DF:CA:BD:06:89:2B:C8:05:2E:EC:7D:EF:66:AF:A8:6E:D8:70:C6:74:68:E6:5C:47:D7 |
76 |
| -a=setup:active |
77 |
| -a=mid:0 |
78 |
| -a=sctp-port:5000 |
79 |
| -a=max-message-size:262144 |
80 |
| -``` |
81 |
| - |
82 |
| -### Publish a Stream |
83 |
| -A user can start publish a stream by making a JSON request to publish with a new Offer. With the following keys. |
84 |
| - |
85 |
| -* `event` - Must be `publish` |
86 |
| -* `id` - Unique ID for this message. Allows server to respond with with errors |
87 |
| -* Stream Identification - `call_id`, `device_id`, `purpose` |
88 |
| -* `sdp` - Offer frome the Peer. Any new additional tracks will belong to the stream. |
89 |
| - |
90 |
| -``` |
91 |
| -{ |
92 |
| - event: 'publish', |
93 |
| - id: `ABC`, |
94 |
| - call_id: 'AAA', |
95 |
| - device_id: 'BBB', |
96 |
| - purpose: 'DDD', |
97 |
| - sdp: `...`, |
98 |
| -} |
99 |
| -``` |
100 |
| - |
101 |
| -** Errors ** |
102 |
| -* Stream already exists |
103 |
| -* Server over capacity |
104 |
| - |
105 |
| -The server will respond to the `subscribe` with the answer. |
106 |
| - |
107 |
| -``` |
108 |
| -{ |
109 |
| - event: 'publish', |
110 |
| - id: `ABC`, |
111 |
| - call_id: 'AAA', |
112 |
| - device_id: 'BBB', |
113 |
| - purpose: 'DDD', |
114 |
| - sdp: `...`, |
115 |
| -} |
116 |
| -``` |
117 |
| - |
118 |
| - |
119 |
| -### Subscribe to a Stream |
120 |
| -A user can subscribe to a stream by making a JSON request to subscribe with a new Offer. With the following keys. |
121 |
| - |
122 |
| -* `event` - Must be `subscribe` |
123 |
| -* `id` - Unique ID for this message. Allows server to respond with with errors |
124 |
| -* Stream Identification - `call_id`, `device_id`, `purpose` |
125 |
| - |
126 |
| -``` |
127 |
| -{ |
128 |
| - event: 'subscribe', |
129 |
| - id: `ABC`, |
130 |
| - call_id: 'AAA', |
131 |
| - device_id: 'BBB', |
132 |
| - purpose: 'DDD', |
133 |
| - sdp: `...`, |
134 |
| -} |
135 |
| -``` |
136 |
| - |
137 |
| -The client will respond to the `subscribe` with the answer. |
138 | 25 |
|
139 |
| -``` |
140 |
| -{ |
141 |
| - event: 'subscribe', |
142 |
| - id: `ABC`, |
143 |
| - sdp: `...`, |
144 |
| -} |
145 |
| -``` |
| 26 | +### Configuration |
146 | 27 |
|
147 |
| -** Errors ** |
148 |
| -* Stream doesn'texist |
149 |
| -* Server over capacity |
| 28 | +* `cp config.yaml.sample config.yaml` |
| 29 | +* Fill in `config.yaml` |
150 | 30 |
|
151 |
| -### Unpublish a Stream |
152 |
| -``` |
153 |
| -{ |
154 |
| - event: 'unpublish', |
155 |
| - id: `ABC`, |
156 |
| - call_id: 'AAA', |
157 |
| - device_id: 'BBB', |
158 |
| - purpose: 'DDD', |
159 |
| -} |
160 |
| -``` |
| 31 | +### Running |
161 | 32 |
|
162 |
| -### Unsubscribe to a Stream |
| 33 | +* `./scripts/run.sh` |
| 34 | +* Access at <http://localhost:8080> |
163 | 35 |
|
164 |
| -``` |
165 |
| -{ |
166 |
| - event: 'unsubscribe', |
167 |
| - id: `ABC`, |
168 |
| - call_id: 'AAA', |
169 |
| - device_id: 'BBB', |
170 |
| - purpose: 'DDD', |
171 |
| -} |
172 |
| -``` |
| 36 | +### Profiling |
173 | 37 |
|
174 |
| -## Running |
| 38 | +* `./scripts/profile.sh` |
| 39 | +* Access at <http://localhost:8080> |
175 | 40 |
|
176 |
| -* `go run *.go` |
177 |
| -* Access at http://localhost:8080 |
| 41 | +### Building |
178 | 42 |
|
| 43 | +* `./scripts/build.sh` |
| 44 | +* `./dist/bin` |
| 45 | +* Access at <http://localhost:8080> |
0 commit comments