Ejemplo n.º 1
0
 def handle_event(self, config, event, conn_name):
     log.debug("Handling event: %s" % (event,))
     # To avoid circular import.
     from go.vumitools.routing import RoutingMetadata
     endpoint = RoutingMetadata(event).next_router_endpoint()
     if endpoint is not None:
         self.publish_event(event, endpoint=endpoint)
Ejemplo n.º 2
0
 def handle_event(self, config, event, conn_name):
     log.debug("Handling event: %s" % (event, ))
     # To avoid circular import.
     from go.vumitools.routing import RoutingMetadata
     endpoint = RoutingMetadata(event).next_router_endpoint()
     if endpoint is not None:
         self.publish_event(event, endpoint=endpoint)
Ejemplo n.º 3
0
    def process_event(self, config, event, connector_name):
        """Process an event message.

        Publish the event to the ``AccountRoutingTableDispatcher``.
        """
        log.debug("Processing event: %s" % (event,))
        yield self.publish_event(event, self.receive_outbound_connector, None)
Ejemplo n.º 4
0
 def _ignore_message(self, failure, msg):
     failure.trap(IgnoreMessage)
     log.debug("Ignoring msg (with NACK) due to %r: %r" % (
         failure.value, msg))
     return self.publish_event(TransportEvent(
         user_message_id=msg['message_id'], nack_reason=str(failure.value),
         event_type='nack'))
Ejemplo n.º 5
0
    def receive_control_message(self, msg):
        log.debug('Received control! %s' % (msg, ))

        try:
            if msg['message_type'] == 'add_worker':
                if msg['worker_name'] in self.workers:
                    log.error('Cannot create worker, name already exist: %s' %
                              (msg['worker_name'], ))
                    return
                for key in msg['config'].keys():
                    msg['config'][key] = msg['config'][key].encode('utf-8')
                self.config[msg['worker_name']] = msg['config']
                worker = self.create_worker(msg['worker_name'],
                                            msg['worker_class'])
                self.workers[msg['worker_name']] = worker

            if msg['message_type'] == 'remove_worker':
                if not msg['worker_name'] in self.workers:
                    log.error('Cannot remove worker, name unknown: %s' %
                              (msg['worker_name']))
                    return
                yield self.workers[msg['worker_name']].stopService()
                self.workers[msg['worker_name']].disownServiceParent()
                self.workers.pop(msg['worker_name'])

        except Exception as ex:
            log.error("Control received: %s" % (msg))
            log.error("Unexpected error %s" % repr(ex))
Ejemplo n.º 6
0
 def send_pdu(self, pdu):
     data = pdu.get_bin()
     unpacked = unpack_pdu(data)
     command_id = unpacked['header']['command_id']
     if command_id not in ('enquire_link', 'enquire_link_resp'):
         log.debug('OUTGOING >>>> %s' % unpacked)
     self.transport.write(data)
Ejemplo n.º 7
0
 def send_pdu(self, pdu):
     data = pdu.get_bin()
     unpacked = unpack_pdu(data)
     command_id = unpacked['header']['command_id']
     if command_id not in ('enquire_link', 'enquire_link_resp'):
         log.debug('OUTGOING >>>> %s' % unpacked)
     self.transport.write(data)
Ejemplo n.º 8
0
 def send_enquire_link_request(self):
     log.debug("Sending enquire link request")
     self.send_packet(self.gen_session_id(), 'ENQRequest', [
         ('requestId', self.gen_request_id()),
         ('enqCmd', 'ENQUIRELINK')
     ])
     self.reset_scheduled_timeout()
