# Copyright 2012, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


from mod_pywebsocket import common
from mod_pywebsocket import util
from mod_pywebsocket.http_header_util import quote_if_necessary


# The list of available server side extension processor classes.
_available_processors = {}
_compression_extension_names = []


class ExtensionProcessorInterface(object):

    def __init__(self, request):
        self._logger = util.get_class_logger(self)

        self._request = request
        self._active = True

    def request(self):
        return self._request

    def name(self):
        return None

    def check_consistency_with_other_processors(self, processors):
        pass

    def set_active(self, active):
        self._active = active

    def is_active(self):
        return self._active

    def _get_extension_response_internal(self):
        return None

    def get_extension_response(self):
        if not self._active:
            self._logger.debug('Extension %s is deactivated', self.name())
            return None

        response = self._get_extension_response_internal()
        if response is None:
            self._active = False
        return response

    def _setup_stream_options_internal(self, stream_options):
        pass

    def setup_stream_options(self, stream_options):
        if self._active:
            self._setup_stream_options_internal(stream_options)


def _log_outgoing_compression_ratio(
        logger, original_bytes, filtered_bytes, average_ratio):
    # Print inf when ratio is not available.
    ratio = float('inf')
    if original_bytes != 0:
        ratio = float(filtered_bytes) / original_bytes

    logger.debug('Outgoing compression ratio: %f (average: %f)' %
            (ratio, average_ratio))


def _log_incoming_compression_ratio(
        logger, received_bytes, filtered_bytes, average_ratio):
    # Print inf when ratio is not available.
    ratio = float('inf')
    if filtered_bytes != 0:
        ratio = float(received_bytes) / filtered_bytes

    logger.debug('Incoming compression ratio: %f (average: %f)' %
            (ratio, average_ratio))


def _parse_window_bits(bits):
    """Return parsed integer value iff the given string conforms to the
    grammar of the window bits extension parameters.
    """

    if bits is None:
        raise ValueError('Value is required')

    # For non integer values such as "10.0", ValueError will be raised.
    int_bits = int(bits)

    # First condition is to drop leading zero case e.g. "08".
    if bits != str(int_bits) or int_bits < 8 or int_bits > 15:
        raise ValueError('Invalid value: %r' % bits)

    return int_bits


class _AverageRatioCalculator(object):
    """Stores total bytes of original and result data, and calculates average
    result / original ratio.
    """

    def __init__(self):
        self._total_original_bytes = 0
        self._total_result_bytes = 0

    def add_original_bytes(self, value):
        self._total_original_bytes += value

    def add_result_bytes(self, value):
        self._total_result_bytes += value

    def get_average_ratio(self):
        if self._total_original_bytes != 0:
            return (float(self._total_result_bytes) /
                    self._total_original_bytes)
        else:
            return float('inf')


