mirror of
https://github.com/denoland/deno.git
synced 2024-11-29 16:30:56 -05:00
fix(node): implement TLSSocket._start (#20120)
Closes https://github.com/denoland/deno/issues/19983 Closes https://github.com/denoland/deno/issues/18303 Closes https://github.com/denoland/deno/issues/16681 Closes https://github.com/denoland/deno/issues/19978
This commit is contained in:
parent
3615afa217
commit
dd3d0f6d0b
3 changed files with 62 additions and 3 deletions
|
@ -56,6 +56,38 @@ Connection: close
|
||||||
await serve;
|
await serve;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// https://github.com/denoland/deno/pull/20120
|
||||||
|
Deno.test("tls.connect mid-read tcp->tls upgrade", async () => {
|
||||||
|
const ctl = new AbortController();
|
||||||
|
const serve = serveTls(() => new Response("hello"), {
|
||||||
|
port: 8443,
|
||||||
|
key,
|
||||||
|
cert,
|
||||||
|
signal: ctl.signal,
|
||||||
|
});
|
||||||
|
|
||||||
|
await delay(200);
|
||||||
|
|
||||||
|
const conn = tls.connect({
|
||||||
|
host: "localhost",
|
||||||
|
port: 8443,
|
||||||
|
secureContext: {
|
||||||
|
ca: rootCaCert,
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
|
} as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
conn.setEncoding("utf8");
|
||||||
|
conn.write(`GET / HTTP/1.1\nHost: www.google.com\n\n`);
|
||||||
|
|
||||||
|
conn.on("data", (_) => {
|
||||||
|
conn.destroy();
|
||||||
|
ctl.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
await serve;
|
||||||
|
});
|
||||||
|
|
||||||
Deno.test("tls.createServer creates a TLS server", async () => {
|
Deno.test("tls.createServer creates a TLS server", async () => {
|
||||||
const p = deferred();
|
const p = deferred();
|
||||||
const server = tls.createServer(
|
const server = tls.createServer(
|
||||||
|
|
|
@ -26,6 +26,11 @@ import {
|
||||||
import { EventEmitter } from "node:events";
|
import { EventEmitter } from "node:events";
|
||||||
import { kEmptyObject } from "ext:deno_node/internal/util.mjs";
|
import { kEmptyObject } from "ext:deno_node/internal/util.mjs";
|
||||||
import { nextTick } from "ext:deno_node/_next_tick.ts";
|
import { nextTick } from "ext:deno_node/_next_tick.ts";
|
||||||
|
import { kHandle } from "ext:deno_node/internal/stream_base_commons.ts";
|
||||||
|
import {
|
||||||
|
isAnyArrayBuffer,
|
||||||
|
isArrayBufferView,
|
||||||
|
} from "ext:deno_node/internal/util/types.ts";
|
||||||
|
|
||||||
const kConnectOptions = Symbol("connect-options");
|
const kConnectOptions = Symbol("connect-options");
|
||||||
const kIsVerified = Symbol("verified");
|
const kIsVerified = Symbol("verified");
|
||||||
|
@ -71,7 +76,11 @@ export class TLSSocket extends net.Socket {
|
||||||
[kPendingSession]: any;
|
[kPendingSession]: any;
|
||||||
[kConnectOptions]: any;
|
[kConnectOptions]: any;
|
||||||
ssl: any;
|
ssl: any;
|
||||||
_start: any;
|
|
||||||
|
_start() {
|
||||||
|
this[kHandle].afterConnect();
|
||||||
|
}
|
||||||
|
|
||||||
constructor(socket: any, opts: any = kEmptyObject) {
|
constructor(socket: any, opts: any = kEmptyObject) {
|
||||||
const tlsOptions = { ...opts };
|
const tlsOptions = { ...opts };
|
||||||
|
|
||||||
|
@ -84,6 +93,9 @@ export class TLSSocket extends net.Socket {
|
||||||
|
|
||||||
let caCerts = tlsOptions?.secureContext?.ca;
|
let caCerts = tlsOptions?.secureContext?.ca;
|
||||||
if (typeof caCerts === "string") caCerts = [caCerts];
|
if (typeof caCerts === "string") caCerts = [caCerts];
|
||||||
|
else if (isArrayBufferView(caCerts) || isAnyArrayBuffer(caCerts)) {
|
||||||
|
caCerts = [new TextDecoder().decode(caCerts)];
|
||||||
|
}
|
||||||
tlsOptions.caCerts = caCerts;
|
tlsOptions.caCerts = caCerts;
|
||||||
|
|
||||||
super({
|
super({
|
||||||
|
@ -139,9 +151,9 @@ export class TLSSocket extends net.Socket {
|
||||||
handle.afterConnect = async (req: any, status: number) => {
|
handle.afterConnect = async (req: any, status: number) => {
|
||||||
try {
|
try {
|
||||||
const conn = await Deno.startTls(handle[kStreamBaseField], options);
|
const conn = await Deno.startTls(handle[kStreamBaseField], options);
|
||||||
|
handle[kStreamBaseField] = conn;
|
||||||
tlssock.emit("secure");
|
tlssock.emit("secure");
|
||||||
tlssock.removeListener("end", onConnectEnd);
|
tlssock.removeListener("end", onConnectEnd);
|
||||||
handle[kStreamBaseField] = conn;
|
|
||||||
} catch {
|
} catch {
|
||||||
// TODO(kt3k): Handle this
|
// TODO(kt3k): Handle this
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,9 +314,16 @@ export class LibuvStreamWrap extends HandleWrap {
|
||||||
let buf = BUF;
|
let buf = BUF;
|
||||||
|
|
||||||
let nread: number | null;
|
let nread: number | null;
|
||||||
|
const ridBefore = this[kStreamBaseField]!.rid;
|
||||||
try {
|
try {
|
||||||
nread = await this[kStreamBaseField]!.read(buf);
|
nread = await this[kStreamBaseField]!.read(buf);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Try to read again if the underlying stream resource
|
||||||
|
// changed. This can happen during TLS upgrades (eg. STARTTLS)
|
||||||
|
if (ridBefore != this[kStreamBaseField]!.rid) {
|
||||||
|
return this.#read();
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
e instanceof Deno.errors.Interrupted ||
|
e instanceof Deno.errors.Interrupted ||
|
||||||
e instanceof Deno.errors.BadResource
|
e instanceof Deno.errors.BadResource
|
||||||
|
@ -365,15 +372,23 @@ export class LibuvStreamWrap extends HandleWrap {
|
||||||
async #write(req: WriteWrap<LibuvStreamWrap>, data: Uint8Array) {
|
async #write(req: WriteWrap<LibuvStreamWrap>, data: Uint8Array) {
|
||||||
const { byteLength } = data;
|
const { byteLength } = data;
|
||||||
|
|
||||||
|
const ridBefore = this[kStreamBaseField]!.rid;
|
||||||
|
|
||||||
|
let nwritten = 0;
|
||||||
try {
|
try {
|
||||||
// TODO(crowlKats): duplicate from runtime/js/13_buffer.js
|
// TODO(crowlKats): duplicate from runtime/js/13_buffer.js
|
||||||
let nwritten = 0;
|
|
||||||
while (nwritten < data.length) {
|
while (nwritten < data.length) {
|
||||||
nwritten += await this[kStreamBaseField]!.write(
|
nwritten += await this[kStreamBaseField]!.write(
|
||||||
data.subarray(nwritten),
|
data.subarray(nwritten),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Try to read again if the underlying stream resource
|
||||||
|
// changed. This can happen during TLS upgrades (eg. STARTTLS)
|
||||||
|
if (ridBefore != this[kStreamBaseField]!.rid) {
|
||||||
|
return this.#write(req, data.subarray(nwritten));
|
||||||
|
}
|
||||||
|
|
||||||
let status: number;
|
let status: number;
|
||||||
|
|
||||||
// TODO(cmorten): map err to status codes
|
// TODO(cmorten): map err to status codes
|
||||||
|
|
Loading…
Reference in a new issue