From: Willy Tarreau Date: Sat, 13 Dec 2008 20:12:26 +0000 (+0100) Subject: [MEDIUM] add a send limit to a buffer X-Git-Tag: v1.3.16-rc1~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f890dc900301e23cab44433d82519512d850b40c;p=thirdparty%2Fhaproxy.git [MEDIUM] add a send limit to a buffer For keep-alive, line-mode protocols and splicing, we will need to limit the sender to process a certain amount of bytes. The limit is automatically set to the buffer size when analysers are detached from the buffer. --- diff --git a/include/proto/buffers.h b/include/proto/buffers.h index bc472a069a..37f724ab71 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -45,6 +45,7 @@ int init_buffer(); */ static inline void buffer_init(struct buffer *buf) { + buf->send_max = 0; buf->l = buf->total = 0; buf->analysers = 0; buf->cons = NULL; @@ -87,6 +88,7 @@ static inline void buffer_check_timeouts(struct buffer *b) */ static inline void buffer_flush(struct buffer *buf) { + buf->send_max = 0; buf->r = buf->lr = buf->w = buf->data; buf->l = 0; buf->flags |= BF_EMPTY | BF_FULL; diff --git a/include/types/buffers.h b/include/types/buffers.h index 3c79a4edd7..27d32713da 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -129,6 +129,7 @@ struct buffer { unsigned int l; /* data length */ char *r, *w, *lr; /* read ptr, write ptr, last read */ char *rlim; /* read limit, used for header rewriting */ + unsigned int send_max; /* number of bytes the sender can consume */ unsigned int analysers; /* bit field indicating what to do on the buffer */ int analyse_exp; /* expiration date for current analysers (if set) */ void (*hijacker)(struct session *, struct buffer *); /* alternative content producer */ diff --git a/src/buffers.c b/src/buffers.c index f7e672d070..3938fc315c 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -30,7 +30,8 @@ int init_buffer() /* writes bytes from message to buffer . Returns -1 in case of - * success, or the number of bytes available otherwise. + * success, or the number of bytes available otherwise. The send limit is + * automatically adjusted with the amount of data written. * FIXME-20060521: handle unaligned data. */ int buffer_write(struct buffer *buf, const char *msg, int len) @@ -44,6 +45,7 @@ int buffer_write(struct buffer *buf, const char *msg, int len) memcpy(buf->r, msg, len); buf->l += len; + buf->send_max += len; buf->r += len; buf->total += len; if (buf->r == buf->data + BUFSIZE) @@ -60,7 +62,8 @@ int buffer_write(struct buffer *buf, const char *msg, int len) /* writes the chunk to buffer . Returns -1 in case of * success, or the number of bytes available otherwise. If the chunk - * has been written, its size is automatically reset to zero. + * has been written, its size is automatically reset to zero. The send limit is + * automatically adjusted with the amount of data written. */ int buffer_write_chunk(struct buffer *buf, struct chunk *chunk) { @@ -76,6 +79,7 @@ int buffer_write_chunk(struct buffer *buf, struct chunk *chunk) memcpy(buf->r, chunk->str, chunk->len); buf->l += chunk->len; + buf->send_max += chunk->len; buf->r += chunk->len; buf->total += chunk->len; if (buf->r == buf->data + BUFSIZE) @@ -133,7 +137,7 @@ int buffer_replace(struct buffer *b, char *pos, char *end, const char *str) /* * same except that the string length is given, which allows str to be NULL if - * len is 0. + * len is 0. The send limit is *not* adjusted. */ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len) { @@ -178,7 +182,7 @@ int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int * argument informs about the length of string so that we don't have to * measure it. It does not include the "\r\n". If is NULL, then the buffer * is only opened for len+2 bytes but nothing is copied in. It may be useful in - * some circumstances. + * some circumstances. The send limit is *not* adjusted. * * The number of bytes added is returned on success. 0 is returned on failure. */ diff --git a/src/proto_uxst.c b/src/proto_uxst.c index e31398a955..21c50fc573 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -799,6 +799,10 @@ void uxst_process_session(struct task *t, int *next) resync = 1; } + /* if noone is interested in analysing data, let's forward everything */ + if (!s->req->analysers && !(s->req->flags & BF_HIJACK)) + s->req->send_max = s->req->l; + /* reflect what the L7 analysers have seen last */ rqf_last = s->req->flags; @@ -869,6 +873,10 @@ void uxst_process_session(struct task *t, int *next) resync = 1; } + /* if noone is interested in analysing data, let's forward everything */ + if (!s->rep->analysers && !(s->rep->flags & BF_HIJACK)) + s->rep->send_max = s->rep->l; + /* reflect what the L7 analysers have seen last */ rpf_last = s->rep->flags; diff --git a/src/session.c b/src/session.c index 6bad79a442..95ece53fa6 100644 --- a/src/session.c +++ b/src/session.c @@ -744,6 +744,10 @@ resync_stream_interface: resync = 1; } + /* if noone is interested in analysing data, let's forward everything */ + if (!s->req->analysers && !(s->req->flags & BF_HIJACK)) + s->req->send_max = s->req->l; + /* reflect what the L7 analysers have seen last */ rqf_last = s->req->flags; @@ -849,6 +853,10 @@ resync_stream_interface: resync = 1; } + /* if noone is interested in analysing data, let's forward everything */ + if (!s->rep->analysers && !(s->rep->flags & BF_HIJACK)) + s->rep->send_max = s->rep->l; + /* reflect what the L7 analysers have seen last */ rpf_last = s->rep->flags; diff --git a/src/stream_sock.c b/src/stream_sock.c index d4a603c98f..68471ed174 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -114,6 +114,10 @@ int stream_sock_read(int fd) { b->l += ret; cur_read += ret; + /* if noone is interested in analysing data, let's forward everything */ + if (!b->analysers) + b->send_max += ret; + if (fdtab[fd].state == FD_STCONN) fdtab[fd].state = FD_STREADY; @@ -306,6 +310,10 @@ int stream_sock_write(int fd) { max = b->data + BUFSIZE - b->w; } + /* limit the amount of outgoing data if required */ + if (max > b->send_max) + max = b->send_max; + if (max == 0) { /* may be we have received a connection acknowledgement in TCP mode without data */ if (likely(fdtab[fd].state == FD_STCONN)) { @@ -363,6 +371,7 @@ int stream_sock_write(int fd) { if (ret > 0) { b->l -= ret; b->w += ret; + b->send_max -= ret; if (fdtab[fd].state == FD_STCONN) fdtab[fd].state = FD_STREADY;