Author: rhuijben
Date: Sun Oct 18 14:00:16 2015
New Revision: 1709280
URL: http://svn.apache.org/viewvc?rev=1709280&view=rev
Log:
Implement a basic frame parser for the http2 protocol. This currently
parses a SETTINGS and WINDOW_UPDATE frame when used against one of the
google servers via serf_get's --http2 mode.
* serf-dev/dev/protocols/http2_protocol.c
(HTTP2_DEFAULT_MAX_FRAME_SIZE,
HTTP2_FLAG_PADDED): New defines.
(serf_http2_procotol_state_t): Add some state variables.
(http2_read): New function that just reads all http2 frames encountered
on the connection.
(http2_protocol_read): Call http2_read.
Modified:
serf/trunk/protocols/http2_protocol.c
Modified: serf/trunk/protocols/http2_protocol.c
URL:
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.c?rev=1709280&r1=1709279&r2=1709280&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.c (original)
+++ serf/trunk/protocols/http2_protocol.c Sun Oct 18 14:00:16 2015
@@ -41,10 +41,20 @@ http2_protocol_hangup(serf_connection_t
static void
http2_protocol_teardown(serf_connection_t *conn);
+#define HTTP2_DEFAULT_MAX_FRAME_SIZE 16384
+
+#define HTTP2_FLAG_PADDED 0x08
+
typedef struct serf_http2_procotol_state_t
{
apr_pool_t *pool;
+ char buffer[HTTP2_DEFAULT_MAX_FRAME_SIZE];
+ apr_size_t buffer_used;
+ serf_bucket_t *cur_frame;
+ serf_bucket_t *cur_payload;
+ int in_payload;
+
} serf_http2_procotol_state_t;
static apr_status_t
@@ -78,11 +88,121 @@ void serf__http2_protocol_init(serf_conn
}
static apr_status_t
+http2_read(serf_connection_t *conn)
+{
+ serf_http2_procotol_state_t *ctx = conn->protocol_baton;
+ apr_status_t status = APR_SUCCESS;
+
+ while (TRUE)
+ {
+ status = APR_SUCCESS;
+
+ if (ctx->cur_frame)
+ {
+ const char *data;
+ apr_size_t len;
+
+ if (! ctx->in_payload)
+ {
+ unsigned char flags;
+
+ status = serf_bucket_http2_unframe_read_info(ctx->cur_frame,
+ NULL, NULL, &flags);
+
+ if (!SERF_BUCKET_READ_ERROR(status))
+ {
+ ctx->in_payload = TRUE;
+
+ if (flags & HTTP2_FLAG_PADDED)
+ {
+ ctx->cur_payload =
+ serf_bucket_http2_unpad_create(
+ ctx->cur_frame, TRUE,
+ ctx->cur_frame->allocator);
+ }
+ else
+ ctx->cur_payload = ctx->cur_frame;
+ }
+
+ if (status)
+ break;
+ }
+
+ status = serf_bucket_read(ctx->cur_frame,
+ sizeof(ctx->buffer) - ctx->buffer_used,
+ &data, &len);
+
+ if (!SERF_BUCKET_READ_ERROR(status))
+ {
+ memcpy(&ctx->buffer[ctx->buffer_used], data, len);
+ ctx->buffer_used += len;
+ }
+
+ if (APR_STATUS_IS_EOF(status))
+ {
+ apr_int32_t streamid;
+ unsigned char frametype;
+ unsigned char flags;
+
+ status = serf_bucket_http2_unframe_read_info(ctx->cur_frame,
+ &streamid,
&frametype,
+ &flags);
+ serf__log(LOGLVL_INFO, LOGCOMP_CONN, __FILE__, conn->config,
+ "Read 0x%02x http2 frame on stream 0x%x, flags=0x%x\n",
+ (int)frametype, (int)streamid, (int)flags);
+
+ serf_bucket_destroy(ctx->cur_payload);
+ ctx->cur_frame = ctx->cur_payload = NULL;
+ ctx->in_payload = FALSE;
+ ctx->buffer_used = 0;
+ }
+ else if (status)
+ break;
+ }
+
+ if (APR_STATUS_IS_EOF(status))
+ {
+ const char *data;
+ apr_size_t len;
+ status = serf_bucket_peek(conn->stream, &data, &len);
+
+ if (SERF_BUCKET_READ_ERROR(status)
+ || APR_STATUS_IS_EOF(status))
+ {
+ /* We have a real EOF*/
+ break;
+ }
+ }
+
+ ctx->cur_frame = ctx->cur_payload =
+ serf_bucket_http2_unframe_create(conn->stream, FALSE,
+ HTTP2_DEFAULT_MAX_FRAME_SIZE,
+ conn->stream->allocator);
+ }
+
+ return status;
+}
+
+static apr_status_t
http2_protocol_read(serf_connection_t *conn)
{
- /* serf_http2_procotol_state_t *ctx = conn->protocol_baton; */
+ apr_status_t status = http2_read(conn);
- return APR_EGENERAL;
+ if (!status)
+ return APR_SUCCESS;
+ else if (APR_STATUS_IS_EOF(status))
+ {
+ /* TODO: Teardown connection, reset if necessary, etc. */
+ return status;
+ }
+ else if (APR_STATUS_IS_EAGAIN(status)
+ || status == SERF_ERROR_WAIT_CONN)
+ {
+ /* Update pollset, etc. etc. */
+ return APR_SUCCESS;
+ }
+ else
+ return status;
}
static apr_status_t
@@ -90,7 +210,7 @@ http2_protocol_write(serf_connection_t *
{
/* serf_http2_procotol_state_t *ctx = conn->protocol_baton; */
- return APR_EGENERAL;
+ return APR_SUCCESS;
}
static apr_status_t