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