Skip to content

Commit

Permalink
mostly cosmetic refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
totaam committed Sep 2, 2022
1 parent 8f010ce commit 61ed242
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 30 deletions.
24 changes: 12 additions & 12 deletions tests/unittests/unit/net/websocket_response_headers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ def f(v, key=b""):
else:
raise Exception("bad header should have failed")
f(None)
f({b"upgrade" : b"not-websocket"})
f({b"upgrade" : b"websocket",
b"sec-websocket-protocol" : b"not-binary",
f({"upgrade" : "not-websocket"})
f({"upgrade" : "websocket",
"sec-websocket-protocol" : "not-binary",
})
f({b"upgrade" : b"websocket",
b"sec-websocket-protocol" : b"binary",
b"sec-websocket-accept" : b"",
f({"upgrade" : "websocket",
"sec-websocket-protocol" : "binary",
"sec-websocket-accept" : "",
})
f({b"upgrade" : b"websocket",
b"sec-websocket-protocol" : b"binary",
b"sec-websocket-accept" : b"key",
f({"upgrade" : "websocket",
"sec-websocket-protocol" : "binary",
"sec-websocket-accept" : "key",
})
key = b"somekey"
verify_response_headers({
b"upgrade" : b"websocket",
b"sec-websocket-protocol" : b"binary",
b"sec-websocket-accept" : make_websocket_accept_hash(key),
"upgrade" : "websocket",
"sec-websocket-protocol" : "binary",
"sec-websocket-accept" : make_websocket_accept_hash(key),
}, key)

def main():
Expand Down
38 changes: 25 additions & 13 deletions xpra/net/websockets/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This file is part of Xpra.
# Copyright (C) 2019 Antoine Martin <[email protected]>
# Copyright (C) 2019-2022 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

Expand Down Expand Up @@ -30,7 +30,7 @@ def get_headers(host, port):
headers = {}
for mod_name in HEADERS_MODULES:
try:
header_module = __import__("xpra.net.websockets.headers.%s" % mod_name, {}, {}, ["get_headers"])
header_module = __import__(f"xpra.net.websockets.headers.{mod_name}", {}, {}, ["get_headers"])
v = header_module.get_headers(host, port)
log("%s.get_headers(%s, %s)=%s", mod_name, host, port, v)
headers.update(v)
Expand All @@ -46,31 +46,42 @@ def get_headers(host, port):


def client_upgrade(read, write, host, port, path=""):
request = "GET /%s HTTP/1.1" % path
key = b64encode(uuid.uuid4().bytes)
request = get_client_upgrade_request(host, port, path, key)
write_request(write, request)
headers = read_server_upgrade(read)
verify_response_headers(headers, key)
log("client_upgrade: done")

def get_client_upgrade_request(host, port, path, key):
request = f"GET /{path} HTTP/1.1"
log("client_upgrade: http request: %s", request)
lines = [request.encode("latin1")]
key = b64encode(uuid.uuid4().bytes)
headers = get_headers(host, port)
headers[b"Sec-WebSocket-Key"] = key
for k,v in headers.items():
lines.append(b"%s: %s" % (k, v))
lines.append(b"")
lines.append(b"")
http_request = b"\r\n".join(lines)
log("client_upgrade: sending http headers: %s", headers)
return b"\r\n".join(lines)

def write_request(write, http_request):
now = monotonic()
while http_request and monotonic()-now<MAX_WRITE_TIME:
while http_request:
elasped = monotonic()-now
if elasped>=MAX_WRITE_TIME:
raise Exception(f"http write timeout, took more {elasped:.1f} seconds")
w = write(http_request)
http_request = http_request[w:]

def read_server_upgrade(read):
now = monotonic()
response = b""
def hasheader(k):
return k in parse_response_header(response)
while monotonic()-now<MAX_READ_TIME and not (hasheader("sec-websocket-protocol") or hasheader("www-authenticate")):
response += read(READ_CHUNK_SIZE)
headers = parse_response_header(response)
verify_response_headers(headers, key)
log("client_upgrade: done")
return parse_response_header(response)

def parse_response_header(response):
#parse response:
Expand All @@ -93,13 +104,14 @@ def verify_response_headers(headers, key):
if not upgrade:
raise Exception("http connection was not upgraded to websocket")
if upgrade!="websocket":
raise Exception("invalid http upgrade: '%s'" % upgrade)
raise Exception(f"invalid http upgrade: {upgrade!r}")
protocol = headers.get("sec-websocket-protocol")
if protocol!="binary":
raise Exception("invalid websocket protocol: '%s'" % protocol)
raise Exception(f"invalid websocket protocol: {protocol!r}")
accept_key = headers.get("sec-websocket-accept")
if not accept_key:
raise Exception("websocket accept key is missing")
expected_key = make_websocket_accept_hash(key)
if bytestostr(accept_key)!=expected_key:
if bytestostr(accept_key)!=bytestostr(expected_key):
log(f"expected {expected_key!r}, received {accept_key!r}")
raise Exception("websocket accept key is invalid")
12 changes: 7 additions & 5 deletions xpra/net/websockets/handler.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This file is part of Xpra.
# Copyright (C) 2016-2019 Antoine Martin <[email protected]>
# Copyright (C) 2016-2022 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

Expand Down Expand Up @@ -41,13 +41,13 @@ def handle_websocket(self):
self.new_websocket_client, self.request, type(self.request))
log("headers:")
for k,v in self.headers.items():
log(" %s=%s", k, v)
ver = self.headers.get('Sec-WebSocket-Version')
log(f" {k}={v}")
ver = self.headers.get("Sec-WebSocket-Version")
if ver is None:
raise Exception("Missing Sec-WebSocket-Version header")

if ver not in SUPPORT_HyBi_PROTOCOLS:
raise Exception("Unsupported protocol version %s" % ver)
raise Exception(f"Unsupported protocol version {ver}")

protocols = self.headers.get("Sec-WebSocket-Protocol", "").split(",")
if "binary" not in protocols:
Expand All @@ -56,11 +56,13 @@ def handle_websocket(self):
key = self.headers.get("Sec-WebSocket-Key")
if key is None:
raise Exception("Missing Sec-WebSocket-Key header")
accept = make_websocket_accept_hash(key)
log(f"websocket hash for key {key!r} = {accept!r}")
for upgrade_string in (
b"HTTP/1.1 101 Switching Protocols",
b"Upgrade: websocket",
b"Connection: Upgrade",
b"Sec-WebSocket-Accept: %s" % make_websocket_accept_hash(key),
b"Sec-WebSocket-Accept: %s" % accept,
b"Sec-WebSocket-Protocol: %s" % b"binary",
b"",
):
Expand Down

0 comments on commit 61ed242

Please sign in to comment.