[MEDIUM] buffers: add BF_EMPTY and BF_FULL to remove dependency on req/rep->l

It is not always convenient to run checks on req->l in functions to
check if a buffer is empty or full. Now the stream_sock functions
set flags BF_EMPTY and BF_FULL according to the buffer contents. Of
course, functions which touch the buffer contents adjust the flags
too.
This commit is contained in:
Willy Tarreau 2008-08-16 22:18:07 +02:00
parent ba392cecf9
commit e393fe224b
8 changed files with 111 additions and 54 deletions

View File

@ -40,12 +40,15 @@ int init_buffer();
/* Initializes all fields in the buffer. The ->rlim field is initialized last /* Initializes all fields in the buffer. The ->rlim field is initialized last
* so that the compiler can optimize it away if changed immediately after the * so that the compiler can optimize it away if changed immediately after the
* call to this function. * call to this function. By default, it is set to the full size of the buffer.
* The BF_EMPTY flags is set.
*/ */
static inline void buffer_init(struct buffer *buf) static inline void buffer_init(struct buffer *buf)
{ {
buf->l = buf->total = buf->flags = 0; buf->l = buf->total = 0;
buf->rlim = buf->r = buf->lr = buf->w = buf->data; buf->r = buf->lr = buf->w = buf->data;
buf->flags = BF_EMPTY;
buf->rlim = buf->data + BUFSIZE;
} }
/* returns 1 if the buffer is empty, 0 otherwise */ /* returns 1 if the buffer is empty, 0 otherwise */
@ -59,11 +62,16 @@ static inline int buffer_isfull(const struct buffer *buf) {
return buf->l == BUFSIZE; return buf->l == BUFSIZE;
} }
/* flushes any content from buffer <buf> */ /* flushes any content from buffer <buf> and adjusts flags
* accordingly.
*/
static inline void buffer_flush(struct buffer *buf) static inline void buffer_flush(struct buffer *buf)
{ {
buf->r = buf->lr = buf->w = buf->data; buf->r = buf->lr = buf->w = buf->data;
buf->l = 0; buf->l = 0;
buf->flags |= BF_EMPTY | BF_FULL;
if (buf->rlim)
buf->flags &= ~BF_FULL;
} }
/* marks the buffer as "shutdown" for reads and cancels the timeout */ /* marks the buffer as "shutdown" for reads and cancels the timeout */
@ -91,6 +99,17 @@ static inline int buffer_max(const struct buffer *buf)
return buf->w - buf->r; return buf->w - buf->r;
} }
/* sets the buffer read limit to <size> bytes, and adjusts the FULL
* flag accordingly.
*/
static inline void buffer_set_rlim(struct buffer *buf, int size)
{
buf->rlim = buf->data + size;
if (buf->l < size)
buf->flags &= ~BF_FULL;
else
buf->flags |= BF_FULL;
}
/* /*
* Tries to realign the given buffer, and returns how many bytes can be written * Tries to realign the given buffer, and returns how many bytes can be written

View File

@ -26,8 +26,13 @@
#include <common/memory.h> #include <common/memory.h>
/* The BF_* macros designate Buffer Flags, which may be ORed in the bit field /* The BF_* macros designate Buffer Flags, which may be ORed in the bit field
* member 'flags' in struct buffer. * member 'flags' in struct buffer. Some of them are persistent (BF_SHUT*),
* some of them (BF_EMPTY,BF_FULL) may only be set by the low-level read/write
* functions as well as those who change the buffer's read limit.
*/ */
#define BF_EMPTY 1 /* buffer is empty */
#define BF_FULL 2 /* buffer cannot accept any more data (l >= rlim-data) */
#define BF_SHUTR 4 /* producer has already shut down */ #define BF_SHUTR 4 /* producer has already shut down */
#define BF_SHUTW 8 /* consumer has already shut down */ #define BF_SHUTW 8 /* consumer has already shut down */

View File

