Example #1
0
class DeflateFrameExtensionProcessor(ExtensionProcessorInterface):
    """WebSocket Per-frame DEFLATE extension processor."""

    _WINDOW_BITS_PARAM = 'window_bits'
    _NO_CONTEXT_TAKEOVER_PARAM = 'no_context_takeover'

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

        self._request = request

        self._response_window_bits = None
        self._response_no_context_takeover = False

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

        window_bits = self._request.get_parameter_value(
            self._WINDOW_BITS_PARAM)
        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

        if window_bits is not None:
            try:
                window_bits = int(window_bits)
            except ValueError, e:
                return None
            if window_bits < 8 or window_bits > 15:
                return None

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

        self._inflater = util._RFC1979Inflater()

        self._compress_outgoing = True

        response = common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION)

        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)' %
            (common.DEFLATE_STREAM_EXTENSION, window_bits, no_context_takeover,
             self._response_window_bits, self._response_no_context_takeover))

        return response
Example #2
0
    def __init__(self, socket, handshake):
        self._handshake = handshake
        self._socket = socket

        # Filters applied to application data part of data frames.
        self._outgoing_frame_filter = None
        self._incoming_frame_filter = None

        if self._handshake._options.use_deflate_frame:
            self._outgoing_frame_filter = (util._RFC1979Deflater(None, False))
            self._incoming_frame_filter = util._RFC1979Inflater()

        self._fragmented = False
Example #3
0
    def _get_extension_response_internal(self):
        # Any unknown parameter will be just ignored.

        s2c_max_window_bits = self._request.get_parameter_value(
            self._S2C_MAX_WINDOW_BITS_PARAM)
        if not _validate_window_bits(s2c_max_window_bits):
            return None

        s2c_no_context_takeover = self._request.has_parameter(
            self._S2C_NO_CONTEXT_TAKEOVER_PARAM)
        if (s2c_no_context_takeover and
            self._request.get_parameter_value(
                self._S2C_NO_CONTEXT_TAKEOVER_PARAM) is not None):
            return None

        self._deflater = util._RFC1979Deflater(
            s2c_max_window_bits, s2c_no_context_takeover)

        self._inflater = util._RFC1979Inflater()

        self._compress_outgoing_enabled = True

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

        if s2c_max_window_bits is not None:
            response.add_parameter(
                self._S2C_MAX_WINDOW_BITS_PARAM, str(s2c_max_window_bits))

        if s2c_no_context_takeover:
            response.add_parameter(
                self._S2C_NO_CONTEXT_TAKEOVER_PARAM, None)

        if self._c2s_max_window_bits is not None:
            response.add_parameter(
                self._C2S_MAX_WINDOW_BITS_PARAM,
                str(self._c2s_max_window_bits))
        if self._c2s_no_context_takeover:
            response.add_parameter(
                self._C2S_NO_CONTEXT_TAKEOVER_PARAM, None)

        self._logger.debug(
            'Enable %s extension ('
            'request: s2c_max_window_bits=%s; s2c_no_context_takeover=%r, '
            'response: c2s_max_window_bits=%s; c2s_no_context_takeover=%r)' %
            (self._request.name(),
             s2c_max_window_bits,
             s2c_no_context_takeover,
             self._c2s_max_window_bits,
             self._c2s_no_context_takeover))

        return response
Example #4
0
    def __init__(self, socket, handshake):
        self._handshake = handshake
        self._socket = socket

        # Filters applied to application data part of data frames.
        self._outgoing_frame_filter = None
        self._incoming_frame_filter = None

        if self._handshake._options.use_deflate_frame:
            self._outgoing_frame_filter = (
                util._RFC1979Deflater(None, False))
            self._incoming_frame_filter = util._RFC1979Inflater()

        self._fragmented = False
Example #5
0
    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
