diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index ffaf8ad65..d34cfa4a8 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -65,6 +65,8 @@ enum { SI_FL_NONE = 0x0000, /* nothing */ SI_FL_EXP = 0x0001, /* timeout has expired */ SI_FL_ERR = 0x0002, /* a non-recoverable error has occurred */ + SI_FL_WAIT_ROOM = 0x0004, /* waiting for space to store incoming data */ + SI_FL_WAIT_DATA = 0x0008, /* waiting for more data to send */ }; struct stream_interface { diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 806e09e93..3da304999 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -925,7 +925,7 @@ void uxst_process_session(struct task *t, int *next) s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT; s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT; s->si[0].prev_state = s->si[0].state; - s->si[0].flags = SI_FL_NONE; + s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP); /* Trick: if a request is being waiting for the server to respond, * and if we know the server can timeout, we don't want the timeout diff --git a/src/session.c b/src/session.c index e163fdfb2..a775ba531 100644 --- a/src/session.c +++ b/src/session.c @@ -945,7 +945,8 @@ resync_stream_interface: s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE & BF_CLEAR_TIMEOUT; s->si[0].prev_state = s->si[0].state; s->si[1].prev_state = s->si[1].state; - s->si[0].flags = s->si[1].flags = SI_FL_NONE; + s->si[0].flags &= ~(SI_FL_ERR|SI_FL_EXP); + s->si[1].flags &= ~(SI_FL_ERR|SI_FL_EXP); /* Trick: if a request is being waiting for the server to respond, * and if we know the server can timeout, we don't want the timeout diff --git a/src/stream_sock.c b/src/stream_sock.c index f04307284..72a42c70d 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -86,6 +86,7 @@ int stream_sock_read(int fd) { /* Not anymore room to store data. This should theorically * never happen, but better safe than sorry ! */ + si->flags |= SI_FL_WAIT_ROOM; b->flags |= BF_FULL; EV_FD_CLR(fd, DIR_RD); b->rex = TICK_ETERNITY; @@ -163,6 +164,7 @@ int stream_sock_read(int fd) { b->xfer_large = 0; } + si->flags |= SI_FL_WAIT_ROOM; b->flags |= BF_FULL; EV_FD_CLR(fd, DIR_RD); b->rex = TICK_ETERNITY; @@ -348,6 +350,7 @@ int stream_sock_write(int fd) { * anything. Theorically we cannot get there, but just in case, * let's disable the write event and pretend we never came there. */ + si->flags |= SI_FL_WAIT_DATA; EV_FD_CLR(fd, DIR_WR); b->wex = TICK_ETERNITY; goto out_wakeup; @@ -397,6 +400,7 @@ int stream_sock_write(int fd) { } } + si->flags |= SI_FL_WAIT_DATA; EV_FD_CLR(fd, DIR_WR); b->wex = TICK_ETERNITY; goto out_wakeup; @@ -477,6 +481,7 @@ void stream_sock_shutw(struct stream_interface *si) return; si->ob->flags |= BF_SHUTW; si->ob->wex = TICK_ETERNITY; + si->flags &= ~SI_FL_WAIT_DATA; switch (si->state) { case SI_ST_EST: @@ -487,6 +492,7 @@ void stream_sock_shutw(struct stream_interface *si) } /* fall through */ case SI_ST_CON: + si->flags &= ~SI_FL_WAIT_ROOM; /* we may have to close a pending connection, and mark the * response buffer as shutr */ @@ -513,6 +519,7 @@ void stream_sock_shutr(struct stream_interface *si) return; si->ib->flags |= BF_SHUTR; si->ib->rex = TICK_ETERNITY; + si->flags &= ~SI_FL_WAIT_ROOM; if (si->state != SI_ST_EST && si->state != SI_ST_CON) return; @@ -551,6 +558,8 @@ void stream_sock_data_finish(struct stream_interface *si) /* Read not closed, update FD status and timeout for reads */ if (ib->flags & (BF_FULL|BF_HIJACK)) { /* stop reading */ + if ((ib->flags & (BF_FULL|BF_HIJACK)) == BF_FULL) + si->flags |= SI_FL_WAIT_ROOM; EV_FD_COND_C(fd, DIR_RD); ib->rex = TICK_ETERNITY; } @@ -559,6 +568,7 @@ void stream_sock_data_finish(struct stream_interface *si) * everytime we get here, otherwise it would risk never to expire. We only * update it if is was not yet set, or if we already got some read status. */ + si->flags &= ~SI_FL_WAIT_ROOM; EV_FD_COND_S(fd, DIR_RD); if (!(ib->flags & BF_READ_NOEXP) && (!tick_isset(ib->rex) || ib->flags & BF_READ_ACTIVITY)) @@ -572,6 +582,8 @@ void stream_sock_data_finish(struct stream_interface *si) if ((ob->flags & BF_EMPTY) || (ob->flags & (BF_HIJACK|BF_WRITE_ENA)) == 0) { /* stop writing */ + if ((ob->flags & (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA)) == (BF_EMPTY|BF_WRITE_ENA)) + si->flags |= SI_FL_WAIT_DATA; EV_FD_COND_C(fd, DIR_WR); ob->wex = TICK_ETERNITY; } @@ -580,6 +592,7 @@ void stream_sock_data_finish(struct stream_interface *si) * everytime we get here, otherwise it would risk never to expire. We only * update it if is was not yet set, or if we already got some write status. */ + si->flags &= ~SI_FL_WAIT_DATA; EV_FD_COND_S(fd, DIR_WR); if (!tick_isset(ob->wex) || ob->flags & BF_WRITE_ACTIVITY) { ob->wex = tick_add_ifset(now_ms, ob->wto);