@@ -12,6 +12,7 @@ import {
12
12
EventDispatcher ,
13
13
MessageEvent ,
14
14
} from '../base/event.js' ;
15
+ import { Subscription } from './subscription.js' ;
15
16
16
17
/**
17
18
* @class QuicConnection
@@ -20,12 +21,14 @@ import {
20
21
* @private
21
22
*/
22
23
export class QuicConnection extends EventDispatcher {
23
- constructor ( url , signaling ) {
24
+ constructor ( url , token , signaling ) {
24
25
super ( ) ;
25
26
this . _signaling = signaling ;
26
27
this . _ended = false ;
27
28
this . _quicStreams = new Map ( ) ; // Key is publication or subscription ID.
28
29
this . _quicTransport = new QuicTransport ( url ) ;
30
+ this . _subscribePromises = new Map ( ) ; // Key is subscription ID.
31
+ this . _init ( token ) ;
29
32
}
30
33
31
34
/**
@@ -54,23 +57,81 @@ export class QuicConnection extends EventDispatcher {
54
57
}
55
58
}
56
59
60
+ async _init ( token ) {
61
+ this . _authenticate ( token ) ;
62
+ const receiveStreamReader =
63
+ this . _quicTransport . receiveStreams ( ) . getReader ( ) ;
64
+ Logger . info ( 'Reader: ' + receiveStreamReader ) ;
65
+ while ( true ) {
66
+ const {
67
+ value : receiveStream ,
68
+ done : readingReceiveStreamsDone
69
+ } = await receiveStreamReader . read ( ) ;
70
+ Logger . info ( 'New stream received' ) ;
71
+ if ( readingReceiveStreamsDone ) {
72
+ break ;
73
+ }
74
+ const chunkReader = receiveStream . readable . getReader ( ) ;
75
+ const {
76
+ value : uuid ,
77
+ done : readingChunksDone
78
+ } = await chunkReader . read ( ) ;
79
+ if ( readingChunksDone ) {
80
+ Logger . error ( 'Stream closed unexpectedly.' ) ;
81
+ return ;
82
+ }
83
+ if ( uuid . length != 16 ) {
84
+ Logger . error ( 'Unexpected length for UUID.' ) ;
85
+ return ;
86
+ }
87
+ chunkReader . releaseLock ( ) ;
88
+ const subscriptionId = this . _uint8ArrayToUuid ( uuid ) ;
89
+ this . _quicStreams . set ( subscriptionId , receiveStream ) ;
90
+ if ( this . _subscribePromises . has ( subscriptionId ) ) {
91
+ const subscription =
92
+ this . _createSubscription ( subscriptionId , receiveStream ) ;
93
+ this . _subscribePromises . get ( subscriptionId ) . resolve ( subscription ) ;
94
+ }
95
+ }
96
+ }
97
+
98
+ _createSubscription ( id , receiveStream ) {
99
+ // TODO: Incomplete subscription.
100
+ const subscription = new Subscription ( id , ( ) => {
101
+ receiveStream . abortReading ( ) ;
102
+ } ) ;
103
+ subscription . stream = receiveStream ;
104
+ return subscription ;
105
+ }
106
+
107
+ async _authenticate ( token ) {
108
+ await this . _quicTransport . ready ;
109
+ const quicStream = await this . _quicTransport . createSendStream ( ) ;
110
+ const writer = quicStream . writable . getWriter ( ) ;
111
+ await writer . ready ;
112
+ writer . write ( new Uint8Array ( 16 ) ) ;
113
+ const encoder = new TextEncoder ( ) ;
114
+ writer . write ( encoder . encode ( token ) ) ;
115
+ }
116
+
57
117
async createSendStream ( sessionId ) {
58
118
Logger . info ( 'Create stream.' ) ;
59
119
await this . _quicTransport . ready ;
60
120
// TODO: Creating quicStream and initializing publication concurrently.
61
121
const quicStream = await this . _quicTransport . createSendStream ( ) ;
62
- const publicationId = await this . _initializePublication ( ) ;
122
+ const publicationId = await this . _initiatePublication ( ) ;
63
123
const writer = quicStream . writable . getWriter ( ) ;
64
124
await writer . ready ;
65
- writer . write ( this . uuidToUint8Array ( publicationId ) ) ;
125
+ writer . write ( this . _uuidToUint8Array ( publicationId ) ) ;
126
+ writer . write ( this . _uuidToUint8Array ( publicationId ) ) ;
66
127
this . _quicStreams . set ( publicationId , quicStream ) ;
67
128
}
68
129
69
130
hasContentSessionId ( id ) {
70
131
return this . _quicStreams . has ( id ) ;
71
132
}
72
133
73
- uuidToUint8Array ( uuidString ) {
134
+ _uuidToUint8Array ( uuidString ) {
74
135
if ( uuidString . length != 32 ) {
75
136
throw new TypeError ( 'Incorrect UUID.' ) ;
76
137
}
@@ -82,6 +143,15 @@ export class QuicConnection extends EventDispatcher {
82
143
return uuidArray ;
83
144
}
84
145
146
+ _uint8ArrayToUuid ( uuidBytes ) {
147
+ let s = '' ;
148
+ for ( let hex of uuidBytes ) {
149
+ const str = hex . toString ( 16 ) ;
150
+ s += str . padStart ( 2 , '0' ) ;
151
+ }
152
+ return s ;
153
+ }
154
+
85
155
/**
86
156
* @function createStream
87
157
* @desc Create a bidirectional stream.
@@ -106,23 +176,38 @@ export class QuicConnection extends EventDispatcher {
106
176
}
107
177
108
178
subscribe ( stream ) {
109
- this . _outgoing = false ;
110
- this . _streamSubscribed = stream ;
111
- if ( ! this . _quicTransport ) {
112
- this . createStream ( ) ;
113
- }
179
+ const p = new Promise ( ( resolve , reject ) => {
180
+ this . _signaling
181
+ . sendSignalingMessage (
182
+ 'subscribe' ,
183
+ { media : null , data : { from : stream . id } , transport : { type : 'quic' } } )
184
+ . then ( ( data ) => {
185
+ if ( this . _quicStreams . has ( data . id ) ) {
186
+ // QUIC stream created before signaling returns.
187
+ const subscription = this . _createSubscription (
188
+ data . id , this . _quicStreams . get ( data . id ) ) ;
189
+ resolve ( subscription ) ;
190
+ } else {
191
+ // QUIC stream is not created yet, resolve promise after getting
192
+ // QUIC stream.
193
+ this . _subscribePromises . set (
194
+ data . id , { resolve : resolve , reject : reject } ) ;
195
+ }
196
+ } ) ;
197
+ } ) ;
198
+ return p ;
114
199
}
115
200
116
- _readAndPrint ( ) {
117
- this . _quicStreams [ 0 ] . waitForReadable ( 5 ) . then ( ( ) => {
201
+ _readAndPrint ( ) {
202
+ this . _quicStreams [ 0 ] . waitForReadable ( 5 ) . then ( ( ) => {
118
203
let data = new Uint8Array ( this . _quicStreams [ 0 ] . readBufferedAmount ) ;
119
204
this . _quicStreams [ 0 ] . readInto ( data ) ;
120
205
Logger . info ( 'Read data: ' + data ) ;
121
206
this . _readAndPrint ( ) ;
122
207
} ) ;
123
208
}
124
209
125
- async _initializePublication ( ) {
210
+ async _initiatePublication ( ) {
126
211
const data = await this . _signaling . sendSignalingMessage ( 'publish' , {
127
212
media : null ,
128
213
data : true ,
0 commit comments