diff options
Diffstat (limited to 'Lib/asyncio/sslproto.py')
-rw-r--r-- | Lib/asyncio/sslproto.py | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 2bbf134..2bfa45d 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -441,6 +441,8 @@ class SSLProtocol(protocols.Protocol): self._waiter = waiter self._loop = loop self._app_protocol = app_protocol + self._app_protocol_is_buffer = \ + isinstance(app_protocol, protocols.BufferedProtocol) self._app_transport = _SSLProtocolTransport(self._loop, self) # _SSLPipe instance (None until the connection is made) self._sslpipe = None @@ -522,7 +524,16 @@ class SSLProtocol(protocols.Protocol): for chunk in appdata: if chunk: - self._app_protocol.data_received(chunk) + try: + if self._app_protocol_is_buffer: + _feed_data_to_bufferred_proto( + self._app_protocol, chunk) + else: + self._app_protocol.data_received(chunk) + except Exception as ex: + self._fatal_error( + ex, 'application protocol failed to receive SSL data') + return else: self._start_shutdown() break @@ -709,3 +720,22 @@ class SSLProtocol(protocols.Protocol): self._transport.abort() finally: self._finalize() + + +def _feed_data_to_bufferred_proto(proto, data): + data_len = len(data) + while data_len: + buf = proto.get_buffer(data_len) + buf_len = len(buf) + if not buf_len: + raise RuntimeError('get_buffer() returned an empty buffer') + + if buf_len >= data_len: + buf[:data_len] = data + proto.buffer_updated(data_len) + return + else: + buf[:buf_len] = data[:buf_len] + proto.buffer_updated(buf_len) + data = data[buf_len:] + data_len = len(data) |