Ejemplo n.º 1
0
 def setup_environ(self):
     """
     Setup the environ dictionary and add the
     `'ws4py.socket'` key. Its associated value
     is the real socket underlying socket.
     """
     SimpleHandler.setup_environ(self)
     self.environ['ws4py.socket'] = get_connection(self.environ['wsgi.input'])
Ejemplo n.º 2
0
 def setup_environ(self):
     """
     Setup the environ dictionary and add the
     `'ws4py.socket'` key. Its associated value
     is the real socket underlying socket.
     """
     SimpleHandler.setup_environ(self)
     self.environ['ws4py.socket'] = get_connection(self.environ['wsgi.input'])
     self.http_version = self.environ['SERVER_PROTOCOL'].rsplit('/')[-1]
Ejemplo n.º 3
0
 def setup_environ(self):
     """
     Setup the environ dictionary and add the
     `'ws4py.socket'` key. Its associated value
     is the real socket underlying socket.
     """
     SimpleHandler.setup_environ(self)
     self.environ['ws4py.socket'] = get_connection(self.environ['wsgi.input'])
     self.http_version = self.environ['SERVER_PROTOCOL'].rsplit('/')[-1]
Ejemplo n.º 4
0
 def setup_environ(self):
     """
     Setup the environ dictionary and add the
     `'ws4py.socket'` key. Its associated value
     is the real socket underlying socket.
     """
     SimpleHandler.setup_environ(self)
     self.environ['ws4py.socket'] = get_connection(
         self.environ['wsgi.input'])
Ejemplo n.º 5
0
    def __call__(self, environ, start_response):
        """ WSGI entry point
        """
        # Upgrade header means websockets...
        upgrade_header = environ.get('HTTP_UPGRADE', '').lower()
        if upgrade_header:
            from ws4py.compat import get_connection
            environ['ws4py.socket'] = get_connection(environ['wsgi.input'])
            # This will make a websocket, hopefully!
            ret = self.wsapp(environ, start_response)
            if 'ws4py.websocket' in environ:
                import cothread
                cothread.Spawn(environ.pop('ws4py.websocket').run)
            return ret

        # Find path to file to server
        path_info = environ["PATH_INFO"]

        if not path_info:
            return self._not_found(start_response)
        elif path_info == "/":
            path_info = "/index.html"

        file_path = os.path.join(self.path, path_info[1:])

        # If file does not exist, return 404
        if not os.path.exists(file_path):
            return self._not_found(start_response)

        # Guess mimetype of file based on file extension
        import mimetypes
        mimetype = mimetypes.guess_type(file_path)[0]

        # If we can't guess mimetype, return a 403 Forbidden
        if mimetype is None:
            if file_path.endswith(".woff"):
                mimetype = "application/octet-stream"
            else:
                return self._forbidden(start_response)

        # Get size of file
        size = os.path.getsize(file_path)

        # Create headers and start response
        headers = [
            ("Content-type", mimetype),
            ("Content-length", str(size)),
        ]

        start_response("200 OK", headers)

        # Send file
        return self._send_file(file_path, size)
