• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const {
4  ObjectSetPrototypeOf,
5  Symbol,
6} = primordials;
7
8const {
9  SocketAddress: _SocketAddress,
10  AF_INET,
11  AF_INET6,
12} = internalBinding('block_list');
13
14const {
15  validateObject,
16  validateString,
17  validatePort,
18  validateUint32,
19} = require('internal/validators');
20
21const {
22  codes: {
23    ERR_INVALID_ARG_VALUE,
24  },
25} = require('internal/errors');
26
27const {
28  customInspectSymbol: kInspect,
29} = require('internal/util');
30
31const { inspect } = require('internal/util/inspect');
32
33const {
34  JSTransferable,
35  kClone,
36  kDeserialize,
37} = require('internal/worker/js_transferable');
38
39const kHandle = Symbol('kHandle');
40const kDetail = Symbol('kDetail');
41
42class SocketAddress extends JSTransferable {
43  static isSocketAddress(value) {
44    return value?.[kHandle] !== undefined;
45  }
46
47  constructor(options = {}) {
48    super();
49    validateObject(options, 'options');
50    let { family = 'ipv4' } = options;
51    const {
52      address = (family === 'ipv4' ? '127.0.0.1' : '::'),
53      port = 0,
54      flowlabel = 0,
55    } = options;
56
57    let type;
58    if (typeof family?.toLowerCase === 'function')
59      family = family.toLowerCase();
60    switch (family) {
61      case 'ipv4':
62        type = AF_INET;
63        break;
64      case 'ipv6':
65        type = AF_INET6;
66        break;
67      default:
68        throw new ERR_INVALID_ARG_VALUE('options.family', options.family);
69    }
70
71    validateString(address, 'options.address');
72    validatePort(port, 'options.port');
73    validateUint32(flowlabel, 'options.flowlabel', false);
74
75    this[kHandle] = new _SocketAddress(address, port, type, flowlabel);
76    this[kDetail] = this[kHandle].detail({
77      address: undefined,
78      port: undefined,
79      family: undefined,
80      flowlabel: undefined,
81    });
82  }
83
84  get address() {
85    return this[kDetail].address;
86  }
87
88  get port() {
89    return this[kDetail].port;
90  }
91
92  get family() {
93    return this[kDetail].family === AF_INET ? 'ipv4' : 'ipv6';
94  }
95
96  get flowlabel() {
97    // The flow label can be changed internally.
98    return this[kHandle].flowlabel();
99  }
100
101  [kInspect](depth, options) {
102    if (depth < 0)
103      return this;
104
105    const opts = {
106      ...options,
107      depth: options.depth == null ? null : options.depth - 1
108    };
109
110    return `SocketAddress ${inspect(this.toJSON(), opts)}`;
111  }
112
113  [kClone]() {
114    const handle = this[kHandle];
115    return {
116      data: { handle },
117      deserializeInfo: 'internal/socketaddress:InternalSocketAddress',
118    };
119  }
120
121  [kDeserialize]({ handle }) {
122    this[kHandle] = handle;
123    this[kDetail] = handle.detail({
124      address: undefined,
125      port: undefined,
126      family: undefined,
127      flowlabel: undefined,
128    });
129  }
130
131  toJSON() {
132    return {
133      address: this.address,
134      port: this.port,
135      family: this.family,
136      flowlabel: this.flowlabel,
137    };
138  }
139}
140
141class InternalSocketAddress extends JSTransferable {
142  constructor(handle) {
143    super();
144    this[kHandle] = handle;
145  }
146}
147
148InternalSocketAddress.prototype.constructor =
149  SocketAddress.prototype.construtor;
150ObjectSetPrototypeOf(InternalSocketAddress.prototype, SocketAddress.prototype);
151
152module.exports = {
153  SocketAddress,
154  InternalSocketAddress,
155  kHandle,
156};
157