diff --git a/doc/python.rst b/doc/python.rst index afb9ce0..268c858 100644 --- a/doc/python.rst +++ b/doc/python.rst @@ -19,7 +19,7 @@ To build extension, run ``setup.py``:: Session Objects --------------- -.. py:class:: Session(side, version, config=None, send_cb=None, recv_cb=None, on_ctrl_recv_cb=None, on_data_chunk_recv_cb=None, on_stream_close_cb=None, on_request_recv_cb=None, user_data=None) +.. py:class:: Session(side, version, config=None, send_cb=None, recv_cb=None, on_ctrl_recv_cb=None, on_invalid_ctrl_recv_cb=None, on_data_chunk_recv_cb=None, on_data_recv_cb=None, before_ctrl_send_cb=None, on_ctrl_send_cb=None, on_ctrl_not_send_cb=None, on_data_send_cb=None, on_stream_close_cb=None, on_request_recv_cb=None, on_ctrl_recv_parse_error_cb=None, on_unknown_ctrl_recv_cb=None, user_data=None) This is the class to hold the resources needed for a SPDY session. Sending and receiving SPDY frames are done using the methods of @@ -88,6 +88,20 @@ Session Objects identified, access attribute of the *frame* to get information. + The *on_invalid_ctrl_recv_cb* specifies callback function + (callable) invoked when an invalid control frame is received. + + .. py:function:: on_invalid_ctrl_recv_cb(session, frame, status_code) + + The *session* is the :py:class:`Session` object invoking the + callback. The *frame* is the received control + frame. ``frame.frame_type`` tells the type of frame. See + `Frame Types`_ for the details. Once the frame type is + identified, access attribute of the *frame* to get + information. The *status_code* is one of the `Stream Status + Codes`_ and indicates the error. When this callback function + is invoked, either RST_STREAM or GOAWAY will be sent. + The *on_data_chunk_recv_cb* specifies callback function (callable) invoked when a chunk of data in DATA frame is received. @@ -102,6 +116,54 @@ Session Objects data frames are received. The *data* is the bytestring of received data. + The *on_data_recv_cb* specifies callback function (callable) + invoked when DATA frame is received. + + .. py:function:: on_data_recv_cb(session, flags, stream_id, length) + + The actual data it contains are received by + :py:func:`on_data_chunk_recv_cb()`. + + The *before_ctrl_send_cb* specifies callback function (callable) + invoked before the control frame is sent. + + .. py:function:: before_ctrl_send_cb(session, frame) + + The *session* is the :py:class:`Session` object invoking the + callback. The *frame* is the control frame to be + sent. ``frame.frame_type`` tells the type of frame. See `Frame + Types`_ for the details. Once the frame type is identified, + access attribute of the *frame* to get information. + + The *on_ctrl_send_cb* specifies callback function (callable) + invoked after the control frame is sent. + + .. py:function:: on_ctrl_send_cb(session, frame) + + The *session* is the :py:class:`Session` object invoking the + callback. The *frame* is the control frame to be + sent. ``frame.frame_type`` tells the type of frame. See `Frame + Types`_ for the details. Once the frame type is identified, + access attribute of the *frame* to get information. + + The *on_ctrl_not_send_cb* specifies callback function (callable) + after the control frame is not sent because of the error. + + .. py:function:: on_ctrl_not_send_cb(session, frame, error_code) + + The *session* is the :py:class:`Session` object invoking the + callback. The *frame* is the received control + frame. ``frame.frame_type`` tells the type of frame. See + `Frame Types`_ for the details. Once the frame type is + identified, access attribute of the *frame* to get + information. The *error_code* is one of the `Error Codes`_ + and indicates the error. + + The *on_data_send_cb* specifies callback function (callable) + invoked after DATA frame is sent. + + .. py:function:: on_data_send_cb(session, flags, stream_id, length) + The *on_stream_close_cb* specifies callback function (callable) invoked when the stream is closed. @@ -126,10 +188,33 @@ Session Objects The *session* is the :py:class:`Session` object invoking the callback. The *stream_id* indicates the stream ID. + The *on_ctrl_recv_parse_error_cb* specifies callback function + (callable) invoked when the received control frame octets could + not be parsed correctly. - The :py:class:`UnsupportedVersionError` will be raised if the - *version* is not supported. The :py:class:`ZlibError` will be - raised if initialization of zlib failed. + .. py:function:: on_ctrl_recv_parse_error_cb(session, type, head, payload, error_code) + + The *type* indicates the type of received control frame. The + *head* is the bytestring of control frame header. The + *payload* is the bytestring of data portion of the received + frame. The *error_code* is one of the error code defined in + `Error Codes`_ and indicates the error. + + The *on_unknown_ctrl_recv_cb* specifies callback function + (callable) invoked when the received control frame type is + unknown. + + .. py:function:: on_unknown_ctrl_recv_cb(session, head, payload) + + The *head* is the bytestring of control frame header. The + *payload* is the bytestring of data portion of the received + frame. + + The :py:class:`InvalidArgumentError` will be raised if the given + argument is invalid. The :py:class:`UnsupportedVersionError` will + be raised if the *version* is not supported. The + :py:class:`ZlibError` will be raised if initialization of zlib + failed. .. py:attribute:: Session.user_data @@ -499,10 +584,36 @@ Read Callback Flags .. py:data:: READ_EOF -Callback Error Codes --------------------- +Error Codes +----------- +.. py:data:: ERR_INVALID_ARGUMENT +.. py:data:: ERR_ZLIB +.. py:data:: ERR_UNSUPPORTED_VERSION +.. py:data:: ERR_WOULDBLOCK +.. py:data:: ERR_PROTO +.. py:data:: ERR_INVALID_FRAME +.. py:data:: ERR_EOF .. py:data:: ERR_DEFERRED +.. py:data:: ERR_STREAM_ID_NOT_AVAILABLE +.. py:data:: ERR_STREAM_CLOSED +.. py:data:: ERR_STREAM_CLOSING +.. py:data:: ERR_STREAM_SHUT_WR +.. py:data:: ERR_INVALID_STREAM_ID +.. py:data:: ERR_INVALID_STREAM_STATE +.. py:data:: ERR_DEFERRED_DATA_EXIST +.. py:data:: ERR_SYN_STREAM_NOT_ALLOWED +.. py:data:: ERR_GOAWAY_ALREADY_SENT +.. py:data:: ERR_INVALID_HEADER_BLOCK +.. py:data:: ERR_INVALID_STATE +.. py:data:: ERR_GZIP +.. py:data:: ERR_TEMPORAL_CALLBACK_FAILURE + +Following error codes indicate fatal error. + +.. py:data:: ERR_FATAL +.. py:data:: ERR_NOMEM +.. py:data:: ERR_CALLBACK_FAILURE Frame Types ----------- diff --git a/python/cspdylay.pxd b/python/cspdylay.pxd index f993e32..395575e 100644 --- a/python/cspdylay.pxd +++ b/python/cspdylay.pxd @@ -11,10 +11,24 @@ cdef extern from 'spdylay/spdylay.h': SPDYLAY_ERR_ZLIB SPDYLAY_ERR_UNSUPPORTED_VERSION SPDYLAY_ERR_WOULDBLOCK + SPDYLAY_ERR_PROTO + SPDYLAY_ERR_INVALID_FRAME SPDYLAY_ERR_EOF SPDYLAY_ERR_DEFERRED + SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE + SPDYLAY_ERR_STREAM_CLOSED + SPDYLAY_ERR_STREAM_CLOSING + SPDYLAY_ERR_STREAM_SHUT_WR + SPDYLAY_ERR_INVALID_STREAM_ID + SPDYLAY_ERR_INVALID_STREAM_STATE + SPDYLAY_ERR_DEFERRED_DATA_EXIST + SPDYLAY_ERR_SYN_STREAM_NOT_ALLOWED + SPDYLAY_ERR_GOAWAY_ALREADY_SENT + SPDYLAY_ERR_INVALID_HEADER_BLOCK + SPDYLAY_ERR_INVALID_STATE + SPDYLAY_ERR_GZIP SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE - # Fatal errors follow + SPDYLAY_ERR_FATAL SPDYLAY_ERR_NOMEM SPDYLAY_ERR_CALLBACK_FAILURE @@ -173,10 +187,34 @@ cdef extern from 'spdylay/spdylay.h': (spdylay_session *session, spdylay_frame_type frame_type, spdylay_frame *frame, void *user_data) + ctypedef void (*spdylay_on_invalid_ctrl_recv_callback)\ + (spdylay_session *session, spdylay_frame_type type, + spdylay_frame *frame, uint32_t status_code, void *user_data) + ctypedef void (*spdylay_on_data_chunk_recv_callback)\ (spdylay_session *session, uint8_t flags, int32_t stream_id, uint8_t *data, size_t len, void *user_data) + ctypedef void (*spdylay_on_data_recv_callback)\ + (spdylay_session *session, uint8_t flags, int32_t stream_id, + int32_t length, void *user_data) + + ctypedef void (*spdylay_before_ctrl_send_callback)\ + (spdylay_session *session, spdylay_frame_type type, + spdylay_frame *frame, void *user_data) + + ctypedef void (*spdylay_on_ctrl_send_callback)\ + (spdylay_session *session, spdylay_frame_type type, + spdylay_frame *frame, void *user_data) + + ctypedef void (*spdylay_on_ctrl_not_send_callback)\ + (spdylay_session *session, spdylay_frame_type type, + spdylay_frame *frame, int error_code, void *user_data) + + ctypedef void (*spdylay_on_data_send_callback)\ + (spdylay_session *session, uint8_t flags, int32_t stream_id, + int32_t length, 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) @@ -184,13 +222,31 @@ cdef extern from 'spdylay/spdylay.h': ctypedef void (*spdylay_on_request_recv_callback)\ (spdylay_session *session, int32_t stream_id, void *user_data) + ctypedef void (*spdylay_on_ctrl_recv_parse_error_callback)\ + (spdylay_session *session, spdylay_frame_type type, + uint8_t *head, size_t headlen, uint8_t *payload, size_t payloadlen, + int error_code, void *user_data) + + ctypedef void (*spdylay_on_unknown_ctrl_recv_callback)\ + (spdylay_session *session, uint8_t *head, size_t headlen, + uint8_t *payload, size_t payloadlen, 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_invalid_ctrl_recv_callback on_invalid_ctrl_recv_callback spdylay_on_data_chunk_recv_callback on_data_chunk_recv_callback + spdylay_on_data_recv_callback on_data_recv_callback + spdylay_before_ctrl_send_callback before_ctrl_send_callback + spdylay_on_ctrl_send_callback on_ctrl_send_callback + spdylay_on_ctrl_not_send_callback on_ctrl_not_send_callback + spdylay_on_data_send_callback on_data_send_callback spdylay_on_stream_close_callback on_stream_close_callback spdylay_on_request_recv_callback on_request_recv_callback + spdylay_on_ctrl_recv_parse_error_callback \ + on_ctrl_recv_parse_error_callback + spdylay_on_unknown_ctrl_recv_callback on_unknown_ctrl_recv_callback int spdylay_session_client_new(spdylay_session **session_ptr, int version, diff --git a/python/spdylay.pyx b/python/spdylay.pyx index cea4383..529c1a3 100644 --- a/python/spdylay.pyx +++ b/python/spdylay.pyx @@ -263,10 +263,9 @@ cdef cspdylay.spdylay_data_provider create_c_data_prd\ cdata_prd.source.ptr = pydata_prd cdata_prd.read_callback = read_callback -cdef void on_ctrl_recv_callback(cspdylay.spdylay_session *session, - cspdylay.spdylay_frame_type frame_type, - cspdylay.spdylay_frame *frame, - void *user_data): + +cdef object cframe2pyframe(cspdylay.spdylay_frame_type frame_type, + cspdylay.spdylay_frame *frame): cdef SynStreamFrame syn_stream cdef SynReplyFrame syn_reply cdef HeadersFrame headers @@ -275,13 +274,7 @@ cdef void on_ctrl_recv_callback(cspdylay.spdylay_session *session, cdef PingFrame ping cdef GoawayFrame goaway cdef WindowUpdateFrame window_update - - cdef Session pysession = user_data - - if not pysession.on_ctrl_recv_cb: - return - - pyframe = None + cdef object pyframe = None if frame_type == cspdylay.SPDYLAY_SYN_STREAM: syn_stream = SynStreamFrame() syn_stream.fill(&frame.syn_stream) @@ -314,15 +307,120 @@ cdef void on_ctrl_recv_callback(cspdylay.spdylay_session *session, window_update = WindowUpdateFrame() window_update.fill(&frame.window_update) pyframe = window_update + return pyframe +cdef void _call_frame_callback(Session pysession, + cspdylay.spdylay_frame_type frame_type, + cspdylay.spdylay_frame *frame, + object callback): + if not callback: + return + pyframe = cframe2pyframe(frame_type, frame) if pyframe: try: - pysession.on_ctrl_recv_cb(pysession, pyframe) + callback(pysession, pyframe) except Exception as e: pysession.error = e except BaseException as e: pysession.base_error = e +cdef void on_ctrl_recv_callback(cspdylay.spdylay_session *session, + cspdylay.spdylay_frame_type frame_type, + cspdylay.spdylay_frame *frame, + void *user_data): + cdef Session pysession = user_data + _call_frame_callback(pysession, frame_type, frame, + pysession.on_ctrl_recv_cb) + +cdef void on_invalid_ctrl_recv_callback(cspdylay.spdylay_session *session, + cspdylay.spdylay_frame_type frame_type, + cspdylay.spdylay_frame *frame, + uint32_t status_code, + void *user_data): + cdef Session pysession = user_data + + if not pysession.on_invalid_ctrl_recv_cb: + return + pyframe = cframe2pyframe(frame_type, frame) + if pyframe: + try: + pysession.on_invalid_ctrl_recv_cb(pysession, pyframe, status_code) + except Exception as e: + pysession.error = e + except BaseException as e: + pysession.base_error = e + +cdef void before_ctrl_send_callback(cspdylay.spdylay_session *session, + cspdylay.spdylay_frame_type frame_type, + cspdylay.spdylay_frame *frame, + void *user_data): + cdef Session pysession = user_data + _call_frame_callback(pysession, frame_type, frame, + pysession.before_ctrl_send_cb) + +cdef void on_ctrl_send_callback(cspdylay.spdylay_session *session, + cspdylay.spdylay_frame_type frame_type, + cspdylay.spdylay_frame *frame, + void *user_data): + cdef Session pysession = user_data + _call_frame_callback(pysession, frame_type, frame, + pysession.on_ctrl_send_cb) + +cdef void on_ctrl_not_send_callback(cspdylay.spdylay_session *session, + cspdylay.spdylay_frame_type frame_type, + cspdylay.spdylay_frame *frame, + int error_code, + void *user_data): + cdef Session pysession = user_data + + if not pysession.on_ctrl_not_send_cb: + return + pyframe = cframe2pyframe(frame_type, frame) + if pyframe: + try: + pysession.on_ctrl_not_send_cb(pysession, pyframe, error_code) + except Exception as e: + pysession.error = e + except BaseException as e: + pysession.base_error = e + +cdef void on_ctrl_recv_parse_error_callback(\ + cspdylay.spdylay_session *session, + cspdylay.spdylay_frame_type frame_type, + uint8_t *head, size_t headlen, + uint8_t *payload, size_t payloadlen, + int error_code, void *user_data): + cdef Session pysession = user_data + + if not pysession.on_ctrl_recv_parse_error_cb: + return + try: + pysession.on_ctrl_recv_parse_error_cb(pysession, frame_type, + (head)[:headlen], + (payload)[:payloadlen], + error_code) + except Exception as e: + pysession.error = e + except BaseException as e: + pysession.base_error = e + +cdef void on_unknown_ctrl_recv_callback(cspdylay.spdylay_session *session, + uint8_t *head, size_t headlen, + uint8_t *payload, size_t payloadlen, + void *user_data): + cdef Session pysession = user_data + + if not pysession.on_unknown_ctrl_recv_cb: + return + try: + pysession.on_unknown_ctrl_recv_cb(pysession, + (head)[:headlen], + (payload)[:payloadlen]) + except Exception as e: + pysession.error = e + except BaseException as e: + pysession.base_error = e + cdef ssize_t recv_callback(cspdylay.spdylay_session *session, uint8_t *buf, size_t length, int flags, void *user_data): @@ -392,6 +490,30 @@ cdef void on_data_chunk_recv_callback(cspdylay.spdylay_session *session, except BaseException as e: pysession.base_error = e +cdef void on_data_recv_callback(cspdylay.spdylay_session *session, + uint8_t flags, int32_t stream_id, + int32_t length, void *user_data): + cdef Session pysession = user_data + if pysession.on_data_recv_cb: + try: + pysession.on_data_recv_cb(pysession, flags, stream_id, length) + except Exception as e: + pysession.error = e + except BaseException as e: + pysession.base_error = e + +cdef void on_data_send_callback(cspdylay.spdylay_session *session, + uint8_t flags, int32_t stream_id, + int32_t length, void *user_data): + cdef Session pysession = user_data + if pysession.on_data_send_cb: + try: + pysession.on_data_send_cb(pysession, flags, stream_id, length) + except Exception as e: + pysession.error = e + 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, @@ -467,9 +589,17 @@ cdef class Session: cdef object recv_callback cdef object send_callback cdef object on_ctrl_recv_cb + cdef object on_invalid_ctrl_recv_cb cdef object on_data_chunk_recv_cb + cdef object on_data_recv_cb + cdef object before_ctrl_send_cb + cdef object on_ctrl_send_cb + cdef object on_ctrl_not_send_cb + cdef object on_data_send_cb cdef object on_stream_close_cb cdef object on_request_recv_cb + cdef object on_ctrl_recv_parse_error_cb + cdef object on_unknown_ctrl_recv_cb cdef object user_data cdef object error @@ -482,9 +612,17 @@ cdef class Session: def __cinit__(self, side, version, config=None, send_cb=None, recv_cb=None, on_ctrl_recv_cb=None, + on_invalid_ctrl_recv_cb=None, on_data_chunk_recv_cb=None, + on_data_recv_cb=None, + before_ctrl_send_cb=None, + on_ctrl_send_cb=None, + on_ctrl_not_send_cb=None, + on_data_send_cb=None, on_stream_close_cb=None, on_request_recv_cb=None, + on_ctrl_recv_parse_error_cb=None, + on_unknown_ctrl_recv_cb=None, user_data=None): cdef cspdylay.spdylay_session_callbacks c_session_callbacks cdef int rv @@ -496,15 +634,24 @@ cdef class Session: send_callback c_session_callbacks.on_ctrl_recv_callback = \ on_ctrl_recv_callback - # c_session_callbacks.on_invalid_ctrl_recv_callback = NULL + c_session_callbacks.on_invalid_ctrl_recv_callback = \ + \ + on_invalid_ctrl_recv_callback c_session_callbacks.on_data_chunk_recv_callback = \ \ on_data_chunk_recv_callback - # c_session_callbacks.on_data_recv_callback = NULL - # c_session_callbacks.before_ctrl_send_callback = NULL - # 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_data_recv_callback = \ + on_data_recv_callback + c_session_callbacks.before_ctrl_send_callback = \ + \ + before_ctrl_send_callback + c_session_callbacks.on_ctrl_send_callback = \ + on_ctrl_send_callback + c_session_callbacks.on_ctrl_not_send_callback = \ + \ + on_ctrl_not_send_callback + c_session_callbacks.on_data_send_callback = \ + on_data_send_callback c_session_callbacks.on_stream_close_callback = \ on_stream_close_callback c_session_callbacks.on_request_recv_callback = \ @@ -512,15 +659,27 @@ cdef class Session: # c_session_callbacks.get_credential_proof = NULL # c_session_callbacks.get_credential_ncerts = NULL # c_session_callbacks.get_credential_cert = NULL - # c_session_callbacks.on_ctrl_recv_parse_error_callback = NULL - # c_session_callbacks.on_unknown_ctrl_recv_callback = NULL + c_session_callbacks.on_ctrl_recv_parse_error_callback = \ + \ + on_ctrl_recv_parse_error_callback + c_session_callbacks.on_unknown_ctrl_recv_callback = \ + \ + on_unknown_ctrl_recv_callback self.recv_callback = recv_cb 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_invalid_ctrl_recv_cb = on_invalid_ctrl_recv_cb + self.on_data_chunk_recv_cb = on_data_chunk_recv_cb + self.on_data_recv_cb = on_data_recv_cb + self.before_ctrl_send_cb = before_ctrl_send_cb + self.on_ctrl_send_cb = on_ctrl_send_cb + self.on_ctrl_not_send_cb = on_ctrl_not_send_cb + self.on_data_send_cb = on_data_send_cb self.on_stream_close_cb = on_stream_close_cb self.on_request_recv_cb = on_request_recv_cb + self.on_ctrl_recv_parse_error_cb = on_ctrl_recv_parse_error_cb + self.on_unknown_ctrl_recv_cb = on_unknown_ctrl_recv_cb self.user_data = user_data @@ -549,9 +708,16 @@ cdef class Session: def __init__(self, side, version, config=None, send_cb=None, recv_cb=None, on_ctrl_recv_cb=None, + on_invalid_ctrl_recv_cb=None, on_data_chunk_recv_cb=None, + on_data_recv_cb=None, + before_ctrl_send_cb=None, + on_ctrl_send_cb=None, + on_ctrl_not_send_cb=None, + on_data_send_cb=None, on_stream_close_cb=None, on_request_recv_cb=None, + on_ctrl_recv_parse_error_cb=None, user_data=None): pass @@ -636,19 +802,6 @@ cdef class Session: raise MemoryError() cpdef submit_request(self, pri, nv, data_prd=None, stream_user_data=None): - ''' Submits frame and optionally one or more DATA frames. If - data_prd is not None, it provides data which will be sent in - subsequent DATA frames. It must have 2 attributes: source and - read_cb. source is an opaque object and passed to read_cb - callback. read_cb must be None or a callable object. The - library calls it when it needs data. 4 arguments are passed to - read_cb: session, stream_id, length and source. And it returns - at most length bytes of byte string. The session is self. The - stream_id is the stream ID of the stream. The length is the - maximum length the library expects. read_cb must not return - more that length bytes. The source is the object passed in - data_prd.source. - ''' cdef cspdylay.spdylay_data_provider c_data_prd cdef cspdylay.spdylay_data_provider *c_data_prd_ptr cdef char **cnv = pynv2cnv(nv) @@ -823,10 +976,31 @@ CTRL_FLAG_UNIDIRECTIONAL = cspdylay.SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL DATA_FLAG_NONE = cspdylay.SPDYLAY_DATA_FLAG_NONE DATA_FLAG_FIN = cspdylay.SPDYLAY_DATA_FLAG_FIN -# Error codes used in callback -ERR_OK = 0 # Not defined in +# Error codes +ERR_INVALID_ARGUMENT = cspdylay.SPDYLAY_ERR_INVALID_ARGUMENT +ERR_ZLIB = cspdylay.SPDYLAY_ERR_ZLIB +ERR_UNSUPPORTED_VERSION = cspdylay.SPDYLAY_ERR_UNSUPPORTED_VERSION +ERR_WOULDBLOCK = cspdylay.SPDYLAY_ERR_WOULDBLOCK +ERR_PROTO = cspdylay.SPDYLAY_ERR_PROTO +ERR_INVALID_FRAME = cspdylay.SPDYLAY_ERR_INVALID_FRAME ERR_EOF = cspdylay.SPDYLAY_ERR_EOF ERR_DEFERRED = cspdylay.SPDYLAY_ERR_DEFERRED +ERR_STREAM_ID_NOT_AVAILABLE = cspdylay.SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE +ERR_STREAM_CLOSED = cspdylay.SPDYLAY_ERR_STREAM_CLOSED +ERR_STREAM_CLOSING = cspdylay.SPDYLAY_ERR_STREAM_CLOSING +ERR_STREAM_SHUT_WR = cspdylay.SPDYLAY_ERR_STREAM_SHUT_WR +ERR_INVALID_STREAM_ID = cspdylay.SPDYLAY_ERR_INVALID_STREAM_ID +ERR_INVALID_STREAM_STATE = cspdylay.SPDYLAY_ERR_INVALID_STREAM_STATE +ERR_DEFERRED_DATA_EXIST = cspdylay.SPDYLAY_ERR_DEFERRED_DATA_EXIST +ERR_SYN_STREAM_NOT_ALLOWED = cspdylay.SPDYLAY_ERR_SYN_STREAM_NOT_ALLOWED +ERR_GOAWAY_ALREADY_SENT = cspdylay.SPDYLAY_ERR_GOAWAY_ALREADY_SENT +ERR_INVALID_HEADER_BLOCK = cspdylay.SPDYLAY_ERR_INVALID_HEADER_BLOCK +ERR_INVALID_STATE = cspdylay.SPDYLAY_ERR_INVALID_STATE +ERR_GZIP = cspdylay.SPDYLAY_ERR_GZIP +ERR_TEMPORAL_CALLBACK_FAILURE = cspdylay.SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE +ERR_FATAL = cspdylay.SPDYLAY_ERR_FATAL +ERR_NOMEM = cspdylay.SPDYLAY_ERR_NOMEM +ERR_CALLBACK_FAILURE = cspdylay.SPDYLAY_ERR_CALLBACK_FAILURE # Read Callback Flags READ_EOF = 1