Ejemplo n.º 6
0
    def upgrade(self,
                protocols=None,
                extensions=None,
                version=WS_VERSION,
                handler_cls=WebSocket,
                heartbeat_freq=None):
        """
        Performs the upgrade of the connection to the WebSocket
        protocol.

        The provided protocols may be a list of WebSocket
        protocols supported by the instance of the tool.

        When no list is provided and no protocol is either
        during the upgrade, then the protocol parameter is
        not taken into account. On the other hand,
        if the protocol from the handshake isn't part
        of the provided list, the upgrade fails immediatly.
        """
        request = cherrypy.serving.request
        request.process_request_body = False

        ws_protocols = None
        ws_location = None
        ws_version = version
        ws_key = None
        ws_extensions = []

        if request.method != 'GET':
            raise HandshakeError('HTTP method must be a GET')

        for key, expected_value in [('Upgrade', 'websocket'),
                                    ('Connection', 'upgrade')]:
            actual_value = request.headers.get(key, '').lower()
            if not actual_value:
                raise HandshakeError('Header %s is not defined' % key)
            if expected_value not in actual_value:
                raise HandshakeError('Illegal value for header %s: %s' %
                                     (key, actual_value))

        version = request.headers.get('Sec-WebSocket-Version')
        supported_versions = ', '.join([str(v) for v in ws_version])
        version_is_valid = False
        if version:
            try:
                version = int(version)
            except:
                pass
            else:
                version_is_valid = version in ws_version

        if not version_is_valid:
            cherrypy.response.headers[
                'Sec-WebSocket-Version'] = supported_versions
            raise HandshakeError('Unhandled or missing WebSocket version')

        key = request.headers.get('Sec-WebSocket-Key')
        if key:
            ws_key = base64.b64decode(key.encode('utf-8'))
            if len(ws_key) != 16:
                raise HandshakeError("WebSocket key's length is invalid")

        protocols = protocols or []
        subprotocols = request.headers.get('Sec-WebSocket-Protocol')
        if subprotocols:
            ws_protocols = []
            for s in subprotocols.split(','):
                s = s.strip()
                if s in protocols:
                    ws_protocols.append(s)

        exts = extensions or []
        extensions = request.headers.get('Sec-WebSocket-Extensions')
        if extensions:
            for ext in extensions.split(','):
                ext = ext.strip()
                if ext in exts:
                    ws_extensions.append(ext)

        location = []
        include_port = False
        if request.scheme == "https":
            location.append("wss://")
            include_port = request.local.port != 443
        else:
            location.append("ws://")
            include_port = request.local.port != 80
        location.append('localhost')
        if include_port:
            location.append(":%d" % request.local.port)
        location.append(request.path_info)
        if request.query_string != "":
            location.append("?%s" % request.query_string)
        ws_location = ''.join(location)

        response = cherrypy.serving.response
        response.stream = True
        response.status = '101 Switching Protocols'
        response.headers['Content-Type'] = 'text/plain'
        response.headers['Upgrade'] = 'websocket'
        response.headers['Connection'] = 'Upgrade'
        response.headers['Sec-WebSocket-Version'] = str(version)
        response.headers['Sec-WebSocket-Accept'] = base64.b64encode(
            sha1(key.encode('utf-8') + WS_KEY).digest())
        if ws_protocols:
            response.headers['Sec-WebSocket-Protocol'] = ', '.join(
                ws_protocols)
        if ws_extensions:
            response.headers['Sec-WebSocket-Extensions'] = ','.join(
                ws_extensions)

        addr = (request.remote.ip, request.remote.port)
        ws_conn = get_connection(request.rfile.rfile)
        request.ws_handler = handler_cls(ws_conn,
                                         ws_protocols,
                                         ws_extensions,
                                         request.wsgi_environ.copy(),
                                         heartbeat_freq=heartbeat_freq)
    def upgrade(self, protocols=None, extensions=None, version=WS_VERSION,
                handler_cls=WebSocket, heartbeat_freq=None):
        """
        Performs the upgrade of the connection to the WebSocket
        protocol.

        The provided protocols may be a list of WebSocket
        protocols supported by the instance of the tool.

        When no list is provided and no protocol is either
        during the upgrade, then the protocol parameter is
        not taken into account. On the other hand,
        if the protocol from the handshake isn't part
        of the provided list, the upgrade fails immediatly.
        """
        request = cherrypy.serving.request
        request.process_request_body = False

        ws_protocols = None
        ws_location = None
        ws_version = version
        ws_key = None
        ws_extensions = []

        if request.method != 'GET':
            raise HandshakeError('HTTP method must be a GET')

        for key, expected_value in [('Upgrade', 'websocket'),
                                     ('Connection', 'upgrade')]:
            actual_value = request.headers.get(key, '').lower()
            if not actual_value:
                raise HandshakeError('Header %s is not defined' % key)
            if expected_value not in actual_value:
                raise HandshakeError('Illegal value for header %s: %s' %
                                     (key, actual_value))

        version = request.headers.get('Sec-WebSocket-Version')
        supported_versions = ', '.join([str(v) for v in ws_version])
        version_is_valid = False
        if version:
            try: version = int(version)
            except: pass
            else: version_is_valid = version in ws_version

        if not version_is_valid:
            cherrypy.response.headers['Sec-WebSocket-Version'] = supported_versions
            raise HandshakeError('Unhandled or missing WebSocket version')

        key = request.headers.get('Sec-WebSocket-Key')
        if key:
            ws_key = base64.b64decode(key.encode('utf-8'))
            if len(ws_key) != 16:
                raise HandshakeError("WebSocket key's length is invalid")

        protocols = protocols or []
        subprotocols = request.headers.get('Sec-WebSocket-Protocol')
        if subprotocols:
            ws_protocols = []
            for s in subprotocols.split(','):
                s = s.strip()
                if s in protocols:
                    ws_protocols.append(s)

        exts = extensions or []
        extensions = request.headers.get('Sec-WebSocket-Extensions')
        if extensions:
            for ext in extensions.split(','):
                ext = ext.strip()
                if ext in exts:
                    ws_extensions.append(ext)

        location = []
        include_port = False
        if request.scheme == "https":
            location.append("wss://")
            include_port = request.local.port != 443
        else:
            location.append("ws://")
            include_port = request.local.port != 80
        location.append('localhost')
        if include_port:
            location.append(":%d" % request.local.port)
        location.append(request.path_info)
        if request.query_string != "":
            location.append("?%s" % request.query_string)
        ws_location = ''.join(location)

        response = cherrypy.serving.response
        response.stream = True
        response.status = '101 Switching Protocols'
        response.headers['Content-Type'] = 'text/plain'
        response.headers['Upgrade'] = 'websocket'
        response.headers['Connection'] = 'Upgrade'
        response.headers['Sec-WebSocket-Version'] = str(version)
        response.headers['Sec-WebSocket-Accept'] = base64.b64encode(sha1(key.encode('utf-8') + WS_KEY).digest())
        if ws_protocols:
            response.headers['Sec-WebSocket-Protocol'] = ', '.join(ws_protocols)
        if ws_extensions:
            response.headers['Sec-WebSocket-Extensions'] = ','.join(ws_extensions)

        addr = (request.remote.ip, request.remote.port)
        rfile = request.rfile.rfile
        if isinstance(rfile, KnownLengthRFile):
            rfile = rfile.rfile

        ws_conn = get_connection(rfile)
        request.ws_handler = handler_cls(ws_conn, ws_protocols, ws_extensions,
                                         request.wsgi_environ.copy(),
                                         heartbeat_freq=heartbeat_freq)