Example #6
0
    def _get_extension_response_internal(self):
        # Any unknown parameter will be just ignored.

        s2c_max_window_bits = self._request.get_parameter_value(
            self._S2C_MAX_WINDOW_BITS_PARAM)
        if not _validate_window_bits(s2c_max_window_bits):
            return None

        s2c_no_context_takeover = self._request.has_parameter(
            self._S2C_NO_CONTEXT_TAKEOVER_PARAM)
        if (s2c_no_context_takeover and self._request.get_parameter_value(
                self._S2C_NO_CONTEXT_TAKEOVER_PARAM) is not None):
            return None

        self._deflater = util._RFC1979Deflater(s2c_max_window_bits,
                                               s2c_no_context_takeover)

        self._inflater = util._RFC1979Inflater()

        self._compress_outgoing_enabled = True

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

        if s2c_max_window_bits is not None:
            response.add_parameter(self._S2C_MAX_WINDOW_BITS_PARAM,
                                   str(s2c_max_window_bits))

        if s2c_no_context_takeover:
            response.add_parameter(self._S2C_NO_CONTEXT_TAKEOVER_PARAM, None)

        if self._c2s_max_window_bits is not None:
            response.add_parameter(self._C2S_MAX_WINDOW_BITS_PARAM,
                                   str(self._c2s_max_window_bits))
        if self._c2s_no_context_takeover:
            response.add_parameter(self._C2S_NO_CONTEXT_TAKEOVER_PARAM, None)

        self._logger.debug(
            'Enable %s extension ('
            'request: s2c_max_window_bits=%s; s2c_no_context_takeover=%r, '
            'response: c2s_max_window_bits=%s; c2s_no_context_takeover=%r)' %
            (self._request.name(), s2c_max_window_bits,
             s2c_no_context_takeover, self._c2s_max_window_bits,
             self._c2s_no_context_takeover))

        return response
Example #7
0
    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()
Example #8
0
    def _get_extension_response_internal(self):
        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

        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 (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 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
Example #9
0
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
    """

    _S2C_MAX_WINDOW_BITS_PARAM = 's2c_max_window_bits'
    _S2C_NO_CONTEXT_TAKEOVER_PARAM = 's2c_no_context_takeover'
    _C2S_MAX_WINDOW_BITS_PARAM = 'c2s_max_window_bits'
    _C2S_NO_CONTEXT_TAKEOVER_PARAM = 'c2s_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._c2s_max_window_bits = None
        self._c2s_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._S2C_MAX_WINDOW_BITS_PARAM,
                                self._S2C_NO_CONTEXT_TAKEOVER_PARAM,
                                self._C2S_MAX_WINDOW_BITS_PARAM]:
                    self._logger.debug('Unknown parameter: %r', name)
                    return None
        else:
            # Any unknown parameter will be just ignored.
            pass

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

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

        c2s_max_window_bits = self._request.has_parameter(
            self._C2S_MAX_WINDOW_BITS_PARAM)
        if (self._draft08 and
            c2s_max_window_bits and
            self._request.get_parameter_value(
                self._C2S_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._C2S_MAX_WINDOW_BITS_PARAM,
                               c2s_max_window_bits)
            return None

        self._rfc1979_deflater = util._RFC1979Deflater(
            s2c_max_window_bits, s2c_no_context_takeover)

        self._rfc1979_inflater = util._RFC1979Inflater()

        self._framer = _PerMessageDeflateFramer(
            s2c_max_window_bits, s2c_no_context_takeover)
        self._framer.set_bfinal(False)
        self._framer.set_compress_outgoing_enabled(True)

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

        if s2c_max_window_bits is not None:
            response.add_parameter(
                self._S2C_MAX_WINDOW_BITS_PARAM, str(s2c_max_window_bits))

        if s2c_no_context_takeover:
            response.add_parameter(
                self._S2C_NO_CONTEXT_TAKEOVER_PARAM, None)

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

        if self._c2s_no_context_takeover:
            response.add_parameter(
                self._C2S_NO_CONTEXT_TAKEOVER_PARAM, None)

        self._logger.debug(
            'Enable %s extension ('
            'request: s2c_max_window_bits=%s; s2c_no_context_takeover=%r, '
            'response: c2s_max_window_bits=%s; c2s_no_context_takeover=%r)' %
            (self._request.name(),
             s2c_max_window_bits,
             s2c_no_context_takeover,
             self._c2s_max_window_bits,
             self._c2s_no_context_takeover))

        return response
Example #10
0
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, 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
Example #11
0
class PerMessageDeflateExtensionProcessor(ExtensionProcessorInterface):
    """permessage-deflate extension processor.

    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):
        # This method returns "deflate" (not "permessage-deflate") for
        # compatibility.
        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, 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
