in buckets/fcgi_buckets.c [657:765]
static apr_status_t serf_fcgi_frame_refill(serf_bucket_t *bucket)
{
fcgi_frame_ctx_t *ctx = bucket->data;
apr_status_t status;
serf_bucket_t *head = NULL;
apr_size_t payload;
if (ctx->at_eof)
return APR_EOF;
if (!ctx->agg)
ctx->agg = serf_bucket_aggregate_create(bucket->allocator);
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,
1, 0xFFFF);
remaining = serf_bucket_get_remaining(head);
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[SERF__STD_IOV_COUNT];
int vecs_used;
status = serf_bucket_read_iovec(head, 0xFFF0, COUNT_OF(vecs),
vecs, &vecs_used);
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_t *tmp;
tmp = serf_bucket_iovec_create(vecs, vecs_used, bucket->allocator);
payload = (apr_size_t)serf_bucket_get_remaining(ctx->agg);
tmp = serf__bucket_event_create(tmp, head, NULL, NULL,
destroy_bucket, bucket->allocator);
serf_bucket_aggregate_append(ctx->agg, tmp);
}
else
payload = 0;
}
if (!payload && !ctx->send_eof)
return APR_SUCCESS;
}
else
{
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 %"
APR_SIZE_T_FMT "\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);
ctx->record_data[2] = (ctx->stream_id >> 8);
ctx->record_data[3] = (ctx->stream_id & 0xFF);
ctx->record_data[4] = (payload >> 8) & 0xFF;
ctx->record_data[5] = (payload & 0xFF);
ctx->record_data[6] = 0; /* padding */
ctx->record_data[7] = 0; /* reserved */
serf_bucket_aggregate_prepend(ctx->agg,
serf_bucket_simple_create(ctx->record_data,
FCGI_RECORD_SIZE,
NULL, NULL,
bucket->allocator));
return APR_SUCCESS;
}