#define BF_READ_DONTWAIT 0x400000 /* wake the task up after every read (eg: HTTP request) */
#define BF_AUTO_CONNECT 0x800000 /* consumer may attempt to establish a new connection */
+#define BF_DONT_READ 0x1000000 /* disable reading for now */
+
/* 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))
}
}
+ /* We can shut read side if "connection: close" && !abort_on_close && !content-length */
+ if ((txn->meth == HTTP_METH_GET || txn->meth == HTTP_METH_HEAD) &&
+ (s->flags & SN_CONN_CLOSED) && !(s->be->options & PR_O_ABRT_CLOSE)) {
+ struct hdr_ctx ctx;
+ ctx.idx = 0;
+ if (!http_find_header2("Transfer-Encoding", 17, msg->sol, &txn->hdr_idx, &ctx)) {
+ ctx.idx = 0;
+ if (!http_find_header2("Content-length", 14, msg->sol, &txn->hdr_idx, &ctx))
+ req->flags |= BF_DONT_READ;
+ }
+ }
+
/* that's OK for us now, let's move on to next analysers */
return 1;
/* we're almost sure that we need some space if the buffer is not
* empty, even if it's not full, because the applets can't fill it.
*/
- if ((si->ib->flags & (BF_SHUTR|BF_OUT_EMPTY)) == 0)
+ if ((si->ib->flags & (BF_SHUTR|BF_OUT_EMPTY|BF_DONT_READ)) == 0)
si->flags |= SI_FL_WAIT_ROOM;
if (si->ob->flags & BF_WRITE_ACTIVITY) {
si->ib->rex = tick_add_ifset(now_ms, si->ib->rto);
}
- if (likely((si->ob->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL)) == BF_WRITE_PARTIAL &&
+ if (likely((si->ob->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL|BF_DONT_READ)) == BF_WRITE_PARTIAL &&
(si->ob->prod->flags & SI_FL_WAIT_ROOM)))
si->ob->prod->chk_rcv(si->ob->prod);
switch (si->state) {
case SI_ST_EST:
- if (!(si->ib->flags & BF_SHUTR))
+ if (!(si->ib->flags & (BF_SHUTR|BF_DONT_READ)))
break;
/* fall through */
if (unlikely(si->state != SI_ST_EST || (ib->flags & BF_SHUTR)))
return;
- if (ib->flags & (BF_FULL|BF_HIJACK)) {
+ if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
/* stop reading */
- if ((ib->flags & (BF_FULL|BF_HIJACK)) == BF_FULL)
+ if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
si->flags |= SI_FL_WAIT_ROOM;
}
else {
EV_FD_CLR(fd, DIR_RD);
b->rex = TICK_ETERNITY;
}
- else if ((b->flags & (BF_SHUTR|BF_READ_PARTIAL|BF_FULL|BF_READ_NOEXP)) == BF_READ_PARTIAL)
+ else if ((b->flags & (BF_SHUTR|BF_READ_PARTIAL|BF_FULL|BF_DONT_READ|BF_READ_NOEXP)) == BF_READ_PARTIAL)
b->rex = tick_add_ifset(now_ms, b->rto);
/* we have to wake up if there is a special event or if we don't have
}
/* the producer might be waiting for more room to store data */
- if (likely((b->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL)) == BF_WRITE_PARTIAL &&
+ if (likely((b->flags & (BF_SHUTW|BF_WRITE_PARTIAL|BF_FULL|BF_DONT_READ)) == BF_WRITE_PARTIAL &&
(b->prod->flags & SI_FL_WAIT_ROOM)))
b->prod->chk_rcv(b->prod);
EV_FD_CLR(si->fd, DIR_WR);
shutdown(si->fd, SHUT_WR);
- if (!(si->ib->flags & BF_SHUTR))
+ if (!(si->ib->flags & (BF_SHUTR|BF_DONT_READ)))
return;
/* fall through */
/* Check if we need to close the read side */
if (!(ib->flags & BF_SHUTR)) {
/* Read not closed, update FD status and timeout for reads */
- if (ib->flags & (BF_FULL|BF_HIJACK)) {
+ if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
/* stop reading */
- if ((ib->flags & (BF_FULL|BF_HIJACK)) == BF_FULL)
+ if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
si->flags |= SI_FL_WAIT_ROOM;
EV_FD_COND_C(fd, DIR_RD);
ib->rex = TICK_ETERNITY;
*/
si->flags &= ~SI_FL_WAIT_ROOM;
EV_FD_COND_S(fd, DIR_RD);
- if (!(ib->flags & BF_READ_NOEXP) && !tick_isset(ib->rex))
+ if (!(ib->flags & (BF_READ_NOEXP|BF_DONT_READ)) && !tick_isset(ib->rex))
ib->rex = tick_add_ifset(now_ms, ib->rto);
}
}
if (unlikely(si->state != SI_ST_EST || (ib->flags & BF_SHUTR)))
return;
- if (ib->flags & (BF_FULL|BF_HIJACK)) {
+ if (ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) {
/* stop reading */
- if ((ib->flags & (BF_FULL|BF_HIJACK)) == BF_FULL)
+ if ((ib->flags & (BF_FULL|BF_HIJACK|BF_DONT_READ)) == BF_FULL)
si->flags |= SI_FL_WAIT_ROOM;
EV_FD_COND_C(si->fd, DIR_RD);
}