[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