Modified: serf/trunk/protocols/http2_protocol.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.c?rev=1714622&r1=1714621&r2=1714622&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.c (original)
+++ serf/trunk/protocols/http2_protocol.c Mon Nov 16 16:27:04 2015
@@ -59,106 +59,107 @@ static apr_status_t
 http2_process(serf_http2_protocol_t *h2);
 
 static serf_bucket_t *
-serf_bucket_create_numberv(serf_bucket_alloc_t *allocator, const char *format, 
...)
+serf_bucket_create_numberv(serf_bucket_alloc_t *allocator, const char *format,
+                           ...)
 {
-  va_list argp;
-  const char *c;
-  char *buffer;
-  apr_size_t sz = 0;
-  unsigned char *r;
-
-  va_start(argp, format);
-
-  for (c = format; *c; c++)
-    {
-      SERF_H2_assert(*c >= '1' && *c <= '4');
-
-      if (*c >= '1' && *c <= '4')
-        sz += (*c - '0');
-    }
-
-  buffer = serf_bucket_mem_alloc(allocator, sz);
-  r = (void*)buffer;
-  for (c = format; *c; c++)
-    {
-      apr_uint32_t tmp;
-
-      switch (*c)
-       {
-         case '1':
-           *r++ = va_arg(argp, int) & 0xFF;
-           break;
-         case '2':
-           tmp = va_arg(argp, int);
-           *r++ = (tmp >> 8) & 0xFF;
-           *r++ = tmp & 0xFF;
-           break;
-         case '3':
-           tmp = va_arg(argp, apr_uint32_t);
-           *r++ = (tmp >> 16) & 0xFF;
-           *r++ = (tmp >> 8) & 0xFF;
-           *r++ = tmp & 0xFF;
-           break;
-         case '4':
-           tmp = va_arg(argp, apr_uint32_t);
-           *r++ = (tmp >> 24) & 0xFF;
-           *r++ = (tmp >> 16) & 0xFF;
-           *r++ = (tmp >> 8) & 0xFF;
-           *r++ = tmp & 0xFF;
-           break;
-       }
+    va_list argp;
+    const char *c;
+    char *buffer;
+    apr_size_t sz = 0;
+    unsigned char *r;
+
+    va_start(argp, format);
+
+    for (c = format; *c; c++)
+    {
+        SERF_H2_assert(*c >= '1' && *c <= '4');
+
+        if (*c >= '1' && *c <= '4')
+            sz += (*c - '0');
+    }
+
+    buffer = serf_bucket_mem_alloc(allocator, sz);
+    r = (void*)buffer;
+    for (c = format; *c; c++)
+    {
+        apr_uint32_t tmp;
+
+        switch (*c)
+        {
+            case '1':
+                *r++ = va_arg(argp, int) & 0xFF;
+                break;
+            case '2':
+                tmp = va_arg(argp, int);
+                *r++ = (tmp >> 8) & 0xFF;
+                *r++ = tmp & 0xFF;
+                break;
+            case '3':
+                tmp = va_arg(argp, apr_uint32_t);
+                *r++ = (tmp >> 16) & 0xFF;
+                *r++ = (tmp >> 8) & 0xFF;
+                *r++ = tmp & 0xFF;
+                break;
+            case '4':
+                tmp = va_arg(argp, apr_uint32_t);
+                *r++ = (tmp >> 24) & 0xFF;
+                *r++ = (tmp >> 16) & 0xFF;
+                *r++ = (tmp >> 8) & 0xFF;
+                *r++ = tmp & 0xFF;
+                break;
+        }
     }
 
-  va_end(argp);
+    va_end(argp);
 
-  return serf_bucket_simple_own_create(buffer, sz, allocator);
+    return serf_bucket_simple_own_create(buffer, sz, allocator);
 }
 
 struct serf_http2_protocol_t
 {
-  apr_pool_t *pool;
-  serf_connection_t *conn; /* Either CONN or CLIENT is set */
-  serf_incoming_t *client;
-  serf_bucket_t *stream, *ostream;
-  serf_bucket_alloc_t *allocator;
-
-  serf_http2_processor_t processor;
-  void *processor_baton;
-  serf_bucket_t *read_frame;   /* Frame currently being read */
-  bool in_frame;
-  apr_size_t prefix_left;
-
-  serf_hpack_table_t *hpack_tbl;
-  serf_config_t *config;
-
-  /* Local -> Remote. Settings provided by other side */
-  apr_uint32_t lr_default_window;
-  apr_uint32_t lr_window;
-  apr_uint32_t lr_max_framesize;
-  apr_uint32_t lr_max_headersize;
-  apr_uint32_t lr_max_concurrent;
-  apr_uint32_t lr_hpack_table_size;
-  apr_int32_t lr_next_streamid;
-  bool lr_push_enabled;
-
-  /* Remote -> Local. Settings set by us. Acknowledged by other side */
-  apr_uint32_t rl_default_window;
-  apr_uint32_t rl_window;
-  apr_uint32_t rl_max_framesize;
-  apr_uint32_t rl_max_headersize;
-  apr_uint32_t rl_max_concurrent;
-  apr_uint32_t rl_hpack_table_size;
-  apr_int32_t rl_next_streamid;
-  bool rl_push_enabled;
+    apr_pool_t *pool;
+    serf_connection_t *conn; /* Either CONN or CLIENT is set */
+    serf_incoming_t *client;
+    serf_bucket_t *stream, *ostream;
+    serf_bucket_alloc_t *allocator;
+
+    serf_http2_processor_t processor;
+    void *processor_baton;
+    serf_bucket_t *read_frame;   /* Frame currently being read */
+    bool in_frame;
+    apr_size_t prefix_left;
+
+    serf_hpack_table_t *hpack_tbl;
+    serf_config_t *config;
+
+    /* Local -> Remote. Settings provided by other side */
+    apr_uint32_t lr_default_window;
+    apr_uint32_t lr_window;
+    apr_uint32_t lr_max_framesize;
+    apr_uint32_t lr_max_headersize;
+    apr_uint32_t lr_max_concurrent;
+    apr_uint32_t lr_hpack_table_size;
+    apr_int32_t lr_next_streamid;
+    bool lr_push_enabled;
+
+    /* Remote -> Local. Settings set by us. Acknowledged by other side */
+    apr_uint32_t rl_default_window;
+    apr_uint32_t rl_window;
+    apr_uint32_t rl_max_framesize;
+    apr_uint32_t rl_max_headersize;
+    apr_uint32_t rl_max_concurrent;
+    apr_uint32_t rl_hpack_table_size;
+    apr_int32_t rl_next_streamid;
+    bool rl_push_enabled;
 
-  serf_http2_stream_t *first;
-  serf_http2_stream_t *last;
+    serf_http2_stream_t *first;
+    serf_http2_stream_t *last;
 
-  int setting_acks;
-  bool enforce_flow_control;
+    int setting_acks;
+    bool enforce_flow_control;
 
-  serf_bucket_t *continuation_bucket;
-  apr_int32_t continuation_streamid;
+    serf_bucket_t *continuation_bucket;
+    apr_int32_t continuation_streamid;
 };
 
 /* Forward definition */
@@ -171,33 +172,33 @@ http2_bucket_processor(void *baton,
 static apr_status_t
 http2_protocol_cleanup(void *state)
 {
-  serf_http2_protocol_t *h2 = state;
-  serf_connection_t *conn = h2->conn;
-  serf_incoming_t *client = h2->client;
-  serf_http2_stream_t *stream, *next;
+    serf_http2_protocol_t *h2 = state;
+    serf_connection_t *conn = h2->conn;
+    serf_incoming_t *client = h2->client;
+    serf_http2_stream_t *stream, *next;
 
-  /* First clean out all streams */
-  for (stream = h2->first; stream; stream = next)
+    /* First clean out all streams */
+    for (stream = h2->first; stream; stream = next)
     {
-      next = stream->next;
-      serf_http2__stream_cleanup(stream);
+        next = stream->next;
+        serf_http2__stream_cleanup(stream);
     }
 
-  h2->first = h2->last = NULL;
+    h2->first = h2->last = NULL;
 
-  if (h2->processor != NULL)
+    if (h2->processor != NULL)
     {
-      h2->read_frame = NULL;
+        h2->read_frame = NULL;
 
-      if (h2->processor == http2_bucket_processor)
+        if (h2->processor == http2_bucket_processor)
         {
-          serf_bucket_t *payload = h2->processor_baton;
+            serf_bucket_t *payload = h2->processor_baton;
 
-          if (payload)
-            serf_bucket_destroy(payload);
+            if (payload)
+                serf_bucket_destroy(payload);
 
-          h2->processor = NULL;
-          h2->processor_baton = NULL;
+            h2->processor = NULL;
+            h2->processor_baton = NULL;
 
         }
       /* Else: The processor (probably a stream)
@@ -205,107 +206,110 @@ http2_protocol_cleanup(void *state)
                by adding frames to an aggregate to allow
                reading multiple frames as a stream. */
     }
-  else if (h2->read_frame)
+    else if (h2->read_frame)
     {
-      serf_bucket_destroy(h2->read_frame);
-      h2->read_frame = NULL;
+        serf_bucket_destroy(h2->read_frame);
+        h2->read_frame = NULL;
     }
-  h2->in_frame = FALSE;
+    h2->in_frame = FALSE;
 
-  if (conn)
-      conn->protocol_baton = NULL;
-  if (client)
-      client->protocol_baton = NULL;
+    if (conn)
+        conn->protocol_baton = NULL;
+    if (client)
+        client->protocol_baton = NULL;
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 void serf__http2_protocol_init(serf_connection_t *conn)
 {
-  serf_http2_protocol_t *h2;
-  apr_pool_t *protocol_pool;
-  serf_bucket_t *tmp;
-  const bool WE_ARE_CLIENT = true;
-
-  apr_pool_create(&protocol_pool, conn->pool);
-
-  h2 = apr_pcalloc(protocol_pool, sizeof(*h2));
-  h2->pool = protocol_pool;
-  h2->conn = conn;
-  h2->stream = conn->stream;
-  h2->ostream = conn->ostream_tail;
-  h2->allocator = conn->allocator;
-  h2->config = conn->config;
-
-  /* Defaults until negotiated */
-  h2->rl_default_window = HTTP2_DEFAULT_WINDOW_SIZE;
-  h2->rl_window = HTTP2_DEFAULT_WINDOW_SIZE;
-  h2->rl_next_streamid = WE_ARE_CLIENT ? 2 : 1;
-  h2->rl_max_framesize = HTTP2_DEFAULT_MAX_FRAMESIZE;
-  h2->rl_max_headersize = APR_UINT32_MAX;
-  h2->rl_max_concurrent = HTTP2_DEFAULT_MAX_CONCURRENT;
-  h2->rl_hpack_table_size = HTTP2_DEFAULT_HPACK_TABLE_SIZE;
-  h2->rl_push_enabled = TRUE;
-
-  h2->lr_default_window = HTTP2_DEFAULT_WINDOW_SIZE;
-  h2->lr_window = HTTP2_DEFAULT_WINDOW_SIZE;
-  h2->lr_next_streamid = WE_ARE_CLIENT ? 1 : 2;
-  h2->lr_max_framesize = HTTP2_DEFAULT_MAX_FRAMESIZE;
-  h2->lr_max_headersize = APR_UINT32_MAX;
-  h2->lr_max_concurrent = HTTP2_DEFAULT_MAX_CONCURRENT;
-  h2->lr_hpack_table_size = HTTP2_DEFAULT_HPACK_TABLE_SIZE;
-  h2->lr_push_enabled = TRUE;
-
-  h2->setting_acks = 0;
-  h2->enforce_flow_control = TRUE;
-  h2->continuation_bucket = NULL;
-  h2->continuation_streamid = 0;
-
-  h2->first = h2->last = NULL;
-
-  h2->hpack_tbl = serf__hpack_table_create(TRUE,
-                                           HTTP2_DEFAULT_HPACK_TABLE_SIZE,
-                                           protocol_pool);
-
-  apr_pool_cleanup_register(protocol_pool, h2, http2_protocol_cleanup,
-                            apr_pool_cleanup_null);
-
-  conn->perform_read = http2_outgoing_read;
-  conn->perform_write = http2_outgoing_write;
-  conn->perform_hangup = http2_outgoing_hangup;
-  conn->perform_teardown = http2_outgoing_teardown;
-  conn->protocol_baton = h2;
-
-  /* Disable HTTP/1.1 guessing that affects writability */
-  conn->probable_keepalive_limit = 0;
-  conn->max_outstanding_requests = 0;
-
-  /* Send the HTTP/2 Connection Preface */
-  tmp = SERF_BUCKET_SIMPLE_STRING(HTTP2_CONNECTION_PREFIX, h2->allocator);
-  serf_bucket_aggregate_append(h2->ostream, tmp);
-
-  /* And now a settings frame and a huge window */
-  {
-    serf_bucket_t *window_size;
-
-    tmp = serf__bucket_http2_frame_create(NULL, HTTP2_FRAME_TYPE_SETTINGS, 0,
-                                          NULL, NULL, NULL, /* stream: 0 */
-                                          h2->lr_max_framesize,
-                                          h2->allocator);
+    serf_http2_protocol_t *h2;
+    apr_pool_t *protocol_pool;
+    serf_bucket_t *tmp;
+    const bool WE_ARE_CLIENT = true;
 
-    serf_http2__enqueue_frame(h2, tmp, FALSE);
+    apr_pool_create(&protocol_pool, conn->pool);
 
-    /* Add 1GB to the current window. */
-    window_size = serf_bucket_create_numberv(conn->allocator, "4", 0x40000000);
-    tmp = serf__bucket_http2_frame_create(window_size,
-                                          HTTP2_FRAME_TYPE_WINDOW_UPDATE, 0,
-                                          NULL, NULL, NULL, /* stream: 0 */
-                                          h2->lr_max_framesize,
-                                          h2->allocator);
-    serf_http2__enqueue_frame(h2, tmp, FALSE);
+    h2 = apr_pcalloc(protocol_pool, sizeof(*h2));
+    h2->pool = protocol_pool;
+    h2->conn = conn;
+    h2->stream = conn->stream;
+    h2->ostream = conn->ostream_tail;
+    h2->allocator = conn->allocator;
+    h2->config = conn->config;
+
+    /* Defaults until negotiated */
+    h2->rl_default_window = HTTP2_DEFAULT_WINDOW_SIZE;
+    h2->rl_window = HTTP2_DEFAULT_WINDOW_SIZE;
+    h2->rl_next_streamid = WE_ARE_CLIENT ? 2 : 1;
+    h2->rl_max_framesize = HTTP2_DEFAULT_MAX_FRAMESIZE;
+    h2->rl_max_headersize = APR_UINT32_MAX;
+    h2->rl_max_concurrent = HTTP2_DEFAULT_MAX_CONCURRENT;
+    h2->rl_hpack_table_size = HTTP2_DEFAULT_HPACK_TABLE_SIZE;
+    h2->rl_push_enabled = TRUE;
 
-    h2->rl_window += 0x40000000; /* And update our own administration */
-  }
+    h2->lr_default_window = HTTP2_DEFAULT_WINDOW_SIZE;
+    h2->lr_window = HTTP2_DEFAULT_WINDOW_SIZE;
+    h2->lr_next_streamid = WE_ARE_CLIENT ? 1 : 2;
+    h2->lr_max_framesize = HTTP2_DEFAULT_MAX_FRAMESIZE;
+    h2->lr_max_headersize = APR_UINT32_MAX;
+    h2->lr_max_concurrent = HTTP2_DEFAULT_MAX_CONCURRENT;
+    h2->lr_hpack_table_size = HTTP2_DEFAULT_HPACK_TABLE_SIZE;
+    h2->lr_push_enabled = TRUE;
+
+    h2->setting_acks = 0;
+    h2->enforce_flow_control = TRUE;
+    h2->continuation_bucket = NULL;
+    h2->continuation_streamid = 0;
+
+    h2->first = h2->last = NULL;
+
+    h2->hpack_tbl = serf__hpack_table_create(TRUE,
+                                             HTTP2_DEFAULT_HPACK_TABLE_SIZE,
+                                             protocol_pool);
+
+    apr_pool_cleanup_register(protocol_pool, h2, http2_protocol_cleanup,
+                              apr_pool_cleanup_null);
+
+    conn->perform_read = http2_outgoing_read;
+    conn->perform_write = http2_outgoing_write;
+    conn->perform_hangup = http2_outgoing_hangup;
+    conn->perform_teardown = http2_outgoing_teardown;
+    conn->protocol_baton = h2;
+
+    /* Disable HTTP/1.1 guessing that affects writability */
+    conn->probable_keepalive_limit = 0;
+    conn->max_outstanding_requests = 0;
+
+    /* Send the HTTP/2 Connection Preface */
+    tmp = SERF_BUCKET_SIMPLE_STRING(HTTP2_CONNECTION_PREFIX, h2->allocator);
+    serf_bucket_aggregate_append(h2->ostream, tmp);
+
+    /* And now a settings frame and a huge window */
+    {
+        serf_bucket_t *window_size;
+
+        tmp = serf__bucket_http2_frame_create(NULL, HTTP2_FRAME_TYPE_SETTINGS,
+                                              0,
+                                              NULL, NULL, NULL, /* stream: 0 */
+                                              h2->lr_max_framesize,
+                                              h2->allocator);
+
+        serf_http2__enqueue_frame(h2, tmp, FALSE);
+
+        /* Add 1GB to the current window. */
+        window_size = serf_bucket_create_numberv(conn->allocator, "4",
+                                                 0x40000000);
+        tmp = serf__bucket_http2_frame_create(window_size,
+                                              HTTP2_FRAME_TYPE_WINDOW_UPDATE,
+                                              0,
+                                              NULL, NULL, NULL, /* stream: 0 */
+                                              h2->lr_max_framesize,
+                                              h2->allocator);
+        serf_http2__enqueue_frame(h2, tmp, FALSE);
+
+        h2->rl_window += 0x40000000; /* And update our own administration */
+    }
 }
 
 void serf__http2_protocol_init_server(serf_incoming_t *client)
@@ -370,7 +374,8 @@ void serf__http2_protocol_init_server(se
     {
         serf_bucket_t *window_size;
 
-        tmp = serf__bucket_http2_frame_create(NULL, HTTP2_FRAME_TYPE_SETTINGS, 
0,
+        tmp = serf__bucket_http2_frame_create(NULL, HTTP2_FRAME_TYPE_SETTINGS,
+                                              0,
                                               NULL, NULL, NULL, /* stream: 0 */
                                               h2->lr_max_framesize,
                                               h2->allocator);
@@ -378,9 +383,11 @@ void serf__http2_protocol_init_server(se
         serf_http2__enqueue_frame(h2, tmp, FALSE);
 
         /* Add 1GB to the current window. */
-        window_size = serf_bucket_create_numberv(h2->allocator, "4", 
0x40000000);
+        window_size = serf_bucket_create_numberv(h2->allocator, "4",
+                                                 0x40000000);
         tmp = serf__bucket_http2_frame_create(window_size,
-                                              HTTP2_FRAME_TYPE_WINDOW_UPDATE, 
0,
+                                              HTTP2_FRAME_TYPE_WINDOW_UPDATE,
+                                              0,
                                               NULL, NULL, NULL, /* stream: 0 */
                                               h2->lr_max_framesize,
                                               h2->allocator);
@@ -394,25 +401,25 @@ void serf__http2_protocol_init_server(se
 static apr_status_t
 enqueue_http2_request(serf_http2_protocol_t *h2)
 {
-  serf_http2_stream_t *stream;
+    serf_http2_stream_t *stream;
 
-  stream = serf_http2__stream_create(h2, -1,
-                                     h2->lr_default_window,
-                                     h2->rl_default_window,
-                                     h2->allocator);
-
-  if (h2->first)
-    {
-      stream->next = h2->first;
-      h2->first->prev = stream;
-      h2->first = stream;
+    stream = serf_http2__stream_create(h2, -1,
+                                       h2->lr_default_window,
+                                       h2->rl_default_window,
+                                       h2->allocator);
+
+    if (h2->first)
+    {
+        stream->next = h2->first;
+        h2->first->prev = stream;
+        h2->first = stream;
     }
-  else
-    h2->last = h2->first = stream;
+    else
+        h2->last = h2->first = stream;
 
-  return serf_http2__stream_setup_next_request(stream, h2->conn,
-                                               h2->lr_max_framesize,
-                                               h2->hpack_tbl);
+    return serf_http2__stream_setup_next_request(stream, h2->conn,
+                                                 h2->lr_max_framesize,
+                                                 h2->hpack_tbl);
 }
 
 apr_status_t
@@ -420,58 +427,58 @@ serf_http2__enqueue_frame(serf_http2_pro
                           serf_bucket_t *frame,
                           int pump)
 {
-  apr_status_t status;
-
-  if (!pump
-      && !((h2->conn && h2->conn->dirty_conn)
-           || (h2->client && h2->client->dirty_conn)))
-    {
-      const char *data;
-      apr_size_t len;
+    apr_status_t status;
 
-      /* Cheap check to see if we should request a write
-         event next time around */
-      status = serf_bucket_peek(h2->ostream, &data, &len);
+    if (!pump
+        && !((h2->conn && h2->conn->dirty_conn)
+             || (h2->client && h2->client->dirty_conn)))
+    {
+        const char *data;
+        apr_size_t len;
+
+        /* Cheap check to see if we should request a write
+           event next time around */
+        status = serf_bucket_peek(h2->ostream, &data, &len);
 
-      if (SERF_BUCKET_READ_ERROR(status))
+        if (SERF_BUCKET_READ_ERROR(status))
         {
-          serf_bucket_destroy(frame);
-          return status;
+            serf_bucket_destroy(frame);
+            return status;
         }
 
-      if (len == 0)
+        if (len == 0)
         {
-          h2->conn->dirty_conn = TRUE;
-          h2->conn->ctx->dirty_pollset = TRUE;
+            h2->conn->dirty_conn = TRUE;
+            h2->conn->ctx->dirty_pollset = TRUE;
         }
     }
 
-  serf_bucket_aggregate_append(h2->ostream, frame);
+    serf_bucket_aggregate_append(h2->ostream, frame);
 
-  if (!pump)
-    return APR_SUCCESS;
+    if (!pump)
+        return APR_SUCCESS;
 
-  /* Flush final output buffer (after ssl, etc.) */
-  if (h2->conn)
-    status = serf__connection_flush(h2->conn, TRUE);
-  else
-    status = serf__incoming_client_flush(h2->client, TRUE);
-
-  if (APR_STATUS_IS_EAGAIN(status))
-      return APR_SUCCESS;
-  else if (status)
-      return status;
-
-  if (h2->conn) {
-    h2->conn->dirty_conn = true;
-    h2->conn->ctx->dirty_pollset = true;
-  }
-  else {
-    h2->client->dirty_conn = true;
-    h2->client->ctx->dirty_pollset = true;
-  }
+      /* Flush final output buffer (after ssl, etc.) */
+    if (h2->conn)
+        status = serf__connection_flush(h2->conn, TRUE);
+    else
+        status = serf__incoming_client_flush(h2->client, TRUE);
+
+    if (APR_STATUS_IS_EAGAIN(status))
+        return APR_SUCCESS;
+    else if (status)
+        return status;
 
-  return APR_SUCCESS;
+    if (h2->conn) {
+        h2->conn->dirty_conn = true;
+        h2->conn->ctx->dirty_pollset = true;
+    }
+    else {
+        h2->client->dirty_conn = true;
+        h2->client->ctx->dirty_pollset = true;
+    }
+
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -482,18 +489,18 @@ http2_handle_priority(void *baton,
                       const char *data,
                       apr_size_t len)
 {
-  serf_http2_stream_t *stream = baton;
+    serf_http2_stream_t *stream = baton;
 
-  if (len != HTTP2_PRIORITY_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+    if (len != HTTP2_PRIORITY_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
 
-  if (stream == NULL)
-      return APR_SUCCESS; /* Nothing to record this on */
+    if (stream == NULL)
+        return APR_SUCCESS; /* Nothing to record this on */
 
-  /* ### TODO: Store priority information on stream */
-  SERF_H2_assert(stream->h2 != NULL);
+    /* ### TODO: Store priority information on stream */
+    SERF_H2_assert(stream->h2 != NULL);
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -504,29 +511,29 @@ http2_handle_promise(void *baton,
                      const char *data,
                      apr_size_t len)
 {
-  serf_http2_stream_t *parent_stream = baton;
-  serf_http2_protocol_t *h2= parent_stream->h2;
-  serf_http2_stream_t *promised_stream;
-  apr_int32_t streamid;
-  const struct promise_t
-  {
-    unsigned char s3, s2, s1, s0;
-  } *promise;
-
-  if (len != HTTP2_PROMISE_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-
-  SERF_H2_assert(h2 != NULL);
-
-  promise = (const void *)data;
-
-  /* Highest bit is reserved */
-  streamid = ((promise->s3 & 0x7F) << 24) | (promise->s2 << 16)
-             |(promise->s1 << 8) | promise->s0;
-
-  if (streamid == 0
-      || (streamid < h2->rl_next_streamid)
-      || (streamid & 0x01) != (h2->rl_next_streamid & 0x01))
+    serf_http2_stream_t *parent_stream = baton;
+    serf_http2_protocol_t *h2 = parent_stream->h2;
+    serf_http2_stream_t *promised_stream;
+    apr_int32_t streamid;
+    const struct promise_t
+    {
+        unsigned char s3, s2, s1, s0;
+    } *promise;
+
+    if (len != HTTP2_PROMISE_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+
+    SERF_H2_assert(h2 != NULL);
+
+    promise = (const void *)data;
+
+    /* Highest bit is reserved */
+    streamid = ((promise->s3 & 0x7F) << 24) | (promise->s2 << 16)
+        | (promise->s1 << 8) | promise->s0;
+
+    if (streamid == 0
+        || (streamid < h2->rl_next_streamid)
+        || (streamid & 0x01) != (h2->rl_next_streamid & 0x01))
     {
       /* The promised stream identifier MUST bet a valid choice for the
          next stream sent by the sender */
@@ -537,10 +544,10 @@ http2_handle_promise(void *baton,
          identifier is an identifier for a stream that is not currently in the
          "idle" state.*/
 
-      return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
     }
-  else if (parent_stream->status != H2S_OPEN
-           && parent_stream->status != H2S_HALFCLOSED_LOCAL)
+    else if (parent_stream->status != H2S_OPEN
+             && parent_stream->status != H2S_HALFCLOSED_LOCAL)
     {
       /* PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
          is in either the "open" or "half-closed (remote)" state.  The stream
@@ -549,19 +556,19 @@ http2_handle_promise(void *baton,
          0x0, a recipient MUST respond with a connection error (Section 5.4.1)
          of type PROTOCOL_ERROR.*/
 
-      return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
     }
 
-  promised_stream = serf_http2__stream_get(h2, streamid, TRUE, FALSE);
-  if (!promised_stream || promised_stream->status != H2S_IDLE)
-    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+    promised_stream = serf_http2__stream_get(h2, streamid, TRUE, FALSE);
+    if (!promised_stream || promised_stream->status != H2S_IDLE)
+        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
 
-  promised_stream->status = H2S_RESERVED_REMOTE;
+    promised_stream->status = H2S_RESERVED_REMOTE;
 
-  /* Store data to allow stream to handle the promise */
-  parent_stream->new_reserved_stream = promised_stream;
+    /* Store data to allow stream to handle the promise */
+    parent_stream->new_reserved_stream = promised_stream;
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -572,17 +579,17 @@ http2_handle_frame_reset(void *baton,
                          const char *data,
                          apr_size_t len)
 {
-  serf_http2_stream_t *stream = baton;
+    serf_http2_stream_t *stream = baton;
 
-  if (len != HTTP2_RST_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+    if (len != HTTP2_RST_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
 
-  SERF_H2_assert(stream->h2 != NULL);
+    SERF_H2_assert(stream->h2 != NULL);
 
-  /* ### TODO: Handle error code, etc. */
-  stream->status = H2S_CLOSED;
+    /* ### TODO: Handle error code, etc. */
+    stream->status = H2S_CLOSED;
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -593,36 +600,36 @@ http2_handle_stream_window_update(void *
                                   const char *data,
                                   apr_size_t len)
 {
-  serf_http2_stream_t *stream = baton;
-  apr_uint32_t value;
-  const struct window_update_t
-  {
-    unsigned char v3, v2, v1, v0;
-  } *window_update;
+    serf_http2_stream_t *stream = baton;
+    apr_uint32_t value;
+    const struct window_update_t
+    {
+        unsigned char v3, v2, v1, v0;
+    } *window_update;
 
 
-  if (len != HTTP2_WINDOW_UPDATE_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+    if (len != HTTP2_WINDOW_UPDATE_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
 
-  window_update = (const void *)data;
+    window_update = (const void *)data;
 
-  value = (window_update->v3 << 24) | (window_update->v2 << 16)
-          | (window_update->v2 << 8) | window_update->v0;
+    value = (window_update->v3 << 24) | (window_update->v2 << 16)
+        | (window_update->v2 << 8) | window_update->v0;
 
-  value &= HTTP2_WINDOW_MAX_ALLOWED; /* The highest bit is reserved */
+    value &= HTTP2_WINDOW_MAX_ALLOWED; /* The highest bit is reserved */
 
-  if (value == 0)
+    if (value == 0)
     {
       /* A receiver MUST treat the receipt of a WINDOW_UPDATE frame with an
         flow - control window increment of 0 as a stream error(Section 5.4.2)
         of type PROTOCOL_ERROR; errors on the connection flow - control window
         MUST be treated as a connection error(Section 5.4.1). */
-      return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
     }
 
-  stream->lr_window += value;
+    stream->lr_window += value;
 
-  if (stream->lr_window > HTTP2_WINDOW_MAX_ALLOWED)
+    if (stream->lr_window > HTTP2_WINDOW_MAX_ALLOWED)
     {
       /* A sender MUST NOT allow a flow-control window to exceed 2^31-1
          octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
@@ -631,14 +638,14 @@ http2_handle_stream_window_update(void *
          sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
          connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
          is sent.*/
-      return SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
+        return SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
     }
 
-  serf__log(LOGLVL_INFO, SERF_LOGHTTP2, stream->h2->config,
-            "Increasing window on frame %d with 0x%x to 0x%x\n",
-            stream->streamid, value, stream->lr_window);
+    serf__log(LOGLVL_INFO, SERF_LOGHTTP2, stream->h2->config,
+              "Increasing window on frame %d with 0x%x to 0x%x\n",
+              stream->streamid, value, stream->lr_window);
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -649,37 +656,37 @@ http2_handle_connection_window_update(vo
                                       const char *data,
                                       apr_size_t len)
 {
-  serf_http2_protocol_t *h2 = baton;
-  apr_uint32_t value;
-  const struct window_update_t
-  {
-    unsigned char v3, v2, v1, v0;
-  } *window_update;
+    serf_http2_protocol_t *h2 = baton;
+    apr_uint32_t value;
+    const struct window_update_t
+    {
+        unsigned char v3, v2, v1, v0;
+    } *window_update;
 
-  if (len != HTTP2_WINDOW_UPDATE_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+    if (len != HTTP2_WINDOW_UPDATE_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
 
-  SERF_H2_assert(h2 != NULL);
+    SERF_H2_assert(h2 != NULL);
 
-  window_update = (const void *)data;
+    window_update = (const void *)data;
 
-  value = (window_update->v3 << 24) | (window_update->v2 << 16)
-          | (window_update->v2 << 8) | window_update->v0;
+    value = (window_update->v3 << 24) | (window_update->v2 << 16)
+        | (window_update->v2 << 8) | window_update->v0;
 
-  value &= HTTP2_WINDOW_MAX_ALLOWED; /* The highest bit is reserved */
+    value &= HTTP2_WINDOW_MAX_ALLOWED; /* The highest bit is reserved */
 
-  if (value == 0)
+    if (value == 0)
     {
       /* A receiver MUST treat the receipt of a WINDOW_UPDATE frame with an
         flow - control window increment of 0 as a stream error(Section 5.4.2)
         of type PROTOCOL_ERROR; errors on the connection flow - control window
         MUST be treated as a connection error(Section 5.4.1). */
-      return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
     }
 
-  h2->lr_window += value;
+    h2->lr_window += value;
 
-  if (h2->lr_window > HTTP2_WINDOW_MAX_ALLOWED)
+    if (h2->lr_window > HTTP2_WINDOW_MAX_ALLOWED)
     {
       /* A sender MUST NOT allow a flow-control window to exceed 2^31-1
          octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
@@ -688,14 +695,14 @@ http2_handle_connection_window_update(vo
          sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
          connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
          is sent.*/
-      return SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
+        return SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
     }
 
-  serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-            "Increasing window on connection with 0x%x to 0x%x\n",
-            value, h2->lr_window);
+    serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+              "Increasing window on connection with 0x%x to 0x%x\n",
+              value, h2->lr_window);
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -706,34 +713,34 @@ http2_handle_ping(void *baton,
                   const char *data,
                   apr_size_t len)
 {
-  serf_http2_protocol_t *h2 = baton;
-  serf_bucket_t *body;
-  apr_status_t status;
-
-  if (len != HTTP2_PING_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-
-  SERF_H2_assert(h2 != NULL);
-
-  /* Reply with a PONG (=PING + ACK) with the same data*/
-
-  body = serf_bucket_simple_copy_create(data, len,
-                                        h2->allocator);
-
-  status = serf_http2__enqueue_frame(
-                  h2,
-                  serf__bucket_http2_frame_create(body,
-                                                  HTTP2_FRAME_TYPE_PING,
-                                                  HTTP2_FLAG_ACK,
-                                                  NULL, NULL, NULL,
-                                                  h2->lr_max_framesize,
-                                                  h2->allocator),
-                  TRUE /* pump */);
+    serf_http2_protocol_t *h2 = baton;
+    serf_bucket_t *body;
+    apr_status_t status;
 
-  if (SERF_BUCKET_READ_ERROR(status))
-    return status;
+    if (len != HTTP2_PING_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+
+    SERF_H2_assert(h2 != NULL);
+
+    /* Reply with a PONG (=PING + ACK) with the same data*/
+
+    body = serf_bucket_simple_copy_create(data, len,
+                                          h2->allocator);
 
-  return APR_SUCCESS;
+    status = serf_http2__enqueue_frame(
+        h2,
+        serf__bucket_http2_frame_create(body,
+                                        HTTP2_FRAME_TYPE_PING,
+                                        HTTP2_FLAG_ACK,
+                                        NULL, NULL, NULL,
+                                        h2->lr_max_framesize,
+                                        h2->allocator),
+        TRUE /* pump */);
+
+    if (SERF_BUCKET_READ_ERROR(status))
+        return status;
+
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -744,15 +751,15 @@ http2_handle_ping_ack(void *baton,
                       const char *data,
                       apr_size_t len)
 {
-  serf_http2_protocol_t *h2 = baton;
-  if (len != HTTP2_PING_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+    serf_http2_protocol_t *h2 = baton;
+    if (len != HTTP2_PING_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
 
-  SERF_H2_assert(h2 != NULL);
+    SERF_H2_assert(h2 != NULL);
 
-  /* Did we send a ping? */
+    /* Did we send a ping? */
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -763,85 +770,85 @@ http2_handle_settings(void *baton,
                       const char *data,
                       apr_size_t len)
 {
-  serf_http2_protocol_t *h2 = baton;
-  apr_size_t i;
-  const struct setting_t
-  {
-    unsigned char s1, s0;
-    unsigned char v3, v2, v1, v0;
-  } *setting;
-
-  if ((len % HTTP2_SETTING_SIZE) != 0)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-
-  /* ### TODO: Handle settings */
-  setting = (const void *)data;
-  for (i = 0, setting = (const void *)data;
-       i < len;
-       i += sizeof(*setting), setting++)
-    {
-      apr_uint16_t id = (setting->s1 << 8) | setting->s0;
-      apr_uint32_t value = (setting->v3 << 24) | (setting->v2 << 16)
-                           | (setting->v1 << 8) | setting->v0;
+    serf_http2_protocol_t *h2 = baton;
+    apr_size_t i;
+    const struct setting_t
+    {
+        unsigned char s1, s0;
+        unsigned char v3, v2, v1, v0;
+    } *setting;
+
+    if ((len % HTTP2_SETTING_SIZE) != 0)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+
+      /* ### TODO: Handle settings */
+    setting = (const void *)data;
+    for (i = 0, setting = (const void *)data;
+    i < len;
+        i += sizeof(*setting), setting++)
+    {
+        apr_uint16_t id = (setting->s1 << 8) | setting->s0;
+        apr_uint32_t value = (setting->v3 << 24) | (setting->v2 << 16)
+            | (setting->v1 << 8) | setting->v0;
 
-      switch (id)
+        switch (id)
         {
-          case HTTP2_SETTING_HEADER_TABLE_SIZE:
-            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                      "Setting HPACK Table size to %u\n", value);
-            serf__hpack_table_set_max_table_size(h2->hpack_tbl,
-                                                 h2->rl_hpack_table_size,
-                                                 value);
-            break;
-          case HTTP2_SETTING_ENABLE_PUSH:
-            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                      "Setting Push enabled: %u\n", value);
-            h2->lr_push_enabled = (value != 0);
-            break;
-          case HTTP2_SETTING_MAX_CONCURRENT_STREAMS:
-            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                      "Setting Max Concurrent %u\n", value);
-            h2->lr_max_concurrent = value;
-            break;
-          case HTTP2_SETTING_INITIAL_WINDOW_SIZE:
-            /* Sanitize? */
-            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                      "Setting Initial Window Size %u\n", value);
-            h2->lr_default_window = value;
-            break;
-          case HTTP2_SETTING_MAX_FRAME_SIZE:
-            /* Sanitize? */
-            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                      "Setting Max framesize %u\n", value);
-            h2->lr_max_framesize = value;
-            break;
-          case HTTP2_SETTING_MAX_HEADER_LIST_SIZE:
-            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                      "Setting Max header list size %u\n", value);
-            h2->lr_max_headersize = value;
-            break;
-          default:
-            /* An endpoint that receives a SETTINGS frame with any unknown
-               or unsupported identifier MUST ignore that setting. */
-            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                      "Ignoring unknown setting %d, value %u\n", id, value);
-            break;
+            case HTTP2_SETTING_HEADER_TABLE_SIZE:
+                serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                          "Setting HPACK Table size to %u\n", value);
+                serf__hpack_table_set_max_table_size(h2->hpack_tbl,
+                                                     h2->rl_hpack_table_size,
+                                                     value);
+                break;
+            case HTTP2_SETTING_ENABLE_PUSH:
+                serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                          "Setting Push enabled: %u\n", value);
+                h2->lr_push_enabled = (value != 0);
+                break;
+            case HTTP2_SETTING_MAX_CONCURRENT_STREAMS:
+                serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                          "Setting Max Concurrent %u\n", value);
+                h2->lr_max_concurrent = value;
+                break;
+            case HTTP2_SETTING_INITIAL_WINDOW_SIZE:
+              /* Sanitize? */
+                serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                          "Setting Initial Window Size %u\n", value);
+                h2->lr_default_window = value;
+                break;
+            case HTTP2_SETTING_MAX_FRAME_SIZE:
+              /* Sanitize? */
+                serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                          "Setting Max framesize %u\n", value);
+                h2->lr_max_framesize = value;
+                break;
+            case HTTP2_SETTING_MAX_HEADER_LIST_SIZE:
+                serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                          "Setting Max header list size %u\n", value);
+                h2->lr_max_headersize = value;
+                break;
+            default:
+              /* An endpoint that receives a SETTINGS frame with any unknown
+                 or unsupported identifier MUST ignore that setting. */
+                serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                          "Ignoring unknown setting %d, value %u\n", id, 
value);
+                break;
         }
     }
 
   /* Always ack settings */
-  serf_http2__enqueue_frame(
-                    h2,
-                    serf__bucket_http2_frame_create(
-                                    NULL,
-                                    HTTP2_FRAME_TYPE_SETTINGS,
-                                    HTTP2_FLAG_ACK,
-                                    NULL, NULL, NULL,
-                                    h2->lr_max_framesize,
-                                    h2->allocator),
-                    TRUE);
+    serf_http2__enqueue_frame(
+        h2,
+        serf__bucket_http2_frame_create(
+            NULL,
+            HTTP2_FRAME_TYPE_SETTINGS,
+            HTTP2_FLAG_ACK,
+            NULL, NULL, NULL,
+            h2->lr_max_framesize,
+            h2->allocator),
+        TRUE);
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_bucket_prefix_handler_t.
@@ -852,92 +859,92 @@ http2_handle_goaway(void *baton,
                     const char *data,
                     apr_size_t len)
 {
-  serf_http2_protocol_t *h2 = baton;
-  apr_int32_t last_streamid;
-  apr_uint32_t error_code;
-  apr_uint32_t loglevel;
-  const struct goaway_t
-  {
-    unsigned char s3, s2, s1, s0;
-    unsigned char e3, e2, e1, e0;
-  } *goaway;
-
-  if (len < HTTP2_GOWAWAY_DATA_SIZE)
-    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-
-  SERF_H2_assert(h2 != NULL);
-
-  goaway = (const void *)data;
-
-  last_streamid = ((goaway->s3 & 0x7F) << 24) | (goaway->s2 << 16)
-                  | (goaway->s1 << 8) | goaway->s0;
-  error_code = (goaway->e3 << 24) | (goaway->e2 << 16)
-               | (goaway->e1 << 8) | goaway->e0;
-
-  switch (error_code + SERF_ERROR_HTTP2_NO_ERROR)
-    {
-      case SERF_ERROR_HTTP2_PROTOCOL_ERROR:
-      case SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR:
-      case SERF_ERROR_HTTP2_SETTINGS_TIMEOUT:
-      case SERF_ERROR_HTTP2_FRAME_SIZE_ERROR:
-      case SERF_ERROR_HTTP2_COMPRESSION_ERROR:
-      case SERF_ERROR_HTTP2_INADEQUATE_SECURITY:
-        loglevel = LOGLVL_ERROR;
-        break;
-
-      case SERF_ERROR_HTTP2_HTTP_1_1_REQUIRED:
-      case SERF_ERROR_HTTP2_ENHANCE_YOUR_CALM:
-        loglevel = LOGLVL_WARNING;
-        break;
-
-      case SERF_ERROR_HTTP2_REFUSED_STREAM:
-      case SERF_ERROR_HTTP2_CANCEL:
-      case SERF_ERROR_HTTP2_CONNECT_ERROR:
-      case SERF_ERROR_HTTP2_STREAM_CLOSED:
-        /* These errors should have been sent as a stream
-           error. This usually tells us that we have an http/2
-           implementation on the other side that doesn't implement
-           full stream state handling. (See HTTP/2 RFC)*/
-        loglevel = LOGLVL_ERROR;
-        break;
-
-      case SERF_ERROR_HTTP2_NO_ERROR:
-        loglevel = LOGLVL_INFO;
-        break;
-
-      case SERF_ERROR_HTTP2_INTERNAL_ERROR:
-      default:
-        loglevel = LOGLVL_WARNING;
-        break;
-    }
-
-  if (len > HTTP2_GOWAWAY_DATA_SIZE)
-    {
-      char *goaway_text;
-
-      /* The server produced additional information in the error frame
-         Usually this is some literal text explaining what went wrong.
-
-         Copy the text to make it 0 terminated and then log it. */
-
-      /* If this value appears truncated, that may be caused by the
-         limit set in http2_process */
-
-      goaway_text = serf_bstrmemdup(h2->allocator,
-                                    data + HTTP2_GOWAWAY_DATA_SIZE,
-                                    len - HTTP2_GOWAWAY_DATA_SIZE);
-
-      serf__log(loglevel, SERF_LOGHTTP2, h2->config,
-                "Received GOAWAY, last-stream=0x%x, error=%u: %s\n",
-                last_streamid, error_code, goaway_text);
-
-      serf_bucket_mem_free(h2->allocator, goaway_text);
-    }
-  else
-    {
-      serf__log(loglevel, SERF_LOGHTTP2, h2->config,
-                "Received GOAWAY, last-stream=0x%x, error=%u.\n",
-                last_streamid, error_code);
+    serf_http2_protocol_t *h2 = baton;
+    apr_int32_t last_streamid;
+    apr_uint32_t error_code;
+    apr_uint32_t loglevel;
+    const struct goaway_t
+    {
+        unsigned char s3, s2, s1, s0;
+        unsigned char e3, e2, e1, e0;
+    } *goaway;
+
+    if (len < HTTP2_GOWAWAY_DATA_SIZE)
+        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+
+    SERF_H2_assert(h2 != NULL);
+
+    goaway = (const void *)data;
+
+    last_streamid = ((goaway->s3 & 0x7F) << 24) | (goaway->s2 << 16)
+        | (goaway->s1 << 8) | goaway->s0;
+    error_code = (goaway->e3 << 24) | (goaway->e2 << 16)
+        | (goaway->e1 << 8) | goaway->e0;
+
+    switch (error_code + SERF_ERROR_HTTP2_NO_ERROR)
+    {
+        case SERF_ERROR_HTTP2_PROTOCOL_ERROR:
+        case SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR:
+        case SERF_ERROR_HTTP2_SETTINGS_TIMEOUT:
+        case SERF_ERROR_HTTP2_FRAME_SIZE_ERROR:
+        case SERF_ERROR_HTTP2_COMPRESSION_ERROR:
+        case SERF_ERROR_HTTP2_INADEQUATE_SECURITY:
+            loglevel = LOGLVL_ERROR;
+            break;
+
+        case SERF_ERROR_HTTP2_HTTP_1_1_REQUIRED:
+        case SERF_ERROR_HTTP2_ENHANCE_YOUR_CALM:
+            loglevel = LOGLVL_WARNING;
+            break;
+
+        case SERF_ERROR_HTTP2_REFUSED_STREAM:
+        case SERF_ERROR_HTTP2_CANCEL:
+        case SERF_ERROR_HTTP2_CONNECT_ERROR:
+        case SERF_ERROR_HTTP2_STREAM_CLOSED:
+          /* These errors should have been sent as a stream
+             error. This usually tells us that we have an http/2
+             implementation on the other side that doesn't implement
+             full stream state handling. (See HTTP/2 RFC)*/
+            loglevel = LOGLVL_ERROR;
+            break;
+
+        case SERF_ERROR_HTTP2_NO_ERROR:
+            loglevel = LOGLVL_INFO;
+            break;
+
+        case SERF_ERROR_HTTP2_INTERNAL_ERROR:
+        default:
+            loglevel = LOGLVL_WARNING;
+            break;
+    }
+
+    if (len > HTTP2_GOWAWAY_DATA_SIZE)
+    {
+        char *goaway_text;
+
+        /* The server produced additional information in the error frame
+           Usually this is some literal text explaining what went wrong.
+
+           Copy the text to make it 0 terminated and then log it. */
+
+        /* If this value appears truncated, that may be caused by the
+           limit set in http2_process */
+
+        goaway_text = serf_bstrmemdup(h2->allocator,
+                                      data + HTTP2_GOWAWAY_DATA_SIZE,
+                                      len - HTTP2_GOWAWAY_DATA_SIZE);
+
+        serf__log(loglevel, SERF_LOGHTTP2, h2->config,
+                  "Received GOAWAY, last-stream=0x%x, error=%u: %s\n",
+                  last_streamid, error_code, goaway_text);
+
+        serf_bucket_mem_free(h2->allocator, goaway_text);
+    }
+    else
+    {
+        serf__log(loglevel, SERF_LOGHTTP2, h2->config,
+                  "Received GOAWAY, last-stream=0x%x, error=%u.\n",
+                  last_streamid, error_code);
     }
 
   /* ### TODO: If the error is not critical stop creating new frames
@@ -947,7 +954,7 @@ http2_handle_goaway(void *baton,
                We may receive a new error later, signalling a more
                important problem */
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 
@@ -956,32 +963,32 @@ static apr_status_t
 http2_handle_continuation(void *baton,
                           serf_bucket_t *aggregate_bucket)
 {
-  serf_http2_protocol_t *h2 = baton;
-  apr_status_t status;
-  const char *data;
-  apr_size_t len;
+    serf_http2_protocol_t *h2 = baton;
+    apr_status_t status;
+    const char *data;
+    apr_size_t len;
 
-  if (h2->continuation_bucket != aggregate_bucket)
-    return APR_EOF; /* This is all we have */
+    if (h2->continuation_bucket != aggregate_bucket)
+        return APR_EOF; /* This is all we have */
 
-  SERF_H2_assert(h2->read_frame == NULL);
-  SERF_H2_assert(h2->continuation_bucket == aggregate_bucket);
+    SERF_H2_assert(h2->read_frame == NULL);
+    SERF_H2_assert(h2->continuation_bucket == aggregate_bucket);
 
-  status = http2_process(h2);
-  if (status)
-    return status;
+    status = http2_process(h2);
+    if (status)
+        return status;
 
-  if (h2->continuation_bucket == aggregate_bucket)
+    if (h2->continuation_bucket == aggregate_bucket)
     {
       /* We expect more data in the future. Something
          was done in http2_process() or it didn't
          return APR_SUCCESS */
-      return APR_SUCCESS;
+        return APR_SUCCESS;
     }
 
   /* As h2->continuation_bucket is no longer attached we don't
      recurse on peeking. Just check if there is more */
-  return serf_bucket_peek(aggregate_bucket, &data, &len);
+    return serf_bucket_peek(aggregate_bucket, &data, &len);
 }
 
 /* Implements the serf__bucket_http2_unframe_set_eof callback */
@@ -989,15 +996,15 @@ static apr_status_t
 http2_end_of_frame(void *baton,
                    serf_bucket_t *frame)
 {
-  serf_http2_protocol_t *h2 = baton;
+    serf_http2_protocol_t *h2 = baton;
 
-  SERF_H2_assert(h2->read_frame == frame);
-  h2->read_frame = NULL;
-  h2->in_frame = FALSE;
-  h2->processor = NULL;
-  h2->processor_baton = NULL;
+    SERF_H2_assert(h2->read_frame == frame);
+    h2->read_frame = NULL;
+    h2->in_frame = FALSE;
+    h2->processor = NULL;
+    h2->processor_baton = NULL;
 
-  return APR_SUCCESS;
+    return APR_SUCCESS;
 }
 
 /* Implements serf_http2_processor_t */
@@ -1006,558 +1013,583 @@ http2_bucket_processor(void *baton,
                        serf_http2_protocol_t *h2,
                        serf_bucket_t *frame_bucket)
 {
-  struct iovec vecs[IOV_MAX];
-  int vecs_used;
-  serf_bucket_t *payload = baton;
-  apr_status_t status;
+    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, IOV_MAX,
-                                  vecs, &vecs_used);
+    status = serf_bucket_read_iovec(payload, SERF_READ_ALL_AVAIL, IOV_MAX,
+                                    vecs, &vecs_used);
 
-  if (APR_STATUS_IS_EOF(status))
+    if (APR_STATUS_IS_EOF(status))
     {
-      SERF_H2_assert(!h2->in_frame && !h2->read_frame);
-      serf_bucket_destroy(payload);
+        SERF_H2_assert(!h2->in_frame && !h2->read_frame);
+        serf_bucket_destroy(payload);
     }
 
-  return status;
+    return status;
 }
 
 /* Processes incoming HTTP2 data */
 static apr_status_t
 http2_process(serf_http2_protocol_t *h2)
 {
-  while (TRUE)
+    while (TRUE)
     {
-      apr_status_t status;
-      serf_bucket_t *body;
+        apr_status_t status;
+        serf_bucket_t *body;
 
-      if (h2->processor)
+        if (h2->processor)
         {
-          status = h2->processor(h2->processor_baton, h2, h2->read_frame);
+            status = h2->processor(h2->processor_baton, h2, h2->read_frame);
 
-          if (SERF_BUCKET_READ_ERROR(status))
-            return status;
-          else if (APR_STATUS_IS_EOF(status))
+            if (SERF_BUCKET_READ_ERROR(status))
+                return status;
+            else if (APR_STATUS_IS_EOF(status))
             {
               /* ### frame ended */
-              SERF_H2_assert(h2->read_frame == NULL);
-              h2->processor = NULL;
-              h2->processor_baton = NULL;
+                SERF_H2_assert(h2->read_frame == NULL);
+                h2->processor = NULL;
+                h2->processor_baton = NULL;
             }
-          else if (h2->in_frame)
+            else if (h2->in_frame)
             {
-              if (status)
-                return status;
-              else
-                continue;
+                if (status)
+                    return status;
+                else
+                    continue;
             }
         }
-      else
+        else
         {
-          SERF_H2_assert(!h2->in_frame);
+            SERF_H2_assert(!h2->in_frame);
         }
 
-      body = h2->read_frame;
+        body = h2->read_frame;
 
-      if (! body)
+        if (!body)
         {
-          SERF_H2_assert(!h2->in_frame);
+            SERF_H2_assert(!h2->in_frame);
 
-          body = serf__bucket_http2_unframe_create(
-                                             h2->stream,
-                                             h2->rl_max_framesize,
-                                             h2->allocator);
+            body = serf__bucket_http2_unframe_create(
+                h2->stream,
+                h2->rl_max_framesize,
+                h2->allocator);
 
-          serf__bucket_http2_unframe_set_eof(body,
-                                             http2_end_of_frame, h2);
+            serf__bucket_http2_unframe_set_eof(body,
+                                               http2_end_of_frame, h2);
 
-          serf_bucket_set_config(body, h2->config);
-          h2->read_frame = body;
+            serf_bucket_set_config(body, h2->config);
+            h2->read_frame = body;
         }
 
-      if (! h2->in_frame)
+        if (!h2->in_frame)
         {
-          apr_int32_t sid;
-          unsigned char frametype;
-          unsigned char frameflags;
-          apr_size_t remaining;
-          serf_http2_processor_t process_handler = NULL;
-          void *process_baton = NULL;
-          serf_bucket_t *process_bucket = NULL;
-          serf_http2_stream_t *stream;
-          apr_uint32_t reset_reason;
+            apr_int32_t sid;
+            unsigned char frametype;
+            unsigned char frameflags;
+            apr_size_t remaining;
+            serf_http2_processor_t process_handler = NULL;
+            void *process_baton = NULL;
+            serf_bucket_t *process_bucket = NULL;
+            serf_http2_stream_t *stream;
+            apr_uint32_t reset_reason;
+
+            status = serf__bucket_http2_unframe_read_info(body, &sid,
+                                                          &frametype,
+                                                          &frameflags);
 
-          status = serf__bucket_http2_unframe_read_info(body, &sid,
-                                                        &frametype, 
&frameflags);
-
-          if (APR_STATUS_IS_EOF(status))
+            if (APR_STATUS_IS_EOF(status))
             {
               /* Entire frame is already read (just header) */
-              SERF_H2_assert(h2->read_frame == NULL);
-              SERF_H2_assert(! h2->in_frame);
+                SERF_H2_assert(h2->read_frame == NULL);
+                SERF_H2_assert(!h2->in_frame);
             }
-          else if (status)
+            else if (status)
             {
-              SERF_H2_assert(h2->read_frame != NULL);
-              SERF_H2_assert(! h2->in_frame);
-              return status;
+                SERF_H2_assert(h2->read_frame != NULL);
+                SERF_H2_assert(!h2->in_frame);
+                return status;
             }
-          else
+            else
             {
-              h2->in_frame = TRUE;
-              SERF_H2_assert(h2->read_frame != NULL);
+                h2->in_frame = TRUE;
+                SERF_H2_assert(h2->read_frame != NULL);
             }
 
-          serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
-                    "Reading 0x%x frame, stream=0x%x, flags=0x%x\n",
-                    frametype, sid, frameflags);
+            serf__log(LOGLVL_INFO, SERF_LOGHTTP2, h2->config,
+                      "Reading 0x%x frame, stream=0x%x, flags=0x%x\n",
+                      frametype, sid, frameflags);
 
-          /* If status is EOF then the frame doesn't have/declare a body */
-          switch (frametype)
+            /* If status is EOF then the frame doesn't have/declare a body */
+            switch (frametype)
             {
       /* ---------------------------------------------------- */
-              case HTTP2_FRAME_TYPE_DATA:
-              case HTTP2_FRAME_TYPE_HEADERS:
-              case HTTP2_FRAME_TYPE_PUSH_PROMISE:
-                if (h2->continuation_bucket)
-                  {
-                    h2->continuation_bucket = NULL;
-                    h2->continuation_streamid = 0;
-                    return APR_EAGAIN;
-                  }
-
-                stream = serf_http2__stream_get(h2, sid, TRUE, TRUE);
-
-                if (sid == 0)
-                  {
-                    /* DATA, HEADERS and PUSH_PROMISE:
-
-                      These frames MUST be associated with a stream.  If a
-                      XXX frame is received whose stream identifier field is 
0x0,
-                      the recipient MUST respond with a connection error
-                      (Section 5.4.1) of type PROTOCOL_ERROR. */
-                    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
-                  }
+                case HTTP2_FRAME_TYPE_DATA:
+                case HTTP2_FRAME_TYPE_HEADERS:
+                case HTTP2_FRAME_TYPE_PUSH_PROMISE:
+                    if (h2->continuation_bucket)
+                    {
+                        h2->continuation_bucket = NULL;
+                        h2->continuation_streamid = 0;
+                        return APR_EAGAIN;
+                    }
 
-                reset_reason = 0;
+                    stream = serf_http2__stream_get(h2, sid, TRUE, TRUE);
 
-                if (frametype == HTTP2_FRAME_TYPE_DATA)
-                  {
-                    /* Windowing is applied above padding! */
-                    remaining = (apr_size_t)serf_bucket_get_remaining(body);
+                    if (sid == 0)
+                    {
+                      /* DATA, HEADERS and PUSH_PROMISE:
 
-                    if (h2->rl_window < remaining)
-                      {
-                        if (h2->enforce_flow_control)
-                          reset_reason = SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
+                        These frames MUST be associated with a stream.  If a
+                        XXX frame is received whose stream identifier field is
+                        0x0, the recipient MUST respond with a connection error
+                        (Section 5.4.1) of type PROTOCOL_ERROR. */
+                        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+                    }
 
-                        h2->rl_window = 0;
-                      }
-                    else
-                      h2->rl_window -= remaining;
+                    reset_reason = 0;
 
-                    if (stream)
-                      {
-                        if (stream->rl_window < remaining)
-                          {
-                            if (h2->enforce_flow_control)
-                              reset_reason = 
SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
+                    if (frametype == HTTP2_FRAME_TYPE_DATA)
+                    {
+                      /* Windowing is applied above padding! */
+                        remaining =
+                            (apr_size_t)serf_bucket_get_remaining(body);
+
+                        if (h2->rl_window < remaining)
+                        {
+                            if (h2->enforce_flow_control) {
+                                reset_reason =
+                                    SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
+                            }
 
-                            stream->rl_window = 0;
-                          }
+                            h2->rl_window = 0;
+                        }
                         else
-                          stream->rl_window -= remaining;
-                      }
-                  }
-
-                /* DATA, HEADERS and PUSH_PROMISE can have padding */
-                if (frameflags & HTTP2_FLAG_PADDED)
-                  body = serf__bucket_http2_unpad_create(body, h2->allocator);
-
-                /* An HEADERS frame can have an included priority 'frame' */
-                if (frametype == HTTP2_FRAME_TYPE_HEADERS
-                                        && (frameflags & HTTP2_FLAG_PRIORITY))
-                  {
-                    body = serf_bucket_prefix_create(body,
-                                                     HTTP2_PRIORITY_DATA_SIZE,
-                                                     http2_handle_priority,
-                                                     stream, h2->allocator);
-                  }
-                else if (frametype == HTTP2_FRAME_TYPE_PUSH_PROMISE)
-                  {
-                    body = serf_bucket_prefix_create(body,
-                                                     HTTP2_PROMISE_DATA_SIZE,
-                                                     http2_handle_promise,
-                                                     stream, h2->allocator);
-                  }
-
-                if (!stream)
-                  {
-                    if (!reset_reason)
-                      reset_reason = SERF_ERROR_HTTP2_STREAM_CLOSED;
-                  }
-                else
-                  switch (frametype)
+                            h2->rl_window -= remaining;
+
+                        if (stream)
+                        {
+                            if (stream->rl_window < remaining)
+                            {
+                                if (h2->enforce_flow_control) {
+                                    reset_reason =
+                                        SERF_ERROR_HTTP2_FLOW_CONTROL_ERROR;
+                                }
+
+                                stream->rl_window = 0;
+                            }
+                            else
+                                stream->rl_window -= remaining;
+                        }
+                    }
+
+                  /* DATA, HEADERS and PUSH_PROMISE can have padding */
+                    if (frameflags & HTTP2_FLAG_PADDED) {
+                        body = serf__bucket_http2_unpad_create(body,
+                                                               h2->allocator);
+                    }
+
+                      /* An HEADERS frame can have an included priority 
'frame' */
+                    if (frametype == HTTP2_FRAME_TYPE_HEADERS
+                        && (frameflags & HTTP2_FLAG_PRIORITY))
                     {
-                      case HTTP2_FRAME_TYPE_DATA:
-                        if (stream->status != H2S_OPEN
-                            && stream->status != H2S_HALFCLOSED_LOCAL)
-                          {
-                            reset_reason = SERF_ERROR_HTTP2_STREAM_CLOSED;
-                          }
-                        break;
-                      case HTTP2_FRAME_TYPE_HEADERS:
-                        if (stream->status != H2S_OPEN
-                            && stream->status != H2S_HALFCLOSED_LOCAL
-                            && stream->status != H2S_IDLE
-                            && stream->status != H2S_RESERVED_REMOTE)
-                          {
-                            reset_reason = SERF_ERROR_HTTP2_STREAM_CLOSED;
-                          }
-                        break;
-                      case HTTP2_FRAME_TYPE_PUSH_PROMISE:
-                        if (stream->status != H2S_OPEN
-                            && stream->status != H2S_HALFCLOSED_LOCAL)
-                          {
-                            reset_reason = SERF_ERROR_HTTP2_STREAM_CLOSED;
-                          }
-                        break;
+                        body = serf_bucket_prefix_create(body,
+                                                         
HTTP2_PRIORITY_DATA_SIZE,
+                                                         http2_handle_priority,
+                                                         stream, 
h2->allocator);
+                    }
+                    else if (frametype == HTTP2_FRAME_TYPE_PUSH_PROMISE)
+                    {
+                        body = serf_bucket_prefix_create(body,
+                                                         
HTTP2_PROMISE_DATA_SIZE,
+                                                         http2_handle_promise,
+                                                         stream, 
h2->allocator);
                     }
 
-                if (reset_reason)
-                  {
-                    if (stream)
-                      serf_http2__stream_reset(stream, reset_reason, TRUE);
+                    if (!stream)
+                    {
+                        if (!reset_reason)
+                            reset_reason = SERF_ERROR_HTTP2_STREAM_CLOSED;
+                    }
                     else
-                      serf_http2__enqueue_stream_reset(h2, sid, reset_reason);
-                  }
+                        switch (frametype)
+                        {
+                            case HTTP2_FRAME_TYPE_DATA:
+                                if (stream->status != H2S_OPEN
+                                    && stream->status != H2S_HALFCLOSED_LOCAL)
+                                {
+                                    reset_reason =
+                                        SERF_ERROR_HTTP2_STREAM_CLOSED;
+                                }
+                                break;
+                            case HTTP2_FRAME_TYPE_HEADERS:
+                                if (stream->status != H2S_OPEN
+                                    && stream->status != H2S_HALFCLOSED_LOCAL
+                                    && stream->status != H2S_IDLE
+                                    && stream->status != H2S_RESERVED_REMOTE)
+                                {
+                                    reset_reason =
+                                        SERF_ERROR_HTTP2_STREAM_CLOSED;
+                                }
+                                break;
+                            case HTTP2_FRAME_TYPE_PUSH_PROMISE:
+                                if (stream->status != H2S_OPEN
+                                    && stream->status != H2S_HALFCLOSED_LOCAL)
+                                {
+                                    reset_reason =
+                                        SERF_ERROR_HTTP2_STREAM_CLOSED;
+                                }
+                                break;
+                        }
 
-                if (frametype == HTTP2_FRAME_TYPE_HEADERS
-                    || frametype == HTTP2_FRAME_TYPE_PUSH_PROMISE)
-                  {
-                    if (!(frameflags & HTTP2_FLAG_END_HEADERS))
-                      {
-                        /* This header frame is *directly* followed by
-                           continuation frames... We hide this from the
-                           stream code, by providing an aggregate that will
-                           read through the body of multiple frames */
-
-                        h2->continuation_bucket = serf_bucket_aggregate_create(
-                                                          h2->allocator);
-                        h2->continuation_streamid = sid;
-
-                        serf_bucket_aggregate_append(h2->continuation_bucket,
-                                                     body);
-
-                        serf_bucket_aggregate_hold_open(
-                                      h2->continuation_bucket,
-                                      http2_handle_continuation, h2);
-
-                        body = h2->continuation_bucket;
-                      }
-
-                    if (stream && !reset_reason)
-                      {
-                        body = serf_http2__stream_handle_hpack(
-                                          stream, body, frametype,
-                                          (frameflags & HTTP2_FLAG_END_STREAM),
-                                          HTTP2_MAX_HEADER_ENTRYSIZE,
-                                          h2->hpack_tbl, h2->config,
-                                          h2->allocator);
-                      }
-                    else
-                      {
-                        /* Even when we don't want to process the headers we
-                            must read them to update the HPACK state */
-                        body = serf__bucket_hpack_decode_create(
-                                          body, NULL, NULL,
-                                          HTTP2_MAX_HEADER_ENTRYSIZE,
-                                          h2->hpack_tbl, h2->allocator);
-                      }
-                  }
-                else if (! reset_reason)
-                  {
-                    /* We have a data bucket */
-                    body = serf_http2__stream_handle_data(
-                                        stream, body, frametype,
-                                        (frameflags & HTTP2_FLAG_END_STREAM),
-                                        h2->config, h2->allocator);
-                  }
+                    if (reset_reason)
+                    {
+                        if (stream) {
+                            serf_http2__stream_reset(stream, reset_reason,
+                                                     TRUE);
+                        }
+                        else {
+                            serf_http2__enqueue_stream_reset(h2, sid,
+                                                             reset_reason);
+                        }
+                    }
 
-                if (body)
-                  process_bucket = body; /* We will take care of discarding */
-                else
-                  {
-                    /* The stream wants to handle the reading itself */
-                    process_handler = serf_http2__stream_processor;
-                    process_baton = stream;
-                  }
-                break;
+                    if (frametype == HTTP2_FRAME_TYPE_HEADERS
+                        || frametype == HTTP2_FRAME_TYPE_PUSH_PROMISE)
+                    {
+                        if (!(frameflags & HTTP2_FLAG_END_HEADERS))
+                        {
+                          /* This header frame is *directly* followed by
+                             continuation frames... We hide this from the
+                             stream code, by providing an aggregate that will
+                             read through the body of multiple frames */
+
+                            h2->continuation_bucket =
+                                serf_bucket_aggregate_create(h2->allocator);
+                            h2->continuation_streamid = sid;
+
+                            serf_bucket_aggregate_append(
+                                h2->continuation_bucket, body);
+
+                            serf_bucket_aggregate_hold_open(
+                                h2->continuation_bucket,
+                                http2_handle_continuation, h2);
+
+                            body = h2->continuation_bucket;
+                        }
+
+                        if (stream && !reset_reason)
+                        {
+                            body = serf_http2__stream_handle_hpack(
+                                stream, body, frametype,
+                                (frameflags & HTTP2_FLAG_END_STREAM),
+                                HTTP2_MAX_HEADER_ENTRYSIZE,
+                                h2->hpack_tbl, h2->config,
+                                h2->allocator);
+                        }
+                        else
+                        {
+                          /* Even when we don't want to process the headers we
+                              must read them to update the HPACK state */
+                            body = serf__bucket_hpack_decode_create(
+                                body, NULL, NULL,
+                                HTTP2_MAX_HEADER_ENTRYSIZE,
+                                h2->hpack_tbl, h2->allocator);
+                        }
+                    }
+                    else if (!reset_reason)
+                    {
+                      /* We have a data bucket */
+                        body = serf_http2__stream_handle_data(
+                            stream, body, frametype,
+                            (frameflags & HTTP2_FLAG_END_STREAM),
+                            h2->config, h2->allocator);
+                    }
 
-      /* ---------------------------------------------------- */
-              case HTTP2_FRAME_TYPE_PRIORITY:
-                if (sid == 0)
-                  {
-                    /* The PRIORITY frame always identifies a stream.  If a
-                       PRIORITY frame is received with a stream identifier of
-                       0x0, the recipient MUST respond with a connection error
-                       (Section 5.4.1) of type PROTOCOL_ERROR.*/
+                    if (body) {
+                        /* We will take care of discarding */
+                        process_bucket = body;
+                    }
+                    else
+                    {
+                      /* The stream wants to handle the reading itself */
+                        process_handler = serf_http2__stream_processor;
+                        process_baton = stream;
+                    }
+                    break;
 
-                    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
-                  }
-                else if (serf_bucket_get_remaining(body)
-                                                  != HTTP2_PRIORITY_DATA_SIZE)
-                  {
-                    /* A PRIORITY frame with a length other than 5 octets MUST
-                       be treated as a stream error (Section 5.4.2) of type
-                       FRAME_SIZE_ERROR.*/
-
-                    /* ### But we currently upgrade this to a connection error 
*/
-                    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-                  }
+          /* ---------------------------------------------------- */
+                case HTTP2_FRAME_TYPE_PRIORITY:
+                    if (sid == 0)
+                    {
+                      /* The PRIORITY frame always identifies a stream.  If a
+                         PRIORITY frame is received with a stream identifier
+                         of 0x0, the recipient MUST respond with a connection
+                         error (Section 5.4.1) of type PROTOCOL_ERROR.*/
 
-                stream = serf_http2__stream_get(h2, sid, TRUE, TRUE);
+                        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+                    }
+                    else if (serf_bucket_get_remaining(body)
+                             != HTTP2_PRIORITY_DATA_SIZE)
+                    {
+                      /* A PRIORITY frame with a length other than 5 octets
+                         MUST be treated as a stream error (Section 5.4.2) of
+                         type FRAME_SIZE_ERROR.*/
 
-                if (stream)
-                  {
-                    body = serf_bucket_prefix_create(body,
-                                                     HTTP2_PRIORITY_DATA_SIZE,
-                                                     http2_handle_priority,
-                                                     stream, h2->allocator);
-                  }
+                      /* ### But we currently upgrade this to a connection 
error
+                       */
+                        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+                    }
 
-                /* Just reading will do the right thing now */
-                process_bucket = body;
-                break;
+                    stream = serf_http2__stream_get(h2, sid, TRUE, TRUE);
 
-      /* ---------------------------------------------------- */
-              case HTTP2_FRAME_TYPE_RST_STREAM:
-                if (sid == 0)
-                  {
-                    /* RST_STREAM frames MUST be associated with a stream.
-                       If a RST_STREAM frame is received with a stream
-                       identifier of 0x0, the recipient MUST treat this as a
-                       connection error (Section 5.4.1) of type PROTOCOL_ERROR.
-                     */
+                    if (stream)
+                    {
+                        body = serf_bucket_prefix_create(
+                                            body,
+                                            HTTP2_PRIORITY_DATA_SIZE,
+                                            http2_handle_priority,
+                                            stream, h2->allocator);
+                    }
 
-                    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
-                  }
-                else if (serf_bucket_get_remaining(body)
-                                                  != HTTP2_RST_DATA_SIZE)
-                  {
-                    /* A RST_STREAM frame with a length other than 4 octets 
MUST
-                       be treated as a connection error (Section 5.4.1) of type
-                       FRAME_SIZE_ERROR. */
+                  /* Just reading will do the right thing now */
+                    process_bucket = body;
+                    break;
+
+          /* ---------------------------------------------------- */
+                case HTTP2_FRAME_TYPE_RST_STREAM:
+                    if (sid == 0)
+                    {
+                      /* RST_STREAM frames MUST be associated with a stream.
+                         If a RST_STREAM frame is received with a stream
+                         identifier of 0x0, the recipient MUST treat this as
+                         a connection error (Section 5.4.1) of type
+                         PROTOCOL_ERROR.
+                       */
 
-                    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-                  }
+                        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+                    }
+                    else if (serf_bucket_get_remaining(body)
+                             != HTTP2_RST_DATA_SIZE)
+                    {
+                      /* A RST_STREAM frame with a length other than 4 octets
+                         MUST be treated as a connection error (Section 5.4.1)
+                         of type FRAME_SIZE_ERROR. */
 
-                stream = serf_http2__stream_get(h2, sid, TRUE, TRUE);
+                        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+                    }
 
-                if (stream)
-                  {
-                    body = serf_bucket_prefix_create(body,
-                                                     
HTTP2_FRAME_TYPE_RST_STREAM,
-                                                     http2_handle_frame_reset,
-                                                     stream, h2->allocator);
-                  }
+                    stream = serf_http2__stream_get(h2, sid, TRUE, TRUE);
 
-                /* Just reading will do the right thing now */
-                process_bucket = body;
-                break;
+                    if (stream)
+                    {
+                        body = serf_bucket_prefix_create(
+                                                body,
+                                                HTTP2_FRAME_TYPE_RST_STREAM,
+                                                http2_handle_frame_reset,
+                                                stream, h2->allocator);
+                    }
 
-      /* ---------------------------------------------------- */
-              case HTTP2_FRAME_TYPE_SETTINGS:
-                if (sid != 0)
-                  {
-                    /* SETTINGS frames always apply to a connection, never a
-                       single stream. The stream identifier for a SETTINGS
-                       frame MUST be zero (0x0).  If an endpoint receives a
-                       SETTINGS frame whose stream identifier field is
-                       anything other than 0x0, the endpoint MUST respond
-                       with a connection error (Section 5.4.1) of type
-                       PROTOCOL_ERROR.
-                    */
-                    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
-                  }
+                  /* Just reading will do the right thing now */
+                    process_bucket = body;
+                    break;
+
+          /* ---------------------------------------------------- */
+                case HTTP2_FRAME_TYPE_SETTINGS:
+                    if (sid != 0)
+                    {
+                      /* SETTINGS frames always apply to a connection, never a
+                         single stream. The stream identifier for a SETTINGS
+                         frame MUST be zero (0x0).  If an endpoint receives a
+                         SETTINGS frame whose stream identifier field is
+                         anything other than 0x0, the endpoint MUST respond
+                         with a connection error (Section 5.4.1) of type
+                         PROTOCOL_ERROR.
+                      */
+                        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+                    }
 
-                remaining = (apr_size_t)serf_bucket_get_remaining(body);
-                if (frameflags & HTTP2_FLAG_ACK)
-                  {
-                    if (remaining != 0)
-                      {
-                        /* When this bit is set, the payload of the SETTINGS
-                           frame MUST be empty. Receipt of a SETTINGS frame
-                           with the ACK flag set and a length field value
-                           other than 0 MUST be treated as a connection error
-                           (Section 5.4.1) of type FRAME_SIZE_ERROR. */
+                    remaining = (apr_size_t)serf_bucket_get_remaining(body);
+                    if (frameflags & HTTP2_FLAG_ACK)
+                    {
+                        if (remaining != 0)
+                        {
+                          /* When this bit is set, the payload of the SETTINGS
+                             frame MUST be empty. Receipt of a SETTINGS frame
+                             with the ACK flag set and a length field value
+                             other than 0 MUST be treated as a connection error
+                             (Section 5.4.1) of type FRAME_SIZE_ERROR. */
+                            return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+                        }
+                        h2->setting_acks++;
+                    }
+                    else if ((remaining % HTTP2_SETTING_SIZE) != 0)
+                    {
+                      /* A SETTINGS frame with a length other than a multiple
+                         of 6 octets MUST be treated as a connection error
+                         (Section 5.4.1) of type FRAME_SIZE_ERROR. */
                         return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-                      }
-                    h2->setting_acks++;
-                  }
-                else if ((remaining % HTTP2_SETTING_SIZE) != 0)
-                  {
-                    /* A SETTINGS frame with a length other than a multiple of
-                       6 octets MUST be treated as a connection error (Section
-                       5.4.1) of type FRAME_SIZE_ERROR. */
-                    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-                  }
-                else
-                  {
-                    /* Just read everything... We checked it against our
-                       max-framesize */
-                    body = serf_bucket_prefix_create(body, remaining,
-                                                     http2_handle_settings, h2,
-                                                     h2->allocator);
-                  }
-
-                /* Just reading will do the right thing now */
-                process_bucket = body;
-                break;
+                    }
+                    else
+                    {
+                      /* Just read everything... We checked it against our
+                         max-framesize */
+                        body = serf_bucket_prefix_create(body, remaining,
+                                                         http2_handle_settings,
+                                                         h2, h2->allocator);
+                    }
 
-      /* ---------------------------------------------------- */
-              case HTTP2_FRAME_TYPE_PING:
-                if (sid != 0)
-                  {
-                    /* PING frames are not associated with any individual
-                       stream.  If a PING frame is received with a stream
-                       identifier field value other than 0x0, the recipient
-                       MUST respond with a connection error (Section 5.4.1)
-                       of type PROTOCOL_ERROR.*/
-                    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
-                  }
-                else if (serf_bucket_get_remaining(body)
-                                                  != HTTP2_PING_DATA_SIZE)
-                  {
-                    /* Receipt of a PING frame with a length field value other
-                       than 8 MUST be treated as a connection error (Section
-                       5.4.1) of type FRAME_SIZE_ERROR.. */
-                    return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-                  }
-
-                body = serf_bucket_prefix_create(body, HTTP2_PING_DATA_SIZE,
-                                                 (frameflags & HTTP2_FLAG_ACK)
-                                                   ? http2_handle_ping
-                                                   : http2_handle_ping_ack,
-                                                 h2, h2->allocator);
+                  /* Just reading will do the right thing now */
+                    process_bucket = body;
+                    break;
+
+          /* ---------------------------------------------------- */
+                case HTTP2_FRAME_TYPE_PING:
+                    if (sid != 0)
+                    {
+                      /* PING frames are not associated with any individual
+                         stream.  If a PING frame is received with a stream
+                         identifier field value other than 0x0, the recipient
+                         MUST respond with a connection error (Section 5.4.1)
+                         of type PROTOCOL_ERROR.*/
+                        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+                    }
+                    else if (serf_bucket_get_remaining(body)
+                             != HTTP2_PING_DATA_SIZE)
+                    {
+                      /* Receipt of a PING frame with a length field value
+                         other than 8 MUST be treated as a connection error
+                         (Section 5.4.1) of type FRAME_SIZE_ERROR.. */
+                        return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
+                    }
 
-                /* Just reading will do the right thing now */
-                process_bucket = body;
-                break;
-      /* ---------------------------------------------------- */
-              case HTTP2_FRAME_TYPE_GOAWAY:
-                if (sid != 0)
-                  {
-                    /* The GOAWAY frame applies to the connection, not a
-                       specific stream. An endpoint MUST treat a GOAWAY frame
-                       with a stream identifier other than 0x0 as a connection
-                       error(Section 5.4.1) of type PROTOCOL_ERROR. */
-                    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
-                  }
+                    body = serf_bucket_prefix_create(
+                                            body,
+                                            HTTP2_PING_DATA_SIZE,
+                                            (frameflags & HTTP2_FLAG_ACK)
+                                                    ? http2_handle_ping
+                                                    : http2_handle_ping_ack,
+                                            h2, h2->allocator);
+
+                    /* Just reading will do the right thing now */
+                    process_bucket = body;
+                    break;
+          /* ---------------------------------------------------- */
+                case HTTP2_FRAME_TYPE_GOAWAY:
+                    if (sid != 0)
+                    {
+                      /* The GOAWAY frame applies to the connection, not a
+                         specific stream. An endpoint MUST treat a GOAWAY frame
+                         with a stream identifier other than 0x0 as a
+                         connection error (Section 5.4.1) of type
+                         PROTOCOL_ERROR. */
+                        return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
+                    }
 
-                /* As the final go-away frame is best effort only we are not
-                   checking the bodysize against HTTP2_GOWAWAY_DATA_SIZE here.
-                   We'll see what we get in the goaway handler.
-
-                   Go away frames may contain additional opaque debug
-                   information at the end, so instead of reading
-                   HTTP2_GOWAWAY_DATA_SIZE bytes, we just read the whole frame.
-                 */
-                remaining = (apr_size_t)serf_bucket_get_remaining(body);
-
-                body = serf_bucket_prefix_create(body,
-                                                 MIN(remaining,
-                                                     HTTP2_GOWAWAY_DATA_SIZE
-                                                                        + 256),
-                                                 http2_handle_goaway, h2,
-                                                 h2->allocator);
+                  /* As the final go-away frame is best effort only we are not
+                     checking the bodysize against HTTP2_GOWAWAY_DATA_SIZE
+                     here. We'll see what we get in the goaway handler.
+
+                     Go away frames may contain additional opaque debug
+                     information at the end, so instead of reading
+                     HTTP2_GOWAWAY_DATA_SIZE bytes, we just read the whole 
frame.
+                   */
+                    remaining = (apr_size_t)serf_bucket_get_remaining(body);
 
-                /* Just reading will do the right thing now */
-                process_bucket = body;
-                break;
-      /* ---------------------------------------------------- */
-              case HTTP2_FRAME_TYPE_WINDOW_UPDATE:
-                if (serf_bucket_get_remaining(body)

[... 450 lines stripped ...]


Reply via email to