From e7ad3633c7c0d35dd85292e6c20a48320de8f720 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 5 Apr 2014 17:59:24 +0900 Subject: [PATCH] nghttp2_data_source_read_callback: Replace eof with uint32_t *data_flags Replace int *eof with uint32_t *data_flags so that we can easily extend functionality if we have to (but we don't do if possible). --- examples/libevent-server.c | 4 +-- lib/includes/nghttp2/nghttp2.h | 42 +++++++++++++++++------- lib/nghttp2_session.c | 8 ++--- src/HttpServer.cc | 4 +-- src/nghttp.cc | 4 +-- src/shrpx_http2_downstream_connection.cc | 6 ++-- src/shrpx_http2_upstream.cc | 8 ++--- tests/nghttp2_session_test.c | 10 +++--- 8 files changed, 52 insertions(+), 34 deletions(-) diff --git a/examples/libevent-server.c b/examples/libevent-server.c index 13609462..7303ecf6 100644 --- a/examples/libevent-server.c +++ b/examples/libevent-server.c @@ -328,7 +328,7 @@ static char* percent_decode(const uint8_t *value, size_t valuelen) static ssize_t file_read_callback (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t length, int *eof, + uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { int fd = source->fd; @@ -338,7 +338,7 @@ static ssize_t file_read_callback return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } if(r == 0) { - *eof = 1; + *data_flags |= NGHTTP2_DATA_FLAG_EOF; } return r; } diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 42d0ed1b..82958982 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -621,6 +621,23 @@ typedef union { void *ptr; } nghttp2_data_source; +/** + * @enum + * + * The flags used to set in |data_flags| output parameter in + * :type:`nghttp2_data_source_read_callback`. + */ +typedef enum { + /** + * No flag set. + */ + NGHTTP2_DATA_FLAG_NONE = 0, + /** + * Indicates EOF was sensed. + */ + NGHTTP2_DATA_FLAG_EOF = 0x01 +} nghttp2_data_flag; + /** * @functypedef * @@ -629,21 +646,22 @@ typedef union { * implementation of this function must read at most |length| bytes of * data from |source| (or possibly other places) and store them in * |buf| and return number of data stored in |buf|. If EOF is reached, - * set |*eof| to 1. If the application wants to postpone DATA frames, - * (e.g., asynchronous I/O, or reading data blocks for long time), it - * is achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without - * reading any data in this invocation. The library removes DATA - * frame from the outgoing queue temporarily. To move back deferred - * DATA frame to outgoing queue, call `nghttp2_session_resume_data()`. - * In case of error, there are 2 choices. Returning - * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream - * by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. - * Returning :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the - * entire session failure. + * set :enum:`NGHTTP2_DATA_FLAG_EOF` flag in |*data_falgs|. If the + * application wants to postpone DATA frames, (e.g., asynchronous I/O, + * or reading data blocks for long time), it is achieved by returning + * :enum:`NGHTTP2_ERR_DEFERRED` without reading any data in this + * invocation. The library removes DATA frame from the outgoing queue + * temporarily. To move back deferred DATA frame to outgoing queue, + * call `nghttp2_session_resume_data()`. In case of error, there are + * 2 choices. Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` + * will close the stream by issuing RST_STREAM with + * :enum:`NGHTTP2_INTERNAL_ERROR`. Returning + * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session + * failure. */ typedef ssize_t (*nghttp2_data_source_read_callback) (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t length, int *eof, + uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data); /** diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index fae49a1e..ec02f0db 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -5388,7 +5388,7 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_private_data *frame) { ssize_t rv; - int eof_flags; + uint32_t data_flags; uint8_t flags; ssize_t payloadlen; ssize_t padded_payloadlen; @@ -5404,10 +5404,10 @@ int nghttp2_session_pack_data(nghttp2_session *session, /* Current max DATA length is less then buffer chunk size */ assert(nghttp2_buf_avail(buf) >= (ssize_t)datamax); - eof_flags = 0; + data_flags = NGHTTP2_DATA_FLAG_NONE; payloadlen = frame->data_prd.read_callback (session, frame->hd.stream_id, buf->pos, datamax, - &eof_flags, &frame->data_prd.source, session->user_data); + &data_flags, &frame->data_prd.source, session->user_data); if(payloadlen == NGHTTP2_ERR_DEFERRED || payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) { @@ -5430,7 +5430,7 @@ int nghttp2_session_pack_data(nghttp2_session *session, frame->hd.flags &= (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT); flags = NGHTTP2_FLAG_NONE; - if(eof_flags) { + if(data_flags & NGHTTP2_DATA_FLAG_EOF) { frame->eof = 1; if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) { flags |= NGHTTP2_FLAG_END_STREAM; diff --git a/src/HttpServer.cc b/src/HttpServer.cc index fe5e1e71..78292e9c 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -922,7 +922,7 @@ void Http2Handler::terminate_session(nghttp2_error_code error_code) ssize_t file_read_callback (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t length, int *eof, + uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { auto hd = static_cast(user_data); @@ -942,7 +942,7 @@ ssize_t file_read_callback } if(r == 0) { - *eof = 1; + *data_flags |= NGHTTP2_DATA_FLAG_EOF; } return r; diff --git a/src/nghttp.cc b/src/nghttp.cc index 0852c73b..8c6c667e 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -1669,7 +1669,7 @@ int communicate(const std::string& scheme, const std::string& host, namespace { ssize_t file_read_callback (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t length, int *eof, + uint8_t *buf, size_t length, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { auto req = (Request*)nghttp2_session_get_stream_user_data @@ -1683,7 +1683,7 @@ ssize_t file_read_callback return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } else { if(r == 0) { - *eof = 1; + *data_flags |= NGHTTP2_DATA_FLAG_EOF; } else { req->data_offset += r; } diff --git a/src/shrpx_http2_downstream_connection.cc b/src/shrpx_http2_downstream_connection.cc index e47d99df..96d25002 100644 --- a/src/shrpx_http2_downstream_connection.cc +++ b/src/shrpx_http2_downstream_connection.cc @@ -154,7 +154,7 @@ namespace { ssize_t http2_data_read_callback(nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, - int *eof, + uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { @@ -183,7 +183,7 @@ ssize_t http2_data_read_callback(nghttp2_session *session, if(!downstream->get_upgrade_request() || (downstream->get_response_state() == Downstream::HEADER_COMPLETE && !downstream->get_upgraded())) { - *eof = 1; + *data_flags |= NGHTTP2_DATA_FLAG_EOF; } else { return NGHTTP2_ERR_DEFERRED; } @@ -204,7 +204,7 @@ ssize_t http2_data_read_callback(nghttp2_session *session, if(evbuffer_get_length(body) == 0) { // Check get_request_state() == MSG_COMPLETE just in case if(downstream->get_request_state() == Downstream::MSG_COMPLETE) { - *eof = 1; + *data_flags |= NGHTTP2_DATA_FLAG_EOF; break; } return NGHTTP2_ERR_DEFERRED; diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 5d7bfbbe..dba024c0 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -891,7 +891,7 @@ namespace { ssize_t downstream_data_read_callback(nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length, - int *eof, + uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { @@ -910,7 +910,7 @@ ssize_t downstream_data_read_callback(nghttp2_session *session, if(nread == 0 && downstream->get_response_state() == Downstream::MSG_COMPLETE) { if(!downstream->get_upgraded()) { - *eof = 1; + *data_flags |= NGHTTP2_DATA_FLAG_EOF; } else { // For tunneling, issue RST_STREAM to finish the stream. if(LOG_ENABLED(INFO)) { @@ -923,14 +923,14 @@ ssize_t downstream_data_read_callback(nghttp2_session *session, } // Send WINDOW_UPDATE before buffer is empty to avoid delay because // of RTT. - if(*eof != 1 && + if(((*data_flags) & NGHTTP2_DATA_FLAG_EOF) == 0 && handler->get_outbuf_length() + evbuffer_get_length(body) < OUTBUF_MAX_THRES) { if(downstream->resume_read(SHRPX_NO_BUFFER) != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } } - if(nread == 0 && *eof != 1) { + if(nread == 0 && ((*data_flags) & NGHTTP2_DATA_FLAG_EOF) == 0) { return NGHTTP2_ERR_DEFERRED; } return nread; diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 83f824fc..ad6c7a31 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -232,7 +232,7 @@ static ssize_t select_padding_callback(nghttp2_session *session, static ssize_t fixed_length_data_source_read_callback (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t len, int *eof, + uint8_t *buf, size_t len, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { my_user_data *ud = (my_user_data*)user_data; @@ -244,14 +244,14 @@ static ssize_t fixed_length_data_source_read_callback } ud->data_source_length -= wlen; if(ud->data_source_length == 0) { - *eof = 1; + *data_flags |= NGHTTP2_DATA_FLAG_EOF; } return wlen; } static ssize_t temporal_failure_data_source_read_callback (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t len, int *eof, + uint8_t *buf, size_t len, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; @@ -259,7 +259,7 @@ static ssize_t temporal_failure_data_source_read_callback static ssize_t fail_data_source_read_callback (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t len, int *eof, + uint8_t *buf, size_t len, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -332,7 +332,7 @@ static int on_begin_headers_callback(nghttp2_session *session, static ssize_t defer_data_source_read_callback (nghttp2_session *session, int32_t stream_id, - uint8_t *buf, size_t len, int *eof, + uint8_t *buf, size_t len, uint32_t *data_flags, nghttp2_data_source *source, void *user_data) { return NGHTTP2_ERR_DEFERRED;