1'use strict'; 2 3const EventEmitter = require('events'); 4const { kEmptyObject } = require('internal/util'); 5const { Duplex } = require('stream'); 6const _tls_wrap = require('_tls_wrap'); 7const _tls_common = require('_tls_common'); 8 9const { 10 Symbol, 11 ReflectConstruct, 12} = primordials; 13 14const kCallback = Symbol('Callback'); 15const kOtherSide = Symbol('Other'); 16 17class DuplexSocket extends Duplex { 18 constructor() { 19 super(); 20 this[kCallback] = null; 21 this[kOtherSide] = null; 22 } 23 24 _read() { 25 const callback = this[kCallback]; 26 if (callback) { 27 this[kCallback] = null; 28 callback(); 29 } 30 } 31 32 _write(chunk, encoding, callback) { 33 if (chunk.length === 0) { 34 process.nextTick(callback); 35 } else { 36 this[kOtherSide].push(chunk); 37 this[kOtherSide][kCallback] = callback; 38 } 39 } 40 41 _final(callback) { 42 this[kOtherSide].on('end', callback); 43 this[kOtherSide].push(null); 44 } 45} 46 47class DuplexPair { 48 constructor() { 49 this.socket1 = new DuplexSocket(); 50 this.socket2 = new DuplexSocket(); 51 this.socket1[kOtherSide] = this.socket2; 52 this.socket2[kOtherSide] = this.socket1; 53 } 54} 55 56class SecurePair extends EventEmitter { 57 constructor(secureContext = _tls_common.createSecureContext(), 58 isServer = false, 59 requestCert = !isServer, 60 rejectUnauthorized = false, 61 options = kEmptyObject) { 62 super(); 63 const { socket1, socket2 } = new DuplexPair(); 64 65 this.server = options.server; 66 this.credentials = secureContext; 67 68 this.encrypted = socket1; 69 this.cleartext = new _tls_wrap.TLSSocket(socket2, { 70 secureContext, 71 isServer, 72 requestCert, 73 rejectUnauthorized, 74 ...options, 75 }); 76 this.cleartext.once('secure', () => this.emit('secure')); 77 } 78 79 destroy() { 80 this.cleartext.destroy(); 81 this.encrypted.destroy(); 82 } 83} 84 85exports.createSecurePair = function createSecurePair(...args) { 86 return ReflectConstruct(SecurePair, args); 87}; 88