Skip to content

Commit

Permalink
Client & Server debug feature implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
rmruano committed Sep 27, 2021
1 parent 977e3d7 commit 44b1fe0
Show file tree
Hide file tree
Showing 3 changed files with 329 additions and 52 deletions.
52 changes: 33 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,32 +34,36 @@ Usage
var smpp = require('smpp');
var session = smpp.connect({
url: 'smpp://example.com:2775',
auto_enquire_link_period: 10000
});
session.bind_transceiver({
system_id: 'YOUR_SYSTEM_ID',
password: 'YOUR_PASSWORD'
}, function(pdu) {
if (pdu.command_status == 0) {
// Successfully bound
session.submit_sm({
destination_addr: 'DESTINATION NUMBER',
short_message: 'Hello!'
}, function(pdu) {
if (pdu.command_status == 0) {
// Message successfully sent
console.log(pdu.message_id);
}
});
}
auto_enquire_link_period: 10000,
debug: true
}, function() {
session.bind_transceiver({
system_id: 'YOUR_SYSTEM_ID',
password: 'YOUR_PASSWORD'
}, function(pdu) {
if (pdu.command_status === 0) {
// Successfully bound
session.submit_sm({
destination_addr: 'DESTINATION NUMBER',
short_message: 'Hello!'
}, function(pdu) {
if (pdu.command_status === 0) {
// Message successfully sent
console.log(pdu.message_id);
}
});
}
});
});
```

### Creating a SMPP server

``` javascript
var smpp = require('smpp');
var server = smpp.createServer(function(session) {
var server = smpp.createServer({
debug: true
}, function(session) {
session.on('bind_transceiver', function(pdu) {
// we pause the session to prevent further incoming pdu events,
// untill we authorize the session with some async operation.
Expand All @@ -80,6 +84,16 @@ var server = smpp.createServer(function(session) {
server.listen(2775);
```

### Debug
To enable a simple debug of ingoing/outgoing messages pass `debug: true` as server/client option. Debug is disabled by default.

Alternatively, you can listen for the `debug` even and write your own implementation:
``` javascript
session.on('debug', function(type, msg, payload) {
console.log({type: type, msg: msg, payload: payload});
});
```

Encodings
---------

Expand Down
91 changes: 76 additions & 15 deletions lib/smpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,72 @@ var net = require('net'),
PDU = require('./pdu').PDU,
EventEmitter = require('events').EventEmitter;

function Session(options) {
function Session(mode, options) {
EventEmitter.call(this);
this.options = options || {};
var self = this;
var transport = net;
this._extractPDUs = this._extractPDUs.bind(self);
this.sequence = 0;
this.paused = false;
this.remoteAddress = null;
this._busy = false;
this._callbacks = {};
this._interval = 0;
this._command_length = null;
this._mode = mode;
this._id = Math.floor(Math.random() * (999999 - 100000)) + 100000; // random session id
this._prevBytesRead = 0;
if (options.socket) {
// server mode
this.socket = options.socket;
} else {
// client mode
if (options.tls) {
transport = tls;
}
this.socket = transport.connect(this.options);
this.socket.on('connect', function() {
self.emit('connect');
this.socket.on('connect', (function() {
self.remoteAddress = self.socket.remoteAddress;
self.debug("server.connected", "connected to server", {secure: options.tls});
self.emit('connect'); // @todo should emmit the session, but it would break BC
if(self.options.auto_enquire_link_period) {
self._interval = setInterval(function() {
self.enquire_link();
}, self.options.auto_enquire_link_period);
}
});
this.socket.on('secureConnect', function() {
self.emit('secureConnect');
});
}).bind(this));
this.socket.on('secureConnect', (function() {
self.emit('secureConnect'); // @todo should emmit the session, but it would break BC
}).bind(this));
}
this.socket.on('readable', this._extractPDUs.bind(this));
this.remoteAddress = this.socket.remoteAddress;
this.socket.on('open', function() {
self.debug("socket.open");
});
this.socket.on('readable', function() {
if ( (self.socket.bytesRead - self._prevBytesRead) > 0 ) {
// on disconnections the readable event receives 0 bytes, we do not want to debug that
self.debug("socket.data.in", null, {bytes: self.socket.bytesRead - self._prevBytesRead});
self._prevBytesRead = self.socket.bytesRead;
}
self._extractPDUs();
});
this.socket.on('close', function() {
if (self._mode === "server") {
self.debug("client.disconnected", "client has disconnected");
} else {
self.debug("server.disconnected", "disconnected from server");
}
self.emit('close');
if(self._interval) {
clearInterval(self._interval);
self._interval = 0;
}
});
this.socket.on('error', function(e) {
self.emit('error', e);
self.debug("socket.error", e.message, e);
self.emit('error', e); // Emitted errors will kill the program if they're not captured.
if(self._interval) {
clearInterval(self._interval);
self._interval = 0;
Expand All @@ -55,6 +81,34 @@ function Session(options) {

util.inherits(Session, EventEmitter);

Session.prototype.debug = function(type, msg, payload) {
if (type === undefined) type = null;
if (msg === undefined) msg = null;
if (this.options.debug) {
var coloredTypes = {
"reset": "\x1b[0m",
"dim": "\x1b[2m",
"client.connected": "\x1b[1m\x1b[34m",
"client.disconnected": "\x1b[1m\x1b[31m",
"server.connected": "\x1b[1m\x1b[34m",
"server.disconnected": "\x1b[1m\x1b[31m",
"pdu.command.in": "\x1b[36m",
"pdu.command.out": "\x1b[32m",
"socket.error": "\x1b[41m\x1b[30m"
}
var now = new Date();
var logBuffer = now.toISOString() +
" - " + (this._mode === "server" ? "srv" : "cli") +
" - " + this._id +
" - " + (coloredTypes.hasOwnProperty(type) ? coloredTypes[type] + type + coloredTypes.reset : type) +
" - " + (msg !== null ? msg : "" ) +
" - " + coloredTypes.dim + (payload !== undefined ? JSON.stringify(payload) : "") + coloredTypes.reset;
if (this.remoteAddress) logBuffer += " - [" + this.remoteAddress + "]"
console.log( logBuffer );
}
this.emit('debug', type, msg, payload);
}

Session.prototype.connect = function() {
this.sequence = 0;
this.paused = false;
Expand All @@ -80,6 +134,7 @@ Session.prototype._extractPDUs = function() {
if (!(pdu = PDU.fromStream(this.socket, this._command_length))) {
break;
}
this.debug("pdu.command.in", pdu.command, pdu);
} catch (e) {
this.emit('error', e);
return;
Expand Down Expand Up @@ -116,12 +171,15 @@ Session.prototype.send = function(pdu, responseCallback, sendCallback) {
} else if (responseCallback && !sendCallback) {
sendCallback = responseCallback;
}
this.socket.write(pdu.toBuffer(), function() {
this.debug("pdu.command.out", pdu.command, pdu);
var buffer = pdu.toBuffer();
this.socket.write(buffer, (function() {
this.debug("socket.data.out", null, {bytes: buffer.length});
this.emit('send', pdu);
if (sendCallback) {
sendCallback(pdu);
}
}.bind(this));
}).bind(this));
return true;
};

Expand Down Expand Up @@ -181,9 +239,11 @@ function Server(options, listener) {

this.tls = options.key && options.cert;
var transport = this.tls ? tls : net;
this.options = options;

transport.Server.call(this, options, function(socket) {
var session = new Session({socket: socket});
var session = new Session("server", {socket: socket, debug: self.options.debug});
session.debug("client.connected", "client has connected");
session.server = self;
self.sessions.push(session);
socket.on('close', function() {
Expand Down Expand Up @@ -240,7 +300,7 @@ exports.connect = exports.createSession = function(url, listener) {
} else if (typeof url == 'string') {
options = parse(url);
options.host = options.slashes ? options.hostname : url;
options.tls = options.protocol == 'ssmpp:';
options.tls = options.protocol === 'ssmpp:';
} else if (typeof url == 'function') {
listener = url;
} else {
Expand All @@ -249,12 +309,13 @@ exports.connect = exports.createSession = function(url, listener) {
url = parse(options.url);
options.host = url.hostname;
options.port = url.port;
options.tls = url.protocol == 'ssmpp:';
options.tls = url.protocol === 'ssmpp:';
}
}
options.port = options.port || (options.tls ? 3550 : 2775);
options.debug = options.debug || false;

var session = new Session(options);
var session = new Session("client", options);
if (listener) {
session.on(options.tls ? 'secureConnect' : 'connect', listener);
}
Expand Down

0 comments on commit 44b1fe0

Please sign in to comment.