Add new error code NGHTTP2_ERR_PAUSE to send_data_callback

If application returns NGHTTP2_ERR_PAUSE from send_data_callback, it
means application processed all data, but wants to make
nghttp2_session_mem_send or nghttp2_session_send return immediately.
This is useful if application writes to fixed sized buffers, and there
is no room to write more data.
This commit is contained in:
Tatsuhiro Tsujikawa 2015-10-03 17:00:16 +09:00
parent da89f9c150
commit 45d4c9dece
2 changed files with 25 additions and 13 deletions

View File

@ -1199,18 +1199,22 @@ typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session,
* The application has to send complete DATA frame in this callback. * The application has to send complete DATA frame in this callback.
* If all data were written successfully, return 0. * If all data were written successfully, return 0.
* *
* If it cannot send it all, just return * If it cannot send any data at all, just return
* :enum:`NGHTTP2_ERR_WOULDBLOCK`; the library will call this callback * :enum:`NGHTTP2_ERR_WOULDBLOCK`; the library will call this callback
* with the same parameters later (It is recommended to send complete * with the same parameters later (It is recommended to send complete
* DATA frame at once in this function to deal with error; if partial * DATA frame at once in this function to deal with error; if partial
* frame data has already sent, it is impossible to send another data * frame data has already sent, it is impossible to send another data
* in that state, and all we can do is tear down connection). If * in that state, and all we can do is tear down connection). When
* application decided to reset this stream, return * data is fully processed, but application wants to make
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then the library * `nghttp2_session_mem_send()` or `nghttp2_session_send()` return
* will send RST_STREAM with INTERNAL_ERROR as error code. The * immediately without processing next frames, return
* application can also return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, * :enum:`NGHTTP2_ERR_PAUSE`. If application decided to reset this
* which will result in connection closure. Returning any other value * stream, return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then
* is treated as :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. * the library will send RST_STREAM with INTERNAL_ERROR as error code.
* The application can also return
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, which will result in
* connection closure. Returning any other value is treated as
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned.
*/ */
typedef int (*nghttp2_send_data_callback)(nghttp2_session *session, typedef int (*nghttp2_send_data_callback)(nghttp2_session *session,
nghttp2_frame *frame, nghttp2_frame *frame,

View File

@ -2610,12 +2610,15 @@ static int session_call_send_data(nghttp2_session *session,
&aux_data->data_prd.source, &aux_data->data_prd.source,
session->user_data); session->user_data);
if (rv == 0 || rv == NGHTTP2_ERR_WOULDBLOCK || switch (rv) {
rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { case 0:
case NGHTTP2_ERR_WOULDBLOCK:
case NGHTTP2_ERR_PAUSE:
case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:
return rv; return rv;
default:
return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session, static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
@ -2790,6 +2793,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
case NGHTTP2_OB_SEND_NO_COPY: { case NGHTTP2_OB_SEND_NO_COPY: {
nghttp2_stream *stream; nghttp2_stream *stream;
nghttp2_frame *frame; nghttp2_frame *frame;
int pause;
DEBUGF(fprintf(stderr, "send: no copy DATA\n")); DEBUGF(fprintf(stderr, "send: no copy DATA\n"));
@ -2833,7 +2837,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
return 0; return 0;
} }
assert(rv == 0); pause = (rv == NGHTTP2_ERR_PAUSE);
rv = session_after_frame_sent1(session); rv = session_after_frame_sent1(session);
if (rv < 0) { if (rv < 0) {
@ -2848,6 +2852,10 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
/* We have already adjusted the next state */ /* We have already adjusted the next state */
if (pause) {
return 0;
}
break; break;
} }
case NGHTTP2_OB_SEND_CLIENT_MAGIC: { case NGHTTP2_OB_SEND_CLIENT_MAGIC: {