Author: rhuijben
Date: Wed Nov 18 01:09:20 2015
New Revision: 1714914

URL: http://svn.apache.org/viewvc?rev=1714914&view=rev
Log:
Resolve several issues in the fcgi frame bucket, to avoid generating
unneeded following frames when done.

* buckets/fcgi_buckets.c
  (fcgi_frame_ctx_t): Add config.
  (destroy_bucket): New function.
  (serf_fcgi_frame_refill): Handle several corner cases. Log written
    records.
  (serf_fcgi_frame_read,
   serf_fcgi_frame_read_iovec,
   serf_fcgi_frame_peek): Handle eof as success in some cases.
  (serf_fcgi_frame_set_config): Store config.

* protocols/fcgi_stream.c
  (fcgi_stream_enqueue_response): Send reason after status. Schedule
    end of request record too.

* test/serf_httpd.c
  (main): Support multiple levels of logging via multiple -v arguments.

Modified:
    serf/trunk/buckets/fcgi_buckets.c
    serf/trunk/protocols/fcgi_stream.c
    serf/trunk/test/serf_httpd.c

Modified: serf/trunk/buckets/fcgi_buckets.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/buckets/fcgi_buckets.c?rev=1714914&r1=1714913&r2=1714914&view=diff
==============================================================================
--- serf/trunk/buckets/fcgi_buckets.c (original)
+++ serf/trunk/buckets/fcgi_buckets.c Wed Nov 18 01:09:20 2015
@@ -610,6 +610,8 @@ typedef struct fcgi_frame_ctx_t
     bool send_eof;
     bool at_eof;
 
+    serf_config_t *config;
+
     char record_data[FCGI_RECORD_SIZE];
 } fcgi_frame_ctx_t;
 
@@ -636,6 +638,14 @@ serf__bucket_fcgi_frame_create(serf_buck
     return serf_bucket_create(&serf_bucket_type__fcgi_frame, alloc, ctx);
 }
 
+static apr_status_t destroy_bucket(void *baton,
+                                   apr_uint64_t bytes_read)
+{
+    serf_bucket_t *head = baton;
+    serf_bucket_destroy(head);
+    return APR_SUCCESS;
+}
+
 static apr_status_t serf_fcgi_frame_refill(serf_bucket_t *bucket)
 {
     fcgi_frame_ctx_t *ctx = bucket->data;
@@ -652,24 +662,29 @@ static apr_status_t serf_fcgi_frame_refi
     if (!ctx->stream)
     {
         payload = 0;
+        ctx->at_eof = true;
+
+        if (ctx->send_stream && !ctx->send_eof)
+            return APR_EOF;
     }
     else if (ctx->send_stream)
     {
         apr_uint64_t remaining;
+
         serf_bucket_split_create(&head, &ctx->stream, ctx->stream,
-                                 8192, 0xFFF0); /* Some guesses */
+                                 1, 0xFFFF);
 
         remaining = serf_bucket_get_remaining(head);
-        if (remaining != SERF_LENGTH_UNKNOWN) {
-            serf_bucket_aggregate_append(ctx->agg, head);
-            payload = (apr_size_t)remaining;
-        }
-        else if (remaining == 0)
+        if (remaining == 0)
         {
             payload = 0;
             serf_bucket_destroy(head);
             ctx->at_eof = true;
         }
+        else if (remaining != SERF_LENGTH_UNKNOWN) {
+            serf_bucket_aggregate_append(ctx->agg, head);
+            payload = (apr_size_t)remaining;
+        }
         else
         {
             struct iovec vecs[IOV_MAX];
@@ -680,30 +695,25 @@ static apr_status_t serf_fcgi_frame_refi
 
             if (SERF_BUCKET_READ_ERROR(status))
                 return status;
+            else if (!APR_STATUS_IS_EOF(status)) {
+                /* No get_remaining()... then the split screen should stop
+                   directly when done reading this amount of vecs */
+                return SERF_ERROR_TRUNCATED_STREAM;
+            }
 
             if (vecs_used) {
-                serf_bucket_aggregate_append_iovec(ctx->agg, vecs, vecs_used);
+                serf_bucket_t *tmp;
+
+                tmp = serf_bucket_iovec_create(vecs, vecs_used, 
bucket->allocator);
                 payload = (apr_size_t)serf_bucket_get_remaining(ctx->agg);
 
-                if (APR_STATUS_IS_EOF(status)) {
-                    /* Keep head alive by appending it to the aggregate */
-                    serf_bucket_aggregate_append(ctx->agg, head);
-                }
-                else {
-                    /* Write a new record for the remaining part of head :( */
-                    serf_bucket_aggregate_append(ctx->agg,
-                                serf__bucket_fcgi_frame_create(head, 
ctx->stream_id,
-                                                            ctx->frame_type,
-                                                            true /* 
send_as_stream */,
-                                                            false /* send_eof 
*/,
-                                                            
bucket->allocator));
-                }
+                tmp = serf__bucket_event_create(tmp, head, NULL, NULL,
+                                                destroy_bucket, 
bucket->allocator);
+
+                serf_bucket_aggregate_append(ctx->agg, tmp);
             }
             else
                 payload = 0;
-
-            if (APR_STATUS_IS_EOF(status))
-                ctx->at_eof = true;
         }
 
         if (!payload && !ctx->send_eof)
@@ -711,9 +721,22 @@ static apr_status_t serf_fcgi_frame_refi
     }
     else
     {
-        abort(); /* ### TODO */
+        apr_uint64_t remaining = serf_bucket_get_remaining(ctx->stream);
+
+        if (remaining >= 0xFFFF)
+            abort(); /* Impossible (or unimplemented yet) */
+
+        payload = (apr_size_t)remaining;
+        ctx->at_eof = true;
+
+        serf_bucket_aggregate_append(ctx->agg, ctx->stream);
+        ctx->stream = NULL;
     }
 
