ยปCore Development>Code coverage>Lib/asyncio/sslproto.py

Python code coverage for Lib/asyncio/sslproto.py

#countcontent
1n/aimport collections
2n/aimport warnings
3n/atry:
4n/a import ssl
5n/aexcept ImportError: # pragma: no cover
6n/a ssl = None
7n/a
8n/afrom . import base_events
9n/afrom . import compat
10n/afrom . import protocols
11n/afrom . import transports
12n/afrom .log import logger
13n/a
14n/a
15n/adef _create_transport_context(server_side, server_hostname):
16n/a if server_side:
17n/a raise ValueError('Server side SSL needs a valid SSLContext')
18n/a
19n/a # Client side may pass ssl=True to use a default
20n/a # context; in that case the sslcontext passed is None.
21n/a # The default is secure for client connections.
22n/a if hasattr(ssl, 'create_default_context'):
23n/a # Python 3.4+: use up-to-date strong settings.
24n/a sslcontext = ssl.create_default_context()
25n/a if not server_hostname:
26n/a sslcontext.check_hostname = False
27n/a else:
28n/a # Fallback for Python 3.3.
29n/a sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
30n/a sslcontext.options |= ssl.OP_NO_SSLv2
31n/a sslcontext.options |= ssl.OP_NO_SSLv3
32n/a sslcontext.set_default_verify_paths()
33n/a sslcontext.verify_mode = ssl.CERT_REQUIRED
34n/a return sslcontext
35n/a
36n/a
37n/adef _is_sslproto_available():
38n/a return hasattr(ssl, "MemoryBIO")
39n/a
40n/a
41n/a# States of an _SSLPipe.
42n/a_UNWRAPPED = "UNWRAPPED"
43n/a_DO_HANDSHAKE = "DO_HANDSHAKE"
44n/a_WRAPPED = "WRAPPED"
45n/a_SHUTDOWN = "SHUTDOWN"
46n/a
47n/a
48n/aclass _SSLPipe(object):
49n/a """An SSL "Pipe".
50n/a
51n/a An SSL pipe allows you to communicate with an SSL/TLS protocol instance
52n/a through memory buffers. It can be used to implement a security layer for an
53n/a existing connection where you don't have access to the connection's file
54n/a descriptor, or for some reason you don't want to use it.
55n/a
56n/a An SSL pipe can be in "wrapped" and "unwrapped" mode. In unwrapped mode,
57n/a data is passed through untransformed. In wrapped mode, application level
58n/a data is encrypted to SSL record level data and vice versa. The SSL record
59n/a level is the lowest level in the SSL protocol suite and is what travels
60n/a as-is over the wire.
61n/a
62n/a An SslPipe initially is in "unwrapped" mode. To start SSL, call
63n/a do_handshake(). To shutdown SSL again, call unwrap().
64n/a """
65n/a
66n/a max_size = 256 * 1024 # Buffer size passed to read()
67n/a
68n/a def __init__(self, context, server_side, server_hostname=None):
69n/a """
70n/a The *context* argument specifies the ssl.SSLContext to use.
71n/a
72n/a The *server_side* argument indicates whether this is a server side or
73n/a client side transport.
74n/a
75n/a The optional *server_hostname* argument can be used to specify the
76n/a hostname you are connecting to. You may only specify this parameter if
77n/a the _ssl module supports Server Name Indication (SNI).
78n/a """
79n/a self._context = context
80n/a self._server_side = server_side
81n/a self._server_hostname = server_hostname
82n/a self._state = _UNWRAPPED
83n/a self._incoming = ssl.MemoryBIO()
84n/a self._outgoing = ssl.MemoryBIO()
85n/a self._sslobj = None
86n/a self._need_ssldata = False
87n/a self._handshake_cb = None
88n/a self._shutdown_cb = None
89n/a
90n/a @property
91n/a def context(self):
92n/a """The SSL context passed to the constructor."""
93n/a return self._context
94n/a
95n/a @property
96n/a def ssl_object(self):
97n/a """The internal ssl.SSLObject instance.
98n/a
99n/a Return None if the pipe is not wrapped.
100n/a """
101n/a return self._sslobj
102n/a
103n/a @property
104n/a def need_ssldata(self):
105n/a """Whether more record level data is needed to complete a handshake
106n/a that is currently in progress."""
107n/a return self._need_ssldata
108n/a
109n/a @property
110n/a def wrapped(self):
111n/a """
112n/a Whether a security layer is currently in effect.
113n/a
114n/a Return False during handshake.
115n/a """
116n/a return self._state == _WRAPPED
117n/a
118n/a def do_handshake(self, callback=None):
119n/a """Start the SSL handshake.
120n/a
121n/a Return a list of ssldata. A ssldata element is a list of buffers
122n/a
123n/a The optional *callback* argument can be used to install a callback that
124n/a will be called when the handshake is complete. The callback will be
125n/a called with None if successful, else an exception instance.
126n/a """
127n/a if self._state != _UNWRAPPED:
128n/a raise RuntimeError('handshake in progress or completed')
129n/a self._sslobj = self._context.wrap_bio(
130n/a self._incoming, self._outgoing,
131n/a server_side=self._server_side,
132n/a server_hostname=self._server_hostname)
133n/a self._state = _DO_HANDSHAKE
134n/a self._handshake_cb = callback
135n/a ssldata, appdata = self.feed_ssldata(b'', only_handshake=True)
136n/a assert len(appdata) == 0
137n/a return ssldata
138n/a
139n/a def shutdown(self, callback=None):
140n/a """Start the SSL shutdown sequence.
141n/a
142n/a Return a list of ssldata. A ssldata element is a list of buffers
143n/a
144n/a The optional *callback* argument can be used to install a callback that
145n/a will be called when the shutdown is complete. The callback will be
146n/a called without arguments.
147n/a """
148n/a if self._state == _UNWRAPPED:
149n/a raise RuntimeError('no security layer present')
150n/a if self._state == _SHUTDOWN:
151n/a raise RuntimeError('shutdown in progress')
152n/a assert self._state in (_WRAPPED, _DO_HANDSHAKE)
153n/a self._state = _SHUTDOWN
154n/a self._shutdown_cb = callback
155n/a ssldata, appdata = self.feed_ssldata(b'')
156n/a assert appdata == [] or appdata == [b'']
157n/a return ssldata
158n/a
159n/a def feed_eof(self):
160n/a """Send a potentially "ragged" EOF.
161n/a
162n/a This method will raise an SSL_ERROR_EOF exception if the EOF is
163n/a unexpected.
164n/a """
165n/a self._incoming.write_eof()
166n/a ssldata, appdata = self.feed_ssldata(b'')
167n/a assert appdata == [] or appdata == [b'']
168n/a
169n/a def feed_ssldata(self, data, only_handshake=False):
170n/a """Feed SSL record level data into the pipe.
171n/a
172n/a The data must be a bytes instance. It is OK to send an empty bytes
173n/a instance. This can be used to get ssldata for a handshake initiated by
174n/a this endpoint.
175n/a
176n/a Return a (ssldata, appdata) tuple. The ssldata element is a list of
177n/a buffers containing SSL data that needs to be sent to the remote SSL.
178n/a
179n/a The appdata element is a list of buffers containing plaintext data that
180n/a needs to be forwarded to the application. The appdata list may contain
181n/a an empty buffer indicating an SSL "close_notify" alert. This alert must
182n/a be acknowledged by calling shutdown().
183n/a """
184n/a if self._state == _UNWRAPPED:
185n/a # If unwrapped, pass plaintext data straight through.
186n/a if data:
187n/a appdata = [data]
188n/a else:
189n/a appdata = []
190n/a return ([], appdata)
191n/a
192n/a self._need_ssldata = False
193n/a if data:
194n/a self._incoming.write(data)
195n/a
196n/a ssldata = []
197n/a appdata = []
198n/a try:
199n/a if self._state == _DO_HANDSHAKE:
200n/a # Call do_handshake() until it doesn't raise anymore.
201n/a self._sslobj.do_handshake()
202n/a self._state = _WRAPPED
203n/a if self._handshake_cb:
204n/a self._handshake_cb(None)
205n/a if only_handshake:
206n/a return (ssldata, appdata)
207n/a # Handshake done: execute the wrapped block
208n/a
209n/a if self._state == _WRAPPED:
210n/a # Main state: read data from SSL until close_notify
211n/a while True:
212n/a chunk = self._sslobj.read(self.max_size)
213n/a appdata.append(chunk)
214n/a if not chunk: # close_notify
215n/a break
216n/a
217n/a elif self._state == _SHUTDOWN:
218n/a # Call shutdown() until it doesn't raise anymore.
219n/a self._sslobj.unwrap()
220n/a self._sslobj = None
221n/a self._state = _UNWRAPPED
222n/a if self._shutdown_cb:
223n/a self._shutdown_cb()
224n/a
225n/a elif self._state == _UNWRAPPED:
226n/a # Drain possible plaintext data after close_notify.
227n/a appdata.append(self._incoming.read())
228n/a except (ssl.SSLError, ssl.CertificateError) as exc:
229n/a if getattr(exc, 'errno', None) not in (
230n/a ssl.SSL_ERROR_WANT_READ, ssl.SSL_ERROR_WANT_WRITE,
231n/a ssl.SSL_ERROR_SYSCALL):
232n/a if self._state == _DO_HANDSHAKE and self._handshake_cb:
233n/a self._handshake_cb(exc)
234n/a raise
235n/a self._need_ssldata = (exc.errno == ssl.SSL_ERROR_WANT_READ)
236n/a
237n/a # Check for record level data that needs to be sent back.
238n/a # Happens for the initial handshake and renegotiations.
239n/a if self._outgoing.pending:
240n/a ssldata.append(self._outgoing.read())
241n/a return (ssldata, appdata)
242n/a
243n/a def feed_appdata(self, data, offset=0):
244n/a """Feed plaintext data into the pipe.
245n/a
246n/a Return an (ssldata, offset) tuple. The ssldata element is a list of
247n/a buffers containing record level data that needs to be sent to the
248n/a remote SSL instance. The offset is the number of plaintext bytes that
249n/a were processed, which may be less than the length of data.
250n/a
251n/a NOTE: In case of short writes, this call MUST be retried with the SAME
252n/a buffer passed into the *data* argument (i.e. the id() must be the
253n/a same). This is an OpenSSL requirement. A further particularity is that
254n/a a short write will always have offset == 0, because the _ssl module
255n/a does not enable partial writes. And even though the offset is zero,
256n/a there will still be encrypted data in ssldata.
257n/a """
258n/a assert 0 <= offset <= len(data)
259n/a if self._state == _UNWRAPPED:
260n/a # pass through data in unwrapped mode
261n/a if offset < len(data):
262n/a ssldata = [data[offset:]]
263n/a else:
264n/a ssldata = []
265n/a return (ssldata, len(data))
266n/a
267n/a ssldata = []
268n/a view = memoryview(data)
269n/a while True:
270n/a self._need_ssldata = False
271n/a try:
272n/a if offset < len(view):
273n/a offset += self._sslobj.write(view[offset:])
274n/a except ssl.SSLError as exc:
275n/a # It is not allowed to call write() after unwrap() until the
276n/a # close_notify is acknowledged. We return the condition to the
277n/a # caller as a short write.
278n/a if exc.reason == 'PROTOCOL_IS_SHUTDOWN':
279n/a exc.errno = ssl.SSL_ERROR_WANT_READ
280n/a if exc.errno not in (ssl.SSL_ERROR_WANT_READ,
281n/a ssl.SSL_ERROR_WANT_WRITE,
282n/a ssl.SSL_ERROR_SYSCALL):
283n/a raise
284n/a self._need_ssldata = (exc.errno == ssl.SSL_ERROR_WANT_READ)
285n/a
286n/a # See if there's any record level data back for us.
287n/a if self._outgoing.pending:
288n/a ssldata.append(self._outgoing.read())
289n/a if offset == len(view) or self._need_ssldata:
290n/a break
291n/a return (ssldata, offset)
292n/a
293n/a
294n/aclass _SSLProtocolTransport(transports._FlowControlMixin,
295n/a transports.Transport):
296n/a
297n/a def __init__(self, loop, ssl_protocol, app_protocol):
298n/a self._loop = loop
299n/a # SSLProtocol instance
300n/a self._ssl_protocol = ssl_protocol
301n/a self._app_protocol = app_protocol
302n/a self._closed = False
303n/a
304n/a def get_extra_info(self, name, default=None):
305n/a """Get optional transport information."""
306n/a return self._ssl_protocol._get_extra_info(name, default)
307n/a
308n/a def set_protocol(self, protocol):
309n/a self._app_protocol = protocol
310n/a
311n/a def get_protocol(self):
312n/a return self._app_protocol
313n/a
314n/a def is_closing(self):
315n/a return self._closed
316n/a
317n/a def close(self):
318n/a """Close the transport.
319n/a
320n/a Buffered data will be flushed asynchronously. No more data
321n/a will be received. After all buffered data is flushed, the
322n/a protocol's connection_lost() method will (eventually) called
323n/a with None as its argument.
324n/a """
325n/a self._closed = True
326n/a self._ssl_protocol._start_shutdown()
327n/a
328n/a # On Python 3.3 and older, objects with a destructor part of a reference
329n/a # cycle are never destroyed. It's not more the case on Python 3.4 thanks
330n/a # to the PEP 442.
331n/a if compat.PY34:
332n/a def __del__(self):
333n/a if not self._closed:
334n/a warnings.warn("unclosed transport %r" % self, ResourceWarning,
335n/a source=self)
336n/a self.close()
337n/a
338n/a def pause_reading(self):
339n/a """Pause the receiving end.
340n/a
341n/a No data will be passed to the protocol's data_received()
342n/a method until resume_reading() is called.
343n/a """
344n/a self._ssl_protocol._transport.pause_reading()
345n/a
346n/a def resume_reading(self):
347n/a """Resume the receiving end.
348n/a
349n/a Data received will once again be passed to the protocol's
350n/a data_received() method.
351n/a """
352n/a self._ssl_protocol._transport.resume_reading()
353n/a
354n/a def set_write_buffer_limits(self, high=None, low=None):
355n/a """Set the high- and low-water limits for write flow control.
356n/a
357n/a These two values control when to call the protocol's
358n/a pause_writing() and resume_writing() methods. If specified,
359n/a the low-water limit must be less than or equal to the
360n/a high-water limit. Neither value can be negative.
361n/a
362n/a The defaults are implementation-specific. If only the
363n/a high-water limit is given, the low-water limit defaults to an
364n/a implementation-specific value less than or equal to the
365n/a high-water limit. Setting high to zero forces low to zero as
366n/a well, and causes pause_writing() to be called whenever the
367n/a buffer becomes non-empty. Setting low to zero causes
368n/a resume_writing() to be called only once the buffer is empty.
369n/a Use of zero for either limit is generally sub-optimal as it
370n/a reduces opportunities for doing I/O and computation
371n/a concurrently.
372n/a """
373n/a self._ssl_protocol._transport.set_write_buffer_limits(high, low)
374n/a
375n/a def get_write_buffer_size(self):
376n/a """Return the current size of the write buffer."""
377n/a return self._ssl_protocol._transport.get_write_buffer_size()
378n/a
379n/a def write(self, data):
380n/a """Write some data bytes to the transport.
381n/a
382n/a This does not block; it buffers the data and arranges for it
383n/a to be sent out asynchronously.
384n/a """
385n/a if not isinstance(data, (bytes, bytearray, memoryview)):
386n/a raise TypeError("data: expecting a bytes-like instance, got {!r}"
387n/a .format(type(data).__name__))
388n/a if not data:
389n/a return
390n/a self._ssl_protocol._write_appdata(data)
391n/a
392n/a def can_write_eof(self):
393n/a """Return True if this transport supports write_eof(), False if not."""
394n/a return False
395n/a
396n/a def abort(self):
397n/a """Close the transport immediately.
398n/a
399n/a Buffered data will be lost. No more data will be received.
400n/a The protocol's connection_lost() method will (eventually) be
401n/a called with None as its argument.
402n/a """
403n/a self._ssl_protocol._abort()
404n/a
405n/a
406n/aclass SSLProtocol(protocols.Protocol):
407n/a """SSL protocol.
408n/a
409n/a Implementation of SSL on top of a socket using incoming and outgoing
410n/a buffers which are ssl.MemoryBIO objects.
411n/a """
412n/a
413n/a def __init__(self, loop, app_protocol, sslcontext, waiter,
414n/a server_side=False, server_hostname=None,
415n/a call_connection_made=True):
416n/a if ssl is None:
417n/a raise RuntimeError('stdlib ssl module not available')
418n/a
419n/a if not sslcontext:
420n/a sslcontext = _create_transport_context(server_side, server_hostname)
421n/a
422n/a self._server_side = server_side
423n/a if server_hostname and not server_side:
424n/a self._server_hostname = server_hostname
425n/a else:
426n/a self._server_hostname = None
427n/a self._sslcontext = sslcontext
428n/a # SSL-specific extra info. More info are set when the handshake
429n/a # completes.
430n/a self._extra = dict(sslcontext=sslcontext)
431n/a
432n/a # App data write buffering
433n/a self._write_backlog = collections.deque()
434n/a self._write_buffer_size = 0
435n/a
436n/a self._waiter = waiter
437n/a self._loop = loop
438n/a self._app_protocol = app_protocol
439n/a self._app_transport = _SSLProtocolTransport(self._loop,
440n/a self, self._app_protocol)
441n/a # _SSLPipe instance (None until the connection is made)
442n/a self._sslpipe = None
443n/a self._session_established = False
444n/a self._in_handshake = False
445n/a self._in_shutdown = False
446n/a # transport, ex: SelectorSocketTransport
447n/a self._transport = None
448n/a self._call_connection_made = call_connection_made
449n/a
450n/a def _wakeup_waiter(self, exc=None):
451n/a if self._waiter is None:
452n/a return
453n/a if not self._waiter.cancelled():
454n/a if exc is not None:
455n/a self._waiter.set_exception(exc)
456n/a else:
457n/a self._waiter.set_result(None)
458n/a self._waiter = None
459n/a
460n/a def connection_made(self, transport):
461n/a """Called when the low-level connection is made.
462n/a
463n/a Start the SSL handshake.
464n/a """
465n/a self._transport = transport
466n/a self._sslpipe = _SSLPipe(self._sslcontext,
467n/a self._server_side,
468n/a self._server_hostname)
469n/a self._start_handshake()
470n/a
471n/a def connection_lost(self, exc):
472n/a """Called when the low-level connection is lost or closed.
473n/a
474n/a The argument is an exception object or None (the latter
475n/a meaning a regular EOF is received or the connection was
476n/a aborted or closed).
477n/a """
478n/a if self._session_established:
479n/a self._session_established = False
480n/a self._loop.call_soon(self._app_protocol.connection_lost, exc)
481n/a self._transport = None
482n/a self._app_transport = None
483n/a self._wakeup_waiter(exc)
484n/a
485n/a def pause_writing(self):
486n/a """Called when the low-level transport's buffer goes over
487n/a the high-water mark.
488n/a """
489n/a self._app_protocol.pause_writing()
490n/a
491n/a def resume_writing(self):
492n/a """Called when the low-level transport's buffer drains below
493n/a the low-water mark.
494n/a """
495n/a self._app_protocol.resume_writing()
496n/a
497n/a def data_received(self, data):
498n/a """Called when some SSL data is received.
499n/a
500n/a The argument is a bytes object.
501n/a """
502n/a try:
503n/a ssldata, appdata = self._sslpipe.feed_ssldata(data)
504n/a except ssl.SSLError as e:
505n/a if self._loop.get_debug():
506n/a logger.warning('%r: SSL error %s (reason %s)',
507n/a self, e.errno, e.reason)
508n/a self._abort()
509n/a return
510n/a
511n/a for chunk in ssldata:
512n/a self._transport.write(chunk)
513n/a
514n/a for chunk in appdata:
515n/a if chunk:
516n/a self._app_protocol.data_received(chunk)
517n/a else:
518n/a self._start_shutdown()
519n/a break
520n/a
521n/a def eof_received(self):
522n/a """Called when the other end of the low-level stream
523n/a is half-closed.
524n/a
525n/a If this returns a false value (including None), the transport
526n/a will close itself. If it returns a true value, closing the
527n/a transport is up to the protocol.
528n/a """
529n/a try:
530n/a if self._loop.get_debug():
531n/a logger.debug("%r received EOF", self)
532n/a
533n/a self._wakeup_waiter(ConnectionResetError)
534n/a
535n/a if not self._in_handshake:
536n/a keep_open = self._app_protocol.eof_received()
537n/a if keep_open:
538n/a logger.warning('returning true from eof_received() '
539n/a 'has no effect when using ssl')
540n/a finally:
541n/a self._transport.close()
542n/a
543n/a def _get_extra_info(self, name, default=None):
544n/a if name in self._extra:
545n/a return self._extra[name]
546n/a else:
547n/a return self._transport.get_extra_info(name, default)
548n/a
549n/a def _start_shutdown(self):
550n/a if self._in_shutdown:
551n/a return
552n/a self._in_shutdown = True
553n/a self._write_appdata(b'')
554n/a
555n/a def _write_appdata(self, data):
556n/a self._write_backlog.append((data, 0))
557n/a self._write_buffer_size += len(data)
558n/a self._process_write_backlog()
559n/a
560n/a def _start_handshake(self):
561n/a if self._loop.get_debug():
562n/a logger.debug("%r starts SSL handshake", self)
563n/a self._handshake_start_time = self._loop.time()
564n/a else:
565n/a self._handshake_start_time = None
566n/a self._in_handshake = True
567n/a # (b'', 1) is a special value in _process_write_backlog() to do
568n/a # the SSL handshake
569n/a self._write_backlog.append((b'', 1))
570n/a self._loop.call_soon(self._process_write_backlog)
571n/a
572n/a def _on_handshake_complete(self, handshake_exc):
573n/a self._in_handshake = False
574n/a
575n/a sslobj = self._sslpipe.ssl_object
576n/a try:
577n/a if handshake_exc is not None:
578n/a raise handshake_exc
579n/a
580n/a peercert = sslobj.getpeercert()
581n/a if not hasattr(self._sslcontext, 'check_hostname'):
582n/a # Verify hostname if requested, Python 3.4+ uses check_hostname
583n/a # and checks the hostname in do_handshake()
584n/a if (self._server_hostname
585n/a and self._sslcontext.verify_mode != ssl.CERT_NONE):
586n/a ssl.match_hostname(peercert, self._server_hostname)
587n/a except BaseException as exc:
588n/a if self._loop.get_debug():
589n/a if isinstance(exc, ssl.CertificateError):
590n/a logger.warning("%r: SSL handshake failed "
591n/a "on verifying the certificate",
592n/a self, exc_info=True)
593n/a else:
594n/a logger.warning("%r: SSL handshake failed",
595n/a self, exc_info=True)
596n/a self._transport.close()
597n/a if isinstance(exc, Exception):
598n/a self._wakeup_waiter(exc)
599n/a return
600n/a else:
601n/a raise
602n/a
603n/a if self._loop.get_debug():
604n/a dt = self._loop.time() - self._handshake_start_time
605n/a logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
606n/a
607n/a # Add extra info that becomes available after handshake.
608n/a self._extra.update(peercert=peercert,
609n/a cipher=sslobj.cipher(),
610n/a compression=sslobj.compression(),
611n/a ssl_object=sslobj,
612n/a )
613n/a if self._call_connection_made:
614n/a self._app_protocol.connection_made(self._app_transport)
615n/a self._wakeup_waiter()
616n/a self._session_established = True
617n/a # In case transport.write() was already called. Don't call
618n/a # immediately _process_write_backlog(), but schedule it:
619n/a # _on_handshake_complete() can be called indirectly from
620n/a # _process_write_backlog(), and _process_write_backlog() is not
621n/a # reentrant.
622n/a self._loop.call_soon(self._process_write_backlog)
623n/a
624n/a def _process_write_backlog(self):
625n/a # Try to make progress on the write backlog.
626n/a if self._transport is None:
627n/a return
628n/a
629n/a try:
630n/a for i in range(len(self._write_backlog)):
631n/a data, offset = self._write_backlog[0]
632n/a if data:
633n/a ssldata, offset = self._sslpipe.feed_appdata(data, offset)
634n/a elif offset:
635n/a ssldata = self._sslpipe.do_handshake(
636n/a self._on_handshake_complete)
637n/a offset = 1
638n/a else:
639n/a ssldata = self._sslpipe.shutdown(self._finalize)
640n/a offset = 1
641n/a
642n/a for chunk in ssldata:
643n/a self._transport.write(chunk)
644n/a
645n/a if offset < len(data):
646n/a self._write_backlog[0] = (data, offset)
647n/a # A short write means that a write is blocked on a read
648n/a # We need to enable reading if it is paused!
649n/a assert self._sslpipe.need_ssldata
650n/a if self._transport._paused:
651n/a self._transport.resume_reading()
652n/a break
653n/a
654n/a # An entire chunk from the backlog was processed. We can
655n/a # delete it and reduce the outstanding buffer size.
656n/a del self._write_backlog[0]
657n/a self._write_buffer_size -= len(data)
658n/a except BaseException as exc:
659n/a if self._in_handshake:
660n/a # BaseExceptions will be re-raised in _on_handshake_complete.
661n/a self._on_handshake_complete(exc)
662n/a else:
663n/a self._fatal_error(exc, 'Fatal error on SSL transport')
664n/a if not isinstance(exc, Exception):
665n/a # BaseException
666n/a raise
667n/a
668n/a def _fatal_error(self, exc, message='Fatal error on transport'):
669n/a # Should be called from exception handler only.
670n/a if isinstance(exc, base_events._FATAL_ERROR_IGNORE):
671n/a if self._loop.get_debug():
672n/a logger.debug("%r: %s", self, message, exc_info=True)
673n/a else:
674n/a self._loop.call_exception_handler({
675n/a 'message': message,
676n/a 'exception': exc,
677n/a 'transport': self._transport,
678n/a 'protocol': self,
679n/a })
680n/a if self._transport:
681n/a self._transport._force_close(exc)
682n/a
683n/a def _finalize(self):
684n/a if self._transport is not None:
685n/a self._transport.close()
686n/a
687n/a def _abort(self):
688n/a if self._transport is not None:
689n/a try:
690n/a self._transport.abort()
691n/a finally:
692n/a self._finalize()