Author: rhuijben
Date: Wed Oct 28 10:37:37 2015
New Revision: 1710981
URL: http://svn.apache.org/viewvc?rev=1710981&view=rev
Log:
Add an eof callback to the http2 unframe bucket (modeled after the similar
callback on the aggregate bucket), to ease handling frame buckets that are
handed of to separate handlers.
* buckets/http2_frame_buckets.c
(http2_unframe_context_t): Add callback info.
(serf__bucket_http2_unframe_create): Default callback to NULL.
(serf__bucket_http2_unframe_set_eof): New function.
(serf__bucket_http2_unframe_read_info,
serf_http2_unframe_read,
serf_http2_unframe_read_iovec): Call callback when hitting eof.
* protocols/http2_buckets.h
(serf__bucket_http2_unframe_create): Extend documentation.
(serf__bucket_http2_unframe_set_eof): New function.
Modified:
serf/trunk/buckets/http2_frame_buckets.c
serf/trunk/protocols/http2_buckets.h
Modified: serf/trunk/buckets/http2_frame_buckets.c
URL:
http://svn.apache.org/viewvc/serf/trunk/buckets/http2_frame_buckets.c?rev=1710981&r1=1710980&r2=1710981&view=diff
==============================================================================
--- serf/trunk/buckets/http2_frame_buckets.c (original)
+++ serf/trunk/buckets/http2_frame_buckets.c Wed Oct 28 10:37:37 2015
@@ -38,6 +38,10 @@ typedef struct http2_unframe_context_t
apr_size_t prefix_remaining;
+ apr_status_t (*eof_callback)(void *baton,
+ serf_bucket_t *bucket);
+ void *eof_callback_baton;
+
/* These fields are only set after prefix_remaining is 0 */
apr_size_t payload_remaining; /* 0 <= payload_length < 2^24 */
apr_int32_t stream_id; /* 0 <= stream_id < 2^31 */
@@ -60,11 +64,26 @@ serf__bucket_http2_unframe_create(serf_b
ctx->stream = stream;
ctx->max_payload_size = max_payload_size;
ctx->prefix_remaining = sizeof(ctx->prefix_buffer);
+ ctx->eof_callback = NULL;
+
ctx->destroy_stream = (destroy_stream != 0);
return serf_bucket_create(&serf_bucket_type__http2_unframe, allocator, ctx);
}
+void
+serf__bucket_http2_unframe_set_eof(serf_bucket_t *bucket,
+ apr_status_t (*eof_callback)(
+ void *baton,
+ serf_bucket_t *bucket),
+ void *eof_callback_baton)
+{
+ http2_unframe_context_t *ctx = bucket->data;
+
+ ctx->eof_callback = eof_callback;
+ ctx->eof_callback_baton = eof_callback_baton;
+}
+
apr_status_t
serf__bucket_http2_unframe_read_info(serf_bucket_t *bucket,
apr_int32_t *stream_id,
@@ -123,6 +142,28 @@ serf__bucket_http2_unframe_read_info(ser
*/
if (ctx->max_payload_size < payload_length)
return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+
+ status = (ctx->payload_remaining == 0) ? APR_EOF
+ : APR_SUCCESS;
+
+ /* If we hava a zero-length frame we have to call the eof callback
+ now, as the read operations will just shortcut to APR_EOF */
+ if (ctx->payload_remaining == 0 && ctx->eof_callback)
+ {
+ apr_status_t cb_status;
+
+ cb_status = ctx->eof_callback(ctx->eof_callback_baton,
+ bucket);
+
+ if (SERF_BUCKET_READ_ERROR(cb_status))
+ status = cb_status;
+ }
+ }
+ else if (APR_STATUS_IS_EOF(status))
+ {
+ /* Reading frame failed because we couldn't read the header. Report
+ a read failure instead of semi-success */
+ status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
}
else if (!status)
status = APR_EAGAIN;
@@ -163,7 +204,14 @@ serf_http2_unframe_read(serf_bucket_t *b
ctx->payload_remaining -= *len;
if (ctx->payload_remaining == 0)
- status = APR_EOF;
+ {
+ if (ctx->eof_callback)
+ status = ctx->eof_callback(ctx->eof_callback_baton,
+ bucket);
+
+ if (!SERF_BUCKET_READ_ERROR(status))
+ status = APR_EOF;
+ }
}
return status;
@@ -209,7 +257,14 @@ serf_http2_unframe_read_iovec(serf_bucke
ctx->payload_remaining -= len;
if (ctx->payload_remaining == 0)
- status = APR_EOF;
+ {
+ if (ctx->eof_callback)
+ status = ctx->eof_callback(ctx->eof_callback_baton,
+ bucket);
+
+ if (!SERF_BUCKET_READ_ERROR(status))
+ status = APR_EOF;
+ }
}
return status;
Modified: serf/trunk/protocols/http2_buckets.h
URL:
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_buckets.h?rev=1710981&r1=1710980&r2=1710981&view=diff
==============================================================================
--- serf/trunk/protocols/http2_buckets.h (original)
+++ serf/trunk/protocols/http2_buckets.h Wed Oct 28 10:37:37 2015
@@ -38,12 +38,32 @@ extern "C" {
extern const serf_bucket_type_t serf_bucket_type__http2_unframe;
#define SERF__BUCKET_IS_HTTP2_UNFRAME(b) SERF_BUCKET_CHECK((b), _http2_unframe)
+/* Creates a bucket that reads a single http2 frame from stream. If
+ DESTROY_STREAM is true STREAM will be destroyed with the bucket, otherwise
+ it won't.
+
+ The frame header information can be obtained by calling
+ serf__bucket_http2_unframe_read_info().
+
+ After the header has been read the remaining payload size can be retrieved
+ using serf_bucket_get_remaining()
+ */
serf_bucket_t *
serf__bucket_http2_unframe_create(serf_bucket_t *stream,
int destroy_stream,
apr_size_t max_payload_size,
serf_bucket_alloc_t *allocator);
+/* Sets the end of frame handler on the frame, which will be called as soon as
+ the whole frame has been read from the contained stream */
+void
+serf__bucket_http2_unframe_set_eof(serf_bucket_t *bucket,
+ apr_status_t (*eof_callback)(
+ void *baton,
+ serf_bucket_t *bucket),
+ void *eof_callback_baton);
+
+
/* Obtains the frame header state, reading from the bucket if necessary.
If the header was read successfully (or was already read before calling)
the *stream_id, * frame_type and *flags values (when not pointing to NULL)