bpo-32069: Drop legacy SSL transport (#4451) · python/cpython@51d546a (original) (raw)
`@@ -74,28 +74,12 @@ def _make_socket_transport(self, sock, protocol, waiter=None, *,
`
74
74
`def _make_ssl_transport(self, rawsock, protocol, sslcontext, waiter=None,
`
75
75
`*, server_side=False, server_hostname=None,
`
76
76
`extra=None, server=None):
`
77
``
`-
if not sslproto._is_sslproto_available():
`
78
``
`-
return self._make_legacy_ssl_transport(
`
79
``
`-
rawsock, protocol, sslcontext, waiter,
`
80
``
`-
server_side=server_side, server_hostname=server_hostname,
`
81
``
`-
extra=extra, server=server)
`
82
``
-
83
77
`ssl_protocol = sslproto.SSLProtocol(self, protocol, sslcontext, waiter,
`
84
78
`server_side, server_hostname)
`
85
79
`_SelectorSocketTransport(self, rawsock, ssl_protocol,
`
86
80
`extra=extra, server=server)
`
87
81
`return ssl_protocol._app_transport
`
88
82
``
89
``
`-
def _make_legacy_ssl_transport(self, rawsock, protocol, sslcontext,
`
90
``
`-
waiter, *,
`
91
``
`-
server_side=False, server_hostname=None,
`
92
``
`-
extra=None, server=None):
`
93
``
`-
Use the legacy API: SSL_write, SSL_read, etc. The legacy API is used
`
94
``
`-
on Python 3.4 and older, when ssl.MemoryBIO is not available.
`
95
``
`-
return _SelectorSslTransport(
`
96
``
`-
self, rawsock, protocol, sslcontext, waiter,
`
97
``
`-
server_side, server_hostname, extra, server)
`
98
``
-
99
83
`def _make_datagram_transport(self, sock, protocol,
`
100
84
`address=None, waiter=None, extra=None):
`
101
85
`return _SelectorDatagramTransport(self, sock, protocol,
`
`@@ -848,238 +832,6 @@ def can_write_eof(self):
`
848
832
`return True
`
849
833
``
850
834
``
851
``
`-
class _SelectorSslTransport(_SelectorTransport):
`
852
``
-
853
``
`-
_buffer_factory = bytearray
`
854
``
-
855
``
`-
def init(self, loop, rawsock, protocol, sslcontext, waiter=None,
`
856
``
`-
server_side=False, server_hostname=None,
`
857
``
`-
extra=None, server=None):
`
858
``
`-
if ssl is None:
`
859
``
`-
raise RuntimeError('stdlib ssl module not available')
`
860
``
-
861
``
`-
if not sslcontext:
`
862
``
`-
sslcontext = sslproto._create_transport_context(server_side, server_hostname)
`
863
``
-
864
``
`-
wrap_kwargs = {
`
865
``
`-
'server_side': server_side,
`
866
``
`-
'do_handshake_on_connect': False,
`
867
``
`-
}
`
868
``
`-
if server_hostname and not server_side:
`
869
``
`-
wrap_kwargs['server_hostname'] = server_hostname
`
870
``
`-
sslsock = sslcontext.wrap_socket(rawsock, **wrap_kwargs)
`
871
``
-
872
``
`-
super().init(loop, sslsock, protocol, extra, server)
`
873
``
`-
the protocol connection is only made after the SSL handshake
`
874
``
`-
self._protocol_connected = False
`
875
``
-
876
``
`-
self._server_hostname = server_hostname
`
877
``
`-
self._waiter = waiter
`
878
``
`-
self._sslcontext = sslcontext
`
879
``
`-
self._paused = False
`
880
``
-
881
``
`-
SSL-specific extra info. (peercert is set later)
`
882
``
`-
self._extra.update(sslcontext=sslcontext)
`
883
``
-
884
``
`-
if self._loop.get_debug():
`
885
``
`-
logger.debug("%r starts SSL handshake", self)
`
886
``
`-
start_time = self._loop.time()
`
887
``
`-
else:
`
888
``
`-
start_time = None
`
889
``
`-
self._on_handshake(start_time)
`
890
``
-
891
``
`-
def _wakeup_waiter(self, exc=None):
`
892
``
`-
if self._waiter is None:
`
893
``
`-
return
`
894
``
`-
if not self._waiter.cancelled():
`
895
``
`-
if exc is not None:
`
896
``
`-
self._waiter.set_exception(exc)
`
897
``
`-
else:
`
898
``
`-
self._waiter.set_result(None)
`
899
``
`-
self._waiter = None
`
900
``
-
901
``
`-
def _on_handshake(self, start_time):
`
902
``
`-
try:
`
903
``
`-
self._sock.do_handshake()
`
904
``
`-
except ssl.SSLWantReadError:
`
905
``
`-
self._loop._add_reader(self._sock_fd,
`
906
``
`-
self._on_handshake, start_time)
`
907
``
`-
return
`
908
``
`-
except ssl.SSLWantWriteError:
`
909
``
`-
self._loop._add_writer(self._sock_fd,
`
910
``
`-
self._on_handshake, start_time)
`
911
``
`-
return
`
912
``
`-
except BaseException as exc:
`
913
``
`-
if self._loop.get_debug():
`
914
``
`-
logger.warning("%r: SSL handshake failed",
`
915
``
`-
self, exc_info=True)
`
916
``
`-
self._loop._remove_reader(self._sock_fd)
`
917
``
`-
self._loop._remove_writer(self._sock_fd)
`
918
``
`-
self._sock.close()
`
919
``
`-
self._wakeup_waiter(exc)
`
920
``
`-
if isinstance(exc, Exception):
`
921
``
`-
return
`
922
``
`-
else:
`
923
``
`-
raise
`
924
``
-
925
``
`-
self._loop._remove_reader(self._sock_fd)
`
926
``
`-
self._loop._remove_writer(self._sock_fd)
`
927
``
-
928
``
`-
peercert = self._sock.getpeercert()
`
929
``
`-
if not hasattr(self._sslcontext, 'check_hostname'):
`
930
``
`-
Verify hostname if requested, Python 3.4+ uses check_hostname
`
931
``
`-
and checks the hostname in do_handshake()
`
932
``
`-
if (self._server_hostname and
`
933
``
`-
self._sslcontext.verify_mode != ssl.CERT_NONE):
`
934
``
`-
try:
`
935
``
`-
ssl.match_hostname(peercert, self._server_hostname)
`
936
``
`-
except Exception as exc:
`
937
``
`-
if self._loop.get_debug():
`
938
``
`-
logger.warning("%r: SSL handshake failed "
`
939
``
`-
"on matching the hostname",
`
940
``
`-
self, exc_info=True)
`
941
``
`-
self._sock.close()
`
942
``
`-
self._wakeup_waiter(exc)
`
943
``
`-
return
`
944
``
-
945
``
`-
Add extra info that becomes available after handshake.
`
946
``
`-
self._extra.update(peercert=peercert,
`
947
``
`-
cipher=self._sock.cipher(),
`
948
``
`-
compression=self._sock.compression(),
`
949
``
`-
ssl_object=self._sock,
`
950
``
`-
)
`
951
``
-
952
``
`-
self._read_wants_write = False
`
953
``
`-
self._write_wants_read = False
`
954
``
`-
self._loop._add_reader(self._sock_fd, self._read_ready)
`
955
``
`-
self._protocol_connected = True
`
956
``
`-
self._loop.call_soon(self._protocol.connection_made, self)
`
957
``
`-
only wake up the waiter when connection_made() has been called
`
958
``
`-
self._loop.call_soon(self._wakeup_waiter)
`
959
``
-
960
``
`-
if self._loop.get_debug():
`
961
``
`-
dt = self._loop.time() - start_time
`
962
``
`-
logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
`
963
``
-
964
``
`-
def pause_reading(self):
`
965
``
`-
XXX This is a bit icky, given the comment at the top of
`
966
``
`-
_read_ready(). Is it possible to evoke a deadlock? I don't
`
967
``
`-
know, although it doesn't look like it; write() will still
`
968
``
`-
accept more data for the buffer and eventually the app will
`
969
``
`-
call resume_reading() again, and things will flow again.
`
970
``
-
971
``
`-
if self._closing:
`
972
``
`-
raise RuntimeError('Cannot pause_reading() when closing')
`
973
``
`-
if self._paused:
`
974
``
`-
raise RuntimeError('Already paused')
`
975
``
`-
self._paused = True
`
976
``
`-
self._loop._remove_reader(self._sock_fd)
`
977
``
`-
if self._loop.get_debug():
`
978
``
`-
logger.debug("%r pauses reading", self)
`
979
``
-
980
``
`-
def resume_reading(self):
`
981
``
`-
if not self._paused:
`
982
``
`-
raise RuntimeError('Not paused')
`
983
``
`-
self._paused = False
`
984
``
`-
if self._closing:
`
985
``
`-
return
`
986
``
`-
self._loop._add_reader(self._sock_fd, self._read_ready)
`
987
``
`-
if self._loop.get_debug():
`
988
``
`-
logger.debug("%r resumes reading", self)
`
989
``
-
990
``
`-
def _read_ready(self):
`
991
``
`-
if self._conn_lost:
`
992
``
`-
return
`
993
``
`-
if self._write_wants_read:
`
994
``
`-
self._write_wants_read = False
`
995
``
`-
self._write_ready()
`
996
``
-
997
``
`-
if self._buffer:
`
998
``
`-
self._loop._add_writer(self._sock_fd, self._write_ready)
`
999
``
-
1000
``
`-
try:
`
1001
``
`-
data = self._sock.recv(self.max_size)
`
1002
``
`-
except (BlockingIOError, InterruptedError, ssl.SSLWantReadError):
`
1003
``
`-
pass
`
1004
``
`-
except ssl.SSLWantWriteError:
`
1005
``
`-
self._read_wants_write = True
`
1006
``
`-
self._loop._remove_reader(self._sock_fd)
`
1007
``
`-
self._loop._add_writer(self._sock_fd, self._write_ready)
`
1008
``
`-
except Exception as exc:
`
1009
``
`-
self._fatal_error(exc, 'Fatal read error on SSL transport')
`
1010
``
`-
else:
`
1011
``
`-
if data:
`
1012
``
`-
self._protocol.data_received(data)
`
1013
``
`-
else:
`
1014
``
`-
try:
`
1015
``
`-
if self._loop.get_debug():
`
1016
``
`-
logger.debug("%r received EOF", self)
`
1017
``
`-
keep_open = self._protocol.eof_received()
`
1018
``
`-
if keep_open:
`
1019
``
`-
logger.warning('returning true from eof_received() '
`
1020
``
`-
'has no effect when using ssl')
`
1021
``
`-
finally:
`
1022
``
`-
self.close()
`
1023
``
-
1024
``
`-
def _write_ready(self):
`
1025
``
`-
if self._conn_lost:
`
1026
``
`-
return
`
1027
``
`-
if self._read_wants_write:
`
1028
``
`-
self._read_wants_write = False
`
1029
``
`-
self._read_ready()
`
1030
``
-
1031
``
`-
if not (self._paused or self._closing):
`
1032
``
`-
self._loop._add_reader(self._sock_fd, self._read_ready)
`
1033
``
-
1034
``
`-
if self._buffer:
`
1035
``
`-
try:
`
1036
``
`-
n = self._sock.send(self._buffer)
`
1037
``
`-
except (BlockingIOError, InterruptedError, ssl.SSLWantWriteError):
`
1038
``
`-
n = 0
`
1039
``
`-
except ssl.SSLWantReadError:
`
1040
``
`-
n = 0
`
1041
``
`-
self._loop._remove_writer(self._sock_fd)
`
1042
``
`-
self._write_wants_read = True
`
1043
``
`-
except Exception as exc:
`
1044
``
`-
self._loop._remove_writer(self._sock_fd)
`
1045
``
`-
self._buffer.clear()
`
1046
``
`-
self._fatal_error(exc, 'Fatal write error on SSL transport')
`
1047
``
`-
return
`
1048
``
-
1049
``
`-
if n:
`
1050
``
`-
del self._buffer[:n]
`
1051
``
-
1052
``
`-
self._maybe_resume_protocol() # May append to buffer.
`
1053
``
-
1054
``
`-
if not self._buffer:
`
1055
``
`-
self._loop._remove_writer(self._sock_fd)
`
1056
``
`-
if self._closing:
`
1057
``
`-
self._call_connection_lost(None)
`
1058
``
-
1059
``
`-
def write(self, data):
`
1060
``
`-
if not isinstance(data, (bytes, bytearray, memoryview)):
`
1061
``
`-
raise TypeError('data argument must be a bytes-like object, '
`
1062
``
`-
'not %r' % type(data).name)
`
1063
``
`-
if not data:
`
1064
``
`-
return
`
1065
``
-
1066
``
`-
if self._conn_lost:
`
1067
``
`-
if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:
`
1068
``
`-
logger.warning('socket.send() raised exception.')
`
1069
``
`-
self._conn_lost += 1
`
1070
``
`-
return
`
1071
``
-
1072
``
`-
if not self._buffer:
`
1073
``
`-
self._loop._add_writer(self._sock_fd, self._write_ready)
`
1074
``
-
1075
``
`-
Add it to the buffer.
`
1076
``
`-
self._buffer.extend(data)
`
1077
``
`-
self._maybe_pause_protocol()
`
1078
``
-
1079
``
`-
def can_write_eof(self):
`
1080
``
`-
return False
`
1081
``
-
1082
``
-
1083
835
`class _SelectorDatagramTransport(_SelectorTransport):
`
1084
836
``
1085
837
`_buffer_factory = collections.deque
`