Beispiel #1
0
def gotConnection(conn, username, password):
    yield conn.authenticate(username, password)
 
    chan = yield conn.channel(1)
    yield chan.channel_open()


    DeliverSmPDU = DeliverSM( 	source_addr = '584141111330', 
				destination_addr = '24247', 
				short_message = 'Prueba 01 !', 
				seqNum = 1,)

    content = DeliverSmContent(DeliverSmPDU, 'SIMULATOR' )
    
    #print DeliverSmPDU
    
    yield chan.basic_publish(exchange='messaging', routing_key='deliver.sm.SIMULATOR', content=content)

    # A clean way to tear down and stop
    yield chan.channel_close()

    chan0 = yield conn.channel(0)
    yield chan0.connection_close()
    
    reactor.stop()
Beispiel #2
0
    def test_normal_nopickling(self):
        c = DeliverSmContent(self.body, 'connector1', prePickle=False)

        self.assertEquals(c.body, self.body)
        self.assertEquals(c['headers']['connector-id'], 'connector1')
        self.assertEquals(c['headers']['concatenated'], False)
        self.assertFalse(c['message-id'] == None)
Beispiel #3
0
def gotConnection(conn, username, password,src,dest,text):
   yield conn.authenticate(username, password)
   #print 'Connected to RabbitMQ'
 
   chan = yield conn.channel(1)
   yield chan.channel_open()
    
   DeliverSmPDU = DeliverSM( 	source_addr = src, 
  	source_addr_ton = AddrTon.NATIONAL,
  	source_addr_npi = AddrNpi.ISDN,
  	destination_addr = dest, 
  	dest_addr_ton = AddrTon.NATIONAL,
  	dest_addr_npi = AddrNpi.ISDN,
  	esm_class=EsmClass(EsmClassMode.DEFAULT, EsmClassType.DEFAULT),
  	protocol_id=0,
  	priority_flag=PriorityFlag.LEVEL_0,
  	registered_delivery=RegisteredDelivery(RegisteredDeliveryReceipt.NO_SMSC_DELIVERY_RECEIPT_REQUESTED),
  	replace_if_present_flag=ReplaceIfPresentFlag.DO_NOT_REPLACE,
  	short_message = text, 
	seqNum = 1,)

   content = DeliverSmContent(DeliverSmPDU, 'SIMULATOR' )
    
   #print DeliverSmPDU
   yield chan.basic_publish(exchange='messaging', routing_key='deliver.sm.SIMULATOR', content=content)
    
   # A clean way to tear down and stop
   yield chan.channel_close()
    
   chan0 = yield conn.channel(0)
   yield chan0.connection_close()
Beispiel #4
0
    def test_headers_concatenated(self):
        c = DeliverSmContent(self.body,
                             'connector1',
                             prePickle=False,
                             concatenated=True)

        self.assertEquals(c['headers']['concatenated'], True)
        self.assertFalse(c['message-id'] == None)
Beispiel #5
0
    def test_normal_pickling(self):
        c = DeliverSmContent(self.body, 'connector1')

        self.assertNotEquals(c.body, self.body)
        self.assertEquals(c.body, pickle.dumps(self.body, 2))
        self.assertEquals(c['headers']['connector-id'], 'connector1')
        self.assertEquals(c['headers']['concatenated'], False)
        self.assertFalse(c['message-id'] == None)
        self.assertTrue('created_at' in c['headers'])
