Skip to content

Commit

Permalink
Initial implementation of SMPP multipart messages using painstakingly…
Browse files Browse the repository at this point in the history
… handcrafted user data headers.
  • Loading branch information
jerith committed Oct 12, 2013
1 parent b601b78 commit f56480e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 0 deletions.
25 changes: 25 additions & 0 deletions vumi/transports/smpp/clientserver/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ def submit_sm(self, **kwargs):
returnValue(0)

sar_params = kwargs.pop('sar_params', None)
has_udh = kwargs.pop('has_udh', False)

pdu_params = self.bind_params.copy()
pdu_params.update(kwargs)
Expand All @@ -470,6 +471,12 @@ def submit_sm(self, **kwargs):
**pdu_params)
returnValue(sequence_number)

if self.config.send_multipart_udh and not has_udh:
if len(message) > 130:
sequence_number = yield self._submit_multipart_udh(
**pdu_params)
returnValue(sequence_number)

sequence_number = yield self.get_next_seq()

pdu = SubmitSM(sequence_number, **pdu_params)
Expand Down Expand Up @@ -508,6 +515,24 @@ def _submit_multipart_sar(self, **pdu_params):
sequence_number = yield self.submit_sm(**params)
returnValue(sequence_number)

@inlineCallbacks
def _submit_multipart_udh(self, **pdu_params):
message = pdu_params['short_message']
split_msg = []
while message:
split_msg.append(message[:130])
message = message[130:]
ref_num = randint(1, 255)
for i, msg in enumerate(split_msg):
params = pdu_params.copy()
params['has_udh'] = True
params['esm_class'] = 0x40
udh = '\05\00\03%s%s%s' % (
chr(ref_num), chr(len(split_msg)), chr(i + 1))
params['short_message'] = udh + msg
sequence_number = yield self.submit_sm(**params)
returnValue(sequence_number)

@inlineCallbacks
def enquire_link(self, **kwargs):
if self.state in ['BOUND_TX', 'BOUND_RX', 'BOUND_TRX']:
Expand Down
32 changes: 32 additions & 0 deletions vumi/transports/smpp/clientserver/tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,38 @@ def test_submit_sm_sms_multipart_sar(self):
self.assertEqual(long_message, ''.join(msg_parts))
self.assertEqual(1, len(set(msg_refs)))

@inlineCallbacks
def test_submit_sm_sms_multipart_udh(self):
"""Submit a long SMS message using multipart user data headers."""
esme = yield self.get_esme(config={
'send_multipart_udh': True,
})
long_message = 'This is a long message.' * 20
yield esme.submit_sm(short_message=long_message)
self.assertEqual(4, len(esme.fake_sent_pdus))
msg_parts = []
msg_refs = []

for i, sm_pdu in enumerate(esme.fake_sent_pdus):
sm = unpack_pdu(sm_pdu.get_bin())
mandatory_parameters = sm['body']['mandatory_parameters']
self.assertEqual('submit_sm', sm['header']['command_id'])
msg = mandatory_parameters['short_message']

udh_hlen, udh_tag, udh_len, udh_ref, udh_tot, udh_seq = [
ord(octet) for octet in msg[:6]]
self.assertEqual(5, udh_hlen)
self.assertEqual(0, udh_tag)
self.assertEqual(3, udh_len)
msg_refs.append(udh_ref)
self.assertEqual(4, udh_tot)
self.assertEqual(i + 1, udh_seq)
msg_parts.append(msg[6:])
self.assertEqual(0x40, mandatory_parameters['esm_class'])

self.assertEqual(long_message, ''.join(msg_parts))
self.assertEqual(1, len(set(msg_refs)))

@inlineCallbacks
def test_submit_sm_ussd_continue(self):
"""Submit a USSD message with a session continue flag."""
Expand Down
4 changes: 4 additions & 0 deletions vumi/transports/smpp/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ class SmppTransportConfig(Transport.CONFIG_CLASS):
"If `True`, messages longer than 140 bytes will be sent as a series "
"of smaller messages with the sar_* parameters set. Default is "
"`False`.", default=False, static=True)
send_multipart_udh = ConfigBool(
"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)
split_bind_prefix = ConfigText(
"This is the Redis prefix to use for storing things like sequence "
"numbers and message ids for delivery report handling. It defaults "
Expand Down

0 comments on commit f56480e

Please sign in to comment.