Esempio n. 1
0
    def concatDeliverSMs(self, HSetReturn, hashKey, splitMethod, total_segments, msg_ref_num, segment_seqnum):
        if HSetReturn == 0:
            self.log.warn('This hashKey %s already exists, will not reset it !', hashKey)
            return

        # @TODO: longDeliverSm part expiry must be configurable
        yield self.redisClient.expire(hashKey, 300)

        # This is the last part
        if segment_seqnum == total_segments:
            hvals = yield self.redisClient.hvals(hashKey)
            if len(hvals) != total_segments:
                self.log.warn(
                    'Received the last part (msg_ref_num:%s) and did not find all parts in redis, data lost !',
                    msg_ref_num)
                return

            # Get PDUs
            pdus = {}
            for pickledValue in hvals:
                value = pickle.loads(pickledValue)

                pdus[value['segment_seqnum']] = value['pdu']

            # Where is the message content to be found ?
            if 'short_message' in pdus[1].params:
                msg_content_key = 'short_message'
            elif 'message_payload' in pdus[1].params:
                msg_content_key = 'message_payload'
            else:
                self.log.warn('Cannot find message content in first pdu params: %s', pdus[1].params)
                return

            # Build concat_message_content
            concat_message_content = ''
            for i in range(total_segments):
                if splitMethod == 'sar':
                    concat_message_content += pdus[i + 1].params[msg_content_key]
                else:
                    concat_message_content += pdus[i + 1].params[msg_content_key][6:]

            # Build the final pdu and return it back to deliver_sm_event
            pdu = pdus[1]  # Take the first part as a base of work
            # 1. Remove message splitting information from pdu
            if splitMethod == 'sar':
                del pdu.params['sar_segment_seqnum']
                del pdu.params['sar_total_segments']
                del pdu.params['sar_msg_ref_num']
            else:
                pdu.params['esm_class'] = None
            # 2. Set the new concat_message_content
            pdu.params[msg_content_key] = concat_message_content

            routable = RoutableDeliverSm(pdu, Connector(self.SMPPClientFactory.config.id))
            yield self.deliver_sm_event_post_interception(routable=routable, smpp=None, concatenated=True)
Esempio n. 2
0
    def deliver_sm_event_interceptor(self, smpp, pdu):
        self.log.debug('Intercepting deliver_sm event in smppc %s',
                       self.SMPPClientFactory.config.id)

        if self.RouterPB is None:
            self.log.error(
                '(deliver_sm_event_interceptor/%s) RouterPB not set: deliver_sm will not be routed',
                self.SMPPClientFactory.config.id)
            return

        # Prepare for interception
        # this is a temporary routable instance to be used in interception
        routable = RoutableDeliverSm(
            pdu, Connector(self.SMPPClientFactory.config.id))

        # Interception inline
        # @TODO: make Interception in a thread, just like httpapi interception
        interceptor = self.RouterPB.getMOInterceptionTable().getInterceptorFor(
            routable)
        if interceptor is not None:
            self.log.debug(
                "RouterPB selected %s interceptor for this DeliverSmPDU",
                interceptor)
            if self.interceptorpb_client is None:
                smpp.factory.stats.inc('interceptor_error_count')
                self.log.error("InterceptorPB not set !")
                raise InterceptorNotSetError('InterceptorPB not set !')
            if not self.interceptorpb_client.isConnected:
                smpp.factory.stats.inc('interceptor_error_count')
                self.log.error("InterceptorPB not connected !")
                raise InterceptorNotConnectedError(
                    'InterceptorPB not connected !')

            script = interceptor.getScript()
            self.log.debug("Interceptor script loaded: %s", script)

            # Run !
            d = self.interceptorpb_client.run_script(script, routable)
            d.addCallback(self.deliver_sm_event_post_interception,
                          routable=routable,
                          smpp=smpp)
            d.addErrback(self.deliver_sm_event_post_interception)
            return d
        else:
            return self.deliver_sm_event_post_interception(routable=routable,
                                                           smpp=smpp)
Esempio n. 3
0
    def deliver_sm_callback(self, message):
        """This callback is a queue listener
        It will only decide where to send the input message and republish it to the routedConnector
        The consumer will execute the remaining job of final delivery 
        c.f. test_router.DeliverSmDeliveryTestCases for use cases
        """
        msgid = message.content.properties['message-id']
        scid = message.content.properties['headers']['connector-id']
        concatenated = message.content.properties['headers']['concatenated']
        will_be_concatenated = message.content.properties['headers'][
            'will_be_concatenated']
        connector = Connector(scid)
        DeliverSmPDU = pickle.loads(message.content.body)
        self.log.debug(
            "Callbacked a deliver_sm with a DeliverSmPDU[%s] (?): %s" %
            (msgid, DeliverSmPDU))

        # @todo: Implement MO throttling here, same as in jasmin.managers.listeners.SMPPClientSMListener.submit_sm_callback
        self.deliver_sm_q.get().addCallback(
            self.deliver_sm_callback).addErrback(self.deliver_sm_errback)

        # Routing
        routable = RoutableDeliverSm(DeliverSmPDU, connector)
        route = self.getMORoutingTable().getRouteFor(routable)
        if route is None:
            self.log.debug(
                "No route matched this DeliverSmPDU with scid:%s and msgid:%s"
                % (scid, msgid))
            yield self.rejectMessage(message)
        else:
            # Get connector from selected route
            self.log.debug("RouterPB selected %s for this SubmitSmPDU" % route)
            routedConnector = route.getConnector()

            # Smpps will not route any concatenated content, it must instead route
            # multiparted messages
            # Only http connector needs concatenated content
            if concatenated and routedConnector.type != 'http':
                self.log.debug(
                    "DeliverSmPDU [msgid:%s] not routed because its content is concatenated and the routedConnector is not http: %s"
                    % (msgid, routedConnector.type))
                yield self.rejectMessage(message)

            # Http will not route any multipart messages, it must instead route
            # concatenated messages
            # Only smpps connector needs multipart content
            elif will_be_concatenated and routedConnector.type == 'http':
                self.log.debug(
                    "DeliverSmPDU [msgid:%s] not routed because there will be a one concatenated message for all parts: %s"
                    % (msgid))
                yield self.rejectMessage(message)

            else:
                self.log.debug(
                    "Connector '%s'(%s) is set to be a route for this DeliverSmPDU"
                    % (routedConnector.cid, routedConnector.type))
                yield self.ackMessage(message)

                # Enqueue DeliverSm for delivery through publishing it to deliver_sm_thrower.(type)
                content = RoutedDeliverSmContent(DeliverSmPDU, msgid, scid,
                                                 routedConnector)
                self.log.debug(
                    "Publishing RoutedDeliverSmContent [msgid:%s] in deliver_sm_thrower.%s with [dcid:%s]"
                    % (msgid, routedConnector.type, routedConnector.cid))
                yield self.amqpBroker.publish(
                    exchange='messaging',
                    routing_key='deliver_sm_thrower.%s' % routedConnector.type,
                    content=content)
Esempio n. 4
0
    source_addr=submit_sm.params['source_addr'],
    dest_addr_ton=submit_sm.params['dest_addr_ton'],
    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']))