Beispiel #6
0
    def deliver_sm_event_post_interception(self, *args, **kw):
        """This event is called whenever a deliver_sm pdu is received through a SMPPc
        It will hand the pdu to the router or a dlr thrower (depending if its a DLR or not).

        Note: this event will catch data_sm pdus as well
        """

        try:
            # Control args
            if 'smpp' not in kw or 'routable' not in kw:
                self.log.error(
                    'deliver_sm_event_post_interception missing arguments after interception: %s',
                    kw)
                raise InterceptorRunError(
                    'deliver_sm_event_post_interception missing arguments after interception'
                )

            # Set defaults
            smpp = kw['smpp']
            routable = kw['routable']

            if 'concatenated' in kw:
                concatenated = kw['concatenated']
            else:
                concatenated = False

            # Get message_content
            if 'short_message' in routable.pdu.params and len(
                    routable.pdu.params['short_message']) > 0:
                message_content = routable.pdu.params['short_message']
            elif 'message_payload' in routable.pdu.params:
                message_content = routable.pdu.params['message_payload']
            elif 'short_message' in routable.pdu.params:
                message_content = routable.pdu.params['short_message']
            else:
                message_content = None

            # Post interception:
            if len(args) == 1:
                if isinstance(args[0], bool) and not args[0]:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.error(
                        'Failed running interception script, got a False return.'
                    )
                    raise InterceptorRunError(
                        'Failed running interception script, check log for details'
                    )
                elif isinstance(args[0], dict) and args[0]['smpp_status'] > 0:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.info(
                        'Interceptor script returned %s smpp_status error.',
                        args[0]['smpp_status'])
                    raise DeliverSmInterceptionError(
                        code=args[0]['smpp_status'])
                elif isinstance(args[0], str):
                    smpp.factory.stats.inc('interceptor_count')
                    routable = pickle.loads(args[0])
                else:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.error(
                        'Failed running interception script, got the following return: %s',
                        args[0])
                    raise InterceptorRunError(
                        'Failed running interception script, got the following return: %s'
                        % args[0])

            self.log.debug(
                'Handling deliver_sm_event_post_interception event for smppc: %s',
                self.SMPPClientFactory.config.id)

            routable.pdu.dlr = self.SMPPOperationFactory.isDeliveryReceipt(
                routable.pdu)
            content = DeliverSmContent(routable,
                                       self.SMPPClientFactory.config.id,
                                       pickleProtocol=self.pickleProtocol,
                                       concatenated=concatenated)
            msgid = content.properties['message-id']

            if routable.pdu.dlr is None:
                # We have a SMS-MO

                # UDH is set ?
                UDHI_INDICATOR_SET = False
                if 'esm_class' in routable.pdu.params and hasattr(
                        routable.pdu.params['esm_class'], 'gsmFeatures'):
                    for gsmFeature in routable.pdu.params[
                            'esm_class'].gsmFeatures:
                        if str(gsmFeature) == 'UDHI_INDICATOR_SET':
                            UDHI_INDICATOR_SET = True
                            break

                not_class2 = True
                if 'data_coding' in routable.pdu.params:
                    dcs = routable.pdu.params['data_coding']
                    if (str(dcs.scheme)
                            == 'GSM_MESSAGE_CLASS') and (dcs.schemeData
                                                         is not None):
                        not_class2 = (str(dcs.schemeData.msgClass) !=
                                      'CLASS_2')

                splitMethod = None
                # Is it a part of a long message ?
                if 'sar_msg_ref_num' in routable.pdu.params:
                    splitMethod = 'sar'
                    total_segments = routable.pdu.params['sar_total_segments']
                    segment_seqnum = routable.pdu.params['sar_segment_seqnum']
                    msg_ref_num = routable.pdu.params['sar_msg_ref_num']
                    self.log.debug(
                        'Received SMS-MO part [queue-msgid:%s] using SAR: ttl_segments=%s, segment_sn=%s, msgref=%s',
                        msgid, total_segments, segment_seqnum, msg_ref_num)
                elif UDHI_INDICATOR_SET and not_class2 and message_content[:
                                                                           3] == '\x05\x00\x03':
                    splitMethod = 'udh'
                    total_segments = struct.unpack('!B', message_content[4])[0]
                    segment_seqnum = struct.unpack('!B', message_content[5])[0]
                    msg_ref_num = struct.unpack('!B', message_content[3])[0]
                    self.log.debug(
                        'Received SMS-MO part [queue-msgid:%s] using UDH: ttl_segments=%s, segment_sn=%s, msgref=%s',
                        msgid, total_segments, segment_seqnum, msg_ref_num)

                if splitMethod is None:
                    # It's a simple short message or a part of a concatenated message
                    routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                    self.log.debug(
                        "Publishing DeliverSmContent[%s] with routing_key[%s]",
                        msgid, routing_key)
                    yield self.amqpBroker.publish(exchange='messaging',
                                                  routing_key=routing_key,
                                                  content=content)

                    # Get values from data_sm or deliver_sm
                    priority_flag = None
                    if 'priority_flag' in routable.pdu.params:
                        priority_flag = routable.pdu.params['priority_flag']
                    validity_period = None
                    if 'validity_period' in routable.pdu.params:
                        validity_period = routable.pdu.params[
                            'validity_period']

                    # Do not log text for privacy reasons
                    # Added in #691
                    if self.config.log_privacy:
                        logged_content = '** %s byte content **' % len(
                            message_content)
                    else:
                        logged_content = '%r' % message_content

                    self.log.info(
                        "SMS-MO [cid:%s] [queue-msgid:%s] [status:%s] [prio:%s] [validity:%s] [from:%s] [to:%s] \
[content:%s]", self.SMPPClientFactory.config.id, msgid, routable.pdu.status,
                        priority_flag, validity_period,
                        routable.pdu.params['source_addr'],
                        routable.pdu.params['destination_addr'],
                        logged_content)
                else:
                    # Long message part received
                    if self.redisClient is None:
                        self.log.critical(
                            'Invalid RC found while receiving part of long DeliverSm [queue-msgid:%s], MSG IS LOST !',
                            msgid)
                    else:
                        # Save it to redis
                        hashKey = "longDeliverSm:%s:%s:%s" % (
                            self.SMPPClientFactory.config.id, msg_ref_num,
                            routable.pdu.params['destination_addr'])
                        hashValues = {
                            'pdu': routable.pdu,
                            'total_segments': total_segments,
                            'msg_ref_num': msg_ref_num,
                            'segment_seqnum': segment_seqnum
                        }
                        yield self.redisClient.hset(
                            hashKey, segment_seqnum,
                            pickle.dumps(hashValues,
                                         self.pickleProtocol)).addCallback(
                                             self.concatDeliverSMs, hashKey,
                                             splitMethod, total_segments,
                                             msg_ref_num, segment_seqnum)

                        self.log.info(
                            "DeliverSmContent[%s] is part of long msg of (%s), will be enqueued after concatenation.",
                            msgid, total_segments)

                        # Flag it as "will_be_concatenated" and publish it to router
                        routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                        self.log.debug(
                            "Publishing DeliverSmContent[%s](flagged:wbc) with routing_key[%s]",
                            msgid, routing_key)
                        content.properties['headers'][
                            'will_be_concatenated'] = True
                        yield self.amqpBroker.publish(exchange='messaging',
                                                      routing_key=routing_key,
                                                      content=content)
            else:
                # This is a DLR !
                # Send DLR to DLRLookup
                yield self.amqpBroker.publish(
                    exchange='messaging',
                    routing_key='dlr.deliver_sm',
                    content=DLR(pdu_type=routable.pdu.id,
                                msgid=self.code_dlr_msgid(routable.pdu),
                                status=routable.pdu.dlr['stat'],
                                cid=self.SMPPClientFactory.config.id,
                                dlr_details=routable.pdu.dlr))
        except (InterceptorRunError, DeliverSmInterceptionError) as e:
            # Do not log text for privacy reasons
            # Added in #691
            if self.config.log_privacy:
                logged_content = '** %s byte content **' % len(message_content)
            else:
                logged_content = '%r' % message_content

            self.log.info(
                "SMS-MO [cid:%s] [i-status:%s] [from:%s] [to:%s] [content:%s]",
                self.SMPPClientFactory.config.id, e.status,
                routable.pdu.params['source_addr'],
                routable.pdu.params['destination_addr'], logged_content)

            # Known exception handling
            defer.returnValue(DataHandlerResponse(status=e.status))
        except Exception as e:
            # Unknown exception handling
            self.log.critical('Got an unknown exception (%s): %s', type(e), e)
            defer.returnValue(
                DataHandlerResponse(status=CommandStatus.ESME_RUNKNOWNERR))
