Skip to content
This repository has been archived by the owner on Mar 21, 2018. It is now read-only.

Commit

Permalink
fakesmpp can now be used as a node package.
Browse files Browse the repository at this point in the history
  • Loading branch information
Laci Szucs authored and Laci Szucs committed Jun 7, 2016
1 parent 949a136 commit 6f1deb6
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 107 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/*
14 changes: 14 additions & 0 deletions cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const _ = require('lodash');
const optimist = require('optimist');
const options = require('./options');
const argv = _.reduce(cliOptions, (optimist, option, name) => {
return optimist.options(name, option);
}, optimist);

if (argv.help) {
optimist.showHelp();
return;
}

module.exports = require('smpp').spawnServer(argv);

3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict';

module.exports = require('./smpp');
13 changes: 13 additions & 0 deletions logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

const winston = require('winston');
const logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
json: false,
timestamp: true
})
]
});

module.exports = logger;
29 changes: 29 additions & 0 deletions options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module.exports = Object.freeze({
port: {
default: 2775,
alias: 'p',
describe: 'Port which server listen to.'
},
ddmin: {
default: 0,
describe: 'Minimum delay after submit_sm requested and deliver_sm request to ESME.'
},
ddmax: {
default: 0,
describe: 'Maximum delay after submit_sm requested and deliver_sm request to ESME.'
},
statuses: {
alias: 's',
default: 'delivered',
describe: "Comma separated list of statuses, server send in deliver_sm request to ESME."
},
auth: {
default: 'user:pass',
describe: 'Comma separated auth credentials in format [system_id]:[password]'
},
help: {
default: false,
alias: 'h',
describe: 'Current help.'
}
});
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,11 @@
"bugs": {
"url": "https://github.com/lab-coop/fakesmpp/issues"
},
"homepage": "https://github.com/lab-coop/fakesmpp#readme"
"homepage": "https://github.com/lab-coop/fakesmpp#readme",
"dependencies": {
"optimist": "^0.6.1",
"smpp": "^0.2.0",
"strftime": "^0.9.2",
"winston": "^2.2.0"
}
}
197 changes: 91 additions & 106 deletions smpp.js
Original file line number Diff line number Diff line change
@@ -1,120 +1,105 @@
/**
* Fake SMPP.
*/
var smpp = require('smpp');
var winston = require('winston');
var strftime = require('strftime');
var optimist = require('optimist');
var argv = optimist
.options('port', {alias: 'p', default: 2775, describe: 'Port which server listen to.'})
.options('ddmin', {default: 0, describe: 'Minimum delay after submit_sm requested and deliver_sm request to ESME.'}) // delivery min delay
.options('ddmax', {default: 0, describe: 'Maximum delay after submit_sm requested and deliver_sm request to ESME.'}) // delivery max delay
.options('statuses', {alias: 's', default: 'delivered', describe: "Comma separated list of statuses, server send in deliver_sm request to ESME."})
.options('auth', {default: 'user:pass', describe: 'Comma separated auth credentials in format [system_id]:[password]'})
.options('help', {default: false, alias: 'h', describe: 'Current help.'})
.argv;
const _ = require('lodash');
const smpp = require('smpp');
const strftime = require('strftime');
const optionsDefaults = _.mapValues(require('./options'), 'default');

if (argv.help) {
optimist.showHelp();
return;
}
const logger = require('./logger');
const Statuses = require('./statuses').Statuses;

var Statuses = require('./statuses').Statuses;
// Read auth data
var auth_data = function(str) {
var auth = {};
str.split(",").map(function(str) {
var l = str.split(":");
if (l.length > 0 && l[0] != '') {
var val = "";
var key = l[0];
if (l.length > 1) {
val = l[1];
}
auth[key] = val;
}
});
module.exports = Object.freeze({
spawnServer
});

function spawnServer(argv) {
// You may now use it as a package.json dependency
argv = _.defaults(argv, optionsDefaults);

// Read auth data
const auth_data = (argv.auth || '').split(',').reduce((auth, str) => {
const pair = str.split(':');
if (pair.length && pair[0].length) {
auth[pair[0]] = pair[1] || '';
}
return auth;
}(argv.auth);
// Init logger
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ json: false, timestamp: true })
]});
});

// List of statuses which we iterate in response.
var statuses = new Statuses(argv.statuses.split(','));//.map(function (val) {return val.toUpperCase()}));
// List of statuses which we iterate in response.
var statuses = new Statuses(argv.statuses.split(','));//.map(function (val) {return val.toUpperCase()}));

