diff --git a/python/spdylay.pyx b/python/spdylay.pyx index 45c3a4ac..cea4383a 100644 --- a/python/spdylay.pyx +++ b/python/spdylay.pyx @@ -417,15 +417,26 @@ cdef void on_request_recv_callback(cspdylay.spdylay_session *session, except BaseException as e: pysession.base_error = e +cdef class ReadCtrl: + cdef int flags + + def __cinit__(self): + self.flags = 0 + + property flags: + def __set__(self, value): + self.flags = value + cdef ssize_t read_callback(cspdylay.spdylay_session *session, int32_t stream_id, uint8_t *buf, size_t length, int *eof, cspdylay.spdylay_data_source *source, void *user_data): cdef Session pysession = user_data + cdef ReadCtrl read_ctrl = ReadCtrl() data_prd = source.ptr try: - res = data_prd.read_cb(pysession, stream_id, length, + res = data_prd.read_cb(pysession, stream_id, length, read_ctrl, data_prd.source) except TemporalCallbackFailureError as e: return cspdylay.SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE @@ -439,6 +450,8 @@ cdef ssize_t read_callback(cspdylay.spdylay_session *session, pysession.base_error = e return cspdylay.SPDYLAY_ERR_CALLBACK_FAILURE + if read_ctrl.flags & READ_EOF: + eof[0] = 1 if res == cspdylay.SPDYLAY_ERR_DEFERRED: return res elif res: @@ -447,7 +460,6 @@ cdef ssize_t read_callback(cspdylay.spdylay_session *session, memcpy(buf, res, len(res)) return len(res) else: - eof[0] = 1 return 0 cdef class Session: @@ -816,6 +828,9 @@ ERR_OK = 0 # Not defined in ERR_EOF = cspdylay.SPDYLAY_ERR_EOF ERR_DEFERRED = cspdylay.SPDYLAY_ERR_DEFERRED +# Read Callback Flags +READ_EOF = 1 + # The status code for RST_STREAM OK = cspdylay.SPDYLAY_OK PROTOCOL_ERROR = cspdylay.SPDYLAY_PROTOCOL_ERROR diff --git a/python/spdylay_tests.py b/python/spdylay_tests.py index 9e6b1f1c..11b8c8cf 100644 --- a/python/spdylay_tests.py +++ b/python/spdylay_tests.py @@ -44,8 +44,11 @@ def send_cb(session, data): iob.outputs.add_buffer(io.BytesIO(data)) return len(data) -def read_cb(session, stream_id, length, source): - return source.read(length) +def read_cb(session, stream_id, length, read_ctrl, source): + data = source.read(length) + if not data: + read_ctrl.flags = spdylay.READ_EOF + return data def on_data_chunk_recv_cb(session, flags, stream_id, data): session.user_data.recv_data.write(data) @@ -191,7 +194,7 @@ class SpdylayTests(unittest.TestCase): self.assertFalse(self.client_session.want_write()) def test_deferred_data(self): - def deferred_read_cb(session, stream_id, length, source): + def deferred_read_cb(session, stream_id, length, read_ctrl, source): return spdylay.ERR_DEFERRED data_prd = spdylay.DataProvider(io.BytesIO(b'Hello World'), diff --git a/python/spdyserv.py b/python/spdyserv.py index 11a8fb08..8305f49a 100644 --- a/python/spdyserv.py +++ b/python/spdyserv.py @@ -22,8 +22,11 @@ def send_cb(session, data): ssctrl.sock.sendall(data) return len(data) -def read_cb(session, stream_id, length, source): - return source.read(length) +def read_cb(session, stream_id, length, read_ctrl, source): + data = source.read(length) + if not data: + read_ctrl.flags = spdylay.READ_EOF + return data def on_ctrl_recv_cb(session, frame): ssctrl = session.user_data