Ejemplo n.º 9
0
    def consume_user_message(self, msg):
        regex_KEYWORD = re.compile('KEYWORD')

        log.debug("Consumer user message %s" % (msg,))
        if msg['timestamp']:
            timestamp = time_to_vusion_format(msg['timestamp'])
        self.unmatchable_reply_collection.save(
            {'participant-phone': msg['from_addr'],
             'to': msg['to_addr'],
             'message-content': msg['content'],
             'timestamp': timestamp,
             })

        code = self.shortcodes_collection.find_one({
            'shortcode': msg['to_addr']})
        if code is None:
            return
        template = self.templates_collection.find_one({
            '_id': ObjectId(code['error-template'])})
        if template is None:
            return
        error_message = TransportUserMessage(**{
            'from_addr': msg['to_addr'],
            'to_addr': msg['from_addr'],
            'transport_name': msg['transport_name'],
            'transport_type': msg['transport_type'],
            'transport_metadata': msg['transport_metadata'],
            'content': re.sub(
                regex_KEYWORD, get_first_word(msg['content']),
                template['template']
            )
        })
        yield self.transport_publisher.publish_message(error_message)
        log.debug("Reply '%s' sent to %s" %
                  (error_message['content'], error_message['to_addr']))
Ejemplo n.º 10
0
    def process_command_stop(self, user_account_key, conversation_key):
        yield super(SequentialSendApplication, self).process_command_stop(
            user_account_key, conversation_key)

        log.debug("Unscheduling conversation: %s" % (conversation_key,))
        yield self.redis.srem('scheduled_conversations', json.dumps(
                [user_account_key, conversation_key]))
Ejemplo n.º 11
0
 def send_smpp(self, message):
     log.debug("Sending SMPP message: %s" % (message))
     # first do a lookup in our YAML to see if we've got a source_addr
     # defined for the given MT number, if not, trust the from_addr
     # in the message
     to_addr = message['to_addr']
     from_addr = message['from_addr']
     text = message['content']
     continue_session = (
         message['session_event'] != TransportUserMessage.SESSION_CLOSE)
     config = self.get_static_config()
     route = get_operator_number(to_addr, config.COUNTRY_CODE,
                                 config.OPERATOR_PREFIX,
                                 config.OPERATOR_NUMBER)
     source_addr = route or from_addr
     session_info = message['transport_metadata'].get('session_info')
     return self.esme_client.submit_sm(
         # these end up in the PDU
         short_message=text.encode(self.submit_sm_encoding),
         data_coding=self.submit_sm_data_coding,
         destination_addr=to_addr.encode('ascii'),
         source_addr=source_addr.encode('ascii'),
         session_info=session_info.encode('ascii')
             if session_info is not None else None,
         # these don't end up in the PDU
         message_type=message['transport_type'],
         continue_session=continue_session,
     )
Ejemplo n.º 12
0
    def receive_control_message(self, msg):
        log.debug('Received control! %s' % (msg,))

        try:
            if msg['message_type'] == 'add_worker':
                if msg['worker_name'] in self.workers:
                    log.error('Cannot create worker, name already exist: %s'
                              % (msg['worker_name'],))
                    return
                for key in msg['config'].keys():
                    msg['config'][key] = msg['config'][key].encode('utf-8')
                self.config[msg['worker_name']] = msg['config']
                worker = self.create_worker(msg['worker_name'],
                                            msg['worker_class'])
                self.workers[msg['worker_name']] = worker

            if msg['message_type'] == 'remove_worker':
                if not msg['worker_name'] in self.workers:
                    log.error('Cannot remove worker, name unknown: %s'
                              % (msg['worker_name']))
                    return
                yield self.workers[msg['worker_name']].stopService()
                self.workers[msg['worker_name']].disownServiceParent()
                self.workers.pop(msg['worker_name'])

        except Exception as ex:
            log.error("Control received: %s" % (msg))
            log.error("Unexpected error %s" % repr(ex))
Ejemplo n.º 13
0
    def process_command_stop(self, user_account_key, conversation_key):
        yield super(SequentialSendApplication,
                    self).process_command_stop(user_account_key,
                                               conversation_key)

        log.debug("Unscheduling conversation: %s" % (conversation_key, ))
        yield self.redis.srem('scheduled_conversations',
                              json.dumps([user_account_key, conversation_key]))
