diff --git a/python/cspdylay.pxd b/python/cspdylay.pxd index a033b1c5..282d6060 100644 --- a/python/cspdylay.pxd +++ b/python/cspdylay.pxd @@ -159,11 +159,20 @@ cdef extern from 'spdylay/spdylay.h': (spdylay_session *session, uint8_t flags, int32_t stream_id, uint8_t *data, size_t len, void *user_data) + ctypedef void (*spdylay_on_stream_close_callback)\ + (spdylay_session *session, int32_t stream_id, + spdylay_status_code status_code, void *user_data) + + ctypedef void (*spdylay_on_request_recv_callback)\ + (spdylay_session *session, int32_t stream_id, void *user_data) + ctypedef struct spdylay_session_callbacks: spdylay_send_callback send_callback spdylay_recv_callback recv_callback spdylay_on_ctrl_recv_callback on_ctrl_recv_callback spdylay_on_data_chunk_recv_callback on_data_chunk_recv_callback + spdylay_on_stream_close_callback on_stream_close_callback + spdylay_on_request_recv_callback on_request_recv_callback int spdylay_session_client_new(spdylay_session **session_ptr, int version, diff --git a/python/spdylay.pyx b/python/spdylay.pyx index be7ac3c3..d00be6c0 100644 --- a/python/spdylay.pyx +++ b/python/spdylay.pyx @@ -326,6 +326,31 @@ cdef void on_data_chunk_recv_callback(cspdylay.spdylay_session *session, except BaseException as e: pysession.base_error = e +cdef void on_stream_close_callback(cspdylay.spdylay_session *session, + int32_t stream_id, + cspdylay.spdylay_status_code status_code, + void *user_data): + cdef Session pysession = user_data + if pysession.on_stream_close_cb: + try: + pysession.on_stream_close_cb(pysession, stream_id, status_code) + except Exception as e: + pysession.error = e + except BaseException as e: + pysession.base_error = e + +cdef void on_request_recv_callback(cspdylay.spdylay_session *session, + int32_t stream_id, + void *user_data): + cdef Session pysession = user_data + if pysession.on_request_recv_cb: + try: + pysession.on_request_recv_cb(pysession, stream_id) + except Exception as e: + pysession.error = e + except BaseException as e: + pysession.base_error = e + 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, @@ -365,7 +390,8 @@ cdef class Session: cdef object send_callback cdef object on_ctrl_recv_cb cdef object on_data_chunk_recv_cb - + cdef object on_stream_close_cb + cdef object on_request_recv_cb cdef object user_data cdef object error @@ -379,6 +405,8 @@ cdef class Session: recv_cb=None, send_cb=None, on_data_chunk_recv_cb=None, on_ctrl_recv_cb=None, + on_stream_close_cb=None, + on_request_recv_cb=None, user_data=None): cdef cspdylay.spdylay_session_callbacks c_session_callbacks cdef int rv @@ -399,8 +427,10 @@ cdef class Session: # c_session_callbacks.on_ctrl_send_callback = NULL # c_session_callbacks.on_ctrl_not_send_callback = NULL # c_session_callbacks.on_data_send_callback = NULL - # c_session_callbacks.on_stream_close_callback = NULL - # c_session_callbacks.on_request_recv_callback = NULL + c_session_callbacks.on_stream_close_callback = \ + on_stream_close_callback + c_session_callbacks.on_request_recv_callback = \ + on_request_recv_callback # c_session_callbacks.get_credential_proof = NULL # c_session_callbacks.get_credential_ncerts = NULL # c_session_callbacks.get_credential_cert = NULL @@ -411,6 +441,9 @@ cdef class Session: self.send_callback = send_cb self.on_data_chunk_recv_cb = on_data_chunk_recv_cb self.on_ctrl_recv_cb = on_ctrl_recv_cb + self.on_stream_close_cb = on_stream_close_cb + self.on_request_recv_cb = on_request_recv_cb + self.user_data = user_data if side == CLIENT: @@ -439,6 +472,8 @@ cdef class Session: recv_cb=None, send_cb=None, on_data_chunk_recv_cb=None, on_ctrl_recv_cb=None, + on_stream_close_cb=None, + on_request_recv_cb=None, user_data=None): pass diff --git a/python/spdyserv.py b/python/spdyserv.py index 6cb1e97b..11a8fb08 100644 --- a/python/spdyserv.py +++ b/python/spdyserv.py @@ -28,10 +28,23 @@ def read_cb(session, stream_id, length, source): def on_ctrl_recv_cb(session, frame): ssctrl = session.user_data if frame.frame_type == spdylay.SYN_STREAM: - # This will crash cookies... - nv = dict(frame.nv) - if b'user-agent' in nv: - user_agent = nv[b'user-agent'].decode('utf-8') + stctrl = StreamCtrl(frame.stream_id) + stctrl.headers.extend(frame.nv) + ssctrl.streams[frame.stream_id] = stctrl + +def on_stream_close_cb(session, stream_id, status_code): + ssctrl = session.user_data + if stream_id in ssctrl.streams: + del ssctrl.streams[stream_id] + +def on_request_recv_cb(session, stream_id): + ssctrl = session.user_data + if stream_id in ssctrl.streams: + stctrl = ssctrl.streams[stream_id] + for name, value in stctrl.headers: + if name == b'user-agent': + user_agent = value.decode('utf-8') + break else: user_agent = '' html = '''\ @@ -47,17 +60,17 @@ def on_ctrl_recv_cb(session, frame): data_prd = spdylay.DataProvider(io.BytesIO(bytes(html, 'utf-8')), read_cb) - stctrl = StreamCtrl(frame.stream_id, data_prd) - ssctrl.streams[frame.stream_id] = stctrl + stctrl.data_prd = data_prd nv = [(b':status', b'200 OK'), (b':version', b'HTTP/1.1'), (b'server', b'python+spdylay')] - session.submit_response(frame.stream_id, nv, data_prd) + session.submit_response(stream_id, nv, data_prd) class StreamCtrl: - def __init__(self, stream_id, data_prd): + def __init__(self, stream_id): self.stream_id = stream_id - self.data_prd = data_prd + self.data_prd = None + self.headers = [] class SessionCtrl: def __init__(self, sock): @@ -83,6 +96,8 @@ class ThreadedSPDYRequestHandler(socketserver.BaseRequestHandler): version, send_cb=send_cb, on_ctrl_recv_cb=on_ctrl_recv_cb, + on_stream_close_cb=on_stream_close_cb, + on_request_recv_cb=on_request_recv_cb, user_data=ssctrl) session.submit_settings(\