// Validate options
if (argv.ddmax < argv.ddmin) {
logger.error("ddmin(%d) > ddmax(%d)", argv.ddmin, arg.ddmax);
}
// Validate options
if (argv.ddmax < argv.ddmin) {
logger.error("ddmin(%d) > ddmax(%d)", argv.ddmin, arg.ddmax);
}
const server = smpp.createServer(function(session) {
session.on('bind_transceiver', function(pdu) {
logger.info("bind_transceiver requested.", {system_id: pdu.system_id});
session.on('submit_sm', function(pdu) {
var msg_received_on = new Date();
var r = Math.floor(Math.random() * (99 - 10) + 10);
var msg_id = ""+msg_received_on.getTime() + "." + r;
var delivery_delay = getDeliveryDelay(argv.ddmin, argv.ddmax);
logger.info("Msg was received, id=%s assigned.", msg_id, {From: pdu.source_addr, To: pdu.destination_addr, ShortMsg: pdu.short_message.message.toString(), MsgPayload: pdu.message_payload.message.toString(), ScheduleDeliveryTime: pdu.schedule_delivery_time});

logger.info("Send submit_sm_resp for id=%s.", msg_id);
session.send(pdu.response({
message_id: msg_id,
}));

var server = smpp.createServer(function(session) {
session.on('bind_transceiver', function(pdu) {
logger.info("bind_transceiver requested.", {system_id: pdu.system_id});
session.on('submit_sm', function(pdu) {
var msg_received_on = new Date();
var r = Math.floor(Math.random() * (99 - 10) + 10);
var msg_id = ""+msg_received_on.getTime() + "." + r;
var delivery_delay = getDeliveryDelay(argv.ddmin, argv.ddmax);
logger.info("Msg was received, id=%s assigned.", msg_id, {From: pdu.source_addr, To: pdu.destination_addr, ShortMsg: pdu.short_message.message.toString(), MsgPayload: pdu.message_payload.message.toString(), ScheduleDeliveryTime: pdu.schedule_delivery_time});

logger.info("Send submit_sm_resp for id=%s.", msg_id);
session.send(pdu.response({
message_id: msg_id,
}));

// Send request to ESME to confirm delivery
setTimeout(function() {
var status = statuses.next();
var dr = getDeliveryReceipt(msg_id, status, msg_received_on, new Date(), pdu.short_message.message.toString());
logger.info("delivery_sm.short_message=%s", dr);
logger.info("Send deliver_sm for id=%d with status.stat=%s, status.err=%s.", msg_id, status.stat, status.err);
session.deliver_sm({
source_addr: pdu.source_addr,
source_addr_ton: pdu.source_addr_ton,
source_addr_npi: pdu.source_addr_npi,
dest_addr_ton: pdu.dest_addr_ton,
dest_addr_npi: pdu.dest_addr_npi,
destination_addr: pdu.destination_addr,
short_message: dr,
esm_class: smpp.ESM_CLASS.MC_DELIVERY_RECEIPT,
sequence_number: pdu.sequence_number,
}, function(pdu) {
logger.info("deliver_sm_resp received.");
});
}, delivery_delay);
});
// Send request to ESME to confirm delivery
setTimeout(function() {
var status = statuses.next();
var dr = getDeliveryReceipt(msg_id, status, msg_received_on, new Date(), pdu.short_message.message.toString());
logger.info("delivery_sm.short_message=%s", dr);
logger.info("Send deliver_sm for id=%d with status.stat=%s, status.err=%s.", msg_id, status.stat, status.err);
session.deliver_sm({
source_addr: pdu.source_addr,
source_addr_ton: pdu.source_addr_ton,
source_addr_npi: pdu.source_addr_npi,
dest_addr_ton: pdu.dest_addr_ton,
dest_addr_npi: pdu.dest_addr_npi,
destination_addr: pdu.destination_addr,
short_message: dr,
esm_class: smpp.ESM_CLASS.MC_DELIVERY_RECEIPT,
sequence_number: pdu.sequence_number,
}, function(pdu) {
logger.info("deliver_sm_resp received.");
});
}, delivery_delay);
});

// Availability check
session.on('enquire_link', function(pdu) {
session.send(pdu.response());
});
session.on('unbind', function(pdu) {
session.send(pdu.response());
session.close();
});
// we pause the session to prevent further incoming pdu events,
// untill we authorize the session with some async operation.
session.pause();
checkAsyncUserPass(pdu.system_id, pdu.password, function(err) {
if (err) {
logger.error("bind_transceiver failed. Incorrert credentials.");
session.send(pdu.response({
command_status: smpp.ESME_RBINDFAIL
}));
session.close();
return;
}
session.send(pdu.response());
logger.info("bind_transceiver completed successfully.", {system_id: pdu.system_id});
session.resume();
});
// Availability check
session.on('enquire_link', function(pdu) {
session.send(pdu.response());
});
session.on('unbind', function(pdu) {
session.send(pdu.response());
session.close();
});
});
server.listen(argv.port);
logger.info("Server listen port #%d", argv.port);
// we pause the session to prevent further incoming pdu events,
// untill we authorize the session with some async operation.
session.pause();
checkAsyncUserPass(pdu.system_id, pdu.password, function(err) {
if (err) {
logger.error("bind_transceiver failed. Incorrert credentials.");
session.send(pdu.response({
command_status: smpp.ESME_RBINDFAIL
}));
session.close();
return;
}
session.send(pdu.response());
logger.info("bind_transceiver completed successfully.", {system_id: pdu.system_id});
session.resume();
});
});
});
server.listen(argv.port);
logger.info("Server listen port #%d", argv.port);
return server;
}

//
// Check if system_id with password has access to send messages.
Expand Down

0 comments on commit 6f1deb6

Please sign in to comment.