class DeflateFrameExtensionProcessor(ExtensionProcessorInterface):
    """deflate-frame extension processor.

    Specification:
    http://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate
    """

    _WINDOW_BITS_PARAM = 'max_window_bits'
    _NO_CONTEXT_TAKEOVER_PARAM = 'no_context_takeover'

    def __init__(self, request):
        ExtensionProcessorInterface.__init__(self, request)
        self._logger = util.get_class_logger(self)

        self._response_window_bits = None
        self._response_no_context_takeover = False
        self._bfinal = False

        # Calculates
        #     (Total outgoing bytes supplied to this filter) /
        #     (Total bytes sent to the network after applying this filter)
        self._outgoing_average_ratio_calculator = _AverageRatioCalculator()

        # Calculates
        #     (Total bytes received from the network) /
        #     (Total incoming bytes obtained after applying this filter)
        self._incoming_average_ratio_calculator = _AverageRatioCalculator()

    def name(self):
        return common.DEFLATE_FRAME_EXTENSION

    def _get_extension_response_internal(self):
        # Any unknown parameter will be just ignored.

        window_bits = None
        if self._request.has_parameter(self._WINDOW_BITS_PARAM):
            window_bits = self._request.get_parameter_value(
                self._WINDOW_BITS_PARAM)
            try:
                window_bits = _parse_window_bits(window_bits)
            except ValueError as e:
                return None

        no_context_takeover = self._request.has_parameter(
            self._NO_CONTEXT_TAKEOVER_PARAM)
        if (no_context_takeover and
            self._request.get_parameter_value(
                self._NO_CONTEXT_TAKEOVER_PARAM) is not None):
            return None

        self._rfc1979_deflater = util._RFC1979Deflater(
            window_bits, no_context_takeover)

        self._rfc1979_inflater = util._RFC1979Inflater()

        self._compress_outgoing = True

        response = common.ExtensionParameter(self._request.name())

        if self._response_window_bits is not None:
            response.add_parameter(
                self._WINDOW_BITS_PARAM, str(self._response_window_bits))
        if self._response_no_context_takeover:
            response.add_parameter(
                self._NO_CONTEXT_TAKEOVER_PARAM, None)

        self._logger.debug(
            'Enable %s extension ('
            'request: window_bits=%s; no_context_takeover=%r, '
            'response: window_wbits=%s; no_context_takeover=%r)' %
            (self._request.name(),
             window_bits,
             no_context_takeover,
             self._response_window_bits,
             self._response_no_context_takeover))

        return response

    def _setup_stream_options_internal(self, stream_options):

        class _OutgoingFilter(object):

            def __init__(self, parent):
                self._parent = parent

            def filter(self, frame):
                self._parent._outgoing_filter(frame)

        class _IncomingFilter(object):

            def __init__(self, parent):
                self._parent = parent

            def filter(self, frame):
                self._parent._incoming_filter(frame)

        stream_options.outgoing_frame_filters.append(
            _OutgoingFilter(self))
        stream_options.incoming_frame_filters.insert(
            0, _IncomingFilter(self))

    def set_response_window_bits(self, value):
        self._response_window_bits = value

    def set_response_no_context_takeover(self, value):
        self._response_no_context_takeover = value

    def set_bfinal(self, value):
        self._bfinal = value

    def enable_outgoing_compression(self):
        self._compress_outgoing = True

    def disable_outgoing_compression(self):
        self._compress_outgoing = False

    def _outgoing_filter(self, frame):
        """Transform outgoing frames. This method is called only by
        an _OutgoingFilter instance.
        """

        original_payload_size = len(frame.payload)
        self._outgoing_average_ratio_calculator.add_original_bytes(
                original_payload_size)

        if (not self._compress_outgoing or
            common.is_control_opcode(frame.opcode)):
            self._outgoing_average_ratio_calculator.add_result_bytes(
                    original_payload_size)
            return

        frame.payload = self._rfc1979_deflater.filter(
            frame.payload, bfinal=self._bfinal)
        frame.rsv1 = 1

        filtered_payload_size = len(frame.payload)
        self._outgoing_average_ratio_calculator.add_result_bytes(
                filtered_payload_size)

        _log_outgoing_compression_ratio(
                self._logger,
                original_payload_size,
                filtered_payload_size,
                self._outgoing_average_ratio_calculator.get_average_ratio())

    def _incoming_filter(self, frame):
        """Transform incoming frames. This method is called only by
        an _IncomingFilter instance.
        """

        received_payload_size = len(frame.payload)
        self._incoming_average_ratio_calculator.add_result_bytes(
                received_payload_size)

        if frame.rsv1 != 1 or common.is_control_opcode(frame.opcode):
            self._incoming_average_ratio_calculator.add_original_bytes(
                    received_payload_size)
            return

        frame.payload = self._rfc1979_inflater.filter(frame.payload)
        frame.rsv1 = 0

        filtered_payload_size = len(frame.payload)
        self._incoming_average_ratio_calculator.add_original_bytes(
                filtered_payload_size)

        _log_incoming_compression_ratio(
                self._logger,
                received_payload_size,
                filtered_payload_size,
                self._incoming_average_ratio_calculator.get_average_ratio())


_available_processors[common.DEFLATE_FRAME_EXTENSION] = (
    DeflateFrameExtensionProcessor)
_compression_extension_names.append(common.DEFLATE_FRAME_EXTENSION)

_available_processors[common.X_WEBKIT_DEFLATE_FRAME_EXTENSION] = (
    DeflateFrameExtensionProcessor)
_compression_extension_names.append(common.X_WEBKIT_DEFLATE_FRAME_EXTENSION)


def _parse_compression_method(data):
    """Parses the value of "method" extension parameter."""

    return common.parse_extensions(data)


