Skip to content

Commit 873866a

Browse files
committed
Retry on WANT_WRITE & WANT_READ in sendall()
This change introduces retries in `OpenSSL.SSL.Connection.sendall()` when `WANT_WRITE_ERROR` or `WANT_READ_ERROR` happen. It relies on `SSL_MODE_ENABLE_PARTIAL_WRITE` being set on the context, that changes the mode of `SSL_write()` to return errors only if zero bytes has been sent making it safe to retry in these cases. Ideally, the calling code is supposed to `poll()`/`select()` the socket to know when it's okay to attempt the next retry (hence it is readable or writable) but it's not available in the `sendall()` method and just retrying the operation is good enough. Fixes #176 Refs: * http://openssl.6102.n7.nabble.com/SSL-MODE-ACCEPT-MOVING-WRITE-BUFFER-td6421.html * https://stackoverflow.com/a/28992313/595220 * https://www.openssl.org/docs/manmaster/man3/SSL_write.html * https://stackoverflow.com/a/20817394/595220
1 parent 124a013 commit 873866a

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

CHANGELOG.rst

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Deprecations:
2525
Changes:
2626
^^^^^^^^
2727

28+
- Fixed the inability of ``OpenSSL.SSL.Connection.sendall()`` to
29+
keep with sending data over the wire after ``SSL_ERROR_WANT_READ``
30+
or ``SSL_ERROR_WANT_WRITE`` is returned by ``SSL_write()``.
31+
`#176 <https://github.com/pyca/pyopenssl/pull/176>`_
2832
- Added a new optional ``chain`` parameter to ``OpenSSL.crypto.X509StoreContext()``
2933
where additional untrusted certificates can be specified to help chain building.
3034
`#948 <https://github.com/pyca/pyopenssl/pull/948>`_

src/OpenSSL/SSL.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -1670,7 +1670,14 @@ def sendall(self, buf, flags=0):
16701670
result = _lib.SSL_write(
16711671
self._ssl, data + total_sent, min(left_to_send, 2147483647)
16721672
)
1673-
self._raise_ssl_error(self._ssl, result)
1673+
try:
1674+
self._raise_ssl_error(self._ssl, result)
1675+
except (WantReadError, WantWriteError):
1676+
# NOTE: The use of SSL_MODE_ENABLE_PARTIAL_WRITE
1677+
# NOTE: above guarantees that in case of failure
1678+
# NOTE: no bytes have been written so we don't need
1679+
# NOTE: to update the counters, just need to retry.
1680+
continue
16741681
total_sent += result
16751682
left_to_send -= result
16761683

0 commit comments

Comments
 (0)