summaryrefslogtreecommitdiff
path: root/websocket
diff options
context:
space:
mode:
authorJuho Hovila <juho.hovila@arm.com>2018-08-29 11:30:17 +0300
committerGitHub <noreply@github.com>2018-08-29 11:30:17 +0300
commit7997ee1c18d142ed910aded8a1636cab78b86e42 (patch)
tree3df88b84b315d076bf35ff3fb7ada162bfd2081a /websocket
parentae589495b75162703ab4fe1f8712f50d22b12d4e (diff)
downloadwebsocket-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.py38
-rw-r--r--websocket/_ssl_compat.py10
-rw-r--r--websocket/_utils.py7
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