@@ -21,6 +21,7 @@ if (process.features.openssl_is_boringssl) {
2121
2222const assert = require ( 'assert' ) ;
2323const { describe, it } = require ( 'node:test' ) ;
24+ const https = require ( 'node:https' ) ;
2425const tls = require ( 'tls' ) ;
2526const fixtures = require ( '../common/fixtures' ) ;
2627
@@ -117,6 +118,170 @@ describe('TLS callback exception handling', () => {
117118 await promise ;
118119 } ) ;
119120
121+ it ( 'newSession synchronous error emits error' , async ( t ) => {
122+ const server = tls . createServer ( {
123+ key : fixtures . readKey ( 'agent2-key.pem' ) ,
124+ cert : fixtures . readKey ( 'agent2-cert.pem' ) ,
125+ sessionTimeout : 3600 ,
126+ } ) ;
127+ const agent = new https . Agent ( {
128+ keepAlive : false ,
129+ keepAliveMsecs : 10_000 ,
130+ maxSockets : 5 ,
131+ } ) ;
132+
133+ t . after ( ( ) => {
134+ agent . destroy ( ) ;
135+ server . close ( ) ;
136+ } ) ;
137+
138+ const { promise, resolve } = createTestPromise ( ) ;
139+
140+ const expectedError = new Error ( ) ;
141+ server . on ( 'newSession' , common . mustCall ( ( ) => {
142+ setImmediate ( resolve ) ;
143+ throw expectedError ;
144+ } , 2 ) ) ;
145+
146+ server . on ( 'error' , common . mustCall ( ( e ) => {
147+ assert . strictEqual ( e , expectedError ) ;
148+ } , 2 ) ) ;
149+
150+ await new Promise ( ( res ) => server . listen ( 0 , res ) ) ;
151+
152+ // We might need one or two requests to trigger the `resumeSession` event
153+ const clientOptions = {
154+ port : server . address ( ) . port ,
155+ host : '127.0.0.1' ,
156+ rejectUnauthorized : false ,
157+ } ;
158+ // First connection: Establish a session
159+ const socket = tls . connect ( clientOptions , common . mustCall ( ( ) => {
160+ // Close immediately to allow session resumption on next connect
161+ socket . end ( ) ;
162+ } ) ) ;
163+
164+ socket . on ( 'error' , common . mustNotCall ( ) ) ;
165+
166+ socket . on ( 'close' , common . mustCall ( ) ) ;
167+
168+ await promise ;
169+ } ) ;
170+
171+ it ( 'OCSPRequest listener synchronous error emits tlsClientError' , async ( t ) => {
172+ const server = tls . createServer ( {
173+ key : fixtures . readKey ( 'agent2-key.pem' ) ,
174+ cert : fixtures . readKey ( 'agent2-cert.pem' ) ,
175+ requestOCSP : true ,
176+ } ) ;
177+
178+ t . after ( ( ) => server . close ( ) ) ;
179+
180+ const { promise, resolve, reject } = createTestPromise ( ) ;
181+
182+ const expectedError = new Error ( ) ;
183+ server . on ( 'OCSPRequest' , ( cert , issuer , cb ) => {
184+ throw expectedError ;
185+ } ) ;
186+
187+ server . on ( 'tlsClientError' , common . mustCall ( ( err , socket ) => {
188+ try {
189+ assert . strictEqual ( err , expectedError ) ;
190+ socket . destroy ( ) ;
191+ resolve ( ) ;
192+ } catch ( e ) {
193+ reject ( e ) ;
194+ }
195+ } ) ) ;
196+ server . on ( 'secureConnection' , common . mustNotCall ( 'secureConnection listener' ) ) ;
197+ server . on ( 'error' , common . mustNotCall ( 'server error listener' ) ) ;
198+
199+ await new Promise ( ( res ) => server . listen ( 0 , res ) ) ;
200+
201+ const client = tls . connect ( {
202+ port : server . address ( ) . port ,
203+ host : '127.0.0.1' ,
204+ rejectUnauthorized : false ,
205+ requestOCSP : true ,
206+ } ) ;
207+
208+ client . on ( 'error' , common . mustCall ( ) ) ;
209+
210+ await promise ;
211+ } ) ;
212+
213+ it ( 'resumeSession listener synchronous error emits tlsClientError' , async ( t ) => {
214+ const server = tls . createServer ( {
215+ key : fixtures . readKey ( 'agent2-key.pem' ) ,
216+ cert : fixtures . readKey ( 'agent2-cert.pem' ) ,
217+ sessionTimeout : 3600 ,
218+ } ) ;
219+ const agent = new https . Agent ( {
220+ keepAlive : true ,
221+ keepAliveMsecs : 10_000 ,
222+ maxSockets : 5 ,
223+ } ) ;
224+
225+ t . after ( ( ) => {
226+ agent . destroy ( ) ;
227+ server . close ( ) ;
228+ } ) ;
229+
230+ const { promise, resolve, reject } = createTestPromise ( ) ;
231+
232+ const expectedError = new Error ( ) ;
233+ server . on ( 'resumeSession' , ( id , cb ) => {
234+ throw expectedError ;
235+ } ) ;
236+
237+ server . on ( 'tlsClientError' , common . mustCall ( ( err , socket ) => {
238+ try {
239+ assert . strictEqual ( err , expectedError ) ;
240+ socket . destroy ( ) ;
241+ resolve ( ) ;
242+ } catch ( e ) {
243+ reject ( e ) ;
244+ }
245+ } ) ) ;
246+ server . on ( 'error' , common . mustNotCall ( 'server error listener' ) ) ;
247+
248+ await new Promise ( ( res ) => server . listen ( 0 , res ) ) ;
249+
250+ const expectErrorOnResume = common . expectsError ( ) ;
251+
252+ // We might need one or two requests to trigger the `resumeSession` event
253+ let triggeredOnFirstRequest = true ;
254+ const reqOptions = {
255+ port : server . address ( ) . port ,
256+ host : '127.0.0.1' ,
257+ path : '/' ,
258+ method : 'GET' ,
259+ agent,
260+ rejectUnauthorized : false ,
261+ } ;
262+ const req = https . request ( reqOptions , ( res ) => {
263+ triggeredOnFirstRequest = false ;
264+ res . resume ( ) ;
265+ res . on ( 'end' , ( ) => {
266+ const req = https . request ( reqOptions , ( res ) => {
267+ res . resume ( ) ;
268+ } ) ;
269+ req . on ( 'error' , expectErrorOnResume ) ;
270+ req . end ( ) ;
271+ } ) ;
272+ } ) ;
273+
274+ req . on ( 'error' , expectErrorOnResume ) ;
275+ req . end ( ) ;
276+
277+ await promise ;
278+
279+ if ( ! triggeredOnFirstRequest ) {
280+ // The second request would have received the error instead.
281+ req . off ( 'error' , expectErrorOnResume ) ;
282+ }
283+ } ) ;
284+
120285 // Test 2: PSK server callback throwing should emit tlsClientError
121286 it ( 'pskCallback throwing emits tlsClientError' , async ( t ) => {
122287 const server = tls . createServer ( {
0 commit comments