Read smaller frames to workaround OpenSSL bug
As older versions of OpenSSL (in particular 1.0.2) have limitations on
the size of buffers they can work with, take small views into our larger
buffer and read those in instead. This should keep the buffer sizes more
manageable for OpenSSL.
+import ctypes
import errno
import functools
import logging
@@ -14,6 +15,7 @@ try:
except ImportError:
ssl = None
+from tlz import sliding_window
from tornado import netutil
from tornado.iostream import StreamClosedError
from tornado.tcpclient import TCPClient
@@ -34,6 +36,7 @@ from .utils import ensure_concrete_host, from_frames, get_tcp_server_address, to
logger = logging.getLogger(__name__)
+C_INT_MAX = 256 ** ctypes.sizeof(ctypes.c_int) // 2 - 1
MAX_BUFFER_SIZE = MEMORY_LIMIT / 2
@@ -193,9 +196,15 @@ class TCP(Comm):
frames_nbytes = await stream.read_bytes(fmt_size)
(frames_nbytes,) = struct.unpack(fmt, frames_nbytes)
- frames = bytearray(frames_nbytes)
- n = await stream.read_into(frames)
- assert n == frames_nbytes, (n, frames_nbytes)
+ frames = memoryview(bytearray(frames_nbytes))
+ # Workaround for OpenSSL 1.0.2 (can drop with OpenSSL 1.1.1)
+ for i, j in sliding_window(
+ 2, range(0, frames_nbytes + C_INT_MAX, C_INT_MAX)
+ ):
+ chunk = frames[i:j]
+ chunk_nbytes = len(chunk)
+ n = await stream.read_into(chunk)
+ assert n == chunk_nbytes, (n, chunk_nbytes)
except StreamClosedError as e:
self.stream = None
self._closed = True
