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,