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.
* 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
* with the same parameters later (It is recommended to send complete
* 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
* in that state, and all we can do is tear down connection). If
* application decided to reset this stream, return
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then 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.
* in that state, and all we can do is tear down connection). When
* data is fully processed, but application wants to make
* `nghttp2_session_mem_send()` or `nghttp2_session_send()` return
* immediately without processing next frames, return
* :enum:`NGHTTP2_ERR_PAUSE`. If application decided to reset this
* stream, return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then
* 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,
nghttp2_frame *frame,

View File

@ -2610,13 +2610,16 @@ static int session_call_send_data(nghttp2_session *session,
&aux_data->data_prd.source,
session->user_data);
if (rv == 0 || rv == NGHTTP2_ERR_WOULDBLOCK ||
rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
switch (rv) {
case 0:
case NGHTTP2_ERR_WOULDBLOCK:
case NGHTTP2_ERR_PAUSE:
case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:
return rv;
}
default:
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
const uint8_t **data_ptr,
@ -2790,6 +2793,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
case NGHTTP2_OB_SEND_NO_COPY: {
nghttp2_stream *stream;
nghttp2_frame *frame;
int pause;
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;
}
assert(rv == 0);
pause = (rv == NGHTTP2_ERR_PAUSE);
rv = session_after_frame_sent1(session);
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 */
if (pause) {
return 0;
}
break;
}
case NGHTTP2_OB_SEND_CLIENT_MAGIC: {