Esempio n. 1
0
class DLRThrower(Thrower):
    name = 'DLRThrower'

    def __init__(self, config):
        self.log_category = "jasmin-dlr-thrower"
        self.exchangeName = 'messaging'
        self.consumerTag = 'DLRThrower'
        self.routingKey = 'dlr_thrower.*'
        self.queueName = 'dlr_thrower'
        self.callback = self.dlr_throwing_callback
        self.opFactory = SMPPOperationFactory()

        Thrower.__init__(self, config)

    @defer.inlineCallbacks
    def http_dlr_callback(self, message):
        msgid = message.content.properties['message-id']
        url = message.content.properties['headers']['url']
        method = message.content.properties['headers']['method']
        level = message.content.properties['headers']['level']
        self.log.debug('Got one message (msgid:%s) to throw', msgid)

        # If any, clear requeuing timer
        self.clearRequeueTimer(msgid)

        # Build mandatory arguments
        args = {
            'id':
            msgid,
            'level':
            level,
            'message_status':
            message.content.properties['headers']['message_status']
        }

        # Level 2 extra args
        if level in [2, 3]:
            args['id_smsc'] = message.content.properties['headers']['id_smsc']
            args['sub'] = message.content.properties['headers']['sub']
            args['dlvrd'] = message.content.properties['headers']['dlvrd']
            args['subdate'] = message.content.properties['headers']['subdate']
            args['donedate'] = message.content.properties['headers'][
                'donedate']
            args['err'] = message.content.properties['headers']['err']
            args['text'] = message.content.properties['headers']['text']

        try:
            # Throw the message to http endpoint
            encodedArgs = urllib.urlencode(args)
            postdata = None
            baseurl = url
            if method == 'GET':
                baseurl += '?%s' % encodedArgs
            else:
                postdata = encodedArgs

            self.log.debug('Calling %s with args %s using %s method.', baseurl,
                           encodedArgs, method)
            content = yield getPage(baseurl,
                                    method=method,
                                    postdata=postdata,
                                    timeout=self.config.timeout,
                                    agent='Jasmin gateway/1.0 %s' % self.name,
                                    headers={
                                        'Content-Type':
                                        'application/x-www-form-urlencoded',
                                        'Accept': 'text/plain'
                                    })
            self.log.info('Throwed DLR [msgid:%s] to %s.', msgid, baseurl)

            self.log.debug('Destination end replied to message [msgid:%s]: %r',
                           msgid, content)
            # Check for acknowledgement
            if content.strip() != 'ACK/Jasmin':
                raise MessageAcknowledgementError(
                    'Destination end did not acknowledge receipt of the DLR message.'
                )

            # Everything is okay ? then:
            yield self.ackMessage(message)
        except Exception as e:
            self.log.error('Throwing HTTP/DLR [msgid:%s] to (%s): %r.', msgid,
                           baseurl, e)

            # List of errors after which, no further retrying shall be made
            noRetryErrors = ['404 Not Found']

            # Requeue message for later retry
            if (str(e) not in noRetryErrors
                    and self.getThrowingRetrials(message) <=
                    self.config.max_retries):
                self.log.debug('Message try-count is %s [msgid:%s]: requeuing',
                               self.getThrowingRetrials(message), msgid)
                yield self.rejectAndRequeueMessage(message)
            elif str(e) in noRetryErrors:
                self.log.warn(
                    'Message is no more processed after receiving "%s" error',
                    str(e))
                yield self.rejectMessage(message)
            else:
                self.log.warn(
                    'Message try-count is %s [msgid:%s]: purged from queue',
                    self.getThrowingRetrials(message), msgid)
                yield self.rejectMessage(message)

    @defer.inlineCallbacks
    def smpp_dlr_callback(self, message):
        msgid = message.content.properties['message-id']
        system_id = message.content.properties['headers']['system_id']
        message_status = message.content.properties['headers'][
            'message_status']
        source_addr = '%s' % message.content.properties['headers'][
            'source_addr']
        destination_addr = '%s' % message.content.properties['headers'][
            'destination_addr']
        sub_date = message.content.properties['headers']['sub_date']
        source_addr_ton = message.content.properties['headers'][
            'source_addr_ton']
        source_addr_npi = message.content.properties['headers'][
            'source_addr_npi']
        dest_addr_ton = message.content.properties['headers']['dest_addr_ton']
        dest_addr_npi = message.content.properties['headers']['dest_addr_npi']
        self.log.debug('Got one message (msgid:%s) to throw', msgid)

        # If any, clear requeuing timer
        self.clearRequeueTimer(msgid)

        try:
            if self.smpps is None or self.smpps_access is None:
                raise SmppsNotSetError()

            # Get bound connections (or systemids)
            if self.smpps_access == 'direct':
                bound_systemdids = self.smpps.bound_connections
            else:
                bound_systemdids = yield self.smpps.list_bound_systemids()

            if system_id not in bound_systemdids:
                raise SystemIdNotBound(system_id)

            # Build the Receipt PDU (data_sm)
            pdu = self.opFactory.getReceipt(dlr_pdu=self.config.dlr_pdu,
                                            msgid=msgid,
                                            source_addr=source_addr,
                                            destination_addr=destination_addr,
                                            message_status=message_status,
                                            sub_date=sub_date,
                                            source_addr_ton=source_addr_ton,
                                            source_addr_npi=source_addr_npi,
                                            dest_addr_ton=dest_addr_ton,
                                            dest_addr_npi=dest_addr_npi)

            # Pick a deliverer and sendRequest
            if self.smpps_access == 'direct':
                deliverer = bound_systemdids[
                    system_id].getNextBindingForDelivery()

                if deliverer is None:
                    raise NoDelivererForSystemId(system_id)

                yield deliverer.sendRequest(
                    pdu,
                    deliverer.config().responseTimerSecs)
            else:
                r = yield self.smpps.deliverer_send_request(system_id, pdu)
                if not r:
                    raise DeliveringFailed(
                        'Delivering failed, check %s smpps logs for more details'
                        % system_id)
        except Exception as e:
            self.log.error('Throwing SMPP/DLR [msgid:%s] to (%s): %r.', msgid,
                           system_id, e)

            # List of exceptions after which, no further retrying shall be made
            noRetryExceptions = [SmppsNotSetError]

            retry = True
            for noRetryException in noRetryExceptions:
                if isinstance(e, noRetryException):
                    retry = False
                    break

            # Requeue message for later retry
            if retry and self.getThrowingRetrials(
                    message) <= self.config.max_retries:
                self.log.debug('Message try-count is %s [msgid:%s]: requeuing',
                               self.getThrowingRetrials(message), msgid)
                yield self.rejectAndRequeueMessage(message)
            elif retry and self.getThrowingRetrials(
                    message) > self.config.max_retries:
                self.log.warn(
                    'Message is no more processed after receiving "%s" error',
                    str(e))
                yield self.rejectMessage(message)
            else:
                self.log.warn(
                    'Message try-count is %s [msgid:%s]: purged from queue',
                    self.getThrowingRetrials(message), msgid)
                yield self.rejectMessage(message)
        else:
            # Everything is okay ? then:
            yield self.ackMessage(message)

    @defer.inlineCallbacks
    def dlr_throwing_callback(self, message):
        Thrower.throwing_callback(self, message)

        if message.routing_key == 'dlr_thrower.http':
            yield self.http_dlr_callback(message)
        elif message.routing_key == 'dlr_thrower.smpps':
            yield self.smpp_dlr_callback(message)
        else:
            self.log.error('Unknown routing_key in dlr_throwing_callback: %s',
                           message.routing_key)
            yield self.rejectMessage(message)
