[Python-modules-commits] [python-mod-pywebsocket] 01/04: Imported Upstream version 0.8

Takaki Taniguchi takaki at moszumanska.debian.org
Tue Feb 2 07:51:42 UTC 2016


This is an automated email from the git hooks/post-receive script.

takaki pushed a commit to annotated tag debian/0.8-1
in repository python-mod-pywebsocket.

commit 36dd185ba8118fb432057ad7ada50f9eff47643d
Author: TANIGUCHI Takaki <takaki at asis.media-as.org>
Date:   Tue Feb 2 16:25:48 2016 +0900

    Imported Upstream version 0.8
---
 src/example/arraybuffer_benchmark.html          |  32 +-
 src/example/benchmark.html                      | 137 +++---
 src/example/console.html                        |  14 +-
 src/example/cookie_wsh.py                       |  32 ++
 src/example/echo_client.py                      | 134 ++++--
 src/example/eventsource.cgi                     |   6 +-
 src/example/eventsource.html                    |  17 +-
 src/example/util.js                             |  51 +++
 src/example/xhr_benchmark.html                  | 310 +++++++++++++
 src/mod_pywebsocket/__init__.py                 |  27 ++
 src/mod_pywebsocket/_stream_hybi.py             |  32 +-
 src/mod_pywebsocket/common.py                   |  19 +-
 src/mod_pywebsocket/deflate_stream_extension.py |  69 ---
 src/mod_pywebsocket/extensions.py               | 579 +++++++++++++++---------
 src/mod_pywebsocket/handshake/hybi.py           |  34 +-
 src/mod_pywebsocket/mux.py                      |   7 -
 src/mod_pywebsocket/standalone.py               |  32 +-
 src/mod_pywebsocket/util.py                     | 138 +-----
 src/mod_pywebsocket/xhr_benchmark_handler.py    | 110 +++++
 src/setup.py                                    |   2 +-
 src/test/client_for_testing.py                  |  87 ++--
 src/test/mock.py                                |   5 -
 src/test/mux_client_for_testing.py              |  12 +-
 src/test/run_all.py                             |   7 +-
 src/test/test_endtoend.py                       | 390 +++++++++++++---
 src/test/test_extensions.py                     | 249 +++++++++-
 src/test/test_handshake.py                      |  38 +-
 src/test/test_handshake_hybi.py                 |  21 +-
 src/test/test_handshake_hybi08.py               | 306 -------------
 src/test/test_msgutil.py                        | 169 ++++---
 src/test/test_util.py                           |  63 +++
 31 files changed, 1938 insertions(+), 1191 deletions(-)

diff --git a/src/example/arraybuffer_benchmark.html b/src/example/arraybuffer_benchmark.html
index 19482d9..869cd7e 100644
--- a/src/example/arraybuffer_benchmark.html
+++ b/src/example/arraybuffer_benchmark.html
@@ -49,21 +49,6 @@ var MULTIPLIERS = [5, 2];
 // (such as JIT) run.
 var REPEAT_FOR_WARMUP = 3;
 
