Skip to content

Commit

Permalink
src: add opened promise
Browse files Browse the repository at this point in the history
  • Loading branch information
flakey5 committed Oct 3, 2023
1 parent 1e862db commit 0791af0
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 2 deletions.
33 changes: 32 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import net from 'node:net';
import tls from 'node:tls';
import { Duplex } from 'node:stream';
import type { ReadableStream, WritableStream } from 'node:stream/web';
import type { SocketAddress, SocketOptions } from './types';
import type { SocketAddress, SocketInfo, SocketOptions } from './types';
import { isSocketAddress } from './is-socket-address';

export function connect(
Expand All @@ -23,11 +23,15 @@ export function connect(
export class Socket {
readable: ReadableStream<unknown>;
writable: WritableStream<unknown>;
opened: Promise<SocketInfo>;
closed: Promise<void>;

private socket: net.Socket | tls.TLSSocket;
private allowHalfOpen: boolean;
private secureTransport: SocketOptions['secureTransport'];
private openedIsResolved: boolean;
private openedResolve!: (info: SocketInfo) => void;
private openedReject!: (reason?: unknown) => void;
private closedResolve!: () => void;
private closedReject!: (reason?: unknown) => void;
private startTlsCalled = false;
Expand All @@ -39,6 +43,19 @@ export class Socket {
this.secureTransport = options?.secureTransport ?? 'off';
this.allowHalfOpen = options?.allowHalfOpen ?? true;

this.openedIsResolved = false;
this.opened = new Promise((resolve, reject) => {
this.openedResolve = (info): void => {
this.openedIsResolved = true;
resolve(info);
};
this.openedReject = (...args): void => {
this.openedIsResolved = true;
// eslint-disable-next-line prefer-promise-reject-errors -- ESLint gets this wrong as we are completely forwarding the arguments to reject.
reject(...args);
};
});

this.closed = new Promise((resolve, reject) => {
this.closedResolve = (...args): void => {
resolve(...args);
Expand All @@ -64,13 +81,27 @@ export class Socket {
this.socket = new tls.TLSSocket(addressOrSocket);
}

this.socket.on(
this.socket instanceof tls.TLSSocket ? 'secureConnect' : 'connect',
() => {
this.openedResolve({
remoteAddress: this.socket.remoteAddress,
localAddress: this.socket.localAddress,
});
},
);

this.socket.on('close', (hadError) => {
if (!hadError) {
this.closedResolve();
}
});

this.socket.on('error', (err) => {
if (!this.openedIsResolved) {
this.openedReject(err);
}

if (err instanceof Error) {
this.closedReject(new SocketError(err.message));
} else {
Expand Down
5 changes: 5 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ export interface SocketAddress {
/** The port number to connect to. Example: `5432`. */
port: number;
}

export interface SocketInfo {
remoteAddress?: string;
localAddress?: string;
}
4 changes: 3 additions & 1 deletion test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
void tap.test(
'Socket connected to tcp server with secureTransport: off',
async (t) => {
t.plan(6);
t.plan(7);
let connectCount = 0;
const message = 'abcde\r\n';

Expand All @@ -38,6 +38,8 @@ void tap.test(
'should pipe message',
);

await t.resolveMatch(socket.opened, { localAddress: '::1' });

const close = socket.close();
t.equal(
socket.closed,
Expand Down
1 change: 1 addition & 0 deletions test/tls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ void tap.test('Socket `connect` with TLS', (t) => {
});
const address = await listenAndGetSocketAddress(server);
const socket = connect(address, { secureTransport: 'on' });
await socket.opened;
const result = await writeAndReadSocket(socket, message);
t.equal(connectCount, 2, 'should connect two times');
t.equal(result, message, 'should pipe message');
Expand Down

0 comments on commit 0791af0

Please sign in to comment.