Skip to content

Add documentation #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# NUClearNet.js

[![Node.js CI](https://github.com/Fastcode/NUClearNet.js/actions/workflows/node.js.yml/badge.svg)](https://github.com/Fastcode/NUClearNet.js/actions/workflows/node.js.yml)

Node.js module for interacting with the [NUClear](https://github.com/Fastcode/NUClear) network.

## Installation

The package contains a native module, so you'll need a working C++ compiler on your system to install and build it.

```
npm install nuclearnet.js --save
```

## Usage

The following example show a typical usage pattern of creating a network instance, listening for join, leave, and packet events, and sending data.

```js
const { NUClearNet } = require('nuclearnet.js');

// Create a network instance
const net = new NUClearNet();

// Set a join listener to be notified when peers join the network.
// This should be done before calling `connect()` for the first time, to get join events
// from peers that are already on the network.
net.on('nuclear_join', function (peer) {
console.log(`peer ${peer.name} has joined`);
});

// Set a leave listener to be notified when peers leave the network
net.on('nuclear_leave', function (peer) {
console.log(`peer ${peer.name} has left`);
});

// Listen for all incoming packets
net.on('nuclear_packet', function (packet) {
const packetType = packet.type !== undefined ? packet.type : 'unknown type';
console.log(`got a packet (${packetType}) of length ${packet.payload.length} from peer ${packet.peer.name}`);
});

// Listen for packets of a specific type
net.on('packet_type_a', function (packet) {
console.log(`got a packet (packet_type_a) of length ${packet.payload.length} from peer ${packet.peer.name}`);

// Send a response to the peer
net.send({
target: packet.peer.name,
reliable: true,
type: 'packet_type_b',
payload: Buffer.from('hello there!'),
});
});

// Connect to the network using the peer name "My Name"
net.connect({ name: 'My Name' });
```

## API

See [`index.d.ts`](./index.d.ts) for types and API details.
212 changes: 128 additions & 84 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,119 +21,163 @@
* NUClearNet options for connecting to the network
*/
export interface NUClearNetOptions {
/// The name of this node on the NUClearNetwork
name: string
/// The announce address for this network defaults to 239.226.152.162
address?: string
/// The announce port for this network defaults to 7447
port?: number
/// The MTU of the network. Used for splitting packets optimally
mtu?: number
/** The name of this node on the NUClearNetwork */
name: string;

/** The announce address for this network. Defaults to `239.226.152.162`. */
address?: string;

/** The announce port for this network. Defaults to `7447`. */
port?: number;

/** The MTU of the network. Used for splitting packets optimally. */
mtu?: number;
}

/**
* Data provided for sending information on the network
*/
export interface NUClearNetSend {
/// The type of the message to send, either as a string that will be hashed or as a 64 bit hash directly
type: string|Buffer
/// The data to send
payload: Buffer
/// The target to send the packet to, undefined means send to everyone on the network
target?: string
/// If the packet should be sent using a more reliable protocol which handles retransmissions
reliable?: boolean
/**
* The type of the message to send: either a string that will be hashed,
* or a Buffer with the 64 bit hash.
*/
type: string | Buffer;

/** The data to send */
payload: Buffer;

/**
* The target to send the packet to. If `undefined`, the packet will be sent
* to everyone on the network.
*/
target?: string;

/**
* If `true`, the packet should be sent using a reliable protocol
* which handles retransmissions.
*/
reliable?: boolean;
}

/**
* Information for a peer on the NUClear network
* Information about a peer on the NUClear network
*/
export interface NUClearNetPeer {
/// The name the peer has on the network. See NUClearNetOptions.name
name: string
/// The IP address of the peer either as dotted decimal for IPv4 or an IPv6 string
address: string
/// The port the peer has connected on.
/// This will be an ephemeral port and the combination of address+port will be unique for a peer
port: number
/** The name the peer has on the network. See `NUClearNetOptions.name` */
name: string;

/** The IP address of the peer: either a dotted decimal IPv4 string, or an IPv6 string. */
address: string;

/**
* The port the peer has connected on. This will be an ephemeral port.
* The combination of `address` + `port` will be unique for a peer.
*/
port: number;
}

/**
* A data packet that is received by the NUClear network
* A data packet that received on the NUClear network
*/
export interface NUClearNetPacket {
/// The peer the packet was sent from
peer: NUClearNetPeer
/// The hashcode of the packets type
hash: Buffer
/// The bytes that were sent from the peer
payload: Buffer
/// If the peer sent this as a reliable transmission (see NUClearNetSend.reliable)
reliable: boolean
/** The peer the packet was sent from */
peer: NUClearNetPeer;

/** The hash code of the packet's type */
hash: Buffer;

/** The data that was sent from the peer */
payload: Buffer;

/**
* Will be set to `true`, if the peer sent the packet with reliable transmission
* (see `NUClearNetSend.reliable`).
*/
reliable: boolean;
}

/**
* A packet that will be received using on('message.type') will always have a known string type
* It will be the same string as provided in the on statement
* A packet that is received using `on('message.type')` will always have a known string type:
* the same string that was provided in the on statement.
*/
export interface NUClearNetTypedPacket extends NUClearNetPacket {
/// The type that was provided in the on statement for this packet
type: string
/** The type that was provided in the on statement for this packet */
type: string;
}

/**
* When using on('nuclear_packet') the type as a string may or may not be known depending on if another
* user has requested this type.
* When using `on('nuclear_packet')` the type as a string may or may not be known depending on
* whether another user has requested the same type. This interface represents that type of packet.
*/
export interface NUClearNetMaybeTypedPacket extends NUClearNetPacket {
/// The type that was provided in an on statement, or undefined if nobody has executed an on statement for this type
type: string|undefined
/**
* The type that was provided in an on statement, or `undefined` if nobody has executed
* an on statement for this type.
*/
type: string | undefined;
}

/**
* Create a new NUClearNet instance
* Must be connected before it will provide data however you should set your join and leave callbacks before calling
* connect.
* If connect is called first you will not receive the join events from already connected peers.
* Represents a NUClearNet network client.
*
* Usage notes:
* - Before it will provide data, the instance must be connected first via `.connect()`.
* - Join and leave callbacks should be set before calling `.connect()`. If not, join
* events from already connected peers will not be received.
* - After calling `.destroy()`, the instance should not be used again.
*/
export declare class NUClearNet {
/// Stores the `connect()` options. Is an empty object until `connect()` is called.
options: Partial<NUClearNetOptions>;

public constructor()

/// Will fire when a peer joins or leaves the network.
public on(event: 'nuclear_join'|'nuclear_leave', callback: (peer: NUClearNetPeer) => void): this

/// Will fire when NUClearNet receives any packet
public on(event: 'nuclear_packet', callback: (packet: NUClearNetMaybeTypedPacket) => void): this

/// Will fire when the requested packet is received
public on(event: string, callback: (packet: NUClearNetTypedPacket) => void): this

/// Hash the provided string using the hashing method of NUClearNet.
/// These hashes will be identical to those used by NUClearNet
public hash(data: string): Buffer

/// Stop listening for a type
/// Note that if this is the last listener for a type, the type will revert to being an undefined type
/// for NUClearNetMaybeTypedPacket
public removeListener(event: string, listener: Function): this

/// Connect to the NUClearNetwork
/// If this function is called multiple times
/// it will disconnect from the previous network and reconnect to a new one
public connect(options: NUClearNetOptions): void

/// Disconnect from the NUClearNetwork
/// Does not disconnect listeners and reconnecting will resume events
public disconnect(): void

/// Disconnect and destroy this NUClearNetwork instance, clearing all listeners
/// Attempting to use this instance after calling destroy() will throw an error.
public destroy(): void

/// Send the packet over the NUClearNetwork
/// This function will throw an error if the network is not connected
public send(options: NUClearNetSend): void
/** Stores the `connect()` options. Is an empty object until `connect()` is called. */
options: Partial<NUClearNetOptions>;

/** Create a new NUClearNet instance. */
public constructor();

/** Emitted when a peer joins or leaves the network. */
public on(event: 'nuclear_join' | 'nuclear_leave', callback: (peer: NUClearNetPeer) => void): this;

/** Emitted when NUClearNet receives any packet */
public on(event: 'nuclear_packet', callback: (packet: NUClearNetMaybeTypedPacket) => void): this;

/** Emitted when the given packet is received */
public on(event: string, callback: (packet: NUClearNetTypedPacket) => void): this;

/**
* Hash the provided string using the NUClearNet hashing method.
* These hashes will be identical to those used by NUClear
*/
public hash(data: string): Buffer;

/**
* Stop listening for the given type.
* Note that after removing the last listener for a type, the type will revert to
* being an undefined type for `NUClearNetMaybeTypedPacket`.
*/
public removeListener(event: string, listener: Function): this;

/**
* Connect this instance to the NUclear network.
* Subsequent calls to this function will disconnect from the previous network and
* reconnect to a new one.
*/
public connect(options: NUClearNetOptions): void;

/**
* Disconnect this instance from the NUClear network.
* Does not remove event listeners, therefore reconnecting will resume events.
*/
public disconnect(): void;

/**
* Disconnect and destroy this NUClearNetwork instance, clearing all event listeners.
* Attempting to use this instance after calling `destroy()` will throw an error.
*/
public destroy(): void;

/**
* Send the given packet over the NUClear network.
* Will throw if the network is not connected.
*/
public send(options: NUClearNetSend): void;
}
2 changes: 1 addition & 1 deletion tests/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ test('NUClearNet.send() throws if used before connect()', () => {
const net = new NUClearNet();

assert.throws(() => {
net.send('nuclearnet');
net.send({});
}, /The network is not currently connected/);

net.destroy();
Expand Down