[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.16-1409-g5afdf4d
eric at webkit.org
eric at webkit.org
Thu Dec 3 13:45:11 UTC 2009
The following commit has been merged in the webkit-1.1 branch:
commit e1e5924544ea09711f3d73306845be44c31bd5b7
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Thu Nov 26 06:16:09 2009 +0000
2009-11-25 Yuzo Fujishima <yuzo at google.com>
Reviewed by Eric Seidel.
Update pywebsocket to 0.4.2
Update pywebsocket to 0.4.2
https://bugs.webkit.org/show_bug.cgi?id=31861
* pywebsocket/example/echo_client.py:
* pywebsocket/example/echo_wsh.py:
* pywebsocket/mod_pywebsocket/__init__.py:
* pywebsocket/mod_pywebsocket/dispatch.py:
* pywebsocket/mod_pywebsocket/msgutil.py:
* pywebsocket/mod_pywebsocket/standalone.py:
* pywebsocket/setup.py:
* pywebsocket/test/test_dispatch.py:
* pywebsocket/test/test_msgutil.py:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51406 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 0a77a7b..fbe25cd 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,22 @@
+2009-11-25 Yuzo Fujishima <yuzo at google.com>
+
+ Reviewed by Eric Seidel.
+
+ Update pywebsocket to 0.4.2
+
+ Update pywebsocket to 0.4.2
+ https://bugs.webkit.org/show_bug.cgi?id=31861
+
+ * pywebsocket/example/echo_client.py:
+ * pywebsocket/example/echo_wsh.py:
+ * pywebsocket/mod_pywebsocket/__init__.py:
+ * pywebsocket/mod_pywebsocket/dispatch.py:
+ * pywebsocket/mod_pywebsocket/msgutil.py:
+ * pywebsocket/mod_pywebsocket/standalone.py:
+ * pywebsocket/setup.py:
+ * pywebsocket/test/test_dispatch.py:
+ * pywebsocket/test/test_msgutil.py:
+
2009-11-25 Adam Barth <abarth at webkit.org>
Reviewed by Eric Seidel.
diff --git a/WebKitTools/pywebsocket/example/echo_client.py b/WebKitTools/pywebsocket/example/echo_client.py
index 61b129c..3262a6d 100644
--- a/WebKitTools/pywebsocket/example/echo_client.py
+++ b/WebKitTools/pywebsocket/example/echo_client.py
@@ -46,6 +46,8 @@ import socket
import sys
+_TIMEOUT_SEC = 10
+
_DEFAULT_PORT = 80
_DEFAULT_SECURE_PORT = 443
_UNDEFINED_PORT = -1
@@ -57,6 +59,8 @@ _EXPECTED_RESPONSE = (
_UPGRADE_HEADER +
_CONNECTION_HEADER)
+_GOODBYE_MESSAGE = 'Goodbye'
+
def _method_line(resource):
return 'GET %s HTTP/1.1\r\n' % resource
@@ -96,13 +100,14 @@ class EchoClient(object):
Shake hands and then repeat sending message and receiving its echo.
"""
self._socket = socket.socket()
+ self._socket.settimeout(self._options.socket_timeout)
try:
self._socket.connect((self._options.server_host,
self._options.server_port))
if self._options.use_tls:
self._socket = _TLSSocket(self._socket)
self._handshake()
- for line in self._options.message.split(','):
+ for line in self._options.message.split(',') + [_GOODBYE_MESSAGE]:
frame = '\x00' + line.encode('utf-8') + '\xff'
self._socket.send(frame)
if self._options.verbose:
@@ -111,7 +116,8 @@ class EchoClient(object):
if received != frame:
raise Exception('Incorrect echo: %r' % received)
if self._options.verbose:
- print 'Recv: %s' % received[1:-1].decode('utf-8')
+ print 'Recv: %s' % received[1:-1].decode('utf-8',
+ 'replace')
finally:
self._socket.close()
@@ -166,11 +172,17 @@ def main():
parser.add_option('-r', '--resource', dest='resource', type='string',
default='/echo', help='resource path')
parser.add_option('-m', '--message', dest='message', type='string',
- help='comma-separated messages to send')
+ help=('comma-separated messages to send excluding "%s" '
+ 'that is always sent at the end' %
+ _GOODBYE_MESSAGE))
parser.add_option('-q', '--quiet', dest='verbose', action='store_false',
default=True, help='suppress messages')
parser.add_option('-t', '--tls', dest='use_tls', action='store_true',
default=False, help='use TLS (wss://)')
+ parser.add_option('-k', '--socket_timeout', dest='socket_timeout',
+ type='int', default=_TIMEOUT_SEC,
+ help='Timeout(sec) for sockets')
+
(options, unused_args) = parser.parse_args()
# Default port number depends on whether TLS is used.
diff --git a/WebKitTools/pywebsocket/example/echo_wsh.py b/WebKitTools/pywebsocket/example/echo_wsh.py
index f680fa5..50cad31 100644
--- a/WebKitTools/pywebsocket/example/echo_wsh.py
+++ b/WebKitTools/pywebsocket/example/echo_wsh.py
@@ -31,6 +31,9 @@
from mod_pywebsocket import msgutil
+_GOODBYE_MESSAGE = 'Goodbye'
+
+
def web_socket_do_extra_handshake(request):
pass # Always accept.
@@ -39,6 +42,8 @@ def web_socket_transfer_data(request):
while True:
line = msgutil.receive_message(request)
msgutil.send_message(request, line)
+ if line == _GOODBYE_MESSAGE:
+ return
# vi:sts=4 sw=4 et
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/__init__.py b/WebKitTools/pywebsocket/mod_pywebsocket/__init__.py
index beacc9e..05e80e8 100644
--- a/WebKitTools/pywebsocket/mod_pywebsocket/__init__.py
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/__init__.py
@@ -96,6 +96,9 @@ web_socket_transfer_data is called after the handshake completed
successfully. A handler can receive/send messages from/to the client
using request. mod_pywebsocket.msgutil module provides utilities
for data transfer.
+
+A Web Socket handler must be thread-safe if the server (Apache or
+standalone.py) is configured to use threads.
"""
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py b/WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py
index 6d500cb..87a7315 100644
--- a/WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/dispatch.py
@@ -62,7 +62,7 @@ def _normalize_path(path):
"""
path = path.replace('\\', os.path.sep)
- path = os.path.abspath(path)
+ path = os.path.realpath(path)
path = path.replace('\\', '/')
return path
@@ -136,7 +136,8 @@ class Dispatcher(object):
self._source_warnings = []
if scan_dir is None:
scan_dir = root_dir
- if not os.path.realpath(scan_dir).startswith(os.path.realpath(root_dir)):
+ if not os.path.realpath(scan_dir).startswith(
+ os.path.realpath(root_dir)):
raise DispatchError('scan_dir:%s must be a directory under '
'root_dir:%s.' % (scan_dir, root_dir))
self._source_files_in_dir(root_dir, scan_dir)
@@ -182,13 +183,14 @@ class Dispatcher(object):
def _handler(self, request):
try:
- return self._handlers[request.ws_resource]
+ ws_resource_path = request.ws_resource.split('?', 1)[0]
+ return self._handlers[ws_resource_path]
except KeyError:
raise DispatchError('No handler for: %r' % request.ws_resource)
def _source_files_in_dir(self, root_dir, scan_dir):
"""Source all the handler source files in the scan_dir directory.
-
+
The resource path is determined relative to root_dir.
"""
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py b/WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py
index bdb554d..9fa9b59 100644
--- a/WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/msgutil.py
@@ -73,7 +73,9 @@ def receive_message(request):
else:
# The payload is delimited with \xff.
bytes = _read_until(request, '\xff')
- message = bytes.decode('utf-8')
+ # The Web Socket protocol section 4.4 specifies that invalid
+ # characters must be replaced with U+fffd REPLACEMENT CHARACTER.
+ message = bytes.decode('utf-8', 'replace')
if frame_type == 0x00:
return message
# Discard data of other types.
diff --git a/WebKitTools/pywebsocket/mod_pywebsocket/standalone.py b/WebKitTools/pywebsocket/mod_pywebsocket/standalone.py
index a4c142b..3b2d0dc 100644
--- a/WebKitTools/pywebsocket/mod_pywebsocket/standalone.py
+++ b/WebKitTools/pywebsocket/mod_pywebsocket/standalone.py
@@ -38,6 +38,7 @@ Usage:
python standalone.py [-p <ws_port>] [-w <websock_handlers>]
[-s <scan_dir>]
[-d <document_root>]
+ ... for other options, see _main below ...
<ws_port> is the port number to use for ws:// connection.
@@ -59,6 +60,7 @@ import BaseHTTPServer
import SimpleHTTPServer
import SocketServer
import logging
+import logging.handlers
import optparse
import os
import socket
@@ -75,6 +77,24 @@ import dispatch
import handshake
+_LOG_LEVELS = {
+ 'debug': logging.DEBUG,
+ 'info': logging.INFO,
+ 'warn': logging.WARN,
+ 'error': logging.ERROR,
+ 'critical': logging.CRITICAL};
+
+_DEFAULT_LOG_MAX_BYTES = 1024 * 256
+_DEFAULT_LOG_BACKUP_COUNT = 5
+
+
+def _print_warnings_if_any(dispatcher):
+ warnings = dispatcher.source_warnings()
+ if warnings:
+ for warning in warnings:
+ logging.warning('mod_pywebsocket: %s' % warning)
+
+
class _StandaloneConnection(object):
"""Mimic mod_python mp_conn."""
@@ -152,6 +172,7 @@ class WebSocketServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
socket_ = OpenSSL.SSL.Connection(ctx, socket_)
return socket_
+
class WebSocketRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""SimpleHTTPRequestHandler specialized for Web Socket."""
@@ -159,15 +180,13 @@ class WebSocketRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""Override SocketServer.StreamRequestHandler.setup."""
self.connection = self.request
- self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
- self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
+ self.rfile = socket._fileobject(self.request, 'rb', self.rbufsize)
+ self.wfile = socket._fileobject(self.request, 'wb', self.wbufsize)
def __init__(self, *args, **keywords):
self._request = _StandaloneRequest(
self, WebSocketRequestHandler.options.use_tls)
- self._dispatcher = dispatch.Dispatcher(
- WebSocketRequestHandler.options.websock_handlers,
- WebSocketRequestHandler.options.scan_dir)
+ self._dispatcher = WebSocketRequestHandler.options.dispatcher
self._print_warnings_if_any()
self._handshaker = handshake.Handshaker(self._request,
self._dispatcher)
@@ -200,10 +219,35 @@ class WebSocketRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
return False
return result
+ def log_request(self, code='-', size='-'):
+ """Override BaseHTTPServer.log_request."""
+
+ logging.info('"%s" %s %s',
+ self.requestline, str(code), str(size))
+
+ def log_error(self, *args):
+ """Override BaseHTTPServer.log_error."""
+
+ # Despite the name, this method is for warnings than for errors.
+ # For example, HTTP status code is logged by this method.
+ logging.warn('%s - %s' % (self.address_string(), (args[0] % args[1:])))
-def _main():
- logging.basicConfig()
+def _configure_logging(options):
+ logger = logging.getLogger()
+ logger.setLevel(_LOG_LEVELS[options.log_level])
+ if options.log_file:
+ handler = logging.handlers.RotatingFileHandler(
+ options.log_file, 'a', options.log_max, options.log_count)
+ else:
+ handler = logging.StreamHandler()
+ formatter = logging.Formatter(
+ "[%(asctime)s] [%(levelname)s] %(name)s: %(message)s")
+ handler.setFormatter(formatter)
+ logger.addHandler(handler)
+
+
+def _main():
parser = optparse.OptionParser()
parser.add_option('-p', '--port', dest='port', type='int',
default=handshake._DEFAULT_WEB_SOCKET_PORT,
@@ -224,27 +268,51 @@ def _main():
default='', help='TLS private key file.')
parser.add_option('-c', '--certificate', dest='certificate',
default='', help='TLS certificate file.')
+ parser.add_option('-l', '--log_file', dest='log_file',
+ default='', help='Log file.')
+ parser.add_option('--log_level', type='choice', dest='log_level',
+ default='warn',
+ choices=['debug', 'info', 'warn', 'error', 'critical'],
+ help='Log level.')
+ parser.add_option('--log_max', dest='log_max', type='int',
+ default=_DEFAULT_LOG_MAX_BYTES,
+ help='Log maximum bytes')
+ parser.add_option('--log_count', dest='log_count', type='int',
+ default=_DEFAULT_LOG_BACKUP_COUNT,
+ help='Log backup count')
options = parser.parse_args()[0]
+ os.chdir(options.document_root)
+
+ _configure_logging(options)
+
if options.use_tls:
if not _HAS_OPEN_SSL:
- print >>sys.stderr, 'To use TLS, install pyOpenSSL.'
+ logging.critical('To use TLS, install pyOpenSSL.')
sys.exit(1)
if not options.private_key or not options.certificate:
- print >>sys.stderr, ('To use TLS, specify private_key and '
- 'certificate.')
+ logging.critical(
+ 'To use TLS, specify private_key and certificate.')
sys.exit(1)
if not options.scan_dir:
options.scan_dir = options.websock_handlers
- WebSocketRequestHandler.options = options
- WebSocketServer.options = options
-
- os.chdir(options.document_root)
-
- server = WebSocketServer(('', options.port), WebSocketRequestHandler)
- server.serve_forever()
+ try:
+ # Share a Dispatcher among request handlers to save time for
+ # instantiation. Dispatcher can be shared because it is thread-safe.
+ options.dispatcher = dispatch.Dispatcher(options.websock_handlers,
+ options.scan_dir)
+ _print_warnings_if_any(options.dispatcher)
+
+ WebSocketRequestHandler.options = options
+ WebSocketServer.options = options
+
+ server = WebSocketServer(('', options.port), WebSocketRequestHandler)
+ server.serve_forever()
+ except Exception, e:
+ logging.critical(str(e))
+ sys.exit(1)
if __name__ == '__main__':
diff --git a/WebKitTools/pywebsocket/setup.py b/WebKitTools/pywebsocket/setup.py
index 1810a6d..ae07f8a 100644
--- a/WebKitTools/pywebsocket/setup.py
+++ b/WebKitTools/pywebsocket/setup.py
@@ -56,7 +56,7 @@ setup(author='Yuzo Fujishima',
name=_PACKAGE_NAME,
packages=[_PACKAGE_NAME],
url='http://code.google.com/p/pywebsocket/',
- version='0.4.1',
+ version='0.4.2',
)
diff --git a/WebKitTools/pywebsocket/test/test_dispatch.py b/WebKitTools/pywebsocket/test/test_dispatch.py
index d617205..d31d6bd 100644
--- a/WebKitTools/pywebsocket/test/test_dispatch.py
+++ b/WebKitTools/pywebsocket/test/test_dispatch.py
@@ -156,6 +156,20 @@ class DispatcherTest(unittest.TestCase):
self.assertEqual('sub/plain_wsh.py is called for /sub/plain, None',
request.connection.written_data())
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = '/sub/plain?'
+ request.ws_protocol = None
+ dispatcher.transfer_data(request)
+ self.assertEqual('sub/plain_wsh.py is called for /sub/plain?, None',
+ request.connection.written_data())
+
+ request = mock.MockRequest(connection=mock.MockConn(''))
+ request.ws_resource = '/sub/plain?q=v'
+ request.ws_protocol = None
+ dispatcher.transfer_data(request)
+ self.assertEqual('sub/plain_wsh.py is called for /sub/plain?q=v, None',
+ request.connection.written_data())
+
def test_transfer_data_no_handler(self):
dispatcher = dispatch.Dispatcher(_TEST_HANDLERS_DIR, None)
for resource in ['/blank', '/sub/non_callable',
diff --git a/WebKitTools/pywebsocket/test/test_msgutil.py b/WebKitTools/pywebsocket/test/test_msgutil.py
index b3ba539..16b88e0 100644
--- a/WebKitTools/pywebsocket/test/test_msgutil.py
+++ b/WebKitTools/pywebsocket/test/test_msgutil.py
@@ -71,6 +71,13 @@ class MessageTest(unittest.TestCase):
# U+672c is encoded as e6,9c,ac in UTF-8
self.assertEqual(u'\u672c', msgutil.receive_message(request))
+ def test_receive_message_erroneous_unicode(self):
+ # \x80 and \x81 are invalid as UTF-8.
+ request = _create_request('\x00\x80\x81\xff')
+ # Invalid characters should be replaced with
+ # U+fffd REPLACEMENT CHARACTER
+ self.assertEqual(u'\ufffd\ufffd', msgutil.receive_message(request))
+
def test_receive_message_discard(self):
request = _create_request('\x80\x06IGNORE\x00Hello\xff'
'\x01DISREGARD\xff\x00World!\xff')
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list