+    serf__log(LOGLVL_DEBUG, LOGCOMP_CONN, __FILE__, ctx->config,
+              "Generating 0x%x frame on stream 0x%x of size 0x%x\n",
+              ctx->frame_type, ctx->stream_id, payload);
+
     /* Create FCGI record */
     ctx->record_data[0] = (ctx->frame_type >> 8);
     ctx->record_data[1] = (ctx->frame_type & 0xFF);
@@ -745,6 +768,8 @@ static apr_status_t serf_fcgi_frame_read
 
         if (!APR_STATUS_IS_EOF(status))
             return status;
+        else if (*len)
+            return APR_SUCCESS;
     }
 
     status = serf_fcgi_frame_refill(bucket);
@@ -776,6 +801,8 @@ static apr_status_t serf_fcgi_frame_read
 
         if (!APR_STATUS_IS_EOF(status))
             return status;
+        else if (*vecs_used)
+            return APR_SUCCESS;
     }
 
     status = serf_fcgi_frame_refill(bucket);
@@ -805,6 +832,8 @@ static apr_status_t serf_fcgi_frame_peek
 
         if (!APR_STATUS_IS_EOF(status))
             return status;
+        else if (*len)
+            return APR_SUCCESS;
     }
 
     status = serf_fcgi_frame_refill(bucket);
@@ -843,6 +872,8 @@ static apr_status_t serf_fcgi_frame_set_
 {
     fcgi_frame_ctx_t *ctx = bucket->data;
 
+    ctx->config = config;
+
     if (!ctx->agg)
         ctx->agg = serf_bucket_aggregate_create(bucket->allocator);
     serf_bucket_set_config(ctx->agg, config);

Modified: serf/trunk/protocols/fcgi_stream.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/protocols/fcgi_stream.c?rev=1714914&r1=1714913&r2=1714914&view=diff
==============================================================================
--- serf/trunk/protocols/fcgi_stream.c (original)
+++ serf/trunk/protocols/fcgi_stream.c Wed Nov 18 01:09:20 2015
@@ -111,7 +111,9 @@ fcgi_stream_enqueue_response(serf_incomi
     tmp = SERF_BUCKET_SIMPLE_STRING("Status: ", alloc);
     serf_bucket_aggregate_append(agg, tmp);
 
-    tmp = serf_bucket_simple_copy_create(linebuf->line + 9, 3, alloc);
+    /* Skip "HTTP/1.1 " but send status and reason */
+    tmp = serf_bucket_simple_copy_create(linebuf->line + 9, linebuf->used - 9,
+                                         alloc);
     serf_bucket_aggregate_append(agg, tmp);
     serf_bucket_mem_free(alloc, linebuf);
 
@@ -120,12 +122,27 @@ fcgi_stream_enqueue_response(serf_incomi
 
     serf_bucket_aggregate_append(agg, response_bkt);
 
-    return serf_fcgi__enqueue_frame(
+    /* Send response over STDOUT, closing stdout when done */
+    status = serf_fcgi__enqueue_frame(
         stream->fcgi,
         serf__bucket_fcgi_frame_create(agg, stream->streamid,
                                        FCGI_FRAMETYPE(FCGI_V1, FCGI_STDOUT),
-                                       true, true,
+                                       true, false,
+                                       alloc), false);
+    if (status)
+        return status;
+
+    /* As we don't use STDERR we don't have to close it either */
+
+    /* Send end of request: FCGI_REQUEST_COMPLETE, exit code 0 */
+    tmp = SERF_BUCKET_SIMPLE_STRING_LEN("\0\0\0\0\0\0\0\0", 8, alloc);
+    status = serf_fcgi__enqueue_frame(
+        stream->fcgi,
+        serf__bucket_fcgi_frame_create(tmp, stream->streamid,
+                                       FCGI_FRAMETYPE(FCGI_V1, 
FCGI_END_REQUEST),
+                                       false, false,
                                        alloc), true);
+    return status;
 }
 
 static apr_status_t

Modified: serf/trunk/test/serf_httpd.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/test/serf_httpd.c?rev=1714914&r1=1714913&r2=1714914&view=diff
==============================================================================
--- serf/trunk/test/serf_httpd.c (original)
+++ serf/trunk/test/serf_httpd.c Wed Nov 18 01:09:20 2015
@@ -151,7 +151,7 @@ static apr_status_t request_generate_res
     serf_bucket_t *tmp;
 #define CRLF "\r\n"
 
-    tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 OK" CRLF, alloc);
+    tmp = SERF_BUCKET_SIMPLE_STRING("HTTP/1.1 200 BOE" CRLF, alloc);
     serf_bucket_aggregate_append(agg, tmp);
 
     tmp = SERF_BUCKET_SIMPLE_STRING("Content-Type: text/plain" CRLF, alloc);
@@ -454,11 +454,18 @@ int main(int argc, const char **argv)
     if (verbose) {
         serf_log_output_t *output;
         apr_status_t status;
+        apr_uint32_t level;
+
+        level = SERF_LOG_WARNING;
+        if (verbose >= 3)
+            level = SERF_LOG_DEBUG;
+        else if (verbose >= 2)
+            level = SERF_LOG_INFO;
 
         status = serf_logging_create_stream_output(
             &output,
             context,
-            SERF_LOG_INFO,
+            level,
             SERF_LOGCOMP_ALL_MSG & ~(SERF_LOGCOMP_RAWMSG | 
SERF_LOGCOMP_SSLMSG),
             SERF_LOG_DEFAULT_LAYOUT,
             stderr,


Reply via email to