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 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 handle_multipart_pdu(self, pdu): if not detect_multipart(pdu): return succeed(False) # We have a multipart SMS. pdu_params = pdu['body']['mandatory_parameters'] d = self.handle_deliver_sm_multipart(pdu, pdu_params) d.addCallback(lambda _: True) return d
def handle_deliver_sm(self, pdu): if self.state not in ['BOUND_RX', 'BOUND_TRX']: log.err('WARNING: Received deliver_sm in wrong state: %s' % ( self.state)) return if pdu['header']['command_status'] != 'ESME_ROK': return # TODO: Only ACK messages once we've processed them? sequence_number = pdu['header']['sequence_number'] pdu_resp = DeliverSMResp(sequence_number, **self.bind_params) yield self.send_pdu(pdu_resp) pdu_params = pdu['body']['mandatory_parameters'] pdu_opts = unpacked_pdu_opts(pdu) # This might be a delivery receipt with PDU parameters. If we get a # delivery receipt without these parameters we'll try a regex match # later once we've decoded the message properly. receipted_message_id = pdu_opts.get('receipted_message_id', None) message_state = pdu_opts.get('message_state', None) if receipted_message_id is not None and message_state is not None: yield self.esme_callbacks.delivery_report( message_id=receipted_message_id, message_state={ 1: 'ENROUTE', 2: 'DELIVERED', 3: 'EXPIRED', 4: 'DELETED', 5: 'UNDELIVERABLE', 6: 'ACCEPTED', 7: 'UNKNOWN', 8: 'REJECTED', }.get(message_state, 'UNKNOWN'), ) # We might have a `message_payload` optional field to worry about. message_payload = pdu_opts.get('message_payload', None) if message_payload is not None: pdu_params['short_message'] = message_payload.decode('hex') if detect_ussd(pdu_opts): # We have a USSD message. yield self._handle_deliver_sm_ussd(pdu, pdu_params, pdu_opts) elif detect_multipart(pdu): # We have a multipart SMS. yield self._handle_deliver_sm_multipart(pdu, pdu_params) else: # We have a standard SMS. yield self._handle_deliver_sm_sms(pdu_params)
def handle_deliver_sm(self, pdu): if self.state not in ['BOUND_RX', 'BOUND_TRX']: log.err('WARNING: Received deliver_sm in wrong state: %s' % (self.state)) return if pdu['header']['command_status'] != 'ESME_ROK': return # TODO: Only ACK messages once we've processed them? sequence_number = pdu['header']['sequence_number'] pdu_resp = DeliverSMResp(sequence_number, **self.bind_params) yield self.send_pdu(pdu_resp) pdu_params = pdu['body']['mandatory_parameters'] pdu_opts = unpacked_pdu_opts(pdu) # This might be a delivery receipt with PDU parameters. If we get a # delivery receipt without these parameters we'll try a regex match # later once we've decoded the message properly. receipted_message_id = pdu_opts.get('receipted_message_id', None) message_state = pdu_opts.get('message_state', None) if receipted_message_id is not None and message_state is not None: yield self.esme_callbacks.delivery_report( message_id=receipted_message_id, message_state={ 1: 'ENROUTE', 2: 'DELIVERED', 3: 'EXPIRED', 4: 'DELETED', 5: 'UNDELIVERABLE', 6: 'ACCEPTED', 7: 'UNKNOWN', 8: 'REJECTED', }.get(message_state, 'UNKNOWN'), ) # We might have a `message_payload` optional field to worry about. message_payload = pdu_opts.get('message_payload', None) if message_payload is not None: pdu_params['short_message'] = message_payload.decode('hex') if detect_ussd(pdu_opts): # We have a USSD message. yield self._handle_deliver_sm_ussd(pdu, pdu_params, pdu_opts) elif detect_multipart(pdu): # We have a multipart SMS. yield self._handle_deliver_sm_multipart(pdu, pdu_params) else: # We have a standard SMS. yield self._handle_deliver_sm_sms(pdu_params)
def handle_deliver_sm_multipart(self, pdu, pdu_params): redis_key = "multi_%s" % (multipart_key(detect_multipart(pdu)),) self.log.debug("Redis multipart key: %s" % (redis_key)) multi = yield self.load_multipart_message(redis_key) multi.add_pdu(pdu) completed = multi.get_completed() if completed: yield self.redis.delete(redis_key) self.log.msg("Reassembled Message: %s" % (completed["message"])) # We assume that all parts have the same data_coding here, because # otherwise there's nothing sensible we can do. decoded_msg = self.dcs_decode(completed["message"], pdu_params["data_coding"]) # and we can finally pass the whole message on yield self.handle_short_message_content( source_addr=completed["from_msisdn"], destination_addr=completed["to_msisdn"], short_message=decoded_msg ) else: yield self.save_multipart_message(redis_key, multi)
def _handle_deliver_sm_multipart(self, pdu, pdu_params): redis_key = "multi_%s" % (multipart_key(detect_multipart(pdu)), ) log.debug("Redis multipart key: %s" % (redis_key)) multi = yield self.load_multipart_message(redis_key) multi.add_pdu(pdu) completed = multi.get_completed() if completed: yield self.redis.delete(redis_key) log.msg("Reassembled Message: %s" % (completed['message'])) # We assume that all parts have the same data_coding here, because # otherwise there's nothing sensible we can do. decoded_msg = self._decode_message(completed['message'], pdu_params['data_coding']) # and we can finally pass the whole message on yield self._deliver_sm(source_addr=completed['from_msisdn'], destination_addr=completed['to_msisdn'], short_message=decoded_msg) else: yield self.save_multipart_message(redis_key, multi)
def get_multipart(m): return detect_multipart(unpack_pdu(m.get_bin()))