def _create_accepted_method_desc(method_name, method_params):
    """Creates accepted-method-desc from given method name and parameters"""

    extension = common.ExtensionParameter(method_name)
    for name, value in method_params:
        extension.add_parameter(name, value)
    return common.format_extension(extension)


class CompressionExtensionProcessorBase(ExtensionProcessorInterface):
    """Base class for perframe-compress and permessage-compress extension."""

    _METHOD_PARAM = 'method'

    def __init__(self, request):
        ExtensionProcessorInterface.__init__(self, request)
        self._logger = util.get_class_logger(self)
        self._compression_method_name = None
        self._compression_processor = None
        self._compression_processor_hook = None

    def name(self):
        return ''

    def _lookup_compression_processor(self, method_desc):
        return None

    def _get_compression_processor_response(self):
        """Looks up the compression processor based on the self._request and
           returns the compression processor's response.
        """

        method_list = self._request.get_parameter_value(self._METHOD_PARAM)
        if method_list is None:
            return None
        methods = _parse_compression_method(method_list)
        if methods is None:
            return None
        comression_processor = None
        # The current implementation tries only the first method that matches
        # supported algorithm. Following methods aren't tried even if the
        # first one is rejected.
        # TODO(bashi): Need to clarify this behavior.
        for method_desc in methods:
            compression_processor = self._lookup_compression_processor(
                method_desc)
            if compression_processor is not None:
                self._compression_method_name = method_desc.name()
                break
        if compression_processor is None:
            return None

        if self._compression_processor_hook:
            self._compression_processor_hook(compression_processor)

        processor_response = compression_processor.get_extension_response()
        if processor_response is None:
            return None
        self._compression_processor = compression_processor
        return processor_response

    def _get_extension_response_internal(self):
        processor_response = self._get_compression_processor_response()
        if processor_response is None:
            return None

        response = common.ExtensionParameter(self._request.name())
        accepted_method_desc = _create_accepted_method_desc(
                                   self._compression_method_name,
                                   processor_response.get_parameters())
        response.add_parameter(self._METHOD_PARAM, accepted_method_desc)
        self._logger.debug(
            'Enable %s extension (method: %s)' %
            (self._request.name(), self._compression_method_name))
        return response

    def _setup_stream_options_internal(self, stream_options):
        if self._compression_processor is None:
            return
        self._compression_processor.setup_stream_options(stream_options)

    def set_compression_processor_hook(self, hook):
        self._compression_processor_hook = hook

    def get_compression_processor(self):
        return self._compression_processor


