From: Willy Tarreau Date: Mon, 27 Aug 2012 20:08:00 +0000 (+0200) Subject: REORG: channel: move buffer_{replace,insert_line}* to buffer.{c,h} X-Git-Tag: v1.5-dev12~60 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=af81935b8296346705df2489f1d601bf570ec40e;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/common/buffer.h b/include/common/buffer.h index cf40f096bf..e49316efe1 100644 --- a/include/common/buffer.h +++ b/include/common/buffer.h @@ -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 at position which must be in + * buffer , and moves just after the end of . '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 */ /* diff --git a/include/proto/channel.h b/include/proto/channel.h index 4ba55b9f69..3c3fe4c3b3 100644 --- a/include/proto/channel.h +++ b/include/proto/channel.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 at position which must be in - * buffer , and moves just after the end of . '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 */ diff --git a/src/buffer.c b/src/buffer.c index 764f692846..f98da94508 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -18,6 +18,78 @@ #include +/* This function writes the string at position which must be in + * buffer , and moves just after the end of . 's parameters + * and 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 is not updated. The + * string length is taken from parameter . If is null, the + * 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 followed by "\r\n" at position in buffer . The + * 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. 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. diff --git a/src/channel.c b/src/channel.c index ce90147b7d..8a8e8c333e 100644 --- a/src/channel.c +++ b/src/channel.c @@ -297,78 +297,6 @@ int bo_getblk(struct channel *buf, char *blk, int len, int offset) return len; } -/* This function writes the string at position which must be in - * buffer , and moves just after the end of . 's parameters - * and 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 is not updated. The - * string length is taken from parameter . If is null, the - * 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 followed by "\r\n" at position in buffer . The - * 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. 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 diff --git a/src/frontend.c b/src/frontend.c index aa6cb9e688..ffd1017e59 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -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; diff --git a/src/proto_http.c b/src/proto_http.c index a3b9f341ee..a047bc15ff 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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 ; * - there is a CR/LF at or after . */ -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;