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
/* 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 {
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
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
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;
}
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 */
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);
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
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;
}
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:
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;
}
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) {
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;
- }
-
- /* 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);
+ ret = len;
+ return ret;
}
- 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<CRLF>, and
- * terminate the (empty) trailers section with a last <CRLF>. 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;
+ /* 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;
}
- /* 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;
+ if (!st->initialized) {
+ ret = len;
+ st->sov = ((st->sov > ret) ? (st->sov-ret) : 0);
+ return ret;
}
- 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;
- }
- }
+ 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;
- end:
+ st->initialized = 0;
+ st->sov = 0;
+ msg->next = ret;
+ FLT_NXT(filter, msg->chn) = ret;
+ FLT_FWD(filter, msg->chn) = 0;
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))))
- 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;
-
- LIST_ADDQ(&st->comp_chunks, &cc->list);
- return 0;
-}
-
-/* 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;
-}
-
/***********************************************************************/
/*
* Selects a compression algorithm depending on the client request.
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;
*tail++ = '\r';
*tail++ = '\n';
+ /* At the end of data, we must write the empty chunk 0<CRLF>,
+ * and terminate the trailers section with a last <CRLF>. 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);
.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,
};
/* 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) {
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 */
}
}
* 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;
}
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)
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;
* 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)