Beispiel #7
0
    def deliver_sm_event_post_interception(self, *args, **kw):
        """This event is called whenever a deliver_sm pdu is received through a SMPPc
        It will hand the pdu to the router or a dlr thrower (depending if its a DLR or not).

        Note: this event will catch data_sm pdus as well
        """

        try:
            # Control args
            if 'smpp' not in kw or 'pdu' not in kw:
                self.log.error(
                    'deliver_sm_event_post_interception missing arguments after interception: %s', kw)
                raise InterceptorRunError(
                    'deliver_sm_event_post_interception missing arguments after interception')

            # Set defaults
            smpp = kw['smpp']
            pdu = kw['pdu']
            if 'concatenated' in kw:
                concatenated = kw['concatenated']
            else:
                concatenated = False

            # Get message_content
            if 'short_message' in pdu.params:
                message_content = pdu.params['short_message']
            elif 'message_payload' in pdu.params:
                message_content = pdu.params['message_payload']
            else:
                message_content = None

            # Post interception:
            if len(args) == 1:
                if isinstance(args[0], bool) and not args[0]:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.error('Failed running interception script, got a False return.')
                    raise InterceptorRunError('Failed running interception script, check log for details')
                elif isinstance(args[0], dict) and args[0]['smpp_status'] > 0:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.info(
                        'Interceptor script returned %s smpp_status error.', args[0]['smpp_status'])
                    raise DeliverSmInterceptionError(code=args[0]['smpp_status'])
                elif isinstance(args[0], str):
                    smpp.factory.stats.inc('interceptor_count')
                    temp_routable = pickle.loads(args[0])
                    pdu = temp_routable.pdu
                else:
                    smpp.factory.stats.inc('interceptor_error_count')
                    self.log.error(
                        'Failed running interception script, got the following return: %s', args[0])
                    raise InterceptorRunError(
                        'Failed running interception script, got the following return: %s', args[0])

            self.log.debug('Handling deliver_sm_event_post_interception event for smppc: %s',
                           self.SMPPClientFactory.config.id)

            pdu.dlr = self.SMPPOperationFactory.isDeliveryReceipt(pdu)
            content = DeliverSmContent(pdu,
                                       self.SMPPClientFactory.config.id,
                                       pickleProtocol=self.pickleProtocol,
                                       concatenated=concatenated)
            msgid = content.properties['message-id']

            if pdu.dlr is None:
                # We have a SMS-MO

                # UDH is set ?
                UDHI_INDICATOR_SET = False
                if 'esm_class' in pdu.params and hasattr(pdu.params['esm_class'], 'gsmFeatures'):
                    for gsmFeature in pdu.params['esm_class'].gsmFeatures:
                        if str(gsmFeature) == 'UDHI_INDICATOR_SET':
                            UDHI_INDICATOR_SET = True
                            break

                splitMethod = None
                # Is it a part of a long message ?
                if 'sar_msg_ref_num' in pdu.params:
                    splitMethod = 'sar'
                    total_segments = pdu.params['sar_total_segments']
                    segment_seqnum = pdu.params['sar_segment_seqnum']
                    msg_ref_num = pdu.params['sar_msg_ref_num']
                    self.log.debug('Received a part of SMS-MO [queue-msgid:%s] using SAR options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s',
                                   msgid, total_segments, segment_seqnum, msg_ref_num)
                elif UDHI_INDICATOR_SET and message_content[:3] == '\x05\x00\x03':
                    splitMethod = 'udh'
                    total_segments = struct.unpack('!B', message_content[4])[0]
                    segment_seqnum = struct.unpack('!B', message_content[5])[0]
                    msg_ref_num = struct.unpack('!B', message_content[3])[0]
                    self.log.debug('Received a part of SMS-MO [queue-msgid:%s] using UDH options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s',
                                   msgid, total_segments, segment_seqnum, msg_ref_num)

                if splitMethod is None:
                    # It's a simple short message or a part of a concatenated message
                    routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                    self.log.debug("Publishing DeliverSmContent[%s] with routing_key[%s]", msgid, routing_key)
                    yield self.amqpBroker.publish(exchange='messaging', routing_key=routing_key, content=content)

                    # Get values from data_sm or deliver_sm
                    priority_flag = None
                    if 'priority_flag' in pdu.params:
                        priority_flag = pdu.params['priority_flag']
                    validity_period = None
                    if 'validity_period' in pdu.params:
                        validity_period = pdu.params['validity_period']

                    self.log.info("SMS-MO [cid:%s] [queue-msgid:%s] [status:%s] [prio:%s] [validity:%s] [from:%s] [to:%s] [content:%s]",
                                  self.SMPPClientFactory.config.id,
                                  msgid,
                                  pdu.status,
                                  priority_flag,
                                  validity_period,
                                  pdu.params['source_addr'],
                                  pdu.params['destination_addr'],
                                  re.sub(r'[^\x20-\x7E]+', '.', message_content))
                else:
                    # Long message part received
                    if self.redisClient is None:
                        self.warn('No valid RC were found while receiving a part of a long DeliverSm [queue-msgid:%s], MESSAGE IS LOST !',
                                  msgid)

                    # Save it to redis
                    hashKey = "longDeliverSm:%s" % (msg_ref_num)
                    hashValues = {'pdu': pdu,
                                  'total_segments':total_segments,
                                  'msg_ref_num':msg_ref_num,
                                  'segment_seqnum':segment_seqnum}
                    yield self.redisClient.hset(
                        hashKey, segment_seqnum, pickle.dumps(hashValues, self.pickleProtocol)).addCallback(
                            self.concatDeliverSMs,
                            splitMethod,
                            total_segments,
                            msg_ref_num,
                            segment_seqnum)

                    self.log.info("DeliverSmContent[%s] is a part of a long message of %s parts, will be sent to queue after concatenation.",
                                  msgid, total_segments)

                    # Flag it as "will_be_concatenated" and publish it to router
                    routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                    self.log.debug("Publishing DeliverSmContent[%s](flagged:wbc) with routing_key[%s]",
                                   msgid, routing_key)
                    content.properties['headers']['will_be_concatenated'] = True
                    yield self.amqpBroker.publish(exchange='messaging', routing_key=routing_key, content=content)
            else:
                # This is a DLR !
                # Check for DLR request
                if self.redisClient is not None:
                    _coded_dlr_id = self.code_dlr_msgid(pdu)

                    q = yield self.redisClient.get("queue-msgid:%s" % _coded_dlr_id)
                    submit_sm_queue_id = None
                    connector_type = None
                    if q is not None:
                        q = pickle.loads(q)
                        submit_sm_queue_id = q['msgid']
                        connector_type = q['connector_type']


                    if submit_sm_queue_id is not None and connector_type == 'httpapi':
                        pickledDlr = yield self.redisClient.get("dlr:%s" % submit_sm_queue_id)

                        if pickledDlr is not None:
                            dlr = pickle.loads(pickledDlr)
                            dlr_url = dlr['url']
                            dlr_level = dlr['level']
                            dlr_method = dlr['method']

                            if dlr_level in [2, 3]:
                                self.log.debug('Got DLR information for msgid[%s], url:%s, level:%s',
                                               submit_sm_queue_id, dlr_url, dlr_level)
                                # The dlr_url in DLRContentForHttpapi indicates the level
                                # of the actual delivery receipt (2) and not the
                                # requested one (maybe 2 or 3)
                                content = DLRContentForHttpapi(pdu.dlr['stat'], submit_sm_queue_id,
                                                               dlr_url, dlr_level=2, id_smsc=_coded_dlr_id,
                                                               sub=pdu.dlr['sub'], dlvrd=pdu.dlr['dlvrd'],
                                                               subdate=pdu.dlr['sdate'],
                                                               donedate=pdu.dlr['ddate'], err=pdu.dlr['err'],
                                                               text=pdu.dlr['text'], method=dlr_method)
                                routing_key = 'dlr_thrower.http'
                                self.log.debug("Publishing DLRContentForHttpapi[%s] with routing_key[%s]",
                                               submit_sm_queue_id, routing_key)
                                yield self.amqpBroker.publish(exchange='messaging',
                                                              routing_key=routing_key,
                                                              content=content)

                                self.log.debug('Removing DLR request for msgid[%s]', submit_sm_queue_id)
                                yield self.redisClient.delete('dlr:%s' % submit_sm_queue_id)
                            else:
                                self.log.debug('SMS-C receipt is requested, will not send any DLR receipt at this level.')
                        else:
                            self.log.warn('DLR for msgid[%s] not found !',
                                          submit_sm_queue_id)
                    elif submit_sm_queue_id is not None and connector_type == 'smpps':
                        pickledSmppsMap = yield self.redisClient.get("smppsmap:%s" % submit_sm_queue_id)

                        if pickledSmppsMap is not None:
                            smpps_map = pickle.loads(pickledSmppsMap)
                            system_id = smpps_map['system_id']
                            source_addr = smpps_map['source_addr']
                            destination_addr = smpps_map['destination_addr']
                            sub_date = smpps_map['sub_date']
                            registered_delivery = smpps_map['registered_delivery']

                            success_states = ['ACCEPTD', 'DELIVRD']
                            final_states = ['DELIVRD', 'EXPIRED', 'DELETED', 'UNDELIV', 'REJECTD']
                            # Do we need to forward the receipt to the original sender ?
                            if ((pdu.dlr['stat'] in success_states and
                                    str(registered_delivery.receipt) == 'SMSC_DELIVERY_RECEIPT_REQUESTED') or
                                    (pdu.dlr['stat'] not in success_states and
                                    str(registered_delivery.receipt) in ['SMSC_DELIVERY_RECEIPT_REQUESTED',
                                                                         'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE'])):
                                self.log.debug(
                                    'Got DLR information for msgid[%s], registered_deliver%s, system_id:%s',
                                    submit_sm_queue_id, registered_delivery, system_id)

                                content = DLRContentForSmpps(pdu.dlr['stat'], submit_sm_queue_id, system_id,
                                                             source_addr, destination_addr, sub_date)

                                routing_key = 'dlr_thrower.smpps'
                                self.log.debug("Publishing DLRContentForSmpps[%s] with routing_key[%s]",
                                               submit_sm_queue_id, routing_key)
                                yield self.amqpBroker.publish(exchange='messaging',
                                                              routing_key=routing_key,
                                                              content=content)

                                if pdu.dlr['stat'] in final_states:
                                    self.log.debug('Removing SMPPs map for msgid[%s]', submit_sm_queue_id)
                                    yield self.redisClient.delete('smppsmap:%s' % submit_sm_queue_id)
                    else:
                        self.log.warn('Got a DLR for an unknown message id: %s (coded:%s)',
                                      pdu.dlr['id'], _coded_dlr_id)
                else:
                    self.log.warn('DLR for msgid[%s] is not checked, no valid RC were found', msgid)

                self.log.info("DLR [cid:%s] [smpp-msgid:%s] [status:%s] [submit date:%s] [done date:%s] [sub/dlvrd messages:%s/%s] [err:%s] [content:%s]",
                              self.SMPPClientFactory.config.id,
                              _coded_dlr_id,
                              pdu.dlr['stat'],
                              pdu.dlr['sdate'],
                              pdu.dlr['ddate'],
                              pdu.dlr['sub'],
                              pdu.dlr['dlvrd'],
                              pdu.dlr['err'],
                              pdu.dlr['text'])
        except (InterceptorRunError, DeliverSmInterceptionError) as e:
            self.log.info("SMS-MO [cid:%s] [istatus:%s] [from:%s] [to:%s] [content:%s]",
                          self.SMPPClientFactory.config.id,
                          e.status,
                          pdu.params['source_addr'],
                          pdu.params['destination_addr'],
                          re.sub(r'[^\x20-\x7E]+', '.', message_content))

            # Known exception handling
            defer.returnValue(DataHandlerResponse(status=e.status))
        except Exception, e:
            # Unknown exception handling
            self.log.critical('Got an unknown exception: %s', e)
            defer.returnValue(DataHandlerResponse(status=CommandStatus.ESME_RUNKNOWNERR))
