diff --git a/include/proto/filters.h b/include/proto/filters.h index 0e0eb5f30..0eb69a2cd 100644 --- a/include/proto/filters.h +++ b/include/proto/filters.h @@ -92,10 +92,7 @@ int flt_stream_init(struct stream *s); void flt_stream_release(struct stream *s, int only_backend); int flt_http_headers(struct stream *s, struct http_msg *msg); -int flt_http_start_chunk(struct stream *s, struct http_msg *msg); int flt_http_data(struct stream *s, struct http_msg *msg); -int flt_http_last_chunk(struct stream *s, struct http_msg *msg); -int flt_http_end_chunk(struct stream *s, struct http_msg *msg); int flt_http_chunk_trailers(struct stream *s, struct http_msg *msg); int flt_http_end(struct stream *s, struct http_msg *msg); void flt_http_reset(struct stream *s, struct http_msg *msg); diff --git a/include/types/filters.h b/include/types/filters.h index 635b2d191..e3a091dd1 100644 --- a/include/types/filters.h +++ b/include/types/filters.h @@ -105,25 +105,9 @@ struct flt_kw_list { * Returns a negative value if an error occurs, 0 if * it needs to read more data (or to wait for some * reason), any other value otherwise. - * - http_start_chunk : Called when we start to process a new chunk - * (for chunk-encoded request/response only). At this - * step, the chunk length is known and non-null. - * Returns a negative value if an error occurs, 0 if - * it needs to read more data (or to wait for some - * reason), any other value otherwise. * - http_data : Called when unparsed body data are available. * Returns a negative value if an error occurs, else * the number of consumed bytes. - * - http_last_chunk : Called when the last chunk (with a zero length) is - * received. - * Returns a negative value if an error occurs, 0 if - * it needs to read more data (or to wait for some - * reason), any other value otherwise. - * - http_end_chunk : Called at the end of a chunk (expect for the last - * one). - * Returns a negative value if an error occurs, 0 if - * it needs to read more data (or to wait for some - * reason), any other value otherwise. * - http_chunk_trailers : Called when part of trailer headers of a * chunk-encoded request/response are ready to be * processed. @@ -177,10 +161,7 @@ struct flt_ops { * HTTP callbacks */ int (*http_headers) (struct stream *s, struct filter *f, struct http_msg *msg); - int (*http_start_chunk) (struct stream *s, struct filter *f, struct http_msg *msg); int (*http_data) (struct stream *s, struct filter *f, struct http_msg *msg); - int (*http_last_chunk) (struct stream *s, struct filter *f, struct http_msg *msg); - int (*http_end_chunk) (struct stream *s, struct filter *f, struct http_msg *msg); int (*http_chunk_trailers)(struct stream *s, struct filter *f, struct http_msg *msg); int (*http_end) (struct stream *s, struct filter *f, struct http_msg *msg); void (*http_reset) (struct stream *s, struct filter *f, struct http_msg *msg); diff --git a/src/filters.c b/src/filters.c index 01dc5fa8e..88c361246 100644 --- a/src/filters.c +++ b/src/filters.c @@ -415,23 +415,6 @@ flt_http_headers(struct stream *s, struct http_msg *msg) return ret; } -int -flt_http_start_chunk(struct stream *s, struct http_msg *msg) -{ - int ret = 1; - - RESUME_FILTER_LOOP(s, msg->chn) { - if (filter->ops->http_start_chunk) { - ret = filter->ops->http_start_chunk(s, filter, msg); - if (ret <= 0) - BREAK_EXECUTION(s, msg->chn, end); - } - FLT_NXT(filter, msg->chn) += msg->sol; - } RESUME_FILTER_END; - end: - return ret; -} - /* * Calls 'http_data' callback for all "data" filters attached to a stream. This * function is called when incoming data are available (excluding chunks @@ -451,9 +434,14 @@ flt_http_data(struct stream *s, struct http_msg *msg) /* Save buffer state */ buf_i = msg->chn->buf->i; list_for_each_entry(filter, &s->strm_flt.filters, list) { + /* If the HTTP parser is ahead, we update the next offset of the + * current filter. This happens for chunked messages, at the + * begining of a new chunk. */ + if (msg->next > FLT_NXT(filter, msg->chn)) + FLT_NXT(filter, msg->chn) = msg->next; if (filter->ops->http_data && !flt_want_forward_data(filter, msg->chn)) { ret = filter->ops->http_data(s, filter, msg); - if (ret < 0) + if (ret <= 0) break; } else { @@ -466,7 +454,7 @@ flt_http_data(struct stream *s, struct http_msg *msg) ret = MIN(msg->chunk_len + msg->next, msg->chn->buf->i) - FLT_NXT(filter, msg->chn); } - /* Increase FLT_NXT offset of the current filter */ + /* Update the next offset of the current filter */ FLT_NXT(filter, msg->chn) += ret; /* And set this value as the bound for the next filter. It will @@ -478,43 +466,6 @@ flt_http_data(struct stream *s, struct http_msg *msg) return ret; } -int -flt_http_end_chunk(struct stream *s, struct http_msg *msg) -{ - int ret = 1; - - RESUME_FILTER_LOOP(s, msg->chn) { - if (filter->ops->http_end_chunk) { - ret = filter->ops->http_end_chunk(s, filter, msg); - if (ret <= 0) - BREAK_EXECUTION(s, msg->chn, end); - } - flt_reset_forward_data(filter, msg->chn); - FLT_NXT(filter, msg->chn) += msg->sol; - } RESUME_FILTER_END; - end: - return ret; -} - -int -flt_http_last_chunk(struct stream *s, struct http_msg *msg) -{ - int ret = 1; - - RESUME_FILTER_LOOP(s, msg->chn) { - if (filter->ops->http_last_chunk) { - ret = filter->ops->http_last_chunk(s, filter, msg); - if (ret <= 0) - BREAK_EXECUTION(s, msg->chn, end); - } - flt_reset_forward_data(filter, msg->chn); - FLT_NXT(filter, msg->chn) += msg->sol; - } RESUME_FILTER_END; - end: - return ret; -} - - /* * Calls 'http_chunk_trailers' callback for all "data" filters attached to a * stream. This function is called for chunked messages only when a part of the @@ -526,17 +477,23 @@ flt_http_last_chunk(struct stream *s, struct http_msg *msg) int flt_http_chunk_trailers(struct stream *s, struct http_msg *msg) { - int ret = 1; + struct filter *filter; + int ret = 1; - RESUME_FILTER_LOOP(s, msg->chn) { + list_for_each_entry(filter, &s->strm_flt.filters, list) { + /* Be sure to set the next offset of the filter at the right + * place. This is really useful when the first part of the + * trailers was parsed. */ + FLT_NXT(filter, msg->chn) = msg->next; if (filter->ops->http_chunk_trailers) { ret = filter->ops->http_chunk_trailers(s, filter, msg); - if (ret <= 0) - BREAK_EXECUTION(s, msg->chn, end); + if (ret < 0) + break; } + /* Update the next offset of the current filter. Here all data + * are always consumed. */ FLT_NXT(filter, msg->chn) += msg->sol; - } RESUME_FILTER_END; -end: + } return ret; } @@ -610,6 +567,11 @@ flt_http_forward_data(struct stream *s, struct http_msg *msg, unsigned int len) int ret = len; list_for_each_entry(filter, &s->strm_flt.filters, list) { + /* If the HTTP parser is ahead, we update the next offset of the + * current filter. This happens for chunked messages, when the + * chunk envelope is parsed. */ + if (msg->next > FLT_NXT(filter, msg->chn)) + FLT_NXT(filter, msg->chn) = msg->next; if (filter->ops->http_forward_data) { /* Remove bytes that the current filter considered as * forwarded */ diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c index ddc607d4f..5dacc90d7 100644 --- a/src/flt_http_comp.c +++ b/src/flt_http_comp.c @@ -34,29 +34,14 @@ struct flt_ops comp_ops; static struct buffer *tmpbuf = &buf_empty; -struct comp_chunk { - unsigned int start; /* start of the chunk relative to FLT_FWD offset */ - unsigned int end; /* end of the chunk relative to FLT_FWD offset */ - int skip; /* if set to 1, the chunk is skipped. Otherwise it is compressed */ - int is_last; /* if set, this is the last chunk. Data after this - * chunk will be forwarded as it is. */ - struct list list; -}; - struct comp_state { struct comp_ctx *comp_ctx; /* compression context */ struct comp_algo *comp_algo; /* compression algorithm if not NULL */ - struct list comp_chunks; /* data chunks that should be compressed or skipped */ - unsigned int first; /* offset of the first chunk. Data before - * this offset will be forwarded as it - * is. */ + int sov; + int consumed; + int initialized; }; -static int add_comp_chunk(struct comp_state *st, unsigned int start, - unsigned int len, int skip, int is_last); -static int skip_input_data(struct filter *filter, struct http_msg *msg, - unsigned int consumed); - static int select_compression_request_header(struct comp_state *st, struct stream *s, struct http_msg *msg); @@ -70,7 +55,7 @@ static int http_compression_buffer_add_data(struct comp_state *st, struct buffer *out, int sz); static int http_compression_buffer_end(struct comp_state *st, struct stream *s, struct buffer **in, struct buffer **out, - unsigned int consumed, int end); + int end); /***********************************************************************/ static int @@ -104,11 +89,12 @@ comp_start_analyze(struct stream *s, struct filter *filter, struct channel *chn) if (!(st = malloc(sizeof(*st)))) return -1; - LIST_INIT(&st->comp_chunks); - st->comp_algo = NULL; - st->comp_ctx = NULL; - st->first = 0; - filter->ctx = st; + st->comp_algo = NULL; + st->comp_ctx = NULL; + st->sov = 0; + st->consumed = 0; + st->initialized = 0; + filter->ctx = st; } return 1; } @@ -125,6 +111,8 @@ comp_analyze(struct stream *s, struct filter *filter, struct channel *chn, switch (an_bit) { case AN_RES_HTTP_PROCESS_BE: select_compression_response_header(st, s, &s->txn->rsp); + if (st->comp_algo) + st->sov = s->txn->rsp.sov; break; } end: @@ -135,16 +123,10 @@ static int comp_end_analyze(struct stream *s, struct filter *filter, struct channel *chn) { struct comp_state *st = filter->ctx; - struct comp_chunk *cc, *back; if (!st || !(chn->flags & CF_ISRESP)) goto end; - list_for_each_entry_safe(cc, back, &st->comp_chunks, list) { - LIST_DEL(&cc->list); - free(cc); - } - if (!st->comp_algo || !s->txn->status) goto release_ctx; @@ -177,11 +159,10 @@ comp_http_headers(struct stream *s, struct filter *filter, } static int -comp_skip_http_chunk_envelope(struct stream *s, struct filter *filter, - struct http_msg *msg) +comp_http_data(struct stream *s, struct filter *filter, struct http_msg *msg) { struct comp_state *st = filter->ctx; - unsigned int start; + unsigned int len; int ret; if (!(msg->chn->flags & CF_ISRESP) || !st->comp_algo) { @@ -189,227 +170,100 @@ comp_skip_http_chunk_envelope(struct stream *s, struct filter *filter, return 1; } - start = FLT_NXT(filter, msg->chn) - FLT_FWD(filter, msg->chn); - /* If this is the last chunk, we flag it */ - if (msg->chunk_len == 0 && msg->msg_state == HTTP_MSG_CHUNK_SIZE) - ret = add_comp_chunk(st, start, 0, 1, 1); - else - ret = add_comp_chunk(st, start, msg->sol, 1, 0); + len = MIN(msg->chunk_len + msg->next, msg->chn->buf->i) - FLT_NXT(filter, msg->chn); + if (!len) + return len; - return !ret ? 1 : -1; + if (!st->initialized) { + b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->sov); + ret = http_compression_buffer_init(msg->chn->buf, tmpbuf); + b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->sov); + if (ret < 0) { + msg->chn->flags |= CF_WAKE_WRITE; + return 0; + } + } + b_adv(msg->chn->buf, FLT_NXT(filter, msg->chn)); + ret = http_compression_buffer_add_data(st, msg->chn->buf, tmpbuf, len); + b_rew(msg->chn->buf, FLT_NXT(filter, msg->chn)); + if (ret < 0) + return ret; + + st->initialized = 1; + msg->next += ret; + msg->chunk_len -= ret; + FLT_NXT(filter, msg->chn) = msg->next; + return 0; } static int -comp_http_data(struct stream *s, struct filter *filter, - struct http_msg *msg) +comp_http_chunk_trailers(struct stream *s, struct filter *filter, + struct http_msg *msg) { struct comp_state *st = filter->ctx; - unsigned int start; - int is_last, ret; + int ret; - ret = MIN(msg->chunk_len + msg->next, msg->chn->buf->i) - FLT_NXT(filter, msg->chn); if (!(msg->chn->flags & CF_ISRESP) || !st->comp_algo) { flt_set_forward_data(filter, msg->chn); - goto end; + return 1; } - if (!ret) - goto end; - start = FLT_NXT(filter, msg->chn) - FLT_FWD(filter, msg->chn); - is_last = (!(msg->flags & HTTP_MSGF_TE_CHNK) && - (msg->chunk_len == ret - msg->next + FLT_NXT(filter, msg->chn))); + if (!st->initialized) + return 1; - if (add_comp_chunk(st, start, ret, 0, is_last) == -1) - ret = -1; - end: - return ret; + st->consumed = msg->next - st->sov; + b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->sov); + ret = http_compression_buffer_end(st, s, &msg->chn->buf, &tmpbuf, 1); + if (ret < 0) + return ret; + + st->initialized = 0; + st->sov = 0; + msg->next = ret; + FLT_NXT(filter, msg->chn) = ret; + FLT_FWD(filter, msg->chn) = 0; + return 1; } + static int comp_http_forward_data(struct stream *s, struct filter *filter, struct http_msg *msg, unsigned int len) { struct comp_state *st = filter->ctx; - struct comp_chunk *cc, *back; - unsigned int sz, consumed = 0, compressed = 0; - int is_last = 0, ret = len; + int ret; if (!(msg->chn->flags & CF_ISRESP) || !st->comp_algo) { flt_set_forward_data(filter, msg->chn); - goto end; + ret = len; + return ret; } - /* no data to forward or no chunk or the first chunk is too far */ - if (!len || LIST_ISEMPTY(&st->comp_chunks)) - goto end; - if (st->first > len) { - consumed = len; - goto update_chunks; - } - - /* initialize the buffer used to write compressed data */ - b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first); - ret = http_compression_buffer_init(msg->chn->buf, tmpbuf); - b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first); - if (ret < 0) { - msg->chn->flags |= CF_WAKE_WRITE; - return 0; - } - - /* Loop on all chunks */ - list_for_each_entry_safe(cc, back, &st->comp_chunks, list) { - /* current chunk must not be handled yet */ - if (len <= cc->start) { - consumed = len; - break; - } - - /* Get the number of bytes that must be handled in the current - * chunk */ - sz = MIN(len, cc->end) - cc->start; - - if (cc->skip) { - /* No compression for this chunk, data must be - * skipped. This happens when the HTTP response is - * chunked, the chunk envelope is skipped. */ - ret = sz; - } - else { - /* Compress the chunk */ - b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + cc->start); - ret = http_compression_buffer_add_data(st, msg->chn->buf, tmpbuf, sz); - b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn) + cc->start); - if (ret < 0) - goto end; - compressed += ret; - } - - /* Update the chunk by removing consumed bytes. If all bytes are - * consumed, the chunk is removed from the list and we - * loop. Otherwise, we stop here. */ - cc->start += ret; - consumed = cc->start; - if (cc->start != cc->end) - break; - - /* Remember if this is the last chunk */ - is_last = cc->is_last; - LIST_DEL(&cc->list); - free(cc); - } - - if (compressed) { - /* Some data was compressed so we can switch buffers to replace - * uncompressed data by compressed ones. */ - b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first); - ret = http_compression_buffer_end(st, s, &msg->chn->buf, &tmpbuf, - consumed - st->first, is_last); - b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first); - } - else { - /* Here some data was consumed but no compression was - * preformed. This means that all consumed data must be - * skipped. - */ - ret = skip_input_data(filter, msg, consumed); - } - - if (is_last && !(msg->flags & HTTP_MSGF_TE_CHNK)) { - /* At the end of data, if the original response was not - * chunked-encoded, we must write the empty chunk 0, and - * terminate the (empty) trailers section with a last . If - * we're forwarding a chunked-encoded response, these parts are - * preserved and not rewritten. - */ - char *p = bi_end(msg->chn->buf); - memcpy(p, "0\r\n\r\n", 5); - msg->chn->buf->i += 5; - ret += 5; - } - - /* Then, the last step. We need to update state of other filters. */ - if (ret >= 0) { - flt_change_forward_size(filter, msg->chn, -(consumed - st->first - ret)); - msg->next -= (consumed - st->first - ret); - ret += st->first; - } - - update_chunks: - /* Now, we need to update all remaining chunks to keep them synchronized - * with the next position of buf->p. If the chunk list is empty, we - * forward remaining data, if any. */ - st->first -= MIN(st->first, consumed); - if (LIST_ISEMPTY(&st->comp_chunks)) - ret += len - consumed; - else { - list_for_each_entry(cc, &st->comp_chunks, list) { - cc->start -= consumed; - cc->end -= consumed; - } - } - - end: - return ret; -} - -/***********************************************************************/ -static int -add_comp_chunk(struct comp_state *st, unsigned int start, unsigned int len, - int skip, int is_last) -{ - struct comp_chunk *cc; - - if (!(cc = malloc(sizeof(*cc)))) + /* To work, previous filters MUST forward all data */ + if (FLT_FWD(filter, msg->chn) + len != FLT_NXT(filter, msg->chn)) { + Warning("HTTP compression failed: unexpected behavior of previous filters\n"); return -1; - cc->start = start; - cc->end = start + len; - cc->skip = skip; - cc->is_last = is_last; + } - if (LIST_ISEMPTY(&st->comp_chunks)) - st->first = cc->start; + if (!st->initialized) { + ret = len; + st->sov = ((st->sov > ret) ? (st->sov-ret) : 0); + return ret; + } - LIST_ADDQ(&st->comp_chunks, &cc->list); - return 0; -} + st->consumed = len - st->sov; + b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->sov); + ret = http_compression_buffer_end(st, s, &msg->chn->buf, &tmpbuf, + msg->msg_state == HTTP_MSG_ENDING); + if (ret < 0) + return ret; -/* This function might be moved in a filter function, probably with others to - * add/remove/move/replace buffer data */ -static int -skip_input_data(struct filter *filter, struct http_msg *msg, - unsigned int consumed) -{ - struct comp_state *st = filter->ctx; - int block1, block2; - - /* 1. Copy input data, skipping consumed ones. */ - b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first + consumed); - block1 = msg->chn->buf->i; - if (block1 > bi_contig_data(msg->chn->buf)) - block1 = bi_contig_data(msg->chn->buf); - block2 = msg->chn->buf->i - block1; - - memcpy(trash.str, bi_ptr(msg->chn->buf), block1); - if (block2 > 0) - memcpy(trash.str + block1, msg->chn->buf->data, block2); - trash.len = block1 + block2; - b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first + consumed); - - /* 2. Then write back these data at the right place in the buffer */ - b_adv(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first); - block1 = trash.len; - if (block1 > bi_contig_data(msg->chn->buf)) - block1 = bi_contig_data(msg->chn->buf); - block2 = trash.len - block1; - - memcpy(bi_ptr(msg->chn->buf), trash.str, block1); - if (block2 > 0) - memcpy(msg->chn->buf->data, trash.str + block1, block2); - b_rew(msg->chn->buf, FLT_FWD(filter, msg->chn) + st->first); - - /* Then adjut the input size */ - msg->chn->buf->i -= consumed; - return 0; + st->initialized = 0; + st->sov = 0; + msg->next = ret; + FLT_NXT(filter, msg->chn) = ret; + FLT_FWD(filter, msg->chn) = 0; + return ret; } /***********************************************************************/ @@ -740,7 +594,7 @@ http_compression_buffer_add_data(struct comp_state *st, struct buffer *in, static int http_compression_buffer_end(struct comp_state *st, struct stream *s, struct buffer **in, struct buffer **out, - unsigned int consumed, int end) + int end) { struct buffer *ib = *in, *ob = *out; char *tail; @@ -804,21 +658,39 @@ http_compression_buffer_end(struct comp_state *st, struct stream *s, *tail++ = '\r'; *tail++ = '\n'; + /* At the end of data, we must write the empty chunk 0, + * and terminate the trailers section with a last . If + * we're forwarding a chunked-encoded response, we'll have a + * trailers section after the empty chunk which needs to be + * forwarded and which will provide the last CRLF. Otherwise + * we write it ourselves. + */ + if (end) { + struct http_msg *msg = &s->txn->rsp; + + memcpy(tail, "0\r\n", 3); + tail += 3; + if (msg->msg_state == HTTP_MSG_ENDING) { + memcpy(tail, "\r\n", 2); + tail += 2; + } + } + ob->i = tail - ob->p; to_forward = ob->i; /* update input rate */ if (st->comp_ctx && st->comp_ctx->cur_lvl > 0) { - update_freq_ctr(&global.comp_bps_in, consumed); - strm_fe(s)->fe_counters.comp_in += consumed; - s->be->be_counters.comp_in += consumed; + update_freq_ctr(&global.comp_bps_in, st->consumed); + strm_fe(s)->fe_counters.comp_in += st->consumed; + s->be->be_counters.comp_in += st->consumed; } else { - strm_fe(s)->fe_counters.comp_byp += consumed; - s->be->be_counters.comp_byp += consumed; + strm_fe(s)->fe_counters.comp_byp += st->consumed; + s->be->be_counters.comp_byp += st->consumed; } /* copy the remaining data in the tmp buffer. */ - b_adv(ib, consumed); + b_adv(ib, st->consumed); if (ib->i > 0) { left = bi_contig_data(ib); memcpy(ob->p + ob->i, bi_ptr(ib), left); @@ -854,10 +726,8 @@ struct flt_ops comp_ops = { .channel_end_analyze = comp_end_analyze, .http_headers = comp_http_headers, - .http_start_chunk = comp_skip_http_chunk_envelope, - .http_end_chunk = comp_skip_http_chunk_envelope, - .http_last_chunk = comp_skip_http_chunk_envelope, .http_data = comp_http_data, + .http_chunk_trailers = comp_http_chunk_trailers, .http_forward_data = comp_http_forward_data, }; diff --git a/src/proto_http.c b/src/proto_http.c index 3b39e9cef..ab608fedf 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2214,9 +2214,10 @@ static int http_forward_trailers(struct http_msg *msg) /* we have msg->next which points to next line. Look for CRLF. */ while (1) { const char *p1 = NULL, *p2 = NULL; - const char *ptr = b_ptr(buf, msg->next + msg->sol); - const char *stop = bi_end(buf); - int bytes; + const char *start = b_ptr(buf, msg->next + msg->sol); + const char *stop = bi_end(buf); + const char *ptr = start; + int bytes = 0; /* scan current line and stop at LF or CRLF */ while (1) { @@ -2248,19 +2249,17 @@ static int http_forward_trailers(struct http_msg *msg) if (p2 >= buf->data + buf->size) p2 = buf->data; - bytes = p2 - b_ptr(buf, msg->next + msg->sol); + bytes = p2 - start; if (bytes < 0) bytes += buf->size; + msg->sol += bytes; /* LF/CRLF at beginning of line => end of trailers at p2. * Everything was scheduled for forwarding, there's nothing left - * from this message. - */ - if (p1 == b_ptr(buf, msg->next + msg->sol)) { - msg->sol += bytes; + * from this message. */ + if (p1 == start) return 1; - } - msg->sol += bytes; + /* OK, next line then */ } } @@ -5541,27 +5540,15 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) * set ->next to point to the body and switch to DATA or * TRAILERS state. */ - if (!msg->sol) { - ret = http_parse_chunk_size(msg); - if (ret == 0) - goto missing_data; - else if (ret < 0) { - stream_inc_http_err_ctr(s); - if (msg->err_pos >= 0) - http_capture_bad_message(&sess->fe->invalid_req, s, msg, HTTP_MSG_CHUNK_SIZE, s->be); - goto return_bad_req; - } + ret = http_parse_chunk_size(msg); + if (ret == 0) + goto missing_data; + else if (ret < 0) { + stream_inc_http_err_ctr(s); + if (msg->err_pos >= 0) + http_capture_bad_message(&sess->fe->invalid_req, s, msg, HTTP_MSG_CHUNK_SIZE, s->be); + goto return_bad_req; } - if (msg->chunk_len) - FLT_STRM_CB(s, flt_http_start_chunk(s, msg), - /* default_ret */ 1, - /* on_error */ goto return_bad_req, - /* on_wait */ goto missing_data); - else - FLT_STRM_CB(s, flt_http_last_chunk(s, msg), - /* default_ret */ 1, - /* on_error */ goto return_bad_req, - /* on_wait */ goto missing_data); msg->next += msg->sol; msg->sol = 0; msg->msg_state = msg->chunk_len ? HTTP_MSG_DATA : HTTP_MSG_TRAILERS; @@ -5569,41 +5556,31 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) } else if (msg->msg_state == HTTP_MSG_CHUNK_CRLF) { /* we want the CRLF after the data */ - if (!msg->sol) { - ret = http_skip_chunk_crlf(msg); - if (ret == 0) - goto missing_data; - else if (ret < 0) { - stream_inc_http_err_ctr(s); - if (msg->err_pos >= 0) - http_capture_bad_message(&sess->fe->invalid_req, s, msg, HTTP_MSG_CHUNK_CRLF, s->be); - goto return_bad_req; - } + ret = http_skip_chunk_crlf(msg); + if (ret == 0) + goto missing_data; + else if (ret < 0) { + stream_inc_http_err_ctr(s); + if (msg->err_pos >= 0) + http_capture_bad_message(&sess->fe->invalid_req, s, msg, HTTP_MSG_CHUNK_CRLF, s->be); + goto return_bad_req; } - FLT_STRM_CB(s, flt_http_end_chunk(s, msg), - /* default_ret */ 1, - /* on_error */ goto return_bad_req, - /* on_wait */ goto missing_data); msg->next += msg->sol; msg->sol = 0; msg->msg_state = HTTP_MSG_CHUNK_SIZE; /* we're in MSG_CHUNK_SIZE now */ } else if (msg->msg_state == HTTP_MSG_TRAILERS) { - ret = 1; - if (!msg->sol) { - ret = http_forward_trailers(msg); - if (ret < 0) { - stream_inc_http_err_ctr(s); - if (msg->err_pos >= 0) - http_capture_bad_message(&sess->fe->invalid_req, s, msg, HTTP_MSG_TRAILERS, s->be); - goto return_bad_req; - } + ret = http_forward_trailers(msg); + if (ret < 0) { + stream_inc_http_err_ctr(s); + if (msg->err_pos >= 0) + http_capture_bad_message(&sess->fe->invalid_req, s, msg, HTTP_MSG_TRAILERS, s->be); + goto return_bad_req; } FLT_STRM_CB(s, flt_http_chunk_trailers(s, msg), /* default_ret */ 1, - /* on_error */ goto return_bad_req, - /* on_wait */ goto missing_data); + /* on_error */ goto return_bad_req); msg->next += msg->sol; msg->sol = 0; if (!ret) @@ -6866,20 +6843,14 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit case HTTP_MSG_CHUNK_CRLF - HTTP_MSG_DATA: /* we want the CRLF after the data */ - if (!msg->sol) { - ret = http_skip_chunk_crlf(msg); - if (ret == 0) - goto missing_data; - else if (ret < 0) { - if (msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_CHUNK_CRLF, sess->fe); - goto return_bad_res; - } + ret = http_skip_chunk_crlf(msg); + if (ret == 0) + goto missing_data; + else if (ret < 0) { + if (msg->err_pos >= 0) + http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_CHUNK_CRLF, sess->fe); + goto return_bad_res; } - FLT_STRM_CB(s, flt_http_end_chunk(s, msg), - /* default_ret */ 1, - /* on_error */ goto return_bad_res, - /* on_wait */ goto missing_data); msg->next += msg->sol; msg->sol = 0; msg->msg_state = HTTP_MSG_CHUNK_SIZE; @@ -6890,46 +6861,33 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit * set ->next to point to the body and switch to DATA or * TRAILERS state. */ - if (!msg->sol) { - ret = http_parse_chunk_size(msg); - if (ret == 0) - goto missing_data; - else if (ret < 0) { - if (msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_CHUNK_SIZE, sess->fe); - goto return_bad_res; - } + ret = http_parse_chunk_size(msg); + if (ret == 0) + goto missing_data; + else if (ret < 0) { + if (msg->err_pos >= 0) + http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_CHUNK_SIZE, sess->fe); + goto return_bad_res; } - if (msg->chunk_len) - FLT_STRM_CB(s, flt_http_start_chunk(s, msg), - /* default_ret */ 1, - /* on_error */ goto return_bad_res, - /* on_wait */ goto missing_data); - else - FLT_STRM_CB(s, flt_http_last_chunk(s, msg), - /* default_ret */ 1, - /* on_error */ goto return_bad_res, - /* on_wait */ goto missing_data); msg->next += msg->sol; msg->sol = 0; - msg->msg_state = msg->chunk_len ? HTTP_MSG_DATA : HTTP_MSG_TRAILERS; - /* otherwise we're in HTTP_MSG_DATA or HTTP_MSG_TRAILERS state */ - break; + if (msg->chunk_len) { + msg->msg_state = HTTP_MSG_DATA; + break; + } + msg->msg_state = HTTP_MSG_TRAILERS; + /* fall through */ case HTTP_MSG_TRAILERS - HTTP_MSG_DATA: - ret = 1; - if (!msg->sol) { - ret = http_forward_trailers(msg); - if (ret < 0) { - if (msg->err_pos >= 0) - http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_TRAILERS, sess->fe); - goto return_bad_res; - } + ret = http_forward_trailers(msg); + if (ret < 0) { + if (msg->err_pos >= 0) + http_capture_bad_message(&s->be->invalid_rep, s, msg, HTTP_MSG_TRAILERS, sess->fe); + goto return_bad_res; } FLT_STRM_CB(s, flt_http_chunk_trailers(s, msg), /* default_ret */ 1, - /* on_error */ goto return_bad_res, - /* on_wait */ goto missing_data); + /* on_error */ goto return_bad_res); msg->next += msg->sol; msg->sol = 0; if (!ret)