aboutsummaryrefslogtreecommitdiff
path: root/src/js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js')
-rw-r--r--src/js/node/net.js151
-rw-r--r--src/js/node/tls.js351
-rw-r--r--src/js/out/modules/node/net.js118
-rw-r--r--src/js/out/modules/node/tls.js190
4 files changed, 702 insertions, 108 deletions
diff --git a/src/js/node/net.js b/src/js/node/net.js
index 430a0dfa2..1b7742dd1 100644
--- a/src/js/node/net.js
+++ b/src/js/node/net.js
@@ -64,6 +64,7 @@ const bunTlsSymbol = Symbol.for("::buntls::");
const bunSocketServerHandlers = Symbol.for("::bunsocket_serverhandlers::");
const bunSocketServerConnections = Symbol.for("::bunnetserverconnections::");
const bunSocketServerOptions = Symbol.for("::bunnetserveroptions::");
+const bunSocketInternal = Symbol.for("::bunnetsocketinternal::");
var SocketClass;
const Socket = (function (InternalSocket) {
@@ -117,7 +118,7 @@ const Socket = (function (InternalSocket) {
const self = socket.data;
socket.timeout(self.timeout);
socket.ref();
- self.#socket = socket;
+ self[bunSocketInternal] = socket;
self.connecting = false;
self.emit("connect", self);
Socket.#Drain(socket);
@@ -164,7 +165,7 @@ const Socket = (function (InternalSocket) {
if (self.#closed) return;
self.#closed = true;
//socket cannot be used after close
- self.#socket = null;
+ self[bunSocketInternal] = null;
const queue = self.#readQueue;
if (queue.isEmpty()) {
if (self.push(null)) return;
@@ -289,23 +290,33 @@ const Socket = (function (InternalSocket) {
localAddress = "127.0.0.1";
#readQueue = createFIFO();
remotePort;
- #socket;
+ [bunSocketInternal] = null;
timeout = 0;
#writeCallback;
#writeChunk;
#pendingRead;
isServer = false;
+ _handle;
+ _parent;
+ _parentWrap;
+ #socket;
constructor(options) {
- const { signal, write, read, allowHalfOpen = false, ...opts } = options || {};
+ const { socket, signal, write, read, allowHalfOpen = false, ...opts } = options || {};
super({
...opts,
allowHalfOpen,
readable: true,
writable: true,
});
+ this._handle = this;
+ this._parent = this;
+ this._parentWrap = this;
this.#pendingRead = undefined;
+ if (socket instanceof Socket) {
+ this.#socket = socket;
+ }
signal?.once("abort", () => this.destroy());
this.once("connect", () => this.emit("ready"));
}
@@ -327,7 +338,7 @@ const Socket = (function (InternalSocket) {
socket.data = this;
socket.timeout(this.timeout);
socket.ref();
- this.#socket = socket;
+ this[bunSocketInternal] = socket;
this.connecting = false;
this.emit("connect", this);
Socket.#Drain(socket);
@@ -335,6 +346,7 @@ const Socket = (function (InternalSocket) {
connect(port, host, connectListener) {
var path;
+ var connection = this.#socket;
if (typeof port === "string") {
path = port;
port = undefined;
@@ -357,6 +369,7 @@ const Socket = (function (InternalSocket) {
port,
host,
path,
+ socket,
// TODOs
localAddress,
localPort,
@@ -371,7 +384,11 @@ const Socket = (function (InternalSocket) {
pauseOnConnect,
servername,
} = port;
+
this.servername = servername;
+ if (socket) {
+ connection = socket;
+ }
}
if (!pauseOnConnect) {
@@ -399,41 +416,117 @@ const Socket = (function (InternalSocket) {
} else {
tls.rejectUnauthorized = rejectUnauthorized;
tls.requestCert = true;
+ if (!connection && tls.socket) {
+ connection = tls.socket;
+ }
+ }
+ }
+ if (connection) {
+ if (
+ typeof connection !== "object" ||
+ !(connection instanceof Socket) ||
+ typeof connection[bunTlsSymbol] === "function"
+ ) {
+ throw new TypeError("socket must be an instance of net.Socket");
}
}
-
this.authorized = false;
this.secureConnecting = true;
this._secureEstablished = false;
this._securePending = true;
if (connectListener) this.on("secureConnect", connectListener);
} else if (connectListener) this.on("connect", connectListener);
- bunConnect(
- path
- ? {
+ // start using existing connection
+
+ if (connection) {
+ const socket = connection[bunSocketInternal];
+
+ if (socket) {
+ const result = socket.wrapTLS({
+ data: this,
+ tls,
+ socket: Socket.#Handlers,
+ });
+ if (result) {
+ const [raw, tls] = result;
+ // replace socket
+ connection[bunSocketInternal] = raw;
+ raw.timeout(raw.timeout);
+ raw.connecting = false;
+ // set new socket
+ this[bunSocketInternal] = tls;
+ tls.timeout(tls.timeout);
+ tls.connecting = true;
+ this[bunSocketInternal] = socket;
+ // start tls
+ tls.open();
+ } else {
+ this[bunSocketInternal] = null;
+ throw new Error("Invalid socket");
+ }
+ } else {
+ // wait to be connected
+ connection.once("connect", () => {
+ const socket = connection[bunSocketInternal];
+ if (!socket) return;
+
+ const result = socket.wrapTLS({
data: this,
- unix: path,
- socket: Socket.#Handlers,
tls,
- }
- : {
- data: this,
- hostname: host || "localhost",
- port: port,
socket: Socket.#Handlers,
- tls,
- },
- );
+ });
+
+ if (result) {
+ const [raw, tls] = result;
+ // replace socket
+ connection[bunSocketInternal] = raw;
+ raw.timeout(raw.timeout);
+ raw.connecting = false;
+ // set new socket
+ this[bunSocketInternal] = tls;
+ tls.timeout(tls.timeout);
+ tls.connecting = true;
+ this[bunSocketInternal] = socket;
+ // start tls
+ tls.open();
+ } else {
+ this[bunSocketInternal] = null;
+ throw new Error("Invalid socket");
+ }
+ });
+ }
+ } else if (path) {
+ // start using unix socket
+ bunConnect({
+ data: this,
+ unix: path,
+ socket: Socket.#Handlers,
+ tls,
+ }).catch(error => {
+ this.emit("error", error);
+ });
+ } else {
+ // default start
+ bunConnect({
+ data: this,
+ hostname: host || "localhost",
+ port: port,
+ socket: Socket.#Handlers,
+ tls,
+ }).catch(error => {
+ this.emit("error", error);
+ });
+ }
return this;
}
_destroy(err, callback) {
- this.#socket?.end();
+ this[bunSocketInternal]?.end();
callback(err);
}
_final(callback) {
- this.#socket?.end();
+ this[bunSocketInternal]?.end();
callback();
}
@@ -446,7 +539,7 @@ const Socket = (function (InternalSocket) {
}
get localPort() {
- return this.#socket?.localPort;
+ return this[bunSocketInternal]?.localPort;
}
get pending() {
@@ -472,11 +565,11 @@ const Socket = (function (InternalSocket) {
}
ref() {
- this.#socket?.ref();
+ this[bunSocketInternal]?.ref();
}
get remoteAddress() {
- return this.#socket?.remoteAddress;
+ return this[bunSocketInternal]?.remoteAddress;
}
get remoteFamily() {
@@ -484,7 +577,7 @@ const Socket = (function (InternalSocket) {
}
resetAndDestroy() {
- this.#socket?.end();
+ this[bunSocketInternal]?.end();
}
setKeepAlive(enable = false, initialDelay = 0) {
@@ -498,19 +591,19 @@ const Socket = (function (InternalSocket) {
}
setTimeout(timeout, callback) {
- this.#socket?.timeout(timeout);
+ this[bunSocketInternal]?.timeout(timeout);
this.timeout = timeout;
if (callback) this.once("timeout", callback);
return this;
}
unref() {
- this.#socket?.unref();
+ this[bunSocketInternal]?.unref();
}
_write(chunk, encoding, callback) {
- if (typeof chunk == "string" && encoding !== "utf8") chunk = Buffer.from(chunk, encoding);
- var written = this.#socket?.write(chunk);
+ if (typeof chunk == "string" && encoding !== "ascii") chunk = Buffer.from(chunk, encoding);
+ var written = this[bunSocketInternal]?.write(chunk);
if (written == chunk.length) {
callback();
} else if (this.#writeCallback) {
diff --git a/src/js/node/tls.js b/src/js/node/tls.js
index 356c25cbd..310a36620 100644
--- a/src/js/node/tls.js
+++ b/src/js/node/tls.js
@@ -1,9 +1,30 @@
// Hardcoded module "node:tls"
-import { isTypedArray } from "util/types";
+import { isArrayBufferView, isTypedArray } from "util/types";
import net, { Server as NetServer } from "node:net";
const InternalTCPSocket = net[Symbol.for("::bunternal::")];
-
+const bunSocketInternal = Symbol.for("::bunnetsocketinternal::");
+
+const { RegExp, Array, String } = globalThis[Symbol.for("Bun.lazy")]("primordials");
+const SymbolReplace = Symbol.replace;
+const RegExpPrototypeSymbolReplace = RegExp.prototype[SymbolReplace];
+const RegExpPrototypeExec = RegExp.prototype.exec;
+
+const StringPrototypeStartsWith = String.prototype.startsWith;
+const StringPrototypeSlice = String.prototype.slice;
+const StringPrototypeIncludes = String.prototype.includes;
+const StringPrototypeSplit = String.prototype.split;
+const StringPrototypeIndexOf = String.prototype.indexOf;
+const StringPrototypeSubstring = String.prototype.substring;
+const StringPrototypeEndsWith = String.prototype.endsWith;
+
+const ArrayPrototypeIncludes = Array.prototype.includes;
+const ArrayPrototypeJoin = Array.prototype.join;
+const ArrayPrototypeForEach = Array.prototype.forEach;
+const ArrayPrototypePush = Array.prototype.push;
+const ArrayPrototypeSome = Array.prototype.some;
+const ArrayPrototypeReduce = Array.prototype.reduce;
function parseCertString() {
+ // Removed since JAN 2022 Node v18.0.0+ https://github.com/nodejs/node/pull/41479
throwNotImplemented("Not implemented");
}
@@ -18,6 +39,164 @@ function isValidTLSArray(obj) {
}
}
+function unfqdn(host) {
+ return RegExpPrototypeSymbolReplace(/[.]$/, host, "");
+}
+
+function splitHost(host) {
+ return StringPrototypeSplit.call(RegExpPrototypeSymbolReplace(/[A-Z]/g, unfqdn(host), toLowerCase), ".");
+}
+
+function check(hostParts, pattern, wildcards) {
+ // Empty strings, null, undefined, etc. never match.
+ if (!pattern) return false;
+
+ const patternParts = splitHost(pattern);
+
+ if (hostParts.length !== patternParts.length) return false;
+
+ // Pattern has empty components, e.g. "bad..example.com".
+ if (ArrayPrototypeIncludes.call(patternParts, "")) return false;
+
+ // RFC 6125 allows IDNA U-labels (Unicode) in names but we have no
+ // good way to detect their encoding or normalize them so we simply
+ // reject them. Control characters and blanks are rejected as well
+ // because nothing good can come from accepting them.
+ const isBad = s => RegExpPrototypeExec.call(/[^\u0021-\u007F]/u, s) !== null;
+ if (ArrayPrototypeSome.call(patternParts, isBad)) return false;
+
+ // Check host parts from right to left first.
+ for (let i = hostParts.length - 1; i > 0; i -= 1) {
+ if (hostParts[i] !== patternParts[i]) return false;
+ }
+
+ const hostSubdomain = hostParts[0];
+ const patternSubdomain = patternParts[0];
+ const patternSubdomainParts = StringPrototypeSplit.call(patternSubdomain, "*");
+
+ // Short-circuit when the subdomain does not contain a wildcard.
+ // RFC 6125 does not allow wildcard substitution for components
+ // containing IDNA A-labels (Punycode) so match those verbatim.
+ if (patternSubdomainParts.length === 1 || StringPrototypeIncludes.call(patternSubdomain, "xn--"))
+ return hostSubdomain === patternSubdomain;
+
+ if (!wildcards) return false;
+
+ // More than one wildcard is always wrong.
+ if (patternSubdomainParts.length > 2) return false;
+
+ // *.tld wildcards are not allowed.
+ if (patternParts.length <= 2) return false;
+
+ const { 0: prefix, 1: suffix } = patternSubdomainParts;
+
+ if (prefix.length + suffix.length > hostSubdomain.length) return false;
+
+ if (!StringPrototypeStartsWith.call(hostSubdomain, prefix)) return false;
+
+ if (!StringPrototypeEndsWith.call(hostSubdomain, suffix)) return false;
+
+ return true;
+}
+
+// This pattern is used to determine the length of escaped sequences within
+// the subject alt names string. It allows any valid JSON string literal.
+// This MUST match the JSON specification (ECMA-404 / RFC8259) exactly.
+const jsonStringPattern =
+ // eslint-disable-next-line no-control-regex
+ /^"(?:[^"\\\u0000-\u001f]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4}))*"/;
+
+function splitEscapedAltNames(altNames) {
+ const result = [];
+ let currentToken = "";
+ let offset = 0;
+ while (offset !== altNames.length) {
+ const nextSep = StringPrototypeIndexOf.call(altNames, ", ", offset);
+ const nextQuote = StringPrototypeIndexOf.call(altNames, '"', offset);
+ if (nextQuote !== -1 && (nextSep === -1 || nextQuote < nextSep)) {
+ // There is a quote character and there is no separator before the quote.
+ currentToken += StringPrototypeSubstring.call(altNames, offset, nextQuote);
+ const match = RegExpPrototypeExec.call(jsonStringPattern, StringPrototypeSubstring.call(altNames, nextQuote));
+ if (!match) {
+ let error = new SyntaxError("ERR_TLS_CERT_ALTNAME_FORMAT: Invalid subject alternative name string");
+ error.name = ERR_TLS_CERT_ALTNAME_FORMAT;
+ throw error;
+ }
+ currentToken += JSON.parse(match[0]);
+ offset = nextQuote + match[0].length;
+ } else if (nextSep !== -1) {
+ // There is a separator and no quote before it.
+ currentToken += StringPrototypeSubstring.call(altNames, offset, nextSep);
+ ArrayPrototypePush.call(result, currentToken);
+ currentToken = "";
+ offset = nextSep + 2;
+ } else {
+ currentToken += StringPrototypeSubstring.call(altNames, offset);
+ offset = altNames.length;
+ }
+ }
+ ArrayPrototypePush.call(result, currentToken);
+ return result;
+}
+function checkServerIdentity(hostname, cert) {
+ const subject = cert.subject;
+ const altNames = cert.subjectaltname;
+ const dnsNames = [];
+ const ips = [];
+
+ hostname = "" + hostname;
+
+ if (altNames) {
+ const splitAltNames = StringPrototypeIncludes.call(altNames, '"')
+ ? splitEscapedAltNames(altNames)
+ : StringPrototypeSplit.call(altNames, ", ");
+ ArrayPrototypeForEach.call(splitAltNames, name => {
+ if (StringPrototypeStartsWith.call(name, "DNS:")) {
+ ArrayPrototypePush.call(dnsNames, StringPrototypeSlice.call(name, 4));
+ } else if (StringPrototypeStartsWith.call(name, "IP Address:")) {
+ ArrayPrototypePush.call(ips, canonicalizeIP(StringPrototypeSlice.call(name, 11)));
+ }
+ });
+ }
+
+ let valid = false;
+ let reason = "Unknown reason";
+
+ hostname = unfqdn(hostname); // Remove trailing dot for error messages.
+
+ if (net.isIP(hostname)) {
+ valid = ArrayPrototypeIncludes.call(ips, canonicalizeIP(hostname));
+ if (!valid) reason = `IP: ${hostname} is not in the cert's list: ` + ArrayPrototypeJoin.call(ips, ", ");
+ } else if (dnsNames.length > 0 || subject?.CN) {
+ const hostParts = splitHost(hostname);
+ const wildcard = pattern => check(hostParts, pattern, true);
+
+ if (dnsNames.length > 0) {
+ valid = ArrayPrototypeSome.call(dnsNames, wildcard);
+ if (!valid) reason = `Host: ${hostname}. is not in the cert's altnames: ${altNames}`;
+ } else {
+ // Match against Common Name only if no supported identifiers exist.
+ const cn = subject.CN;
+
+ if (ArrayIsArray(cn)) valid = ArrayPrototypeSome.call(cn, wildcard);
+ else if (cn) valid = wildcard(cn);
+
+ if (!valid) reason = `Host: ${hostname}. is not cert's CN: ${cn}`;
+ }
+ } else {
+ reason = "Cert does not contain a DNS name";
+ }
+
+ if (!valid) {
+ let error = new Error(`ERR_TLS_CERT_ALTNAME_INVALID: Hostname/IP does not match certificate's altnames: ${reason}`);
+ error.name = "ERR_TLS_CERT_ALTNAME_INVALID";
+ error.reason = reason;
+ error.host = host;
+ error.cert = cert;
+ return error;
+ }
+}
+
var InternalSecureContext = class SecureContext {
context;
@@ -83,6 +262,36 @@ function createSecureContext(options) {
return new SecureContext(options);
}
+// Translate some fields from the handle's C-friendly format into more idiomatic
+// javascript object representations before passing them back to the user. Can
+// be used on any cert object, but changing the name would be semver-major.
+function translatePeerCertificate(c) {
+ if (!c) return null;
+
+ if (c.issuerCertificate != null && c.issuerCertificate !== c) {
+ c.issuerCertificate = translatePeerCertificate(c.issuerCertificate);
+ }
+ if (c.infoAccess != null) {
+ const info = c.infoAccess;
+ c.infoAccess = { __proto__: null };
+
+ // XXX: More key validation?
+ RegExpPrototypeSymbolReplace(/([^\n:]*):([^\n]*)(?:\n|$)/g, info, (all, key, val) => {
+ if (val.charCodeAt(0) === 0x22) {
+ // The translatePeerCertificate function is only
+ // used on internally created legacy certificate
+ // objects, and any value that contains a quote
+ // will always be a valid JSON string literal,
+ // so this should never throw.
+ val = JSONParse(val);
+ }
+ if (key in c.infoAccess) ArrayPrototypePush.call(c.infoAccess[key], val);
+ else c.infoAccess[key] = [val];
+ });
+ }
+ return c;
+}
+
const buntls = Symbol.for("::buntls::");
var SocketClass;
@@ -107,8 +316,22 @@ const TLSSocket = (function (InternalTLSSocket) {
})(
class TLSSocket extends InternalTCPSocket {
#secureContext;
- constructor(options) {
- super(options);
+ ALPNProtocols;
+ #socket;
+
+ constructor(socket, options) {
+ super(socket instanceof InternalTCPSocket ? options : options || socket);
+ options = options || socket || {};
+ if (typeof options === "object") {
+ const { ALPNProtocols } = options;
+ if (ALPNProtocols) {
+ convertALPNProtocols(ALPNProtocols, this);
+ }
+ if (socket instanceof InternalTCPSocket) {
+ this.#socket = socket;
+ }
+ }
+
this.#secureContext = options.secureContext || createSecureContext(options);
this.authorized = false;
this.secureConnecting = true;
@@ -123,28 +346,52 @@ const TLSSocket = (function (InternalTLSSocket) {
secureConnecting = false;
_SNICallback;
servername;
- alpnProtocol;
authorized = false;
authorizationError;
encrypted = true;
- exportKeyingMaterial() {
- throw Error("Not implented in Bun yet");
+ _start() {
+ // some frameworks uses this _start internal implementation is suposed to start TLS handshake
+ // on Bun we auto start this after on_open callback and when wrapping we start it after the socket is attached to the net.Socket/tls.Socket
}
- setMaxSendFragment() {
+
+ exportKeyingMaterial(length, label, context) {
+ //SSL_export_keying_material
throw Error("Not implented in Bun yet");
}
- setServername() {
+ setMaxSendFragment(size) {
+ // SSL_set_max_send_fragment
throw Error("Not implented in Bun yet");
}
+ setServername(name) {
+ if (this.isServer) {
+ let error = new Error("ERR_TLS_SNI_FROM_SERVER: Cannot issue SNI from a TLS server-side socket");
+ error.name = "ERR_TLS_SNI_FROM_SERVER";
+ throw error;
+ }
+ // if the socket is detached we can't set the servername but we set this property so when open will auto set to it
+ this.servername = name;
+ this[bunSocketInternal]?.setServername(name);
+ }
setSession() {
throw Error("Not implented in Bun yet");
}
getPeerCertificate() {
+ // need to implement peerCertificate on socket.zig
+ // const cert = this[bunSocketInternal]?.peerCertificate;
+ // if(cert) {
+ // return translatePeerCertificate(cert);
+ // }
throw Error("Not implented in Bun yet");
}
getCertificate() {
+ // need to implement certificate on socket.zig
+ // const cert = this[bunSocketInternal]?.certificate;
+ // if(cert) {
+ // It's not a peer cert, but the formatting is identical.
+ // return translatePeerCertificate(cert);
+ // }
throw Error("Not implented in Bun yet");
}
getPeerX509Certificate() {
@@ -154,16 +401,17 @@ const TLSSocket = (function (InternalTLSSocket) {
throw Error("Not implented in Bun yet");
}
- [buntls](port, host) {
- var { servername } = this;
- if (servername) {
- return {
- serverName: typeof servername === "string" ? servername : host,
- ...this.#secureContext,
- };
- }
+ get alpnProtocol() {
+ return this[bunSocketInternal]?.alpnProtocol;
+ }
- return true;
+ [buntls](port, host) {
+ return {
+ socket: this.#socket,
+ ALPNProtocols: this.ALPNProtocols,
+ serverName: this.servername || host || "localhost",
+ ...this.#secureContext,
+ };
}
},
);
@@ -177,9 +425,12 @@ class Server extends NetServer {
_rejectUnauthorized;
_requestCert;
servername;
+ ALPNProtocols;
+ #checkServerIdentity;
constructor(options, secureConnectionListener) {
super(options, secureConnectionListener);
+ this.#checkServerIdentity = options?.checkServerIdentity || checkServerIdentity;
this.setSecureContext(options);
}
emit(event, args) {
@@ -197,6 +448,12 @@ class Server extends NetServer {
options = options.context;
}
if (options) {
+ const { ALPNProtocols } = options;
+
+ if (ALPNProtocols) {
+ convertALPNProtocols(ALPNProtocols, this);
+ }
+
let key = options.key;
if (key) {
if (!isValidTLSArray(key)) {
@@ -277,6 +534,8 @@ class Server extends NetServer {
// Client always is NONE on set_verify
rejectUnauthorized: isClient ? false : this._rejectUnauthorized,
requestCert: isClient ? false : this._requestCert,
+ ALPNProtocols: this.ALPNProtocols,
+ checkServerIdentity: this.#checkServerIdentity,
},
SocketClass,
];
@@ -296,6 +555,11 @@ const CLIENT_RENEG_LIMIT = 3,
DEFAULT_MAX_VERSION = "TLSv1.3",
createConnection = (port, host, connectListener) => {
if (typeof port === "object") {
+ port.checkServerIdentity || checkServerIdentity;
+ const { ALPNProtocols } = port;
+ if (ALPNProtocols) {
+ convertALPNProtocols(ALPNProtocols, port);
+ }
// port is option pass Socket options and let connect handle connection options
return new TLSSocket(port).connect(port, host, connectListener);
}
@@ -312,7 +576,55 @@ function getCurves() {
return;
}
-function convertALPNProtocols(protocols, out) {}
+// Convert protocols array into valid OpenSSL protocols list
+// ("\x06spdy/2\x08http/1.1\x08http/1.0")
+function convertProtocols(protocols) {
+ const lens = new Array(protocols.length);
+ const buff = Buffer.allocUnsafe(
+ ArrayPrototypeReduce.call(
+ protocols,
+ (p, c, i) => {
+ const len = Buffer.byteLength(c);
+ if (len > 255) {
+ throw new RangeError(
+ "The byte length of the protocol at index " + `${i} exceeds the maximum length.`,
+ "<= 255",
+ len,
+ true,
+ );
+ }
+ lens[i] = len;
+ return p + 1 + len;
+ },
+ 0,
+ ),
+ );
+
+ let offset = 0;
+ for (let i = 0, c = protocols.length; i < c; i++) {
+ buff[offset++] = lens[i];
+ buff.write(protocols[i], offset);
+ offset += lens[i];
+ }
+
+ return buff;
+}
+
+function convertALPNProtocols(protocols, out) {
+ // If protocols is Array - translate it into buffer
+ if (Array.isArray(protocols)) {
+ out.ALPNProtocols = convertProtocols(protocols);
+ } else if (isTypedArray(protocols)) {
+ // Copy new buffer not to be modified by user.
+ out.ALPNProtocols = Buffer.from(protocols);
+ } else if (isArrayBufferView(protocols)) {
+ out.ALPNProtocols = Buffer.from(
+ protocols.buffer.slice(protocols.byteOffset, protocols.byteOffset + protocols.byteLength),
+ );
+ } else if (Buffer.isBuffer(protocols)) {
+ out.ALPNProtocols = protocols;
+ }
+}
var exports = {
[Symbol.for("CommonJS")]: 0,
@@ -351,6 +663,7 @@ export {
getCurves,
parseCertString,
SecureContext,
+ checkServerIdentity,
Server,
TLSSocket,
exports as default,
diff --git a/src/js/out/modules/node/net.js b/src/js/out/modules/node/net.js
index 164ec6677..c34f86b04 100644
--- a/src/js/out/modules/node/net.js
+++ b/src/js/out/modules/node/net.js
@@ -26,7 +26,7 @@ var isIPv4 = function(s) {
self.emit("listening");
}, createServer = function(options, connectionListener) {
return new Server(options, connectionListener);
-}, v4Seg = "(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])", v4Str = `(${v4Seg}[.]){3}${v4Seg}`, IPv4Reg = new RegExp(`^${v4Str}$`), v6Seg = "(?:[0-9a-fA-F]{1,4})", IPv6Reg = new RegExp("^(" + `(?:${v6Seg}:){7}(?:${v6Seg}|:)|` + `(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` + `(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` + `(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` + `(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` + `(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` + `(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` + `(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` + ")(%[0-9a-zA-Z-.:]{1,})?$"), { Bun, createFIFO, Object } = globalThis[Symbol.for("Bun.lazy")]("primordials"), { connect: bunConnect } = Bun, { setTimeout } = globalThis, bunTlsSymbol = Symbol.for("::buntls::"), bunSocketServerHandlers = Symbol.for("::bunsocket_serverhandlers::"), bunSocketServerConnections = Symbol.for("::bunnetserverconnections::"), bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"), SocketClass, Socket = function(InternalSocket) {
+}, v4Seg = "(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])", v4Str = `(${v4Seg}[.]){3}${v4Seg}`, IPv4Reg = new RegExp(`^${v4Str}$`), v6Seg = "(?:[0-9a-fA-F]{1,4})", IPv6Reg = new RegExp("^(" + `(?:${v6Seg}:){7}(?:${v6Seg}|:)|` + `(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` + `(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` + `(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` + `(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` + `(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` + `(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` + `(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` + ")(%[0-9a-zA-Z-.:]{1,})?$"), { Bun, createFIFO, Object } = globalThis[Symbol.for("Bun.lazy")]("primordials"), { connect: bunConnect } = Bun, { setTimeout } = globalThis, bunTlsSymbol = Symbol.for("::buntls::"), bunSocketServerHandlers = Symbol.for("::bunsocket_serverhandlers::"), bunSocketServerConnections = Symbol.for("::bunnetserverconnections::"), bunSocketServerOptions = Symbol.for("::bunnetserveroptions::"), bunSocketInternal = Symbol.for("::bunnetsocketinternal::"), SocketClass, Socket = function(InternalSocket) {
return SocketClass = InternalSocket, Object.defineProperty(SocketClass.prototype, Symbol.toStringTag, {
value: "Socket",
enumerable: !1
@@ -62,7 +62,7 @@ var isIPv4 = function(s) {
},
open(socket) {
const self = socket.data;
- socket.timeout(self.timeout), socket.ref(), self.#socket = socket, self.connecting = !1, self.emit("connect", self), Socket2.#Drain(socket);
+ socket.timeout(self.timeout), socket.ref(), self[bunSocketInternal] = socket, self.connecting = !1, self.emit("connect", self), Socket2.#Drain(socket);
},
handshake(socket, success, verifyError) {
const { data: self } = socket;
@@ -87,7 +87,7 @@ var isIPv4 = function(s) {
const self = socket.data;
if (self.#closed)
return;
- self.#closed = !0, self.#socket = null;
+ self.#closed = !0, self[bunSocketInternal] = null;
const queue = self.#readQueue;
if (queue.isEmpty()) {
if (self.push(null))
@@ -163,21 +163,27 @@ var isIPv4 = function(s) {
localAddress = "127.0.0.1";
#readQueue = createFIFO();
remotePort;
- #socket;
+ [bunSocketInternal] = null;
timeout = 0;
#writeCallback;
#writeChunk;
#pendingRead;
isServer = !1;
+ _handle;
+ _parent;
+ _parentWrap;
+ #socket;
constructor(options) {
- const { signal, write, read, allowHalfOpen = !1, ...opts } = options || {};
+ const { socket, signal, write, read, allowHalfOpen = !1, ...opts } = options || {};
super({
...opts,
allowHalfOpen,
readable: !0,
writable: !0
});
- this.#pendingRead = void 0, signal?.once("abort", () => this.destroy()), this.once("connect", () => this.emit("ready"));
+ if (this._handle = this, this._parent = this, this._parentWrap = this, this.#pendingRead = void 0, socket instanceof Socket2)
+ this.#socket = socket;
+ signal?.once("abort", () => this.destroy()), this.once("connect", () => this.emit("ready"));
}
address() {
return {
@@ -190,10 +196,10 @@ var isIPv4 = function(s) {
return this.writableLength;
}
#attach(port, socket) {
- this.remotePort = port, socket.data = this, socket.timeout(this.timeout), socket.ref(), this.#socket = socket, this.connecting = !1, this.emit("connect", this), Socket2.#Drain(socket);
+ this.remotePort = port, socket.data = this, socket.timeout(this.timeout), socket.ref(), this[bunSocketInternal] = socket, this.connecting = !1, this.emit("connect", this), Socket2.#Drain(socket);
}
connect(port, host, connectListener) {
- var path;
+ var path, connection = this.#socket;
if (typeof port === "string") {
if (path = port, port = void 0, typeof host === "function")
connectListener = host, host = void 0;
@@ -207,6 +213,7 @@ var isIPv4 = function(s) {
port,
host,
path,
+ socket,
localAddress,
localPort,
family,
@@ -220,7 +227,8 @@ var isIPv4 = function(s) {
pauseOnConnect,
servername
} = port;
- this.servername = servername;
+ if (this.servername = servername, socket)
+ connection = socket;
}
if (!pauseOnConnect)
this.resume();
@@ -228,36 +236,78 @@ var isIPv4 = function(s) {
const bunTLS = this[bunTlsSymbol];
var tls = void 0;
if (typeof bunTLS === "function") {
- if (tls = bunTLS.call(this, port, host, !0), this._requestCert = !0, this._rejectUnauthorized = rejectUnauthorized, tls)
+ if (tls = bunTLS.call(this, port, host, !0), this._requestCert = !0, this._rejectUnauthorized = rejectUnauthorized, tls) {
if (typeof tls !== "object")
tls = {
rejectUnauthorized,
requestCert: !0
};
- else
- tls.rejectUnauthorized = rejectUnauthorized, tls.requestCert = !0;
+ else if (tls.rejectUnauthorized = rejectUnauthorized, tls.requestCert = !0, !connection && tls.socket)
+ connection = tls.socket;
+ }
+ if (connection) {
+ if (typeof connection !== "object" || !(connection instanceof Socket2) || typeof connection[bunTlsSymbol] === "function")
+ throw new TypeError("socket must be an instance of net.Socket");
+ }
if (this.authorized = !1, this.secureConnecting = !0, this._secureEstablished = !1, this._securePending = !0, connectListener)
this.on("secureConnect", connectListener);
} else if (connectListener)
this.on("connect", connectListener);
- return bunConnect(path ? {
- data: this,
- unix: path,
- socket: Socket2.#Handlers,
- tls
- } : {
- data: this,
- hostname: host || "localhost",
- port,
- socket: Socket2.#Handlers,
- tls
- }), this;
+ if (connection) {
+ const socket2 = connection[bunSocketInternal];
+ if (socket2) {
+ const result = socket2.wrapTLS({
+ data: this,
+ tls,
+ socket: Socket2.#Handlers
+ });
+ if (result) {
+ const [raw, tls2] = result;
+ connection[bunSocketInternal] = raw, raw.timeout(raw.timeout), raw.connecting = !1, this[bunSocketInternal] = tls2, tls2.timeout(tls2.timeout), tls2.connecting = !0, this[bunSocketInternal] = socket2, tls2.open();
+ } else
+ throw this[bunSocketInternal] = null, new Error("Invalid socket");
+ } else
+ connection.once("connect", () => {
+ const socket3 = connection[bunSocketInternal];
+ if (!socket3)
+ return;
+ const result = socket3.wrapTLS({
+ data: this,
+ tls,
+ socket: Socket2.#Handlers
+ });
+ if (result) {
+ const [raw, tls2] = result;
+ connection[bunSocketInternal] = raw, raw.timeout(raw.timeout), raw.connecting = !1, this[bunSocketInternal] = tls2, tls2.timeout(tls2.timeout), tls2.connecting = !0, this[bunSocketInternal] = socket3, tls2.open();
+ } else
+ throw this[bunSocketInternal] = null, new Error("Invalid socket");
+ });
+ } else if (path)
+ bunConnect({
+ data: this,
+ unix: path,
+ socket: Socket2.#Handlers,
+ tls
+ }).catch((error) => {
+ this.emit("error", error);
+ });
+ else
+ bunConnect({
+ data: this,
+ hostname: host || "localhost",
+ port,
+ socket: Socket2.#Handlers,
+ tls
+ }).catch((error) => {
+ this.emit("error", error);
+ });
+ return this;
}
_destroy(err, callback) {
- this.#socket?.end(), callback(err);
+ this[bunSocketInternal]?.end(), callback(err);
}
_final(callback) {
- this.#socket?.end(), callback();
+ this[bunSocketInternal]?.end(), callback();
}
get localAddress() {
return "127.0.0.1";
@@ -266,7 +316,7 @@ var isIPv4 = function(s) {
return "IPv4";
}
get localPort() {
- return this.#socket?.localPort;
+ return this[bunSocketInternal]?.localPort;
}
get pending() {
return this.connecting;
@@ -289,16 +339,16 @@ var isIPv4 = function(s) {
return this.writable ? "writeOnly" : "closed";
}
ref() {
- this.#socket?.ref();
+ this[bunSocketInternal]?.ref();
}
get remoteAddress() {
- return this.#socket?.remoteAddress;
+ return this[bunSocketInternal]?.remoteAddress;
}
get remoteFamily() {
return "IPv4";
}
resetAndDestroy() {
- this.#socket?.end();
+ this[bunSocketInternal]?.end();
}
setKeepAlive(enable = !1, initialDelay = 0) {
return this;
@@ -307,17 +357,17 @@ var isIPv4 = function(s) {
return this;
}
setTimeout(timeout, callback) {
- if (this.#socket?.timeout(timeout), this.timeout = timeout, callback)
+ if (this[bunSocketInternal]?.timeout(timeout), this.timeout = timeout, callback)
this.once("timeout", callback);
return this;
}
unref() {
- this.#socket?.unref();
+ this[bunSocketInternal]?.unref();
}
_write(chunk, encoding, callback) {
- if (typeof chunk == "string" && encoding !== "utf8")
+ if (typeof chunk == "string" && encoding !== "ascii")
chunk = Buffer.from(chunk, encoding);
- var written = this.#socket?.write(chunk);
+ var written = this[bunSocketInternal]?.write(chunk);
if (written == chunk.length)
callback();
else if (this.#writeCallback)
diff --git a/src/js/out/modules/node/tls.js b/src/js/out/modules/node/tls.js
index 4cceadc7f..ca8a13270 100644
--- a/src/js/out/modules/node/tls.js
+++ b/src/js/out/modules/node/tls.js
@@ -1,4 +1,4 @@
-import {isTypedArray} from "node:util/types";
+import {isArrayBufferView, isTypedArray} from "node:util/types";
import net, {Server as NetServer} from "node:net";
var parseCertString = function() {
throwNotImplemented("Not implemented");
@@ -11,18 +11,127 @@ var parseCertString = function() {
return !1;
return !0;
}
+}, unfqdn = function(host2) {
+ return RegExpPrototypeSymbolReplace(/[.]$/, host2, "");
+}, splitHost = function(host2) {
+ return StringPrototypeSplit.call(RegExpPrototypeSymbolReplace(/[A-Z]/g, unfqdn(host2), toLowerCase), ".");
+}, check = function(hostParts, pattern, wildcards) {
+ if (!pattern)
+ return !1;
+ const patternParts = splitHost(pattern);
+ if (hostParts.length !== patternParts.length)
+ return !1;
+ if (ArrayPrototypeIncludes.call(patternParts, ""))
+ return !1;
+ const isBad = (s) => RegExpPrototypeExec.call(/[^\u0021-\u007F]/u, s) !== null;
+ if (ArrayPrototypeSome.call(patternParts, isBad))
+ return !1;
+ for (let i = hostParts.length - 1;i > 0; i -= 1)
+ if (hostParts[i] !== patternParts[i])
+ return !1;
+ const hostSubdomain = hostParts[0], patternSubdomain = patternParts[0], patternSubdomainParts = StringPrototypeSplit.call(patternSubdomain, "*");
+ if (patternSubdomainParts.length === 1 || StringPrototypeIncludes.call(patternSubdomain, "xn--"))
+ return hostSubdomain === patternSubdomain;
+ if (!wildcards)
+ return !1;
+ if (patternSubdomainParts.length > 2)
+ return !1;
+ if (patternParts.length <= 2)
+ return !1;
+ const { 0: prefix, 1: suffix } = patternSubdomainParts;
+ if (prefix.length + suffix.length > hostSubdomain.length)
+ return !1;
+ if (!StringPrototypeStartsWith.call(hostSubdomain, prefix))
+ return !1;
+ if (!StringPrototypeEndsWith.call(hostSubdomain, suffix))
+ return !1;
+ return !0;
+}, splitEscapedAltNames = function(altNames) {
+ const result = [];
+ let currentToken = "", offset = 0;
+ while (offset !== altNames.length) {
+ const nextSep = StringPrototypeIndexOf.call(altNames, ", ", offset), nextQuote = StringPrototypeIndexOf.call(altNames, '"', offset);
+ if (nextQuote !== -1 && (nextSep === -1 || nextQuote < nextSep)) {
+ currentToken += StringPrototypeSubstring.call(altNames, offset, nextQuote);
+ const match = RegExpPrototypeExec.call(jsonStringPattern, StringPrototypeSubstring.call(altNames, nextQuote));
+ if (!match) {
+ let error = new SyntaxError("ERR_TLS_CERT_ALTNAME_FORMAT: Invalid subject alternative name string");
+ throw error.name = ERR_TLS_CERT_ALTNAME_FORMAT, error;
+ }
+ currentToken += JSON.parse(match[0]), offset = nextQuote + match[0].length;
+ } else if (nextSep !== -1)
+ currentToken += StringPrototypeSubstring.call(altNames, offset, nextSep), ArrayPrototypePush.call(result, currentToken), currentToken = "", offset = nextSep + 2;
+ else
+ currentToken += StringPrototypeSubstring.call(altNames, offset), offset = altNames.length;
+ }
+ return ArrayPrototypePush.call(result, currentToken), result;
+}, checkServerIdentity = function(hostname, cert) {
+ const { subject, subjectaltname: altNames } = cert, dnsNames = [], ips = [];
+ if (hostname = "" + hostname, altNames) {
+ const splitAltNames = StringPrototypeIncludes.call(altNames, '"') ? splitEscapedAltNames(altNames) : StringPrototypeSplit.call(altNames, ", ");
+ ArrayPrototypeForEach.call(splitAltNames, (name) => {
+ if (StringPrototypeStartsWith.call(name, "DNS:"))
+ ArrayPrototypePush.call(dnsNames, StringPrototypeSlice.call(name, 4));
+ else if (StringPrototypeStartsWith.call(name, "IP Address:"))
+ ArrayPrototypePush.call(ips, canonicalizeIP(StringPrototypeSlice.call(name, 11)));
+ });
+ }
+ let valid = !1, reason = "Unknown reason";
+ if (hostname = unfqdn(hostname), net.isIP(hostname)) {
+ if (valid = ArrayPrototypeIncludes.call(ips, canonicalizeIP(hostname)), !valid)
+ reason = `IP: ${hostname} is not in the cert's list: ` + ArrayPrototypeJoin.call(ips, ", ");
+ } else if (dnsNames.length > 0 || subject?.CN) {
+ const hostParts = splitHost(hostname), wildcard = (pattern) => check(hostParts, pattern, !0);
+ if (dnsNames.length > 0) {
+ if (valid = ArrayPrototypeSome.call(dnsNames, wildcard), !valid)
+ reason = `Host: ${hostname}. is not in the cert's altnames: ${altNames}`;
+ } else {
+ const cn = subject.CN;
+ if (ArrayIsArray(cn))
+ valid = ArrayPrototypeSome.call(cn, wildcard);
+ else if (cn)
+ valid = wildcard(cn);
+ if (!valid)
+ reason = `Host: ${hostname}. is not cert's CN: ${cn}`;
+ }
+ } else
+ reason = "Cert does not contain a DNS name";
+ if (!valid) {
+ let error = new Error(`ERR_TLS_CERT_ALTNAME_INVALID: Hostname/IP does not match certificate's altnames: ${reason}`);
+ return error.name = "ERR_TLS_CERT_ALTNAME_INVALID", error.reason = reason, error.host = host, error.cert = cert, error;
+ }
}, SecureContext = function(options) {
return new InternalSecureContext(options);
}, createSecureContext = function(options) {
return new SecureContext(options);
-}, createServer = function(options, connectionListener) {
+};
+var createServer = function(options, connectionListener) {
return new Server(options, connectionListener);
}, getCiphers = function() {
return DEFAULT_CIPHERS.split(":");
}, getCurves = function() {
return;
+}, convertProtocols = function(protocols) {
+ const lens = new Array(protocols.length), buff = Buffer.allocUnsafe(ArrayPrototypeReduce.call(protocols, (p, c, i) => {
+ const len = Buffer.byteLength(c);
+ if (len > 255)
+ throw new RangeError("The byte length of the protocol at index " + `${i} exceeds the maximum length.`, "<= 255", len, !0);
+ return lens[i] = len, p + 1 + len;
+ }, 0));
+ let offset = 0;
+ for (let i = 0, c = protocols.length;i < c; i++)
+ buff[offset++] = lens[i], buff.write(protocols[i], offset), offset += lens[i];
+ return buff;
}, convertALPNProtocols = function(protocols, out) {
-}, InternalTCPSocket = net[Symbol.for("::bunternal::")], InternalSecureContext = class SecureContext2 {
+ if (Array.isArray(protocols))
+ out.ALPNProtocols = convertProtocols(protocols);
+ else if (isTypedArray(protocols))
+ out.ALPNProtocols = Buffer.from(protocols);
+ else if (isArrayBufferView(protocols))
+ out.ALPNProtocols = Buffer.from(protocols.buffer.slice(protocols.byteOffset, protocols.byteOffset + protocols.byteLength));
+ else if (Buffer.isBuffer(protocols))
+ out.ALPNProtocols = protocols;
+}, InternalTCPSocket = net[Symbol.for("::bunternal::")], bunSocketInternal = Symbol.for("::bunnetsocketinternal::"), { RegExp, Array, String } = globalThis[Symbol.for("Bun.lazy")]("primordials"), SymbolReplace = Symbol.replace, RegExpPrototypeSymbolReplace = RegExp.prototype[SymbolReplace], RegExpPrototypeExec = RegExp.prototype.exec, StringPrototypeStartsWith = String.prototype.startsWith, StringPrototypeSlice = String.prototype.slice, StringPrototypeIncludes = String.prototype.includes, StringPrototypeSplit = String.prototype.split, StringPrototypeIndexOf = String.prototype.indexOf, StringPrototypeSubstring = String.prototype.substring, StringPrototypeEndsWith = String.prototype.endsWith, ArrayPrototypeIncludes = Array.prototype.includes, ArrayPrototypeJoin = Array.prototype.join, ArrayPrototypeForEach = Array.prototype.forEach, ArrayPrototypePush = Array.prototype.push, ArrayPrototypeSome = Array.prototype.some, ArrayPrototypeReduce = Array.prototype.reduce, jsonStringPattern = /^"(?:[^"\\\u0000-\u001f]|\\(?:["\\/bfnrt]|u[0-9a-fA-F]{4}))*"/, InternalSecureContext = class SecureContext2 {
context;
constructor(options) {
const context = {};
@@ -73,8 +182,17 @@ var parseCertString = function() {
});
}(class TLSSocket2 extends InternalTCPSocket {
#secureContext;
- constructor(options) {
- super(options);
+ ALPNProtocols;
+ #socket;
+ constructor(socket, options) {
+ super(socket instanceof InternalTCPSocket ? options : options || socket);
+ if (options = options || socket || {}, typeof options === "object") {
+ const { ALPNProtocols } = options;
+ if (ALPNProtocols)
+ convertALPNProtocols(ALPNProtocols, this);
+ if (socket instanceof InternalTCPSocket)
+ this.#socket = socket;
+ }
this.#secureContext = options.secureContext || createSecureContext(options), this.authorized = !1, this.secureConnecting = !0, this._secureEstablished = !1, this._securePending = !0;
}
_secureEstablished = !1;
@@ -84,19 +202,24 @@ var parseCertString = function() {
secureConnecting = !1;
_SNICallback;
servername;
- alpnProtocol;
authorized = !1;
authorizationError;
encrypted = !0;
- exportKeyingMaterial() {
- throw Error("Not implented in Bun yet");
+ _start() {
}
- setMaxSendFragment() {
+ exportKeyingMaterial(length, label, context) {
throw Error("Not implented in Bun yet");
}
- setServername() {
+ setMaxSendFragment(size) {
throw Error("Not implented in Bun yet");
}
+ setServername(name) {
+ if (this.isServer) {
+ let error = new Error("ERR_TLS_SNI_FROM_SERVER: Cannot issue SNI from a TLS server-side socket");
+ throw error.name = "ERR_TLS_SNI_FROM_SERVER", error;
+ }
+ this.servername = name, this[bunSocketInternal]?.setServername(name);
+ }
setSession() {
throw Error("Not implented in Bun yet");
}
@@ -112,14 +235,16 @@ var parseCertString = function() {
getX509Certificate() {
throw Error("Not implented in Bun yet");
}
- [buntls](port, host) {
- var { servername } = this;
- if (servername)
- return {
- serverName: typeof servername === "string" ? servername : host,
- ...this.#secureContext
- };
- return !0;
+ get alpnProtocol() {
+ return this[bunSocketInternal]?.alpnProtocol;
+ }
+ [buntls](port, host2) {
+ return {
+ socket: this.#socket,
+ ALPNProtocols: this.ALPNProtocols,
+ serverName: this.servername || host2 || "localhost",
+ ...this.#secureContext
+ };
}
});
@@ -132,9 +257,11 @@ class Server extends NetServer {
_rejectUnauthorized;
_requestCert;
servername;
+ ALPNProtocols;
+ #checkServerIdentity;
constructor(options, secureConnectionListener) {
super(options, secureConnectionListener);
- this.setSecureContext(options);
+ this.#checkServerIdentity = options?.checkServerIdentity || checkServerIdentity, this.setSecureContext(options);
}
emit(event, args) {
if (super.emit(event, args), event === "connection")
@@ -146,6 +273,9 @@ class Server extends NetServer {
if (options instanceof InternalSecureContext)
options = options.context;
if (options) {
+ const { ALPNProtocols } = options;
+ if (ALPNProtocols)
+ convertALPNProtocols(ALPNProtocols, this);
let key = options.key;
if (key) {
if (!isValidTLSArray(key))
@@ -194,26 +324,33 @@ class Server extends NetServer {
setTicketKeys() {
throw Error("Not implented in Bun yet");
}
- [buntls](port, host, isClient) {
+ [buntls](port, host2, isClient) {
return [
{
- serverName: this.servername || host || "localhost",
+ serverName: this.servername || host2 || "localhost",
key: this.key,
cert: this.cert,
ca: this.ca,
passphrase: this.passphrase,
secureOptions: this.secureOptions,
rejectUnauthorized: isClient ? !1 : this._rejectUnauthorized,
- requestCert: isClient ? !1 : this._requestCert
+ requestCert: isClient ? !1 : this._requestCert,
+ ALPNProtocols: this.ALPNProtocols,
+ checkServerIdentity: this.#checkServerIdentity
},
SocketClass
];
}
}
-var CLIENT_RENEG_LIMIT = 3, CLIENT_RENEG_WINDOW = 600, DEFAULT_ECDH_CURVE = "auto", DEFAULT_CIPHERS = "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256", DEFAULT_MIN_VERSION = "TLSv1.2", DEFAULT_MAX_VERSION = "TLSv1.3", createConnection = (port, host, connectListener) => {
- if (typeof port === "object")
- return new TLSSocket(port).connect(port, host, connectListener);
- return new TLSSocket().connect(port, host, connectListener);
+var CLIENT_RENEG_LIMIT = 3, CLIENT_RENEG_WINDOW = 600, DEFAULT_ECDH_CURVE = "auto", DEFAULT_CIPHERS = "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256", DEFAULT_MIN_VERSION = "TLSv1.2", DEFAULT_MAX_VERSION = "TLSv1.3", createConnection = (port, host2, connectListener) => {
+ if (typeof port === "object") {
+ port.checkServerIdentity;
+ const { ALPNProtocols } = port;
+ if (ALPNProtocols)
+ convertALPNProtocols(ALPNProtocols, port);
+ return new TLSSocket(port).connect(port, host2, connectListener);
+ }
+ return new TLSSocket().connect(port, host2, connectListener);
}, connect = createConnection, exports = {
[Symbol.for("CommonJS")]: 0,
CLIENT_RENEG_LIMIT,
@@ -244,6 +381,7 @@ export {
createConnection,
convertALPNProtocols,
connect,
+ checkServerIdentity,
TLSSocket,
Server,
SecureContext,