in buckets/request_buckets.c [397:474]
static apr_status_t serf_incoming_rq_wait_for(serf_bucket_t *bucket,
incoming_rq_status_t wait_for)
{
incoming_request_context_t *ctx = bucket->data;
apr_status_t read_status, status;
if (ctx->state == STATE_TRAILERS && wait_for == STATE_BODY) {
/* We are done with the body, but not with the request.
Can't return EOF yet */
wait_for = STATE_DONE;
}
while (ctx->state < wait_for) {
switch (ctx->state) {
case STATE_INIT:
read_status = serf_linebuf_fetch(&ctx->linebuf, ctx->stream,
SERF_NEWLINE_ANY);
if (SERF_BUCKET_READ_ERROR(read_status))
return read_status;
status = serf_incoming_rq_parse_rqline(bucket);
if (status || read_status)
return status ? status : read_status;
break;
case STATE_HEADERS:
case STATE_TRAILERS:
read_status = serf_linebuf_fetch(&ctx->linebuf, ctx->stream,
SERF_NEWLINE_ANY);
if (SERF_BUCKET_READ_ERROR(read_status))
return read_status;
status = serf_incoming_rq_parse_headerline(bucket);
if (status || read_status)
return status ? status : read_status;
break;
case STATE_PREBODY:
/* TODO: Determine the body type.. Wrap bucket if necessary,
etc.*/
/* What kind of body do we expect */
{
const char *te;
ctx->body = ctx->stream;
te = serf_bucket_headers_get(ctx->headers, "Transfer-Encoding");
if (te && strcasecmp(te, "chunked") == 0) {
ctx->body = serf_bucket_dechunk_create(ctx->stream,
bucket->allocator);
ctx->expect_trailers = true;
}
else {
const char *cl;
cl = serf_bucket_headers_get(ctx->headers, "Content-Length");
if (cl) {
apr_uint64_t length;
length = apr_strtoi64(cl, NULL, 10);
if (errno == ERANGE) {
return APR_FROM_OS_ERROR(ERANGE);
}
ctx->body = serf_bucket_response_body_create(
ctx->body, length, bucket->allocator);
}
}
ctx->state++;
}
break;
case STATE_DONE:
break;
default:
return APR_EGENERAL; /* Should never happen */
}
}
return (ctx->state == STATE_DONE) ? APR_EOF : APR_SUCCESS;
}