From 61cadf26ea283fb549ac559c3ed501876207e097 Mon Sep 17 00:00:00 2001 From: Tim Newsham Date: Fri, 17 Jul 2015 07:58:07 -1000 Subject: [PATCH 1/8] add support for ssl cert chains to support client certs --- websocket/_http.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/websocket/_http.py b/websocket/_http.py index 5c4a638..7cd1da2 100644 --- a/websocket/_http.py +++ b/websocket/_http.py @@ -132,6 +132,9 @@ def _wrap_sni_socket(sock, sslopt, hostname, check_hostname): context.check_hostname = check_hostname if 'ciphers' in sslopt: context.set_ciphers(sslopt['ciphers']) + if 'cert_chain' in sslopt : + certfile,keyfile,password = sslopt['cert_chain'] + context.load_cert_chain(certfile,keyfile,password) return context.wrap_socket( sock, From 6410340fca47f258d50a34646138ba03b2b2783b Mon Sep 17 00:00:00 2001 From: Craig Jellick Date: Fri, 17 Jul 2015 13:49:28 -0700 Subject: [PATCH 2/8] Fix string formatting in exception --- websocket/_http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocket/_http.py b/websocket/_http.py index 5c4a638..0c73776 100644 --- a/websocket/_http.py +++ b/websocket/_http.py @@ -183,7 +183,7 @@ def _tunnel(sock, host, port, auth): if status != 200: raise WebSocketProxyException( - "failed CONNECT via proxy status: %r" + status) + "failed CONNECT via proxy status: %r" % status) return sock From 0465188677d829ba1656bce3aab0d6ec24e7d01c Mon Sep 17 00:00:00 2001 From: Niall Donegan Date: Mon, 20 Jul 2015 17:25:41 +0100 Subject: [PATCH 3/8] Typo fix in README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 495a043..8ef2b1b 100644 --- a/README.rst +++ b/README.rst @@ -62,7 +62,7 @@ Low Level API example:: print "Sending 'Hello, World'..." ws.send("Hello, World") print "Sent" - print "Reeiving..." + print "Receiving..." result = ws.recv() print "Received '%s'" % result ws.close() From fd2bf764af78844cad19c6277c6c17f2b04210e2 Mon Sep 17 00:00:00 2001 From: liris Date: Thu, 23 Jul 2015 07:45:03 +0900 Subject: [PATCH 4/8] add space. --- websocket/_http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocket/_http.py b/websocket/_http.py index ba3d550..7da328e 100644 --- a/websocket/_http.py +++ b/websocket/_http.py @@ -134,7 +134,7 @@ def _wrap_sni_socket(sock, sslopt, hostname, check_hostname): context.set_ciphers(sslopt['ciphers']) if 'cert_chain' in sslopt : certfile,keyfile,password = sslopt['cert_chain'] - context.load_cert_chain(certfile,keyfile,password) + context.load_cert_chain(certfile, keyfile, password) return context.wrap_socket( sock, From 821808f229f30b5791a6c9d1dbd2553c223612b1 Mon Sep 17 00:00:00 2001 From: liris Date: Thu, 23 Jul 2015 07:48:06 +0900 Subject: [PATCH 5/8] documentation --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index bbd94e1..1acee62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,9 @@ ChangeLog - fixed timeout+ssl error handling bug on python 2.7.10 (#190) - add proxy support to wsdump.py (#194) - use wsaccel if available (#193) + - add support for ssl cert chains to support client certs (#195) + - fix string formatting in exception (#196) + - fix typo in README.rst (#197) - 0.32.0 From 0dcebf652b018215904a538b20bc88f354ada443 Mon Sep 17 00:00:00 2001 From: liris Date: Thu, 30 Jul 2015 09:17:24 +0900 Subject: [PATCH 6/8] fixed #198 introduce on_data callback to pass data type. --- ChangeLog | 1 + websocket/_app.py | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1acee62..8dfdbec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,7 @@ ChangeLog - add support for ssl cert chains to support client certs (#195) - fix string formatting in exception (#196) - fix typo in README.rst (#197) + - introduce on_data callback to pass data type. (#198) - 0.32.0 diff --git a/websocket/_app.py b/websocket/_app.py index 9f8940f..c0f1878 100644 --- a/websocket/_app.py +++ b/websocket/_app.py @@ -48,7 +48,8 @@ class WebSocketApp(object): on_close=None, on_ping=None, on_pong=None, on_cont_message=None, keep_running=True, get_mask_key=None, cookie=None, - subprotocols=None): + subprotocols=None, + on_data=None): """ url: websocket url. header: custom header for websocket handshake. @@ -71,6 +72,14 @@ class WebSocketApp(object): The passing 2nd arugment is utf-8 string which we get from the server. The 3rd arugment is continue flag. if 0, the data continue to next frame data + on_data: callback object which is called when a message recieved. + This is called before on_message or on_cont_message, + and then on_message or on_cont_message is called. + on_data has 4 argument. + The 1st arugment is this class object. + The passing 2nd arugment is utf-8 string which we get from the server. + The 3rd argument is data type. ABNF.OPCODE_TEXT or ABNF.OPCODE_BINARY will be came. + The 4rd arugment is continue flag. if 0, the data continue keep_running: a boolean flag indicating whether the app's main loop should keep running, defaults to True get_mask_key: a callable to produce new mask keys, @@ -82,6 +91,7 @@ class WebSocketApp(object): self.cookie = cookie self.on_open = on_open self.on_message = on_message + self.on_data = on_data self.on_error = on_error self.on_close = on_close self.on_ping = on_ping @@ -192,11 +202,13 @@ class WebSocketApp(object): elif op_code == ABNF.OPCODE_PONG: self._callback(self.on_pong, frame.data) elif op_code == ABNF.OPCODE_CONT and self.on_cont_message: + self._callback(self.on_data, data, frame.opcode, frame.fin) self._callback(self.on_cont_message, frame.data, frame.fin) else: data = frame.data if six.PY3 and frame.opcode == ABNF.OPCODE_TEXT: data = data.decode("utf-8") + self._callback(self.on_data, data, frame.opcode, True) self._callback(self.on_message, data) except Exception as e: self._callback(self.on_error, e) From ec06e865881bdda96e9b995171bc7d3befe24032 Mon Sep 17 00:00:00 2001 From: liris Date: Thu, 30 Jul 2015 09:31:36 +0900 Subject: [PATCH 7/8] fixed #199 WebSocketBadStatusException for handshake error --- ChangeLog | 1 + websocket/_exceptions.py | 12 ++++++++++++ websocket/_handshake.py | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8dfdbec..c255cbc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ ChangeLog - fix string formatting in exception (#196) - fix typo in README.rst (#197) - introduce on_data callback to pass data type. (#198) + - WebSocketBadStatusException for Handshake error (#199) - 0.32.0 diff --git a/websocket/_exceptions.py b/websocket/_exceptions.py index 9b1791d..ffc41ab 100644 --- a/websocket/_exceptions.py +++ b/websocket/_exceptions.py @@ -31,18 +31,21 @@ class WebSocketException(Exception): """ pass + class WebSocketProtocolException(WebSocketException): """ If the webscoket protocol is invalid, this exception will be raised. """ pass + class WebSocketPayloadException(WebSocketException): """ If the webscoket payload is invalid, this exception will be raised. """ pass + class WebSocketConnectionClosedException(WebSocketException): """ If remote host closed the connection or some network error happened, @@ -50,12 +53,14 @@ class WebSocketConnectionClosedException(WebSocketException): """ pass + class WebSocketTimeoutException(WebSocketException): """ WebSocketTimeoutException will be raised at socket timeout during read/write data. """ pass + class WebSocketProxyException(WebSocketException): """ WebSocketProxyException will be raised when proxy error occured. @@ -63,3 +68,10 @@ class WebSocketProxyException(WebSocketException): pass +class WebSocketBadStatusException(WebSocketException): + """ + WebSocketBadStatusException will be raised when we get bad handshake status code. + """ + def __init__(self, message, status_code): + super(WebSocketBadStatusException, self).__init__(message % status_code) + self.status_code = status_code diff --git a/websocket/_handshake.py b/websocket/_handshake.py index d8876e7..4d20fed 100644 --- a/websocket/_handshake.py +++ b/websocket/_handshake.py @@ -108,7 +108,7 @@ def _get_handshake_headers(resource, host, port, options): def _get_resp_headers(sock, success_status=101): status, resp_headers = read_headers(sock) if status != success_status: - raise WebSocketException("Handshake status %d" % status) + raise WebSocketBadStatusException("Handshake status %d", status) return status, resp_headers _HEADERS_TO_CHECK = { From d00154724b6c724809e7490868ae053a99d1a35a Mon Sep 17 00:00:00 2001 From: liris Date: Thu, 30 Jul 2015 10:30:12 +0900 Subject: [PATCH 8/8] fixed #192 introduced close timeout --- ChangeLog | 1 + websocket/_core.py | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index c255cbc..44572f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ ChangeLog - fix typo in README.rst (#197) - introduce on_data callback to pass data type. (#198) - WebSocketBadStatusException for Handshake error (#199) + - set close timeout (#192) - 0.32.0 diff --git a/websocket/_core.py b/websocket/_core.py index 4d7ddec..7524f94 100644 --- a/websocket/_core.py +++ b/websocket/_core.py @@ -422,13 +422,16 @@ class WebSocket(object): self.connected = False self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE) - def close(self, status=STATUS_NORMAL, reason=six.b("")): + def close(self, status=STATUS_NORMAL, reason=six.b(""), timeout=3): """ Close Websocket object status: status code to send. see STATUS_XXX. reason: the reason to close. This must be string. + + timeout: timeout until recieve a close frame. + If None, it will wait forever until recieve a close frame. """ if self.connected: if status < 0 or status >= ABNF.LENGTH_16: @@ -437,8 +440,8 @@ class WebSocket(object): try: self.connected = False self.send(struct.pack('!H', status) + reason, ABNF.OPCODE_CLOSE) - timeout = self.sock.gettimeout() - self.sock.settimeout(3) + sock_timeout = self.sock.gettimeout() + self.sock.settimeout(timeout) try: frame = self.recv_frame() if isEnabledForError(): @@ -447,7 +450,7 @@ class WebSocket(object): error("close status: " + repr(recv_status)) except: pass - self.sock.settimeout(timeout) + self.sock.settimeout(sock_timeout) self.sock.shutdown(socket.SHUT_RDWR) except: pass