Author: rhuijben
Date: Sun Nov 1 13:37:40 2015
New Revision: 1711764
URL: http://svn.apache.org/viewvc?rev=1711764&view=rev
Log:
In the http2 handling: Move more of the responsibilities of setting up a
request to the stream handling. Fix continuation handling to properly
support responses with headers that don't fit in a single frame.
* protocols/http2_protocol.c
(setup_for_http2): Rename to...
(enqueue_http2_request): ... this.
(http2_bucket_processor): Use the most efficient reading we know of.
(http2_bucket_processor): Pass continuation bucket as body as intended.
(http2_protocol_write): Simplify code by delegating to stream.
* protocols/http2_protocol.h
(serf_http2__stream_setup_request): Rename to...
(serf_http2__stream_setup_next_request): ... this.
* protocols/http2_stream.c
(serf_http2__stream_setup_request): Rename to...
(serf_http2__stream_setup_next_request): ... this and handle connection
bookkeeping.
(serf_http2__stream_processor): Use more efficient draining.
Modified:
serf/trunk/protocols/http2_protocol.c
serf/trunk/protocols/http2_protocol.h
serf/trunk/protocols/http2_stream.c
Modified: serf/trunk/protocols/http2_protocol.c
URL:
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.c?rev=1711764&r1=1711763&r2=1711764&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.c (original)
+++ serf/trunk/protocols/http2_protocol.c Sun Nov 1 13:37:40 2015
@@ -285,8 +285,7 @@ void serf__http2_protocol_init(serf_conn
/* Creates a HTTP/2 request from a serf request */
static apr_status_t
-setup_for_http2(serf_http2_protocol_t *h2,
- serf_request_t *request)
+enqueue_http2_request(serf_http2_protocol_t *h2)
{
serf_http2_stream_t *stream;
@@ -304,8 +303,8 @@ setup_for_http2(serf_http2_protocol_t *h
else
h2->last = h2->first = stream;
- return serf_http2__stream_setup_request(stream, h2->hpack_tbl,
- request);
+ return serf_http2__stream_setup_next_request(stream, h2->conn,
+ h2->hpack_tbl);
}
apr_status_t
@@ -756,12 +755,12 @@ http2_bucket_processor(void *baton,
serf_http2_protocol_t *h2,
serf_bucket_t *frame_bucket)
{
- struct iovec vecs[16];
+ struct iovec vecs[IOV_MAX];
int vecs_used;
serf_bucket_t *payload = baton;
apr_status_t status;
- status = serf_bucket_read_iovec(payload, SERF_READ_ALL_AVAIL, 16,
+ status = serf_bucket_read_iovec(payload, SERF_READ_ALL_AVAIL, IOV_MAX,
vecs, &vecs_used);
if (APR_STATUS_IS_EOF(status))
@@ -1006,6 +1005,8 @@ http2_process(serf_http2_protocol_t *h2)
serf_bucket_aggregate_hold_open(
h2->continuation_bucket,
http2_handle_continuation, h2);
+
+ body = h2->continuation_bucket;
}
if (stream && !reset_reason)
@@ -1346,24 +1347,13 @@ http2_protocol_read(serf_connection_t *c
static apr_status_t
http2_protocol_write(serf_connection_t *conn)
{
- serf_http2_protocol_t *ctx = conn->protocol_baton;
- serf_request_t *request = conn->unwritten_reqs;
+ serf_http2_protocol_t *h2 = conn->protocol_baton;
apr_status_t status;
- if (request)
+ if (conn->unwritten_reqs
+ && conn->nr_of_written_reqs < h2->lr_max_concurrent)
{
- conn->unwritten_reqs = request->next;
- if (conn->unwritten_reqs_tail == request)
- conn->unwritten_reqs = conn->unwritten_reqs_tail = NULL;
-
- request->next = NULL;
-
- serf__link_requests(&conn->written_reqs, &conn->written_reqs_tail,
- request);
- conn->nr_of_written_reqs++;
- conn->nr_of_written_reqs--;
-
- status = setup_for_http2(ctx, request);
+ status = enqueue_http2_request(h2);
if (status)
return status;
}
Modified: serf/trunk/protocols/http2_protocol.h
URL:
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.h?rev=1711764&r1=1711763&r2=1711764&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.h (original)
+++ serf/trunk/protocols/http2_protocol.h Sun Nov 1 13:37:40 2015
@@ -188,11 +188,11 @@ serf_http2__stream_get(serf_http2_protoc
int create_for_remote,
int move_first);
-/* Sets up STREAM to handle REQUEST */
+/* Sets up STREAM to handle the next request from CONN */
apr_status_t
-serf_http2__stream_setup_request(serf_http2_stream_t *stream,
- serf_hpack_table_t *hpack_tbl,
- serf_request_t *request);
+serf_http2__stream_setup_next_request(serf_http2_stream_t *stream,
+ serf_connection_t *conn,
+ serf_hpack_table_t *hpack_tbl);
apr_status_t
serf_http2__stream_reset(serf_http2_stream_t *stream,
Modified: serf/trunk/protocols/http2_stream.c
URL:
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_stream.c?rev=1711764&r1=1711763&r2=1711764&view=diff
==============================================================================
--- serf/trunk/protocols/http2_stream.c (original)
+++ serf/trunk/protocols/http2_stream.c Sun Nov 1 13:37:40 2015
@@ -82,14 +82,19 @@ serf_http2__stream_cleanup(serf_http2_st
}
apr_status_t
-serf_http2__stream_setup_request(serf_http2_stream_t *stream,
- serf_hpack_table_t *hpack_tbl,
- serf_request_t *request)
+serf_http2__stream_setup_next_request(serf_http2_stream_t *stream,
+ serf_connection_t *conn,
+ serf_hpack_table_t *hpack_tbl)
{
+ serf_request_t *request = conn->unwritten_reqs;
apr_status_t status;
serf_bucket_t *hpack;
serf_bucket_t *body;
+ SERF_H2_assert(request != NULL);
+ if (!request)
+ return APR_EGENERAL;
+
stream->data->request = request;
if (!request->req_bkt)
@@ -99,6 +104,17 @@ serf_http2__stream_setup_request(serf_ht
return status;
}
+ conn->unwritten_reqs = request->next;
+ if (conn->unwritten_reqs_tail == request)
+ conn->unwritten_reqs = conn->unwritten_reqs_tail = NULL;
+
+ request->next = NULL;
+
+ serf__link_requests(&conn->written_reqs, &conn->written_reqs_tail,
+ request);
+ conn->nr_of_written_reqs++;
+ conn->nr_of_written_reqs--;
+
serf__bucket_request_read(request->req_bkt, &body, NULL, NULL);
status = serf__bucket_hpack_create_from_request(&hpack, hpack_tbl,
request->req_bkt,
@@ -324,45 +340,25 @@ serf_http2__stream_processor(void *baton
status = APR_SUCCESS;
}
- /* ### TODO: Delegate to request */
while (!status)
{
- const char *data;
- apr_size_t len;
+ struct iovec vecs[IOV_MAX];
+ int vecs_used;
- status = serf_bucket_read(stream->data->response_agg,
- SERF_READ_ALL_AVAIL, &data, &len);
+ /* Drain the bucket as efficiently as possible */
+ status = serf_bucket_read_iovec(stream->data->response_agg,
+ SERF_READ_ALL_AVAIL,
+ IOV_MAX, vecs, &vecs_used);
- if (!SERF_BUCKET_READ_ERROR(status))
+ if (vecs_used)
{
-#if 0
- if (len > 0)
- {
- serf_bucket_alloc_t *alloc = stream->data->response_agg->allocator;
- char *printable = serf_bstrmemdup(alloc, data, len);
- char *c;
-
- for (c = printable; *c; c++)
- {
- /* Poor mans isctrl */
- if (((*c < ' ') || (*c > '\x7E')) && !strchr("\r\n", *c))
- {
- *c = ' ';
- }
- }
-
-#ifdef _DEBUG
- fputs(printable, stdout);
-#endif
-
- serf_bucket_mem_free(alloc, printable);
- }
-#endif
+ /* We have data... What should we do with it? */
}
}
if (APR_STATUS_IS_EOF(status)
- && stream->status == H2S_CLOSED || stream->status ==
H2S_HALFCLOSED_REMOTE)
+ && (stream->status == H2S_CLOSED
+ || stream->status == H2S_HALFCLOSED_REMOTE))
{
/* If there was a request, it is already gone, so we can now safely
destroy our aggregate which may include everything upto the http2