@ -49,6 +49,12 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
if (buf->r == buf->data + BUFSIZE) if (buf->r == buf->data + BUFSIZE)
buf->r = buf->data; buf->r = buf->data;
buf->flags &= ~(BF_EMPTY|BF_FULL);
if (buf->l == 0)
buf->flags |= BF_EMPTY;
if (buf->l >= buf->rlim - buf->data)
buf->flags |= BF_FULL;
return -1; return -1;
} }
@ -74,8 +80,14 @@ int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
buf->total += chunk->len; buf->total += chunk->len;
if (buf->r == buf->data + BUFSIZE) if (buf->r == buf->data + BUFSIZE)
buf->r = buf->data; buf->r = buf->data;
chunk->len = 0;
buf->flags &= ~(BF_EMPTY|BF_FULL);
if (buf->l == 0)
buf->flags |= BF_EMPTY;
if (buf->l >= buf->rlim - buf->data)
buf->flags |= BF_FULL;
chunk->len = 0;
return -1; return -1;
} }
@ -110,6 +122,12 @@ int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
if (b->lr > pos) b->lr += delta; if (b->lr > pos) b->lr += delta;
b->l += delta; b->l += delta;
b->flags &= ~(BF_EMPTY|BF_FULL);
if (b->l == 0)
b->flags |= BF_EMPTY;
if (b->l >= b->rlim - b->data)
b->flags |= BF_FULL;
return delta; return delta;
} }
@ -145,6 +163,12 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int
if (b->lr > pos) b->lr += delta; if (b->lr > pos) b->lr += delta;
b->l += delta; b->l += delta;
b->flags &= ~(BF_EMPTY|BF_FULL);
if (b->l == 0)
b->flags |= BF_EMPTY;
if (b->l >= b->rlim - b->data)
b->flags |= BF_FULL;
return delta; return delta;
} }
@ -183,6 +207,12 @@ int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
if (b->lr > pos) b->lr += delta; if (b->lr > pos) b->lr += delta;
b->l += delta; b->l += delta;
b->flags &= ~(BF_EMPTY|BF_FULL);
if (b->l == 0)
b->flags |= BF_EMPTY;
if (b->l >= b->rlim - b->data)
b->flags |= BF_FULL;
return delta; return delta;
} }

View File

