summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eventlet/green/ssl.py25
-rw-r--r--eventlet/greenio/base.py2
-rw-r--r--tests/ssl_test.py153
3 files changed, 107 insertions, 73 deletions
diff --git a/eventlet/green/ssl.py b/eventlet/green/ssl.py
index 81eae3d..828f9bf 100644
--- a/eventlet/green/ssl.py
+++ b/eventlet/green/ssl.py
@@ -3,16 +3,17 @@ __ssl = __import__('ssl')
from eventlet.patcher import slurp_properties
slurp_properties(__ssl, globals(), srckeys=dir(__ssl))
+import errno
import functools
import sys
-import errno
-time = __import__('time')
+import time
-from eventlet.support import get_errno, PY33, six
-from eventlet.hubs import trampoline, IOClosed
+from eventlet import greenio
from eventlet.greenio import (
- set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS,
+ set_nonblocking, GreenSocket, CONNECT_ERR, CONNECT_SUCCESS,
)
+from eventlet.hubs import trampoline, IOClosed
+from eventlet.support import get_errno, PY33, six
orig_socket = __import__('socket')
socket = orig_socket.socket
if sys.version_info >= (2, 7):
@@ -181,10 +182,11 @@ class GreenSSLSocket(_original_sslsocket):
except orig_socket.error as e:
if self.act_non_blocking:
raise
- if get_errno(e) == errno.EWOULDBLOCK:
+ erno = get_errno(e)
+ if erno in greenio.SOCKET_BLOCKING:
trampoline(self, write=True,
timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
- if get_errno(e) in SOCKET_CLOSED:
+ elif erno in greenio.SOCKET_CLOSED:
return ''
raise
@@ -204,14 +206,15 @@ class GreenSSLSocket(_original_sslsocket):
except orig_socket.error as e:
if self.act_non_blocking:
raise
- if get_errno(e) == errno.EWOULDBLOCK:
+ erno = get_errno(e)
+ if erno in greenio.SOCKET_BLOCKING:
try:
trampoline(
self, read=True,
timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
except IOClosed:
return b''
- if get_errno(e) in SOCKET_CLOSED:
+ elif erno in greenio.SOCKET_CLOSED:
return b''
raise
@@ -318,7 +321,7 @@ class GreenSSLSocket(_original_sslsocket):
set_nonblocking(newsock)
break
except orig_socket.error as e:
- if get_errno(e) != errno.EWOULDBLOCK:
+ if get_errno(e) not in greenio.SOCKET_BLOCKING:
raise
trampoline(self, read=True, timeout=self.gettimeout(),
timeout_exc=timeout_exc('timed out'))
@@ -331,7 +334,7 @@ class GreenSSLSocket(_original_sslsocket):
cert_reqs=self.cert_reqs,
ssl_version=self.ssl_version,
ca_certs=self.ca_certs,
- do_handshake_on_connect=self.do_handshake_on_connect,
+ do_handshake_on_connect=False,
suppress_ragged_eofs=self.suppress_ragged_eofs)
return (new_ssl, addr)
diff --git a/eventlet/greenio/base.py b/eventlet/greenio/base.py
index e1c4a45..60a8f29 100644
--- a/eventlet/greenio/base.py
+++ b/eventlet/greenio/base.py
@@ -11,7 +11,7 @@ from eventlet.support import get_errno, six
__all__ = [
'GreenSocket', '_GLOBAL_DEFAULT_TIMEOUT', 'set_nonblocking',
- 'SOCKET_CLOSED', 'CONNECT_ERR', 'CONNECT_SUCCESS',
+ 'SOCKET_BLOCKING', 'SOCKET_CLOSED', 'CONNECT_ERR', 'CONNECT_SUCCESS',
'shutdown_safe', 'SSL',
]
diff --git a/tests/ssl_test.py b/tests/ssl_test.py
index 621ff47..13e090c 100644
--- a/tests/ssl_test.py
+++ b/tests/ssl_test.py
@@ -1,6 +1,5 @@
import socket
import warnings
-from unittest import main
import eventlet
from eventlet import greenio
@@ -8,22 +7,23 @@ try:
from eventlet.green import ssl
except ImportError:
pass
-from tests import (
- LimitedTestCase, certificate_file, private_key_file, check_idle_cpu_usage,
- skip_if_no_ssl
-)
+import tests
-def listen_ssl_socket(address=('127.0.0.1', 0)):
+def listen_ssl_socket(address=('localhost', 0), **kwargs):
sock = ssl.wrap_socket(
- socket.socket(), private_key_file, certificate_file, server_side=True)
+ socket.socket(),
+ tests.private_key_file,
+ tests.certificate_file,
+ server_side=True,
+ **kwargs
+ )
sock.bind(address)
sock.listen(50)
-
return sock
-class SSLTest(LimitedTestCase):
+class SSLTest(tests.LimitedTestCase):
def setUp(self):
# disabling socket.ssl warnings because we're testing it here
warnings.filterwarnings(
@@ -33,30 +33,29 @@ class SSLTest(LimitedTestCase):
super(SSLTest, self).setUp()
- @skip_if_no_ssl
+ @tests.skip_if_no_ssl
def test_duplex_response(self):
def serve(listener):
sock, addr = listener.accept()
- sock.read(8192)
- sock.write(b'response')
+ sock.recv(8192)
+ sock.sendall(b'response')
sock = listen_ssl_socket()
server_coro = eventlet.spawn(serve, sock)
- client = ssl.wrap_socket(
- eventlet.connect(('127.0.0.1', sock.getsockname()[1])))
- client.write(b'line 1\r\nline 2\r\n\r\n')
- self.assertEqual(client.read(8192), b'response')
+ client = ssl.wrap_socket(eventlet.connect(sock.getsockname()))
+ client.sendall(b'line 1\r\nline 2\r\n\r\n')
+ self.assertEqual(client.recv(8192), b'response')
server_coro.wait()
- @skip_if_no_ssl
+ @tests.skip_if_no_ssl
def test_ssl_close(self):
def serve(listener):
sock, addr = listener.accept()
- sock.read(8192)
+ sock.recv(8192)
try:
- self.assertEqual(b"", sock.read(8192))
+ self.assertEqual(b'', sock.recv(8192))
except greenio.SSL.ZeroReturnError:
pass
@@ -64,54 +63,54 @@ class SSLTest(LimitedTestCase):
server_coro = eventlet.spawn(serve, sock)
- raw_client = eventlet.connect(('127.0.0.1', sock.getsockname()[1]))
+ raw_client = eventlet.connect(sock.getsockname())
client = ssl.wrap_socket(raw_client)
- client.write(b'X')
+ client.sendall(b'X')
greenio.shutdown_safe(client)
client.close()
server_coro.wait()
- @skip_if_no_ssl
+ @tests.skip_if_no_ssl
def test_ssl_connect(self):
def serve(listener):
sock, addr = listener.accept()
- sock.read(8192)
+ sock.recv(8192)
sock = listen_ssl_socket()
server_coro = eventlet.spawn(serve, sock)
raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_client = ssl.wrap_socket(raw_client)
- ssl_client.connect(('127.0.0.1', sock.getsockname()[1]))
- ssl_client.write(b'abc')
+ ssl_client.connect(sock.getsockname())
+ ssl_client.sendall(b'abc')
greenio.shutdown_safe(ssl_client)
ssl_client.close()
server_coro.wait()
- @skip_if_no_ssl
+ @tests.skip_if_no_ssl
def test_ssl_unwrap(self):
def serve():
sock, addr = listener.accept()
self.assertEqual(sock.recv(6), b'before')
- sock_ssl = ssl.wrap_socket(sock, private_key_file, certificate_file,
+ sock_ssl = ssl.wrap_socket(sock, tests.private_key_file, tests.certificate_file,
server_side=True)
sock_ssl.do_handshake()
- self.assertEqual(sock_ssl.read(6), b'during')
+ self.assertEqual(sock_ssl.recv(6), b'during')
sock2 = sock_ssl.unwrap()
self.assertEqual(sock2.recv(5), b'after')
sock2.close()
listener = eventlet.listen(('127.0.0.1', 0))
server_coro = eventlet.spawn(serve)
- client = eventlet.connect((listener.getsockname()))
- client.send(b'before')
+ client = eventlet.connect(listener.getsockname())
+ client.sendall(b'before')
client_ssl = ssl.wrap_socket(client)
client_ssl.do_handshake()
- client_ssl.write(b'during')
+ client_ssl.sendall(b'during')
client2 = client_ssl.unwrap()
- client2.send(b'after')
+ client2.sendall(b'after')
server_coro.wait()
- @skip_if_no_ssl
+ @tests.skip_if_no_ssl
def test_sendall_cpu_usage(self):
"""SSL socket.sendall() busy loop
@@ -132,8 +131,8 @@ class SSLTest(LimitedTestCase):
def serve(listener):
conn, _ = listener.accept()
conn.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, BUFFER_SIZE)
- self.assertEqual(conn.read(8), b'request')
- conn.write(b'response')
+ self.assertEqual(conn.recv(8), b'request')
+ conn.sendall(b'response')
stage_1.wait()
conn.sendall(b'x' * SENDALL_SIZE)
@@ -144,41 +143,73 @@ class SSLTest(LimitedTestCase):
client_sock = eventlet.connect(server_sock.getsockname())
client_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, BUFFER_SIZE)
client = ssl.wrap_socket(client_sock)
- client.write(b'request')
- self.assertEqual(client.read(8), b'response')
+ client.sendall(b'request')
+ self.assertEqual(client.recv(8), b'response')
stage_1.send()
- check_idle_cpu_usage(0.2, 0.1)
+ tests.check_idle_cpu_usage(0.2, 0.1)
server_coro.kill()
- @skip_if_no_ssl
+ @tests.skip_if_no_ssl
def test_greensslobject(self):
def serve(listener):
sock, addr = listener.accept()
- sock.write(b'content')
+ sock.sendall(b'content')
greenio.shutdown_safe(sock)
sock.close()
- listener = listen_ssl_socket(('', 0))
+ listener = listen_ssl_socket()
eventlet.spawn(serve, listener)
- client = ssl.wrap_socket(
- eventlet.connect(('localhost', listener.getsockname()[1])))
- self.assertEqual(client.read(1024), b'content')
- self.assertEqual(client.read(1024), b'')
+ client = ssl.wrap_socket(eventlet.connect(listener.getsockname()))
+ self.assertEqual(client.recv(1024), b'content')
+ self.assertEqual(client.recv(1024), b'')
- @skip_if_no_ssl
+ @tests.skip_if_no_ssl
def test_regression_gh_17(self):
- def serve(listener):
- sock, addr = listener.accept()
-
- # to simulate condition mentioned in GH-17
- sock._sslobj = None
- sock.sendall(b'some data')
- greenio.shutdown_safe(sock)
- sock.close()
-
- listener = listen_ssl_socket(('', 0))
- eventlet.spawn(serve, listener)
- ssl.wrap_socket(eventlet.connect(('localhost', listener.getsockname()[1])))
-
-if __name__ == '__main__':
- main()
+ # https://github.com/eventlet/eventlet/issues/17
+ # ssl wrapped but unconnected socket methods go special code path
+ # test that path at least for syntax/typo errors
+ sock = ssl.wrap_socket(socket.socket())
+ sock.settimeout(0.01)
+ try:
+ sock.sendall(b'')
+ except ssl.SSLError as e:
+ assert 'timed out' in str(e)
+
+ @tests.skip_if_no_ssl
+ def test_no_handshake_block_accept_loop(self):
+ listener = listen_ssl_socket()
+ listener.settimeout(0.3)
+
+ def serve(sock):
+ try:
+ name = sock.recv(8)
+ sock.sendall(b'hello ' + name)
+ except Exception:
+ # ignore evil clients
+ pass
+ finally:
+ greenio.shutdown_safe(sock)
+ sock.close()
+
+ def accept_loop():
+ while True:
+ try:
+ sock, _ = listener.accept()
+ except socket.error:
+ return
+ eventlet.spawn(serve, sock)
+
+ loopt = eventlet.spawn(accept_loop)
+
+ # evil no handshake
+ evil = eventlet.connect(listener.getsockname())
+ good = ssl.wrap_socket(eventlet.connect(listener.getsockname()))
+ good.sendall(b'good')
+ response = good.recv(16)
+ good.close()
+ assert response == b'hello good'
+ evil.close()
+
+ listener.close()
+ loopt.wait()
+ eventlet.sleep(0)