@@ -4,22 +4,81 @@ const net = require('net')
44const assert = require ( 'assert' )
55const util = require ( './util' )
66const { InvalidArgumentError, ConnectTimeoutError } = require ( './errors' )
7+
78let tls // include tls conditionally since it is not always available
89
910// TODO: session re-use does not wait for the first
1011// connection to resolve the session and might therefore
1112// resolve the same servername multiple times even when
1213// re-use is enabled.
1314
15+ let SessionCache
16+ if ( global . FinalizationRegistry ) {
17+ SessionCache = class WeakSessionCache {
18+ constructor ( maxCachedSessions ) {
19+ this . _maxCachedSessions = maxCachedSessions
20+ this . _sessionCache = new Map ( )
21+ this . _sessionRegistry = new global . FinalizationRegistry ( ( key ) => {
22+ if ( this . _sessionCache . size < this . _maxCachedSessions ) {
23+ return
24+ }
25+
26+ const ref = this . _sessionCache . get ( key )
27+ if ( ref !== undefined && ref . deref ( ) === undefined ) {
28+ this . _sessionCache . delete ( key )
29+ }
30+ } )
31+ }
32+
33+ get ( sessionKey ) {
34+ const ref = this . _sessionCache . get ( sessionKey )
35+ return ref ? ref . deref ( ) : null
36+ }
37+
38+ set ( sessionKey , session ) {
39+ if ( this . _maxCachedSessions === 0 ) {
40+ return
41+ }
42+
43+ this . _sessionCache . set ( sessionKey , new WeakRef ( session ) )
44+ this . _sessionRegistry . register ( session , sessionKey )
45+ }
46+ }
47+ } else {
48+ SessionCache = class SimpleSessionCache {
49+ constructor ( maxCachedSessions ) {
50+ this . _maxCachedSessions = maxCachedSessions
51+ this . _sessionCache = new Map ( )
52+ }
53+
54+ get ( sessionKey ) {
55+ return this . _sessionCache . get ( sessionKey )
56+ }
57+
58+ set ( sessionKey , session ) {
59+ if ( this . _maxCachedSessions === 0 ) {
60+ return
61+ }
62+
63+ if ( this . _sessionCache . size >= this . _maxCachedSessions ) {
64+ // remove the oldest session
65+ const { value : oldestKey } = this . _sessionCache . keys ( ) . next ( )
66+ this . _sessionCache . delete ( oldestKey )
67+ }
68+
69+ this . _sessionCache . set ( sessionKey , session )
70+ }
71+ }
72+ }
73+
1474function buildConnector ( { maxCachedSessions, socketPath, timeout, ...opts } ) {
1575 if ( maxCachedSessions != null && ( ! Number . isInteger ( maxCachedSessions ) || maxCachedSessions < 0 ) ) {
1676 throw new InvalidArgumentError ( 'maxCachedSessions must be a positive integer or zero' )
1777 }
1878
1979 const options = { path : socketPath , ...opts }
20- const sessionCache = new Map ( )
80+ const sessionCache = new SessionCache ( maxCachedSessions == null ? 100 : maxCachedSessions )
2181 timeout = timeout == null ? 10e3 : timeout
22- maxCachedSessions = maxCachedSessions == null ? 100 : maxCachedSessions
2382
2483 return function connect ( { hostname, host, protocol, port, servername, localAddress, httpSocket } , callback ) {
2584 let socket
@@ -47,25 +106,9 @@ function buildConnector ({ maxCachedSessions, socketPath, timeout, ...opts }) {
47106
48107 socket
49108 . on ( 'session' , function ( session ) {
50- // cache is disabled
51- if ( maxCachedSessions === 0 ) {
52- return
53- }
54-
55- if ( sessionCache . size >= maxCachedSessions ) {
56- // remove the oldest session
57- const { value : oldestKey } = sessionCache . keys ( ) . next ( )
58- sessionCache . delete ( oldestKey )
59- }
60-
109+ // TODO (fix): Can a session become invalid once established? Don't think so?
61110 sessionCache . set ( sessionKey , session )
62111 } )
63- . on ( 'error' , function ( err ) {
64- if ( sessionKey && err . code !== 'UND_ERR_INFO' ) {
65- // TODO (fix): Only delete for session related errors.
66- sessionCache . delete ( sessionKey )
67- }
68- } )
69112 } else {
70113 assert ( ! httpSocket , 'httpSocket can only be sent on TLS update' )
71114 socket = net . connect ( {
0 commit comments