mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 07:07:04 +02:00
REORG: channel: move buffer_{replace,insert_line}* to buffer.{c,h}
These functions do not depend on the channel flags anymore thus they're much better suited to be used on plain buffers. Move them from channel to buffer.
This commit is contained in:
parent
f941cf2ef2
commit
af81935b82
@ -38,6 +38,8 @@ struct buffer {
|
||||
};
|
||||
|
||||
|
||||
int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len);
|
||||
int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len);
|
||||
void buffer_dump(FILE *o, struct buffer *b, int from, int to);
|
||||
void buffer_slow_realign(struct buffer *buf);
|
||||
void buffer_bounce_realign(struct buffer *buf);
|
||||
@ -337,6 +339,18 @@ static inline void buffer_flush(struct buffer *buf)
|
||||
buf->i = 0;
|
||||
}
|
||||
|
||||
/* This function writes the string <str> at position <pos> which must be in
|
||||
* buffer <b>, and moves <end> just after the end of <str>. <b>'s parameters
|
||||
* (l, r, lr) are updated to be valid after the shift. the shift value
|
||||
* (positive or negative) is returned. If there's no space left, the move is
|
||||
* not done. The function does not adjust ->o because it does not make sense
|
||||
* to use it on data scheduled to be sent.
|
||||
*/
|
||||
static inline int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
|
||||
{
|
||||
return buffer_replace2(b, pos, end, str, strlen(str));
|
||||
}
|
||||
|
||||
#endif /* _COMMON_BUFFER_H */
|
||||
|
||||
/*
|
||||
|
@ -45,8 +45,6 @@ int bi_putblk(struct channel *buf, const char *str, int len);
|
||||
int bi_putchr(struct channel *buf, char c);
|
||||
int bo_getline(struct channel *buf, char *str, int len);
|
||||
int bo_getblk(struct channel *buf, char *blk, int len, int offset);
|
||||
int buffer_replace2(struct channel *b, char *pos, char *end, const char *str, int len);
|
||||
int buffer_insert_line2(struct channel *b, char *pos, const char *str, int len);
|
||||
unsigned long long buffer_forward(struct channel *buf, unsigned long long bytes);
|
||||
|
||||
/* Initialize all fields in the buffer. */
|
||||
@ -369,18 +367,6 @@ static inline int bo_getchr(struct channel *buf)
|
||||
return *buffer_wrap_sub(&buf->buf, buf->buf.p - buf->buf.o);
|
||||
}
|
||||
|
||||
/* This function writes the string <str> at position <pos> which must be in
|
||||
* buffer <b>, and moves <end> just after the end of <str>. <b>'s parameters
|
||||
* (l, r, lr) are updated to be valid after the shift. the shift value
|
||||
* (positive or negative) is returned. If there's no space left, the move is
|
||||
* not done. The function does not adjust ->o because it does not make sense
|
||||
* to use it on data scheduled to be sent.
|
||||
*/
|
||||
static inline int buffer_replace(struct channel *b, char *pos, char *end, const char *str)
|
||||
{
|
||||
return buffer_replace2(b, pos, end, str, strlen(str));
|
||||
}
|
||||
|
||||
|
||||
#endif /* _PROTO_CHANNEL_H */
|
||||
|
||||
|
72
src/buffer.c
72
src/buffer.c
@ -18,6 +18,78 @@
|
||||
|
||||
#include <types/global.h>
|
||||
|
||||
/* This function writes the string <str> at position <pos> which must be in
|
||||
* buffer <b>, and moves <end> just after the end of <str>. <b>'s parameters
|
||||
* <l> and <r> are updated to be valid after the shift. The shift value
|
||||
* (positive or negative) is returned. If there's no space left, the move is
|
||||
* not done. The function does not adjust ->o because it does not make sense to
|
||||
* use it on data scheduled to be sent. For the same reason, it does not make
|
||||
* sense to call this function on unparsed data, so <orig> is not updated. The
|
||||
* string length is taken from parameter <len>. If <len> is null, the <str>
|
||||
* pointer is allowed to be null.
|
||||
*/
|
||||
int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = len - (end - pos);
|
||||
|
||||
if (bi_end(b) + delta >= b->data + b->size)
|
||||
return 0; /* no space left */
|
||||
|
||||
if (buffer_not_empty(b) &&
|
||||
bi_end(b) + delta > bo_ptr(b) &&
|
||||
bo_ptr(b) >= bi_end(b))
|
||||
return 0; /* no space left before wrapping data */
|
||||
|
||||
/* first, protect the end of the buffer */
|
||||
memmove(end + delta, end, bi_end(b) - end);
|
||||
|
||||
/* now, copy str over pos */
|
||||
if (len)
|
||||
memcpy(pos, str, len);
|
||||
|
||||
b->i += delta;
|
||||
|
||||
if (buffer_len(b) == 0)
|
||||
b->p = b->data;
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
|
||||
* argument informs about the length of string <str> so that we don't have to
|
||||
* measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
|
||||
* is only opened for len+2 bytes but nothing is copied in. It may be useful in
|
||||
* some circumstances. The send limit is *not* adjusted. Same comments as above
|
||||
* for the valid use cases.
|
||||
*
|
||||
* The number of bytes added is returned on success. 0 is returned on failure.
|
||||
*/
|
||||
int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = len + 2;
|
||||
|
||||
if (bi_end(b) + delta >= b->data + b->size)
|
||||
return 0; /* no space left */
|
||||
|
||||
/* first, protect the end of the buffer */
|
||||
memmove(pos + delta, pos, bi_end(b) - pos);
|
||||
|
||||
/* now, copy str over pos */
|
||||
if (len && str) {
|
||||
memcpy(pos, str, len);
|
||||
pos[len] = '\r';
|
||||
pos[len + 1] = '\n';
|
||||
}
|
||||
|
||||
b->i += delta;
|
||||
return delta;
|
||||
}
|
||||
|
||||
/* This function realigns input data in a possibly wrapping buffer so that it
|
||||
* becomes contiguous and starts at the beginning of the buffer area. The
|
||||
* function may only be used when the buffer's output is empty.
|
||||
|
@ -297,78 +297,6 @@ int bo_getblk(struct channel *buf, char *blk, int len, int offset)
|
||||
return len;
|
||||
}
|
||||
|
||||
/* This function writes the string <str> at position <pos> which must be in
|
||||
* buffer <b>, and moves <end> just after the end of <str>. <b>'s parameters
|
||||
* <l> and <r> are updated to be valid after the shift. The shift value
|
||||
* (positive or negative) is returned. If there's no space left, the move is
|
||||
* not done. The function does not adjust ->o because it does not make sense to
|
||||
* use it on data scheduled to be sent. For the same reason, it does not make
|
||||
* sense to call this function on unparsed data, so <orig> is not updated. The
|
||||
* string length is taken from parameter <len>. If <len> is null, the <str>
|
||||
* pointer is allowed to be null.
|
||||
*/
|
||||
int buffer_replace2(struct channel *b, char *pos, char *end, const char *str, int len)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = len - (end - pos);
|
||||
|
||||
if (bi_end(&b->buf) + delta >= b->buf.data + b->buf.size)
|
||||
return 0; /* no space left */
|
||||
|
||||
if (buffer_not_empty(&b->buf) &&
|
||||
bi_end(&b->buf) + delta > bo_ptr(&b->buf) &&
|
||||
bo_ptr(&b->buf) >= bi_end(&b->buf))
|
||||
return 0; /* no space left before wrapping data */
|
||||
|
||||
/* first, protect the end of the buffer */
|
||||
memmove(end + delta, end, bi_end(&b->buf) - end);
|
||||
|
||||
/* now, copy str over pos */
|
||||
if (len)
|
||||
memcpy(pos, str, len);
|
||||
|
||||
b->buf.i += delta;
|
||||
|
||||
if (buffer_len(&b->buf) == 0)
|
||||
b->buf.p = b->buf.data;
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
|
||||
* argument informs about the length of string <str> so that we don't have to
|
||||
* measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
|
||||
* is only opened for len+2 bytes but nothing is copied in. It may be useful in
|
||||
* some circumstances. The send limit is *not* adjusted. Same comments as above
|
||||
* for the valid use cases.
|
||||
*
|
||||
* The number of bytes added is returned on success. 0 is returned on failure.
|
||||
*/
|
||||
int buffer_insert_line2(struct channel *b, char *pos, const char *str, int len)
|
||||
{
|
||||
int delta;
|
||||
|
||||
delta = len + 2;
|
||||
|
||||
if (bi_end(&b->buf) + delta >= b->buf.data + b->buf.size)
|
||||
return 0; /* no space left */
|
||||
|
||||
/* first, protect the end of the buffer */
|
||||
memmove(pos + delta, pos, bi_end(&b->buf) - pos);
|
||||
|
||||
/* now, copy str over pos */
|
||||
if (len && str) {
|
||||
memcpy(pos, str, len);
|
||||
pos[len] = '\r';
|
||||
pos[len + 1] = '\n';
|
||||
}
|
||||
|
||||
b->buf.i += delta;
|
||||
return delta;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
|
@ -389,7 +389,7 @@ int frontend_decode_proxy_request(struct session *s, struct channel *req, int an
|
||||
|
||||
/* remove the PROXY line from the request */
|
||||
len = line - req->buf.data;
|
||||
buffer_replace2(req, req->buf.data, line, NULL, 0);
|
||||
buffer_replace2(&req->buf, req->buf.data, line, NULL, 0);
|
||||
req->total -= len; /* don't count the header line */
|
||||
|
||||
req->analysers &= ~an_bit;
|
||||
|
@ -421,7 +421,7 @@ int http_header_add_tail(struct http_msg *msg, struct hdr_idx *hdr_idx, const ch
|
||||
int bytes, len;
|
||||
|
||||
len = strlen(text);
|
||||
bytes = buffer_insert_line2(msg->buf, msg->buf->buf.p + msg->eoh, text, len);
|
||||
bytes = buffer_insert_line2(&msg->buf->buf, msg->buf->buf.p + msg->eoh, text, len);
|
||||
if (!bytes)
|
||||
return -1;
|
||||
http_msg_move_end(msg, bytes);
|
||||
@ -441,7 +441,7 @@ int http_header_add_tail2(struct http_msg *msg,
|
||||
{
|
||||
int bytes;
|
||||
|
||||
bytes = buffer_insert_line2(msg->buf, msg->buf->buf.p + msg->eoh, text, len);
|
||||
bytes = buffer_insert_line2(&msg->buf->buf, msg->buf->buf.p + msg->eoh, text, len);
|
||||
if (!bytes)
|
||||
return -1;
|
||||
http_msg_move_end(msg, bytes);
|
||||
@ -610,7 +610,7 @@ int http_remove_header2(struct http_msg *msg, struct hdr_idx *idx, struct hdr_ct
|
||||
hdr = &idx->v[cur_idx];
|
||||
if (sol[ctx->del] == ':' && ctx->val + ctx->vlen + ctx->tws == hdr->len) {
|
||||
/* This was the only value of the header, we must now remove it entirely. */
|
||||
delta = buffer_replace2(msg->buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0);
|
||||
delta = buffer_replace2(&msg->buf->buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0);
|
||||
http_msg_move_end(msg, delta);
|
||||
idx->used--;
|
||||
hdr->len = 0; /* unused entry */
|
||||
@ -630,7 +630,7 @@ int http_remove_header2(struct http_msg *msg, struct hdr_idx *idx, struct hdr_ct
|
||||
*/
|
||||
|
||||
skip_comma = (ctx->val + ctx->vlen + ctx->tws == hdr->len) ? 0 : 1;
|
||||
delta = buffer_replace2(msg->buf, sol + ctx->del + skip_comma,
|
||||
delta = buffer_replace2(&msg->buf->buf, sol + ctx->del + skip_comma,
|
||||
sol + ctx->val + ctx->vlen + ctx->tws + skip_comma,
|
||||
NULL, 0);
|
||||
hdr->len += delta;
|
||||
@ -1608,12 +1608,12 @@ static int http_upgrade_v09_to_v10(struct http_txn *txn)
|
||||
|
||||
if (msg->sl.rq.u_l == 0) {
|
||||
/* if no URI was set, add "/" */
|
||||
delta = buffer_replace2(msg->buf, cur_end, cur_end, " /", 2);
|
||||
delta = buffer_replace2(&msg->buf->buf, cur_end, cur_end, " /", 2);
|
||||
cur_end += delta;
|
||||
http_msg_move_end(msg, delta);
|
||||
}
|
||||
/* add HTTP version */
|
||||
delta = buffer_replace2(msg->buf, cur_end, cur_end, " HTTP/1.0\r\n", 11);
|
||||
delta = buffer_replace2(&msg->buf->buf, cur_end, cur_end, " HTTP/1.0\r\n", 11);
|
||||
http_msg_move_end(msg, delta);
|
||||
cur_end += delta;
|
||||
cur_end = (char *)http_parse_reqline(msg,
|
||||
@ -5588,7 +5588,7 @@ int apply_filter_to_req_headers(struct session *t, struct channel *req, struct h
|
||||
|
||||
case ACT_REPLACE:
|
||||
len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
|
||||
delta = buffer_replace2(req, cur_ptr, cur_end, trash, len);
|
||||
delta = buffer_replace2(&req->buf, cur_ptr, cur_end, trash, len);
|
||||
/* FIXME: if the user adds a newline in the replacement, the
|
||||
* index will not be recalculated for now, and the new line
|
||||
* will not be counted as a new header.
|
||||
@ -5601,7 +5601,7 @@ int apply_filter_to_req_headers(struct session *t, struct channel *req, struct h
|
||||
break;
|
||||
|
||||
case ACT_REMOVE:
|
||||
delta = buffer_replace2(req, cur_ptr, cur_next, NULL, 0);
|
||||
delta = buffer_replace2(&req->buf, cur_ptr, cur_next, NULL, 0);
|
||||
cur_next += delta;
|
||||
|
||||
http_msg_move_end(&txn->req, delta);
|
||||
@ -5713,7 +5713,7 @@ int apply_filter_to_req_line(struct session *t, struct channel *req, struct hdr_
|
||||
case ACT_REPLACE:
|
||||
*cur_end = term; /* restore the string terminator */
|
||||
len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
|
||||
delta = buffer_replace2(req, cur_ptr, cur_end, trash, len);
|
||||
delta = buffer_replace2(&req->buf, cur_ptr, cur_end, trash, len);
|
||||
/* FIXME: if the user adds a newline in the replacement, the
|
||||
* index will not be recalculated for now, and the new line
|
||||
* will not be counted as a new header.
|
||||
@ -5914,7 +5914,7 @@ char *find_cookie_value_end(char *s, const char *e)
|
||||
* - there are non-space chars before <from> ;
|
||||
* - there is a CR/LF at or after <next>.
|
||||
*/
|
||||
int del_hdr_value(struct channel *buf, char **from, char *next)
|
||||
int del_hdr_value(struct buffer *buf, char **from, char *next)
|
||||
{
|
||||
char *prev = *from;
|
||||
|
||||
@ -6094,7 +6094,7 @@ void manage_client_side_cookies(struct session *t, struct channel *req)
|
||||
*/
|
||||
preserve_hdr = 1;
|
||||
if (del_from != NULL) {
|
||||
int delta = del_hdr_value(req, &del_from, prev);
|
||||
int delta = del_hdr_value(&req->buf, &del_from, prev);
|
||||
val_end += delta;
|
||||
next += delta;
|
||||
hdr_end += delta;
|
||||
@ -6117,13 +6117,13 @@ void manage_client_side_cookies(struct session *t, struct channel *req)
|
||||
int stripped_after = 0;
|
||||
|
||||
if (att_end != equal) {
|
||||
stripped_before = buffer_replace2(req, att_end, equal, NULL, 0);
|
||||
stripped_before = buffer_replace2(&req->buf, att_end, equal, NULL, 0);
|
||||
equal += stripped_before;
|
||||
val_beg += stripped_before;
|
||||
}
|
||||
|
||||
if (val_beg > equal + 1) {
|
||||
stripped_after = buffer_replace2(req, equal + 1, val_beg, NULL, 0);
|
||||
stripped_after = buffer_replace2(&req->buf, equal + 1, val_beg, NULL, 0);
|
||||
val_beg += stripped_after;
|
||||
stripped_before += stripped_after;
|
||||
}
|
||||
@ -6304,7 +6304,7 @@ void manage_client_side_cookies(struct session *t, struct channel *req)
|
||||
if ((t->be->ck_opts & PR_CK_PFX) && (delim != val_end)) {
|
||||
int delta; /* negative */
|
||||
|
||||
delta = buffer_replace2(req, val_beg, delim + 1, NULL, 0);
|
||||
delta = buffer_replace2(&req->buf, val_beg, delim + 1, NULL, 0);
|
||||
val_end += delta;
|
||||
next += delta;
|
||||
hdr_end += delta;
|
||||
@ -6327,7 +6327,7 @@ void manage_client_side_cookies(struct session *t, struct channel *req)
|
||||
preserve_hdr = 1;
|
||||
|
||||
if (del_from != NULL) {
|
||||
int delta = del_hdr_value(req, &del_from, prev);
|
||||
int delta = del_hdr_value(&req->buf, &del_from, prev);
|
||||
if (att_beg >= del_from)
|
||||
att_beg += delta;
|
||||
if (att_end >= del_from)
|
||||
@ -6380,11 +6380,11 @@ void manage_client_side_cookies(struct session *t, struct channel *req)
|
||||
if (del_from) {
|
||||
int delta;
|
||||
if (preserve_hdr) {
|
||||
delta = del_hdr_value(req, &del_from, hdr_end);
|
||||
delta = del_hdr_value(&req->buf, &del_from, hdr_end);
|
||||
hdr_end = del_from;
|
||||
cur_hdr->len += delta;
|
||||
} else {
|
||||
delta = buffer_replace2(req, hdr_beg, hdr_next, NULL, 0);
|
||||
delta = buffer_replace2(&req->buf, hdr_beg, hdr_next, NULL, 0);
|
||||
|
||||
/* FIXME: this should be a separate function */
|
||||
txn->hdr_idx.v[old_idx].next = cur_hdr->next;
|
||||
@ -6462,7 +6462,7 @@ int apply_filter_to_resp_headers(struct session *t, struct channel *rtr, struct
|
||||
|
||||
case ACT_REPLACE:
|
||||
len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
|
||||
delta = buffer_replace2(rtr, cur_ptr, cur_end, trash, len);
|
||||
delta = buffer_replace2(&rtr->buf, cur_ptr, cur_end, trash, len);
|
||||
/* FIXME: if the user adds a newline in the replacement, the
|
||||
* index will not be recalculated for now, and the new line
|
||||
* will not be counted as a new header.
|
||||
@ -6475,7 +6475,7 @@ int apply_filter_to_resp_headers(struct session *t, struct channel *rtr, struct
|
||||
break;
|
||||
|
||||
case ACT_REMOVE:
|
||||
delta = buffer_replace2(rtr, cur_ptr, cur_next, NULL, 0);
|
||||
delta = buffer_replace2(&rtr->buf, cur_ptr, cur_next, NULL, 0);
|
||||
cur_next += delta;
|
||||
|
||||
http_msg_move_end(&txn->rsp, delta);
|
||||
@ -6552,7 +6552,7 @@ int apply_filter_to_sts_line(struct session *t, struct channel *rtr, struct hdr_
|
||||
case ACT_REPLACE:
|
||||
*cur_end = term; /* restore the string terminator */
|
||||
len = exp_replace(trash, cur_ptr, exp->replace, pmatch);
|
||||
delta = buffer_replace2(rtr, cur_ptr, cur_end, trash, len);
|
||||
delta = buffer_replace2(&rtr->buf, cur_ptr, cur_end, trash, len);
|
||||
/* FIXME: if the user adds a newline in the replacement, the
|
||||
* index will not be recalculated for now, and the new line
|
||||
* will not be counted as a new header.
|
||||
@ -6807,13 +6807,13 @@ void manage_server_side_cookies(struct session *t, struct channel *res)
|
||||
int stripped_after = 0;
|
||||
|
||||
if (att_end != equal) {
|
||||
stripped_before = buffer_replace2(res, att_end, equal, NULL, 0);
|
||||
stripped_before = buffer_replace2(&res->buf, att_end, equal, NULL, 0);
|
||||
equal += stripped_before;
|
||||
val_beg += stripped_before;
|
||||
}
|
||||
|
||||
if (val_beg > equal + 1) {
|
||||
stripped_after = buffer_replace2(res, equal + 1, val_beg, NULL, 0);
|
||||
stripped_after = buffer_replace2(&res->buf, equal + 1, val_beg, NULL, 0);
|
||||
val_beg += stripped_after;
|
||||
stripped_before += stripped_after;
|
||||
}
|
||||
@ -6871,7 +6871,7 @@ void manage_server_side_cookies(struct session *t, struct channel *res)
|
||||
/* this cookie must be deleted */
|
||||
if (*prev == ':' && next == hdr_end) {
|
||||
/* whole header */
|
||||
delta = buffer_replace2(res, hdr_beg, hdr_next, NULL, 0);
|
||||
delta = buffer_replace2(&res->buf, hdr_beg, hdr_next, NULL, 0);
|
||||
txn->hdr_idx.v[old_idx].next = cur_hdr->next;
|
||||
txn->hdr_idx.used--;
|
||||
cur_hdr->len = 0;
|
||||
@ -6883,7 +6883,7 @@ void manage_server_side_cookies(struct session *t, struct channel *res)
|
||||
*/
|
||||
} else {
|
||||
/* just remove the value */
|
||||
int delta = del_hdr_value(res, &prev, next);
|
||||
int delta = del_hdr_value(&res->buf, &prev, next);
|
||||
next = prev;
|
||||
hdr_end += delta;
|
||||
hdr_next += delta;
|
||||
@ -6898,7 +6898,7 @@ void manage_server_side_cookies(struct session *t, struct channel *res)
|
||||
/* replace bytes val_beg->val_end with the cookie name associated
|
||||
* with this server since we know it.
|
||||
*/
|
||||
delta = buffer_replace2(res, val_beg, val_end, srv->cookie, srv->cklen);
|
||||
delta = buffer_replace2(&res->buf, val_beg, val_end, srv->cookie, srv->cklen);
|
||||
next += delta;
|
||||
hdr_end += delta;
|
||||
hdr_next += delta;
|
||||
@ -6912,7 +6912,7 @@ void manage_server_side_cookies(struct session *t, struct channel *res)
|
||||
/* insert the cookie name associated with this server
|
||||
* before existing cookie, and insert a delimiter between them..
|
||||
*/
|
||||
delta = buffer_replace2(res, val_beg, val_beg, srv->cookie, srv->cklen + 1);
|
||||
delta = buffer_replace2(&res->buf, val_beg, val_beg, srv->cookie, srv->cklen + 1);
|
||||
next += delta;
|
||||
hdr_end += delta;
|
||||
hdr_next += delta;
|
||||
|
Loading…
Reference in New Issue
Block a user