Ejemplo n.º 14
0
 def _ignore_message(self, failure, msg):
     failure.trap(IgnoreMessage)
     log.debug("Ignoring msg (with NACK) due to %r: %r" %
               (failure.value, msg))
     return self.publish_event(
         TransportEvent(user_message_id=msg['message_id'],
                        nack_reason=str(failure.value),
                        event_type='nack'))
Ejemplo n.º 15
0
 def handle_data(self, data):
     pdu = unpack_pdu(data)
     command_id = pdu['header']['command_id']
     if command_id not in ('enquire_link', 'enquire_link_resp'):
         log.debug('INCOMING <<<< %s' % binascii.b2a_hex(data))
         log.debug('INCOMING <<<< %s' % pdu)
     handler = getattr(self, 'handle_%s' % (command_id, ),
                       self._command_handler_not_found)
     yield handler(pdu)
Ejemplo n.º 16
0
    def startService(self):
        log.debug('Starting Multiworker %s' % (self.config, ))
        super(MultiWorker, self).startService()

        self.workers = {}
        self.worker_creator = self.WORKER_CREATOR(self.options)
        for wname, wclass in self.config.get('workers', {}).items():
            worker = self.create_worker(wname, wclass)
            self.workers[wname] = worker
Ejemplo n.º 17
0
    def handle_enquire_link_request(self, session_id, params):
        try:
            self.validate_packet_fields(params, self.ENQUIRE_LINK_FIELDS)
        except CodedXmlOverTcpError as e:
            self.handle_error(session_id, params.get('requestId'), e)
            return

        log.debug("Enquire link request received, sending response")
        self.send_enquire_link_response(session_id, params['requestId'])
Ejemplo n.º 18
0
 def submit_sm_success(self, sent_sms_id, transport_msg_id):
     yield self.r_delete_message(sent_sms_id)
     log.debug("Mapping transport_msg_id=%s to sent_sms_id=%s" % (
         transport_msg_id, sent_sms_id))
     log.debug("PUBLISHING ACK: (%s -> %s)" % (
         sent_sms_id, transport_msg_id))
     self.publish_ack(
         user_message_id=sent_sms_id,
         sent_message_id=transport_msg_id)
Ejemplo n.º 19
0
    def startService(self):
        log.debug('Starting Multiworker %s' % (self.config,))
        super(MultiWorker, self).startService()

        self.workers = {}
        self.worker_creator = self.WORKER_CREATOR(self.options)
        for wname, wclass in self.config.get('workers', {}).items():
            worker = self.create_worker(wname, wclass)
            self.workers[wname] = worker
Ejemplo n.º 20
0
 def handle_data(self, data):
     pdu = unpack_pdu(data)
     command_id = pdu['header']['command_id']
     if command_id not in ('enquire_link', 'enquire_link_resp'):
         log.debug('INCOMING <<<< %s' % binascii.b2a_hex(data))
         log.debug('INCOMING <<<< %s' % pdu)
     handler = getattr(self, 'handle_%s' % (command_id,),
                       self._command_handler_not_found)
     yield handler(pdu)
Ejemplo n.º 21
0
 def startWorker(self):
     log.debug('Starting Dynamic Dispatcher %s' % (self.config,))
     self.exposed_consumer = {}
     self.exposed_publisher = {}
     self.exposed_event_publisher = {}
     self.transport_consumer = {}
     self.transport_publisher = {}
     self.transport_event_consumer = {}
     super(DynamicDispatchWorker, self).startWorker()
     yield self.setup_control()
Ejemplo n.º 22
0
 def poll_conversations(self):
     then, now = yield self.get_interval()
     conv_jsons = yield self._get_scheduled_conversations()
     conversations = yield self.get_conversations(
         [json.loads(c) for c in conv_jsons])
     log.debug("Processing %s to %s: %s" % (
         then, now, [c.key for c in conversations]))
     for conv in conversations:
         if not conv.ended():
             yield self.process_conversation_schedule(then, now, conv)
