Exemplo n.º 1
0
    def handle(self, bundle: TransactionBundle, statistics: StatisticsSet):
        """
        The main dispatcher for incoming messages.

        :param bundle: The transaction bundle
        :param statistics: Container for shared memory with statistics counters
        :returns: The message to reply with
        """
        if not bundle.request:
            # Nothing to do...
            return None

        # Update the allow_rapid_commit flag
        bundle.allow_rapid_commit = self.allow_rapid_commit

        # Count the incoming message type
        statistics.count_message_in(bundle.request.message_type)

        # Log what we are doing (low-detail, so not DEBUG_HANDLING here)
        logger.debug("Handling {}".format(bundle))

        # Collect the handlers
        handlers = self.get_handlers(bundle)

        # Analyse pre
        for handler in handlers:
            # noinspection PyBroadException
            try:
                handler.analyse_pre(bundle)
            except:
                # Ignore all errors, analysis isn't that important
                pass

        try:
            # Pre-process the request
            for handler in handlers:
                handler.pre(bundle)

            # Init the response
            self.init_response(bundle)

            # Process the request
            for handler in handlers:
                logger.log(DEBUG_HANDLING, "Applying {}".format(handler))
                handler.handle(bundle)

            # Post-process the request
            for handler in handlers:
                handler.post(bundle)

        except ForOtherServerError as e:
            # Specific form of CannotRespondError that should have its own log message
            message = str(e) or 'Message is for another server'
            logger.debug("{}: ignoring".format(message))
            statistics.count_for_other_server()
            bundle.response = None

        except CannotRespondError as e:
            message = str(e) or 'Cannot respond to this message'
            logger.warning("{}: ignoring".format(message))
            statistics.count_do_not_respond()
            bundle.response = None

        except UseMulticastError:
            logger.debug("Unicast request received when multicast is required: informing client")
            statistics.count_use_multicast()
            bundle.response = self.construct_use_multicast_reply(bundle)

        # Analyse post
        for handler in handlers:
            # noinspection PyBroadException
            try:
                handler.analyse_post(bundle)
            except:
                # Ignore all errors, analysis isn't that important
                pass

        if bundle.response:
            logger.log(DEBUG_HANDLING, "Responding with {}".format(bundle.response.__class__.__name__))

            # Count the outgoing message type
            statistics.count_message_out(bundle.response.message_type)
        else:
            logger.log(DEBUG_HANDLING, "Not responding")
Exemplo n.º 2
0
    def handle(self, bundle: TransactionBundle, statistics: StatisticsSet):
        """
        The main dispatcher for incoming messages.

        :param bundle: The transaction bundle
        :param statistics: Container for shared memory with statistics counters
        :returns: The message to reply with
        """
        if not bundle.request:
            # Nothing to do...
            return None

        # Update the allow_rapid_commit flag
        bundle.allow_rapid_commit = self.allow_rapid_commit

        # Count the incoming message type
        statistics.count_message_in(bundle.request.message_type)

        # Log what we are doing (low-detail, so not DEBUG_HANDLING here)
        logger.debug("Handling {}".format(bundle))

        # Collect the handlers
        handlers = self.get_handlers(bundle)

        # Analyse pre
        for handler in handlers:
            # noinspection PyBroadException
            try:
                handler.analyse_pre(bundle)
            except:
                # Ignore all errors, analysis isn't that important
                logger.exception("{} pre analysis failed".format(handler.__class__.__name__))

        try:
            # Pre-process the request
            for handler in handlers:
                handler.pre(bundle)

            # Init the response
            self.init_response(bundle)

            # Process the request
            for handler in handlers:
                logger.log(DEBUG_HANDLING, "Applying {}".format(handler))
                handler.handle(bundle)

            # Post-process the request
            for handler in handlers:
                handler.post(bundle)

        except ForOtherServerError as e:
            # Specific form of CannotRespondError that should have its own log message
            message = str(e) or 'Message is for another server'
            logger.debug("{}: ignoring".format(message))
            statistics.count_for_other_server()
            bundle.response = None

        except CannotRespondError as e:
            message = str(e) or 'Cannot respond to this message'
            logger.warning("{}: ignoring".format(message))
            statistics.count_do_not_respond()
            bundle.response = None

        except UseMulticastError:
            logger.debug("Unicast request received when multicast is required: informing client")
            statistics.count_use_multicast()
            bundle.response = self.construct_use_multicast_reply(bundle)

        except ReplyWithStatusError as e:
            # Leasequery has its own reply message type
            if isinstance(e, ReplyWithLeasequeryError):
                bundle.response = self.construct_leasequery_status_reply(bundle, e.option)
            else:
                bundle.response = self.construct_plain_status_reply(bundle, e.option)

            logger.warning("Replying with {}".format(e))

            # Update the right counter based on the status code
            if e.option.status_code == STATUS_UNKNOWN_QUERY_TYPE:
                statistics.count_unknown_query_type()
            elif e.option.status_code == STATUS_MALFORMED_QUERY:
                statistics.count_malformed_query()
            elif e.option.status_code == STATUS_NOT_ALLOWED:
                statistics.count_not_allowed()
            else:
                statistics.count_other_error()

        # Analyse post
        for handler in handlers:
            # noinspection PyBroadException
            try:
                handler.analyse_post(bundle)
            except:
                # Ignore all errors, analysis isn't that important
                logger.exception("{} post analysis failed".format(handler.__class__.__name__))

        if bundle.response:
            logger.log(DEBUG_HANDLING, "Responding with {}".format(bundle.response.__class__.__name__))

            # Count the outgoing message type
            statistics.count_message_out(bundle.response.message_type)
        else:
            logger.log(DEBUG_HANDLING, "Not responding")
