Skip to content
Bidirectional networking over RSA and AES.
TypeScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
.gitignore
README.md
package-lock.json
package.json
tsconfig.json

README.md

TCP

This is a utility package which helps simplify secure communication between a client and a server over TCP. It transmits values over channels, similar to event emitters, and offers a connection guard on the server.

Overview

When a connection is first established, the client sends an identity (such as a username) to the server. The server's guard will receive the connection and identity, and may accept or reject the connection.

Approved connections become active and can actively transmit values back and forth between the client and server. These transactions are automatically encrypted with RSA public keys which are exchanged when the connection is accepted.

Each transaction is also encrypted with AES256. For this to work, both the server and client must already know the password. The server's guard can set a different password for each client, but a connection will not establish unless both sides agree on a password.

Server

The server binds to a port and uses the connection event as a guard. You can accept incoming connections by calling connection.accept() with a 32-character password for AES256 encryption.

const server = new Server(12345);

server.on('connection', async connection => {
    let ip = connection.getAddress();
    let identity = connection.getIdentity();

    if (identity == 'baileyherbert') {
        await connection.accept('00a3ac30ef0b23da56f09fc5b68f40fa');
        await connection.send('notification', 'Welcome back!');
    }
});

server.start();

Client

The client connects directly to the server given the port, host, and an identity string. When starting the client with start(), a 32-character password must be supplied which must match the password provided by the server with accept().

const client = new Client(12345, '127.0.0.1', 'baileyherbert');

client.start('00a3ac30ef0b23da56f09fc5b68f40fa').then(async () => {
    client.listen('notification', message => {
        console.log('The server said:', message);
    });

    await client.send('event', 'signed_in');
});

Data

Many different types of data can be sent. They are encoded to JSON while transmitting over encryption, and are decoded before triggering listeners. For instance, all of the following are supported:

client.send('channel', true);
client.send('channel', 'some text');
client.send('channel', 125.3);
client.send('channel', { name: 'John Doe' });

Buffering

The internal socket is configured to send data without delay on both sides of a connection. However, Node will sometimes emit data in chunks. To address this, the package implements a newline buffer. It is important to note that this is managed internally, and you do not need to manually append a new line character to the end of your data payloads.

Calls

This package supports a call method which works similarly to send, but gives us the return value of the remote function which listened to it.

// Server can return immediately or through a promise:
connection.listen('updateProfile', changes => {
    return { id: 42 };
    return new Promise(resolve => {
        resolve({ id: 42 });
    });
});

// The client gets it back when using call():
client.call('updateProfile', { name: 'John Smith' }).then(profile => {
    console.log('Profile updated for user', profile.id); // 42
});

TypeScript

When working with TypeScript, you can use generics to constrain data types.

client.send<boolean>('channel', true); // valid
client.send<boolean>('channel', 'string'); // error

client.listen<{ name: string }>('channel', info => {
    let { name } = info; // valid, recognizes as string
    let { age } = info; // error, age not found
});

client.call<boolean>('channel').then(bool => ...);
client.call<boolean, string>('channel', str).then(bool => ...);
You can’t perform that action at this time.