Ejemplo n.º 23
0
 def poll_conversations(self):
     then, now = yield self.get_interval()
     conv_jsons = yield self._get_scheduled_conversations()
     conversations = yield self.get_conversations(
         [json.loads(c) for c in conv_jsons])
     log.debug("Processing %s to %s: %s" %
               (then, now, [c.key for c in conversations]))
     for conv in conversations:
         if not conv.ended():
             yield self.process_conversation_schedule(then, now, conv)
Ejemplo n.º 24
0
    def send_packet(self, session_id, packet_type, params):
        if (not self.authenticated
                and packet_type not in self.IGNORE_AUTH_PACKETS):
            raise XmlOverTcpError(
                "'%s' packet could not be sent, client not authenticated"
                % packet_type)

        packet = self.serialize_packet(session_id, packet_type, params)
        log.debug("Sending packet: %s" % packet)
        self.transport.write(packet)
Ejemplo n.º 25
0
 def startWorker(self):
     log.debug('Starting Dynamic Dispatcher %s' % (self.config, ))
     self.exposed_consumer = {}
     self.exposed_publisher = {}
     self.exposed_event_publisher = {}
     self.transport_consumer = {}
     self.transport_publisher = {}
     self.transport_event_consumer = {}
     super(DynamicDispatchWorker, self).startWorker()
     yield self.setup_control()
Ejemplo n.º 26
0
    def handle_enquire_link_response(self, session_id, params):
        try:
            self.validate_packet_fields(params, self.ENQUIRE_LINK_FIELDS)
        except CodedXmlOverTcpError as e:
            self.handle_error(session_id, params.get('requestId'), e)
            return

        log.debug("Enquire link response received, sending next request in %s "
                  "seconds" % self.enquire_link_interval)
        self.cancel_scheduled_timeout()
Ejemplo n.º 27
0
    def process_outbound(self, config, msg, connector_name):
        """Process an outbound message.

        Outbound messages can be from:

        * conversations
        * routers
        * the opt-out worker
        * the billing worker

        And may go to:

        * routers
        * transports
        * the billing worker
        """
        log.debug("Processing outbound: %s" % (msg,))
        msg_mdh = self.get_metadata_helper(msg)
        msg_mdh.set_user_account(config.user_account_key)

        connector_type = self.connector_type(connector_name)
        src_conn = self.acquire_source(msg, connector_type, self.OUTBOUND)

        if self.billing_outbound_connector:
            if connector_type in (self.CONVERSATION, self.ROUTER):
                msg_mdh.reset_paid()
            elif connector_type == self.OPT_OUT:
                tag = yield self.tag_for_reply(msg)
                yield self.publish_outbound_to_billing(config, msg, tag)
                return
            elif connector_type == self.BILLING:
                yield self.publish_outbound_from_billing(config, msg)
                return
        else:
            if connector_type == self.OPT_OUT:
                yield self.publish_outbound_optout(config, msg)
                return

        target = self.find_target(config, msg, src_conn)
        if target is None:
            raise NoTargetError(
                "No target found for outbound message from '%s': %s" % (
                    connector_name, msg), msg)

        if self.billing_outbound_connector:
            target_conn = GoConnector.parse(target[0])
            if target_conn.ctype == target_conn.TRANSPORT_TAG:
                tag = [target_conn.tagpool, target_conn.tagname]
                yield self.publish_outbound_to_billing(config, msg, tag)
                return

        dst_connector_name, dst_endpoint = yield self.set_destination(
            msg, target, self.OUTBOUND)

        yield self.publish_outbound(msg, dst_connector_name, dst_endpoint)
