Skip to content

Commit

Permalink
Merge pull request #1070 from praekelt/feature/MOMZA-664-make-smpp-re…
Browse files Browse the repository at this point in the history
…f-num-configurable

Make multipart reference rollover configurable
  • Loading branch information
rudigiesler committed May 11, 2017
2 parents 4011e37 + 22ba8ba commit 322a817
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 5 deletions.
6 changes: 6 additions & 0 deletions vumi/transports/smpp/processors/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,10 @@ class SubmitShortMessageProcessorConfig(Config):
"If `True`, messages longer than 140 bytes will be sent as a series "
"of smaller messages with the user data headers. Default is `False`.",
default=False, static=True)
multipart_sar_reference_rollover = ConfigInt(
"The value at which the reference number of a multi part SMS will "
"roll over. eg. a value of 2 will result in a series 0, 1, 0, 1 ...",
default=0x10000, static=True)

def post_validate(self):
long_message_params = (
Expand Down Expand Up @@ -543,6 +547,8 @@ def send_short_message(self, service, vumi_message_id, destination_addr,
return service.submit_sm_long(**kwargs)

elif self.config.send_multipart_sar:
kwargs['reference_rollover'] = (
self.config.multipart_sar_reference_rollover)
return service.submit_csm_sar(**kwargs)

elif self.config.send_multipart_udh:
Expand Down
41 changes: 40 additions & 1 deletion vumi/transports/smpp/processors/tests/test_default.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from twisted.internet.defer import inlineCallbacks
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.internet.task import Clock
from twisted.trial.unittest import FailTest

from vumi.errors import ConfigError
from vumi.tests.helpers import VumiTestCase
from vumi.transports.tests.helpers import TransportHelper
from vumi.transports.smpp.pdu_utils import unpacked_pdu_opts
from vumi.transports.smpp.smpp_transport import SmppTransceiverTransport
from vumi.transports.smpp.tests.fake_smsc import FakeSMSC

Expand All @@ -13,6 +15,16 @@ def setUp(self):
self.fake_smsc = FakeSMSC()
self.tx_helper = self.add_helper(
TransportHelper(SmppTransceiverTransport))
self.clock = Clock()

@inlineCallbacks
def get_transport(self, config):
transport = yield self.tx_helper.get_transport(config, start=False)
transport.clock = self.clock
yield transport.startWorker()
self.clock.advance(0)
yield self.fake_smsc.bind()
returnValue(transport)

@inlineCallbacks
def test_data_coding_override_keys_ints(self):
Expand Down Expand Up @@ -61,3 +73,30 @@ def test_data_coding_override_keys_invalid(self):
)
else:
raise FailTest("Expected ConfigError to be raised")

@inlineCallbacks
def test_multipart_sar_reference_rollover(self):
"""
If the multipart_sar_reference_rollover config value is set, then for
multipart messages, the reference should rollover at that value.
"""
config = {
'system_id': 'foo',
'password': 'bar',
'twisted_endpoint': self.fake_smsc.endpoint,
'submit_short_message_processor_config': {
'send_multipart_sar': True,
'multipart_sar_reference_rollover': 0xFF,
},
}
transport = yield self.get_transport(config)
transport.service.sequence_generator.redis.set(
'smpp_last_sequence_number', 0xFF)

yield transport.submit_sm_processor.send_short_message(
transport.service, 'test-id', '+1234', 'test message ' * 20,
optional_parameters={})
pdus = yield self.fake_smsc.await_pdus(2)

msg_refs = [unpacked_pdu_opts(p)['sar_msg_ref_num'] for p in pdus]
self.assertEqual(msg_refs, [1, 1])
8 changes: 5 additions & 3 deletions vumi/transports/smpp/smpp_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ def csm_split_message(self, message):
return split_msg

@inlineCallbacks
def submit_csm_sar(self, vumi_message_id, destination_addr, **pdu_params):
def submit_csm_sar(
self, vumi_message_id, destination_addr,
reference_rollover=0x10000, **pdu_params):
"""
Submit a concatenated SMS to the SMSC using the optional
SAR parameter names in the various PDUS.
Expand All @@ -338,8 +340,8 @@ def submit_csm_sar(self, vumi_message_id, destination_addr, **pdu_params):
for i, msg in enumerate(split_msg):
pdu_params = pdu_params.copy()
optional_parameters.update({
# Reference number must be between 00 & FFFF
'sar_msg_ref_num': (ref_num % 0xFFFF),
# Reference number must be between 00 & the configure value
'sar_msg_ref_num': (ref_num % reference_rollover),
'sar_total_segments': len(split_msg),
'sar_segment_seqnum': i + 1,
})
Expand Down
38 changes: 37 additions & 1 deletion vumi/transports/smpp/tests/test_smpp_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,43 @@ def test_submit_csm_sar_ref_num_limit(self):
self.assertEqual(4, pdu_opts['sar_total_segments'])

self.assertEqual(long_message, ''.join(msg_parts))
self.assertEqual([2, 2, 2, 2], msg_refs)
self.assertEqual([1, 1, 1, 1], msg_refs)

stored_ids = yield self.lookup_message_ids(service, seq_nums)
self.assertEqual(['abc123'] * len(seq_nums), stored_ids)

@inlineCallbacks
def test_submit_csm_sar_ref_num_custom_limit(self):
"""
The SAR reference number is set correctly when the generated reference
number is larger than the configured limit.
"""
service = yield self.get_service({'send_multipart_sar': True})
yield self.fake_smsc.bind()
# forward until we go past 0xFF
yield self.set_sequence_number(service, 0x100)

long_message = 'This is a long message.' * 20
seq_nums = yield service.submit_csm_sar(
'abc123', 'dest_addr', short_message=long_message,
reference_rollover=0x100)
pdus = yield self.fake_smsc.await_pdus(4)
msg_parts = []
msg_refs = []

for i, sm in enumerate(pdus):
pdu_opts = unpacked_pdu_opts(sm)
mandatory_parameters = sm['body']['mandatory_parameters']

self.assertEqual('submit_sm', sm['header']['command_id'])
msg_parts.append(mandatory_parameters['short_message'])
self.assertTrue(len(mandatory_parameters['short_message']) <= 130)
msg_refs.append(pdu_opts['sar_msg_ref_num'])
self.assertEqual(i + 1, pdu_opts['sar_segment_seqnum'])
self.assertEqual(4, pdu_opts['sar_total_segments'])

self.assertEqual(long_message, ''.join(msg_parts))
self.assertEqual([1, 1, 1, 1], msg_refs)

stored_ids = yield self.lookup_message_ids(service, seq_nums)
self.assertEqual(['abc123'] * len(seq_nums), stored_ids)
Expand Down

0 comments on commit 322a817

Please sign in to comment.