Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/net/websockets/handler.py : 24%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of Xpra.
2# Copyright (C) 2016-2019 Antoine Martin <antoine@xpra.org>
3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
4# later version. See the file COPYING for details.
6from xpra.util import envbool
7from xpra.net.websockets.common import make_websocket_accept_hash
8from xpra.server.http_handler import HTTPRequestHandler
9from xpra.log import Logger
11log = Logger("network", "websocket")
13WEBSOCKET_ONLY_UPGRADE = envbool("XPRA_WEBSOCKET_ONLY_UPGRADE", False)
15# HyBi-07 report version 7
16# HyBi-08 - HyBi-12 report version 8
17# HyBi-13 reports version 13
18SUPPORT_HyBi_PROTOCOLS = ("7", "8", "13")
21class WebSocketRequestHandler(HTTPRequestHandler):
23 server_version = "Xpra-WebSocket-Server"
25 def __init__(self, sock, addr, new_websocket_client,
26 web_root="/usr/share/xpra/www/",
27 http_headers_dir="/etc/xpra/http-headers", script_paths=None):
28 self.new_websocket_client = new_websocket_client
29 self.only_upgrade = WEBSOCKET_ONLY_UPGRADE
30 super().__init__(sock, addr, web_root, http_headers_dir, script_paths)
32 def handle_websocket(self):
33 log("handle_websocket() calling %s, request=%s (%s)",
34 self.new_websocket_client, self.request, type(self.request))
35 log("headers:")
36 for k,v in self.headers.items():
37 log(" %s=%s", k, v)
38 ver = self.headers.get('Sec-WebSocket-Version')
39 if ver is None:
40 raise Exception("Missing Sec-WebSocket-Version header")
42 if ver not in SUPPORT_HyBi_PROTOCOLS:
43 raise Exception("Unsupported protocol version %s" % ver)
45 protocols = self.headers.get("Sec-WebSocket-Protocol", "").split(",")
46 if "binary" not in protocols:
47 raise Exception("client does not support 'binary' protocol")
49 key = self.headers.get("Sec-WebSocket-Key")
50 if key is None:
51 raise Exception("Missing Sec-WebSocket-Key header")
52 for upgrade_string in (
53 b"HTTP/1.1 101 Switching Protocols",
54 b"Upgrade: websocket",
55 b"Connection: Upgrade",
56 b"Sec-WebSocket-Accept: %s" % make_websocket_accept_hash(key),
57 b"Sec-WebSocket-Protocol: %s" % b"binary",
58 b"",
59 ):
60 self.wfile.write(b"%s\r\n" % upgrade_string)
61 self.wfile.flush()
62 self.new_websocket_client(self)
64 def do_GET(self):
65 upgrade_requested = (self.headers.get('upgrade') or "").lower() == 'websocket'
66 if self.only_upgrade or upgrade_requested:
67 if not upgrade_requested:
68 self.send_error(403, "only websocket connections are allowed")
69 return
70 try:
71 self.handle_websocket()
72 except Exception as e:
73 log("do_GET()", exc_info=True)
74 log.error("Error: cannot handle websocket upgrade:")
75 log.error(" %s", e)
76 self.send_error(403, "failed to handle websocket: %s" % e)
77 return
78 HTTPRequestHandler.do_GET(self)
80 def do_HEAD(self):
81 if self.only_upgrade:
82 self.send_error(405, "Method Not Allowed")
83 return
84 HTTPRequestHandler.do_HEAD(self)
86 def handle_request(self):
87 if self.only_upgrade:
88 self.send_error(405, "Method Not Allowed")
89 return
90 HTTPRequestHandler.handle_request(self)