Ejemplo n.º 28
0
    def process_outbound(self, config, msg, connector_name):
        """Process an outbound message.

        Outbound messages can be from:

        * conversations
        * routers
        * the opt-out worker
        * the billing worker

        And may go to:

        * routers
        * transports
        * the billing worker
        """
        log.debug("Processing outbound: %s" % (msg, ))
        msg_mdh = self.get_metadata_helper(msg)
        msg_mdh.set_user_account(config.user_account_key)

        connector_type = self.connector_type(connector_name)
        src_conn = self.acquire_source(msg, connector_type, self.OUTBOUND)

        if self.billing_outbound_connector:
            if connector_type in (self.CONVERSATION, self.ROUTER):
                msg_mdh.reset_paid()
            elif connector_type == self.OPT_OUT:
                tag = yield self.tag_for_reply(msg)
                yield self.publish_outbound_to_billing(config, msg, tag)
                return
            elif connector_type == self.BILLING:
                yield self.publish_outbound_from_billing(config, msg)
                return
        else:
            if connector_type == self.OPT_OUT:
                yield self.publish_outbound_optout(config, msg)
                return

        target = self.find_target(config, msg, src_conn)
        if target is None:
            raise NoTargetError(
                "No target found for outbound message from '%s': %s" %
                (connector_name, msg), msg)

        if self.billing_outbound_connector:
            target_conn = GoConnector.parse(target[0])
            if target_conn.ctype == target_conn.TRANSPORT_TAG:
                tag = [target_conn.tagpool, target_conn.tagname]
                yield self.publish_outbound_to_billing(config, msg, tag)
                return

        dst_connector_name, dst_endpoint = yield self.set_destination(
            msg, target, self.OUTBOUND)

        yield self.publish_outbound(msg, dst_connector_name, dst_endpoint)
Ejemplo n.º 29
0
 def setup_exposed(self, name):
     log.debug("Setup exposed %s" % (name, ))
     if not name in self._exposed_names:
         self._exposed_names.append(name.encode('utf-8'))
         self.exposed_publisher[name] = yield self.publish_to(
             ('%s.inbound' % (name, )).encode('utf-8'))
         self.exposed_event_publisher[name] = yield self.publish_to(
             ('%s.event' % (name, )).encode('utf-8'))
         self.exposed_consumer[name] = yield self.consume(
             ('%s.outbound' % (name, )).encode('utf-8'),
             functools.partial(self.dispatch_outbound_message, name),
             message_class=TransportUserMessage)
Ejemplo n.º 30
0
    def start_survey(self, to_addr, contact, conversation, **msg_options):
        log.debug('Starting %r -> %s' % (conversation, to_addr))

        # We reverse the to_addr & from_addr since we're faking input
        # from the client to start the survey.
        from_addr = msg_options.pop('from_addr')
        conversation.set_go_helper_metadata(
            msg_options.setdefault('helper_metadata', {}))
        msg = TransportUserMessage(from_addr=to_addr, to_addr=from_addr,
                                   content='', **msg_options)

        return self._handle_survey_message(msg, contact)
Ejemplo n.º 31
0
 def setup_exposed(self, name):
     log.debug("Setup exposed %s" % (name,))
     if not name in self._exposed_names:
         self._exposed_names.append(name.encode('utf-8'))
         self.exposed_publisher[name] = yield self.publish_to(
             ('%s.inbound' % (name,)).encode('utf-8'))
         self.exposed_event_publisher[name] = yield self.publish_to(
             ('%s.event' % (name,)).encode('utf-8'))
         self.exposed_consumer[name] = yield self.consume(
             ('%s.outbound' % (name,)).encode('utf-8'),
             functools.partial(self.dispatch_outbound_message,
                               name),
             message_class=TransportUserMessage)
Ejemplo n.º 32
0
    def process_outbound(self, config, msg, connector_name):
        """Process an outbound message.

        Any errors are logged and the message is allowed to continue on its
        path and fulfill its destiny.
        """
        log.debug("Processing outbound: %r" % (msg,))
        msg_mdh = self.get_metadata_helper(msg)
        try:
            yield self.create_transaction_for_outbound(msg)
            msg_mdh.set_paid()
        except BillingError:
            log.err()
        yield self.publish_outbound(msg, self.receive_inbound_connector, None)
