Skip to content

Commit 33d0ea4

Browse files
author
taras
committed
WIP
1 parent a308f75 commit 33d0ea4

File tree

6 files changed

+63
-46
lines changed

6 files changed

+63
-46
lines changed

uvloop/handles/pipe.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ cdef class ReadUnixTransport(UVStream):
2525
cdef ReadUnixTransport new(Loop loop, object protocol, Server server,
2626
object waiter)
2727

28+
cpdef write(self, data)
29+
2830

2931
cdef class WriteUnixTransport(UVStream):
3032

uvloop/handles/pipe.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ cdef class ReadUnixTransport(UVStream):
156156
def get_write_buffer_size(self):
157157
raise NotImplementedError
158158

159-
def write(self, data):
159+
cpdef write(self, data):
160160
raise NotImplementedError
161161

162162
def writelines(self, list_of_data):

uvloop/handles/stream.pyx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@ cdef void __uv_stream_buffered_alloc(
931931
try:
932932
(<SSLProtocol>sc._protocol).get_buffer_impl(
933933
suggested_size, &uvbuf.base, &uvbuf.len)
934+
934935
return
935936
except BaseException as exc:
936937
# Can't call 'sc._fatal_error' or 'sc._close', libuv will SF.

uvloop/includes/consts.pxi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ cdef enum:
1515

1616

1717
LOG_THRESHOLD_FOR_CONNLOST_WRITES = 5
18+
19+
SSL_READ_DEFAULT_SIZE = 64 * 1024
1820
SSL_READ_MAX_SIZE = 256 * 1024
1921

2022

uvloop/sslproto.pxd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ cdef class SSLProtocol:
5858
object _incoming_write
5959
object _outgoing
6060
object _outgoing_read
61-
char* _ssl_buffer
62-
size_t _ssl_buffer_len
61+
bytearray _plain_read_buffer
62+
bytearray _ssl_read_buffer
63+
object _ssl_read_max_size_obj
64+
6365
SSLProtocolState _state
6466
size_t _conn_lost
6567
AppProtocolState _app_state

uvloop/sslproto.pyx

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from cpython.bytearray cimport PyByteArray_FromStringAndSize, PyByteArray_AS_STRING, PyByteArray_GET_SIZE, PyByteArray_Resize
2+
from cpython.bytes cimport PyBytes_FromStringAndSize
3+
4+
15
cdef _create_transport_context(server_side, server_hostname):
26
if server_side:
37
raise ValueError('Server side SSL needs a valid SSLContext')
@@ -199,22 +203,12 @@ cdef class SSLProtocol:
199203
buffers which are ssl.MemoryBIO objects.
200204
"""
201205

202-
def __cinit__(self, *args, **kwargs):
203-
self._ssl_buffer_len = SSL_READ_MAX_SIZE
204-
self._ssl_buffer = <char*>PyMem_RawMalloc(self._ssl_buffer_len)
205-
if not self._ssl_buffer:
206-
raise MemoryError()
207-
208-
def __dealloc__(self):
209-
PyMem_RawFree(self._ssl_buffer)
210-
self._ssl_buffer = NULL
211-
self._ssl_buffer_len = 0
212-
213206
def __init__(self, loop, app_protocol, sslcontext, waiter,
214207
server_side=False, server_hostname=None,
215208
call_connection_made=True,
216209
ssl_handshake_timeout=None,
217210
ssl_shutdown_timeout=None):
211+
218212
if ssl_handshake_timeout is None:
219213
ssl_handshake_timeout = SSL_HANDSHAKE_TIMEOUT
220214
elif ssl_handshake_timeout <= 0:
@@ -261,6 +255,11 @@ cdef class SSLProtocol:
261255
self._incoming_write = self._incoming.write
262256
self._outgoing = ssl_MemoryBIO()
263257
self._outgoing_read = self._outgoing.read
258+
259+
self._plain_read_buffer = PyByteArray_FromStringAndSize(
260+
NULL, SSL_READ_DEFAULT_SIZE)
261+
self._ssl_read_max_size_obj = SSL_READ_MAX_SIZE
262+
264263
self._state = UNWRAPPED
265264
self._conn_lost = 0 # Set when connection_lost called
266265
if call_connection_made:
@@ -291,8 +290,12 @@ cdef class SSLProtocol:
291290
self._app_protocol_get_buffer = app_protocol.get_buffer
292291
self._app_protocol_buffer_updated = app_protocol.buffer_updated
293292
self._app_protocol_is_buffer = True
293+
self._ssl_read_buffer = None
294294
else:
295295
self._app_protocol_is_buffer = False
296+
if self._ssl_read_buffer is None:
297+
self._ssl_read_buffer = PyByteArray_FromStringAndSize(
298+
NULL, SSL_READ_MAX_SIZE)
296299

297300
cdef _wakeup_waiter(self, exc=None):
298301
if self._waiter is None:
@@ -356,21 +359,24 @@ cdef class SSLProtocol:
356359
self._handshake_timeout_handle = None
357360

358361
cdef get_buffer_impl(self, size_t n, char** buf, size_t* buf_size):
359-
cdef size_t want = n
360-
if want > SSL_READ_MAX_SIZE:
361-
want = SSL_READ_MAX_SIZE
362-
if self._ssl_buffer_len < want:
363-
self._ssl_buffer = <char*>PyMem_RawRealloc(self._ssl_buffer, want)
364-
if not self._ssl_buffer:
365-
raise MemoryError()
366-
self._ssl_buffer_len = want
367-
368-
buf[0] = self._ssl_buffer
369-
buf_size[0] = self._ssl_buffer_len
362+
cdef Py_ssize_t want = min(<Py_ssize_t>n, SSL_READ_MAX_SIZE)
363+
364+
if len(self._plain_read_buffer) < want:
365+
PyByteArray_Resize(self._plain_read_buffer, want)
366+
if self._ssl_read_buffer is not None:
367+
PyByteArray_Resize(self._ssl_read_buffer, want)
368+
369+
buf[0] = PyByteArray_AS_STRING(self._plain_read_buffer)
370+
buf_size[0] = PyByteArray_GET_SIZE(self._plain_read_buffer)
370371

371372
cdef buffer_updated_impl(self, size_t nbytes):
372-
self._incoming_write(PyMemoryView_FromMemory(
373-
self._ssl_buffer, nbytes, PyBUF_WRITE))
373+
mv = PyMemoryView_FromMemory(
374+
self._plain_read_buffer,
375+
nbytes,
376+
PyBUF_WRITE
377+
)
378+
379+
self._incoming_write(mv)
374380

375381
if self._state == DO_HANDSHAKE:
376382
self._do_handshake()
@@ -597,7 +603,7 @@ cdef class SSLProtocol:
597603
bint close_notify = False
598604
try:
599605
while True:
600-
if not self._sslobj_read(SSL_READ_MAX_SIZE):
606+
if not self._sslobj_read(self._ssl_read_max_size_obj):
601607
close_notify = True
602608
break
603609
except ssl_SSLAgainErrors as exc:
@@ -787,7 +793,7 @@ cdef class SSLProtocol:
787793
PyBUF_WRITE)
788794

789795
last_bytes_read = <Py_ssize_t>self._sslobj_read(
790-
app_buffer_size - total_bytes_read, app_buffer)
796+
self._ssl_read_max_size_obj, app_buffer)
791797
total_bytes_read += last_bytes_read
792798

793799
if last_bytes_read == 0:
@@ -823,32 +829,36 @@ cdef class SSLProtocol:
823829

824830
cdef _do_read__copied(self):
825831
cdef:
826-
list data
827-
bytes first, chunk = b'1'
828-
bint zero = True, one = False
832+
Py_ssize_t bytes_read = -1
833+
list data = None
834+
bytes first_chunk = None, curr_chunk
829835

830836
try:
831837
while (<Py_ssize_t>self._incoming.pending > 0 or
832838
<Py_ssize_t>self._sslobj_pending() > 0):
833-
chunk = self._sslobj_read(SSL_READ_MAX_SIZE)
834-
if not chunk:
839+
bytes_read = self._sslobj_read(
840+
self._ssl_read_max_size_obj,
841+
self._ssl_read_buffer)
842+
if bytes_read == 0:
835843
break
836-
if zero:
837-
zero = False
838-
one = True
839-
first = chunk
840-
elif one:
841-
one = False
842-
data = [first, chunk]
844+
845+
curr_chunk = <bytes> PyBytes_FromStringAndSize(
846+
PyByteArray_AS_STRING(self._ssl_read_buffer), bytes_read)
847+
848+
if first_chunk is None:
849+
first_chunk = curr_chunk
850+
elif data is None:
851+
data = [first_chunk, curr_chunk]
843852
else:
844-
data.append(chunk)
853+
data.append(curr_chunk)
845854
except ssl_SSLAgainErrors as exc:
846855
pass
847-
if one:
848-
self._app_protocol.data_received(first)
849-
elif not zero:
856+
857+
if data is not None:
850858
self._app_protocol.data_received(b''.join(data))
851-
if not chunk:
859+
elif first_chunk is not None:
860+
self._app_protocol.data_received(first_chunk)
861+
elif bytes_read == 0:
852862
# close_notify
853863
self._call_eof_received()
854864
self._start_shutdown()

0 commit comments

Comments
 (0)