class PerMessageDeflateExtensionProcessor(ExtensionProcessorInterface):
    """permessage-deflate extension processor. It's also used for
    permessage-compress extension when the deflate method is chosen.

    Specification:
    http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-08
    """

    _SERVER_MAX_WINDOW_BITS_PARAM = 'server_max_window_bits'
    _SERVER_NO_CONTEXT_TAKEOVER_PARAM = 'server_no_context_takeover'
    _CLIENT_MAX_WINDOW_BITS_PARAM = 'client_max_window_bits'
    _CLIENT_NO_CONTEXT_TAKEOVER_PARAM = 'client_no_context_takeover'

    def __init__(self, request, draft08=True):
        """Construct PerMessageDeflateExtensionProcessor

        Args:
            draft08: Follow the constraints on the parameters that were not
                specified for permessage-compress but are specified for
                permessage-deflate as on
                draft-ietf-hybi-permessage-compression-08.
        """

        ExtensionProcessorInterface.__init__(self, request)
        self._logger = util.get_class_logger(self)

        self._preferred_client_max_window_bits = None
        self._client_no_context_takeover = False

        self._draft08 = draft08

    def name(self):
        return 'deflate'

    def _get_extension_response_internal(self):
        if self._draft08:
            for name in self._request.get_parameter_names():
                if name not in [self._SERVER_MAX_WINDOW_BITS_PARAM,
                                self._SERVER_NO_CONTEXT_TAKEOVER_PARAM,
                                self._CLIENT_MAX_WINDOW_BITS_PARAM]:
                    self._logger.debug('Unknown parameter: %r', name)
                    return None
        else:
            # Any unknown parameter will be just ignored.
            pass

        server_max_window_bits = None
        if self._request.has_parameter(self._SERVER_MAX_WINDOW_BITS_PARAM):
            server_max_window_bits = self._request.get_parameter_value(
                    self._SERVER_MAX_WINDOW_BITS_PARAM)
            try:
                server_max_window_bits = _parse_window_bits(
                    server_max_window_bits)
            except ValueError as e:
                self._logger.debug('Bad %s parameter: %r',
                                   self._SERVER_MAX_WINDOW_BITS_PARAM,
                                   e)
                return None

        server_no_context_takeover = self._request.has_parameter(
            self._SERVER_NO_CONTEXT_TAKEOVER_PARAM)
        if (server_no_context_takeover and
            self._request.get_parameter_value(
                self._SERVER_NO_CONTEXT_TAKEOVER_PARAM) is not None):
            self._logger.debug('%s parameter must not have a value: %r',
                               self._SERVER_NO_CONTEXT_TAKEOVER_PARAM,
                               server_no_context_takeover)
            return None

        # client_max_window_bits from a client indicates whether the client can
        # accept client_max_window_bits from a server or not.
        client_client_max_window_bits = self._request.has_parameter(
            self._CLIENT_MAX_WINDOW_BITS_PARAM)
        if (self._draft08 and
            client_client_max_window_bits and
            self._request.get_parameter_value(
                self._CLIENT_MAX_WINDOW_BITS_PARAM) is not None):
            self._logger.debug('%s parameter must not have a value in a '
                               'client\'s opening handshake: %r',
                               self._CLIENT_MAX_WINDOW_BITS_PARAM,
                               client_client_max_window_bits)
            return None

        self._rfc1979_deflater = util._RFC1979Deflater(
            server_max_window_bits, server_no_context_takeover)

        # Note that we prepare for incoming messages compressed with window
        # bits upto 15 regardless of the client_max_window_bits value to be
        # sent to the client.
        self._rfc1979_inflater = util._RFC1979Inflater()

        self._framer = _PerMessageDeflateFramer(
            server_max_window_bits, server_no_context_takeover)
        self._framer.set_bfinal(False)
        self._framer.set_compress_outgoing_enabled(True)

        response = common.ExtensionParameter(self._request.name())

        if server_max_window_bits is not None:
            response.add_parameter(
                self._SERVER_MAX_WINDOW_BITS_PARAM,
                str(server_max_window_bits))

        if server_no_context_takeover:
            response.add_parameter(
                self._SERVER_NO_CONTEXT_TAKEOVER_PARAM, None)

        if self._preferred_client_max_window_bits is not None:
            if self._draft08 and not client_client_max_window_bits:
                self._logger.debug('Processor is configured to use %s but '
                                   'the client cannot accept it',
                                   self._CLIENT_MAX_WINDOW_BITS_PARAM)
                return None
            response.add_parameter(
                self._CLIENT_MAX_WINDOW_BITS_PARAM,
                str(self._preferred_client_max_window_bits))

        if self._client_no_context_takeover:
            response.add_parameter(
                self._CLIENT_NO_CONTEXT_TAKEOVER_PARAM, None)

        self._logger.debug(
            'Enable %s extension ('
            'request: server_max_window_bits=%s; '
            'server_no_context_takeover=%r, '
            'response: client_max_window_bits=%s; '
            'client_no_context_takeover=%r)' %
            (self._request.name(),
             server_max_window_bits,
             server_no_context_takeover,
             self._preferred_client_max_window_bits,
             self._client_no_context_takeover))

        return response

    def _setup_stream_options_internal(self, stream_options):
        self._framer.setup_stream_options(stream_options)

    def set_client_max_window_bits(self, value):
        """If this option is specified, this class adds the
        client_max_window_bits extension parameter to the handshake response,
        but doesn't reduce the LZ77 sliding window size of its inflater.
        I.e., you can use this for testing client implementation but cannot
        reduce memory usage of this class.

        If this method has been called with True and an offer without the
        client_max_window_bits extension parameter is received,
        - (When processing the permessage-deflate extension) this processor
          declines the request.
        - (When processing the permessage-compress extension) this processor
          accepts the request.
        """

        self._preferred_client_max_window_bits = value

    def set_client_no_context_takeover(self, value):
        """If this option is specified, this class adds the
        client_no_context_takeover extension parameter to the handshake
        response, but doesn't reset inflater for each message. I.e., you can
        use this for testing client implementation but cannot reduce memory
        usage of this class.
        """

        self._client_no_context_takeover = value

    def set_bfinal(self, value):
        self._framer.set_bfinal(value)

    def enable_outgoing_compression(self):
        self._framer.set_compress_outgoing_enabled(True)

    def disable_outgoing_compression(self):
        self._framer.set_compress_outgoing_enabled(False)


