serf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rhuij...@apache.org
Subject svn commit: r1711689 - in /serf/trunk/protocols: http2_protocol.c http2_protocol.h
Date Sat, 31 Oct 2015 21:37:13 GMT
Author: rhuijben
Date: Sat Oct 31 21:37:13 2015
New Revision: 1711689

URL: http://svn.apache.org/viewvc?rev=1711689&view=rev
Log:
In the http2 protocol handler: handle incoming window updates and pass a
proper maximum maximum header entry size, instead of the maximum total entry
size (which currently defaults to +- unlimited).

* protocols/http2_protocol.c
  (http2_handle_stream_window_update,
   http2_handle_connection_window_update): Add implementation.
  (http2_process): Update caller.

* protocols/http2_protocol.h
  (HTTP2_WINDOW_MAX_ALLOWED,
   HTTP2_MAX_HEADER_ENTRYSIZE): New define.

Modified:
    serf/trunk/protocols/http2_protocol.c
    serf/trunk/protocols/http2_protocol.h

Modified: serf/trunk/protocols/http2_protocol.c
URL: http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.c?rev=1711689&r1=1711688&r2=1711689&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.c (original)
+++ serf/trunk/protocols/http2_protocol.c Sat Oct 31 21:37:13 2015
@@ -431,11 +431,49 @@ http2_handle_stream_window_update(void *
                                   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;
+
 
   if (len != HTTP2_WINDOW_UPDATE_DATA_SIZE)
     return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
 
-  SERF_H2_assert(stream->h2 != NULL);
+  window_update = (const void *)data;
+
+  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 */
+
+  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;
+    }
+
+  stream->lr_window += value;
+
+  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-
+         control window to exceed this maximum, it MUST terminate either the
+         stream or the connection, as appropriate.  For streams, the sender
+         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;
+    }
+
+  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;
 }
@@ -449,12 +487,51 @@ http2_handle_connection_window_update(vo
                                       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;
 
   if (len != HTTP2_WINDOW_UPDATE_DATA_SIZE)
     return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
 
   SERF_H2_assert(h2 != NULL);
 
+  window_update = (const void *)data;
+
+  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 */
+
+  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;
+    }
+
+  h2->lr_window += value;
+
+  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-
+         control window to exceed this maximum, it MUST terminate either the
+         stream or the connection, as appropriate.  For streams, the sender
+         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;
+    }
+
+  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;
 }
 
@@ -931,7 +1008,7 @@ http2_process(serf_http2_protocol_t *h2)
                         body = serf_http2__stream_handle_hpack(
                                           stream, body, frametype,
                                           (frameflags & HTTP2_FLAG_END_STREAM),
-                                          h2->rl_max_headersize,
+                                          HTTP2_MAX_HEADER_ENTRYSIZE,
                                           h2->hpack_tbl, h2->config,
                                           h2->allocator);
                       }
@@ -940,7 +1017,8 @@ http2_process(serf_http2_protocol_t *h2)
                         /* 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, h2->rl_max_headersize,
+                                          body, NULL, NULL,
+                                          HTTP2_MAX_HEADER_ENTRYSIZE,
                                           h2->hpack_tbl, h2->allocator);
                       }
                   }

Modified: serf/trunk/protocols/http2_protocol.h
URL: http://svn.apache.org/viewvc/serf/trunk/protocols/http2_protocol.h?rev=1711689&r1=1711688&r2=1711689&view=diff
==============================================================================
--- serf/trunk/protocols/http2_protocol.h (original)
+++ serf/trunk/protocols/http2_protocol.h Sat Oct 31 21:37:13 2015
@@ -55,6 +55,8 @@ extern "C" {
 
 #define HTTP2_SETTING_SIZE              6
 
+#define HTTP2_WINDOW_MAX_ALLOWED        0x7FFFFFF
+
 /* Frame type is an 8 bit unsigned integer */
 
 /* http://tools.ietf.org/html/rfc7540#section-11.2 */
@@ -101,6 +103,9 @@ extern "C" {
 #define HTTP2_CONNECTION_PREFIX "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
 
 
+/* Maximum size for a headerline in HPACK */
+#define HTTP2_MAX_HEADER_ENTRYSIZE          0x20000 /* 128 KByte */
+
 
 /* ------------------------------------- */
 typedef struct serf_http2_protocol_t serf_http2_protocol_t;



Mime
View raw message