Beispiel #8
0
    def deliver_sm_event(self, smpp, pdu, concatenated=False):
        """This event is called whenever a deliver_sm pdu is received through a SMPPc
        It will hand the pdu to the router or a dlr thrower (depending if its a DLR or not).
        
        Note: this event will catch data_sm pdus as well
        """

        pdu.dlr = self.SMPPOperationFactory.isDeliveryReceipt(pdu)
        content = DeliverSmContent(pdu,
                                   self.SMPPClientFactory.config.id,
                                   pickleProtocol=self.pickleProtocol,
                                   concatenated=concatenated)
        msgid = content.properties['message-id']

        if pdu.dlr is None:
            # We have a SMS-MO

            # UDH is set ?
            UDHI_INDICATOR_SET = False
            if hasattr(pdu.params['esm_class'], 'gsmFeatures'):
                for gsmFeature in pdu.params['esm_class'].gsmFeatures:
                    if str(gsmFeature) == 'UDHI_INDICATOR_SET':
                        UDHI_INDICATOR_SET = True
                        break

            splitMethod = None
            # Is it a part of a long message ?
            if 'sar_msg_ref_num' in pdu.params:
                splitMethod = 'sar'
                total_segments = pdu.params['sar_total_segments']
                segment_seqnum = pdu.params['sar_segment_seqnum']
                msg_ref_num = pdu.params['sar_msg_ref_num']
                self.log.debug(
                    'Received a part of SMS-MO [queue-msgid:%s] using SAR options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s'
                    % (msgid, total_segments, segment_seqnum, msg_ref_num))
            elif UDHI_INDICATOR_SET and pdu.params[
                    'short_message'][:3] == '\x05\x00\x03':
                splitMethod = 'udh'
                total_segments = struct.unpack(
                    '!B', pdu.params['short_message'][4])[0]
                segment_seqnum = struct.unpack(
                    '!B', pdu.params['short_message'][5])[0]
                msg_ref_num = struct.unpack('!B',
                                            pdu.params['short_message'][3])[0]
                self.log.debug(
                    'Received a part of SMS-MO [queue-msgid:%s] using UDH options: total_segments=%s, segmen_seqnum=%s, msg_ref_num=%s'
                    % (msgid, total_segments, segment_seqnum, msg_ref_num))

            if splitMethod is None:
                # It's a simple short message or a part of a concatenated message
                routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                self.log.debug(
                    "Publishing DeliverSmContent[%s] with routing_key[%s]" %
                    (msgid, routing_key))
                yield self.amqpBroker.publish(exchange='messaging',
                                              routing_key=routing_key,
                                              content=content)

                self.log.info(
                    "SMS-MO [cid:%s] [queue-msgid:%s] [status:%s] [prio:%s] [validity:%s] [from:%s] [to:%s] [content:%s]"
                    %
                    (self.SMPPClientFactory.config.id, msgid, pdu.status,
                     pdu.params['priority_flag'],
                     pdu.params['validity_period'], pdu.params['source_addr'],
                     pdu.params['destination_addr'],
                     re.sub(r'[^\x20-\x7E]+', '.',
                            pdu.params['short_message'])))
            else:
                # Long message part received
                if self.redisClient is None:
                    self.warn(
                        'No valid RC were found while receiving a part of a long DeliverSm [queue-msgid:%s], MESSAGE IS LOST !'
                        % msgid)

                # Save it to redis
                hashKey = "longDeliverSm:%s" % (msg_ref_num)
                hashValues = {
                    'pdu': pdu,
                    'total_segments': total_segments,
                    'msg_ref_num': msg_ref_num,
                    'segment_seqnum': segment_seqnum
                }
                self.redisClient.hset(
                    hashKey, segment_seqnum,
                    pickle.dumps(hashValues, self.pickleProtocol)).addCallback(
                        self.concatDeliverSMs, splitMethod, total_segments,
                        msg_ref_num, segment_seqnum)

                self.log.info(
                    "DeliverSmContent[%s] is a part of a long message of %s parts, will be sent to queue after concatenation."
                    % (msgid, total_segments))

                # Flag it as "will_be_concatenated" and publish it to router
                routing_key = 'deliver.sm.%s' % self.SMPPClientFactory.config.id
                self.log.debug(
                    "Publishing DeliverSmContent[%s](flagged:wbc) with routing_key[%s]"
                    % (msgid, routing_key))
                content.properties['headers']['will_be_concatenated'] = True
                yield self.amqpBroker.publish(exchange='messaging',
                                              routing_key=routing_key,
                                              content=content)
        else:
            # This is a DLR !
            # Check for DLR request
            if self.redisClient is not None:
                _coded_dlr_id = self.code_dlr_msgid(pdu)

                q = yield self.redisClient.get("queue-msgid:%s" %
                                               _coded_dlr_id)
                submit_sm_queue_id = None
                connector_type = None
                if q is not None:
                    q = pickle.loads(q)
                    submit_sm_queue_id = q['msgid']
                    connector_type = q['connector_type']

                if submit_sm_queue_id is not None and connector_type == 'httpapi':
                    pickledDlr = yield self.redisClient.get("dlr:%s" %
                                                            submit_sm_queue_id)

                    if pickledDlr is not None:
                        dlr = pickle.loads(pickledDlr)
                        dlr_url = dlr['url']
                        dlr_level = dlr['level']
                        dlr_method = dlr['method']

                        if dlr_level in [2, 3]:
                            self.log.debug(
                                'Got DLR information for msgid[%s], url:%s, level:%s'
                                % (submit_sm_queue_id, dlr_url, dlr_level))
                            content = DLRContentForHttpapi(
                                pdu.dlr['stat'],
                                submit_sm_queue_id,
                                dlr_url,
                                # The dlr_url in DLRContentForHttpapi indicates the level
                                # of the actual delivery receipt (2) and not the
                                # requested one (maybe 2 or 3)
                                dlr_level=2,
                                id_smsc=_coded_dlr_id,
                                sub=pdu.dlr['sub'],
                                dlvrd=pdu.dlr['dlvrd'],
                                subdate=pdu.dlr['sdate'],
                                donedate=pdu.dlr['ddate'],
                                err=pdu.dlr['err'],
                                text=pdu.dlr['text'],
                                method=dlr_method)
                            routing_key = 'dlr_thrower.http'
                            self.log.debug(
                                "Publishing DLRContentForHttpapi[%s] with routing_key[%s]"
                                % (submit_sm_queue_id, routing_key))
                            yield self.amqpBroker.publish(
                                exchange='messaging',
                                routing_key=routing_key,
                                content=content)

                            self.log.debug(
                                'Removing DLR request for msgid[%s]' %
                                submit_sm_queue_id)
                            yield self.redisClient.delete('dlr:%s' %
                                                          submit_sm_queue_id)
                        else:
                            self.log.debug(
                                'SMS-C receipt is requested, will not send any DLR receipt at this level.'
                            )
                    else:
                        self.log.warn('DLR for msgid[%s] not found !' %
                                      (submit_sm_queue_id))
                elif submit_sm_queue_id is not None and connector_type == 'smpps':
                    pickledSmppsMap = yield self.redisClient.get(
                        "smppsmap:%s" % submit_sm_queue_id)

                    if pickledSmppsMap is not None:
                        smpps_map = pickle.loads(pickledSmppsMap)
                        system_id = smpps_map['system_id']
                        source_addr = smpps_map['source_addr']
                        destination_addr = smpps_map['destination_addr']
                        sub_date = smpps_map['sub_date']
                        registered_delivery = smpps_map['registered_delivery']
                        smpps_map_expiry = smpps_map['expiry']

                        success_states = ['ACCEPTD', 'DELIVRD']
                        final_states = [
                            'DELIVRD', 'EXPIRED', 'DELETED', 'UNDELIV',
                            'REJECTD'
                        ]
                        # Do we need to forward the receipt to the original sender ?
                        if ((pdu.dlr['stat'] in success_states
                             and str(registered_delivery.receipt)
                             == 'SMSC_DELIVERY_RECEIPT_REQUESTED') or
                            (pdu.dlr['stat'] not in success_states
                             and str(registered_delivery.receipt) in [
                                 'SMSC_DELIVERY_RECEIPT_REQUESTED',
                                 'SMSC_DELIVERY_RECEIPT_REQUESTED_FOR_FAILURE'
                             ])):

                            self.log.debug(
                                'Got DLR information for msgid[%s], registered_deliver%s, system_id:%s'
                                % (submit_sm_queue_id, registered_delivery,
                                   system_id))
                            content = DLRContentForSmpps(
                                pdu.dlr['stat'], submit_sm_queue_id, system_id,
                                source_addr, destination_addr, sub_date)

                            routing_key = 'dlr_thrower.smpps'
                            self.log.debug(
                                "Publishing DLRContentForSmpps[%s] with routing_key[%s]"
                                % (submit_sm_queue_id, routing_key))
                            yield self.amqpBroker.publish(
                                exchange='messaging',
                                routing_key=routing_key,
                                content=content)

                            if pdu.dlr['stat'] in final_states:
                                self.log.debug(
                                    'Removing SMPPs map for msgid[%s]' %
                                    submit_sm_queue_id)
                                yield self.redisClient.delete(
                                    'smppsmap:%s' % submit_sm_queue_id)
                else:
                    self.log.warn(
                        'Got a DLR for an unknown message id: %s (coded:%s)' %
                        (pdu.dlr['id'], _coded_dlr_id))
            else:
                self.log.warn(
                    'DLR for msgid[%s] is not checked, no valid RC were found'
                    % msgid)

            self.log.info(
                "DLR [cid:%s] [smpp-msgid:%s] [status:%s] [submit date:%s] [done date:%s] [sub/dlvrd messages:%s/%s] [err:%s] [content:%s]"
                % (
                    self.SMPPClientFactory.config.id,
                    _coded_dlr_id,
                    pdu.dlr['stat'],
                    pdu.dlr['sdate'],
                    pdu.dlr['ddate'],
                    pdu.dlr['sub'],
                    pdu.dlr['dlvrd'],
                    pdu.dlr['err'],
                    pdu.dlr['text'],
                ))
