diff options
author | Juho Hovila <juho.hovila@arm.com> | 2018-08-29 11:30:17 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-29 11:30:17 +0300 |
commit | 7997ee1c18d142ed910aded8a1636cab78b86e42 (patch) | |
tree | 3df88b84b315d076bf35ff3fb7ada162bfd2081a /websocket | |
parent | ae589495b75162703ab4fe1f8712f50d22b12d4e (diff) | |
download | websocket-client-7997ee1c18d142ed910aded8a1636cab78b86e42.tar.gz |
Fix SSL socket handling (#2)
* Fix ssl socket handling
Handle them as recommended in here
https://bugs.python.org/issue21430 and in
python documentation. Do not use undocumented
SSLSocket pending
* Increase version
Diffstat (limited to 'websocket')
-rw-r--r-- | websocket/_socket.py | 38 | ||||
-rw-r--r-- | websocket/_ssl_compat.py | 10 | ||||
-rw-r--r-- | websocket/_utils.py | 7 |
3 files changed, 51 insertions, 4 deletions
diff --git a/websocket/_socket.py b/websocket/_socket.py index c84fcf9..d811c21 100644 --- a/websocket/_socket.py +++ b/websocket/_socket.py @@ -19,6 +19,8 @@ Copyright (C) 2010 Hiroki Ohtani(liris) Boston, MA 02110-1335 USA """ +import errno +import select import socket import six @@ -77,8 +79,24 @@ def recv(sock, bufsize): if not sock: raise WebSocketConnectionClosedException("socket is already closed.") + def _recv(): + try: + return sock.recv(bufsize) + except SSLWantReadError: + pass + except socket.error as exc: + error_code = extract_error_code(exc) + if error_code is None: + raise + if error_code != errno.EAGAIN or error_code != errno.EWOULDBLOCK: + raise + + r, w, e = select.select((sock, ), (), (), sock.gettimeout()) + if r: + return sock.recv(bufsize) + try: - bytes_ = sock.recv(bufsize) + bytes_ = _recv() except socket.timeout as e: message = extract_err_message(e) raise WebSocketTimeoutException(message) @@ -113,8 +131,24 @@ def send(sock, data): if not sock: raise WebSocketConnectionClosedException("socket is already closed.") + def _send(): + try: + return sock.send(data) + except SSLWantWriteError: + pass + except socket.error as exc: + error_code = extract_error_code(exc) + if error_code is None: + raise + if error_code != errno.EAGAIN or error_code != errno.EWOULDBLOCK: + raise + + r, w, e = select.select((), (sock, ), (), sock.gettimeout()) + if w: + return sock.send(data) + try: - return sock.send(data) + return _send() except socket.timeout as e: message = extract_err_message(e) raise WebSocketTimeoutException(message) diff --git a/websocket/_ssl_compat.py b/websocket/_ssl_compat.py index 0304816..5b3c413 100644 --- a/websocket/_ssl_compat.py +++ b/websocket/_ssl_compat.py @@ -19,11 +19,13 @@ Copyright (C) 2010 Hiroki Ohtani(liris) Boston, MA 02110-1335 USA """ -__all__ = ["HAVE_SSL", "ssl", "SSLError"] +__all__ = ["HAVE_SSL", "ssl", "SSLError", "SSLWantReadError", "SSLWantWriteError"] try: import ssl from ssl import SSLError + from ssl import SSLWantReadError + from ssl import SSLWantWriteError if hasattr(ssl, 'SSLContext') and hasattr(ssl.SSLContext, 'check_hostname'): HAVE_CONTEXT_CHECK_HOSTNAME = True else: @@ -41,4 +43,10 @@ except ImportError: class SSLError(Exception): pass + class SSLWantReadError(Exception): + pass + + class SSLWantWriteError(Exception): + pass + HAVE_SSL = False diff --git a/websocket/_utils.py b/websocket/_utils.py index 399fb89..8eddabf 100644 --- a/websocket/_utils.py +++ b/websocket/_utils.py @@ -21,7 +21,7 @@ Copyright (C) 2010 Hiroki Ohtani(liris) """ import six -__all__ = ["NoLock", "validate_utf8", "extract_err_message"] +__all__ = ["NoLock", "validate_utf8", "extract_err_message", "extract_error_code"] class NoLock(object): @@ -103,3 +103,8 @@ def extract_err_message(exception): return exception.args[0] else: return None + + +def extract_error_code(exception): + if exception.args and len(exception.args) > 1: + return exception.args[0] if isinstance(exception.args[0], int) else None |