don't use autoinstall to import pywebsocket but check it in WebKit directly.
[WebKit-https.git] / Tools / Scripts / webkitpy / thirdparty / mod_pywebsocket / handshake / __init__.py
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 opening handshake processor. This class try to apply available
32 opening handshake processors for each protocol version until a connection is
33 successfully established.
34 """
35
36
37 import logging
38
39 from mod_pywebsocket import common
40 from mod_pywebsocket.handshake import draft75
41 from mod_pywebsocket.handshake import hybi00
42 from mod_pywebsocket.handshake import hybi
43 # Export AbortedByUserException, HandshakeException, and VersionException
44 # symbol from this module.
45 from mod_pywebsocket.handshake._base import AbortedByUserException
46 from mod_pywebsocket.handshake._base import HandshakeException
47 from mod_pywebsocket.handshake._base import VersionException
48
49
50 _LOGGER = logging.getLogger(__name__)
51
52
53 def do_handshake(request, dispatcher, allowDraft75=False, strict=False):
54     """Performs WebSocket handshake.
55
56     Args:
57         request: mod_python request.
58         dispatcher: Dispatcher (dispatch.Dispatcher).
59         allowDraft75: allow draft 75 handshake protocol.
60         strict: Strictly check handshake request in draft 75.
61             Default: False. If True, request.connection must provide
62             get_memorized_lines method.
63
64     Handshaker will add attributes such as ws_resource in performing
65     handshake.
66     """
67
68     _LOGGER.debug('Client\'s opening handshake resource: %r', request.uri)
69     # To print mimetools.Message as escaped one-line string, we converts
70     # headers_in to dict object. Without conversion, if we use %r, it just
71     # prints the type and address, and if we use %s, it prints the original
72     # header string as multiple lines.
73     #
74     # Both mimetools.Message and MpTable_Type of mod_python can be
75     # converted to dict.
76     #
77     # mimetools.Message.__str__ returns the original header string.
78     # dict(mimetools.Message object) returns the map from header names to
79     # header values. While MpTable_Type doesn't have such __str__ but just
80     # __repr__ which formats itself as well as dictionary object.
81     _LOGGER.debug(
82         'Client\'s opening handshake headers: %r', dict(request.headers_in))
83
84     handshakers = []
85     handshakers.append(
86         ('RFC 6455', hybi.Handshaker(request, dispatcher)))
87     handshakers.append(
88         ('HyBi 00', hybi00.Handshaker(request, dispatcher)))
89     if allowDraft75:
90         handshakers.append(
91             ('Hixie 75', draft75.Handshaker(request, dispatcher, strict)))
92
93     for name, handshaker in handshakers:
94         _LOGGER.debug('Trying protocol version %s', name)
95         try:
96             handshaker.do_handshake()
97             _LOGGER.info('Established (%s protocol)', name)
98             return
99         except HandshakeException, e:
100             _LOGGER.debug(
101                 'Failed to complete opening handshake as %s protocol: %r',
102                 name, e)
103             if e.status:
104                 raise e
105         except AbortedByUserException, e:
106             raise
107         except VersionException, e:
108             raise
109
110     # TODO(toyoshim): Add a test to cover the case all handshakers fail.
111     raise HandshakeException(
112         'Failed to complete opening handshake for all available protocols',
113         status=common.HTTP_STATUS_BAD_REQUEST)
114
115
116 # vi:sts=4 sw=4 et