@@ -19,6 +19,7 @@ const {
19
19
Promise,
20
20
PromiseAll,
21
21
PromiseReject,
22
+ PromiseResolve,
22
23
RegExp,
23
24
Set,
24
25
Symbol,
@@ -213,13 +214,13 @@ const kDestroy = Symbol('kDestroy');
213
214
const kEndpointBound = Symbol ( 'kEndpointBound' ) ;
214
215
const kEndpointClose = Symbol ( 'kEndpointClose' ) ;
215
216
const kHandshake = Symbol ( 'kHandshake' ) ;
217
+ const kHandshakeComplete = Symbol ( 'kHandshakeComplete' ) ;
216
218
const kHandshakePost = Symbol ( 'kHandshakePost' ) ;
217
219
const kHeaders = Symbol ( 'kHeaders' ) ;
218
220
const kInternalState = Symbol ( 'kInternalState' ) ;
219
221
const kInternalClientState = Symbol ( 'kInternalClientState' ) ;
220
222
const kInternalServerState = Symbol ( 'kInternalServerState' ) ;
221
223
const kListen = Symbol ( 'kListen' ) ;
222
- const kMakeStream = Symbol ( 'kMakeStream' ) ;
223
224
const kMaybeBind = Symbol ( 'kMaybeBind' ) ;
224
225
const kOnFileOpened = Symbol ( 'kOnFileOpened' ) ;
225
226
const kOnFileUnpipe = Symbol ( 'kOnFileUnpipe' ) ;
@@ -1651,6 +1652,9 @@ class QuicSession extends EventEmitter {
1651
1652
destroyed : false ,
1652
1653
earlyData : false ,
1653
1654
handshakeComplete : false ,
1655
+ handshakeCompletePromise : undefined ,
1656
+ handshakeCompletePromiseResolve : undefined ,
1657
+ handshakeCompletePromiseReject : undefined ,
1654
1658
idleTimeout : false ,
1655
1659
maxPacketLength : NGTCP2_DEFAULT_MAX_PKTLEN ,
1656
1660
servername : undefined ,
@@ -1715,6 +1719,26 @@ class QuicSession extends EventEmitter {
1715
1719
} ) ;
1716
1720
}
1717
1721
1722
+ [ kHandshakeComplete ] ( ) {
1723
+ const state = this [ kInternalState ] ;
1724
+ if ( state . handshakeComplete )
1725
+ return PromiseResolve ( ) ;
1726
+
1727
+ if ( state . handshakeCompletePromise !== undefined )
1728
+ return state . handshakeCompletePromise ;
1729
+
1730
+ state . handshakeCompletePromise = new Promise ( ( resolve , reject ) => {
1731
+ state . handshakeCompletePromiseResolve = resolve ;
1732
+ state . handshakeCompletePromiseReject = reject ;
1733
+ } ) . finally ( ( ) => {
1734
+ state . handshakeCompletePromise = undefined ;
1735
+ state . handshakeCompletePromiseReject = undefined ;
1736
+ state . handshakeCompletePromiseResolve = undefined ;
1737
+ } ) ;
1738
+
1739
+ return state . handshakeCompletePromise ;
1740
+ }
1741
+
1718
1742
// Sets the internal handle for the QuicSession instance. For
1719
1743
// server QuicSessions, this is called immediately as the
1720
1744
// handle is created before the QuicServerSession JS object.
@@ -1827,8 +1851,18 @@ class QuicSession extends EventEmitter {
1827
1851
state . verifyErrorReason = verifyErrorReason ;
1828
1852
state . verifyErrorCode = verifyErrorCode ;
1829
1853
state . earlyData = earlyData ;
1830
- if ( ! this [ kHandshakePost ] ( ) )
1854
+
1855
+ if ( ! this [ kHandshakePost ] ( ) ) {
1856
+ if ( typeof state . handshakeCompletePromiseReject === 'function' ) {
1857
+ // TODO(@jasnell): Proper error
1858
+ state . handshakeCompletePromiseReject (
1859
+ new ERR_OPERATION_FAILED ( 'Handshake failed' ) ) ;
1860
+ }
1831
1861
return ;
1862
+ }
1863
+
1864
+ if ( typeof state . handshakeCompletePromiseResolve === 'function' )
1865
+ state . handshakeCompletePromiseResolve ( ) ;
1832
1866
1833
1867
process . nextTick ( ( ) => {
1834
1868
try {
@@ -1971,6 +2005,12 @@ class QuicSession extends EventEmitter {
1971
2005
} else if ( typeof state . closePromiseResolve === 'function' )
1972
2006
state . closePromiseResolve ( ) ;
1973
2007
2008
+ if ( typeof state . handshakeCompletePromiseReject === 'function' ) {
2009
+ // TODO(@jasnell): Proper error
2010
+ state . handshakeCompletePromiseReject (
2011
+ new ERR_OPERATION_FAILED ( 'Handshake failed' ) ) ;
2012
+ }
2013
+
1974
2014
process . nextTick ( emit . bind ( this , 'close' ) ) ;
1975
2015
}
1976
2016
@@ -2113,8 +2153,7 @@ class QuicSession extends EventEmitter {
2113
2153
return this [ kInternalState ] . statelessReset ;
2114
2154
}
2115
2155
2116
- openStream ( options ) {
2117
- const state = this [ kInternalState ] ;
2156
+ async openStream ( options ) {
2118
2157
if ( this . destroyed ) {
2119
2158
throw new ERR_INVALID_STATE (
2120
2159
`${ this . constructor . name } is already destroyed` ) ;
@@ -2123,51 +2162,42 @@ class QuicSession extends EventEmitter {
2123
2162
throw new ERR_INVALID_STATE (
2124
2163
`${ this . constructor . name } is closing` ) ;
2125
2164
}
2165
+
2126
2166
const {
2127
2167
halfOpen, // Unidirectional or Bidirectional
2128
2168
highWaterMark,
2129
2169
defaultEncoding,
2130
2170
} = validateQuicStreamOptions ( options ) ;
2131
2171
2132
- const stream = new QuicStream ( {
2133
- highWaterMark,
2134
- defaultEncoding,
2135
- readable : ! halfOpen
2136
- } , this ) ;
2172
+ await this [ kHandshakeComplete ] ( ) ;
2137
2173
2138
- state . pendingStreams . add ( stream ) ;
2139
-
2140
- // If early data is being used, we can create the internal QuicStream on the
2141
- // ready event, that is immediately after the internal QuicSession handle
2142
- // has been created. Otherwise, we have to wait until the secure event
2143
- // signaling the completion of the TLS handshake.
2144
- const makeStream = QuicSession [ kMakeStream ] . bind ( this , stream , halfOpen ) ;
2145
- let deferred = false ;
2146
- if ( ! this . handshakeComplete ) {
2147
- deferred = true ;
2148
- this . once ( 'secure' , makeStream ) ;
2174
+ if ( this . destroyed ) {
2175
+ throw new ERR_INVALID_STATE (
2176
+ `${ this . constructor . name } is already destroyed` ) ;
2177
+ }
2178
+ if ( this . closing ) {
2179
+ throw new ERR_INVALID_STATE (
2180
+ `${ this . constructor . name } is closing` ) ;
2149
2181
}
2150
2182
2151
- if ( ! deferred )
2152
- makeStream ( stream , halfOpen ) ;
2153
-
2154
- return stream ;
2155
- }
2156
-
2157
- static [ kMakeStream ] ( stream , halfOpen ) {
2158
- this [ kInternalState ] . pendingStreams . delete ( stream ) ;
2159
2183
const handle =
2160
2184
halfOpen ?
2161
2185
_openUnidirectionalStream ( this [ kHandle ] ) :
2162
2186
_openBidirectionalStream ( this [ kHandle ] ) ;
2163
2187
2164
- if ( handle === undefined ) {
2165
- stream . destroy ( new ERR_OPERATION_FAILED ( 'Unable to create QuicStream' ) ) ;
2166
- return ;
2167
- }
2188
+ if ( handle === undefined )
2189
+ throw new ERR_OPERATION_FAILED ( 'Unable to create QuicStream' ) ;
2190
+
2191
+ const stream = new QuicStream ( {
2192
+ highWaterMark,
2193
+ defaultEncoding,
2194
+ readable : ! halfOpen
2195
+ } , this ) ;
2168
2196
2169
2197
stream [ kSetHandle ] ( handle ) ;
2170
2198
this [ kAddStream ] ( stream . id , stream ) ;
2199
+
2200
+ return stream ;
2171
2201
}
2172
2202
2173
2203
get duration ( ) {
0 commit comments