Skip to content

Commit fe42cb5

Browse files
committed
Make TLS reset event tests reliable with modern conn reset API
1 parent 05db347 commit fe42cb5

File tree

2 files changed

+32
-19
lines changed

2 files changed

+32
-19
lines changed

test/integration/subscriptions/tls-error-events.spec.ts

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as _ from 'lodash';
22
import HttpsProxyAgent = require('https-proxy-agent');
3-
import * as semver from 'semver';
43

54
import {
65
getLocal,
@@ -16,7 +15,6 @@ import {
1615
delay,
1716
openRawSocket,
1817
openRawTlsSocket,
19-
writeAndReset,
2018
watchForEvent,
2119
http2DirectRequest
2220
} from "../../test-utils";
@@ -149,41 +147,63 @@ describe("TLS error subscriptions", () => {
149147
await expectNoClientErrors();
150148
});
151149

152-
it("should not be sent for requests from TLS clients that reset later in the connection", async function () {
153-
this.retries(3); // Can be slightly unstable, due to the race for RESET
150+
it("should be sent for requests from TLS clients that reset directly after handshake", async function () {
151+
const events: any[] = [];
152+
await goodServer.on('tls-client-error', () => events.push('tls-client-error'));
153+
await goodServer.on('client-error', () => events.push('client-error'));
154+
155+
const tcpSocket = await openRawSocket(goodServer)
156+
await openRawTlsSocket(tcpSocket);
157+
tcpSocket.resetAndDestroy();
158+
159+
await delay(50);
154160

161+
// We see a TLS error (reset like this is a common form of cert rejection) but no client error
162+
// (no HTTP request has even been attempted):
163+
expect(events).to.deep.equal(['tls-client-error']);
164+
});
165+
166+
it("should not be sent for requests from TLS clients that reset later in the connection", async function () {
155167
let seenTlsErrorPromise = getDeferred<TlsHandshakeFailure>();
156168
await goodServer.on('tls-client-error', (r) => seenTlsErrorPromise.resolve(r));
157169

158170
let seenClientErrorPromise = getDeferred<ClientError>();
159171
await goodServer.on('client-error', (e) => seenClientErrorPromise.resolve(e));
160172

161-
const tlsSocket = await openRawTlsSocket(goodServer);
162-
writeAndReset(tlsSocket, "GET / HTTP/1.1\r\n\r\n");
173+
const tcpSocket = await openRawSocket(goodServer)
174+
const tlsSocket = await openRawTlsSocket(tcpSocket);
175+
tlsSocket.write("GET / HTTP/1.1\r\nHost: hello.world.invalid\r\n"); // Incomplete HTTP request
176+
177+
// Kill the underlying socket before the request head completes (but after some content is sent):
178+
setTimeout(() => {
179+
tcpSocket.resetAndDestroy()
180+
}, 10);
163181

164182
const seenTlsError = await Promise.race([
165-
delay(100).then(() => false),
183+
delay(50).then(() => false),
166184
seenTlsErrorPromise
167185
]);
168-
expect(seenTlsError).to.equal(false);
186+
169187

170188
// No TLS error, but we do expect a client reset error:
189+
expect(seenTlsError).to.equal(false);
171190
expect((await seenClientErrorPromise).errorCode).to.equal('ECONNRESET');
172191
});
173192

174193
it("should not be sent for requests from non-TLS clients that reset before sending anything", async () => {
175194
let seenTlsErrorPromise = getDeferred<TlsHandshakeFailure>();
176195
await goodServer.on('tls-client-error', (r) => seenTlsErrorPromise.resolve(r));
177196

178-
const tlsSocket = await openRawSocket(goodServer);
179-
writeAndReset(tlsSocket, ""); // Send nothing, just connect & RESET
197+
const rawSocket = await openRawSocket(goodServer);
198+
rawSocket.resetAndDestroy(); // Immediate reset without sending any data
180199

181200
const seenTlsError = await Promise.race([
182-
delay(100).then(() => false),
201+
delay(50).then(() => false),
183202
seenTlsErrorPromise
184203
]);
185-
expect(seenTlsError).to.equal(false);
186204

205+
// No TLS error, no client reset error:
206+
expect(seenTlsError).to.equal(false);
187207
await expectNoClientErrors();
188208
});
189209
});

test/test-utils.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,6 @@ export async function openSocksSocket(
225225
return socksConn.socket;
226226
}
227227

228-
// Write a message to a socket that will trigger a respnse, but kill the socket
229-
// before the response is received, so a real response triggers a reset.
230-
export async function writeAndReset(socket: net.Socket, content: string) {
231-
socket.write(content);
232-
setTimeout(() => socket.destroy(), 0);
233-
}
234-
235228
export function makeAbortableRequest(server: Mockttp, path: string) {
236229
if (isNode) {
237230
let req = http.request({

0 commit comments

Comments
 (0)