Esempio n. 2
0
class DLRThrower(Thrower):
    name = 'DLRThrower'

    def __init__(self, config):
        self.log_category = "jasmin-dlr-thrower"
        self.exchangeName = 'messaging'
        self.consumerTag = 'DLRThrower'
        self.routingKey = 'dlr_thrower.*'
        self.queueName = 'dlr_thrower'
        self.callback = self.dlr_throwing_callback
        self.opFactory = SMPPOperationFactory()

        Thrower.__init__(self, config)

    @defer.inlineCallbacks
    def http_dlr_callback(self, message):
        msgid = message.content.properties['message-id']
        url = message.content.properties['headers']['url']
        method = message.content.properties['headers']['method']
        level = message.content.properties['headers']['level']
        self.log.debug('Got one message (msgid:%s) to throw', msgid)

        # If any, clear requeuing timer
        self.clearRequeueTimer(msgid)

        # Build mandatory arguments
        args = {'id': msgid, 'level': level,
                'message_status': message.content.properties['headers']['message_status']}

        # Level 2 extra args
        if level in [2, 3]:
            args['id_smsc'] = message.content.properties['headers']['id_smsc']
            args['sub'] = message.content.properties['headers']['sub']
            args['dlvrd'] = message.content.properties['headers']['dlvrd']
            args['subdate'] = message.content.properties['headers']['subdate']
            args['donedate'] = message.content.properties['headers']['donedate']
            args['err'] = message.content.properties['headers']['err']
            args['text'] = message.content.properties['headers']['text']

        try:
            # Throw the message to http endpoint
            encodedArgs = urllib.urlencode(args)
            postdata = None
            baseurl = url
            if method == 'GET':
                baseurl += '?%s' % encodedArgs
            else:
                postdata = encodedArgs

            self.log.debug('Calling %s with args %s using %s method.', baseurl, encodedArgs, method)
            if '127.0.0.1' not in baseurl:
                content = yield getPage(
                    baseurl,
                    method=method,
                    postdata=postdata,
                    timeout=self.config.timeout,
                    agent='Jasmin gateway/1.0 %s' % self.name,
                    headers={'Content-Type': 'application/x-www-form-urlencoded',
                             'Accept': 'text/plain'})
            else:
                content = 'ACK/Jasmin'
            self.log.info('Throwed DLR [msgid:%s] to %s.', msgid, baseurl)

            self.log.debug('Destination end replied to message [msgid:%s]: %r', msgid, content)
            # Check for acknowledgement
            if content.strip() != 'ACK/Jasmin':
                raise MessageAcknowledgementError(
                    'Destination end did not acknowledge receipt of the DLR message.')

            # Everything is okay ? then:
            yield self.ackMessage(message)
        except Exception as e:
            self.log.error('Throwing HTTP/DLR [msgid:%s] to (%s): %r.', msgid, baseurl, e)

            # List of errors after which, no further retrying shall be made
            noRetryErrors = ['404 Not Found']

            # Requeue message for later retry
            if (str(e) not in noRetryErrors
                and self.getThrowingRetrials(message) <= self.config.max_retries):
                self.log.debug('Message try-count is %s [msgid:%s]: requeuing',
                               self.getThrowingRetrials(message), msgid)
                yield self.rejectAndRequeueMessage(message)
            elif str(e) in noRetryErrors:
                self.log.warn('Message is no more processed after receiving "%s" error', str(e))
                yield self.rejectMessage(message)
            else:
                self.log.warn('Message try-count is %s [msgid:%s]: purged from queue',
                              self.getThrowingRetrials(message), msgid)
                yield self.rejectMessage(message)

    @defer.inlineCallbacks
    def smpp_dlr_callback(self, message):
        msgid = message.content.properties['message-id']
        system_id = message.content.properties['headers']['system_id']
        message_status = message.content.properties['headers']['message_status']
        source_addr = '%s' % message.content.properties['headers']['source_addr']
        destination_addr = '%s' % message.content.properties['headers']['destination_addr']
        sub_date = message.content.properties['headers']['sub_date']
        source_addr_ton = message.content.properties['headers']['source_addr_ton']
        source_addr_npi = message.content.properties['headers']['source_addr_npi']
        dest_addr_ton = message.content.properties['headers']['dest_addr_ton']
        dest_addr_npi = message.content.properties['headers']['dest_addr_npi']
        self.log.debug('Got one message (msgid:%s) to throw', msgid)

        # If any, clear requeuing timer
        self.clearRequeueTimer(msgid)

        try:
            if self.smpps is None or self.smpps_access is None:
                raise SmppsNotSetError()

            # Get bound connections (or systemids)
            if self.smpps_access == 'direct':
                bound_systemdids = self.smpps.bound_connections
            else:
                bound_systemdids = yield self.smpps.list_bound_systemids()

            if system_id not in bound_systemdids:
                raise SystemIdNotBound(system_id)

            # Build the Receipt PDU (data_sm)
            pdu = self.opFactory.getReceipt(dlr_pdu=self.config.dlr_pdu,
                                            msgid=msgid,
                                            source_addr=source_addr,
                                            destination_addr=destination_addr,
                                            message_status=message_status,
                                            sub_date=sub_date,
                                            source_addr_ton=source_addr_ton,
                                            source_addr_npi=source_addr_npi,
                                            dest_addr_ton=dest_addr_ton,
                                            dest_addr_npi=dest_addr_npi)

            # Pick a deliverer and sendRequest
            if self.smpps_access == 'direct':
                deliverer = bound_systemdids[system_id].getNextBindingForDelivery()

                if deliverer is None:
                    raise NoDelivererForSystemId(system_id)

                yield deliverer.sendRequest(pdu, deliverer.config().responseTimerSecs)
            else:
                r = yield self.smpps.deliverer_send_request(system_id, pdu)
                if not r:
                    raise DeliveringFailed('Delivering failed, check %s smpps logs for more details' % system_id)
        except Exception as e:
            self.log.error('Throwing SMPP/DLR [msgid:%s] to (%s): %r.', msgid, system_id, e)

            # List of exceptions after which, no further retrying shall be made
            noRetryExceptions = [SmppsNotSetError]

            retry = True
            for noRetryException in noRetryExceptions:
                if isinstance(e, noRetryException):
                    retry = False
                    break

            # Requeue message for later retry
            if retry and self.getThrowingRetrials(message) <= self.config.max_retries:
                self.log.debug('Message try-count is %s [msgid:%s]: requeuing',
                               self.getThrowingRetrials(message), msgid)
                yield self.rejectAndRequeueMessage(message)
            elif retry and self.getThrowingRetrials(message) > self.config.max_retries:
                self.log.warn('Message is no more processed after receiving "%s" error', str(e))
                yield self.rejectMessage(message)
            else:
                self.log.warn('Message try-count is %s [msgid:%s]: purged from queue',
                              self.getThrowingRetrials(message), msgid)
                yield self.rejectMessage(message)
        else:
            # Everything is okay ? then:
            yield self.ackMessage(message)

    @defer.inlineCallbacks
    def dlr_throwing_callback(self, message):
        Thrower.throwing_callback(self, message)

        if message.routing_key == 'dlr_thrower.http':
            yield self.http_dlr_callback(message)
        elif message.routing_key == 'dlr_thrower.smpps':
            yield self.smpp_dlr_callback(message)
        else:
            self.log.error('Unknown routing_key in dlr_throwing_callback: %s', message.routing_key)
            yield self.rejectMessage(message)