• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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