MINOR: chunks: centralize the trash chunk allocation
At the moment, we need trash chunks almost everywhere and the only
correctly implemented one is in the sample code. Let's move this to
the chunks so that all other places can use this allocator.
Additionally, the get_trash_chunk() function now really returns two
different chunks. Previously it used to always overwrite the same
chunk and point it to a different buffer, which was a bit tricky
because it's not obvious that two consecutive results do alias each
other.
diff --git a/include/common/chunk.h b/include/common/chunk.h
index 191f9e7..18f41af 100644
--- a/include/common/chunk.h
+++ b/include/common/chunk.h
@@ -47,6 +47,8 @@
int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc);
int chunk_strcmp(const struct chunk *chk, const char *str);
int chunk_strcasecmp(const struct chunk *chk, const char *str);
+int alloc_trash_buffers(int bufsize);
+struct chunk *get_trash_chunk(void);
static inline void chunk_reset(struct chunk *chk)
{
diff --git a/include/proto/sample.h b/include/proto/sample.h
index 5241a3a..77d6c18 100644
--- a/include/proto/sample.h
+++ b/include/proto/sample.h
@@ -26,10 +26,6 @@
#include <types/sample.h>
#include <types/stick_table.h>
-/* only exported for late memory allocation, do not use */
-extern char *sample_trash_buf1;
-extern char *sample_trash_buf2;
-
struct sample_expr *sample_parse_expr(char **str, int *idx, char *err, int err_size);
struct sample *sample_process(struct proxy *px, struct session *l4,
void *l7, unsigned int dir, struct sample_expr *expr,
@@ -38,6 +34,5 @@
unsigned int opt, struct sample_expr *expr);
void sample_register_fetches(struct sample_fetch_kw_list *psl);
void sample_register_convs(struct sample_conv_kw_list *psl);
-struct chunk *sample_get_trash_chunk(void);
#endif /* _PROTO_SAMPLE_H */
diff --git a/src/chunk.c b/src/chunk.c
index d027569..9463abb 100644
--- a/src/chunk.c
+++ b/src/chunk.c
@@ -18,6 +18,48 @@
#include <common/config.h>
#include <common/chunk.h>
+/* trash chunks used for various conversions */
+static struct chunk *trash_chunk;
+static struct chunk trash_chunk1;
+static struct chunk trash_chunk2;
+
+/* trash buffers used for various conversions */
+static int trash_size;
+static char *trash_buf1;
+static char *trash_buf2;
+
+/*
+* Returns a pre-allocated and initialized trash chunk that can be used for any
+* type of conversion. Two chunks and their respective buffers are alternatively
+* returned so that it is always possible to iterate data transformations without
+* losing the data being transformed. The blocks are initialized to the size of
+* a standard buffer, so they should be enough for everything.
+*/
+struct chunk *get_trash_chunk(void)
+{
+ char *trash_buf;
+
+ if (trash_chunk == &trash_chunk1) {
+ trash_chunk = &trash_chunk2;
+ trash_buf = trash_buf2;
+ }
+ else {
+ trash_chunk = &trash_chunk1;
+ trash_buf = trash_buf1;
+ }
+ chunk_init(trash_chunk, trash_buf, trash_size);
+ return trash_chunk;
+}
+
+/* Allocates the trash buffers. Returns 0 in case of failure. */
+int alloc_trash_buffers(int bufsize)
+{
+ trash_size = bufsize;
+ trash_buf1 = (char *)calloc(1, bufsize);
+ trash_buf2 = (char *)calloc(1, bufsize);
+ return trash_buf1 && trash_buf2;
+}
+
/*
* Does an snprintf() at the beginning of chunk <chk>, respecting the limit of
* at most chk->size chars. If the chk->len is over, nothing is added. Returns
diff --git a/src/haproxy.c b/src/haproxy.c
index b62d261..0d826d2 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -759,11 +759,9 @@
global.nbproc = 1;
swap_buffer = (char *)calloc(1, global.tune.bufsize);
- sample_trash_buf1 = (char *)calloc(1, global.tune.bufsize);
- sample_trash_buf2 = (char *)calloc(1, global.tune.bufsize);
get_http_auth_buff = (char *)calloc(1, global.tune.bufsize);
static_table_key = calloc(1, sizeof(*static_table_key) + global.tune.bufsize);
-
+ alloc_trash_buffers(global.tune.bufsize);
fdinfo = (struct fdinfo *)calloc(1,
sizeof(struct fdinfo) * (global.maxsock));
diff --git a/src/proto_http.c b/src/proto_http.c
index f664b8e..60b630d 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -8481,7 +8481,7 @@
smp->type = SMP_T_IPV4;
break;
} else {
- struct chunk *temp = sample_get_trash_chunk();
+ struct chunk *temp = get_trash_chunk();
if (smp->data.str.len < temp->size - 1) {
memcpy(temp->str, smp->data.str.str, smp->data.str.len);
temp->str[smp->data.str.len] = '\0';
@@ -8632,11 +8632,12 @@
smp_fetch_base32_src(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
- struct chunk *temp = sample_get_trash_chunk();
+ struct chunk *temp;
if (!smp_fetch_base32(px, l4, l7, opt, args, smp))
return 0;
+ temp = get_trash_chunk();
memcpy(temp->str + temp->len, &smp->data.uint, sizeof(smp->data.uint));
temp->len += sizeof(smp->data.uint);
diff --git a/src/sample.c b/src/sample.c
index 3c0d01e..b3898e0 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -26,13 +26,6 @@
/* static sample used in sample_process() when <p> is NULL */
static struct sample temp_smp;
-/* trash chunk used for sample conversions */
-static struct chunk trash_chunk;
-
-/* trash buffers used or sample conversions */
-char *sample_trash_buf1;
-char *sample_trash_buf2;
-
/* list head of all known sample fetch keywords */
static struct sample_fetch_kw_list sample_fetches = {
.list = LIST_HEAD_INIT(sample_fetches.list)
@@ -101,24 +94,6 @@
return NULL;
}
-
-/*
-* Returns a static trash struct chunk to use in sample casts or format conversions
-* Swiths the 2 available trash buffers to protect data during convert
-*/
-struct chunk *sample_get_trash_chunk(void)
-{
- char *sample_trash_buf;
-
- sample_trash_buf = sample_trash_buf1;
- sample_trash_buf1 = sample_trash_buf2;
- sample_trash_buf2 = sample_trash_buf1;
-
- chunk_init(&trash_chunk, sample_trash_buf, global.tune.bufsize);
-
- return &trash_chunk;
-}
-
/******************************************************************/
/* Sample casts functions */
/* Note: these functions do *NOT* set the output type on the */
@@ -133,7 +108,7 @@
static int c_ip2str(struct sample *smp)
{
- struct chunk *trash = sample_get_trash_chunk();
+ struct chunk *trash = get_trash_chunk();
if (!inet_ntop(AF_INET, (void *)&smp->data.ipv4, trash->str, trash->size))
return 0;
@@ -152,7 +127,7 @@
static int c_ipv62str(struct sample *smp)
{
- struct chunk *trash = sample_get_trash_chunk();
+ struct chunk *trash = get_trash_chunk();
if (!inet_ntop(AF_INET6, (void *)&smp->data.ipv6, trash->str, trash->size))
return 0;
@@ -189,7 +164,7 @@
static int c_bin2str(struct sample *smp)
{
- struct chunk *trash = sample_get_trash_chunk();
+ struct chunk *trash = get_trash_chunk();
unsigned char c;
int ptr = 0;
@@ -205,7 +180,7 @@
static int c_int2str(struct sample *smp)
{
- struct chunk *trash = sample_get_trash_chunk();
+ struct chunk *trash = get_trash_chunk();
char *pos;
pos = ultoa_r(smp->data.uint, trash->str, trash->size);
@@ -222,7 +197,7 @@
static int c_datadup(struct sample *smp)
{
- struct chunk *trash = sample_get_trash_chunk();
+ struct chunk *trash = get_trash_chunk();
trash->len = smp->data.str.len < trash->size ? smp->data.str.len : trash->size;
memcpy(trash->str, smp->data.str.str, trash->len);
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 0c08769..87eff2b 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -1446,7 +1446,7 @@
if (!crt)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (ssl_sock_get_serial(crt, smp_trash) <= 0)
goto out;
@@ -1481,7 +1481,7 @@
if (!crt)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
goto out;
@@ -1521,7 +1521,7 @@
if (!name)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (args && args[0].type == ARGT_STR) {
int pos = 1;
@@ -1567,7 +1567,7 @@
if (!crt)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
goto out;
@@ -1607,7 +1607,7 @@
if (!name)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (args && args[0].type == ARGT_STR) {
int pos = 1;
@@ -1799,7 +1799,7 @@
if (!crt)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (ssl_sock_get_serial(crt, smp_trash) <= 0)
goto out;
@@ -1830,7 +1830,7 @@
if (!crt)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
goto out;
@@ -1862,7 +1862,7 @@
if (!crt)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
goto out;
@@ -1989,7 +1989,7 @@
if (!name)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (args && args[0].type == ARGT_STR) {
int pos = 1;
@@ -2037,7 +2037,7 @@
if (!name)
goto out;
- smp_trash = sample_get_trash_chunk();
+ smp_trash = get_trash_chunk();
if (args && args[0].type == ARGT_STR) {
int pos = 1;