diff --git a/include/types/buffers.h b/include/types/buffers.h index 541e1d145..e7ddea4eb 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -115,13 +115,15 @@ #define BF_EXPECT_MORE 0x2000000 /* more data expected to be sent very soon (one-shoot) */ #define BF_SEND_DONTWAIT 0x4000000 /* don't wait for sending data (one-shoot) */ +#define BF_WAKE_ONCE 0x8000000 /* pretend there is activity on this buffer (one-shoot) */ + /* Use these masks to clear the flags before going back to lower layers */ #define BF_CLEAR_READ (~(BF_READ_NULL|BF_READ_PARTIAL|BF_READ_ERROR|BF_READ_ATTACHED)) #define BF_CLEAR_WRITE (~(BF_WRITE_NULL|BF_WRITE_PARTIAL|BF_WRITE_ERROR)) #define BF_CLEAR_TIMEOUT (~(BF_READ_TIMEOUT|BF_WRITE_TIMEOUT|BF_ANA_TIMEOUT)) /* Masks which define input events for stream analysers */ -#define BF_MASK_ANALYSER (BF_READ_ATTACHED|BF_READ_ACTIVITY|BF_READ_TIMEOUT|BF_ANA_TIMEOUT|BF_WRITE_ACTIVITY) +#define BF_MASK_ANALYSER (BF_READ_ATTACHED|BF_READ_ACTIVITY|BF_READ_TIMEOUT|BF_ANA_TIMEOUT|BF_WRITE_ACTIVITY|BF_WAKE_ONCE) /* Mask for static flags which cause analysers to be woken up when they change */ #define BF_MASK_STATIC (BF_OUT_EMPTY|BF_FULL|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW) diff --git a/src/proto_http.c b/src/proto_http.c index 25421bcf8..ed3132324 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2390,7 +2390,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) req->flags |= BF_READ_DONTWAIT; /* try to get back here ASAP */ return 0; } - if (req->l <= req->size - global.tune.maxrewrite) + if (req->r < req->lr || req->r > req->data + req->size - global.tune.maxrewrite) http_buffer_heavy_realign(req, msg); } @@ -2411,6 +2411,7 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit) /* don't let a connection request be initiated */ buffer_dont_connect(req); s->rep->flags &= ~BF_EXPECT_MORE; /* speed up sending a previous response */ + s->rep->analysers |= an_bit; /* wake us up once it changes */ return 0; } } diff --git a/src/session.c b/src/session.c index c34ed9f65..0f5db314a 100644 --- a/src/session.c +++ b/src/session.c @@ -1506,6 +1506,7 @@ struct task *process_session(struct task *t) rq_prod_last = s->si[0].state; rq_cons_last = s->si[1].state; + s->req->flags &= ~BF_WAKE_ONCE; rqf_last = s->req->flags; if ((s->req->flags ^ flags) & BF_MASK_STATIC) @@ -1543,6 +1544,18 @@ struct task *process_session(struct task *t) s->si[1].state != rp_prod_last) { unsigned int flags = s->rep->flags; + if ((s->rep->flags & BF_MASK_ANALYSER) && + (s->rep->analysers & AN_REQ_WAIT_HTTP)) { + /* Due to HTTP pipelining, the HTTP request analyser might be waiting + * for some free space in the response buffer, so we might need to call + * it when something changes in the response buffer, but still we pass + * it the request buffer. Note that the SI state might very well still + * be zero due to us returning a flow of redirects! + */ + s->rep->analysers &= ~AN_REQ_WAIT_HTTP; + s->req->flags |= BF_WAKE_ONCE; + } + if (s->rep->prod->state >= SI_ST_EST) { int max_loops = global.tune.maxpollevents; unsigned int ana_list; @@ -1617,6 +1630,9 @@ struct task *process_session(struct task *t) if (s->req->analysers & ~req_ana_back) goto resync_request; + if ((s->req->flags & ~rqf_last) & BF_MASK_ANALYSER) + goto resync_request; + /* FIXME: here we should call protocol handlers which rely on * both buffers. */