def handle_deliver_sm(self, pdu): if pdu['header']['command_status'] == 'ESME_ROK': sequence_number = pdu['header']['sequence_number'] message_id = str(uuid.uuid4()) pdu_resp = DeliverSMResp(sequence_number, **self.defaults) self.sendPDU(pdu_resp) pdu_params = pdu['body']['mandatory_parameters'] delivery_report = re.search( # SMPP v3.4 Issue 1.2 pg. 167 is wrong on id length 'id:(?P<id>\S{,65}) +sub:(?P<sub>...)' + ' +dlvrd:(?P<dlvrd>...)' + ' +submit date:(?P<submit_date>\d*)' + ' +done date:(?P<done_date>\d*)' + ' +stat:(?P<stat>[A-Z]{7})' + ' +err:(?P<err>...)' + ' +[Tt]ext:(?P<text>.{,20})' + '.*', pdu_params['short_message'] or '' ) if delivery_report: self.__delivery_report_callback( destination_addr=pdu_params['destination_addr'], source_addr=pdu_params['source_addr'], delivery_report=delivery_report.groupdict(), ) elif detect_multipart(pdu): redis_key = "%s#multi_%s" % ( self.r_prefix, multipart_key(detect_multipart(pdu))) log.msg("Redis multipart key: %s" % (redis_key)) value = json.loads(self.r_server.get(redis_key) or 'null') log.msg("Retrieved value: %s" % (repr(value))) multi = MultipartMessage(value) multi.add_pdu(pdu) completed = multi.get_completed() if completed: self.r_server.delete(redis_key) log.msg("Reassembled Message: %s" % (completed['message'])) # and we can finally pass the whole message on self.__deliver_sm_callback( destination_addr=completed['to_msisdn'], source_addr=completed['from_msisdn'], short_message=completed['message'], message_id=message_id, ) else: self.r_server.set(redis_key, json.dumps(multi.get_array())) else: decoded_msg = self._decode_message(pdu_params['short_message'], pdu_params['data_coding']) self.__deliver_sm_callback( destination_addr=pdu_params['destination_addr'], source_addr=pdu_params['source_addr'], short_message=decoded_msg, message_id=message_id, )
def handle_deliver_sm(self, pdu): if pdu['header']['command_status'] == 'ESME_ROK': sequence_number = pdu['header']['sequence_number'] message_id = str(uuid.uuid4()) pdu_resp = DeliverSMResp(sequence_number, **self.defaults) self.send_pdu(pdu_resp) pdu_params = pdu['body']['mandatory_parameters'] delivery_report = self.config.delivery_report_re.search( pdu_params['short_message'] or '' ) if delivery_report: self.esme_callbacks.delivery_report( destination_addr=pdu_params['destination_addr'], source_addr=pdu_params['source_addr'], delivery_report=delivery_report.groupdict(), ) elif detect_multipart(pdu): redis_key = "%s#multi_%s" % ( self.r_prefix, multipart_key(detect_multipart(pdu))) log.msg("Redis multipart key: %s" % (redis_key)) value = json.loads(self.r_server.get(redis_key) or 'null') log.msg("Retrieved value: %s" % (repr(value))) multi = MultipartMessage(value) multi.add_pdu(pdu) completed = multi.get_completed() if completed: self.r_server.delete(redis_key) log.msg("Reassembled Message: %s" % (completed['message'])) # and we can finally pass the whole message on self.esme_callbacks.deliver_sm( destination_addr=completed['to_msisdn'], source_addr=completed['from_msisdn'], short_message=completed['message'], message_id=message_id, ) else: self.r_server.set(redis_key, json.dumps(multi.get_array())) else: decoded_msg = self._decode_message(pdu_params['short_message'], pdu_params['data_coding']) self.esme_callbacks.deliver_sm( destination_addr=pdu_params['destination_addr'], source_addr=pdu_params['source_addr'], short_message=decoded_msg, message_id=message_id, )
def test_ordering(self): """ Out of order pieces must be re-assembled in-order """ sar_1 = DeliverSM( 1, short_message='\x00\x03\xff\x04\x01There she was just a') sar_2 = DeliverSM( 1, short_message='\x00\x03\xff\x04\x02 walking down the street,') sar_3 = DeliverSM( 1, short_message='\x00\x03\xff\x04\x03 singing doo wa diddy') sar_4 = DeliverSM( 1, short_message='\x00\x03\xff\x04\x04 diddy dum diddy do') multi = MultipartMessage() multi.add_pdu(sar_3.get_obj()) multi.add_pdu(sar_4.get_obj()) multi.add_pdu(sar_2.get_obj()) multi.add_pdu(sar_1.get_obj()) self.assertEquals(multi.get_completed()['message'], ( 'There she was just a walking down the street, ' 'singing doo wa diddy diddy dum diddy do'))
def test_real_csm_data(self): """ Test with real-world data which uses the CSM format. """ asif_1 = { 'body': { 'mandatory_parameters': { 'priority_flag': 0, 'source_addr': '261xxx720371', 'protocol_id': 0, 'replace_if_present_flag': 0, 'registered_delivery': 0, 'dest_addr_ton': 'international', 'source_addr_npi': 'ISDN', 'schedule_delivery_time': '', 'dest_addr_npi': 'ISDN', 'sm_length': 159, 'esm_class': 64, 'data_coding': 0, 'service_type': '', 'source_addr_ton': 'international', 'sm_default_msg_id': 0, 'validity_period': '', 'destination_addr': '261xxx782943', 'short_message': ( '\x05\x00\x03\x1a\x02\x01I try to send sms testing ' 'vumi sms sms sms sms msm sms sms sms sms sms sms sms ' 'sms sms ssms sms smS sms sms sms sms sms sms sms sns ' 'sns sms sms sms sms s') }, 'optional_parameters': [ { 'length': 2, 'tag': 'user_message_reference', 'value': 91 }, { 'length': 16, 'tag': 'dest_subaddress', 'value': 'a0000410020601030303070802090403' } ] }, 'header': { 'command_status': 'ESME_ROK', 'command_length': 242, 'sequence_number': 23, 'command_id': 'deliver_sm' } } asif_2 = { 'body': { 'mandatory_parameters': { 'priority_flag': 1, 'source_addr': '261xxx720371', 'protocol_id': 0, 'replace_if_present_flag': 0, 'registered_delivery': 0, 'dest_addr_ton': 'international', 'source_addr_npi': 'ISDN', 'schedule_delivery_time': '', 'dest_addr_npi': 'ISDN', 'sm_length': 78, 'esm_class': 64, 'data_coding': 0, 'service_type': '', 'source_addr_ton': 'international', 'sm_default_msg_id': 0, 'validity_period': '', 'destination_addr': '261xxx782943', 'short_message': ( '\x05\x00\x03\x1a\x02\x02mns again again again again' ' again again again again sms sms sms sms sms ') }, 'optional_parameters': [ { 'length': 2, 'tag': 'user_message_reference', 'value': 92}, { 'length': 16, 'tag': 'dest_subaddress', 'value': 'a0000410020601030303070802090403' } ] }, 'header': { 'command_status': 'ESME_ROK', 'command_length': 161, 'sequence_number': 24, 'command_id': 'deliver_sm' } } multi = MultipartMessage() self.assertEquals( multi.get_partial(), { 'to_msisdn': '', 'from_msisdn': '', 'message': '' }) self.assertEquals(multi.get_completed(), None) self.assertEquals(multi.get_key(), None) multi.add_pdu(asif_2) self.assertEquals( multi.get_partial(), { 'to_msisdn': '261xxx782943', 'from_msisdn': '261xxx720371', 'message': ( 'mns again again again again again again again ' 'again sms sms sms sms sms ') }) self.assertEquals(multi.get_completed(), None) self.assertEquals(multi.get_key(), '261xxx720371_261xxx782943_26_2') multi.add_pdu(asif_1) self.assertEquals( multi.get_completed()['message'], ('I try to send sms testing vumi sms sms sms sms msm sms ' 'sms sms sms sms sms sms sms sms ssms sms smS sms sms sms sms ' 'sms sms sms sns sns sms sms sms sms smns again again again ' 'again again again again again sms sms sms sms sms ')) self.assertEquals(multi.get_key(), '261xxx720371_261xxx782943_26_2')
def load_multipart_message(self, redis_key): value = yield self.redis.get(redis_key) value = json.loads(value) if value else {} log.debug("Retrieved value: %s" % (repr(value))) returnValue(MultipartMessage(self._unhex_from_redis(value)))