Example #12
0
class DeflateMessageProcessor(ExtensionProcessorInterface):
    """Per-message deflate processor."""

    _S2C_MAX_WINDOW_BITS_PARAM = 's2c_max_window_bits'
    _S2C_NO_CONTEXT_TAKEOVER_PARAM = 's2c_no_context_takeover'
    _C2S_MAX_WINDOW_BITS_PARAM = 'c2s_max_window_bits'
    _C2S_NO_CONTEXT_TAKEOVER_PARAM = 'c2s_no_context_takeover'

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

        self._c2s_max_window_bits = None
        self._c2s_no_context_takeover = False

        self._compress_outgoing = False

        # Counters for statistics.

        # Total number of outgoing bytes supplied to this filter.
        self._total_outgoing_payload_bytes = 0
        # Total number of bytes sent to the network after applying this filter.
        self._total_filtered_outgoing_payload_bytes = 0

        # Total number of bytes received from the network.
        self._total_incoming_payload_bytes = 0
        # Total number of incoming bytes obtained after applying this filter.
        self._total_filtered_incoming_payload_bytes = 0

    def name(self):
        return 'deflate'

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

        s2c_max_window_bits = self._request.get_parameter_value(
            self._S2C_MAX_WINDOW_BITS_PARAM)
        if s2c_max_window_bits is not None:
            try:
                s2c_max_window_bits = int(s2c_max_window_bits)
            except ValueError, e:
                return None
            if s2c_max_window_bits < 8 or s2c_max_window_bits > 15:
                return None

        s2c_no_context_takeover = self._request.has_parameter(
            self._S2C_NO_CONTEXT_TAKEOVER_PARAM)
        if (s2c_no_context_takeover and
            self._request.get_parameter_value(
                self._S2C_NO_CONTEXT_TAKEOVER_PARAM) is not None):
            return None

        self._deflater = util._RFC1979Deflater(
            s2c_max_window_bits, s2c_no_context_takeover)

        self._inflater = util._RFC1979Inflater()

        self._compress_outgoing = True

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

        if s2c_max_window_bits is not None:
            response.add_parameter(
                self._S2C_MAX_WINDOW_BITS_PARAM, str(s2c_max_window_bits))

        if s2c_no_context_takeover is not None:
            response.add_parameter(
                self._S2C_NO_CONTEXT_TAKEOVER_PARAM, None)

        if self._c2s_max_window_bits is not None:
            response.add_parameter(
                self._C2S_MAX_WINDOW_BITS_PARAM,
                str(self._c2s_response_window_bits))
        if self._c2s_no_context_takeover:
            response.add_parameter(
                self._C2S_NO_CONTEXT_TAKEOVER_PARAM, None)

        self._logger.debug(
            'Enable %s extension ('
            'request: s2c_max_window_bits=%s; s2c_no_context_takeover=%r, '
            'response: c2s_max_window_bits=%s; c2s_no_context_takeover=%r)' %
            (self._request.name(),
             s2c_max_window_bits,
             s2c_no_context_takeover,
             self._c2s_max_window_bits,
             self._c2s_no_context_takeover))

        return response
Example #13
0
class DeflateFrameExtensionProcessor(ExtensionProcessorInterface):
    """WebSocket Per-frame DEFLATE extension processor."""

    _WINDOW_BITS_PARAM = 'max_window_bits'
    _NO_CONTEXT_TAKEOVER_PARAM = 'no_context_takeover'

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

        self._request = request

        self._response_window_bits = None
        self._response_no_context_takeover = False

        # Counters for statistics.

        # Total number of outgoing bytes supplied to this filter.
        self._total_outgoing_payload_bytes = 0
        # Total number of bytes sent to the network after applying this filter.
        self._total_filtered_outgoing_payload_bytes = 0

        # Total number of bytes received from the network.
        self._total_incoming_payload_bytes = 0
        # Total number of incoming bytes obtained after applying this filter.
        self._total_filtered_incoming_payload_bytes = 0

    def name(self):
        return common.DEFLATE_FRAME_EXTENSION

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

        window_bits = self._request.get_parameter_value(
            self._WINDOW_BITS_PARAM)
        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

        if window_bits is not None:
            try:
                window_bits = int(window_bits)
            except ValueError, e:
                return None
            if window_bits < 8 or window_bits > 15:
                return None

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

        self._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