Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

951 рядки
35 KiB

  1. cdef _create_transport_context(server_side, server_hostname):
  2. if server_side:
  3. raise ValueError('Server side SSL needs a valid SSLContext')
  4. # Client side may pass ssl=True to use a default
  5. # context; in that case the sslcontext passed is None.
  6. # The default is secure for client connections.
  7. # Python 3.4+: use up-to-date strong settings.
  8. sslcontext = ssl_create_default_context()
  9. if not server_hostname:
  10. sslcontext.check_hostname = False
  11. return sslcontext
  12. cdef class _SSLProtocolTransport:
  13. # TODO:
  14. # _sendfile_compatible = constants._SendfileMode.FALLBACK
  15. def __cinit__(self, Loop loop, ssl_protocol, context):
  16. self._loop = loop
  17. # SSLProtocol instance
  18. self._ssl_protocol = ssl_protocol
  19. self._closed = False
  20. if context is None:
  21. context = Context_CopyCurrent()
  22. self.context = context
  23. def get_extra_info(self, name, default=None):
  24. """Get optional transport information."""
  25. return self._ssl_protocol._get_extra_info(name, default)
  26. def set_protocol(self, protocol):
  27. self._ssl_protocol._set_app_protocol(protocol)
  28. def get_protocol(self):
  29. return self._ssl_protocol._app_protocol
  30. def is_closing(self):
  31. return self._closed
  32. def close(self):
  33. """Close the transport.
  34. Buffered data will be flushed asynchronously. No more data
  35. will be received. After all buffered data is flushed, the
  36. protocol's connection_lost() method will (eventually) called
  37. with None as its argument.
  38. """
  39. self._closed = True
  40. self._ssl_protocol._start_shutdown(self.context.copy())
  41. def __dealloc__(self):
  42. if not self._closed:
  43. self._closed = True
  44. warnings_warn(
  45. "unclosed transport <uvloop.loop._SSLProtocolTransport "
  46. "object>", ResourceWarning)
  47. def is_reading(self):
  48. return not self._ssl_protocol._app_reading_paused
  49. def pause_reading(self):
  50. """Pause the receiving end.
  51. No data will be passed to the protocol's data_received()
  52. method until resume_reading() is called.
  53. """
  54. self._ssl_protocol._pause_reading()
  55. def resume_reading(self):
  56. """Resume the receiving end.
  57. Data received will once again be passed to the protocol's
  58. data_received() method.
  59. """
  60. self._ssl_protocol._resume_reading(self.context.copy())
  61. def set_write_buffer_limits(self, high=None, low=None):
  62. """Set the high- and low-water limits for write flow control.
  63. These two values control when to call the protocol's
  64. pause_writing() and resume_writing() methods. If specified,
  65. the low-water limit must be less than or equal to the
  66. high-water limit. Neither value can be negative.
  67. The defaults are implementation-specific. If only the
  68. high-water limit is given, the low-water limit defaults to an
  69. implementation-specific value less than or equal to the
  70. high-water limit. Setting high to zero forces low to zero as
  71. well, and causes pause_writing() to be called whenever the
  72. buffer becomes non-empty. Setting low to zero causes
  73. resume_writing() to be called only once the buffer is empty.
  74. Use of zero for either limit is generally sub-optimal as it
  75. reduces opportunities for doing I/O and computation
  76. concurrently.
  77. """
  78. self._ssl_protocol._set_write_buffer_limits(high, low)
  79. self._ssl_protocol._control_app_writing(self.context.copy())
  80. def get_write_buffer_limits(self):
  81. return (self._ssl_protocol._outgoing_low_water,
  82. self._ssl_protocol._outgoing_high_water)
  83. def get_write_buffer_size(self):
  84. """Return the current size of the write buffers."""
  85. return self._ssl_protocol._get_write_buffer_size()
  86. def set_read_buffer_limits(self, high=None, low=None):
  87. """Set the high- and low-water limits for read flow control.
  88. These two values control when to call the upstream transport's
  89. pause_reading() and resume_reading() methods. If specified,
  90. the low-water limit must be less than or equal to the
  91. high-water limit. Neither value can be negative.
  92. The defaults are implementation-specific. If only the
  93. high-water limit is given, the low-water limit defaults to an
  94. implementation-specific value less than or equal to the
  95. high-water limit. Setting high to zero forces low to zero as
  96. well, and causes pause_reading() to be called whenever the
  97. buffer becomes non-empty. Setting low to zero causes
  98. resume_reading() to be called only once the buffer is empty.
  99. Use of zero for either limit is generally sub-optimal as it
  100. reduces opportunities for doing I/O and computation
  101. concurrently.
  102. """
  103. self._ssl_protocol._set_read_buffer_limits(high, low)
  104. self._ssl_protocol._control_ssl_reading()
  105. def get_read_buffer_limits(self):
  106. return (self._ssl_protocol._incoming_low_water,
  107. self._ssl_protocol._incoming_high_water)
  108. def get_read_buffer_size(self):
  109. """Return the current size of the read buffer."""
  110. return self._ssl_protocol._get_read_buffer_size()
  111. @property
  112. def _protocol_paused(self):
  113. # Required for sendfile fallback pause_writing/resume_writing logic
  114. return self._ssl_protocol._app_writing_paused
  115. def write(self, data):
  116. """Write some data bytes to the transport.
  117. This does not block; it buffers the data and arranges for it
  118. to be sent out asynchronously.
  119. """
  120. if not isinstance(data, (bytes, bytearray, memoryview)):
  121. raise TypeError(f"data: expecting a bytes-like instance, "
  122. f"got {type(data).__name__}")
  123. if not data:
  124. return
  125. self._ssl_protocol._write_appdata((data,), self.context.copy())
  126. def writelines(self, list_of_data):
  127. """Write a list (or any iterable) of data bytes to the transport.
  128. The default implementation concatenates the arguments and
  129. calls write() on the result.
  130. """
  131. self._ssl_protocol._write_appdata(list_of_data, self.context.copy())
  132. def write_eof(self):
  133. """Close the write end after flushing buffered data.
  134. This raises :exc:`NotImplementedError` right now.
  135. """
  136. raise NotImplementedError
  137. def can_write_eof(self):
  138. """Return True if this transport supports write_eof(), False if not."""
  139. return False
  140. def abort(self):
  141. """Close the transport immediately.
  142. Buffered data will be lost. No more data will be received.
  143. The protocol's connection_lost() method will (eventually) be
  144. called with None as its argument.
  145. """
  146. self._force_close(None)
  147. def _force_close(self, exc):
  148. self._closed = True
  149. self._ssl_protocol._abort(exc)
  150. def _test__append_write_backlog(self, data):
  151. # for test only
  152. self._ssl_protocol._write_backlog.append(data)
  153. self._ssl_protocol._write_buffer_size += len(data)
  154. cdef class SSLProtocol:
  155. """SSL protocol.
  156. Implementation of SSL on top of a socket using incoming and outgoing
  157. buffers which are ssl.MemoryBIO objects.
  158. """
  159. def __cinit__(self, *args, **kwargs):
  160. self._ssl_buffer_len = SSL_READ_MAX_SIZE
  161. self._ssl_buffer = <char*>PyMem_RawMalloc(self._ssl_buffer_len)
  162. if not self._ssl_buffer:
  163. raise MemoryError()
  164. self._ssl_buffer_view = PyMemoryView_FromMemory(
  165. self._ssl_buffer, self._ssl_buffer_len, PyBUF_WRITE)
  166. def __dealloc__(self):
  167. self._ssl_buffer_view = None
  168. PyMem_RawFree(self._ssl_buffer)
  169. self._ssl_buffer = NULL
  170. self._ssl_buffer_len = 0
  171. def __init__(self, loop, app_protocol, sslcontext, waiter,
  172. server_side=False, server_hostname=None,
  173. call_connection_made=True,
  174. ssl_handshake_timeout=None,
  175. ssl_shutdown_timeout=None):
  176. if ssl_handshake_timeout is None:
  177. ssl_handshake_timeout = SSL_HANDSHAKE_TIMEOUT
  178. elif ssl_handshake_timeout <= 0:
  179. raise ValueError(
  180. f"ssl_handshake_timeout should be a positive number, "
  181. f"got {ssl_handshake_timeout}")
  182. if ssl_shutdown_timeout is None:
  183. ssl_shutdown_timeout = SSL_SHUTDOWN_TIMEOUT
  184. elif ssl_shutdown_timeout <= 0:
  185. raise ValueError(
  186. f"ssl_shutdown_timeout should be a positive number, "
  187. f"got {ssl_shutdown_timeout}")
  188. if not sslcontext:
  189. sslcontext = _create_transport_context(
  190. server_side, server_hostname)
  191. self._server_side = server_side
  192. if server_hostname and not server_side:
  193. self._server_hostname = server_hostname
  194. else:
  195. self._server_hostname = None
  196. self._sslcontext = sslcontext
  197. # SSL-specific extra info. More info are set when the handshake
  198. # completes.
  199. self._extra = dict(sslcontext=sslcontext)
  200. # App data write buffering
  201. self._write_backlog = col_deque()
  202. self._write_buffer_size = 0
  203. self._waiter = waiter
  204. self._loop = loop
  205. self._set_app_protocol(app_protocol)
  206. self._app_transport = None
  207. self._app_transport_created = False
  208. # transport, ex: SelectorSocketTransport
  209. self._transport = None
  210. self._ssl_handshake_timeout = ssl_handshake_timeout
  211. self._ssl_shutdown_timeout = ssl_shutdown_timeout
  212. # SSL and state machine
  213. self._sslobj = None
  214. self._incoming = ssl_MemoryBIO()
  215. self._incoming_write = self._incoming.write
  216. self._outgoing = ssl_MemoryBIO()
  217. self._outgoing_read = self._outgoing.read
  218. self._state = UNWRAPPED
  219. self._conn_lost = 0 # Set when connection_lost called
  220. if call_connection_made:
  221. self._app_state = STATE_INIT
  222. else:
  223. self._app_state = STATE_CON_MADE
  224. # Flow Control
  225. self._ssl_writing_paused = False
  226. self._app_reading_paused = False
  227. self._ssl_reading_paused = False
  228. self._incoming_high_water = 0
  229. self._incoming_low_water = 0
  230. self._set_read_buffer_limits()
  231. self._app_writing_paused = False
  232. self._outgoing_high_water = 0
  233. self._outgoing_low_water = 0
  234. self._set_write_buffer_limits()
  235. cdef _set_app_protocol(self, app_protocol):
  236. self._app_protocol = app_protocol
  237. if (hasattr(app_protocol, 'get_buffer') and
  238. not isinstance(app_protocol, aio_Protocol)):
  239. self._app_protocol_get_buffer = app_protocol.get_buffer
  240. self._app_protocol_buffer_updated = app_protocol.buffer_updated
  241. self._app_protocol_is_buffer = True
  242. else:
  243. self._app_protocol_is_buffer = False
  244. cdef _wakeup_waiter(self, exc=None):
  245. if self._waiter is None:
  246. return
  247. if not self._waiter.cancelled():
  248. if exc is not None:
  249. self._waiter.set_exception(exc)
  250. else:
  251. self._waiter.set_result(None)
  252. self._waiter = None
  253. def _get_app_transport(self, context=None):
  254. if self._app_transport is None:
  255. if self._app_transport_created:
  256. raise RuntimeError('Creating _SSLProtocolTransport twice')
  257. self._app_transport = _SSLProtocolTransport(self._loop, self,
  258. context)
  259. self._app_transport_created = True
  260. return self._app_transport
  261. def connection_made(self, transport):
  262. """Called when the low-level connection is made.
  263. Start the SSL handshake.
  264. """
  265. self._transport = transport
  266. self._start_handshake()
  267. def connection_lost(self, exc):
  268. """Called when the low-level connection is lost or closed.
  269. The argument is an exception object or None (the latter
  270. meaning a regular EOF is received or the connection was
  271. aborted or closed).
  272. """
  273. self._write_backlog.clear()
  274. self._outgoing_read()
  275. self._conn_lost += 1
  276. # Just mark the app transport as closed so that its __dealloc__
  277. # doesn't complain.
  278. if self._app_transport is not None:
  279. self._app_transport._closed = True
  280. if self._state != DO_HANDSHAKE:
  281. if self._app_state == STATE_CON_MADE or \
  282. self._app_state == STATE_EOF:
  283. self._app_state = STATE_CON_LOST
  284. self._loop.call_soon(self._app_protocol.connection_lost, exc)
  285. self._set_state(UNWRAPPED)
  286. self._transport = None
  287. self._app_transport = None
  288. self._app_protocol = None
  289. self._wakeup_waiter(exc)
  290. if self._shutdown_timeout_handle:
  291. self._shutdown_timeout_handle.cancel()
  292. self._shutdown_timeout_handle = None
  293. if self._handshake_timeout_handle:
  294. self._handshake_timeout_handle.cancel()
  295. self._handshake_timeout_handle = None
  296. def get_buffer(self, n):
  297. cdef size_t want = n
  298. if want > SSL_READ_MAX_SIZE:
  299. want = SSL_READ_MAX_SIZE
  300. if self._ssl_buffer_len < want:
  301. self._ssl_buffer = <char*>PyMem_RawRealloc(self._ssl_buffer, want)
  302. if not self._ssl_buffer:
  303. raise MemoryError()
  304. self._ssl_buffer_len = want
  305. self._ssl_buffer_view = PyMemoryView_FromMemory(
  306. self._ssl_buffer, want, PyBUF_WRITE)
  307. return self._ssl_buffer_view
  308. def buffer_updated(self, nbytes):
  309. self._incoming_write(PyMemoryView_FromMemory(
  310. self._ssl_buffer, nbytes, PyBUF_WRITE))
  311. if self._state == DO_HANDSHAKE:
  312. self._do_handshake()
  313. elif self._state == WRAPPED:
  314. self._do_read()
  315. elif self._state == FLUSHING:
  316. self._do_flush()
  317. elif self._state == SHUTDOWN:
  318. self._do_shutdown()
  319. def eof_received(self):
  320. """Called when the other end of the low-level stream
  321. is half-closed.
  322. If this returns a false value (including None), the transport
  323. will close itself. If it returns a true value, closing the
  324. transport is up to the protocol.
  325. """
  326. try:
  327. if self._loop.get_debug():
  328. aio_logger.debug("%r received EOF", self)
  329. if self._state == DO_HANDSHAKE:
  330. self._on_handshake_complete(ConnectionResetError)
  331. elif self._state == WRAPPED or self._state == FLUSHING:
  332. # We treat a low-level EOF as a critical situation similar to a
  333. # broken connection - just send whatever is in the buffer and
  334. # close. No application level eof_received() is called -
  335. # because we don't want the user to think that this is a
  336. # graceful shutdown triggered by SSL "close_notify".
  337. self._set_state(SHUTDOWN)
  338. self._on_shutdown_complete(None)
  339. elif self._state == SHUTDOWN:
  340. self._on_shutdown_complete(None)
  341. except Exception:
  342. self._transport.close()
  343. raise
  344. cdef _get_extra_info(self, name, default=None):
  345. if name == 'uvloop.sslproto':
  346. return self
  347. elif name in self._extra:
  348. return self._extra[name]
  349. elif self._transport is not None:
  350. return self._transport.get_extra_info(name, default)
  351. else:
  352. return default
  353. cdef _set_state(self, SSLProtocolState new_state):
  354. cdef bint allowed = False
  355. if new_state == UNWRAPPED:
  356. allowed = True
  357. elif self._state == UNWRAPPED and new_state == DO_HANDSHAKE:
  358. allowed = True
  359. elif self._state == DO_HANDSHAKE and new_state == WRAPPED:
  360. allowed = True
  361. elif self._state == WRAPPED and new_state == FLUSHING:
  362. allowed = True
  363. elif self._state == WRAPPED and new_state == SHUTDOWN:
  364. allowed = True
  365. elif self._state == FLUSHING and new_state == SHUTDOWN:
  366. allowed = True
  367. if allowed:
  368. self._state = new_state
  369. else:
  370. raise RuntimeError(
  371. 'cannot switch state from {} to {}'.format(
  372. self._state, new_state))
  373. # Handshake flow
  374. cdef _start_handshake(self):
  375. if self._loop.get_debug():
  376. aio_logger.debug("%r starts SSL handshake", self)
  377. self._handshake_start_time = self._loop.time()
  378. else:
  379. self._handshake_start_time = None
  380. self._set_state(DO_HANDSHAKE)
  381. # start handshake timeout count down
  382. self._handshake_timeout_handle = \
  383. self._loop.call_later(self._ssl_handshake_timeout,
  384. lambda: self._check_handshake_timeout())
  385. try:
  386. self._sslobj = self._sslcontext.wrap_bio(
  387. self._incoming, self._outgoing,
  388. server_side=self._server_side,
  389. server_hostname=self._server_hostname)
  390. self._sslobj_read = self._sslobj.read
  391. self._sslobj_write = self._sslobj.write
  392. except Exception as ex:
  393. self._on_handshake_complete(ex)
  394. else:
  395. self._do_handshake()
  396. cdef _check_handshake_timeout(self):
  397. if self._state == DO_HANDSHAKE:
  398. msg = (
  399. f"SSL handshake is taking longer than "
  400. f"{self._ssl_handshake_timeout} seconds: "
  401. f"aborting the connection"
  402. )
  403. self._fatal_error(ConnectionAbortedError(msg))
  404. cdef _do_handshake(self):
  405. try:
  406. self._sslobj.do_handshake()
  407. except ssl_SSLAgainErrors as exc:
  408. self._process_outgoing()
  409. except ssl_SSLError as exc:
  410. self._on_handshake_complete(exc)
  411. else:
  412. self._on_handshake_complete(None)
  413. cdef _on_handshake_complete(self, handshake_exc):
  414. if self._handshake_timeout_handle is not None:
  415. self._handshake_timeout_handle.cancel()
  416. self._handshake_timeout_handle = None
  417. sslobj = self._sslobj
  418. try:
  419. if handshake_exc is None:
  420. self._set_state(WRAPPED)
  421. else:
  422. raise handshake_exc
  423. peercert = sslobj.getpeercert()
  424. except Exception as exc:
  425. self._set_state(UNWRAPPED)
  426. if isinstance(exc, ssl_CertificateError):
  427. msg = 'SSL handshake failed on verifying the certificate'
  428. else:
  429. msg = 'SSL handshake failed'
  430. self._fatal_error(exc, msg)
  431. self._wakeup_waiter(exc)
  432. return
  433. if self._loop.get_debug():
  434. dt = self._loop.time() - self._handshake_start_time
  435. aio_logger.debug("%r: SSL handshake took %.1f ms", self, dt * 1e3)
  436. # Add extra info that becomes available after handshake.
  437. self._extra.update(peercert=peercert,
  438. cipher=sslobj.cipher(),
  439. compression=sslobj.compression(),
  440. ssl_object=sslobj)
  441. if self._app_state == STATE_INIT:
  442. self._app_state = STATE_CON_MADE
  443. self._app_protocol.connection_made(self._get_app_transport())
  444. self._wakeup_waiter()
  445. # We should wakeup user code before sending the first data below. In
  446. # case of `start_tls()`, the user can only get the SSLTransport in the
  447. # wakeup callback, because `connection_made()` is not called again.
  448. # We should schedule the first data later than the wakeup callback so
  449. # that the user get a chance to e.g. check ALPN with the transport
  450. # before having to handle the first data.
  451. self._loop._call_soon_handle(
  452. new_MethodHandle(self._loop,
  453. "SSLProtocol._do_read",
  454. <method_t> self._do_read,
  455. None, # current context is good
  456. self))
  457. # Shutdown flow
  458. cdef _start_shutdown(self, object context=None):
  459. if self._state in (FLUSHING, SHUTDOWN, UNWRAPPED):
  460. return
  461. # we don't need the context for _abort or the timeout, because
  462. # TCP transport._force_close() should be able to call
  463. # connection_lost() in the right context
  464. if self._app_transport is not None:
  465. self._app_transport._closed = True
  466. if self._state == DO_HANDSHAKE:
  467. self._abort(None)
  468. else:
  469. self._set_state(FLUSHING)
  470. self._shutdown_timeout_handle = \
  471. self._loop.call_later(self._ssl_shutdown_timeout,
  472. lambda: self._check_shutdown_timeout())
  473. self._do_flush(context)
  474. cdef _check_shutdown_timeout(self):
  475. if self._state in (FLUSHING, SHUTDOWN):
  476. self._transport._force_close(
  477. aio_TimeoutError('SSL shutdown timed out'))
  478. cdef _do_read_into_void(self, object context):
  479. """Consume and discard incoming application data.
  480. If close_notify is received for the first time, call eof_received.
  481. """
  482. cdef:
  483. bint close_notify = False
  484. try:
  485. while True:
  486. if not self._sslobj_read(SSL_READ_MAX_SIZE):
  487. close_notify = True
  488. break
  489. except ssl_SSLAgainErrors as exc:
  490. pass
  491. except ssl_SSLZeroReturnError:
  492. close_notify = True
  493. if close_notify:
  494. self._call_eof_received(context)
  495. cdef _do_flush(self, object context=None):
  496. """Flush the write backlog, discarding new data received.
  497. We don't send close_notify in FLUSHING because we still want to send
  498. the remaining data over SSL, even if we received a close_notify. Also,
  499. no application-level resume_writing() or pause_writing() will be called
  500. in FLUSHING, as we could fully manage the flow control internally.
  501. """
  502. try:
  503. self._do_read_into_void(context)
  504. self._do_write()
  505. self._process_outgoing()
  506. self._control_ssl_reading()
  507. except Exception as ex:
  508. self._on_shutdown_complete(ex)
  509. else:
  510. if not self._get_write_buffer_size():
  511. self._set_state(SHUTDOWN)
  512. self._do_shutdown(context)
  513. cdef _do_shutdown(self, object context=None):
  514. """Send close_notify and wait for the same from the peer."""
  515. try:
  516. # we must skip all application data (if any) before unwrap
  517. self._do_read_into_void(context)
  518. try:
  519. self._sslobj.unwrap()
  520. except ssl_SSLAgainErrors as exc:
  521. self._process_outgoing()
  522. else:
  523. self._process_outgoing()
  524. if not self._get_write_buffer_size():
  525. self._on_shutdown_complete(None)
  526. except Exception as ex:
  527. self._on_shutdown_complete(ex)
  528. cdef _on_shutdown_complete(self, shutdown_exc):
  529. if self._shutdown_timeout_handle is not None:
  530. self._shutdown_timeout_handle.cancel()
  531. self._shutdown_timeout_handle = None
  532. # we don't need the context here because TCP transport.close() should
  533. # be able to call connection_made() in the right context
  534. if shutdown_exc:
  535. self._fatal_error(shutdown_exc, 'Error occurred during shutdown')
  536. else:
  537. self._transport.close()
  538. cdef _abort(self, exc):
  539. self._set_state(UNWRAPPED)
  540. if self._transport is not None:
  541. self._transport._force_close(exc)
  542. # Outgoing flow
  543. cdef _write_appdata(self, list_of_data, object context):
  544. if self._state in (FLUSHING, SHUTDOWN, UNWRAPPED):
  545. if self._conn_lost >= LOG_THRESHOLD_FOR_CONNLOST_WRITES:
  546. aio_logger.warning('SSL connection is closed')
  547. self._conn_lost += 1
  548. return
  549. for data in list_of_data:
  550. self._write_backlog.append(data)
  551. self._write_buffer_size += len(data)
  552. try:
  553. if self._state == WRAPPED:
  554. self._do_write()
  555. self._process_outgoing()
  556. self._control_app_writing(context)
  557. except Exception as ex:
  558. self._fatal_error(ex, 'Fatal error on SSL protocol')
  559. cdef _do_write(self):
  560. """Do SSL write, consumes write backlog and fills outgoing BIO."""
  561. cdef size_t data_len, count
  562. try:
  563. while self._write_backlog:
  564. data = self._write_backlog[0]
  565. count = self._sslobj_write(data)
  566. data_len = len(data)
  567. if count < data_len:
  568. if not PyMemoryView_Check(data):
  569. data = PyMemoryView_FromObject(data)
  570. self._write_backlog[0] = data[count:]
  571. self._write_buffer_size -= count
  572. else:
  573. del self._write_backlog[0]
  574. self._write_buffer_size -= data_len
  575. except ssl_SSLAgainErrors as exc:
  576. pass
  577. cdef _process_outgoing(self):
  578. """Send bytes from the outgoing BIO."""
  579. if not self._ssl_writing_paused:
  580. data = self._outgoing_read()
  581. if len(data):
  582. self._transport.write(data)
  583. # Incoming flow
  584. cdef _do_read(self):
  585. if self._state != WRAPPED:
  586. return
  587. try:
  588. if not self._app_reading_paused:
  589. if self._app_protocol_is_buffer:
  590. self._do_read__buffered()
  591. else:
  592. self._do_read__copied()
  593. if self._write_backlog:
  594. self._do_write()
  595. self._process_outgoing()
  596. self._control_app_writing()
  597. self._control_ssl_reading()
  598. except Exception as ex:
  599. self._fatal_error(ex, 'Fatal error on SSL protocol')
  600. cdef _do_read__buffered(self):
  601. cdef:
  602. Py_buffer pybuf
  603. bint pybuf_inited = False
  604. size_t wants, offset = 0
  605. int count = 1
  606. object buf
  607. buf = self._app_protocol_get_buffer(self._get_read_buffer_size())
  608. wants = len(buf)
  609. try:
  610. count = self._sslobj_read(wants, buf)
  611. if count > 0:
  612. offset = count
  613. if offset < wants:
  614. PyObject_GetBuffer(buf, &pybuf, PyBUF_WRITABLE)
  615. pybuf_inited = True
  616. while offset < wants:
  617. buf = PyMemoryView_FromMemory(
  618. (<char*>pybuf.buf) + offset,
  619. wants - offset,
  620. PyBUF_WRITE)
  621. count = self._sslobj_read(wants - offset, buf)
  622. if count > 0:
  623. offset += count
  624. else:
  625. break
  626. else:
  627. self._loop._call_soon_handle(
  628. new_MethodHandle(self._loop,
  629. "SSLProtocol._do_read",
  630. <method_t>self._do_read,
  631. None, # current context is good
  632. self))
  633. except ssl_SSLAgainErrors as exc:
  634. pass
  635. finally:
  636. if pybuf_inited:
  637. PyBuffer_Release(&pybuf)
  638. if offset > 0:
  639. self._app_protocol_buffer_updated(offset)
  640. if not count:
  641. # close_notify
  642. self._call_eof_received()
  643. self._start_shutdown()
  644. cdef _do_read__copied(self):
  645. cdef:
  646. list data
  647. bytes first, chunk = b'1'
  648. bint zero = True, one = False
  649. try:
  650. while True:
  651. chunk = self._sslobj_read(SSL_READ_MAX_SIZE)
  652. if not chunk:
  653. break
  654. if zero:
  655. zero = False
  656. one = True
  657. first = chunk
  658. elif one:
  659. one = False
  660. data = [first, chunk]
  661. else:
  662. data.append(chunk)
  663. except ssl_SSLAgainErrors as exc:
  664. pass
  665. if one:
  666. self._app_protocol.data_received(first)
  667. elif not zero:
  668. self._app_protocol.data_received(b''.join(data))
  669. if not chunk:
  670. # close_notify
  671. self._call_eof_received()
  672. self._start_shutdown()
  673. cdef _call_eof_received(self, object context=None):
  674. if self._app_state == STATE_CON_MADE:
  675. self._app_state = STATE_EOF
  676. try:
  677. if context is None:
  678. # If the caller didn't provide a context, we assume the
  679. # caller is already in the right context, which is usually
  680. # inside the upstream callbacks like buffer_updated()
  681. keep_open = self._app_protocol.eof_received()
  682. else:
  683. keep_open = run_in_context(
  684. context, self._app_protocol.eof_received,
  685. )
  686. except (KeyboardInterrupt, SystemExit):
  687. raise
  688. except BaseException as ex:
  689. self._fatal_error(ex, 'Error calling eof_received()')
  690. else:
  691. if keep_open:
  692. aio_logger.warning('returning true from eof_received() '
  693. 'has no effect when using ssl')
  694. # Flow control for writes from APP socket
  695. cdef _control_app_writing(self, object context=None):
  696. cdef size_t size = self._get_write_buffer_size()
  697. if size >= self._outgoing_high_water and not self._app_writing_paused:
  698. self._app_writing_paused = True
  699. try:
  700. if context is None:
  701. # If the caller didn't provide a context, we assume the
  702. # caller is already in the right context, which is usually
  703. # inside the upstream callbacks like buffer_updated()
  704. self._app_protocol.pause_writing()
  705. else:
  706. run_in_context(context, self._app_protocol.pause_writing)
  707. except (KeyboardInterrupt, SystemExit):
  708. raise
  709. except BaseException as exc:
  710. self._loop.call_exception_handler({
  711. 'message': 'protocol.pause_writing() failed',
  712. 'exception': exc,
  713. 'transport': self._app_transport,
  714. 'protocol': self,
  715. })
  716. elif size <= self._outgoing_low_water and self._app_writing_paused:
  717. self._app_writing_paused = False
  718. try:
  719. if context is None:
  720. # If the caller didn't provide a context, we assume the
  721. # caller is already in the right context, which is usually
  722. # inside the upstream callbacks like resume_writing()
  723. self._app_protocol.resume_writing()
  724. else:
  725. run_in_context(context, self._app_protocol.resume_writing)
  726. except (KeyboardInterrupt, SystemExit):
  727. raise
  728. except BaseException as exc:
  729. self._loop.call_exception_handler({
  730. 'message': 'protocol.resume_writing() failed',
  731. 'exception': exc,
  732. 'transport': self._app_transport,
  733. 'protocol': self,
  734. })
  735. cdef size_t _get_write_buffer_size(self):
  736. return self._outgoing.pending + self._write_buffer_size
  737. cdef _set_write_buffer_limits(self, high=None, low=None):
  738. high, low = add_flowcontrol_defaults(
  739. high, low, FLOW_CONTROL_HIGH_WATER_SSL_WRITE)
  740. self._outgoing_high_water = high
  741. self._outgoing_low_water = low
  742. # Flow control for reads to APP socket
  743. cdef _pause_reading(self):
  744. self._app_reading_paused = True
  745. cdef _resume_reading(self, object context):
  746. if self._app_reading_paused:
  747. self._app_reading_paused = False
  748. if self._state == WRAPPED:
  749. self._loop._call_soon_handle(
  750. new_MethodHandle(self._loop,
  751. "SSLProtocol._do_read",
  752. <method_t>self._do_read,
  753. context,
  754. self))
  755. # Flow control for reads from SSL socket
  756. cdef _control_ssl_reading(self):
  757. cdef size_t size = self._get_read_buffer_size()
  758. if size >= self._incoming_high_water and not self._ssl_reading_paused:
  759. self._ssl_reading_paused = True
  760. self._transport.pause_reading()
  761. elif size <= self._incoming_low_water and self._ssl_reading_paused:
  762. self._ssl_reading_paused = False
  763. self._transport.resume_reading()
  764. cdef _set_read_buffer_limits(self, high=None, low=None):
  765. high, low = add_flowcontrol_defaults(
  766. high, low, FLOW_CONTROL_HIGH_WATER_SSL_READ)
  767. self._incoming_high_water = high
  768. self._incoming_low_water = low
  769. cdef size_t _get_read_buffer_size(self):
  770. return self._incoming.pending
  771. # Flow control for writes to SSL socket
  772. def pause_writing(self):
  773. """Called when the low-level transport's buffer goes over
  774. the high-water mark.
  775. """
  776. assert not self._ssl_writing_paused
  777. self._ssl_writing_paused = True
  778. def resume_writing(self):
  779. """Called when the low-level transport's buffer drains below
  780. the low-water mark.
  781. """
  782. assert self._ssl_writing_paused
  783. self._ssl_writing_paused = False
  784. if self._state == WRAPPED:
  785. self._process_outgoing()
  786. self._control_app_writing()
  787. elif self._state == FLUSHING:
  788. self._do_flush()
  789. elif self._state == SHUTDOWN:
  790. self._do_shutdown()
  791. cdef _fatal_error(self, exc, message='Fatal error on transport'):
  792. if self._app_transport:
  793. self._app_transport._force_close(exc)
  794. elif self._transport:
  795. self._transport._force_close(exc)
  796. if isinstance(exc, OSError):
  797. if self._loop.get_debug():
  798. aio_logger.debug("%r: %s", self, message, exc_info=True)
  799. elif not isinstance(exc, aio_CancelledError):
  800. self._loop.call_exception_handler({
  801. 'message': message,
  802. 'exception': exc,
  803. 'transport': self._transport,
  804. 'protocol': self,
  805. })