agn-utils/device-tcp-socket/tcp-device.js

88 lines
2.6 KiB
JavaScript

'use strict';
const stream = require('stream'),
Socket = require('net').Socket,
assert = require('assert');
/**
* Base TCPDevice class for handling TCP socket from tracking device
*
*/
class TCPDevice extends stream.Duplex {
constructor(socket, ops) {
super(ops);
this.ops = Object.assign({}, {
maxInvalidReadTry: 5
}, ops);
// Perform type assertions
assert.ok(socket instanceof Socket, 'socket argument must be an instance of Socket'); // prettier-ignore
this.id = null;
this.msgReceived = 0;
this._invalidTry = 0;
this._socket = socket;
this._socket.on('close', hadError => this.emit('close', hadError));
// this._socket.on("connect", () => console.log("Client connected !"));
this._socket.on('drain', () => this.emit('drain'));
this._socket.on('end', () => this.emit('end'));
this._socket.on('error', err => this.emit('error', err));
this._socket.on('lookup', (e, a, f, h) => this.emit('lookup', e, a, f, h));
this._socket.on('readable', this._onData.bind(this));
this._socket.on('timeout', () => this.emit('timeout'));
}
/**
* Half-closes the socket. It is still possible that the opposite
* side is still sending data.
*/
end() {
this._socket.end();
return this;
}
/**
* Destroys the socket and ensures that no more I/O activity happens
* on the socket. When an `err` is included, an 'error' event will
* be emitted and all listeners will receive the error as an
* argument.
* @param err optional error to send
*/
destroy(err) {
this._socket.destroy(err);
return this;
}
_guardInvalidTries() {
this._invalidTry++;
if (this._invalidTry > this.ops.maxInvalidReadTry)
throw new Error('Reached maximum invalid read try');
}
/**
* _onData is triggered by the "readable" event on the underlying TCP socket.
* It is called each time there is new data * received. It is responsible for reading data from the socket and *
* performing the appropriate action given the current read state.
* @virtual Extenders implementation must override this menthod acccording to the detail of the protocol
*/
_onData() { }
_read() {
// Trigger a read but wait until the end of the event loop.
// This is necessary when reading in paused mode where
// _read was triggered by stream.read() originating inside
// a "readable" event handler. Attempting to push more data
// synchronously will not trigger another "readable" event.
setImmediate(() => this._onData());
}
_write() { }
_final() { }
}
module.exports = TCPDevice;