serf_bucket_t* accept_response(serf_request_t *request, serf_bucket_t *stream, void *acceptor_baton, apr_pool_t *pool) { serf_bucket_t *c; serf_bucket_alloc_t *bkt_alloc; handler_baton_t *ctx = acceptor_baton; serf_bucket_t *response; /* get the per-request bucket allocator */ bkt_alloc = serf_request_get_alloc(request); /* Create a barrier so the response doesn't eat us! */ c = serf_bucket_barrier_create(stream, bkt_alloc); APR_ARRAY_PUSH(ctx->accepted_requests, int) = ctx->req_id; response = serf_bucket_response_create(c, bkt_alloc); if (strcasecmp(ctx->method, "HEAD") == 0) serf_bucket_response_set_head(response); return response; }
static serf_bucket_t * s_accept_response(serf_request_t *request, serf_bucket_t *stream, void *UNUSED(acceptor_baton), apr_pool_t *UNUSED(pool)) { serf_bucket_alloc_t *bkt_alloc; serf_bucket_t *c; bkt_alloc = serf_request_get_alloc(request); c = serf_bucket_barrier_create(stream, bkt_alloc); return serf_bucket_response_create(c, bkt_alloc); }
static serf_bucket_t* accept_response(serf_request_t *request, serf_bucket_t *stream, void *acceptor_baton, apr_pool_t *pool) { serf_bucket_t *c; serf_bucket_alloc_t *bkt_alloc; /* get the per-request bucket allocator */ bkt_alloc = serf_request_get_alloc(request); /* Create a barrier so the response doesn't eat us! */ c = serf_bucket_barrier_create(stream, bkt_alloc); return serf_bucket_response_create(c, bkt_alloc); }
static serf_bucket_t* accept_response(serf_request_t *request, serf_bucket_t *stream, void *acceptor_baton, apr_pool_t *pool) { serf_bucket_t *c; serf_bucket_t *response; serf_bucket_alloc_t *bkt_alloc; app_baton_t *app_ctx = acceptor_baton; /* get the per-request bucket allocator */ bkt_alloc = serf_request_get_alloc(request); /* Create a barrier so the response doesn't eat us! */ c = serf_bucket_barrier_create(stream, bkt_alloc); response = serf_bucket_response_create(c, bkt_alloc); if (app_ctx->head_request) serf_bucket_response_set_head(response); return response; }
/* Perform one iteration of the state machine. * * Will return when one the following conditions occurred: * 1) a state change * 2) an error * 3) the stream is not ready or at EOF * 4) APR_SUCCESS, meaning the machine can be run again immediately */ static apr_status_t run_machine(serf_bucket_t *bkt, response_context_t *ctx) { apr_status_t status = APR_SUCCESS; /* initialize to avoid gcc warnings */ switch (ctx->state) { case STATE_STATUS_LINE: /* RFC 2616 says that CRLF is the only line ending, but we can easily * accept any kind of line ending. */ status = fetch_line(ctx, SERF_NEWLINE_ANY); if (SERF_BUCKET_READ_ERROR(status)) return status; if (ctx->linebuf.state == SERF_LINEBUF_READY) { /* The Status-Line is in the line buffer. Process it. */ status = parse_status_line(ctx, bkt->allocator); if (status) return status; /* Good times ahead: we're switching protocols! */ if (ctx->sl.code == 101) { ctx->body = serf_bucket_barrier_create(ctx->stream, bkt->allocator); ctx->state = STATE_DONE; break; } /* Okay... move on to reading the headers. */ ctx->state = STATE_HEADERS; } else { /* The connection closed before we could get the next * response. Treat the request as lost so that our upper * end knows the server never tried to give us a response. */ if (APR_STATUS_IS_EOF(status)) { return SERF_ERROR_REQUEST_LOST; } } break; case STATE_HEADERS: status = fetch_headers(bkt, ctx); if (SERF_BUCKET_READ_ERROR(status)) return status; /* If an empty line was read, then we hit the end of the headers. * Move on to the body. */ if (ctx->linebuf.state == SERF_LINEBUF_READY && !ctx->linebuf.used) { const void *v; /* Advance the state. */ ctx->state = STATE_BODY; ctx->body = serf_bucket_barrier_create(ctx->stream, bkt->allocator); /* * Instaweb/mod_pagespeed change: This section is * re-ordered from the original code from serf to Follow * HTTP spec by checking "Transfer-Encoding: chunked", * before "Content-Length". */ /* Are we C-L, chunked, or conn close? */ v = serf_bucket_headers_get(ctx->headers, "Transfer-Encoding"); /* Need to handle multiple transfer-encoding. */ if (v && strcasecmp("chunked", v) == 0) { ctx->chunked = 1; ctx->body = serf_bucket_dechunk_create(ctx->body, bkt->allocator); } else { v = serf_bucket_headers_get(ctx->headers, "Content-Length"); if (v) { apr_uint64_t length; length = apr_strtoi64(v, NULL, 10); if (errno == ERANGE) { return APR_FROM_OS_ERROR(ERANGE); } ctx->body = serf_bucket_limit_create(ctx->body, length, bkt->allocator); } else if ((ctx->sl.code == 204 || ctx->sl.code == 304)) { ctx->state = STATE_DONE; } } /* * Instaweb would prefer to receive gzipped output if that's what * was asked for. * * v = serf_bucket_headers_get(ctx->headers, "Content-Encoding"); * if (v) { * * Need to handle multiple content-encoding. * * if (v && strcasecmp("gzip", v) == 0) { * ctx->body = * serf_bucket_deflate_create(ctx->body, bkt->allocator, * SERF_DEFLATE_GZIP); * } * else if (v && strcasecmp("deflate", v) == 0) { * ctx->body = * serf_bucket_deflate_create(ctx->body, bkt->allocator, * SERF_DEFLATE_DEFLATE); * } * } */ /* If we're a HEAD request, we don't receive a body. */ if (ctx->head_req) { ctx->state = STATE_DONE; } } break; case STATE_BODY: /* Don't do anything. */ break; case STATE_TRAILERS: status = fetch_headers(bkt, ctx); if (SERF_BUCKET_READ_ERROR(status)) return status; /* If an empty line was read, then we're done. */ if (ctx->linebuf.state == SERF_LINEBUF_READY && !ctx->linebuf.used) { ctx->state = STATE_DONE; return APR_EOF; } break; case STATE_DONE: return APR_EOF; default: /* Not reachable */ return APR_EGENERAL; } return status; }