Skip to content

Commit 71ef378

Browse files
committed
Limit broadcasts to ICE req
I need to reimplement hosted, which means parsing the inner packets so that we can handle ICE, and DTLS. This is also a good change to limit broadcasts to ICE connection test requests which are the only packets we want to pay the broadcast penalty for.
1 parent 82c1611 commit 71ef378

File tree

3 files changed

+85
-25
lines changed

3 files changed

+85
-25
lines changed

Dockerfile

Lines changed: 0 additions & 9 deletions
This file was deleted.

relay/main.js

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { from_string } from '../src/id.js';
12
import { Ip6, parse_ipaddr } from '../src/ipaddr.js';
2-
import { Stun, Class, Method, Attr, AttrType } from '../src/stun.js';
3+
import { Stun, Class, Method, Attr, AttrType, MAGIC_COOKIE } from '../src/stun.js';
34
import { write } from '../src/util.js';
45

56
if (!import.meta.main) throw new Error("swbrd library code is in src");
@@ -96,13 +97,17 @@ class Turn {
9697

9798
// Send indications get modified in place and then relayed
9899
msg.method = Method.Data;
99-
const offset = Stun.minByteLength + Attr.minByteLength + 20 +
100-
Attr.minByteLength;
101-
const length = data.byteLength;
102-
103-
// TODO: I honestly have no clue why the following line works... Surely it's missing a msg.byteOffset somewhere, and why the hell is length in the ending index position?
104-
new Uint8Array(msg.buffer).copyWithin(offset, data.byteOffset, length);
105-
// const moved_data = new Uint8Array(msg.buffer, offset, length);
100+
const offset = msg.byteOffset
101+
/* STUN Header */ + Stun.minByteLength
102+
/* XOR-PEER-ADDRESS Header */ + Attr.minByteLength
103+
/* - Value: Port + IP6 */ + 20
104+
/* DATA Header */ + Attr.minByteLength;
105+
let length = data.byteLength;
106+
107+
// Shift the DataAttribute to where we want it (It's probably already there, but be sure)
108+
new Uint8Array(msg.buffer).copyWithin(offset, data.byteOffset, data.byteOffset + length);
109+
const moved_data = new Uint8Array(msg.buffer, offset, length);
110+
// console.log(moved_data);
106111

107112
const relay = async turn => {
108113
let peer;
@@ -141,17 +146,82 @@ class Turn {
141146
*/
142147
if (fingerprint) this.mappings ??= [];
143148

144-
for (const turn of all.values()) {
145-
if (turn == this) continue;
146-
await relay(turn);
149+
// Special treatment for [::ffff:255.255.255.255]:65535
150+
const fb = moved_data[0];
151+
/* STUN */ if (fb < 3) {
152+
// Verify that the message is an ICE connection test
153+
const inner = new Stun(msg.buffer, {byteOffset: offset});
154+
if (inner.byteLength != length) return;
155+
if (inner.class != Class.Req) return;
156+
if (inner.method != Method.Binding) return;
157+
if (inner.cookie != MAGIC_COOKIE) return;
158+
159+
const [
160+
[
161+
username,
162+
priority,
163+
iceControlled,
164+
iceControlling,
165+
_useCandidate,
166+
],
167+
[integrity],
168+
[fingerprint],
169+
unknown,
170+
] = inner.parse(
171+
[
172+
[AttrType.Username, 'text'],
173+
[AttrType.Priority, 'u32'],
174+
[AttrType.IceControlled, 'u64'],
175+
[AttrType.IceControlling, 'u64'],
176+
[AttrType.UseCandidate, 'bool'],
177+
],
178+
[[AttrType.Integrity, 20]],
179+
[[AttrType.Fingerprint, 'u32']],
180+
);
181+
if (
182+
unknown.length ||
183+
!username || !priority || !integrity || !fingerprint ||
184+
(typeof iceControlled == typeof iceControlling)
185+
) { return; }
186+
187+
const [dst_ufrag, src_ufrag, more] = username.split(':');
188+
if (!dst_ufrag || !src_ufrag || more) return;
189+
const [dpid, spid] = [dst_ufrag, src_ufrag].map(from_string);
190+
if (!dpid || !spid) return;
191+
console.log(dpid, spid);
192+
193+
// Handle Hosted ICE
194+
if (dst_ufrag == 'ucCm6JK3s22XuCRiTZVFpWajUq0tIpB7lDn1Sv8dRv3') {
195+
// TODO: Respond to the ICE
196+
return;
197+
}
198+
// Broadcast the ICE connection test so that it can be discovered
199+
else {
200+
// Broadcast the ICE connection test to everyone
201+
for (const turn of all.values()) {
202+
if (turn == this) continue;
203+
await relay(turn);
204+
}
205+
206+
// Don't respond
207+
return;
208+
}
209+
}
210+
/* DTLS */ else if (20 < fb && fb < 64) {
211+
// TODO: Handle DTLS to hosted
212+
return;
147213
}
214+
/* Drop */ else { return }
148215
}
149216

150217
// Unicast Mapped
151218
else if (is_broadcast) {
152219
const turn = this.mappings[peer.port - 1];
153220
if (!turn) return;
154221
await relay(turn);
222+
223+
// Relayed, so no response
224+
return;
155225
}
156226

157227
// Unicast Transparent
@@ -160,10 +230,10 @@ class Turn {
160230
const turn = all.get(key);
161231
if (!turn) return;
162232
await relay(turn);
163-
}
164233

165-
// We just performed a relay, so don't respond with anything.
166-
return;
234+
// Relayed, so no response
235+
return;
236+
}
167237
}
168238

169239
// Drop all other non-requests

src/conn.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ import { is_firefox, state } from './util.js';
55

66
export const defaults = {
77
iceServers: [{
8-
// urls: 'turn:stun.evan-brass.net',
9-
urls: 'turn:localhost?transport=tcp',
8+
urls: 'turn:stun.evan-brass.net',
109
username: 'guest',
1110
credential: 'password',
1211
}],

0 commit comments

Comments
 (0)