-var logBox = null;
-
-var queuedLog = '';
-
-function addToLog(log) {
-  queuedLog += log + '\n';
-}
-
-function updateLogBox() {
-  logBox.value += queuedLog;
-  logBox.scrollTop = 1000000;
-
-  queuedLog = '';
-}
-
 function writeBenchmark(size, minTotal) {
   var totalSize = 0;
   while (totalSize < minTotal) {
@@ -83,7 +68,7 @@ function readBenchmark(size, minTotal) {
     var arrayBuffer = new ArrayBuffer(size);
 
     if (!verifyArrayBuffer(arrayBuffer, 0x00)) {
-      addToLog('Verification failed');
+      queueLog('Verification failed');
       return -1;
     }
 
@@ -109,7 +94,7 @@ function runBenchmark(benchmarkFunction,
       maxSpeed = Math.max(maxSpeed,
                           calculateSpeedInKB(totalSize, startTimeInMs));
     }
-    addToLog(formatResultInKiB(size, maxSpeed, PRINT_SIZE));
+    queueLog(formatResultInKiB(size, maxSpeed, PRINT_SIZE));
 
     size *= multipliers[multiplierIndex];
     multiplierIndex = (multiplierIndex + 1) % multipliers.length;
@@ -117,28 +102,25 @@ function runBenchmark(benchmarkFunction,
 }
 
 function runBenchmarks() {
-  addToLog('Message size in KiB, Speed in kB/s');
+  queueLog('Message size in KiB, Speed in kB/s');
 
-  addToLog('Write benchmark');
+  queueLog('Write benchmark');
   runBenchmark(
       writeBenchmark, START_SIZE, STOP_THRESHOLD, MIN_TOTAL, MULTIPLIERS, 0);
-  addToLog('Finished');
+  queueLog('Finished');
 
-  addToLog('Read benchmark');
+  queueLog('Read benchmark');
   runBenchmark(
       readBenchmark, START_SIZE, STOP_THRESHOLD, MIN_TOTAL, MULTIPLIERS, 0);
   addToLog('Finished');
-
-  updateLogBox();
 }
 
 function init() {
   logBox = document.getElementById('log');
 
-  addToLog(window.navigator.userAgent.toLowerCase());
+  queueLog(window.navigator.userAgent.toLowerCase());
 
   addToLog('Started...');
-  updateLogBox();
 
   setTimeout(runBenchmarks, 0);
 }
diff --git a/src/example/benchmark.html b/src/example/benchmark.html
index a575e83..cef2bf0 100644
--- a/src/example/benchmark.html
+++ b/src/example/benchmark.html
@@ -34,47 +34,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 <title>WebSocket benchmark</title>
 <script src="util.js"></script>
 <script>
+// Namespace for holding globals.
+var benchmark = {};
+
 var PRINT_SIZE = true;
 
-// Initial size of messages.
-var SEND_START_SIZE = 10 * 1024;
-// Stops benchmark when the size of message exceeds this threshold.
-var SEND_STOP_THRESHOLD = 100000 * 1024;
-// If the size of each message is small, send/receive multiple messages until
-// the sum of sizes reaches this threshold.
-var SEND_MIN_TOTAL = 100000 * 1024;
-var SEND_MULTIPLIERS = [5, 2];
-var SEND_NUM_SOCKETS = 1;
-
-var RECEIVE_START_SIZE = 10 * 1024;
-var RECEIVE_STOP_THRESHOLD = 100000 * 1024;
-var RECEIVE_MIN_TOTAL = 100000 * 1024;
-var RECEIVE_MULTIPLIERS = [5, 2];
-var RECEIVE_NUM_SOCKETS = 1;
+var SEND_PARAMETER = {
+  numSockets: 1,
+  // Initial size of messages.
+  startSize: 100000 * 1024,
+  // Stops benchmark when the size of message exceeds this threshold.
+  stopThreshold: 100000 * 1024,
+  // If the size of each message is small, send/receive multiple messages until
+  // the sum of sizes reaches this threshold.
+  minTotal: 100000 * 1024,
+  multipliers: [5, 2],
+};
+
+var RECEIVE_PARAMETER = {
+  numSockets: 1,
+  startSize: 10 * 1024,
+  stopThreshold: 100000 * 1024,
+  minTotal: 100000 * 1024,
+  multipliers: [5, 2],
+};
 
 var sockets = [];
 var numEstablishedSockets = 0;
 
 var addressBox = null;
-var logBox = null;
 
 var timerID = null;
 
-var startTimeInMs = 0;
+benchmark.startTimeInMs = 0;
 
 var totalSize = 0;
 var totalReplied = 0;
 
-function addToLog(log) {
-  logBox.value += log + '\n'
-  logBox.scrollTop = 1000000;
-}
-
-function calculateAndLogResult(size, totalSize) {
-  var speed = calculateSpeedInKB(totalSize, startTimeInMs);
-  addToLog(formatResultInKiB(size, speed, PRINT_SIZE));
-}
-
 function destroySocket(socket) {
   socket.onopen = function() {};
   socket.onmessage = function() {};
@@ -90,28 +86,8 @@ function destroyAllSockets() {
   sockets = [];
 }
 
-function verifyAcknowledgement(message, size) {
-  if (typeof message != 'string') {
-    addToLog('Invalid ack type: ' + typeof event.data);
-    return false;
-  }
-  var parsedAck = parseInt(message);
-  if (isNaN(parsedAck)) {
-    addToLog('Invalid ack value: ' + event.data);
-    return false;
-  }
-  if (parsedAck != size) {
-    addToLog(
-        'Expected ack for ' + size + 'B but received one for ' + ack + 'B');
-    return false;
-  }
-
-  return true;
-}
-
-function buildSendBenchmarkFunction(
-    size, stopThreshold, minTotal, multipliers, multiplierIndex) {
-  if (size > stopThreshold) {
+function buildSendBenchmarkFunction(size, multiplierIndex, parameter) {
+  if (size > parameter.stopThreshold) {
     addToLog('Finished');
     destroyAllSockets();
     return function() {};
@@ -129,17 +105,15 @@ function buildSendBenchmarkFunction(
       return;
     }
 
-    calculateAndLogResult(size, totalSize);
+    calculateAndLogResult(size, benchmark.startTimeInMs, totalSize, PRINT_SIZE);
 
     timerID = setTimeout(
         buildSendBenchmarkFunction(
-            size * multipliers[multiplierIndex],
-            stopThreshold,
-            minTotal,
-            multipliers,
-            (multiplierIndex + 1) % multipliers.length),
+            size * parameter.multipliers[multiplierIndex],
+            (multiplierIndex + 1) % parameter.multipliers.length,
+            parameter),
         0);
-  }
+  };
 
   return function() {
     for (var i = 0; i < sockets.length; ++i) {
@@ -147,15 +121,14 @@ function buildSendBenchmarkFunction(
       socket.onmessage = onMessageHandler;
     }
 
-    startTimeInMs = getTimeStamp();
+    benchmark.startTimeInMs = getTimeStamp();
 
     totalReplied = 0;
 
     totalSize = 0;
 
     var socketIndex = 0;
-    var buffer = null;
-    while (totalSize < minTotal) {
+    while (totalSize < parameter.minTotal) {
       var buffer = new ArrayBuffer(size);
 
       fillArrayBuffer(buffer, 0x61);
@@ -168,15 +141,15 @@ function buildSendBenchmarkFunction(
   };
 }
 
-function buildReceiveBenchmarkFunction(
-    size, stopThreshold, minTotal, multipliers, multiplierIndex) {
-  if (size > stopThreshold) {
+function buildReceiveBenchmarkFunction(size, multiplierIndex, parameter) {
+  if (size > parameter.stopThreshold) {
     addToLog('Finished');
     destroyAllSockets();
     return function() {};
   }
 
   var onMessageHandler = function(event) {
+    alert();
     var bytesReceived = event.data.byteLength;
     if (bytesReceived != size) {
       addToLog('Expected ' + size + 'B but received ' + bytesReceived + 'B');
@@ -185,7 +158,7 @@ function buildReceiveBenchmarkFunction(
     }
 
     if (!verifyArrayBuffer(event.data, 0x61)) {
-      addToLog('Verification failed');
+      addToLog('Response verification failed');
       destroyAllSockets();
       return;
     }
@@ -196,17 +169,15 @@ function buildReceiveBenchmarkFunction(
       return;
     }
 
-    calculateAndLogResult(size, totalSize);
+    calculateAndLogResult(size, benchmark.startTimeInMs, totalSize, PRINT_SIZE);
 
     timerID = setTimeout(
         buildReceiveBenchmarkFunction(
-            size * multipliers[multiplierIndex],
-            stopThreshold,
-            minTotal,
-            multipliers,
-            (multiplierIndex + 1) % multipliers.length),
+            size * parameter.multipliers[multiplierIndex],
+            (multiplierIndex + 1) % parameter.multipliers.length,
+            parameter),
         0);
-  }
+  };
 
   return function() {
     for (var i = 0; i < sockets.length; ++i) {
@@ -215,20 +186,20 @@ function buildReceiveBenchmarkFunction(
       socket.onmessage = onMessageHandler;
     }
 
-    startTimeInMs = getTimeStamp();
+    benchmark.startTimeInMs = getTimeStamp();
 
     totalReplied = 0;
 
     totalSize = 0;
 
     var socketIndex = 0;
-    while (totalSize < minTotal) {
+    while (totalSize < parameter.minTotal) {
       sockets[socketIndex].send(size);
       socketIndex = (socketIndex + 1) % sockets.length;
 
       totalSize += size;
     }
-  }
+  };
 }
 
 function createSocket() {
@@ -281,13 +252,11 @@ function sendBenchmark() {
   addToLog('Message size in KiB, Speed in kB/s');
 
   var runner = buildSendBenchmarkFunction(
-      SEND_START_SIZE,
-      SEND_STOP_THRESHOLD,
-      SEND_MIN_TOTAL,
-      SEND_MULTIPLIERS,
-      0);
+      SEND_PARAMETER.startSize,
+      0,
+      SEND_PARAMETER);
 
-  startBenchmark(runner, SEND_NUM_SOCKETS);
+  startBenchmark(runner, SEND_PARAMETER.numSockets);
 }
 
 function receiveBenchmark() {
@@ -295,13 +264,11 @@ function receiveBenchmark() {
   addToLog('Message size in KiB, Speed in kB/s');
 
   var runner = buildReceiveBenchmarkFunction(
-      RECEIVE_START_SIZE,
-      RECEIVE_STOP_THRESHOLD,
-      RECEIVE_MIN_TOTAL,
-      RECEIVE_MULTIPLIERS,
-      0);
+      RECEIVE_PARAMETER.startSize,
+      0,
+      RECEIVE_PARAMETER);
 
-  startBenchmark(runner, RECEIVE_NUM_SOCKETS);
+  startBenchmark(runner, RECEIVE_PARAMETER.numSockets);
 }
 
 function stop() {
diff --git a/src/example/console.html b/src/example/console.html
index 3a46bfd..de739be 100644
--- a/src/example/console.html
+++ b/src/example/console.html
@@ -144,11 +144,19 @@ function connect() {
   }
 
   socket.onopen = function () {
+    var extraInfo = [];
     if (('protocol' in socket) && socket.protocol) {
-      addToLog('Opened (protocol = ' + socket.protocol + ')');
-    } else {
-      addToLog('Opened');
+      extraInfo.push('protocol = ' + socket.protocol);
+    }
+    if (('extensions' in socket) && socket.extensions) {
+      extraInfo.push('extensions = ' + socket.extensions);
+    }
+
+    var logMessage = 'Opened';
+    if (extraInfo.length > 0) {
+      logMessage += ' (' + extraInfo.join(', ') + ')';
     }
+    addToLog(logMessage);
   };
   socket.onmessage = function (event) {
     if (('ArrayBuffer' in window) && (event.data instanceof ArrayBuffer)) {
diff --git a/src/example/cookie_wsh.py b/src/example/cookie_wsh.py
new file mode 100644
index 0000000..8b32715
--- /dev/null
+++ b/src/example/cookie_wsh.py
@@ -0,0 +1,32 @@
+# Copyright 2014 Google Inc. All rights reserved.
+#
+# Use of this source code is governed by a BSD-style
+# license that can be found in the COPYING file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+
+import urlparse
+
+
+def _add_set_cookie(request, value):
+    request.extra_headers.append(('Set-Cookie', value))
+
+
+def web_socket_do_extra_handshake(request):
+    components = urlparse.urlparse(request.uri)
+    command = components[4]
+
+    ONE_DAY_LIFE = 'Max-Age=86400'
+
+    if command == 'set':
+        _add_set_cookie(request, '; '.join(['foo=bar', ONE_DAY_LIFE]))
+    elif command == 'set_httponly':
+        _add_set_cookie(request,
+            '; '.join(['httpOnlyFoo=bar', ONE_DAY_LIFE, 'httpOnly']))
+    elif command == 'clear':
+        _add_set_cookie(request, 'foo=0; Max-Age=0')
+        _add_set_cookie(request, 'httpOnlyFoo=0; Max-Age=0')
+
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/src/example/echo_client.py b/src/example/echo_client.py
index 9faeae8..943ce64 100755
--- a/src/example/echo_client.py
+++ b/src/example/echo_client.py
@@ -66,6 +66,9 @@ import sys
 
 from mod_pywebsocket import common
 from mod_pywebsocket.extensions import DeflateFrameExtensionProcessor
+from mod_pywebsocket.extensions import PerMessageDeflateExtensionProcessor
+from mod_pywebsocket.extensions import _PerMessageDeflateFramer
+from mod_pywebsocket.extensions import _parse_window_bits
 from mod_pywebsocket.stream import Stream
 from mod_pywebsocket.stream import StreamHixie75
 from mod_pywebsocket.stream import StreamOptions
@@ -333,6 +336,54 @@ class ClientHandshakeBase(object):
             ch = _receive_bytes(self._socket, 1)
 
 
+def _get_permessage_deflate_framer(extension_response):
+    """Validate the response and return a framer object using the parameters in
+    the response. This method doesn't accept the server_.* parameters.
+    """
+
+    client_max_window_bits = None
+    client_no_context_takeover = None
+
+    client_max_window_bits_name = (
+            PerMessageDeflateExtensionProcessor.
+                    _CLIENT_MAX_WINDOW_BITS_PARAM)
+    client_no_context_takeover_name = (
+            PerMessageDeflateExtensionProcessor.
+                    _CLIENT_NO_CONTEXT_TAKEOVER_PARAM)
+
+    # We didn't send any server_.* parameter.
+    # Handle those parameters as invalid if found in the response.
+
+    for param_name, param_value in extension_response.get_parameters():
+        if param_name == client_max_window_bits_name:
+            if client_max_window_bits is not None:
+                raise ClientHandshakeError(
+                        'Multiple %s found' % client_max_window_bits_name)
+
+            parsed_value = _parse_window_bits(param_value)
+            if parsed_value is None:
+                raise ClientHandshakeError(
+                        'Bad %s: %r' %
+                        (client_max_window_bits_name, param_value))
+            client_max_window_bits = parsed_value
+        elif param_name == client_no_context_takeover_name:
+            if client_no_context_takeover is not None:
+                raise ClientHandshakeError(
+                        'Multiple %s found' % client_no_context_takeover_name)
+
+            if param_value is not None:
+                raise ClientHandshakeError(
+                        'Bad %s: Has value %r' %
+                        (client_no_context_takeover_name, param_value))
+            client_no_context_takeover = True
+
+    if client_no_context_takeover is None:
+        client_no_context_takeover = False
+
+    return _PerMessageDeflateFramer(client_max_window_bits,
+                                    client_no_context_takeover)
+
+
 class ClientHandshakeProcessor(ClientHandshakeBase):
     """WebSocket opening handshake processor for
     draft-ietf-hybi-thewebsocketprotocol-06 and later.
@@ -396,15 +447,20 @@ class ClientHandshakeProcessor(ClientHandshakeBase):
 
         extensions_to_request = []
 
-        if self._options.deflate_stream:
-            extensions_to_request.append(
-                common.ExtensionParameter(
-                    common.DEFLATE_STREAM_EXTENSION))
-
         if self._options.deflate_frame:
             extensions_to_request.append(
                 common.ExtensionParameter(common.DEFLATE_FRAME_EXTENSION))
 
+        if self._options.use_permessage_deflate:
+            extension = common.ExtensionParameter(
+                    common.PERMESSAGE_DEFLATE_EXTENSION)
+            # Accept the client_max_window_bits extension parameter by default.
+            extension.add_parameter(
+                    PerMessageDeflateExtensionProcessor.
+                            _CLIENT_MAX_WINDOW_BITS_PARAM,
+                    None)
+            extensions_to_request.append(extension)
+
         if len(extensions_to_request) != 0:
             fields.append(
                 '%s: %s\r\n' %
@@ -497,23 +553,18 @@ class ClientHandshakeProcessor(ClientHandshakeBase):
                 'Invalid %s header: %r (expected: %s)' %
                 (common.SEC_WEBSOCKET_ACCEPT_HEADER, accept, expected_accept))
 
-        deflate_stream_accepted = False
         deflate_frame_accepted = False
+        permessage_deflate_accepted = False
 
         extensions_header = fields.get(
             common.SEC_WEBSOCKET_EXTENSIONS_HEADER.lower())
         accepted_extensions = []
         if extensions_header is not None and len(extensions_header) != 0:
             accepted_extensions = common.parse_extensions(extensions_header[0])
+
         # TODO(bashi): Support the new style perframe compression extension.
         for extension in accepted_extensions:
             extension_name = extension.name()
-            if (extension_name == common.DEFLATE_STREAM_EXTENSION and
-                len(extension.get_parameter_names()) == 0 and
-                self._options.deflate_stream):
-                deflate_stream_accepted = True
-                continue
-
             if (extension_name == common.DEFLATE_FRAME_EXTENSION and
                 self._options.deflate_frame):
                 deflate_frame_accepted = True
@@ -521,20 +572,29 @@ class ClientHandshakeProcessor(ClientHandshakeBase):
                 unused_extension_response = processor.get_extension_response()
                 self._options.deflate_frame = processor
                 continue
+            elif (extension_name == common.PERMESSAGE_DEFLATE_EXTENSION and
+                  self._options.use_permessage_deflate):
+                permessage_deflate_accepted = True
 
-            raise ClientHandshakeError(
-                'Unexpected extension %r' % extension_name)
+                framer = _get_permessage_deflate_framer(extension)
+                framer.set_compress_outgoing_enabled(True)
+                self._options.use_permessage_deflate = framer
+                continue
 
-        if (self._options.deflate_stream and not deflate_stream_accepted):
             raise ClientHandshakeError(
-                'Requested %s, but the server rejected it' %
-                common.DEFLATE_STREAM_EXTENSION)
+                'Unexpected extension %r' % extension_name)
 
         if (self._options.deflate_frame and not deflate_frame_accepted):
             raise ClientHandshakeError(
                 'Requested %s, but the server rejected it' %
                 common.DEFLATE_FRAME_EXTENSION)
 
+        if (self._options.use_permessage_deflate and
+            not permessage_deflate_accepted):
+            raise ClientHandshakeError(
+                    'Requested %s, but the server rejected it' %
+                    common.PERMESSAGE_DEFLATE_EXTENSION)
+
         # TODO(tyoshino): Handle Sec-WebSocket-Protocol
         # TODO(tyoshino): Handle Cookie, etc.
 
@@ -553,12 +613,18 @@ class ClientHandshakeProcessorHybi00(ClientHandshakeBase):
 
         self._logger = util.get_class_logger(self)
 
+        if (self._options.deflate_frame or
+            self._options.use_permessage_deflate):
+            logging.critical('HyBi 00 doesn\'t support extensions.')
+            sys.exit(1)
+
     def handshake(self):
         """Performs opening handshake on the specified socket.
 
         Raises:
             ClientHandshakeError: handshake failed.
         """
+
         # 4.1 5. send request line.
         self._socket.sendall(_build_method_line(self._options.resource))
         # 4.1 6. Let /fields/ be an empty list of strings.
@@ -782,15 +848,6 @@ class ClientRequest(object):
         self._socket = socket
         self.connection = ClientConnection(socket)
 
-    def _drain_received_data(self):
-        """Drains unread data in the receive buffer."""
-
-        drained_data = util.drain_received_data(self._socket)
-
-        if drained_data:
-            self._logger.debug(
-                'Drained data following close frame: %r', drained_data)
-
 
 def _import_ssl():
     global ssl
@@ -868,13 +925,14 @@ class EchoClient(object):
                 stream_option.mask_send = True
                 stream_option.unmask_receive = False
 
-                if self._options.deflate_stream:
-                    stream_option.deflate_stream = True
-
                 if self._options.deflate_frame is not False:
                     processor = self._options.deflate_frame
                     processor.setup_stream_options(stream_option)
 
+                if self._options.use_permessage_deflate is not False:
+                    framer = self._options.use_permessage_deflate
+                    framer.setup_stream_options(stream_option)
+
                 self._stream = Stream(request, stream_option)
             elif version == _PROTOCOL_VERSION_HYBI00:
                 self._stream = StreamHixie75(request, True)
@@ -947,7 +1005,7 @@ def main():
                       'to use')
     parser.add_option('--tls-module', '--tls_module', dest='tls_module',
                       type='choice',
-                      choices = [_TLS_BY_STANDARD_MODULE, _TLS_BY_PYOPENSSL],
+                      choices=[_TLS_BY_STANDARD_MODULE, _TLS_BY_PYOPENSSL],
                       help='Use ssl module if "%s" is specified. '
                       'Use pyOpenSSL module if "%s" is specified' %
                       (_TLS_BY_STANDARD_MODULE, _TLS_BY_PYOPENSSL))
@@ -979,19 +1037,15 @@ def main():
     parser.add_option('--version-header', '--version_header',
                       dest='version_header',
                       type='int', default=-1,
-                      help='specify Sec-WebSocket-Version header value')
-    parser.add_option('--deflate-stream', '--deflate_stream',
-                      dest='deflate_stream',
-                      action='store_true', default=False,
-                      help='use deflate-stream extension. This value will be '
-                      'ignored if used with protocol version that doesn\'t '
-                      'support deflate-stream.')
+                      help='Specify Sec-WebSocket-Version header value')
     parser.add_option('--deflate-frame', '--deflate_frame',
                       dest='deflate_frame',
                       action='store_true', default=False,
-                      help='use deflate-frame extension. This value will be '
-                      'ignored if used with protocol version that doesn\'t '
-                      'support deflate-frame.')
+                      help='Use the deflate-frame extension.')
+    parser.add_option('--use-permessage-deflate', '--use_permessage_deflate',
+                      dest='use_permessage_deflate',
+                      action='store_true', default=False,
+                      help='Use the permessage-deflate extension.')
     parser.add_option('--log-level', '--log_level', type='choice',
                       dest='log_level', default='warn',
                       choices=['debug', 'info', 'warn', 'error', 'critical'],
diff --git a/src/example/eventsource.cgi b/src/example/eventsource.cgi
index 1119d50..adddf23 100755
--- a/src/example/eventsource.cgi
+++ b/src/example/eventsource.cgi
@@ -43,8 +43,12 @@ import time
 
 sys.stdout.write('Content-type: text/event-stream\r\n\r\n')
 
+id = 0
+
 while True:
-  sys.stdout.write('data: Hello\r\n\r\n')
+  sys.stdout.write('data: Hello\r\nid: %d\r\n\r\n' % id)
   sys.stdout.flush()
 
+  id = id + 1
+
   time.sleep(1)
diff --git a/src/example/eventsource.html b/src/example/eventsource.html
index a8eb5be..1598a88 100644
--- a/src/example/eventsource.html
+++ b/src/example/eventsource.html
@@ -44,18 +44,31 @@ Run the pywebsocket with the --cgi_path parameter.
 <script>
 var eventSource = null;
 
+function addToLog(data) {
+  logBox.value += data + '\n';
+  logBox.scrollTop = 1000000;
+}
+
 function init() {
   logBox = document.getElementById('log');
 
   eventSource  = new EventSource('/eventsource.cgi');
+  eventSource.onopen = function() {
+    addToLog('onopen (readyState = ' + eventSource.readyState + ')');
+  }
   eventSource.onmessage = function(event) {
-    logBox.value += event.data + '\n';
-    logBox.scrollTop = 1000000;
+    addToLog(event.data);
+  }
+  eventSource.onerror = function(event) {
+    addToLog('onerror (readyState = ' + eventSource.readyState + ')');
   }
 }
 </script>
 </head>
 <body onload="init()">
 <textarea id="log" rows="10" cols="40" readonly></textarea>
+<p style="font-size: small">
+  Make sure that pywebsocket is run with --cgi_path parameter.
+</p>
 </body>
 </html>
diff --git a/src/example/util.js b/src/example/util.js
index f56c232..6486f10 100644
--- a/src/example/util.js
+++ b/src/example/util.js
@@ -31,6 +31,20 @@
 // Utilities for example applications.
 
 
+var logBox = null;
+var queuedLog = '';
+
+function queueLog(log) {
+  queuedLog += log + '\n';
+}
+
+function addToLog(log) {
+  logBox.value += queuedLog;
+  queuedLog = '';
+  logBox.value += log + '\n';
+  logBox.scrollTop = 1000000;
+}
+
 function getTimeStamp() {
   return Date.now();
 }
@@ -47,6 +61,11 @@ function calculateSpeedInKB(size, startTimeInMs) {
   return Math.round(size / (getTimeStamp() - startTimeInMs) * 1000) / 1000;
 }
 
+function calculateAndLogResult(size, startTimeInMs, totalSize, printSize) {
+  var speed = calculateSpeedInKB(totalSize, startTimeInMs);
+  addToLog(formatResultInKiB(size, speed, printSize));
+}
+
 function fillArrayBuffer(buffer, c) {
   var i;
 
@@ -90,3 +109,35 @@ function verifyArrayBuffer(buffer, expectedChar) {
 
   return true;
 }
+
+function verifyBlob(blob, expectedChar, doneCallback) {
+  var reader = new FileReader(blob);
+  reader.onerror = function() {
+    doneCallback(blob.size, false);
+  }
+  reader.onloadend = function() {
+    var result = verifyArrayBuffer(reader.result, expectedChar);
+    doneCallback(blob.size, result);
+  }
+  reader.readAsArrayBuffer(blob);
+}
+
+function verifyAcknowledgement(message, size) {
+  if (typeof message != 'string') {
+    addToLog('Invalid ack type: ' + typeof message);
+    return false;
+  }
+  var parsedAck = parseInt(message);
+  if (isNaN(parsedAck)) {
+    addToLog('Invalid ack value: ' + message);
+    return false;
+  }
+  if (parsedAck != size) {
+    addToLog(
+        'Expected ack for ' + size + 'B but received one for ' + parsedAck +
+        'B');
+    return false;
+  }
+
+  return true;
+}
diff --git a/src/example/xhr_benchmark.html b/src/example/xhr_benchmark.html
new file mode 100644
index 0000000..1442d0c
--- /dev/null
+++ b/src/example/xhr_benchmark.html
@@ -0,0 +1,310 @@
+<!--
+Copyright 2013, 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.
+-->
+
+<html>
+<head>
+<title>XMLHttpRequest benchmark</title>
+<script src="util.js"></script>
+<script>
+var PRINT_SIZE = true;
+
+var SEND_PARAMETER = {
+  numXHRs: 1,
+  startSize: 100 * 1024,
+  stopThreshold: 50 * 1024 * 1024,
+  multipliers: [5, 2],
+};
+
+var RECEIVE_PARAMETER = {
+  numXHRs: 1,
+  startSize: 100 * 1024,
+  stopThreshold: 50 * 1024 * 1024,
+  multipliers: [5, 2],
+};
+
+var xhrs = [];
+
+var addressBox = null;
+var logBox = null;
+
+var responseType = 'blob';
+
+var timerID = null;
+
+function destroyAllXHRs() {
+  for (var i = 0; i < xhrs.length; ++i) {
+    xhrs[i].onreadystatechange = function() {};
+    xhrs[i].abort();
+  }
+  xhrs = [];
+}
+
+function sendBenchmark(size, multiplierIndex, parameter) {
+  timerID = null;
+
+  if (size > parameter.stopThreshold) {
+    addToLog('Finished');
+    return;
+  }
+
+  var startTimeInMs = null;
+  var totalSize = 0;
+  var totalReplied = 0;
+
+  var onReadyStateChangeHandler = function () {
+    if (this.readyState != this.DONE) {
+      return;
+    }
+
+    if (this.status != 200) {
+      addToLog('Failed (status=' + this.status + ')');
+      destroyAllXHRs();
+      return;
+    }
+
+    if (!verifyAcknowledgement(this.response, size)) {
+      destroyAllXHRs();
+      return;
+    }
+
+    totalReplied += size;
+
+    if (totalReplied < totalSize) {
+      return;
+    }
+
+    if (startTimeInMs == null) {
+      addToLog('startTimeInMs not set');
+      destroyAllXHRs();
+      return;
+    }
+
+    calculateAndLogResult(size, startTimeInMs, totalSize, PRINT_SIZE);
+
+    destroyAllXHRs();
+
+    timerID = setTimeout(
+        sendBenchmark,
+        0,
+        size * parameter.multipliers[multiplierIndex],
+        (multiplierIndex + 1) % parameter.multipliers.length,
+        parameter);
+  };
+
+  for (var i = 0; i < parameter.numXHRs; ++i) {
+    var xhr = new XMLHttpRequest();
+    xhr.onreadystatechange = onReadyStateChangeHandler;
+    xhrs.push(xhr);
+  }
+
+  startTimeInMs = getTimeStamp();
+
+  for (var i = 0; i < xhrs.length; ++i) {
+    var buffer = new ArrayBuffer(size);
+
+    fillArrayBuffer(buffer, 0x61);
+
+    if (responseType == 'blob') {
+      buffer = new Blob([buffer]);
+    }
+
+    var xhr = xhrs[i];
+    xhr.open('POST', addressBox.value + '_send');
+    xhr.send(buffer);
+
+    totalSize += size;
+  }
+}
+
+function receiveBenchmark(size, multiplierIndex, parameter) {
+  timerID = null;
+
+  if (size > parameter.stopThreshold) {
+    addToLog('Finished');
+    return;
+  }
+
+  var startTimeInMs = null;
+  var totalSize = 0;
+  var totalReplied = 0;
+
+  var checkResultAndContinue = function (bytesReceived, verificationResult) {
+    if (!verificationResult) {
+      addToLog('Response verification failed');
+      destroyAllXHRs();
+      return;
+    }
+
+    totalReplied += bytesReceived;
+
+    if (totalReplied < totalSize) {
+      return;
+    }
+
+    if (startTimeInMs == null) {
+      addToLog('startTimeInMs not set');
+      destroyAllXHRs();
+      return;
+    }
+
+    calculateAndLogResult(size, startTimeInMs, totalSize, PRINT_SIZE);
+
+    destroyAllXHRs();
+
... 3584 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-mod-pywebsocket.git



More information about the Python-modules-commits mailing list