Ejemplo n.º 33
0
    def start_survey(self, to_addr, contact, conversation, **msg_options):
        log.debug('Starting %r -> %s' % (conversation, to_addr))

        # We reverse the to_addr & from_addr since we're faking input
        # from the client to start the survey.
        from_addr = msg_options.pop('from_addr')
        conversation.set_go_helper_metadata(
            msg_options.setdefault('helper_metadata', {}))
        msg = TransportUserMessage(from_addr=to_addr,
                                   to_addr=from_addr,
                                   content='',
                                   **msg_options)

        return self._handle_survey_message(msg, contact)
Ejemplo n.º 34
0
 def receive_control_message(self, msg):
     try:
         log.debug('Received control message %s' % (msg,))
         if msg['action'] == 'add_exposed':
             self.setup_exposed(msg['exposed_name'])
             self.append_mapping(msg['exposed_name'], msg['rules'])
             return
         if msg['action'] == 'remove_exposed':
             self.clear_mapping(msg['exposed_name'])
             self.remove_exposed(msg['exposed_name'])
             return
     except:
         exc_type, exc_value, exc_traceback = sys.exc_info()
         log.error(
             "Error during consume control message: %r" %
             traceback.format_exception(exc_type, exc_value, exc_traceback))
Ejemplo n.º 35
0
 def receive_control_message(self, msg):
     try:
         log.debug('Received control message %s' % (msg, ))
         if msg['action'] == 'add_exposed':
             self.setup_exposed(msg['exposed_name'])
             self.append_mapping(msg['exposed_name'], msg['rules'])
             return
         if msg['action'] == 'remove_exposed':
             self.clear_mapping(msg['exposed_name'])
             self.remove_exposed(msg['exposed_name'])
             return
     except:
         exc_type, exc_value, exc_traceback = sys.exc_info()
         log.error(
             "Error during consume control message: %r" %
             traceback.format_exception(exc_type, exc_value, exc_traceback))
Ejemplo n.º 36
0
    def process_event(self, config, event, connector_name):
        """Process an event message.

        Events must trace back the path through the routers
        and conversations that was taken by the associated outbound
        message.

        Events thus ignore the routing table itself.

        Events can be from:

        * transports
        * routers

        And may go to:

        * routers
        * conversations
        * the opt-out worker
        """
        log.debug("Processing event: %s" % (event, ))

        # events are in same direction as inbound messages so
        # we use INBOUND as the direction in this method.

        yield self._set_event_metadata(event)

        # events for unroutable messages that have completed their hops
        # don't need to be processed further.
        rmeta = RoutingMetadata(event)
        if rmeta.unroutable_event_done():
            return

        connector_type = self.connector_type(connector_name)
        # we ignore the source connector returned but .acquire_source() sets
        # the initial hop and .next_hop() checks that it matches the outbound
        # destination.
        self.acquire_source(event, connector_type, self.INBOUND)

        target = rmeta.next_hop()
        if target is None:
            raise UnroutableMessageError("Could not find next hop for event.",
                                         event)

        dst_connector_name, dst_endpoint = yield self.set_destination(
            event, target, self.INBOUND)
        yield self.publish_event(event, dst_connector_name, dst_endpoint)
Ejemplo n.º 37
0
    def process_event(self, config, event, connector_name):
        """Process an event message.

        Events must trace back the path through the routers
        and conversations that was taken by the associated outbound
        message.

        Events thus ignore the routing table itself.

        Events can be from:

        * transports
        * routers

        And may go to:

        * routers
        * conversations
        * the opt-out worker
        """
        log.debug("Processing event: %s" % (event,))

        # events are in same direction as inbound messages so
        # we use INBOUND as the direction in this method.

        yield self._set_event_metadata(event)

        # events for unroutable messages that have completed their hops
        # don't need to be processed further.
        rmeta = RoutingMetadata(event)
        if rmeta.unroutable_event_done():
            return

        connector_type = self.connector_type(connector_name)
        # we ignore the source connector returned but .acquire_source() sets
        # the initial hop and .next_hop() checks that it matches the outbound
        # destination.
        self.acquire_source(event, connector_type, self.INBOUND)

        target = rmeta.next_hop()
        if target is None:
            raise UnroutableMessageError(
                "Could not find next hop for event.", event)

        dst_connector_name, dst_endpoint = yield self.set_destination(
            event, target, self.INBOUND)
        yield self.publish_event(event, dst_connector_name, dst_endpoint)
