Author: rhuijben
Date: Wed Nov 25 00:26:13 2015
New Revision: 1716282

URL: http://svn.apache.org/viewvc?rev=1716282&view=rev
Log:
* buckets/http2_frame_buckets.c
  (serf__bucket_http2_unframe_read_info): When bucket reading doesn't return
    enough bytes but success, read again instead of returning EAGAIN.
  (serf_http2_frame_context_t): Remove unused variable. Add config.
  (serf_http2_frame_get_remaining,
   serf_http2_frame_set_config): New function.
  (serf_bucket_type__http2_frame): Add get remaining and config support.

Modified:
    serf/trunk/buckets/http2_frame_buckets.c

Modified: serf/trunk/buckets/http2_frame_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/http2_frame_buckets.c?rev=1716282&r1=1716281&r2=1716282&view=diff
==============================================================================
--- serf/trunk/buckets/http2_frame_buckets.c (original)
+++ serf/trunk/buckets/http2_frame_buckets.c Wed Nov 25 00:26:13 2015
@@ -87,6 +87,7 @@ serf__bucket_http2_unframe_read_info(ser
     const char *data;
     apr_size_t len;
     apr_status_t status;
+    const unsigned char *header;
 
     if (ctx->prefix_remaining == 0) {
         if (stream_id)
@@ -99,9 +100,11 @@ serf__bucket_http2_unframe_read_info(ser
         return APR_SUCCESS;
     }
 
-    status = serf_bucket_read(ctx->stream, ctx->prefix_remaining, &data, &len);
-    if (!SERF_BUCKET_READ_ERROR(status)) {
-        const unsigned char *header;
+    do
+    {
+        status = serf_bucket_read(ctx->stream, ctx->prefix_remaining, &data, 
&len);
+        if (SERF_BUCKET_READ_ERROR(status))
+            return status;
 
         if (len < FRAME_PREFIX_SIZE) {
             memcpy(ctx->buffer + FRAME_PREFIX_SIZE - ctx->prefix_remaining,
@@ -114,81 +117,79 @@ serf__bucket_http2_unframe_read_info(ser
             header = (const void *)data;
             ctx->prefix_remaining = 0;
         }
+    } while (!status && ctx->prefix_remaining > 0);
 
-        if (ctx->prefix_remaining == 0) {
-            apr_size_t payload_length = (header[0] << 16)
-                | (header[1] << 8)
-                | (header[2]);
-            ctx->frame_type = header[3];
-            ctx->flags = header[4];
-            /* Highest bit of stream_id MUST be ignored */
-            ctx->stream_id = ((header[5] & 0x7F) << 24)
-                | (header[6] << 16)
-                | (header[7] << 8)
-                | (header[8]);
-
-            ctx->payload_remaining = payload_length;
-
-            /* Fill output arguments if necessary */
-            if (stream_id)
-                *stream_id = ctx->stream_id;
-            if (frame_type)
-                *frame_type = ctx->frame_type;
-            if (flags)
-                *flags = ctx->flags;
-
-              /* https://tools.ietf.org/html/rfc7540#section-4.2
-                An endpoint MUST send an error code of FRAME_SIZE_ERROR if a
-                frame exceeds the size defined in SETTINGS_MAX_FRAME_SIZE,
-                exceeds any limit defined for the frame type, or is too small
-                to contain mandatory frame data.
-              */
-            if (ctx->max_payload_size < payload_length)
-            {
-                if (payload_length == 0x485454 && ctx->frame_type == 0x50
-                    && ctx->flags == 0x2F)
-                {
-                  /* We found "HTTP/" instead of an actual frame. This
-                     is clearly above the initial max payload size of 16384,
-                     which applies before we negotiate a bigger size.
-
-                     We found a HTTP/1.1 server that didn't understand our
-                     HTTP2 prefix "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
-                   */
-
-                    return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
-                }
-
-                return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-            }
+    if (ctx->prefix_remaining == 0) {
+        apr_size_t payload_length = (header[0] << 16)
+            | (header[1] << 8)
+            | (header[2]);
+        ctx->frame_type = header[3];
+        ctx->flags = header[4];
+        /* Highest bit of stream_id MUST be ignored */
+        ctx->stream_id = ((header[5] & 0x7F) << 24)
+            | (header[6] << 16)
+            | (header[7] << 8)
+            | (header[8]);
 
-            status = (ctx->payload_remaining == 0) ? APR_EOF
-                : APR_SUCCESS;
+        ctx->payload_remaining = payload_length;
 
-            /* If we hava a zero-length frame we have to call the eof callback
-               now, as the read operations will just shortcut to APR_EOF */
-            if (ctx->payload_remaining == 0 && ctx->end_of_frame) {
-                apr_status_t cb_status;
+        /* Fill output arguments if necessary */
+        if (stream_id)
+            *stream_id = ctx->stream_id;
+        if (frame_type)
+            *frame_type = ctx->frame_type;
+        if (flags)
+            *flags = ctx->flags;
 
-                cb_status = (*ctx->end_of_frame)(ctx->end_of_frame_baton,
-                                                 bucket);
+            /* https://tools.ietf.org/html/rfc7540#section-4.2
+            An endpoint MUST send an error code of FRAME_SIZE_ERROR if a
+            frame exceeds the size defined in SETTINGS_MAX_FRAME_SIZE,
+            exceeds any limit defined for the frame type, or is too small
+            to contain mandatory frame data.
+            */
+        if (ctx->max_payload_size < payload_length)
+        {
+            if (payload_length == 0x485454 && ctx->frame_type == 0x50
+                && ctx->flags == 0x2F)
+            {
+                /* We found "HTTP/" instead of an actual frame. This
+                    is clearly above the initial max payload size of 16384,
+                    which applies before we negotiate a bigger size.
+
+                    We found a HTTP/1.1 server that didn't understand our
+                    HTTP2 prefix "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+                */
 
-                if (SERF_BUCKET_READ_ERROR(cb_status))
-                    status = cb_status;
+                return SERF_ERROR_HTTP2_PROTOCOL_ERROR;
             }
+
+            return SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
         }
-        else if (APR_STATUS_IS_EOF(status)) {
-          /* Reading frame failed because we couldn't read the header. Report
-             a read failure instead of semi-success */
-            if (ctx->prefix_remaining == FRAME_PREFIX_SIZE)
-                status = SERF_ERROR_EMPTY_STREAM;
-            else
-                status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
-        }
-        else if (!status)
-            status = APR_EAGAIN;
 
+        status = (ctx->payload_remaining == 0) ? APR_EOF
+            : APR_SUCCESS;
+
+        /* If we hava a zero-length frame we have to call the eof callback
+            now, as the read operations will just shortcut to APR_EOF */
+        if (ctx->payload_remaining == 0 && ctx->end_of_frame) {
+            apr_status_t cb_status;
+
+            cb_status = (*ctx->end_of_frame)(ctx->end_of_frame_baton,
+                                                bucket);
+
+            if (SERF_BUCKET_READ_ERROR(cb_status))
+                status = cb_status;
+        }
+    }
+    else if (APR_STATUS_IS_EOF(status)) {
+        /* Reading frame failed because we couldn't read the header. Report
+            a read failure instead of semi-success */
+        if (ctx->prefix_remaining == FRAME_PREFIX_SIZE)
+            status = SERF_ERROR_EMPTY_STREAM;
+        else
+            status = SERF_ERROR_HTTP2_FRAME_SIZE_ERROR;
     }
+
     return status;
 }
 
@@ -612,7 +613,7 @@ typedef struct serf_http2_frame_context_
     void *stream_id_baton;
     void(*stream_id_alloc)(void *baton, apr_int32_t *stream_id);
 
-    apr_size_t current_window;
+    serf_config_t *config;
 
 } serf_http2_frame_context_t;
 
@@ -662,7 +663,7 @@ serf__bucket_http2_frame_create(serf_buc
         ctx->stream_id_baton = stream_id_baton;
     }
 
-    ctx->current_window = 0;
+    ctx->config = NULL;
     ctx->created_frame = FALSE;
 
     return serf_bucket_create(&serf_bucket_type__http2_frame, alloc, ctx);
@@ -924,6 +925,26 @@ serf_http2_frame_peek(serf_bucket_t *buc
     return serf_bucket_peek(ctx->chunk, data, len);
 }
 
+static apr_uint64_t
+serf_http2_frame_get_remaining(serf_bucket_t *bucket)
+{
+    serf_http2_frame_context_t *ctx = bucket->data;
+
+    if (!ctx->created_frame)
+        return SERF_LENGTH_UNKNOWN;
+    else
+        return ctx->bytes_remaining;
+}
+
+static apr_status_t
+serf_http2_frame_set_config(serf_bucket_t *bucket,
+                            serf_config_t *config)
+{
+    serf_http2_frame_context_t *ctx = bucket->data;
+    ctx->config = config;
+    return APR_SUCCESS;
+}
+
 static void
 serf_http2_frame_destroy(serf_bucket_t *bucket)
 {
@@ -948,7 +969,7 @@ const serf_bucket_type_t serf_bucket_typ
     serf_http2_frame_peek,
     serf_http2_frame_destroy,
     serf_default_read_bucket,
-    serf_default_get_remaining,
-    serf_default_ignore_config
+    serf_http2_frame_get_remaining,
+    serf_http2_frame_set_config
 };
 


Reply via email to