@@ -24,7 +24,15 @@ import { shouldPassThrough } from '../util/server-utils';
24
24
import {
25
25
getParentSocket ,
26
26
buildSocketTimingInfo ,
27
- buildSocketEventData
27
+ buildSocketEventData ,
28
+ SocketIsh ,
29
+ InitialRemoteAddress ,
30
+ InitialRemotePort ,
31
+ SocketTimingInfo ,
32
+ LastTunnelAddress ,
33
+ LastHopEncrypted ,
34
+ TlsMetadata ,
35
+ TlsSetupCompleted
28
36
} from '../util/socket-util' ;
29
37
import { MockttpHttpsOptions } from '../mockttp' ;
30
38
import { buildSocksServer , SocksTcpAddress } from './socks-server' ;
@@ -43,10 +51,10 @@ const originalSocketInit = (<any>tls.TLSSocket.prototype)._init;
43
51
const loadSNI = _handle . oncertcb ;
44
52
_handle . oncertcb = function ( info : any ) {
45
53
tlsSocket . servername = info . servername ;
46
- tlsSocket . initialRemoteAddress = tlsSocket . remoteAddress || // Normal case
54
+ tlsSocket [ InitialRemoteAddress ] = tlsSocket . remoteAddress || // Normal case
47
55
tlsSocket . _parent ?. remoteAddress || // For early failing sockets
48
56
tlsSocket . _handle ?. _parentWrap ?. stream ?. remoteAddress ; // For HTTP/2 CONNECT
49
- tlsSocket . initialRemotePort = tlsSocket . remotePort ||
57
+ tlsSocket [ InitialRemotePort ] = tlsSocket . remotePort ||
50
58
tlsSocket . _parent ?. remotePort ||
51
59
tlsSocket . _handle ?. _parentWrap ?. stream ?. remotePort ;
52
60
@@ -76,7 +84,7 @@ function ifTlsDropped(socket: tls.TLSSocket, errorCallback: () => void) {
76
84
// Even if these are shut later on, that doesn't mean they're are rejected connections.
77
85
// To differentiate the two cases, we consider connections OK after waiting 10x longer
78
86
// than the initial TLS handshake for an unhappy disconnection.
79
- const timing = socket . __timingInfo ;
87
+ const timing = socket [ SocketTimingInfo ] ;
80
88
const tlsSetupDuration = timing
81
89
? timing . tlsConnectedTimestamp ! - ( timing . tunnelSetupTimestamp ! || timing . initialSocketTimestamp )
82
90
: 0 ;
@@ -89,11 +97,11 @@ function ifTlsDropped(socket: tls.TLSSocket, errorCallback: () => void) {
89
97
. then ( ( ) => {
90
98
// Mark the socket as having completed TLS setup - this ensures that future
91
99
// errors fire as client errors, not TLS setup errors.
92
- socket . tlsSetupCompleted = true ;
100
+ socket [ TlsSetupCompleted ] = true ;
93
101
} )
94
102
. catch ( ( ) => {
95
103
// If TLS setup was confirmed in any way, we know we don't have a TLS error.
96
- if ( socket . tlsSetupCompleted ) return ;
104
+ if ( socket [ TlsSetupCompleted ] ) return ;
97
105
98
106
// To get here, the socket must have connected & done the TLS handshake, but then
99
107
// closed/ended without ever sending any data. We can fairly confidently assume
@@ -227,8 +235,8 @@ export async function createComboServer(
227
235
228
236
if ( options . debug ) console . log ( `Proxying SOCKS TCP connection to ${ addressString } ` ) ;
229
237
230
- socket . __timingInfo ! . tunnelSetupTimestamp = now ( ) ;
231
- socket . __lastHopConnectAddress = addressString ;
238
+ socket [ SocketTimingInfo ] ! . tunnelSetupTimestamp = now ( ) ;
239
+ socket [ LastTunnelAddress ] = addressString ;
232
240
233
241
// Put the socket back into the server, so we can handle the data within:
234
242
server . emit ( 'connection' , socket ) ;
@@ -245,11 +253,11 @@ export async function createComboServer(
245
253
( server as any ) . _httpServer . requireHostHeader = false ;
246
254
247
255
server . on ( 'connection' , ( socket : net . Socket | http2 . ServerHttp2Stream ) => {
248
- socket . __timingInfo = socket . __timingInfo || buildSocketTimingInfo ( ) ;
256
+ socket [ SocketTimingInfo ] ||= buildSocketTimingInfo ( ) ;
249
257
250
258
// All sockets are initially marked as using unencrypted upstream connections.
251
259
// If TLS is used, this is upgraded to 'true' by secureConnection below.
252
- socket . __lastHopEncrypted = false ;
260
+ socket [ LastHopEncrypted ] = false ;
253
261
254
262
// For actual sockets, set NODELAY to avoid any buffering whilst streaming. This is
255
263
// off by default in Node HTTP, but likely to be enabled soon & is default in curl.
@@ -265,14 +273,14 @@ export async function createComboServer(
265
273
copyTimingDetails ( parentSocket , socket ) ;
266
274
// With TLS metadata, we only propagate directly from parent sockets, not through
267
275
// CONNECT etc - we only want it if the final hop is TLS, previous values don't matter.
268
- socket . __tlsMetadata ??= parentSocket . __tlsMetadata ;
269
- } else if ( ! socket . __timingInfo ) {
270
- socket . __timingInfo = buildSocketTimingInfo ( ) ;
276
+ socket [ TlsMetadata ] ??= parentSocket [ TlsMetadata ] ;
277
+ } else if ( ! socket [ SocketTimingInfo ] ) {
278
+ socket [ SocketTimingInfo ] = buildSocketTimingInfo ( ) ;
271
279
}
272
280
273
- socket . __timingInfo ! . tlsConnectedTimestamp = now ( ) ;
281
+ socket [ SocketTimingInfo ] ! . tlsConnectedTimestamp = now ( ) ;
274
282
275
- socket . __lastHopEncrypted = true ;
283
+ socket [ LastHopEncrypted ] = true ;
276
284
ifTlsDropped ( socket , ( ) => {
277
285
tlsClientErrorListener ( socket , buildTlsError ( socket , 'closed' ) ) ;
278
286
} ) ;
@@ -282,7 +290,7 @@ export async function createComboServer(
282
290
// happens immediately after the connection preface, as long as the connection is OK.
283
291
server ! . on ( 'session' , ( session ) => {
284
292
session . once ( 'remoteSettings' , ( ) => {
285
- session . socket . tlsSetupCompleted = true ;
293
+ ( session . socket as tls . TLSSocket ) [ TlsSetupCompleted ] = true ;
286
294
} ) ;
287
295
} ) ;
288
296
@@ -321,8 +329,8 @@ export async function createComboServer(
321
329
if ( options . debug ) console . log ( `Proxying HTTP/1 CONNECT to ${ connectUrl } ` ) ;
322
330
323
331
socket . write ( 'HTTP/' + req . httpVersion + ' 200 OK\r\n\r\n' , 'utf-8' , ( ) => {
324
- socket . __timingInfo ! . tunnelSetupTimestamp = now ( ) ;
325
- socket . __lastHopConnectAddress = connectUrl ;
332
+ socket [ SocketTimingInfo ] ! . tunnelSetupTimestamp = now ( ) ;
333
+ socket [ LastTunnelAddress ] = connectUrl ;
326
334
server . emit ( 'connection' , socket ) ;
327
335
} ) ;
328
336
}
@@ -343,7 +351,7 @@ export async function createComboServer(
343
351
res . writeHead ( 200 , { } ) ;
344
352
copyAddressDetails ( res . socket , res . stream ) ;
345
353
copyTimingDetails ( res . socket , res . stream ) ;
346
- res . stream . __lastHopConnectAddress = connectUrl ;
354
+ res . stream [ LastTunnelAddress ] = connectUrl ;
347
355
348
356
// When layering HTTP/2 on JS streams, we have to make sure the JS stream won't autoclose
349
357
// when the other side does, because the upper HTTP/2 layers want to handle shutdown, so
@@ -359,15 +367,13 @@ export async function createComboServer(
359
367
return makeDestroyable ( server ) ;
360
368
}
361
369
362
- type SocketIsh < MinProps extends keyof net . Socket > =
363
- streams . Duplex & Partial < Pick < net . Socket , MinProps > > ;
364
370
365
371
const SOCKET_ADDRESS_METADATA_FIELDS = [
366
372
'localAddress' ,
367
373
'localPort' ,
368
374
'remoteAddress' ,
369
375
'remotePort' ,
370
- '__lastHopConnectAddress'
376
+ LastTunnelAddress
371
377
] as const ;
372
378
373
379
// Update the target socket(-ish) with the address details from the source socket,
@@ -388,13 +394,13 @@ function copyAddressDetails(
388
394
} ) ;
389
395
}
390
396
391
- function copyTimingDetails < T extends SocketIsh < '__timingInfo' > > (
392
- source : SocketIsh < '__timingInfo' > ,
397
+ function copyTimingDetails < T extends SocketIsh < typeof SocketTimingInfo > > (
398
+ source : SocketIsh < typeof SocketTimingInfo > ,
393
399
target : T
394
- ) : asserts target is T & { __timingInfo : Required < net . Socket > [ '__timingInfo' ] } {
395
- if ( ! target . __timingInfo ) {
400
+ ) : asserts target is T & { [ SocketTimingInfo ] : Required < net . Socket > [ typeof SocketTimingInfo ] } {
401
+ if ( ! target [ SocketTimingInfo ] ) {
396
402
// Clone timing info, don't copy it - child sockets get their own independent timing stats
397
- target . __timingInfo = Object . assign ( { } , source . __timingInfo ) ;
403
+ target [ SocketTimingInfo ] = Object . assign ( { } , source [ SocketTimingInfo ] ) ;
398
404
}
399
405
}
400
406
@@ -427,17 +433,17 @@ function analyzeAndMaybePassThroughTls(
427
433
// CONNECT or SOCKS) is even better. Note that this may be a hostname or IPv4/6 address:
428
434
let connectHostname : string | undefined ;
429
435
let connectPort : string | undefined ;
430
- if ( socket . __lastHopConnectAddress ) {
431
- const lastColonIndex = socket . __lastHopConnectAddress . lastIndexOf ( ':' ) ;
436
+ if ( socket [ LastTunnelAddress ] ) {
437
+ const lastColonIndex = socket [ LastTunnelAddress ] . lastIndexOf ( ':' ) ;
432
438
if ( lastColonIndex !== - 1 ) {
433
- connectHostname = socket . __lastHopConnectAddress . slice ( 0 , lastColonIndex ) ;
434
- connectPort = socket . __lastHopConnectAddress . slice ( lastColonIndex + 1 ) ;
439
+ connectHostname = socket [ LastTunnelAddress ] . slice ( 0 , lastColonIndex ) ;
440
+ connectPort = socket [ LastTunnelAddress ] . slice ( lastColonIndex + 1 ) ;
435
441
} else {
436
- connectHostname = socket . __lastHopConnectAddress ;
442
+ connectHostname = socket [ LastTunnelAddress ] ;
437
443
}
438
444
}
439
445
440
- socket . __tlsMetadata = {
446
+ socket [ TlsMetadata ] = {
441
447
sniHostname,
442
448
connectHostname,
443
449
connectPort,
0 commit comments