Ejemplo n.º 38
0
    def process_inbound(self, config, msg, connector_name):
        """Process an inbound message.

        Inbound messages can be from:

        * transports (these might be opt-out messages)
        * routers
        * the billing worker

        And may go to:

        * routers
        * conversations
        * the opt-out worker
        * the billing worker
        """
        log.debug("Processing inbound: %r" % (msg,))
        msg_mdh = self.get_metadata_helper(msg)
        msg_mdh.set_user_account(config.user_account_key)

        connector_type = self.connector_type(connector_name)
        src_conn = self.acquire_source(msg, connector_type, self.INBOUND)

        if self.billing_inbound_connector:
            if connector_type == self.TRANSPORT_TAG:
                yield self.publish_inbound_to_billing(config, msg)
                return
            if connector_type == self.BILLING:
                # set the src_conn to the transport and keep routing
                src_conn = str(GoConnector.for_transport_tag(*msg_mdh.tag))

        if msg_mdh.is_optout_message():
            yield self.publish_inbound_optout(config, msg)
            return

        target = self.find_target(config, msg, src_conn)
        if target is None:
            raise NoTargetError(
                "No target found for inbound message from %r"
                % (connector_name,), msg)

        dst_connector_name, dst_endpoint = yield self.set_destination(
            msg, target, self.INBOUND)

        yield self.publish_inbound(msg, dst_connector_name, dst_endpoint)
Ejemplo n.º 39
0
    def process_inbound(self, config, msg, connector_name):
        """Process an inbound message.

        Inbound messages can be from:

        * transports (these might be opt-out messages)
        * routers
        * the billing worker

        And may go to:

        * routers
        * conversations
        * the opt-out worker
        * the billing worker
        """
        log.debug("Processing inbound: %r" % (msg, ))
        msg_mdh = self.get_metadata_helper(msg)
        msg_mdh.set_user_account(config.user_account_key)

        connector_type = self.connector_type(connector_name)
        src_conn = self.acquire_source(msg, connector_type, self.INBOUND)

        if self.billing_inbound_connector:
            if connector_type == self.TRANSPORT_TAG:
                yield self.publish_inbound_to_billing(config, msg)
                return
            if connector_type == self.BILLING:
                # set the src_conn to the transport and keep routing
                src_conn = str(GoConnector.for_transport_tag(*msg_mdh.tag))

        if msg_mdh.is_optout_message():
            yield self.publish_inbound_optout(config, msg)
            return

        target = self.find_target(config, msg, src_conn)
        if target is None:
            raise NoTargetError(
                "No target found for inbound message from %r" %
                (connector_name, ), msg)

        dst_connector_name, dst_endpoint = yield self.set_destination(
            msg, target, self.INBOUND)

        yield self.publish_inbound(msg, dst_connector_name, dst_endpoint)
Ejemplo n.º 40
0
 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.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)
Ejemplo n.º 41
0
 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)
Ejemplo n.º 42
0
    def get_next_key(self, window_id):

        window_key = self.window_key(window_id)
        inflight_key = self.flight_key(window_id)

        waiting_list = yield self.count_waiting(window_id)
        if waiting_list == 0:
            return

        flight_size = yield self.count_in_flight(window_id)
        room_available = self.window_size - flight_size

        if room_available > 0:
            log.debug('Window %s has space for %s' % (window_key,
                                                        room_available))
            next_key = yield self.redis.rpoplpush(window_key, inflight_key)
            if next_key:
                yield self._set_timestamp(window_id, next_key)
                returnValue(next_key)
