summaryrefslogtreecommitdiff
path: root/ext/node/polyfills
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills')
-rw-r--r--ext/node/polyfills/internal/blocklist.mjs227
-rw-r--r--ext/node/polyfills/internal/errors.ts14
-rw-r--r--ext/node/polyfills/net.ts6
3 files changed, 234 insertions, 13 deletions
diff --git a/ext/node/polyfills/internal/blocklist.mjs b/ext/node/polyfills/internal/blocklist.mjs
new file mode 100644
index 000000000..a9aba03b6
--- /dev/null
+++ b/ext/node/polyfills/internal/blocklist.mjs
@@ -0,0 +1,227 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright Joyent and Node contributors. All rights reserved. MIT license.
+
+import { primordials } from "ext:core/mod.js";
+import {
+ op_blocklist_add_address,
+ op_blocklist_add_range,
+ op_blocklist_add_subnet,
+ op_blocklist_check,
+ op_blocklist_new,
+ op_socket_address_get_serialization,
+ op_socket_address_parse,
+} from "ext:core/ops";
+
+import {
+ validateInt32,
+ validateObject,
+ validatePort,
+ validateString,
+ validateUint32,
+} from "ext:deno_node/internal/validators.mjs";
+import { ERR_INVALID_ARG_VALUE } from "ext:deno_node/internal/errors.ts";
+import { customInspectSymbol } from "ext:deno_node/internal/util.mjs";
+import { inspect } from "ext:deno_node/internal/util/inspect.mjs";
+
+const { Symbol } = primordials;
+
+const internalBlockList = Symbol("blocklist");
+
+class BlockList {
+ constructor() {
+ this[internalBlockList] = op_blocklist_new();
+ }
+
+ [customInspectSymbol](depth, options) {
+ if (depth < 0) {
+ return this;
+ }
+
+ const opts = {
+ ...options,
+ depth: options.depth == null ? null : options.depth - 1,
+ };
+
+ return `BlockList ${
+ inspect({
+ rules: [], // TODO(satyarohith): provide the actual rules
+ }, opts)
+ }`;
+ }
+
+ addAddress(address, family = "ipv4") {
+ if (!SocketAddress.isSocketAddress(address)) {
+ validateString(address, "address");
+ validateString(family, "family");
+ new SocketAddress({
+ address,
+ family,
+ });
+ } else {
+ address = address.address;
+ }
+ op_blocklist_add_address(this[internalBlockList], address);
+ }
+
+ addRange(start, end, family = "ipv4") {
+ if (!SocketAddress.isSocketAddress(start)) {
+ validateString(start, "start");
+ validateString(family, "family");
+ new SocketAddress({
+ address: start,
+ family,
+ });
+ } else {
+ start = start.address;
+ }
+ if (!SocketAddress.isSocketAddress(end)) {
+ validateString(end, "end");
+ validateString(family, "family");
+ new SocketAddress({
+ address: end,
+ family,
+ });
+ } else {
+ end = end.address;
+ }
+ const ret = op_blocklist_add_range(this[internalBlockList], start, end);
+ if (ret === false) {
+ throw new ERR_INVALID_ARG_VALUE("start", start, "must come before end");
+ }
+ }
+
+ addSubnet(network, prefix, family = "ipv4") {
+ if (!SocketAddress.isSocketAddress(network)) {
+ validateString(network, "network");
+ validateString(family, "family");
+ new SocketAddress({
+ address: network,
+ family,
+ });
+ } else {
+ network = network.address;
+ family = network.family;
+ }
+ switch (family) {
+ case "ipv4":
+ validateInt32(prefix, "prefix", 0, 32);
+ break;
+ case "ipv6":
+ validateInt32(prefix, "prefix", 0, 128);
+ break;
+ }
+ op_blocklist_add_subnet(this[internalBlockList], network, prefix);
+ }
+
+ check(address, family = "ipv4") {
+ if (!SocketAddress.isSocketAddress(address)) {
+ validateString(address, "address");
+ validateString(family, "family");
+ try {
+ new SocketAddress({
+ address,
+ family,
+ });
+ } catch {
+ // Ignore the error. If it's not a valid address, return false.
+ return false;
+ }
+ } else {
+ family = address.family;
+ address = address.address;
+ }
+ try {
+ return op_blocklist_check(this[internalBlockList], address, family);
+ } catch (_) {
+ // Node API expects false as return value if the address is invalid.
+ // Example: `blocklist.check("1.1.1.1", "ipv6")` should return false.
+ return false;
+ }
+ }
+
+ get rules() {
+ // TODO(satyarohith): return the actual rules
+ return [];
+ }
+}
+
+const kDetail = Symbol("kDetail");
+
+class SocketAddress {
+ static isSocketAddress(value) {
+ return value?.[kDetail] !== undefined;
+ }
+
+ constructor(options = kEmptyObject) {
+ validateObject(options, "options");
+ let { family = "ipv4" } = options;
+ const {
+ address = (family === "ipv4" ? "127.0.0.1" : "::"),
+ port = 0,
+ flowlabel = 0,
+ } = options;
+
+ if (typeof family?.toLowerCase === "function") {
+ // deno-lint-ignore prefer-primordials
+ family = family.toLowerCase();
+ }
+ switch (family) {
+ case "ipv4":
+ break;
+ case "ipv6":
+ break;
+ default:
+ throw new ERR_INVALID_ARG_VALUE("options.family", options.family);
+ }
+
+ validateString(address, "options.address");
+ validatePort(port, "options.port");
+ validateUint32(flowlabel, "options.flowlabel", false);
+
+ this[kDetail] = {
+ address,
+ port,
+ family,
+ flowlabel,
+ };
+ const useInput = op_socket_address_parse(
+ address,
+ port,
+ family,
+ );
+ if (!useInput) {
+ const { 0: address_, 1: family_ } = op_socket_address_get_serialization();
+ this[kDetail].address = address_;
+ this[kDetail].family = family_;
+ }
+ }
+
+ get address() {
+ return this[kDetail].address;
+ }
+
+ get port() {
+ return this[kDetail].port;
+ }
+
+ get family() {
+ return this[kDetail].family;
+ }
+
+ get flowlabel() {
+ // TODO(satyarohith): Implement this in Rust.
+ // The flow label can be changed internally.
+ return this[kDetail].flowlabel;
+ }
+
+ toJSON() {
+ return {
+ address: this.address,
+ port: this.port,
+ family: this.family,
+ flowlabel: this.flowlabel,
+ };
+ }
+}
+
+export { BlockList, SocketAddress };
diff --git a/ext/node/polyfills/internal/errors.ts b/ext/node/polyfills/internal/errors.ts
index cb4119411..6529e9894 100644
--- a/ext/node/polyfills/internal/errors.ts
+++ b/ext/node/polyfills/internal/errors.ts
@@ -667,9 +667,7 @@ function invalidArgTypeHelper(input: any) {
return ` Received type ${typeof input} (${inspected})`;
}
-export class ERR_OUT_OF_RANGE extends RangeError {
- code = "ERR_OUT_OF_RANGE";
-
+export class ERR_OUT_OF_RANGE extends NodeRangeError {
constructor(
str: string,
range: string,
@@ -694,15 +692,7 @@ export class ERR_OUT_OF_RANGE extends RangeError {
}
msg += ` It must be ${range}. Received ${received}`;
- super(msg);
-
- const { name } = this;
- // Add the error code to the name to include it in the stack trace.
- this.name = `${name} [${this.code}]`;
- // Access the stack to generate the error message including the error code from the name.
- this.stack;
- // Reset the name to the actual name.
- this.name = name;
+ super("ERR_OUT_OF_RANGE", msg);
}
}
diff --git a/ext/node/polyfills/net.ts b/ext/node/polyfills/net.ts
index 66b7735d9..6625ce7b5 100644
--- a/ext/node/polyfills/net.ts
+++ b/ext/node/polyfills/net.ts
@@ -24,6 +24,8 @@
// deno-lint-ignore-file prefer-primordials
import { notImplemented } from "ext:deno_node/_utils.ts";
+import { BlockList, SocketAddress } from "ext:deno_node/internal/blocklist.mjs";
+
import { EventEmitter } from "node:events";
import {
isIP,
@@ -2472,7 +2474,7 @@ export function createServer(
return new Server(options, connectionListener);
}
-export { isIP, isIPv4, isIPv6 };
+export { BlockList, isIP, isIPv4, isIPv6, SocketAddress };
export default {
_createServerHandle,
@@ -2480,6 +2482,8 @@ export default {
isIP,
isIPv4,
isIPv6,
+ BlockList,
+ SocketAddress,
connect,
createConnection,
createServer,