Skip to content

Commit

Permalink
Merge branch 'master' into 0.2
Browse files Browse the repository at this point in the history
Conflicts:
	.travis.yml
	lib/smpp.js
	package.json
  • Loading branch information
farhadi committed Sep 19, 2015
2 parents 6015fe5 + 6194952 commit dc641a4
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 20 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: node_js
node_js:
- '0.10'
- '0.11'
- '0.12'
- '4.0'
31 changes: 27 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,29 @@ var server = smpp.createServer(function(session) {
server.listen(2775);
```

Encodings
---------

This smpp implementation supports 3 encodings: `ASCII` (GSM 03.38), `LATIN1`, and `UCS2`.
Respective data_coding for these encodings are `0x01`, `0x03`, and `0x08`.

Default encoding for `data_coding:0` is `ASCII`. You can change it as follows:

``` javascript
smpp.encodings.default = 'LATIN1';
```

String messages will be automatically encoded using one of these three encodings.
If the SMSC you are communicating with doesn't support one of these encodings,
you can simply remove it as follows:

``` javascript
delete smpp.encodings.ASCII;
```

You can also manually convert a message to a buffer and pass it as `short_message`
or `message_payload` parameter to bypass automatic message encoding.

API
-------

Expand Down Expand Up @@ -198,10 +221,10 @@ converted to '000000000430000R'.
* For `short_message` and `message_payload` fields you can specify a buffer or a
string or an object containing `udh` and `message` properties, while `udh` is a
buffer and `message` is either a string or a buffer. strings will be
automatically encoded using ucs2 or ascii depending on their characters. Also
`data_coding` (if not specified) will be automatically set to 0x01 or 0x08 for
ascii and ucs2 encodings respectively. Also UDH indicator bit in `esm_class`
is automatically set if `udh` exists.
automatically encoded using ASCII, LATIN1, or UCS2 depending on their characters.
`data_coding` (if not specified) will be automatically set to 0x01, 0x03, or 0x08
for ASCII, LATIN1, and UCS2 encodings respectively. Also UDH indicator bit in
`esm_class` is automatically set if `udh` exists.
* `sm_length` parameter is not needed. It will be automatically set depending on
the length of the `short_message`.
* `dest_address` parameter in `submit_multi` operation must be an array of
Expand Down
31 changes: 21 additions & 10 deletions lib/defs.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ Object.defineProperty(encodings, 'detect', {
}
});

Object.defineProperty(encodings, 'default', {
value: 'ASCII',
writable: true
});

var filters = {};

filters.time = {
Expand Down Expand Up @@ -366,24 +371,26 @@ filters.message = {
var message = typeof value == 'string' ? value : value.message;
if (typeof message == 'string') {
var encoding = encodings.detect(message);
if (message && !this.data_coding) {
if (message && this.data_coding === null) {
this.data_coding = consts.ENCODING[encoding];
}
message = encodings[encoding].encode(message);
}
if (!value.udh || !value.udh.length) {
return message;
}
this.esm_class = this.esm_class | consts.ESM_CLASS.UDH_INDICATOR;
if ('esm_class' in this) {
this.esm_class = this.esm_class | consts.ESM_CLASS.UDH_INDICATOR;
}
return Buffer.concat([value.udh, message]);
},
decode: function(value) {
if (!Buffer.isBuffer(value)) {
if (!Buffer.isBuffer(value) || !('data_coding' in this)) {
return value;
}
var encoding = this.data_coding & 0x0F;
if (!encoding) {
encoding = 'ASCII';
encoding = encodings.default;
} else {
for (var key in consts.ENCODING) {
if (consts.ENCODING[key] == encoding) {
Expand Down Expand Up @@ -913,7 +920,7 @@ var commands = {
schedule_delivery_time: {type: types.cstring, filter: filters.time},
validity_period: {type: types.cstring, filter: filters.time},
replace_if_present_flag: {type: types.int8},
data_coding: {type: types.int8},
data_coding: {type: types.int8, default: null},
sm_default_msg_id: {type: types.int8}
}
},
Expand Down Expand Up @@ -967,7 +974,7 @@ var commands = {
destination_addr: {type: types.cstring},
esm_class: {type: types.int8},
registered_delivery: {type: types.int8},
data_coding: {type: types.int8}
data_coding: {type: types.int8, default: null}
}
},
data_sm_resp: {
Expand All @@ -993,7 +1000,7 @@ var commands = {
validity_period: {type: types.cstring, filter: filters.time},
registered_delivery: {type: types.int8},
replace_if_present_flag: {type: types.int8},
data_coding: {type: types.int8},
data_coding: {type: types.int8, default: null},
sm_default_msg_id: {type: types.int8},
//sm_length: {type: types.int8},
short_message: {type: types.buffer, filter: filters.message}
Expand Down Expand Up @@ -1088,7 +1095,7 @@ var commands = {
validity_period: {type: types.cstring, filter: filters.time},
registered_delivery: {type: types.int8},
replace_if_present_flag: {type: types.int8},
data_coding: {type: types.int8},
data_coding: {type: types.int8, default: null},
sm_default_msg_id: {type: types.int8},
//sm_length: {type: types.int8},
short_message: {type: types.buffer, filter: filters.message}
Expand Down Expand Up @@ -1119,7 +1126,7 @@ var commands = {
validity_period: {type: types.cstring, filter: filters.time},
registered_delivery: {type: types.int8},
replace_if_present_flag: {type: types.int8},
data_coding: {type: types.int8},
data_coding: {type: types.int8, default: null},
sm_default_msg_id: {type: types.int8},
//sm_length: {type: types.int8},
short_message: {type: types.buffer, filter: filters.message}
Expand Down Expand Up @@ -1173,7 +1180,11 @@ var consts = {
DELIVERED: 2,
EXPIRED: 3,
DELETED: 4,
UNDELIVERABLE: 5
UNDELIVERABLE: 5,
ACCEPTED: 6,
UNKNOWN: 7,
REJECTED: 8,
SKIPPED: 9
},
TON: {
UNKNOWN: 0x00,
Expand Down
12 changes: 9 additions & 3 deletions lib/pdu.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ function PDU(command, options) {
}
var params = commands[command].params || {};
for (var key in params) {
this[key] = options[key] || params[key].default || params[key].type.default;
if (key in options) {
this[key] = options[key];
} else if ('default' in params[key]) {
this[key] = params[key].default;
} else {
this[key] = params[key].type.default;
}
}
for (var key in options) if (key in tlvs) {
this[key] = options[key];
Expand Down Expand Up @@ -88,7 +94,7 @@ PDU.prototype.fromBuffer = function(buffer) {
params = commands[this.command].params || {};
} else {
this.command = 'unknown';
params = {};
return;
}
for (var key in params) {
if (offset >= this.command_length) {
Expand All @@ -97,7 +103,7 @@ PDU.prototype.fromBuffer = function(buffer) {
this[key] = params[key].type.read(buffer, offset);
offset += params[key].type.size(this[key]);
}
while (offset < this.command_length) {
while (offset + 4 <= this.command_length) {
var tlvId = buffer.readUInt16BE(offset);
var length = buffer.readUInt16BE(offset + 2);
offset += 4;
Expand Down
8 changes: 6 additions & 2 deletions lib/smpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ Session.prototype.send = function(pdu, responseCallback, sendCallback) {
// traffic, the sequence_number will be provided by
// client otherwise we generate it automatically
if (!pdu.sequence_number) {
if (this.sequence == 0x7FFFFFFF) {
this.sequence = 0;
}
pdu.sequence_number = ++this.sequence;
}

if (responseCallback) {
this._callbacks[pdu.sequence_number] = responseCallback;
}
Expand Down Expand Up @@ -127,7 +131,7 @@ function Server() {
session.server = self;
self.sessions.push(session);
socket.on('close', function() {
self.sessions.splice(self.sessions.indexOf(socket), 1);
self.sessions.splice(self.sessions.indexOf(session), 1);
});
self.emit('session', session);
});
Expand Down Expand Up @@ -165,7 +169,7 @@ exports.addCommand = function(command, options) {

exports.addTLV = function(tag, options) {
options.tag = tag;
defs.tlvs[tlv] = options;
defs.tlvs[tag] = options;
defs.tlvsById[options.id] = options;
};

Expand Down
81 changes: 81 additions & 0 deletions test/pdu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
var assert = require('assert'),
PDU = require('../lib/pdu').PDU;

describe('PDU', function() {
var buffer, expected;

beforeEach(function() {
buffer = new Buffer('0000003b000000040000000000000002' +
'00010034363730313133333131310001013436373039373' +
'731333337000000000000000001000474657374', 'hex');
expected = {
command_length: 59,
command_id: 4,
command_status: 0,
sequence_number: 2,
command: 'submit_sm',
service_type: '',
source_addr_ton: 1,
source_addr_npi: 0,
source_addr: '46701133111',
dest_addr_ton: 1,
dest_addr_npi: 1,
destination_addr: '46709771337',
esm_class: 0,
protocol_id: 0,
priority_flag: 0,
schedule_delivery_time: '',
validity_period: '',
registered_delivery: 0,
replace_if_present_flag: 0,
data_coding: 1,
sm_default_msg_id: 0,
short_message: { message: 'test' }
};
});

describe('#construct', function() {
it('it should construct a pdu from buffer', function() {
var pdu = new PDU(buffer);
assert.equal(buffer.length, pdu.command_length);
assert.deepEqual(pdu, expected);
});

it('it should not fail with a malformed pdu', function() {
var b = Buffer.concat([buffer, Buffer([0])]);
b[3] = 0x3c;
expected.command_length = 60;
var pdu = new PDU(b);
assert.deepEqual(pdu, expected);
});
});

describe('#fromBuffer()', function() {
it('should return false if buffer size is less than PDU length', function() {
var b = buffer.slice(0, buffer.length - 1);
var pdu = PDU.fromBuffer(b);
assert(!pdu);
});
});

describe('#toBuffer()', function() {
it('should create a buffer from a PDU object', function() {
var submit_sm = {
sequence_number: 2,
source_addr_ton: 1,
source_addr: '46701133111',
dest_addr_ton: 1,
dest_addr_npi: 1,
destination_addr: '46709771337',
short_message: 'test'
};
var pdu = new PDU('submit_sm', submit_sm);
assert.deepEqual(pdu.toBuffer(), buffer);

submit_sm.data_coding = 0;
buffer[52] = 0;
var pdu = new PDU('submit_sm', submit_sm);
assert.deepEqual(pdu.toBuffer(), buffer);
});
});
});

0 comments on commit dc641a4

Please sign in to comment.