Ejemplo n.º 43
0
    def packet_received(self, session_id, packet_type, params):
        log.debug("Packet of type '%s' with session id '%s' received: %s"
                  % (packet_type, session_id, params))

        # dispatch the packet to the appropriate handler
        handler_name = self.PACKET_RECEIVED_HANDLERS.get(packet_type, None)
        if handler_name is None:
            log.err("Packet of an unknown type received: %s" % packet_type)
            return self.send_error_response(
                session_id, params.get('requestId'), '208')

        if (not self.authenticated and
                packet_type not in self.IGNORE_AUTH_PACKETS):
            log.err("'%s' packet received before client authentication "
                    "was completed" % packet_type)
            return self.send_error_response(
                session_id, params.get('requestId'), '207')

        getattr(self, handler_name)(session_id, params)
Ejemplo n.º 44
0
    def _call_api(self, path, query=None, data=None, method='GET'):
        """Perform the actual HTTP call to the billing API.

        If the HTTP response code is anything other than 200,
        raise a BillingError exception.
        """
        url = urljoin(self.base_url, path)
        if query:
            url = "%s?%s" % (url, urllib.urlencode(query))
        data = json.dumps(data, cls=JSONEncoder)
        headers = {'Content-Type': 'application/json'}
        log.debug("Sending billing request to %r: %r" % (url, data))
        response = yield http_request_full(url, data, headers=headers,
                                           method=method)

        log.debug("Got billing response: %r" % (response.delivered_body,))
        if response.code != 200:
            raise BillingError(response.delivered_body)
        result = json.loads(response.delivered_body, cls=JSONDecoder)
        returnValue(result)
Ejemplo n.º 45
0
    def handle_outbound_message(self, message):
        config = self.get_static_config()
        missing_fields = self.ensure_message_values(
            message, ['in_reply_to', 'content'])

        if missing_fields:
            return self.reject_message(message, missing_fields)

        if message['session_event'] == TransportUserMessage.SESSION_CLOSE:
            free_flow = 'FB'
        else:
            free_flow = 'FC'

        headers = {
            'Freeflow': [free_flow],
            'charge': [('Y' if config.airtel_charge else 'N')],
            'amount': [str(config.airtel_charge_amount)],
        }

        content = message['content'].encode(self.ENCODING).lstrip()

        if self.noisy:
            log.debug('in_reply_to: %s' % (message['in_reply_to'],))
            log.debug('content: %r' % (content,))
            log.debug('Response headers: %r' % (headers,))

        self.finish_request(
            message['in_reply_to'],
            content,
            code=http.OK,
            headers=headers)
        return self.publish_ack(
            user_message_id=message['message_id'],
            sent_message_id=message['message_id'])
Ejemplo n.º 46
0
    def handle_outbound_message(self, message):
        config = self.get_static_config()
        missing_fields = self.ensure_message_values(message,
                                                    ['in_reply_to', 'content'])

        if missing_fields:
            return self.reject_message(message, missing_fields)

        if message['session_event'] == TransportUserMessage.SESSION_CLOSE:
            free_flow = 'FB'
        else:
            free_flow = 'FC'

        headers = {
            'Freeflow': [free_flow],
            'charge': [('Y' if config.airtel_charge else 'N')],
            'amount': [str(config.airtel_charge_amount)],
        }

        content = message['content'].encode(self.ENCODING).lstrip()

        if self.noisy:
            log.debug('in_reply_to: %s' % (message['in_reply_to'], ))
            log.debug('content: %r' % (content, ))
            log.debug('Response headers: %r' % (headers, ))

        self.finish_request(message['in_reply_to'],
                            content,
                            code=http.OK,
                            headers=headers)
        return self.publish_ack(user_message_id=message['message_id'],
                                sent_message_id=message['message_id'])
Ejemplo n.º 47
0
 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)))
Ejemplo n.º 48
0
 def handle_outbound(self, config, msg, conn_name):
     log.debug("Handling outbound: %s" % (msg, ))
     return self.publish_outbound(msg, 'default')