@@ -287,24 +287,10 @@ function onSessionReady(handle) {
287
287
process . nextTick ( emit . bind ( socket , 'session' , session ) ) ;
288
288
}
289
289
290
- // Called when the session needs to be closed and destroyed.
291
- // If silent is true, then the session is going to be closed
292
- // immediately without sending any CONNECTION_CLOSE to the
293
- // connected peer. If silent is false, a CONNECTION_CLOSE
294
- // is going to be sent to the peer.
290
+ // Called when the C++ QuicSession::Close() method has been called.
291
+ // Synchronously cleanup and destroy the JavaScript QuicSession.
295
292
function onSessionClose ( code , family , silent , statelessReset ) {
296
- if ( this [ owner_symbol ] ) {
297
- if ( silent ) {
298
- this [ owner_symbol ] [ kDestroy ] ( statelessReset , family , code ) ;
299
- } else {
300
- this [ owner_symbol ] [ kClose ] ( family , code ) ;
301
- }
302
- return ;
303
- }
304
- // When there's no owner_symbol, the session was closed
305
- // before it could be fully set up. Just immediately
306
- // close everything down on the native side.
307
- this . destroy ( code , family ) ;
293
+ this [ owner_symbol ] [ kDestroy ] ( code , family , silent , statelessReset ) ;
308
294
}
309
295
310
296
// Called by the C++ internals when a QuicSession has been destroyed.
@@ -1654,6 +1640,7 @@ class QuicSession extends EventEmitter {
1654
1640
maxPacketLength : NGTCP2_DEFAULT_MAX_PKTLEN ,
1655
1641
servername : undefined ,
1656
1642
socket : undefined ,
1643
+ silentClose : false ,
1657
1644
statelessReset : false ,
1658
1645
stats : undefined ,
1659
1646
pendingStreams : new Set ( ) ,
@@ -1736,46 +1723,15 @@ class QuicSession extends EventEmitter {
1736
1723
1737
1724
// Causes the QuicSession to be immediately destroyed, but with
1738
1725
// additional metadata set.
1739
- [ kDestroy ] ( statelessReset , family , code ) {
1726
+ [ kDestroy ] ( code , family , silent , statelessReset ) {
1740
1727
const state = this [ kInternalState ] ;
1741
- state . statelessReset = statelessReset ;
1742
1728
state . closeCode = code ;
1743
1729
state . closeFamily = family ;
1730
+ state . silentClose = silent ;
1731
+ state . statelessReset = statelessReset ;
1744
1732
this . destroy ( ) ;
1745
1733
}
1746
1734
1747
- // Immediate close has been initiated for the session. Any
1748
- // still open QuicStreams must be abandoned and shutdown
1749
- // with RESET_STREAM and STOP_SENDING frames transmitted
1750
- // as appropriate. Once the streams have been shutdown, a
1751
- // CONNECTION_CLOSE will be generated and sent, switching
1752
- // the session into the closing period.
1753
- [ kClose ] ( family , code ) {
1754
- const state = this [ kInternalState ] ;
1755
- // Do nothing if the QuicSession has already been destroyed.
1756
- if ( state . destroyed )
1757
- return ;
1758
-
1759
- // Set the close code and family so we can keep track.
1760
- state . closeCode = code ;
1761
- state . closeFamily = family ;
1762
-
1763
- // Shutdown all pending streams. These are Streams that
1764
- // have been created but do not yet have a handle assigned.
1765
- for ( const stream of state . pendingStreams )
1766
- stream [ kClose ] ( family , code ) ;
1767
-
1768
- // Shutdown all of the remaining streams
1769
- for ( const stream of state . streams . values ( ) )
1770
- stream [ kClose ] ( family , code ) ;
1771
-
1772
- // By this point, all necessary RESET_STREAM and
1773
- // STOP_SENDING frames ought to have been sent,
1774
- // so now we just trigger sending of the
1775
- // CONNECTION_CLOSE frame.
1776
- this [ kHandle ] . close ( family , code ) ;
1777
- }
1778
-
1779
1735
// Closes the specified stream with the given code. The
1780
1736
// QuicStream object will be destroyed.
1781
1737
[ kStreamClose ] ( id , code ) {
@@ -1873,14 +1829,6 @@ class QuicSession extends EventEmitter {
1873
1829
this [ kInternalState ] . streams . set ( id , stream ) ;
1874
1830
}
1875
1831
1876
- // The QuicSession will be destroyed if closing has been
1877
- // called and there are no remaining streams
1878
- [ kMaybeDestroy ] ( ) {
1879
- const state = this [ kInternalState ] ;
1880
- if ( state . closing && state . streams . size === 0 )
1881
- this . destroy ( ) ;
1882
- }
1883
-
1884
1832
// Called when a client QuicSession has opted to use the
1885
1833
// server provided preferred address. This is a purely
1886
1834
// informationational notification. It is not called on
@@ -1890,6 +1838,17 @@ class QuicSession extends EventEmitter {
1890
1838
emit . bind ( this , 'usePreferredAddress' , address ) ) ;
1891
1839
}
1892
1840
1841
+ // The QuicSession will be destroyed if close() has been
1842
+ // called and there are no remaining streams
1843
+ [ kMaybeDestroy ] ( ) {
1844
+ const state = this [ kInternalState ] ;
1845
+ if ( state . closing && state . streams . size === 0 ) {
1846
+ this . destroy ( ) ;
1847
+ return true ;
1848
+ }
1849
+ return false ;
1850
+ }
1851
+
1893
1852
// Closing allows any existing QuicStream's to complete
1894
1853
// normally but disallows any new QuicStreams from being
1895
1854
// opened. Calls to openStream() will fail, and new streams
@@ -1910,27 +1869,27 @@ class QuicSession extends EventEmitter {
1910
1869
// has been destroyed
1911
1870
if ( state . closing )
1912
1871
return ;
1913
-
1914
1872
state . closing = true ;
1915
- this [ kHandle ] . gracefulClose ( ) ;
1916
1873
1917
- // See if we can close immediately.
1918
- this [ kMaybeDestroy ] ( ) ;
1874
+ // If there are no active streams, we can close immediately,
1875
+ // otherwise set the graceful close flag.
1876
+ if ( ! this [ kMaybeDestroy ] ( ) )
1877
+ this [ kHandle ] . gracefulClose ( ) ;
1919
1878
}
1920
1879
1921
1880
// Destroying synchronously shuts down and frees the
1922
1881
// QuicSession immediately, even if there are still open
1923
1882
// streams.
1924
1883
//
1925
- // A CONNECTION_CLOSE packet is sent to the
1926
- // connected peer and the session is immediately
1927
- // destroyed.
1884
+ // Unless we're in the middle of a silent close, a
1885
+ // CONNECTION_CLOSE packet will be sent to the connected
1886
+ // peer and the session will be immediately destroyed.
1928
1887
//
1929
1888
// If destroy is called with an error argument, the
1930
1889
// 'error' event is emitted on next tick.
1931
1890
//
1932
1891
// Once destroyed, and after the 'error' event (if any),
1933
- // the close event is emitted on next tick.
1892
+ // the ' close' event is emitted on next tick.
1934
1893
destroy ( error ) {
1935
1894
const state = this [ kInternalState ] ;
1936
1895
// Destroy can only be called once. Multiple calls will be ignored
@@ -1939,19 +1898,6 @@ class QuicSession extends EventEmitter {
1939
1898
state . destroyed = true ;
1940
1899
state . closing = false ;
1941
1900
1942
- if ( typeof error === 'number' ||
1943
- ( error != null &&
1944
- typeof error === 'object' &&
1945
- ! ( error instanceof Error ) ) ) {
1946
- const {
1947
- closeCode,
1948
- closeFamily
1949
- } = validateCloseCode ( error ) ;
1950
- state . closeCode = closeCode ;
1951
- state . closeFamily = closeFamily ;
1952
- error = new ERR_QUIC_ERROR ( closeCode , closeFamily ) ;
1953
- }
1954
-
1955
1901
// Destroy any pending streams immediately. These
1956
1902
// are streams that have been created but have not
1957
1903
// yet been assigned an internal handle.
@@ -1965,16 +1911,20 @@ class QuicSession extends EventEmitter {
1965
1911
this . removeListener ( 'newListener' , onNewListener ) ;
1966
1912
this . removeListener ( 'removeListener' , onRemoveListener ) ;
1967
1913
1914
+ // If we are destroying with an error, schedule the
1915
+ // error to be emitted on process.nextTick.
1968
1916
if ( error ) process . nextTick ( emit . bind ( this , 'error' , error ) ) ;
1969
1917
1970
1918
const handle = this [ kHandle ] ;
1919
+ this [ kHandle ] = undefined ;
1920
+
1971
1921
if ( handle !== undefined ) {
1972
1922
// Copy the stats for use after destruction
1973
1923
state . stats = new BigInt64Array ( handle . stats ) ;
1974
- state . idleTimeout = ! ! handle . state [ IDX_QUIC_SESSION_STATE_IDLE_TIMEOUT ] ;
1975
- // Calling destroy will cause a CONNECTION_CLOSE to be
1976
- // sent to the peer and will destroy the QuicSession
1977
- // handler immediately.
1924
+ state . idleTimeout =
1925
+ Boolean ( handle . state [ IDX_QUIC_SESSION_STATE_IDLE_TIMEOUT ] ) ;
1926
+
1927
+ // Destroy the underlying QuicSession handle
1978
1928
handle . destroy ( state . closeCode , state . closeFamily ) ;
1979
1929
} else {
1980
1930
process . nextTick ( emit . bind ( this , 'close' ) ) ;
@@ -2108,7 +2058,8 @@ class QuicSession extends EventEmitter {
2108
2058
const state = this [ kInternalState ] ;
2109
2059
return {
2110
2060
code : state . closeCode ,
2111
- family : state . closeFamily
2061
+ family : state . closeFamily ,
2062
+ silent : state . silentClose ,
2112
2063
} ;
2113
2064
}
2114
2065
0 commit comments