1# Copyright 2011, Google Inc. 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are 6# met: 7# 8# * Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# * Redistributions in binary form must reproduce the above 11# copyright notice, this list of conditions and the following disclaimer 12# in the documentation and/or other materials provided with the 13# distribution. 14# * Neither the name of Google Inc. nor the names of its 15# contributors may be used to endorse or promote products derived from 16# this software without specific prior written permission. 17# 18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 31"""WebSocket extension for Apache HTTP Server. 32 33mod_pywebsocket is a WebSocket extension for Apache HTTP Server 34intended for testing or experimental purposes. mod_python is required. 35 36 37Installation: 38 390. Prepare an Apache HTTP Server for which mod_python is enabled. 40 411. Specify the following Apache HTTP Server directives to suit your 42 configuration. 43 44 If mod_pywebsocket is not in the Python path, specify the following. 45 <websock_lib> is the directory where mod_pywebsocket is installed. 46 47 PythonPath "sys.path+['<websock_lib>']" 48 49 Always specify the following. <websock_handlers> is the directory where 50 user-written WebSocket handlers are placed. 51 52 PythonOption mod_pywebsocket.handler_root <websock_handlers> 53 PythonHeaderParserHandler mod_pywebsocket.headerparserhandler 54 55 To limit the search for WebSocket handlers to a directory <scan_dir> 56 under <websock_handlers>, configure as follows: 57 58 PythonOption mod_pywebsocket.handler_scan <scan_dir> 59 60 <scan_dir> is useful in saving scan time when <websock_handlers> 61 contains many non-WebSocket handler files. 62 63 If you want to support old handshake based on 64 draft-hixie-thewebsocketprotocol-75: 65 66 PythonOption mod_pywebsocket.allow_draft75 On 67 68 If you want to allow handlers whose canonical path is not under the root 69 directory (i.e. symbolic link is in root directory but its target is not), 70 configure as follows: 71 72 PythonOption mod_pywebsocket.allow_handlers_outside_root_dir On 73 74 Example snippet of httpd.conf: 75 (mod_pywebsocket is in /websock_lib, WebSocket handlers are in 76 /websock_handlers, port is 80 for ws, 443 for wss.) 77 78 <IfModule python_module> 79 PythonPath "sys.path+['/websock_lib']" 80 PythonOption mod_pywebsocket.handler_root /websock_handlers 81 PythonHeaderParserHandler mod_pywebsocket.headerparserhandler 82 </IfModule> 83 842. Tune Apache parameters for serving WebSocket. We'd like to note that at 85 least TimeOut directive from core features and RequestReadTimeout 86 directive from mod_reqtimeout should be modified not to kill connections 87 in only a few seconds of idle time. 88 893. Verify installation. You can use example/console.html to poke the server. 90 91 92Writing WebSocket handlers: 93 94When a WebSocket request comes in, the resource name 95specified in the handshake is considered as if it is a file path under 96<websock_handlers> and the handler defined in 97<websock_handlers>/<resource_name>_wsh.py is invoked. 98 99For example, if the resource name is /example/chat, the handler defined in 100<websock_handlers>/example/chat_wsh.py is invoked. 101 102A WebSocket handler is composed of the following three functions: 103 104 web_socket_do_extra_handshake(request) 105 web_socket_transfer_data(request) 106 web_socket_passive_closing_handshake(request) 107 108where: 109 request: mod_python request. 110 111web_socket_do_extra_handshake is called during the handshake after the 112headers are successfully parsed and WebSocket properties (ws_location, 113ws_origin, and ws_resource) are added to request. A handler 114can reject the request by raising an exception. 115 116A request object has the following properties that you can use during the 117extra handshake (web_socket_do_extra_handshake): 118- ws_resource 119- ws_origin 120- ws_version 121- ws_location (Hixie 75 and HyBi 00 only) 122- ws_extensions (Hybi 06 and later) 123- ws_deflate (HyBi 06 and later) 124- ws_protocol 125- ws_requested_protocols (HyBi 06 and later) 126 127The last two are a bit tricky. 128 129For HyBi 06 and later, ws_protocol is always set to None when 130web_socket_do_extra_handshake is called. If ws_requested_protocols is not 131None, you must choose one subprotocol from this list and set it to 132ws_protocol. 133 134For Hixie 75 and HyBi 00, when web_socket_do_extra_handshake is called, 135ws_protocol is set to the value given by the client in 136Sec-WebSocket-Protocol (WebSocket-Protocol for Hixie 75) header or None if 137such header was not found in the opening handshake request. Finish extra 138handshake with ws_protocol untouched to accept the request subprotocol. 139Then, Sec-WebSocket-Protocol (or WebSocket-Protocol) header will be sent to 140the client in response with the same value as requested. Raise an exception 141in web_socket_do_extra_handshake to reject the requested subprotocol. 142 143web_socket_transfer_data is called after the handshake completed 144successfully. A handler can receive/send messages from/to the client 145using request. mod_pywebsocket.msgutil module provides utilities 146for data transfer. 147 148You can receive a message by the following statement. 149 150 message = request.ws_stream.receive_message() 151 152This call blocks until any complete text frame arrives, and the payload data 153of the incoming frame will be stored into message. When you're using IETF 154HyBi 00 or later protocol, receive_message() will return None on receiving 155client-initiated closing handshake. When any error occurs, receive_message() 156will raise some exception. 157 158You can send a message by the following statement. 159 160 request.ws_stream.send_message(message) 161 162Executing the following statement or just return-ing from 163web_socket_transfer_data cause connection close. 164 165 request.ws_stream.close_connection() 166 167When you're using IETF HyBi 00 or later protocol, close_connection will wait 168for closing handshake acknowledgement coming from the client. When it 169couldn't receive a valid acknowledgement, raises an exception. 170 171web_socket_passive_closing_handshake is called after the server receives 172incoming closing frame from the client peer immediately. You can specify 173code and reason by return values. They are sent as a outgoing closing frame 174from the server. A request object has the following properties that you can 175use in web_socket_passive_closing_handshake. 176- ws_close_code 177- ws_close_reason 178 179A WebSocket handler must be thread-safe if the server (Apache or 180standalone.py) is configured to use threads. 181""" 182 183 184# vi:sts=4 sw=4 et tw=72 185