Exemplo n.º 3
0
    def handle(self, bundle: TransactionBundle, statistics: StatisticsSet):
        """
        The main dispatcher for incoming messages.

        :param bundle: The transaction bundle
        :param statistics: Container for shared memory with statistics counters
        """
        if not bundle.request:
            # Nothing to do...
            return

        # Update the allow_rapid_commit flag
        bundle.allow_rapid_commit = self.allow_rapid_commit

        # Count the incoming message type
        statistics.count_message_in(bundle.request.message_type)

        # Log what we are doing (low-detail, so not DEBUG_HANDLING here)
        logger.debug("Handling {}".format(bundle))

        # Collect the handlers
        handlers = self.get_handlers(bundle)

        # Analyse pre
        for handler in handlers:
            # noinspection PyBroadException
            try:
                handler.analyse_pre(bundle)
            except:
                # Ignore all errors, analysis isn't that important
                logger.exception("{} pre analysis failed".format(
                    handler.__class__.__name__))

        try:
            # Pre-process the request
            for handler in handlers:
                handler.pre(bundle)

            # Init the response
            self.init_response(bundle)

            # Process the request
            for handler in handlers:
                logger.log(DEBUG_HANDLING, "Applying {}".format(handler))
                handler.handle(bundle)

            # Post-process the request
            for handler in handlers:
                handler.post(bundle)

        except ForOtherServerError as e:
            # Specific form of CannotRespondError that should have its own log message
            message = str(e) or 'Message is for another server'
            logger.debug("{}: ignoring".format(message))
            statistics.count_for_other_server()
            bundle.response = None

        except CannotRespondError as e:
            message = str(e) or 'Cannot respond to this message'
            logger.warning("{}: ignoring".format(message))
            statistics.count_do_not_respond()
            bundle.response = None

        except UseMulticastError:
            logger.debug(
                "Unicast request received when multicast is required: informing client"
            )
            statistics.count_use_multicast()
            bundle.response = self.construct_use_multicast_reply(bundle)

        except ReplyWithStatusError as e:
            # Leasequery has its own reply message type
            if isinstance(e, ReplyWithLeasequeryError):
                bundle.response = self.construct_leasequery_status_reply(
                    bundle, e.option)
            else:
                bundle.response = self.construct_plain_status_reply(
                    bundle, e.option)

            logger.warning("Replying with {}".format(e))

            # Update the right counter based on the status code
            if e.option.status_code == STATUS_UNKNOWN_QUERY_TYPE:
                statistics.count_unknown_query_type()
            elif e.option.status_code == STATUS_MALFORMED_QUERY:
                statistics.count_malformed_query()
            elif e.option.status_code == STATUS_NOT_ALLOWED:
                statistics.count_not_allowed()
            else:
                statistics.count_other_error()

        # Analyse post
        for handler in handlers:
            # noinspection PyBroadException
            try:
                handler.analyse_post(bundle)
            except:
                # Ignore all errors, analysis isn't that important
                logger.exception("{} post analysis failed".format(
                    handler.__class__.__name__))

        if bundle.response:
            logger.log(
                DEBUG_HANDLING, "Responding with {}".format(
                    bundle.response.__class__.__name__))

            # Count the outgoing message type
            statistics.count_message_out(bundle.response.message_type)
        else:
            logger.log(DEBUG_HANDLING, "Not responding")