@ -333,7 +333,6 @@ int event_accept(int fd) {
goto out_fail_req; /* no memory */ goto out_fail_req; /* no memory */
buffer_init(s->req); buffer_init(s->req);
s->req->rlim += BUFSIZE;
if (p->mode == PR_MODE_HTTP) /* reserve some space for header rewriting */ if (p->mode == PR_MODE_HTTP) /* reserve some space for header rewriting */
s->req->rlim -= MAXREWRITE; s->req->rlim -= MAXREWRITE;

View File

@ -1743,7 +1743,7 @@ int process_request(struct session *t)
* later, so the session will never terminate. We * later, so the session will never terminate. We
* must terminate it now. * must terminate it now.
*/ */
if (unlikely(req->l >= req->rlim - req->data)) { if (unlikely(req->flags & BF_FULL)) {
/* FIXME: check if URI is set and return Status /* FIXME: check if URI is set and return Status
* 414 Request URI too long instead. * 414 Request URI too long instead.
*/ */
@ -2331,7 +2331,7 @@ int process_request(struct session *t)
*/ */
if (!(t->flags & (SN_ASSIGNED|SN_DIRECT)) && if (!(t->flags & (SN_ASSIGNED|SN_DIRECT)) &&
t->txn.meth == HTTP_METH_POST && t->be->url_param_name != NULL && t->txn.meth == HTTP_METH_POST && t->be->url_param_name != NULL &&
t->be->url_param_post_limit != 0 && req->l < BUFSIZE && t->be->url_param_post_limit != 0 && !(req->flags & BF_FULL) &&
memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) { memchr(msg->sol + msg->sl.rq.u, '?', msg->sl.rq.u_l) == NULL) {
/* are there enough bytes here? total == l || r || rlim ? /* are there enough bytes here? total == l || r || rlim ?
* len is unsigned, but eoh is int, * len is unsigned, but eoh is int,
@ -2408,7 +2408,7 @@ int process_request(struct session *t)
* could. Let's switch to the DATA state. * * could. Let's switch to the DATA state. *
************************************************************/ ************************************************************/
req->rlim = req->data + BUFSIZE; /* no more rewrite needed */ buffer_set_rlim(req, BUFSIZE); /* no more rewrite needed */
t->logs.tv_request = now; t->logs.tv_request = now;
/* When a connection is tarpitted, we use the tarpit timeout, /* When a connection is tarpitted, we use the tarpit timeout,
@ -2418,7 +2418,7 @@ int process_request(struct session *t)
* FIXME: this part should be moved elsewhere (eg: on the server side) * FIXME: this part should be moved elsewhere (eg: on the server side)
*/ */
if (txn->flags & TX_CLTARPIT) { if (txn->flags & TX_CLTARPIT) {
t->req->l = 0; buffer_flush(t->req);
/* flush the request so that we can drop the connection early /* flush the request so that we can drop the connection early
* if the client closes first. * if the client closes first.
*/ */
@ -2502,8 +2502,7 @@ int process_request(struct session *t)
* buffer closed). * buffer closed).
*/ */
if (req->l - body >= limit || /* enough bytes! */ if (req->l - body >= limit || /* enough bytes! */
req->l >= req->rlim - req->data || /* full */ req->flags & (BF_FULL | BF_READ_ERROR | BF_READ_NULL | BF_READ_TIMEOUT)) {
req->flags & (BF_READ_ERROR | BF_READ_NULL | BF_READ_TIMEOUT)) {
/* The situation will not evolve, so let's give up on the analysis. */ /* The situation will not evolve, so let's give up on the analysis. */
t->logs.tv_request = now; /* update the request timer to reflect full request */ t->logs.tv_request = now; /* update the request timer to reflect full request */
t->analysis &= ~AN_REQ_HTTP_BODY; t->analysis &= ~AN_REQ_HTTP_BODY;
@ -2542,9 +2541,9 @@ int process_response(struct session *t)
* For the parsing, we use a 28 states FSM. * For the parsing, we use a 28 states FSM.
* *
* Here is the information we currently have : * Here is the information we currently have :
* rep->data + req->som = beginning of response * rep->data + rep->som = beginning of response
* rep->data + req->eoh = end of processed headers / start of current one * rep->data + rep->eoh = end of processed headers / start of current one
* rep->data + req->eol = end of current header or line (LF or CRLF) * rep->data + rep->eol = end of current header or line (LF or CRLF)
* rep->lr = first non-visited byte * rep->lr = first non-visited byte
* rep->r = end of data * rep->r = end of data
*/ */
@ -2644,7 +2643,7 @@ int process_response(struct session *t)
return 1; return 1;
} }
/* too large response does not fit in buffer. */ /* too large response does not fit in buffer. */
else if (rep->l >= rep->rlim - rep->data) { else if (rep->flags & BF_FULL) {
goto hdr_response_bad; goto hdr_response_bad;
} }
/* read timeout : return a 504 to the client. */ /* read timeout : return a 504 to the client. */
@ -2948,7 +2947,7 @@ int process_response(struct session *t)
* could. Let's switch to the DATA state. * * could. Let's switch to the DATA state. *
************************************************************/ ************************************************************/
rep->rlim = rep->data + BUFSIZE; /* no more rewrite needed */ buffer_set_rlim(rep, BUFSIZE); /* no more rewrite needed */
t->logs.t_data = tv_ms_elapsed(&t->logs.tv_accept, &now); t->logs.t_data = tv_ms_elapsed(&t->logs.tv_accept, &now);
#ifdef CONFIG_HAP_TCPSPLICE #ifdef CONFIG_HAP_TCPSPLICE
@ -3049,7 +3048,7 @@ int process_cli(struct session *t)
* allowed to forward the data. * allowed to forward the data.
*/ */
else if (!(rep->flags & BF_SHUTW) && /* already done */ else if (!(rep->flags & BF_SHUTW) && /* already done */
rep->l == 0 && rep->flags & BF_MAY_FORWARD && rep->flags & BF_EMPTY && rep->flags & BF_MAY_FORWARD &&
rep->flags & BF_SHUTR && !(t->flags & SN_SELF_GEN)) { rep->flags & BF_SHUTR && !(t->flags & SN_SELF_GEN)) {
buffer_shutw(rep); buffer_shutw(rep);
if (!(req->flags & BF_SHUTR)) { if (!(req->flags & BF_SHUTR)) {
@ -3129,7 +3128,7 @@ int process_cli(struct session *t)
/* manage read timeout */ /* manage read timeout */
if (!(req->flags & BF_SHUTR)) { if (!(req->flags & BF_SHUTR)) {
if (req->l >= req->rlim - req->data) { if (req->flags & BF_FULL) {
/* no room to read more data */ /* no room to read more data */
if (EV_FD_COND_C(t->cli_fd, DIR_RD)) { if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
/* stop reading until we get some space */ /* stop reading until we get some space */
@ -3148,7 +3147,7 @@ int process_cli(struct session *t)
*/ */
if (req->flags & BF_SHUTR && t->flags & SN_SELF_GEN) { if (req->flags & BF_SHUTR && t->flags & SN_SELF_GEN) {
produce_content(t); produce_content(t);
if (rep->l == 0) { if (rep->flags & BF_EMPTY) {
buffer_shutw(rep); buffer_shutw(rep);
fd_delete(t->cli_fd); fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE; t->cli_state = CL_STCLOSE;
@ -3158,7 +3157,7 @@ int process_cli(struct session *t)
} }
/* we don't enable client write if the buffer is empty, nor if the server has to analyze it */ /* we don't enable client write if the buffer is empty, nor if the server has to analyze it */
if ((rep->l == 0) || !(rep->flags & BF_MAY_FORWARD)) { if ((rep->flags & BF_EMPTY) || !(rep->flags & BF_MAY_FORWARD)) {
if (EV_FD_COND_C(t->cli_fd, DIR_WR)) { if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
/* stop writing */ /* stop writing */
rep->wex = TICK_ETERNITY; rep->wex = TICK_ETERNITY;
@ -3227,7 +3226,7 @@ int process_srv(struct session *t)
if (t->srv_state == SV_STIDLE) { if (t->srv_state == SV_STIDLE) {
if ((rep->flags & BF_SHUTW) || if ((rep->flags & BF_SHUTW) ||
((req->flags & BF_SHUTR) && ((req->flags & BF_SHUTR) &&
(req->l == 0 || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */ (req->flags & BF_EMPTY || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
req->cex = TICK_ETERNITY; req->cex = TICK_ETERNITY;
if (t->pend_pos) if (t->pend_pos)
t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now); t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
@ -3359,7 +3358,7 @@ int process_srv(struct session *t)
else if (t->srv_state == SV_STCONN) { /* connection in progress */ else if (t->srv_state == SV_STCONN) { /* connection in progress */
if ((rep->flags & BF_SHUTW) || if ((rep->flags & BF_SHUTW) ||
((req->flags & BF_SHUTR) && ((req->flags & BF_SHUTR) &&
((req->l == 0 && !(req->flags & BF_WRITE_STATUS)) || ((req->flags & BF_EMPTY && !(req->flags & BF_WRITE_STATUS)) ||
t->be->options & PR_O_ABRT_CLOSE))) { /* give up */ t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
req->cex = TICK_ETERNITY; req->cex = TICK_ETERNITY;
if (!(t->flags & SN_CONN_TAR)) { if (!(t->flags & SN_CONN_TAR)) {
@ -3458,10 +3457,10 @@ int process_srv(struct session *t)
else { /* no error or write 0 */ else { /* no error or write 0 */
t->logs.t_connect = tv_ms_elapsed(&t->logs.tv_accept, &now); t->logs.t_connect = tv_ms_elapsed(&t->logs.tv_accept, &now);
if (req->l == 0) /* nothing to write */ { if (req->flags & BF_EMPTY) {
EV_FD_CLR(t->srv_fd, DIR_WR); EV_FD_CLR(t->srv_fd, DIR_WR);
req->wex = TICK_ETERNITY; req->wex = TICK_ETERNITY;
} else /* need the right to write */ { } else {
EV_FD_SET(t->srv_fd, DIR_WR); EV_FD_SET(t->srv_fd, DIR_WR);
req->wex = tick_add_ifset(now_ms, t->be->timeout.server); req->wex = tick_add_ifset(now_ms, t->be->timeout.server);
if (tick_isset(req->wex)) { if (tick_isset(req->wex)) {
@ -3475,7 +3474,7 @@ int process_srv(struct session *t)
EV_FD_SET(t->srv_fd, DIR_RD); EV_FD_SET(t->srv_fd, DIR_RD);
rep->rex = tick_add_ifset(now_ms, t->be->timeout.server); rep->rex = tick_add_ifset(now_ms, t->be->timeout.server);
t->srv_state = SV_STDATA; t->srv_state = SV_STDATA;
rep->rlim = rep->data + BUFSIZE; /* no rewrite needed */ buffer_set_rlim(rep, BUFSIZE); /* no rewrite needed */
/* if the user wants to log as soon as possible, without counting /* if the user wants to log as soon as possible, without counting
bytes from the server, then this is the right moment. */ bytes from the server, then this is the right moment. */
@ -3493,7 +3492,7 @@ int process_srv(struct session *t)
else { else {
t->srv_state = SV_STDATA; t->srv_state = SV_STDATA;
t->analysis |= AN_RTR_HTTP_HDR; t->analysis |= AN_RTR_HTTP_HDR;
rep->rlim = rep->data + BUFSIZE - MAXREWRITE; /* rewrite needed */ buffer_set_rlim(rep, BUFSIZE - MAXREWRITE); /* rewrite needed */
t->txn.rsp.msg_state = HTTP_MSG_RPBEFORE; t->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
/* reset hdr_idx which was already initialized by the request. /* reset hdr_idx which was already initialized by the request.
* right now, the http parser does it. * right now, the http parser does it.
@ -3558,7 +3557,7 @@ int process_srv(struct session *t)
* coming from the server. * coming from the server.
*/ */
else if (!(req->flags & BF_SHUTW) && /* not already done */ else if (!(req->flags & BF_SHUTW) && /* not already done */
req->l == 0 && req->flags & BF_MAY_FORWARD && req->flags & BF_EMPTY && req->flags & BF_MAY_FORWARD &&
(req->flags & BF_SHUTR || (req->flags & BF_SHUTR ||
(t->be->options & PR_O_FORCE_CLO && rep->flags & BF_READ_STATUS))) { (t->be->options & PR_O_FORCE_CLO && rep->flags & BF_READ_STATUS))) {
buffer_shutw(req); buffer_shutw(req);
@ -3642,7 +3641,7 @@ int process_srv(struct session *t)
/* manage read timeout */ /* manage read timeout */
if (!(rep->flags & BF_SHUTR)) { if (!(rep->flags & BF_SHUTR)) {
if (rep->l >= rep->rlim - rep->data) { if (rep->flags & BF_FULL) {
if (EV_FD_COND_C(t->srv_fd, DIR_RD)) if (EV_FD_COND_C(t->srv_fd, DIR_RD))
rep->rex = TICK_ETERNITY; rep->rex = TICK_ETERNITY;
} else { } else {
@ -3653,7 +3652,7 @@ int process_srv(struct session *t)
/* manage write timeout */ /* manage write timeout */
if (!(req->flags & BF_SHUTW)) { if (!(req->flags & BF_SHUTW)) {
if (req->l == 0 || !(req->flags & BF_MAY_FORWARD)) { if (req->flags & BF_EMPTY || !(req->flags & BF_MAY_FORWARD)) {
/* stop writing */ /* stop writing */
if (EV_FD_COND_C(t->srv_fd, DIR_WR)) if (EV_FD_COND_C(t->srv_fd, DIR_WR))
req->wex = TICK_ETERNITY; req->wex = TICK_ETERNITY;
@ -5101,7 +5100,7 @@ int stats_check_uri_auth(struct session *t, struct proxy *backend)
EV_FD_CLR(t->cli_fd, DIR_RD); EV_FD_CLR(t->cli_fd, DIR_RD);
buffer_shutr(t->req); buffer_shutr(t->req);
buffer_shutr(t->rep); buffer_shutr(t->rep);
t->req->rlim = t->req->data + BUFSIZE; /* no more rewrite needed */ buffer_set_rlim(t->req, BUFSIZE); /* no more rewrite needed */
t->logs.tv_request = now; t->logs.tv_request = now;
t->data_source = DATA_SRC_STATS; t->data_source = DATA_SRC_STATS;
t->data_state = DATA_ST_INIT; t->data_state = DATA_ST_INIT;

View File

@ -483,8 +483,6 @@ int uxst_event_accept(int fd) {
buffer_init(s->req); buffer_init(s->req);
buffer_init(s->rep); buffer_init(s->rep);
s->req->rlim += BUFSIZE;
s->rep->rlim += BUFSIZE;
fd_insert(cfd); fd_insert(cfd);
fdtab[cfd].owner = t; fdtab[cfd].owner = t;
@ -582,7 +580,7 @@ static int process_uxst_cli(struct session *t)
return 1; return 1;
} }
/* last server read and buffer empty */ /* last server read and buffer empty */
else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) { else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->flags & BF_EMPTY)) {
EV_FD_CLR(t->cli_fd, DIR_WR); EV_FD_CLR(t->cli_fd, DIR_WR);
buffer_shutw(rep); buffer_shutw(rep);
shutdown(t->cli_fd, SHUT_WR); shutdown(t->cli_fd, SHUT_WR);
@ -635,7 +633,7 @@ static int process_uxst_cli(struct session *t)
return 1; return 1;
} }
if (req->l >= req->rlim - req->data) { if (req->flags & BF_FULL) {
/* no room to read more data */ /* no room to read more data */
if (EV_FD_COND_C(t->cli_fd, DIR_RD)) { if (EV_FD_COND_C(t->cli_fd, DIR_RD)) {
/* stop reading until we get some space */ /* stop reading until we get some space */
@ -657,7 +655,7 @@ static int process_uxst_cli(struct session *t)
} }
} }
if ((rep->l == 0) || if ((rep->flags & BF_EMPTY) ||
((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) { ((s < SV_STDATA) /* FIXME: this may be optimized && (rep->w == rep->h)*/)) {
if (EV_FD_COND_C(t->cli_fd, DIR_WR)) { if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
/* stop writing */ /* stop writing */
@ -694,7 +692,7 @@ static int process_uxst_cli(struct session *t)
} }
return 1; return 1;
} }
else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->l == 0)) { else if ((s == SV_STSHUTR || s == SV_STCLOSE) && (rep->flags & BF_EMPTY)) {
buffer_shutw(rep); buffer_shutw(rep);
fd_delete(t->cli_fd); fd_delete(t->cli_fd);
t->cli_state = CL_STCLOSE; t->cli_state = CL_STCLOSE;
@ -717,7 +715,7 @@ static int process_uxst_cli(struct session *t)
return 1; return 1;
} }
if (rep->l == 0) { if (rep->flags & BF_EMPTY) {
if (EV_FD_COND_C(t->cli_fd, DIR_WR)) { if (EV_FD_COND_C(t->cli_fd, DIR_WR)) {
/* stop writing */ /* stop writing */
rep->wex = TICK_ETERNITY; rep->wex = TICK_ETERNITY;
@ -770,7 +768,7 @@ static int process_uxst_cli(struct session *t)
} }
return 1; return 1;
} }
else if (req->l >= req->rlim - req->data) { else if (req->flags & BF_FULL) {
/* no room to read more data */ /* no room to read more data */
/* FIXME-20050705: is it possible for a client to maintain a session /* FIXME-20050705: is it possible for a client to maintain a session
@ -821,7 +819,7 @@ static int process_uxst_srv(struct session *t)
if (s == SV_STIDLE) { if (s == SV_STIDLE) {
if (c == CL_STCLOSE || c == CL_STSHUTW || if (c == CL_STCLOSE || c == CL_STSHUTW ||
(c == CL_STSHUTR && (c == CL_STSHUTR &&
(t->req->l == 0 || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */ (t->req->flags & BF_EMPTY || t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
tv_eternity(&req->cex); tv_eternity(&req->cex);
if (t->pend_pos) if (t->pend_pos)
t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now); t->logs.t_queue = tv_ms_elapsed(&t->logs.tv_accept, &now);
@ -870,7 +868,7 @@ static int process_uxst_srv(struct session *t)
else if (s == SV_STCONN) { /* connection in progress */ else if (s == SV_STCONN) { /* connection in progress */
if (c == CL_STCLOSE || c == CL_STSHUTW || if (c == CL_STCLOSE || c == CL_STSHUTW ||
(c == CL_STSHUTR && (c == CL_STSHUTR &&
((t->req->l == 0 && !(req->flags & BF_WRITE_STATUS)) || ((t->req->flags & BF_EMPTY && !(req->flags & BF_WRITE_STATUS)) ||
t->be->options & PR_O_ABRT_CLOSE))) { /* give up */ t->be->options & PR_O_ABRT_CLOSE))) { /* give up */
tv_eternity(&req->cex); tv_eternity(&req->cex);
fd_delete(t->srv_fd); fd_delete(t->srv_fd);
@ -941,7 +939,7 @@ static int process_uxst_srv(struct session *t)
t->logs.t_connect = tv_ms_elapsed(&t->logs.tv_accept, &now); t->logs.t_connect = tv_ms_elapsed(&t->logs.tv_accept, &now);
//fprintf(stderr,"3: c=%d, s=%d\n", c, s); //fprintf(stderr,"3: c=%d, s=%d\n", c, s);
if (req->l == 0) /* nothing to write */ { if (req->flags & BF_EMPTY) /* nothing to write */ {
EV_FD_CLR(t->srv_fd, DIR_WR); EV_FD_CLR(t->srv_fd, DIR_WR);
tv_eternity(&req->wex); tv_eternity(&req->wex);
} else /* need the right to write */ { } else /* need the right to write */ {
@ -962,7 +960,7 @@ static int process_uxst_srv(struct session *t)
t->srv_state = SV_STDATA; t->srv_state = SV_STDATA;
if (t->srv) if (t->srv)
t->srv->cum_sess++; t->srv->cum_sess++;
rep->rlim = rep->data + BUFSIZE; /* no rewrite needed */ buffer_set_rlim(rep, BUFSIZE); /* no rewrite needed */
/* if the user wants to log as soon as possible, without counting /* if the user wants to log as soon as possible, without counting
bytes from the server, then this is the right moment. */ bytes from the server, then this is the right moment. */
@ -1007,7 +1005,7 @@ static int process_uxst_srv(struct session *t)
return 1; return 1;
} }
/* end of client read and no more data to send */ /* end of client read and no more data to send */
else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) { else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->flags & BF_EMPTY)) {
EV_FD_CLR(t->srv_fd, DIR_WR); EV_FD_CLR(t->srv_fd, DIR_WR);
buffer_shutw(req); buffer_shutw(req);
shutdown(t->srv_fd, SHUT_WR); shutdown(t->srv_fd, SHUT_WR);
@ -1048,7 +1046,7 @@ static int process_uxst_srv(struct session *t)
} }
/* recompute request time-outs */ /* recompute request time-outs */
if (req->l == 0) { if (req->flags & BF_EMPTY) {
if (EV_FD_COND_C(t->srv_fd, DIR_WR)) { if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
/* stop writing */ /* stop writing */
tv_eternity(&req->wex); tv_eternity(&req->wex);
@ -1106,7 +1104,7 @@ static int process_uxst_srv(struct session *t)
return 1; return 1;
} }
else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->l == 0)) { else if ((c == CL_STSHUTR || c == CL_STCLOSE) && (req->flags & BF_EMPTY)) {
//EV_FD_CLR(t->srv_fd, DIR_WR); //EV_FD_CLR(t->srv_fd, DIR_WR);
buffer_shutw(req); buffer_shutw(req);
fd_delete(t->srv_fd); fd_delete(t->srv_fd);
@ -1142,7 +1140,7 @@ static int process_uxst_srv(struct session *t)
return 1; return 1;
} }
else if (req->l == 0) { else if (req->flags & BF_EMPTY) {
if (EV_FD_COND_C(t->srv_fd, DIR_WR)) { if (EV_FD_COND_C(t->srv_fd, DIR_WR)) {
/* stop writing */ /* stop writing */
tv_eternity(&req->wex); tv_eternity(&req->wex);
@ -1263,8 +1261,8 @@ void process_uxst_session(struct task *t, int *next)
continue; continue;
} }
if (s->cli_state == CL_STSHUTR || if (s->cli_state == CL_STSHUTR ||
(s->req->l >= s->req->rlim - s->req->data)) { (s->req->flags & BF_FULL)) {
if (s->req->l == 0) { if (s->req->flags & BF_EMPTY) {
s->srv_state = SV_STCLOSE; s->srv_state = SV_STCLOSE;
fsm_resync |= 1; fsm_resync |= 1;
continue; continue;
@ -1275,7 +1273,7 @@ void process_uxst_session(struct task *t, int *next)
*/ */
memcpy(s->rep->data, s->req->data, sizeof(s->rep->data)); memcpy(s->rep->data, s->req->data, sizeof(s->rep->data));
s->rep->l = s->req->l; s->rep->l = s->req->l;
s->rep->rlim = s->rep->data + BUFSIZE; buffer_set_rlim(s->rep, BUFSIZE);
s->rep->w = s->rep->data; s->rep->w = s->rep->data;
s->rep->lr = s->rep->r = s->rep->data + s->rep->l; s->rep->lr = s->rep->r = s->rep->data + s->rep->l;

View File

@ -51,13 +51,13 @@ void client_retnclose(struct session *s, const struct chunk *msg)
EV_FD_CLR(s->cli_fd, DIR_RD); EV_FD_CLR(s->cli_fd, DIR_RD);
EV_FD_SET(s->cli_fd, DIR_WR); EV_FD_SET(s->cli_fd, DIR_WR);
buffer_shutr(s->req); buffer_shutr(s->req);
buffer_flush(s->req);
s->rep->wex = tick_add_ifset(now_ms, s->rep->wto); s->rep->wex = tick_add_ifset(now_ms, s->rep->wto);
s->rep->flags |= BF_MAY_FORWARD; s->rep->flags |= BF_MAY_FORWARD;
s->cli_state = CL_STSHUTR; // FIXME: still used by unix sockets s->cli_state = CL_STSHUTR; // FIXME: still used by unix sockets
buffer_flush(s->rep); buffer_flush(s->rep);
if (msg && msg->len) if (msg && msg->len)
buffer_write(s->rep, msg->str, msg->len); buffer_write(s->rep, msg->str, msg->len);
s->req->l = 0;
} }
@ -69,10 +69,10 @@ void client_retnclose(struct session *s, const struct chunk *msg)
*/ */
void client_return(struct session *s, const struct chunk *msg) void client_return(struct session *s, const struct chunk *msg)
{ {
buffer_flush(s->req);
buffer_flush(s->rep); buffer_flush(s->rep);
if (msg && msg->len) if (msg && msg->len)
buffer_write(s->rep, msg->str, msg->len); buffer_write(s->rep, msg->str, msg->len);
s->req->l = 0;
} }
/* /*

View File

@ -84,6 +84,7 @@ int stream_sock_read(int fd) {
/* Not anymore room to store data. This should theorically /* Not anymore room to store data. This should theorically
* never happen, but better safe than sorry ! * never happen, but better safe than sorry !
*/ */
b->flags |= BF_FULL;
EV_FD_CLR(fd, DIR_RD); EV_FD_CLR(fd, DIR_RD);
b->rex = TICK_ETERNITY; b->rex = TICK_ETERNITY;
goto out_wakeup; goto out_wakeup;
@ -111,6 +112,7 @@ int stream_sock_read(int fd) {
b->l += ret; b->l += ret;
cur_read += ret; cur_read += ret;
b->flags |= BF_PARTIAL_READ; b->flags |= BF_PARTIAL_READ;
b->flags &= ~BF_EMPTY;
if (b->r == b->data + BUFSIZE) { if (b->r == b->data + BUFSIZE) {
b->r = b->data; /* wrap around the buffer */ b->r = b->data; /* wrap around the buffer */
@ -118,7 +120,7 @@ int stream_sock_read(int fd) {
b->total += ret; b->total += ret;
if (b->l == b->rlim - b->data) { if (b->l >= b->rlim - b->data) {
/* The buffer is now full, there's no point in going through /* The buffer is now full, there's no point in going through
* the loop again. * the loop again.
*/ */
@ -151,6 +153,7 @@ int stream_sock_read(int fd) {
b->xfer_large = 0; b->xfer_large = 0;
} }
b->flags |= BF_FULL;
EV_FD_CLR(fd, DIR_RD); EV_FD_CLR(fd, DIR_RD);
b->rex = TICK_ETERNITY; b->rex = TICK_ETERNITY;
goto out_wakeup; goto out_wakeup;
@ -336,11 +339,15 @@ int stream_sock_write(int fd) {
b->flags |= BF_PARTIAL_WRITE; b->flags |= BF_PARTIAL_WRITE;
if (b->l < b->rlim - b->data)
b->flags &= ~BF_FULL;
if (b->w == b->data + BUFSIZE) { if (b->w == b->data + BUFSIZE) {
b->w = b->data; /* wrap around the buffer */ b->w = b->data; /* wrap around the buffer */
} }
if (!b->l) { if (!b->l) {
b->flags |= BF_EMPTY;
EV_FD_CLR(fd, DIR_WR); EV_FD_CLR(fd, DIR_WR);
b->wex = TICK_ETERNITY; b->wex = TICK_ETERNITY;
goto out_wakeup; goto out_wakeup;