@@ -40,26 +40,39 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
4040 private readonly peerConnection : RTCPeerConnection
4141 private readonly metrics ?: CounterGroup
4242 private readonly dataChannelOptions ?: DataChannelOptions
43+ private readonly earlyDataChannels : RTCDataChannel [ ]
4344
4445 constructor ( init : DataChannelMuxerFactoryInit ) {
46+ this . onEarlyDataChannel = this . onEarlyDataChannel . bind ( this )
47+
4548 this . peerConnection = init . peerConnection
4649 this . metrics = init . metrics
4750 this . protocol = init . protocol ?? MUXER_PROTOCOL
4851 this . dataChannelOptions = init . dataChannelOptions ?? { }
52+ this . peerConnection . addEventListener ( 'datachannel' , this . onEarlyDataChannel )
53+ this . earlyDataChannels = [ ]
54+ }
55+
56+ private onEarlyDataChannel ( evt : RTCDataChannelEvent ) : void {
57+ this . earlyDataChannels . push ( evt . channel )
4958 }
5059
5160 createStreamMuxer ( maConn : MultiaddrConnection ) : StreamMuxer {
61+ this . peerConnection . removeEventListener ( 'datachannel' , this . onEarlyDataChannel )
62+
5263 return new DataChannelMuxer ( maConn , {
5364 peerConnection : this . peerConnection ,
5465 dataChannelOptions : this . dataChannelOptions ,
5566 metrics : this . metrics ,
56- protocol : this . protocol
67+ protocol : this . protocol ,
68+ earlyDataChannels : this . earlyDataChannels
5769 } )
5870 }
5971}
6072
6173export interface DataChannelMuxerInit extends DataChannelMuxerFactoryInit {
6274 protocol : string
75+ earlyDataChannels : RTCDataChannel [ ]
6376}
6477
6578export interface DataChannelMuxerComponents {
@@ -90,27 +103,37 @@ export class DataChannelMuxer extends AbstractStreamMuxer<WebRTCStream> implemen
90103 * {@link https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/datachannel_event}
91104 */
92105 this . peerConnection . ondatachannel = ( { channel } ) => {
93- this . log ( 'incoming datachannel with channel id %d, protocol %s and status %s' , channel . id , channel . protocol , channel . readyState )
94-
95- // 'init' channel is only used during connection establishment, it is
96- // closed by the initiator
97- if ( channel . label === 'init' ) {
98- this . log . trace ( 'closing init channel %d' , channel . id )
99- channel . close ( )
100-
101- return
102- }
103-
104- const stream = createStream ( {
105- ...this . streamOptions ,
106- ...this . dataChannelOptions ,
107- channel,
108- direction : 'inbound' ,
109- log : this . log
106+ this . onDataChannel ( channel )
107+ }
108+
109+ queueMicrotask ( ( ) => {
110+ init . earlyDataChannels . forEach ( channel => {
111+ this . onDataChannel ( channel )
110112 } )
113+ } )
114+ }
115+
116+ private onDataChannel ( channel : RTCDataChannel ) : void {
117+ this . log ( 'incoming datachannel with channel id %d, protocol %s and status %s' , channel . id , channel . protocol , channel . readyState )
111118
112- this . onRemoteStream ( stream )
119+ // 'init' channel is only used during connection establishment, it is
120+ // closed by the initiator
121+ if ( channel . label === 'init' ) {
122+ this . log . trace ( 'closing init channel %d' , channel . id )
123+ channel . close ( )
124+
125+ return
113126 }
127+
128+ const stream = createStream ( {
129+ ...this . streamOptions ,
130+ ...this . dataChannelOptions ,
131+ channel,
132+ direction : 'inbound' ,
133+ log : this . log
134+ } )
135+
136+ this . onRemoteStream ( stream )
114137 }
115138
116139 async onCreateStream ( options ?: CreateStreamOptions ) : Promise < WebRTCStream > {
0 commit comments