static apr_status_t serf_incoming_rq_wait_for()

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;
}