Beispiel #9
0
    dest_addr_npi=submit_sm.params['dest_addr_npi'],
    destination_addr=submit_sm.params['destination_addr'],
    esm_class=submit_sm.params['esm_class'],
    protocol_id=submit_sm.params['protocol_id'],
    priority_flag=submit_sm.params['priority_flag'],
    registered_delivery=submit_sm.params['registered_delivery'],
    replace_if_present_flag=submit_sm.params['replace_if_present_flag'],
    data_coding=submit_sm.params['data_coding'],
    short_message=submit_sm.params['short_message'],
    sm_default_msg_id=submit_sm.params['sm_default_msg_id'])
logger.debug("Prepared a new deliver_sm: %s", deliver_sm)

# Prepare for deliver_sm injection
_routable = RoutableDeliverSm(deliver_sm, Connector(routable.user.uid))
content = DeliverSmContent(_routable,
                           routable.user.uid,
                           pickleProtocol=pickle.HIGHEST_PROTOCOL)
routing_key = 'deliver.sm.%s' % routable.user.uid

# Connecto RabbitMQ and publish deliver_sm
logger.debug('Init pika and publish..')
connection = pika.BlockingConnection(pika.URLParameters(RABBITMQ_URL))
channel = connection.channel()
logger.debug('RabbitMQ channel ready, publishing now msgid %s ...',
             content.properties['message-id'])
channel.basic_publish(
    'messaging', routing_key, content.body,
    pika.BasicProperties(message_id=content.properties['message-id'],
                         headers=content.properties['headers']))
logger.debug('Published deliver_sm to %s', routing_key)