class _PerMessageDeflateFramer(object):
    """A framer for extensions with per-message DEFLATE feature."""

    def __init__(self, deflate_max_window_bits, deflate_no_context_takeover):
        self._logger = util.get_class_logger(self)

        self._rfc1979_deflater = util._RFC1979Deflater(
            deflate_max_window_bits, deflate_no_context_takeover)

        self._rfc1979_inflater = util._RFC1979Inflater()

        self._bfinal = False

        self._compress_outgoing_enabled = False

        # True if a message is fragmented and compression is ongoing.
        self._compress_ongoing = False

        # Calculates
        #     (Total outgoing bytes supplied to this filter) /
        #     (Total bytes sent to the network after applying this filter)
        self._outgoing_average_ratio_calculator = _AverageRatioCalculator()

        # Calculates
        #     (Total bytes received from the network) /
        #     (Total incoming bytes obtained after applying this filter)
        self._incoming_average_ratio_calculator = _AverageRatioCalculator()

    def set_bfinal(self, value):
        self._bfinal = value

    def set_compress_outgoing_enabled(self, value):
        self._compress_outgoing_enabled = value

    def _process_incoming_message(self, message, decompress):
        if not decompress:
            return message

        received_payload_size = len(message)
        self._incoming_average_ratio_calculator.add_result_bytes(
                received_payload_size)

        message = self._rfc1979_inflater.filter(message)

        filtered_payload_size = len(message)
        self._incoming_average_ratio_calculator.add_original_bytes(
                filtered_payload_size)

        _log_incoming_compression_ratio(
                self._logger,
                received_payload_size,
                filtered_payload_size,
                self._incoming_average_ratio_calculator.get_average_ratio())

        return message

    def _process_outgoing_message(self, message, end, binary):
        if not binary:
            message = message.encode('utf-8')

        if not self._compress_outgoing_enabled:
            return message

        original_payload_size = len(message)
        self._outgoing_average_ratio_calculator.add_original_bytes(
            original_payload_size)

        message = self._rfc1979_deflater.filter(
            message, end=end, bfinal=self._bfinal)

        filtered_payload_size = len(message)
        self._outgoing_average_ratio_calculator.add_result_bytes(
            filtered_payload_size)

        _log_outgoing_compression_ratio(
                self._logger,
                original_payload_size,
                filtered_payload_size,
                self._outgoing_average_ratio_calculator.get_average_ratio())

        if not self._compress_ongoing:
            self._outgoing_frame_filter.set_compression_bit()
        self._compress_ongoing = not end
        return message

    def _process_incoming_frame(self, frame):
        if frame.rsv1 == 1 and not common.is_control_opcode(frame.opcode):
            self._incoming_message_filter.decompress_next_message()
            frame.rsv1 = 0

    def _process_outgoing_frame(self, frame, compression_bit):
        if (not compression_bit or
            common.is_control_opcode(frame.opcode)):
            return

        frame.rsv1 = 1

    def setup_stream_options(self, stream_options):
        """Creates filters and sets them to the StreamOptions."""

        class _OutgoingMessageFilter(object):

            def __init__(self, parent):
                self._parent = parent

            def filter(self, message, end=True, binary=False):
                return self._parent._process_outgoing_message(
                    message, end, binary)

        class _IncomingMessageFilter(object):

            def __init__(self, parent):
                self._parent = parent
                self._decompress_next_message = False

            def decompress_next_message(self):
                self._decompress_next_message = True

            def filter(self, message):
                message = self._parent._process_incoming_message(
                    message, self._decompress_next_message)
                self._decompress_next_message = False
                return message

        self._outgoing_message_filter = _OutgoingMessageFilter(self)
        self._incoming_message_filter = _IncomingMessageFilter(self)
        stream_options.outgoing_message_filters.append(
            self._outgoing_message_filter)
        stream_options.incoming_message_filters.append(
            self._incoming_message_filter)

        class _OutgoingFrameFilter(object):

            def __init__(self, parent):
                self._parent = parent
                self._set_compression_bit = False

            def set_compression_bit(self):
                self._set_compression_bit = True

            def filter(self, frame):
                self._parent._process_outgoing_frame(
                    frame, self._set_compression_bit)
                self._set_compression_bit = False

        class _IncomingFrameFilter(object):

            def __init__(self, parent):
                self._parent = parent

            def filter(self, frame):
                self._parent._process_incoming_frame(frame)

        self._outgoing_frame_filter = _OutgoingFrameFilter(self)
        self._incoming_frame_filter = _IncomingFrameFilter(self)
        stream_options.outgoing_frame_filters.append(
            self._outgoing_frame_filter)
        stream_options.incoming_frame_filters.append(
            self._incoming_frame_filter)

        stream_options.encode_text_message_to_utf8 = False


