>From 047affc5d4695cfe58c0a4824d371d3b789ab3ef Mon Sep 17 00:00:00 2001 From: Krzysztof Piotr Oledzki <o...@ans.pl> Date: Sun, 27 Sep 2009 13:23:20 +0200 Subject: [MAJOR] struct chunk rework
Add size to struct chunk and simplify the code as there is no longer required to pass sizeof in chunk_printf(). --- include/proto/buffers.h | 61 +++++++++++++++- include/types/buffers.h | 3 +- src/buffers.c | 11 ++- src/cfgparse.c | 18 ++--- src/checks.c | 46 +++++------ src/client.c | 8 +- src/dumpstats.c | 189 +++++++++++++++++++++++------------------------ src/haproxy.c | 2 +- src/proto_http.c | 18 ++--- 9 files changed, 201 insertions(+), 155 deletions(-) diff --git a/include/proto/buffers.h b/include/proto/buffers.h index 53fd41f..404ad06 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -278,10 +278,67 @@ int buffer_write_chunk(struct buffer *buf, struct chunk *chunk); int buffer_replace(struct buffer *b, char *pos, char *end, const char *str); 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); -int chunk_printf(struct chunk *chk, int size, const char *fmt, ...) - __attribute__ ((format(printf, 3, 4))); void buffer_dump(FILE *o, struct buffer *b, int from, int to); +static inline void chunk_init(struct chunk *chk, char *str, size_t size) { + chk->str = str; + chk->len = 0; + chk->size = size; +} + +/* report 0 in case of error, 1 if OK. */ +static inline int chunk_initlen(struct chunk *chk, char *str, size_t size, size_t len) { + + if (len > size) + return 0; + + chk->str = str; + chk->len = len; + chk->size = size; + + return 1; +} + +static inline void chunk_initstr(struct chunk *chk, char *str) { + chk->str = str; + chk->len = strlen(str); + chk->size = 0; /* mark it read-only */ +} + +static inline int chunk_strcpy(struct chunk *chk, const char *str) { + size_t len; + + len = strlen(str); + + if (unlikely(len > chk->size)) + return 0; + + chk->len = len; + memcpy(chk->str, str, len); + + return 1; +} + +int chunk_printf(struct chunk *chk, const char *fmt, ...) + __attribute__ ((format(printf, 2, 3))); + +static void chunk_reset(struct chunk *chk) { + chk->str = NULL; + chk->len = -1; + chk->size = 0; +} + +static void chunk_destroy(struct chunk *chk) { + + if (!chk->size) + return; + + if (chk->str) + free(chk->str); + + chunk_reset(chk); +} + /* * frees the destination chunk if already allocated, allocates a new string, * and copies the source into it. The pointer to the destination string is diff --git a/include/types/buffers.h b/include/types/buffers.h index 8492948..d7d9bd7 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -121,7 +121,8 @@ /* describes a chunk of string */ struct chunk { char *str; /* beginning of the string itself. Might not be 0-terminated */ - int len; /* size of the string from first to last char. <0 = uninit. */ + size_t size; /* total size of the buffer, 0 if the *str is read-only */ + size_t len; /* current size of the string from first to last char. <0 = uninit. */ }; /* needed for a declaration below */ diff --git a/src/buffers.c b/src/buffers.c index ed2aa1e..dd70411 100644 --- a/src/buffers.c +++ b/src/buffers.c @@ -243,17 +243,20 @@ int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len) /* * Does an snprintf() at the end of chunk <chk>, respecting the limit of - * at most <size> chars. If the size is over, nothing is added. Returns + * at most chk->size chars. If the chk->len is over, nothing is added. Returns * the new chunk size. */ -int chunk_printf(struct chunk *chk, int size, const char *fmt, ...) +int chunk_printf(struct chunk *chk, const char *fmt, ...) { va_list argp; int ret; + if (!chk->str || !chk->size) + return 0; + va_start(argp, fmt); - ret = vsnprintf(chk->str + chk->len, size - chk->len, fmt, argp); - if (ret >= size - chk->len) + ret = vsnprintf(chk->str + chk->len, chk->size - chk->len, fmt, argp); + if (ret >= chk->size - chk->len) /* do not copy anything in case of truncation */ chk->str[chk->len] = 0; else diff --git a/src/cfgparse.c b/src/cfgparse.c index b36470b..69fd00f 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -873,10 +873,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) curproxy->fe_sps_lim = defproxy.fe_sps_lim; /* initialize error relocations */ - for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { - if (defproxy.errmsg[rc].str) - chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]); - } + for (rc = 0; rc < HTTP_ERR_SIZE; rc++) + chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]); curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR; } @@ -975,7 +973,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) defproxy.fwdfor_hdr_len = 0; for (rc = 0; rc < HTTP_ERR_SIZE; rc++) - free(defproxy.errmsg[rc].str); + chunk_destroy(&defproxy.errmsg[rc]); /* we cannot free uri_auth because it might already be used */ init_default_instance(); @@ -3467,9 +3465,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { if (http_err_codes[rc] == errnum) { - free(curproxy->errmsg[rc].str); - curproxy->errmsg[rc].str = err; - curproxy->errmsg[rc].len = errlen; + chunk_destroy(&curproxy->errmsg[rc]); + chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen); break; } } @@ -3528,9 +3525,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) errnum = atol(args[1]); for (rc = 0; rc < HTTP_ERR_SIZE; rc++) { if (http_err_codes[rc] == errnum) { - free(curproxy->errmsg[rc].str); - curproxy->errmsg[rc].str = err; - curproxy->errmsg[rc].len = errlen; + chunk_destroy(&curproxy->errmsg[rc]); + chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen); break; } } diff --git a/src/checks.c b/src/checks.c index 278f0c1..3ee0808 100644 --- a/src/checks.c +++ b/src/checks.c @@ -232,24 +232,23 @@ static void set_server_down(struct server *s) */ xferred = redistribute_pending(s); - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "%sServer %s/%s is DOWN", s->state & SRV_BACKUP ? "Backup " : "", s->proxy->id, s->id); if (s->tracked) - chunk_printf(&msg, sizeof(trash), " via %s/%s", + chunk_printf(&msg, " via %s/%s", s->tracked->proxy->id, s->tracked->id); - chunk_printf(&msg, sizeof(trash), ", reason: %s", get_check_status_description(s->check_status)); + chunk_printf(&msg, ", reason: %s", get_check_status_description(s->check_status)); if (s->check_status >= HCHK_STATUS_L57DATA) - chunk_printf(&msg, sizeof(trash), ", code: %d", s->check_code); + chunk_printf(&msg, ", code: %d", s->check_code); - chunk_printf(&msg, sizeof(trash), ", check duration: %lums", s->check_duration); + chunk_printf(&msg, ", check duration: %lums", s->check_duration); - chunk_printf(&msg, sizeof(trash), ". %d active and %d backup servers left.%s" + chunk_printf(&msg, ". %d active and %d backup servers left.%s" " %d sessions active, %d requeued, %d remaining in queue.\n", s->proxy->srv_act, s->proxy->srv_bck, (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "", @@ -313,22 +312,21 @@ static void set_server_up(struct server *s) { */ xferred = check_for_pending(s); - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "%sServer %s/%s is UP", s->state & SRV_BACKUP ? "Backup " : "", s->proxy->id, s->id); if (s->tracked) - chunk_printf(&msg, sizeof(trash), " via %s/%s", + chunk_printf(&msg, " via %s/%s", s->tracked->proxy->id, s->tracked->id); - chunk_printf(&msg, sizeof(trash), ", reason: %s", get_check_status_description(s->check_status)); + chunk_printf(&msg, ", reason: %s", get_check_status_description(s->check_status)); if (s->check_status >= HCHK_STATUS_L57DATA) - chunk_printf(&msg, sizeof(trash), ", code: %d", s->check_code); + chunk_printf(&msg, ", code: %d", s->check_code); - chunk_printf(&msg, sizeof(trash), ". %d active and %d backup servers online.%s" + chunk_printf(&msg, ". %d active and %d backup servers online.%s" " %d sessions requeued, %d total in queue.\n", s->proxy->srv_act, s->proxy->srv_bck, (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "", @@ -362,20 +360,19 @@ static void set_server_disabled(struct server *s) { */ xferred = redistribute_pending(s); - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "Load-balancing on %sServer %s/%s is disabled", s->state & SRV_BACKUP ? "Backup " : "", s->proxy->id, s->id); if (s->tracked) - chunk_printf(&msg, sizeof(trash), " via %s/%s", + chunk_printf(&msg, " via %s/%s", s->tracked->proxy->id, s->tracked->id); - chunk_printf(&msg, sizeof(trash),". %d active and %d backup servers online.%s" + chunk_printf(&msg,". %d active and %d backup servers online.%s" " %d sessions requeued, %d total in queue.\n", s->proxy->srv_act, s->proxy->srv_bck, (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "", @@ -407,19 +404,18 @@ static void set_server_enabled(struct server *s) { */ xferred = check_for_pending(s); - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "Load-balancing on %sServer %s/%s is enabled again", s->state & SRV_BACKUP ? "Backup " : "", s->proxy->id, s->id); if (s->tracked) - chunk_printf(&msg, sizeof(trash), " via %s/%s", + chunk_printf(&msg, " via %s/%s", s->tracked->proxy->id, s->tracked->id); - chunk_printf(&msg, sizeof(trash), ". %d active and %d backup servers online.%s" + chunk_printf(&msg, ". %d active and %d backup servers online.%s" " %d sessions requeued, %d total in queue.\n", s->proxy->srv_act, s->proxy->srv_bck, (s->proxy->srv_bck && !s->proxy->srv_act) ? " Running on backup." : "", diff --git a/src/client.c b/src/client.c index 312d896..0853624 100644 --- a/src/client.c +++ b/src/client.c @@ -277,7 +277,7 @@ int event_accept(int fd) { txn->rsp.sol = txn->rsp.eol = NULL; txn->rsp.som = txn->rsp.eoh = 0; /* relative to the buffer */ txn->req.err_pos = txn->rsp.err_pos = -2; /* block buggy requests/responses */ - txn->auth_hdr.len = -1; + chunk_reset(&txn->auth_hdr); if (p->options2 & PR_O2_REQBUG_OK) txn->req.err_pos = -1; /* let buggy requests pass */ @@ -451,13 +451,15 @@ int event_accept(int fd) { * or we're in health check mode with the 'httpchk' option enabled. In * both cases, we return a fake "HTTP/1.0 200 OK" response and we exit. */ - struct chunk msg = { .str = "HTTP/1.0 200 OK\r\n\r\n", .len = 19 }; + struct chunk msg; + chunk_initstr(&msg, "HTTP/1.0 200 OK\r\n\r\n"); stream_int_retnclose(&s->si[0], &msg); /* forge a 200 response */ s->req->analysers = 0; t->expire = s->rep->wex; } else if (p->mode == PR_MODE_HEALTH) { /* health check mode, no client reading */ - struct chunk msg = { .str = "OK\n", .len = 3 }; + struct chunk msg; + chunk_initstr(&msg, "OK\n"); stream_int_retnclose(&s->si[0], &msg); /* forge an "OK" response */ s->req->analysers = 0; t->expire = s->rep->wex; diff --git a/src/dumpstats.c b/src/dumpstats.c index 82d1803..4a4b794 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -210,9 +210,9 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx return 0; } -int print_csv_header(struct chunk *msg, int size) +int print_csv_header(struct chunk *msg) { - return chunk_printf(msg, size, + return chunk_printf(msg, "# pxname,svname," "qcur,qmax," "scur,smax,slim,stot," @@ -383,8 +383,7 @@ int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri) struct chunk msg; unsigned int up; - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); switch (s->data_state) { case DATA_ST_INIT: @@ -397,7 +396,7 @@ int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri) case DATA_ST_HEAD: if (s->data_ctx.stats.flags & STAT_SHOW_STAT) { - print_csv_header(&msg, sizeof(trash)); + print_csv_header(&msg); if (buffer_write_chunk(rep, &msg) >= 0) return 0; } @@ -408,7 +407,7 @@ int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri) case DATA_ST_INFO: up = (now.tv_sec - start_date.tv_sec); if (s->data_ctx.stats.flags & STAT_SHOW_INFO) { - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "Name: " PRODUCT_NAME "\n" "Version: " HAPROXY_VERSION "\n" "Release_date: " HAPROXY_DATE "\n" @@ -519,12 +518,11 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) struct chunk msg; unsigned int up; - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); switch (s->data_state) { case DATA_ST_INIT: - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "HTTP/1.0 200 OK\r\n" "Cache-Control: no-cache\r\n" "Connection: close\r\n" @@ -532,14 +530,14 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) (s->data_ctx.stats.flags & STAT_FMT_CSV) ? "text/plain" : "text/html"); if (uri->refresh > 0 && !(s->data_ctx.stats.flags & STAT_NO_REFRESH)) - chunk_printf(&msg, sizeof(trash), "Refresh: %d\r\n", + chunk_printf(&msg, "Refresh: %d\r\n", uri->refresh); - chunk_printf(&msg, sizeof(trash), "\r\n"); + chunk_printf(&msg, "\r\n"); s->txn.status = 200; stream_int_retnclose(rep->cons, &msg); // send the start of the response. - msg.len = 0; + chunk_init(&msg, trash, sizeof(trash)); if (!(s->flags & SN_ERR_MASK)) // this is not really an error but it is s->flags |= SN_ERR_PRXCOND; // to mark that it comes from the proxy @@ -559,7 +557,7 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) case DATA_ST_HEAD: if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) { /* WARNING! This must fit in the first buffer !!! */ - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<html><head><title>Statistics Report for " PRODUCT_NAME "%s%s</title>\n" "<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n" "<style type=\"text/css\"><!--\n" @@ -637,7 +635,7 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) uri->node_name ? uri->node_name : "" ); } else { - print_csv_header(&msg, sizeof(trash)); + print_csv_header(&msg); } if (buffer_write_chunk(rep, &msg) >= 0) return 0; @@ -653,7 +651,7 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) * become tricky if we want to support 4kB buffers ! */ if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) { - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<body><h1><a href=\"" PRODUCT_URL "\" style=\"text-decoration: none;\">" PRODUCT_NAME "%s</a></h1>\n" "<h2>Statistics Report for pid %d%s%s</h2>\n" @@ -700,13 +698,13 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) ); if (s->data_ctx.stats.flags & STAT_HIDE_DOWN) - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<li><a href=\"%s%s%s\">Show all servers</a><br>\n", uri->uri_prefix, "", (s->data_ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : ""); else - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<li><a href=\"%s%s%s\">Hide 'DOWN' servers</a><br>\n", uri->uri_prefix, ";up", @@ -714,31 +712,31 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) if (uri->refresh > 0) { if (s->data_ctx.stats.flags & STAT_NO_REFRESH) - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<li><a href=\"%s%s%s\">Enable refresh</a><br>\n", uri->uri_prefix, (s->data_ctx.stats.flags & STAT_HIDE_DOWN) ? ";up" : "", ""); else - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<li><a href=\"%s%s%s\">Disable refresh</a><br>\n", uri->uri_prefix, (s->data_ctx.stats.flags & STAT_HIDE_DOWN) ? ";up" : "", ";norefresh"); } - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<li><a href=\"%s%s%s\">Refresh now</a><br>\n", uri->uri_prefix, (s->data_ctx.stats.flags & STAT_HIDE_DOWN) ? ";up" : "", (s->data_ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<li><a href=\"%s;csv%s\">CSV export</a><br>\n", uri->uri_prefix, (uri->refresh > 0) ? ";norefresh" : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "</td>" "<td align=\"left\" valign=\"top\" nowrap width=\"1%%\">" "<b>External ressources:</b><ul style=\"margin-top: 0.25em;\">\n" @@ -779,7 +777,7 @@ int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri) case DATA_ST_END: if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) { - chunk_printf(&msg, sizeof(trash), "</body></html>\n"); + chunk_printf(&msg, "</body></html>\n"); if (buffer_write_chunk(rep, &msg) >= 0) return 0; } @@ -810,8 +808,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) struct server *sv, *svs; /* server and server-state, server-state=server or server->tracked */ struct chunk msg; - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); switch (s->data_ctx.stats.px_st) { case DATA_ST_PX_INIT: @@ -851,7 +848,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) case DATA_ST_PX_TH: if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) { /* print a new table */ - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<table cols=\"29\" class=\"tbl\" width=\"100%%\">\n" "<tr align=\"center\" class=\"titre\">" "<th colspan=2 class=\"pxname\">%s</th>" @@ -889,7 +886,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) if ((px->cap & PR_CAP_FE) && (!(s->data_ctx.stats.flags & STAT_BOUND) || (s->data_ctx.stats.type & (1 << STATS_TYPE_FE)))) { if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) { - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* name, queue */ "<tr align=center class=\"frontend\"><td>Frontend</td><td colspan=3></td>" /* sessions rate : current, max, limit */ @@ -905,7 +902,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) U2H3(px->feconn), U2H4(px->feconn_max), U2H5(px->maxconn), U2H6(px->cum_feconn), U2H7(px->bytes_in), U2H8(px->bytes_out)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* denied: req, resp */ "<td align=right>%s</td><td align=right>%s</td>" /* errors : request, connect, response */ @@ -922,7 +919,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) px->state == PR_STRUN ? "OPEN" : px->state == PR_STIDLE ? "FULL" : "STOP"); } else { - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* pxid, name, queue cur, queue max, */ "%s,FRONTEND,,," /* sessions : current, max, limit, total */ @@ -1016,7 +1013,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) "UP %d/%d ↓", "UP", "NOLB %d/%d ↓", "NOLB", "<i>no check</i>" }; - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* name */ "<tr align=\"center\" class=\"%s%d\"><td>%s</td>" /* queue : current, max, limit */ @@ -1034,7 +1031,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) U2H5(sv->cur_sess), U2H6(sv->cur_sess_max), LIM2A7(sv->maxconn, "-"), U2H8(sv->cum_sess), U2H9(sv->cum_lbconn)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* bytes : in, out */ "<td align=right>%s</td><td align=right>%s</td>" /* denied: req, resp */ @@ -1050,32 +1047,32 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) sv->retries, sv->redispatches); /* status, lest check */ - chunk_printf(&msg, sizeof(trash), "<td nowrap>"); + chunk_printf(&msg, "<td nowrap>"); if (sv->state & SRV_CHECKED) { - chunk_printf(&msg, sizeof(trash), "%s ", + chunk_printf(&msg, "%s ", human_time(now.tv_sec - sv->last_change, 1)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, srv_hlt_st[sv_state], (svs->state & SRV_RUNNING) ? (svs->health - svs->rise + 1) : (svs->health), (svs->state & SRV_RUNNING) ? (svs->fall) : (svs->rise)); - chunk_printf(&msg, sizeof(trash), "</td><td title=\"%s\" nowrap> %s%s", + chunk_printf(&msg, "</td><td title=\"%s\" nowrap> %s%s", get_check_status_description(sv->check_status), tv_iszero(&sv->check_start)?"":"* ", get_check_status_info(sv->check_status)); if (sv->check_status >= HCHK_STATUS_L57DATA) - chunk_printf(&msg, sizeof(trash), "/%d", sv->check_code); + chunk_printf(&msg, "/%d", sv->check_code); if (sv->check_status >= HCHK_STATUS_CHECKED) - chunk_printf(&msg, sizeof(trash), " in %lums", sv->check_duration); + chunk_printf(&msg, " in %lums", sv->check_duration); } else { - chunk_printf(&msg, sizeof(trash), "</td><td>"); + chunk_printf(&msg, "</td><td>"); } - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* weight */ "</td><td>%d</td>" /* act, bck */ @@ -1087,17 +1084,17 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) /* check failures: unique, fatal, down time */ if (sv->state & SRV_CHECKED) - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<td align=right>%lld</td><td align=right>%lld</td>" "<td nowrap align=right>%s</td>" "", svs->failed_checks, svs->down_trans, human_time(srv_downtime(sv), 1)); else if (sv != svs) - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<td nowrap colspan=3>via %s/%s</td>", svs->proxy->id, svs->id); else - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<td colspan=3></td>"); /* throttle */ @@ -1106,10 +1103,10 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) now.tv_sec >= sv->last_change) { unsigned int ratio; ratio = MAX(1, 100 * (now.tv_sec - sv->last_change) / sv->slowstart); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<td>%d %%</td></tr>\n", ratio); } else { - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "<td>-</td></tr>\n"); } } else { @@ -1117,7 +1114,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) "UP %d/%d,", "UP,", "NOLB %d/%d,", "NOLB,", "no check," }; - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* pxid, name */ "%s,%s," /* queue : current, max */ @@ -1142,12 +1139,12 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) sv->retries, sv->redispatches); /* status */ - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, srv_hlt_st[sv_state], (sv->state & SRV_RUNNING) ? (sv->health - sv->rise + 1) : (sv->health), (sv->state & SRV_RUNNING) ? (sv->fall) : (sv->rise)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* weight, active, backup */ "%d,%d,%d," "", @@ -1157,16 +1154,16 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) /* check failures: unique, fatal; last change, total downtime */ if (sv->state & SRV_CHECKED) - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "%lld,%lld,%d,%d,", sv->failed_checks, sv->down_trans, (int)(now.tv_sec - sv->last_change), srv_downtime(sv)); else - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, ",,,,"); /* queue limit, pid, iid, sid, */ - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "%s," "%d,%d,%d,", LIM2A0(sv->maxqueue, ""), @@ -1178,49 +1175,49 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) now.tv_sec >= sv->last_change) { unsigned int ratio; ratio = MAX(1, 100 * (now.tv_sec - sv->last_change) / sv->slowstart); - chunk_printf(&msg, sizeof(trash), "%d", ratio); + chunk_printf(&msg, "%d", ratio); } /* sessions: lbtot */ - chunk_printf(&msg, sizeof(trash), ",%lld,", sv->cum_lbconn); + chunk_printf(&msg, ",%lld,", sv->cum_lbconn); /* tracked */ if (sv->tracked) - chunk_printf(&msg, sizeof(trash), "%s/%s,", + chunk_printf(&msg, "%s/%s,", sv->tracked->proxy->id, sv->tracked->id); else - chunk_printf(&msg, sizeof(trash), ","); + chunk_printf(&msg, ","); /* type */ - chunk_printf(&msg, sizeof(trash), "%d,", STATS_TYPE_SV); + chunk_printf(&msg, "%d,", STATS_TYPE_SV); /* rate */ - chunk_printf(&msg, sizeof(trash), "%u,,%u,", + chunk_printf(&msg, "%u,,%u,", read_freq_ctr(&sv->sess_per_sec), sv->sps_max); if (sv->state & SRV_CHECKED) { /* check_status */ - chunk_printf(&msg, sizeof(trash), "%s,", get_check_status_info(sv->check_status)); + chunk_printf(&msg, "%s,", get_check_status_info(sv->check_status)); /* check_code */ if (sv->check_status >= HCHK_STATUS_L57DATA) - chunk_printf(&msg, sizeof(trash), "%u,", sv->check_code); + chunk_printf(&msg, "%u,", sv->check_code); else - chunk_printf(&msg, sizeof(trash), ","); + chunk_printf(&msg, ","); /* check_duration */ if (sv->check_status >= HCHK_STATUS_CHECKED) - chunk_printf(&msg, sizeof(trash), "%lu,", sv->check_duration); + chunk_printf(&msg, "%lu,", sv->check_duration); else - chunk_printf(&msg, sizeof(trash), ","); + chunk_printf(&msg, ","); } else { - chunk_printf(&msg, sizeof(trash), ",,,"); + chunk_printf(&msg, ",,,"); } /* finish with EOL */ - chunk_printf(&msg, sizeof(trash), "\n"); + chunk_printf(&msg, "\n"); } if (buffer_write_chunk(rep, &msg) >= 0) return 0; @@ -1234,7 +1231,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) if ((px->cap & PR_CAP_BE) && (!(s->data_ctx.stats.flags & STAT_BOUND) || (s->data_ctx.stats.type & (1 << STATS_TYPE_BE)))) { if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) { - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* name */ "<tr align=center class=\"backend\"><td>Backend</td>" /* queue : current, max */ @@ -1245,7 +1242,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) U2H0(px->nbpend) /* or px->totpend ? */, U2H1(px->nbpend_max), U2H2(read_freq_ctr(&px->be_sess_per_sec)), U2H3(px->be_sps_max)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* sessions : current, max, limit, total, lbtot */ "<td align=right>%s</td><td align=right>%s</td><td align=right>%s</td>" "<td align=right>%s</td><td align=right>%s</td>" @@ -1256,7 +1253,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) U2H6(px->cum_beconn), U2H7(px->cum_lbconn), U2H8(px->bytes_in), U2H9(px->bytes_out)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* denied: req, resp */ "<td align=right>%s</td><td align=right>%s</td>" /* errors : request, connect, response */ @@ -1279,7 +1276,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv, px->srv_act, px->srv_bck); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* rest of backend: nothing, down transitions, total downtime, throttle */ "<td align=center> </td><td align=\"right\">%d</td>" "<td align=\"right\" nowrap>%s</td>" @@ -1288,7 +1285,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) px->down_trans, px->srv?human_time(be_downtime(px), 1):" "); } else { - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, /* pxid, name */ "%s,BACKEND," /* queue : current, max */ @@ -1344,7 +1341,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri) case DATA_ST_PX_END: if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) { - chunk_printf(&msg, sizeof(trash), "</table><p>\n"); + chunk_printf(&msg, "</table><p>\n"); if (buffer_write_chunk(rep, &msg) >= 0) return 0; @@ -1392,8 +1389,7 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) if (s->ana_state != STATS_ST_REP) return; - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); switch (s->data_state) { case DATA_ST_INIT: @@ -1424,7 +1420,7 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) curr_sess = LIST_ELEM(s->data_ctx.sess.bref.ref, struct session *, list); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, "%p: proto=%s", curr_sess, curr_sess->listener->proto->name); @@ -1435,7 +1431,7 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) (const void *)&((struct sockaddr_in *)&curr_sess->cli_addr)->sin_addr, pn, sizeof(pn)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " src=%s:%d fe=%s be=%s srv=%s", pn, ntohs(((struct sockaddr_in *)&curr_sess->cli_addr)->sin_port), @@ -1449,7 +1445,7 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) (const void *)&((struct sockaddr_in6 *)(&curr_sess->cli_addr))->sin6_addr, pn, sizeof(pn)); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " src=%s:%d fe=%s be=%s srv=%s", pn, ntohs(((struct sockaddr_in6 *)&curr_sess->cli_addr)->sin6_port), @@ -1464,13 +1460,13 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) break; } - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " as=%d ts=%02x age=%s calls=%d", curr_sess->ana_state, curr_sess->task->state, human_time(now.tv_sec - curr_sess->logs.tv_accept.tv_sec, 1), curr_sess->task->calls); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " rq[f=%06xh,l=%d,an=%02xh,rx=%s", curr_sess->req->flags, curr_sess->req->l, @@ -1479,19 +1475,19 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) human_time(TICKS_TO_MS(curr_sess->req->rex - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, ",wx=%s", curr_sess->req->wex ? human_time(TICKS_TO_MS(curr_sess->req->wex - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, ",ax=%s]", curr_sess->req->analyse_exp ? human_time(TICKS_TO_MS(curr_sess->req->analyse_exp - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " rp[f=%06xh,l=%d,an=%02xh,rx=%s", curr_sess->rep->flags, curr_sess->rep->l, @@ -1500,19 +1496,19 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) human_time(TICKS_TO_MS(curr_sess->rep->rex - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, ",wx=%s", curr_sess->rep->wex ? human_time(TICKS_TO_MS(curr_sess->rep->wex - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, ",ax=%s]", curr_sess->rep->analyse_exp ? human_time(TICKS_TO_MS(curr_sess->rep->analyse_exp - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " s0=[%d,%1xh,fd=%d,ex=%s]", curr_sess->si[0].state, curr_sess->si[0].flags, @@ -1521,7 +1517,7 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) human_time(TICKS_TO_MS(curr_sess->si[0].exp - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " s1=[%d,%1xh,fd=%d,ex=%s]", curr_sess->si[1].state, curr_sess->si[1].flags, @@ -1530,15 +1526,15 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) human_time(TICKS_TO_MS(curr_sess->si[1].exp - now_ms), TICKS_TO_MS(1000)) : ""); - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " exp=%s", curr_sess->task->expire ? human_time(TICKS_TO_MS(curr_sess->task->expire - now_ms), TICKS_TO_MS(1000)) : ""); if (task_in_rq(curr_sess->task)) - chunk_printf(&msg, sizeof(trash), " run(nice=%d)", curr_sess->task->nice); + chunk_printf(&msg, " run(nice=%d)", curr_sess->task->nice); - chunk_printf(&msg, sizeof(trash), "\n"); + chunk_printf(&msg, "\n"); if (buffer_write_chunk(rep, &msg) >= 0) { /* let's try again later from this session. We add ourselves into @@ -1569,17 +1565,17 @@ void stats_dump_sess_to_buffer(struct session *s, struct buffer *rep) * continuation of a previous truncated line begin with "+" instead of " " * after the offset. The new pointer is returned. */ -static int dump_error_line(struct chunk *out, int size, - struct error_snapshot *err, int *line, int ptr) +static int dump_error_line(struct chunk *out, struct error_snapshot *err, + int *line, int ptr) { int end; unsigned char c; end = out->len + 80; - if (end > size) + if (end > out->size) return ptr; - chunk_printf(out, size, " %05d%c ", ptr, (ptr == *line) ? ' ' : '+'); + chunk_printf(out, " %05d%c ", ptr, (ptr == *line) ? ' ' : '+'); while (ptr < err->len) { c = err->buf[ptr]; @@ -1640,8 +1636,7 @@ void stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) if (s->ana_state != STATS_ST_REP) return; - msg.len = 0; - msg.str = trash; + chunk_init(&msg, trash, sizeof(trash)); if (!s->data_ctx.errors.px) { /* the function had not been called yet, let's prepare the @@ -1680,7 +1675,7 @@ void stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) struct tm tm; get_localtime(es->when.tv_sec, &tm); - chunk_printf(&msg, sizeof(trash), "\n[%02d/%s/%04d:%02d:%02d:%02d.%03d]", + chunk_printf(&msg, "\n[%02d/%s/%04d:%02d:%02d:%02d.%03d]", tm.tm_mday, monthname[tm.tm_mon], tm.tm_year+1900, tm.tm_hour, tm.tm_min, tm.tm_sec, (int)(es->when.tv_usec/1000)); @@ -1696,7 +1691,7 @@ void stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) switch (s->data_ctx.errors.buf) { case 0: - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " frontend %s (#%d): invalid request\n" " src %s, session #%d, backend %s (#%d), server %s (#%d)\n" " request length %d bytes, error at position %d:\n\n", @@ -1707,7 +1702,7 @@ void stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) es->len, es->pos); break; case 1: - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " backend %s (#%d) : invalid response\n" " src %s, session #%d, frontend %s (#%d), server %s (#%d)\n" " response length %d bytes, error at position %d:\n\n", @@ -1729,7 +1724,7 @@ void stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) if (s->data_ctx.errors.sid != es->sid) { /* the snapshot changed while we were dumping it */ - chunk_printf(&msg, sizeof(trash), + chunk_printf(&msg, " WARNING! update detected on this snapshot, dump interrupted. Please re-check!\n"); if (buffer_write_chunk(rep, &msg) >= 0) return; @@ -1742,7 +1737,7 @@ void stats_dump_errors_to_buffer(struct session *s, struct buffer *rep) int newline; newline = s->data_ctx.errors.bol; - newptr = dump_error_line(&msg, sizeof(trash), es, &newline, s->data_ctx.errors.ptr); + newptr = dump_error_line(&msg, es, &newline, s->data_ctx.errors.ptr); if (newptr == s->data_ctx.errors.ptr) return; diff --git a/src/haproxy.c b/src/haproxy.c index 237fa25..4db7641 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -701,7 +701,7 @@ void deinit(void) free(p->monitor_uri); for (i = 0; i < HTTP_ERR_SIZE; i++) - free(p->errmsg[i].str); + chunk_destroy(&p->errmsg[i]); for (i = 0; i < p->nb_reqadd; i++) free(p->req_add[i]); diff --git a/src/proto_http.c b/src/proto_http.c index dd4ee9c..f494848 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -640,7 +640,7 @@ void perform_http_redirect(struct session *s, struct stream_interface *si) memcpy(rdr.str, HTTP_302, rdr.len); /* 2: add the server's prefix */ - if (rdr.len + s->srv->rdr_len > sizeof(trash)) + if (rdr.len + s->srv->rdr_len > rdr.size) return; memcpy(rdr.str + rdr.len, s->srv->rdr_pfx, s->srv->rdr_len); @@ -653,7 +653,7 @@ void perform_http_redirect(struct session *s, struct stream_interface *si) return; len = txn->req.sl.rq.u_l + (txn->req.sol+txn->req.sl.rq.u) - path; - if (rdr.len + len > sizeof(trash) - 4) /* 4 for CRLF-CRLF */ + if (rdr.len + len > rdr.size - 4) /* 4 for CRLF-CRLF */ return; memcpy(rdr.str + rdr.len, path, len); @@ -2199,23 +2199,19 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s /* build redirect message */ switch(rule->code) { case 303: - rdr.len = strlen(HTTP_303); msg_fmt = HTTP_303; break; case 301: - rdr.len = strlen(HTTP_301); msg_fmt = HTTP_301; break; case 302: default: - rdr.len = strlen(HTTP_302); msg_fmt = HTTP_302; break; } - if (unlikely(rdr.len > sizeof(trash))) + if (unlikely(chunk_strcpy(&rdr, msg_fmt))) goto return_bad_req; - memcpy(rdr.str, msg_fmt, rdr.len); switch(rule->type) { case REDIRECT_TYPE_PREFIX: { @@ -2241,7 +2237,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s pathlen = 1; } - if (rdr.len + rule->rdr_len + pathlen > sizeof(trash) - 4) + if (rdr.len + rule->rdr_len + pathlen > rdr.size - 4) goto return_bad_req; /* add prefix. Note that if prefix == "/", we don't want to @@ -2260,7 +2256,7 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s } case REDIRECT_TYPE_LOCATION: default: - if (rdr.len + rule->rdr_len > sizeof(trash) - 4) + if (rdr.len + rule->rdr_len > rdr.size - 4) goto return_bad_req; /* add location */ @@ -4599,8 +4595,8 @@ int stats_check_uri_auth(struct session *t, struct proxy *backend) struct chunk msg; /* no need to go further */ - msg.str = trash; - msg.len = sprintf(trash, HTTP_401_fmt, uri_auth->auth_realm); + sprintf(trash, HTTP_401_fmt, uri_auth->auth_realm); + chunk_initlen(&msg, trash, sizeof(trash), strlen(trash)); txn->status = 401; stream_int_retnclose(t->req->prod, &msg); t->req->analysers = 0; -- 1.6.4.2