A server and socket for vertex.

Usage no npm install needed!

<script type="module">
  import vertexTransport from '';


using node ^6.0.0

npm Build Status Coverage Status


npm install vertex-transport —save

A server and socket for vertex.

Uses ws underneath. They suggest installing binary addons for speed: bufferutil and utf-8-validate

Quick Start

const {VertexServer, VertexSocket} = require('vertex-transport');

Start the server


  .then(server => {})
  .catch(error => {});

Connect a client


  .then(socket => {})
  .catch(error => {});

// on the server
server.on('connection', socket => {});


In addition to regular socket errors.

const {
} = require('vertex-transport').errors;

Emitted in the socket error event handler.

vertexSocket.on('error', error => {});

Passed into the send() rejection handler.

vertexSocket.send({data: 1}).catch(error => {})


  • Emitted on the server-side socket (usually when an attacker is probing the server port).
  • Emitted on the client-side socket in the unlikely event that it sends or recieves unparsable data to the server.

The socket is immediately/aleady closed in both cases.


  • Emitted on the server-side socket when a new connection fails to send any data within config.connectIdleTimeout. Once the first frame is received no futher idle timeouts are applied.

The socket is immediately closed.


  • Passed in the send() promise rejection when the socket is already closed or when it closes while awaiting ACKs for already sent messages.


  • Passed in the send(data, optionalTimeout) promise rejection if an ACK or NAK is not received from the server in the specified time.


  • Emitted if an ACK or NAK arrives after the timeout that caused the VertexSocketTimeoutError.


  • Passed in the send() promise rejection when the remote side assembled a response (ACK+data) that could not be encoded. This will usually only be encountered while developing.

Server Details


// defaults displayed
  host: '',
  port: 65535,
  connectIdleTimeout: 20 * 1000 // 20 seconds
}).then(server => {})
config.[host, port]

Specifiy ip or device, and port to listen on.


If connecting clients send no data within this time they are disconnected.


  • no arguments

Get the servers listening address

returns: Address.

  • no arguments

Stops listening and closes all sockets.

returns: Promise


Extends node events.EventEmitter


event 'error'
  • emits: Error

This is relaying error events from the underlying ws/http server.

event 'listening'

Emitted when the server reaches listening. Since this occurs before the listen() promise is resolved it is inaccessible.

event 'connection'
  • emits: VertexSocket

Emitted when a socket attaches.

Client Details


// defaults displayed
  host: '',
  port: 65535
}).then(socket => {})
config.[host, port]

2 connect 2.


  • no arguments

Get the address at the local side of the socket.

returns: Address.

  • no arguments

Get the address at the remote side of the socket.

returns: Address.

socket.close(code, message)

Closes the socket. The remote side's 'close' event handler will receive the code and message.

returns: undefined

  • error: Optional Error

Close the socket immediately without sending code and message. If provided the Error will be emitted to the local 'error' event handler.

returns: undefined

  • no arguments

Pauses the socket. No data will arrive or depart while paused. Sent data will be bufferred.

returns: undefined

  • no arguments

Divides the socket's paused buffer octets into groups according to how each pronounces "potato".

returns: undefined
  • data: Small payload to send in ping.

Sends a ping to the remote end of the socket. The 'ping' event will be raised there with the data. The remote side will immediatly send a pong causing the 'pong' event to be raised locally.

returns: undefined

socket.send(data, optionalTimeout)
  • data: String, Number, Buffer, null, Object (non-circular) to send.
  • optionalTimeout: Optional milliseconds to timeout awaiting reply.

Default is no timeout. 0 is also no timeout.

returns: Promise

// Each sender gets a promise.

socket.send('something', optionalTimeout)
  .then(result => {
    // resolves if:
    // - the remote side sends ACK
    // The remote side will send an ACK or NAK "immediately" (built-in behaviour).
    // Regarding the timeout:
    // - Both the sending of 'something' and the ACK or NAK reply is behind        
    //   whatever may already be awaiting-write in the socket buffers
    //   (on both sides)
    // - If you're sending data faster than available bandwidth the ACKs will
    //   lag.
    result.meta;     // remote side receives same meta in `on('data', (data, meta) =>`
    result.meta.seq; // the transmission sequence number
    result.meta.ts;  // the time that send('something') was originally called
  .catch(error => {
    // rejects if
    // - the remote side sends NAK
    // - the socket closes
    // - the optional timeout expires
    error.meta; // same meta as above


event 'error'
  • emits: Error

Emits errors related to the socket.

event 'connect'

Emitted when the socket connection is establisted. This is emitted before the listen() promise is resolved - so it is not accessable.

event 'close'
  • emits: code
  • emits: message

Emitted when the socket is closed. The code and message correspond to those passed to the socket.close() function.

event 'ping'
  • emits: data

Emitted when the socket receives a ping from the remote side. It receives data as sent in

event 'pong'
  • emits: data

Emitted when the remote socket's pong (reply to ping) arrives back.

event 'data'
  • emits: data String, Number, Buffer, null, Object
  • emits: meta
  • emits: reply(tag, promise) Function

Emitted when the remote socket sent data using socket.send(data).then The data is serialised to JSON on the sending side and unserialised again at the receiving side before emitting.

The meta contains:

  seq: 0,
  ts: 1476981609811, // the time the message was sent ``
  len: 53 // length of payload in bytes  
  • seq is a number assigned at send(). It is unique only within the socket pair. It is incremented with each send and starts at 0
  • ts is a timestamp. It contains the time the send() was made.
  • len is the byte length of the message.

Once all handlers subscribed to the 'data' event have run, an ACK is sent back to the sender with the same meta (with the ack flag set).

The reply function can be used to piggy-back response data in the ACK.

receivingSocket.on('data', (data, meta, reply) => {
  if (data.get == 'thing') return reply(  'aThing' , new Thing);

The thing will then be available as the sender's promise resolves.

sendingSocket.send({get: 'thing'})
  .then(data => {
    // meta is there too, but not enumerable
    // data.meta === {
    //   seq: // original seq
    //   ts:  // original send() time
    //   len: // reply data size
    //   ack: true
    // }

Multiple replies can be sent in an ACK provided they have unique tags.

socket.on('data', (data, meta, reply) => {
  reply('tag1', {});
  reply('tag2', {});
  reply({}); // auto assigns '0' as tag
  reply({}); // auto assigns '1' as tag

Replies can be promises.

socket.on('data', (data, meta, reply) => {
  reply('tag', new Promise(resolve => resolve(1)));

All promises are evaluated even if one of them rejects. Rejected promises arrive as instances of Error in the senders data and do not cause the senders promise to also reject.