_available_processors[common.PERMESSAGE_DEFLATE_EXTENSION] = (
        PerMessageDeflateExtensionProcessor)
# TODO(tyoshino): Reorganize class names.
_compression_extension_names.append('deflate')


class PerMessageCompressExtensionProcessor(
    CompressionExtensionProcessorBase):
    """permessage-compress extension processor.

    Specification:
    http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression
    """

    _DEFLATE_METHOD = 'deflate'

    def __init__(self, request):
        CompressionExtensionProcessorBase.__init__(self, request)

    def name(self):
        return common.PERMESSAGE_COMPRESSION_EXTENSION

    def _lookup_compression_processor(self, method_desc):
        if method_desc.name() == self._DEFLATE_METHOD:
            return PerMessageDeflateExtensionProcessor(method_desc, False)
        return None


_available_processors[common.PERMESSAGE_COMPRESSION_EXTENSION] = (
    PerMessageCompressExtensionProcessor)
_compression_extension_names.append(common.PERMESSAGE_COMPRESSION_EXTENSION)


class MuxExtensionProcessor(ExtensionProcessorInterface):
    """WebSocket multiplexing extension processor."""

    _QUOTA_PARAM = 'quota'

    def __init__(self, request):
        ExtensionProcessorInterface.__init__(self, request)
        self._quota = 0
        self._extensions = []

    def name(self):
        return common.MUX_EXTENSION

    def check_consistency_with_other_processors(self, processors):
        before_mux = True
        for processor in processors:
            name = processor.name()
            if name == self.name():
                before_mux = False
                continue
            if not processor.is_active():
                continue
            if before_mux:
                # Mux extension cannot be used after extensions
                # that depend on frame boundary, extension data field, or any
                # reserved bits which are attributed to each frame.
                if (name == common.DEFLATE_FRAME_EXTENSION or
                    name == common.X_WEBKIT_DEFLATE_FRAME_EXTENSION):
                    self.set_active(False)
                    return
            else:
                # Mux extension should not be applied before any history-based
                # compression extension.
                if (name == common.DEFLATE_FRAME_EXTENSION or
                    name == common.X_WEBKIT_DEFLATE_FRAME_EXTENSION or
                    name == common.PERMESSAGE_COMPRESSION_EXTENSION or
                    name == common.X_WEBKIT_PERMESSAGE_COMPRESSION_EXTENSION):
                    self.set_active(False)
                    return

    def _get_extension_response_internal(self):
        self._active = False
        quota = self._request.get_parameter_value(self._QUOTA_PARAM)
        if quota is not None:
            try:
                quota = int(quota)
            except ValueError as e:
                return None
            if quota < 0 or quota >= 2 ** 32:
                return None
            self._quota = quota

        self._active = True
        return common.ExtensionParameter(common.MUX_EXTENSION)

    def _setup_stream_options_internal(self, stream_options):
        pass

    def set_quota(self, quota):
        self._quota = quota

    def quota(self):
        return self._quota

    def set_extensions(self, extensions):
        self._extensions = extensions

    def extensions(self):
        return self._extensions


_available_processors[common.MUX_EXTENSION] = MuxExtensionProcessor


def get_extension_processor(extension_request):
    """Given an ExtensionParameter representing an extension offer received
    from a client, configures and returns an instance of the corresponding
    extension processor class.
    """

    processor_class = _available_processors.get(extension_request.name())
    if processor_class is None:
        return None
    return processor_class(extension_request)


def is_compression_extension(extension_name):
    return extension_name in _compression_extension_names


# vi:sts=4 sw=4 et
