1+ import { from_string } from '../src/id.js' ;
12import { 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' ;
34import { write } from '../src/util.js' ;
45
56if ( ! 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
0 commit comments