diff options
Diffstat (limited to 'testing/web-platform/tests/tools/third_party/pywebsocket3/mod_pywebsocket/extensions.py')
-rw-r--r-- | testing/web-platform/tests/tools/third_party/pywebsocket3/mod_pywebsocket/extensions.py | 474 |
1 files changed, 0 insertions, 474 deletions
diff --git a/testing/web-platform/tests/tools/third_party/pywebsocket3/mod_pywebsocket/extensions.py b/testing/web-platform/tests/tools/third_party/pywebsocket3/mod_pywebsocket/extensions.py deleted file mode 100644 index 314a949d45..0000000000 --- a/testing/web-platform/tests/tools/third_party/pywebsocket3/mod_pywebsocket/extensions.py +++ /dev/null @@ -1,474 +0,0 @@ -# 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 __future__ import absolute_import -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 = {} - - -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 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): - """Construct PerMessageDeflateExtensionProcessor.""" - - ExtensionProcessorInterface.__init__(self, request) - self._logger = util.get_class_logger(self) - - self._preferred_client_max_window_bits = None - self._client_no_context_takeover = False - - def name(self): - # This method returns "deflate" (not "permessage-deflate") for - # compatibility. - return 'deflate' - - 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 - - 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) - - -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) - - -# vi:sts=4 sw=4 et |