diff options
author | Thomas Kriechbaumer <thomas@kriechbaumer.name> | 2016-08-18 17:31:43 +0200 |
---|---|---|
committer | Thomas Kriechbaumer <thomas@kriechbaumer.name> | 2016-09-01 09:56:14 +0200 |
commit | d12515f84b32b3157fa99ac3c3a7a7318f9626ba (patch) | |
tree | 5fee9c57965ebbee51227eb374029b89dbe56cca /netlib/websockets/utils.py | |
parent | 281d779fa3eb6b81ec76d046337275c0a82eff46 (diff) | |
download | mitmproxy-d12515f84b32b3157fa99ac3c3a7a7318f9626ba.tar.gz mitmproxy-d12515f84b32b3157fa99ac3c3a7a7318f9626ba.tar.bz2 mitmproxy-d12515f84b32b3157fa99ac3c3a7a7318f9626ba.zip |
websockets: refactor implementation and add tests
Diffstat (limited to 'netlib/websockets/utils.py')
-rw-r--r-- | netlib/websockets/utils.py | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/netlib/websockets/utils.py b/netlib/websockets/utils.py new file mode 100644 index 00000000..aa0d39a1 --- /dev/null +++ b/netlib/websockets/utils.py @@ -0,0 +1,90 @@ +""" +Collection of WebSockets Protocol utility functions (RFC6455) +Spec: https://tools.ietf.org/html/rfc6455 +""" + +from __future__ import absolute_import + +import base64 +import hashlib +import os + +from netlib import http, strutils + +MAGIC = b'258EAFA5-E914-47DA-95CA-C5AB0DC85B11' +VERSION = "13" + + +def client_handshake_headers(version=None, key=None, protocol=None, extensions=None): + """ + Create the headers for a valid HTTP upgrade request. If Key is not + specified, it is generated, and can be found in sec-websocket-key in + the returned header set. + + Returns an instance of http.Headers + """ + if version is None: + version = VERSION + if key is None: + key = base64.b64encode(os.urandom(16)).decode('ascii') + h = http.Headers( + connection="upgrade", + upgrade="websocket", + sec_websocket_version=version, + sec_websocket_key=key, + ) + if protocol is not None: + h['sec-websocket-protocol'] = protocol + if extensions is not None: + h['sec-websocket-extensions'] = extensions + return h + + +def server_handshake_headers(client_key, protocol=None, extensions=None): + """ + The server response is a valid HTTP 101 response. + + Returns an instance of http.Headers + """ + h = http.Headers( + connection="upgrade", + upgrade="websocket", + sec_websocket_accept=create_server_nonce(client_key), + ) + if protocol is not None: + h['sec-websocket-protocol'] = protocol + if extensions is not None: + h['sec-websocket-extensions'] = extensions + return h + + +def check_handshake(headers): + return ( + "upgrade" in headers.get("connection", "").lower() and + headers.get("upgrade", "").lower() == "websocket" and + (headers.get("sec-websocket-key") is not None or headers.get("sec-websocket-accept") is not None) + ) + + +def create_server_nonce(client_nonce): + return base64.b64encode(hashlib.sha1(strutils.always_bytes(client_nonce) + MAGIC).digest()) + + +def check_client_version(headers): + return headers.get("sec-websocket-version", "") == VERSION + + +def get_extensions(headers): + return headers.get("sec-websocket-extensions", None) + + +def get_protocol(headers): + return headers.get("sec-websocket-protocol", None) + + +def get_client_key(headers): + return headers.get("sec-websocket-key", None) + + +def get_server_accept(headers): + return headers.get("sec-websocket-accept", None) |