summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Svetlov <andrew.svetlov@gmail.com>2017-11-18 16:54:05 (GMT)
committerGitHub <noreply@github.com>2017-11-18 16:54:05 (GMT)
commit51d546ae4d563fde608e23c9c337fefd7e95c93f (patch)
treed2bd875c8f22d60a2fc5a5c522bf17a424b97757
parentf02f5e5c3eb815fff9578dc58de60374c6baaa3d (diff)
downloadcpython-51d546ae4d563fde608e23c9c337fefd7e95c93f.zip
cpython-51d546ae4d563fde608e23c9c337fefd7e95c93f.tar.gz
cpython-51d546ae4d563fde608e23c9c337fefd7e95c93f.tar.bz2
bpo-32069: Drop legacy SSL transport (#4451)
* Drop legacy SSL transport * Drop unused import * Fix Windows tests * Drop never executed on Python 3.4+ code
-rw-r--r--Lib/asyncio/proactor_events.py5
-rw-r--r--Lib/asyncio/selector_events.py248
-rw-r--r--Lib/asyncio/sslproto.py20
-rw-r--r--Lib/asyncio/test_utils.py5
-rw-r--r--Lib/test/test_asyncio/test_events.py68
-rw-r--r--Lib/test/test_asyncio/test_selector_events.py363
-rw-r--r--Misc/NEWS.d/next/Library/2017-11-18-17-09-01.bpo-32069.S0wyy4.rst1
7 files changed, 5 insertions, 705 deletions
diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py
index 5e7a397..e35d05b 100644
--- a/Lib/asyncio/proactor_events.py
+++ b/Lib/asyncio/proactor_events.py
@@ -392,11 +392,6 @@ class BaseProactorEventLoop(base_events.BaseEventLoop):
def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
*, server_side=False, server_hostname=None,
extra=None, server=None):
- if not sslproto._is_sslproto_available():
- raise NotImplementedError("Proactor event loop requires Python 3.5"
- " or newer (ssl.MemoryBIO) to support "
- "SSL")
-
ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
server_side, server_hostname)
_ProactorSocketTransport(self, rawsock, ssl_protocol,
diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index f3b278c..4baad48 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -74,28 +74,12 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
*, server_side=False, server_hostname=None,
extra=None, server=None):
- if not sslproto._is_sslproto_available():
- return self._make_legacy_ssl_transport(
- rawsock, protocol, sslcontext, waiter,
- server_side=server_side, server_hostname=server_hostname,
- extra=extra, server=server)
-
ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
server_side, server_hostname)
_SelectorSocketTransport(self, rawsock, ssl_protocol,
extra=extra, server=server)
return ssl_protocol._app_transport
- def _make_legacy_ssl_transport(self, rawsock, protocol, sslcontext,
- waiter, *,
- server_side=False, server_hostname=None,
- extra=None, server=None):
- # Use the legacy API: SSL_write, SSL_read, etc. The legacy API is used
- # on Python 3.4 and older, when ssl.MemoryBIO is not available.
- return _SelectorSslTransport(
- self, rawsock, protocol, sslcontext, waiter,
- server_side, server_hostname, extra, server)
-
def _make_datagram_transport(self, sock, protocol,
address=None, waiter=None, extra=None):
return _SelectorDatagramTransport(self, sock, protocol,
@@ -848,238 +832,6 @@ class _SelectorSocketTransport(_SelectorTransport):
return True
-class _SelectorSslTransport(_SelectorTransport):
-
- _buffer_factory = bytearray
-
- def __init__(self, loop, rawsock, protocol, sslcontext, waiter=None,
- server_side=False, server_hostname=None,
- extra=None, server=None):
- if ssl is None:
- raise RuntimeError('stdlib ssl module not available')
-
- if not sslcontext:
- sslcontext = sslproto._create_transport_context(server_side, server_hostname)
-
- wrap_kwargs = {
- 'server_side': server_side,
- 'do_handshake_on_connect': False,
- }
- if server_hostname and not server_side:
- wrap_kwargs['server_hostname'] = server_hostname
- sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs)
-
- super().__init__(loop, sslsock, protocol, extra, server)
- # the protocol connection is only made after the SSL handshake
- self._protocol_connected = False
-
- self._server_hostname = server_hostname
- self._waiter = waiter
- self._sslcontext = sslcontext
- self._paused = False
-
- # SSL-specific extra info. (peercert is set later)
- self._extra.update(sslcontext=sslcontext)
-
- if self._loop.get_debug():
- logger.debug("%r starts SSL handshake", self)
- start_time = self._loop.time()
- else:
- start_time = None
- self._on_handshake(start_time)
-
- def _wakeup_waiter(self, exc=None):
- if self._waiter is None:
- return
- if not self._waiter.cancelled():
- if exc is not None:
- self._waiter.set_exception(exc)
- else:
- self._waiter.set_result(None)
- self._waiter = None
-
- def _on_handshake(self, start_time):
- try:
- self._sock.do_handshake()
- except ssl.SSLWantReadError:
- self._loop._add_reader(self._sock_fd,
- self._on_handshake, start_time)
- return
- except ssl.SSLWantWriteError:
- self._loop._add_writer(self._sock_fd,
- self._on_handshake, start_time)
- return
- except BaseException as exc:
- if self._loop.get_debug():
- logger.warning("%r: SSL handshake failed",
- self, exc_info=True)
- self._loop._remove_reader(self._sock_fd)
- self._loop._remove_writer(self._sock_fd)
- self._sock.close()
- self._wakeup_waiter(exc)
- if isinstance(exc, Exception):
- return
- else:
- raise
-
- self._loop._remove_reader(self._sock_fd)
- self._loop._remove_writer(self._sock_fd)
-
- peercert = self._sock.getpeercert()
- if not hasattr(self._sslcontext, 'check_hostname'):
- # Verify hostname if requested, Python 3.4+ uses check_hostname
- # and checks the hostname in do_handshake()
- if (self._server_hostname and
- self._sslcontext.verify_mode != ssl.CERT_NONE):
- try:
- ssl.match_hostname(peercert, self._server_hostname)
- except Exception as exc:
- if self._loop.get_debug():
- logger.warning("%r: SSL handshake failed "
- "on matching the hostname",
- self, exc_info=True)
- self._sock.close()
- self._wakeup_waiter(exc)
- return
-
- # Add extra info that becomes available after handshake.
- self._extra.update(peercert=peercert,
- cipher=self._sock.cipher(),
- compression=self._sock.compression(),
- ssl_object=self._sock,
- )
-
- self._read_wants_write = False
- self._write_wants_read = False
- self._loop._add_reader(self._sock_fd, self._read_ready)
- self._protocol_connected = True
- self._loop.call_soon(self._protocol.connection_made, self)
- # only wake up the waiter when connection_made() has been called
- self._loop.call_soon(self._wakeup_waiter)
-
- if self._loop.get_debug():
- dt = self._loop.time() - start_time
- logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
-
- def pause_reading(self):
- # XXX This is a bit icky, given the comment at the top of
- # _read_ready(). Is it possible to evoke a deadlock? I don't
- # know, although it doesn't look like it; write() will still
- # accept more data for the buffer and eventually the app will
- # call resume_reading() again, and things will flow again.
-
- if self._closing:
- raise RuntimeError('Cannot pause_reading() when closing')
- if self._paused:
- raise RuntimeError('Already paused')
- self._paused = True
- self._loop._remove_reader(self._sock_fd)
- if self._loop.get_debug():
- logger.debug("%r pauses reading", self)
-
- def resume_reading(self):
- if not self._paused:
- raise RuntimeError('Not paused')
- self._paused = False
- if self._closing:
- return
- self._loop._add_reader(self._sock_fd, self._read_ready)
- if self._loop.get_debug():
- logger.debug("%r resumes reading", self)
-
- def _read_ready(self):
- if self._conn_lost:
- return
- if self._write_wants_read:
- self._write_wants_read = False
- self._write_ready()
-
- if self._buffer:
- self._loop._add_writer(self._sock_fd, self._write_ready)
-
- try:
- data = self._sock.recv(self.max_size)
- except (BlockingIOError, InterruptedError, ssl.SSLWantReadError):
- pass
- except ssl.SSLWantWriteError:
- self._read_wants_write = True
- self._loop._remove_reader(self._sock_fd)
- self._loop._add_writer(self._sock_fd, self._write_ready)
- except Exception as exc:
- self._fatal_error(exc, 'Fatal read error on SSL transport')
- else:
- if data:
- self._protocol.data_received(data)
- else:
- try:
- if self._loop.get_debug():
- logger.debug("%r received EOF", self)
- keep_open = self._protocol.eof_received()
- if keep_open:
- logger.warning('returning true from eof_received() '
- 'has no effect when using ssl')
- finally:
- self.close()
-
- def _write_ready(self):
- if self._conn_lost:
- return
- if self._read_wants_write:
- self._read_wants_write = False
- self._read_ready()
-
- if not (self._paused or self._closing):
- self._loop._add_reader(self._sock_fd, self._read_ready)
-
- if self._buffer:
- try:
- n = self._sock.send(self._buffer)
- except (BlockingIOError, InterruptedError, ssl.SSLWantWriteError):
- n = 0
- except ssl.SSLWantReadError:
- n = 0
- self._loop._remove_writer(self._sock_fd)
- self._write_wants_read = True
- except Exception as exc:
- self._loop._remove_writer(self._sock_fd)
- self._buffer.clear()
- self._fatal_error(exc, 'Fatal write error on SSL transport')
- return
-
- if n:
- del self._buffer[:n]
-
- self._maybe_resume_protocol() # May append to buffer.
-
- if not self._buffer:
- self._loop._remove_writer(self._sock_fd)
- if self._closing:
- self._call_connection_lost(None)
-
- def write(self, data):
- if not isinstance(data, (bytes, bytearray, memoryview)):
- raise TypeError('data argument must be a bytes-like object, '
- 'not %r' % type(data).__name__)
- if not data:
- return
-
- if self._conn_lost:
- if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
- logger.warning('socket.send() raised exception.')
- self._conn_lost += 1
- return
-
- if not self._buffer:
- self._loop._add_writer(self._sock_fd, self._write_ready)
-
- # Add it to the buffer.
- self._buffer.extend(data)
- self._maybe_pause_protocol()
-
- def can_write_eof(self):
- return False
-
-
class _SelectorDatagramTransport(_SelectorTransport):
_buffer_factory = collections.deque
diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py
index 53e6d2b..c231eb5 100644
--- a/Lib/asyncio/sslproto.py
+++ b/Lib/asyncio/sslproto.py
@@ -18,25 +18,13 @@ def _create_transport_context(server_side, server_hostname):
# Client side may pass ssl=True to use a default
# context; in that case the sslcontext passed is None.
# The default is secure for client connections.
- if hasattr(ssl, 'create_default_context'):
- # Python 3.4+: use up-to-date strong settings.
- sslcontext = ssl.create_default_context()
- if not server_hostname:
- sslcontext.check_hostname = False
- else:
- # Fallback for Python 3.3.
- sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
- sslcontext.options |= ssl.OP_NO_SSLv2
- sslcontext.options |= ssl.OP_NO_SSLv3
- sslcontext.set_default_verify_paths()
- sslcontext.verify_mode = ssl.CERT_REQUIRED
+ # Python 3.4+: use up-to-date strong settings.
+ sslcontext = ssl.create_default_context()
+ if not server_hostname:
+ sslcontext.check_hostname = False
return sslcontext
-def _is_sslproto_available():
- return hasattr(ssl, "MemoryBIO")
-
-
# States of an _SSLPipe.
_UNWRAPPED = "UNWRAPPED"
_DO_HANDSHAKE = "DO_HANDSHAKE"
diff --git a/Lib/asyncio/test_utils.py b/Lib/asyncio/test_utils.py
index c9b1982..c3ddfe3 100644
--- a/Lib/asyncio/test_utils.py
+++ b/Lib/asyncio/test_utils.py
@@ -508,8 +508,3 @@ def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM,
sock.family = family
sock.gettimeout.return_value = 0.0
return sock
-
-
-def force_legacy_ssl_support():
- return mock.patch('asyncio.sslproto._is_sslproto_available',
- return_value=False)
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index 5394ddf..1a8bc13 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -736,10 +736,6 @@ class EventLoopTestsMixin:
self._test_create_ssl_connection(httpd, create_connection,
peername=httpd.address)
- def test_legacy_create_ssl_connection(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_ssl_connection()
-
@unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_ssl_unix_connection(self):
@@ -757,10 +753,6 @@ class EventLoopTestsMixin:
check_sockname,
peername=httpd.address)
- def test_legacy_create_ssl_unix_connection(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_ssl_unix_connection()
-
def test_create_connection_local_addr(self):
with test_utils.run_test_server() as httpd:
port = support.find_unused_port()
@@ -1061,10 +1053,6 @@ class EventLoopTestsMixin:
# stop serving
server.close()
- def test_legacy_create_server_ssl(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_server_ssl()
-
@unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_unix_server_ssl(self):
@@ -1096,10 +1084,6 @@ class EventLoopTestsMixin:
# stop serving
server.close()
- def test_legacy_create_unix_server_ssl(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_unix_server_ssl()
-
@unittest.skipIf(ssl is None, 'No ssl module')
def test_create_server_ssl_verify_failed(self):
proto = MyProto(loop=self.loop)
@@ -1129,10 +1113,6 @@ class EventLoopTestsMixin:
self.assertIsNone(proto.transport)
server.close()
- def test_legacy_create_server_ssl_verify_failed(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_server_ssl_verify_failed()
-
@unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_unix_server_ssl_verify_failed(self):
@@ -1163,11 +1143,6 @@ class EventLoopTestsMixin:
self.assertIsNone(proto.transport)
server.close()
-
- def test_legacy_create_unix_server_ssl_verify_failed(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_unix_server_ssl_verify_failed()
-
@unittest.skipIf(ssl is None, 'No ssl module')
def test_create_server_ssl_match_failed(self):
proto = MyProto(loop=self.loop)
@@ -1196,10 +1171,6 @@ class EventLoopTestsMixin:
proto.transport.close()
server.close()
- def test_legacy_create_server_ssl_match_failed(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_server_ssl_match_failed()
-
@unittest.skipIf(ssl is None, 'No ssl module')
@unittest.skipUnless(hasattr(socket, 'AF_UNIX'), 'No UNIX Sockets')
def test_create_unix_server_ssl_verified(self):
@@ -1226,10 +1197,6 @@ class EventLoopTestsMixin:
server.close()
self.loop.run_until_complete(proto.done)
- def test_legacy_create_unix_server_ssl_verified(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_unix_server_ssl_verified()
-
@unittest.skipIf(ssl is None, 'No ssl module')
def test_create_server_ssl_verified(self):
proto = MyProto(loop=self.loop)
@@ -1259,10 +1226,6 @@ class EventLoopTestsMixin:
server.close()
self.loop.run_until_complete(proto.done)
- def test_legacy_create_server_ssl_verified(self):
- with test_utils.force_legacy_ssl_support():
- self.test_create_server_ssl_verified()
-
def test_create_server_sock(self):
proto = asyncio.Future(loop=self.loop)
@@ -2159,37 +2122,6 @@ if sys.platform == 'win32':
def create_event_loop(self):
return asyncio.ProactorEventLoop()
- if not sslproto._is_sslproto_available():
- def test_create_ssl_connection(self):
- raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
- def test_create_server_ssl(self):
- raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
- def test_create_server_ssl_verify_failed(self):
- raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
- def test_create_server_ssl_match_failed(self):
- raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
- def test_create_server_ssl_verified(self):
- raise unittest.SkipTest("need python 3.5 (ssl.MemoryBIO)")
-
- def test_legacy_create_ssl_connection(self):
- raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
- def test_legacy_create_server_ssl(self):
- raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
- def test_legacy_create_server_ssl_verify_failed(self):
- raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
- def test_legacy_create_server_ssl_match_failed(self):
- raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
- def test_legacy_create_server_ssl_verified(self):
- raise unittest.SkipTest("IocpEventLoop incompatible with legacy SSL")
-
def test_reader_callback(self):
raise unittest.SkipTest("IocpEventLoop does not have add_reader()")
diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py
index a3d118e..e67afcc 100644
--- a/Lib/test/test_asyncio/test_selector_events.py
+++ b/Lib/test/test_asyncio/test_selector_events.py
@@ -14,7 +14,6 @@ from asyncio import selectors
from asyncio import test_utils
from asyncio.selector_events import BaseSelectorEventLoop
from asyncio.selector_events import _SelectorTransport
-from asyncio.selector_events import _SelectorSslTransport
from asyncio.selector_events import _SelectorSocketTransport
from asyncio.selector_events import _SelectorDatagramTransport
@@ -1178,368 +1177,6 @@ class SelectorSocketTransportTests(test_utils.TestCase):
remove_writer.assert_called_with(self.sock_fd)
-@unittest.skipIf(ssl is None, 'No ssl module')
-class SelectorSslTransportTests(test_utils.TestCase):
-
- def setUp(self):
- super().setUp()
- self.loop = self.new_test_loop()
- self.protocol = test_utils.make_test_protocol(asyncio.Protocol)
- self.sock = mock.Mock(socket.socket)
- self.sock.fileno.return_value = 7
- self.sslsock = mock.Mock()
- self.sslsock.fileno.return_value = 1
- self.sslcontext = mock.Mock()
- self.sslcontext.wrap_socket.return_value = self.sslsock
-
- def ssl_transport(self, waiter=None, server_hostname=None):
- transport = _SelectorSslTransport(self.loop, self.sock, self.protocol,
- self.sslcontext, waiter=waiter,
- server_hostname=server_hostname)
- self.addCleanup(close_transport, transport)
- return transport
-
- def _make_one(self, create_waiter=None):
- transport = self.ssl_transport()
- self.sock.reset_mock()
- self.sslsock.reset_mock()
- self.sslcontext.reset_mock()
- self.loop.reset_counters()
- return transport
-
- def test_on_handshake(self):
- waiter = asyncio.Future(loop=self.loop)
- tr = self.ssl_transport(waiter=waiter)
- self.assertTrue(self.sslsock.do_handshake.called)
- self.loop.assert_reader(1, tr._read_ready)
- test_utils.run_briefly(self.loop)
- self.assertIsNone(waiter.result())
-
- def test_on_handshake_reader_retry(self):
- self.loop.set_debug(False)
- self.sslsock.do_handshake.side_effect = ssl.SSLWantReadError
- transport = self.ssl_transport()
- self.loop.assert_reader(1, transport._on_handshake, None)
-
- def test_on_handshake_writer_retry(self):
- self.loop.set_debug(False)
- self.sslsock.do_handshake.side_effect = ssl.SSLWantWriteError
- transport = self.ssl_transport()
- self.loop.assert_writer(1, transport._on_handshake, None)
-
- def test_on_handshake_exc(self):
- exc = ValueError()
- self.sslsock.do_handshake.side_effect = exc
- with test_utils.disable_logger():
- waiter = asyncio.Future(loop=self.loop)
- self.ssl_transport(waiter=waiter)
- self.assertTrue(waiter.done())
- self.assertIs(exc, waiter.exception())
- self.assertTrue(self.sslsock.close.called)
-
- def test_on_handshake_base_exc(self):
- waiter = asyncio.Future(loop=self.loop)
- transport = self.ssl_transport(waiter=waiter)
- exc = BaseException()
- self.sslsock.do_handshake.side_effect = exc
- with test_utils.disable_logger():
- self.assertRaises(BaseException, transport._on_handshake, 0)
- self.assertTrue(self.sslsock.close.called)
- self.assertTrue(waiter.done())
- self.assertIs(exc, waiter.exception())
-
- def test_cancel_handshake(self):
- # Python issue #23197: cancelling a handshake must not raise an
- # exception or log an error, even if the handshake failed
- waiter = asyncio.Future(loop=self.loop)
- transport = self.ssl_transport(waiter=waiter)
- waiter.cancel()
- exc = ValueError()
- self.sslsock.do_handshake.side_effect = exc
- with test_utils.disable_logger():
- transport._on_handshake(0)
- transport.close()
- test_utils.run_briefly(self.loop)
-
- def test_pause_resume_reading(self):
- tr = self._make_one()
- self.assertFalse(tr._paused)
- self.loop.assert_reader(1, tr._read_ready)
- tr.pause_reading()
- self.assertTrue(tr._paused)
- self.assertFalse(1 in self.loop.readers)
- tr.resume_reading()
- self.assertFalse(tr._paused)
- self.loop.assert_reader(1, tr._read_ready)
- with self.assertRaises(RuntimeError):
- tr.resume_reading()
-
- def test_write(self):
- transport = self._make_one()
- transport.write(b'data')
- self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
- def test_write_bytearray(self):
- transport = self._make_one()
- data = bytearray(b'data')
- transport.write(data)
- self.assertEqual(list_to_buffer([b'data']), transport._buffer)
- self.assertEqual(data, bytearray(b'data')) # Hasn't been mutated.
- self.assertIsNot(data, transport._buffer) # Hasn't been incorporated.
-
- def test_write_memoryview(self):
- transport = self._make_one()
- data = memoryview(b'data')
- transport.write(data)
- self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
- def test_write_no_data(self):
- transport = self._make_one()
- transport._buffer.extend(b'data')
- transport.write(b'')
- self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
- def test_write_str(self):
- transport = self._make_one()
- self.assertRaises(TypeError, transport.write, 'str')
-
- def test_write_closing(self):
- transport = self._make_one()
- transport.close()
- self.assertEqual(transport._conn_lost, 1)
- transport.write(b'data')
- self.assertEqual(transport._conn_lost, 2)
-
- @mock.patch('asyncio.selector_events.logger')
- def test_write_exception(self, m_log):
- transport = self._make_one()
- transport._conn_lost = 1
- transport.write(b'data')
- self.assertEqual(transport._buffer, list_to_buffer())
- transport.write(b'data')
- transport.write(b'data')
- transport.write(b'data')
- transport.write(b'data')
- m_log.warning.assert_called_with('socket.send() raised exception.')
-
- def test_read_ready_recv(self):
- self.sslsock.recv.return_value = b'data'
- transport = self._make_one()
- transport._read_ready()
- self.assertTrue(self.sslsock.recv.called)
- self.assertEqual((b'data',), self.protocol.data_received.call_args[0])
-
- def test_read_ready_write_wants_read(self):
- self.loop._add_writer = mock.Mock()
- self.sslsock.recv.side_effect = BlockingIOError
- transport = self._make_one()
- transport._write_wants_read = True
- transport._write_ready = mock.Mock()
- transport._buffer.extend(b'data')
- transport._read_ready()
-
- self.assertFalse(transport._write_wants_read)
- transport._write_ready.assert_called_with()
- self.loop._add_writer.assert_called_with(
- transport._sock_fd, transport._write_ready)
-
- def test_read_ready_recv_eof(self):
- self.sslsock.recv.return_value = b''
- transport = self._make_one()
- transport.close = mock.Mock()
- transport._read_ready()
- transport.close.assert_called_with()
- self.protocol.eof_received.assert_called_with()
-
- def test_read_ready_recv_conn_reset(self):
- err = self.sslsock.recv.side_effect = ConnectionResetError()
- transport = self._make_one()
- transport._force_close = mock.Mock()
- with test_utils.disable_logger():
- transport._read_ready()
- transport._force_close.assert_called_with(err)
-
- def test_read_ready_recv_retry(self):
- self.sslsock.recv.side_effect = ssl.SSLWantReadError
- transport = self._make_one()
- transport._read_ready()
- self.assertTrue(self.sslsock.recv.called)
- self.assertFalse(self.protocol.data_received.called)
-
- self.sslsock.recv.side_effect = BlockingIOError
- transport._read_ready()
- self.assertFalse(self.protocol.data_received.called)
-
- self.sslsock.recv.side_effect = InterruptedError
- transport._read_ready()
- self.assertFalse(self.protocol.data_received.called)
-
- def test_read_ready_recv_write(self):
- self.loop._remove_reader = mock.Mock()
- self.loop._add_writer = mock.Mock()
- self.sslsock.recv.side_effect = ssl.SSLWantWriteError
- transport = self._make_one()
- transport._read_ready()
- self.assertFalse(self.protocol.data_received.called)
- self.assertTrue(transport._read_wants_write)
-
- self.loop._remove_reader.assert_called_with(transport._sock_fd)
- self.loop._add_writer.assert_called_with(
- transport._sock_fd, transport._write_ready)
-
- def test_read_ready_recv_exc(self):
- err = self.sslsock.recv.side_effect = OSError()
- transport = self._make_one()
- transport._fatal_error = mock.Mock()
- transport._read_ready()
- transport._fatal_error.assert_called_with(
- err,
- 'Fatal read error on SSL transport')
-
- def test_write_ready_send(self):
- self.sslsock.send.return_value = 4
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data'])
- transport._write_ready()
- self.assertEqual(list_to_buffer(), transport._buffer)
- self.assertTrue(self.sslsock.send.called)
-
- def test_write_ready_send_none(self):
- self.sslsock.send.return_value = 0
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data1', b'data2'])
- transport._write_ready()
- self.assertTrue(self.sslsock.send.called)
- self.assertEqual(list_to_buffer([b'data1data2']), transport._buffer)
-
- def test_write_ready_send_partial(self):
- self.sslsock.send.return_value = 2
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data1', b'data2'])
- transport._write_ready()
- self.assertTrue(self.sslsock.send.called)
- self.assertEqual(list_to_buffer([b'ta1data2']), transport._buffer)
-
- def test_write_ready_send_closing_partial(self):
- self.sslsock.send.return_value = 2
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data1', b'data2'])
- transport._write_ready()
- self.assertTrue(self.sslsock.send.called)
- self.assertFalse(self.sslsock.close.called)
-
- def test_write_ready_send_closing(self):
- self.sslsock.send.return_value = 4
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data'])
- transport.close()
- transport._write_ready()
- self.protocol.connection_lost.assert_called_with(None)
-
- def test_write_ready_send_closing_empty_buffer(self):
- self.sslsock.send.return_value = 4
- call_soon = self.loop.call_soon = mock.Mock()
- transport = self._make_one()
- transport._buffer = list_to_buffer()
- transport.close()
- transport._write_ready()
- call_soon.assert_called_with(transport._call_connection_lost, None)
-
- def test_write_ready_send_retry(self):
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data'])
-
- self.sslsock.send.side_effect = ssl.SSLWantWriteError
- transport._write_ready()
- self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
- self.sslsock.send.side_effect = BlockingIOError()
- transport._write_ready()
- self.assertEqual(list_to_buffer([b'data']), transport._buffer)
-
- def test_write_ready_send_read(self):
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data'])
-
- self.loop._remove_writer = mock.Mock()
- self.sslsock.send.side_effect = ssl.SSLWantReadError
- transport._write_ready()
- self.assertFalse(self.protocol.data_received.called)
- self.assertTrue(transport._write_wants_read)
- self.loop._remove_writer.assert_called_with(transport._sock_fd)
-
- def test_write_ready_send_exc(self):
- err = self.sslsock.send.side_effect = OSError()
-
- transport = self._make_one()
- transport._buffer = list_to_buffer([b'data'])
- transport._fatal_error = mock.Mock()
- transport._write_ready()
- transport._fatal_error.assert_called_with(
- err,
- 'Fatal write error on SSL transport')
- self.assertEqual(list_to_buffer(), transport._buffer)
-
- def test_write_ready_read_wants_write(self):
- self.loop._add_reader = mock.Mock()
- self.sslsock.send.side_effect = BlockingIOError
- transport = self._make_one()
- transport._read_wants_write = True
- transport._read_ready = mock.Mock()
- transport._write_ready()
-
- self.assertFalse(transport._read_wants_write)
- transport._read_ready.assert_called_with()
- self.loop._add_reader.assert_called_with(
- transport._sock_fd, transport._read_ready)
-
- def test_write_eof(self):
- tr = self._make_one()
- self.assertFalse(tr.can_write_eof())
- self.assertRaises(NotImplementedError, tr.write_eof)
-
- def check_close(self):
- tr = self._make_one()
- tr.close()
-
- self.assertTrue(tr.is_closing())
- self.assertEqual(1, self.loop.remove_reader_count[1])
- self.assertEqual(tr._conn_lost, 1)
-
- tr.close()
- self.assertEqual(tr._conn_lost, 1)
- self.assertEqual(1, self.loop.remove_reader_count[1])
-
- test_utils.run_briefly(self.loop)
-
- def test_close(self):
- self.check_close()
- self.assertTrue(self.protocol.connection_made.called)
- self.assertTrue(self.protocol.connection_lost.called)
-
- def test_close_not_connected(self):
- self.sslsock.do_handshake.side_effect = ssl.SSLWantReadError
- self.check_close()
- self.assertFalse(self.protocol.connection_made.called)
- self.assertFalse(self.protocol.connection_lost.called)
-
- @unittest.skipIf(ssl is None, 'No SSL support')
- def test_server_hostname(self):
- self.ssl_transport(server_hostname='localhost')
- self.sslcontext.wrap_socket.assert_called_with(
- self.sock, do_handshake_on_connect=False, server_side=False,
- server_hostname='localhost')
-
-
-class SelectorSslWithoutSslTransportTests(unittest.TestCase):
-
- @mock.patch('asyncio.selector_events.ssl', None)
- def test_ssl_transport_requires_ssl_module(self):
- Mock = mock.Mock
- with self.assertRaises(RuntimeError):
- _SelectorSslTransport(Mock(), Mock(), Mock(), Mock())
-
-
class SelectorDatagramTransportTests(test_utils.TestCase):
def setUp(self):
diff --git a/Misc/NEWS.d/next/Library/2017-11-18-17-09-01.bpo-32069.S0wyy4.rst b/Misc/NEWS.d/next/Library/2017-11-18-17-09-01.bpo-32069.S0wyy4.rst
new file mode 100644
index 0000000..2d69539
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-11-18-17-09-01.bpo-32069.S0wyy4.rst
@@ -0,0 +1 @@
+Drop legacy SSL transport from asyncio, ssl.MemoryBIO is always used anyway.