[CLEANUP] move remaining stats sockets code to dumpstats
The remains of the stats socket code has nothing to do in proto_uxst
anymore and must move to dumpstats. The code is much cleaner and more
structured. It was also an opportunity to rename AN_REQ_UNIX_STATS
as AN_REQ_STATS_SOCK as the stats socket is no longer unix-specific
either.
The last item refering to stats in proto_uxst is the setting of the
task's nice value which should in fact come from the listener.
diff --git a/include/common/defaults.h b/include/common/defaults.h
index f0873cf..966ef4f 100644
--- a/include/common/defaults.h
+++ b/include/common/defaults.h
@@ -64,8 +64,8 @@
// max # args on a configuration line
#define MAX_LINE_ARGS 64
-// max # args on a uxts socket
-#define MAX_UXST_ARGS 16
+// max # args on a stats socket
+#define MAX_STATS_ARGS 16
// max # of added headers per request
#define MAX_NEWHDR 10
diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h
index 844879a..a0167a7 100644
--- a/include/proto/dumpstats.h
+++ b/include/proto/dumpstats.h
@@ -44,6 +44,8 @@
#define STATS_ST_REP 2
#define STATS_ST_CLOSE 3
+int stats_sock_parse_request(struct session *s, char *line);
+int stats_sock_req_analyser(struct session *s, struct buffer *req, int an_bit);
int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri);
void stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri);
diff --git a/include/types/buffers.h b/include/types/buffers.h
index 0553116..b9836b2 100644
--- a/include/types/buffers.h
+++ b/include/types/buffers.h
@@ -113,7 +113,7 @@
#define AN_REQ_HTTP_INNER 0x00000020 /* inner processing of HTTP request */
#define AN_REQ_HTTP_TARPIT 0x00000040 /* wait for end of HTTP tarpit */
#define AN_REQ_HTTP_BODY 0x00000080 /* inspect HTTP request body */
-#define AN_REQ_UNIX_STATS 0x00000100 /* process unix stats socket request */
+#define AN_REQ_STATS_SOCK 0x00000100 /* process stats socket request */
#define AN_RTR_HTTP_HDR 0x00000200 /* inspect HTTP response headers */
#define AN_REQ_PRST_RDP_COOKIE 0x00000400 /* persistence on rdp cookie */
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 2683b52..91c90e9 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -50,6 +50,19 @@
#include <proto/stream_interface.h>
#include <proto/task.h>
+const char stats_sock_usage_msg[] =
+ "Unknown command. Please enter one of the following commands only :\n"
+ " show info : report information about the running process\n"
+ " show stat : report counters for each proxy and server\n"
+ " show errors : report last request and response errors for each proxy\n"
+ " show sess : report the list of current sessions\n"
+ "\n";
+
+const struct chunk stats_sock_usage = {
+ .str = (char *)&stats_sock_usage_msg,
+ .len = sizeof(stats_sock_usage_msg)-1
+};
+
/* This function parses a "stats" statement in the "global" section. It returns
* -1 if there is any error, otherwise zero. If it returns -1, it may write an
* error message into ther <err> buffer, for at most <errlen> bytes, trailing
@@ -107,7 +120,7 @@
global.stats_sock.options = LI_O_NONE;
global.stats_sock.accept = uxst_event_accept;
global.stats_sock.handler = process_session;
- global.stats_sock.analysers = AN_REQ_UNIX_STATS;
+ global.stats_sock.analysers = AN_REQ_STATS_SOCK;
global.stats_sock.private = global.stats_fe; /* must point to the frontend */
global.stats_fe->timeout.client = MS_TO_TICKS(10000); /* default timeout of 10 seconds */
@@ -211,6 +224,147 @@
"\n");
}
+/* Parses the request line in <cmd> and possibly starts dumping stats on
+ * s->rep with the hijack bit set. Returns 1 if OK, 0 in case of any error.
+ * The line is modified after parsing.
+ */
+int stats_sock_parse_request(struct session *s, char *line)
+{
+ char *args[MAX_STATS_ARGS + 1];
+ int arg;
+
+ while (isspace((unsigned char)*line))
+ line++;
+
+ arg = 0;
+ args[arg] = line;
+
+ while (*line && arg < MAX_STATS_ARGS) {
+ if (isspace((unsigned char)*line)) {
+ *line++ = '\0';
+
+ while (isspace((unsigned char)*line))
+ line++;
+
+ args[++arg] = line;
+ continue;
+ }
+
+ line++;
+ }
+
+ while (++arg <= MAX_STATS_ARGS)
+ args[arg] = line;
+
+ if (strcmp(args[0], "show") == 0) {
+ if (strcmp(args[1], "stat") == 0) {
+ if (*args[2] && *args[3] && *args[4]) {
+ s->data_ctx.stats.flags |= STAT_BOUND;
+ s->data_ctx.stats.iid = atoi(args[2]);
+ s->data_ctx.stats.type = atoi(args[3]);
+ s->data_ctx.stats.sid = atoi(args[4]);
+ }
+
+ s->data_ctx.stats.flags |= STAT_SHOW_STAT;
+ s->data_ctx.stats.flags |= STAT_FMT_CSV;
+ s->ana_state = STATS_ST_REP;
+ buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
+ }
+ else if (strcmp(args[1], "info") == 0) {
+ s->data_ctx.stats.flags |= STAT_SHOW_INFO;
+ s->data_ctx.stats.flags |= STAT_FMT_CSV;
+ s->ana_state = STATS_ST_REP;
+ buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
+ }
+ else if (strcmp(args[1], "sess") == 0) {
+ s->ana_state = STATS_ST_REP;
+ buffer_install_hijacker(s, s->rep, stats_dump_sess_to_buffer);
+ }
+ else if (strcmp(args[1], "errors") == 0) {
+ if (*args[2])
+ s->data_ctx.errors.iid = atoi(args[2]);
+ else
+ s->data_ctx.errors.iid = -1;
+ s->data_ctx.errors.px = NULL;
+ s->ana_state = STATS_ST_REP;
+ buffer_install_hijacker(s, s->rep, stats_dump_errors_to_buffer);
+ }
+ else { /* neither "stat" nor "info" nor "sess" */
+ return 0;
+ }
+ }
+ else { /* not "show" */
+ return 0;
+ }
+ return 1;
+}
+
+/* Processes the stats interpreter on the statistics socket.
+ * In order to ease the transition, we simply simulate the server status
+ * for now. It only knows states STATS_ST_INIT, STATS_ST_REQ, STATS_ST_REP, and
+ * STATS_ST_CLOSE. It removes its analyser bit from req->analysers once done.
+ * It always returns 0.
+ */
+int stats_sock_req_analyser(struct session *s, struct buffer *req, int an_bit)
+{
+ char *line, *p;
+
+ switch (s->ana_state) {
+ case STATS_ST_INIT:
+ /* Stats output not initialized yet */
+ memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
+ s->data_source = DATA_SRC_STATS;
+ s->ana_state = STATS_ST_REQ;
+ buffer_write_dis(s->req);
+ /* fall through */
+
+ case STATS_ST_REQ:
+ /* Now, stats are initialized, hijack is not set, and
+ * we are waiting for a complete request line.
+ */
+
+ line = s->req->data;
+ p = memchr(line, '\n', s->req->l);
+
+ if (p) {
+ *p = '\0';
+ if (!stats_sock_parse_request(s, line)) {
+ /* invalid request */
+ stream_int_retnclose(s->req->prod, &stats_sock_usage);
+ s->ana_state = 0;
+ req->analysers = 0;
+ return 0;
+ }
+ }
+
+ /* processing a valid or incomplete request */
+ if ((req->flags & BF_FULL) || /* invalid request */
+ (req->flags & BF_READ_ERROR) || /* input error */
+ (req->flags & BF_READ_TIMEOUT) || /* read timeout */
+ tick_is_expired(req->analyse_exp, now_ms) || /* request timeout */
+ (req->flags & BF_SHUTR)) { /* input closed */
+ buffer_shutw_now(s->rep);
+ s->ana_state = 0;
+ req->analysers = 0;
+ return 0;
+ }
+ /* don't forward nor abort */
+ req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
+ return 0;
+
+ case STATS_ST_REP:
+ /* do nothing while response is being processed */
+ return 0;
+
+ case STATS_ST_CLOSE:
+ /* end of dump */
+ s->req->analysers &= ~an_bit;
+ s->ana_state = 0;
+ break;
+ }
+ return 0;
+}
+
/*
* Produces statistics data for the session <s>. Expects to be called with
* client socket shut down on input. It *may* make use of informations from
diff --git a/src/proto_uxst.c b/src/proto_uxst.c
index 1c751d6..5078369 100644
--- a/src/proto_uxst.c
+++ b/src/proto_uxst.c
@@ -41,7 +41,6 @@
#include <proto/acl.h>
#include <proto/backend.h>
#include <proto/buffers.h>
-#include <proto/dumpstats.h>
#include <proto/fd.h>
#include <proto/log.h>
#include <proto/protocols.h>
@@ -78,19 +77,6 @@
.nb_listeners = 0,
};
-const char unix_sock_usage_msg[] =
- "Unknown command. Please enter one of the following commands only :\n"
- " show info : report information about the running process\n"
- " show stat : report counters for each proxy and server\n"
- " show errors : report last request and response errors for each proxy\n"
- " show sess : report the list of current sessions\n"
- "\n";
-
-const struct chunk unix_sock_usage = {
- .str = (char *)&unix_sock_usage_msg,
- .len = sizeof(unix_sock_usage_msg)-1
-};
-
/********************************
* 1) low-level socket functions
********************************/
@@ -572,148 +558,6 @@
return 0;
}
-/* Parses the request line in <cmd> and possibly starts dumping stats on
- * s->rep with the hijack bit set. Returns 1 if OK, 0 in case of any error.
- * The line is modified after parsing.
- */
-int unix_sock_parse_request(struct session *s, char *line)
-{
- char *args[MAX_UXST_ARGS + 1];
- int arg;
-
- while (isspace((unsigned char)*line))
- line++;
-
- arg = 0;
- args[arg] = line;
-
- while (*line && arg < MAX_UXST_ARGS) {
- if (isspace((unsigned char)*line)) {
- *line++ = '\0';
-
- while (isspace((unsigned char)*line))
- line++;
-
- args[++arg] = line;
- continue;
- }
-
- line++;
- }
-
- while (++arg <= MAX_UXST_ARGS)
- args[arg] = line;
-
- if (strcmp(args[0], "show") == 0) {
- if (strcmp(args[1], "stat") == 0) {
- if (*args[2] && *args[3] && *args[4]) {
- s->data_ctx.stats.flags |= STAT_BOUND;
- s->data_ctx.stats.iid = atoi(args[2]);
- s->data_ctx.stats.type = atoi(args[3]);
- s->data_ctx.stats.sid = atoi(args[4]);
- }
-
- s->data_ctx.stats.flags |= STAT_SHOW_STAT;
- s->data_ctx.stats.flags |= STAT_FMT_CSV;
- s->ana_state = STATS_ST_REP;
- buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
- }
- else if (strcmp(args[1], "info") == 0) {
- s->data_ctx.stats.flags |= STAT_SHOW_INFO;
- s->data_ctx.stats.flags |= STAT_FMT_CSV;
- s->ana_state = STATS_ST_REP;
- buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
- }
- else if (strcmp(args[1], "sess") == 0) {
- s->ana_state = STATS_ST_REP;
- buffer_install_hijacker(s, s->rep, stats_dump_sess_to_buffer);
- }
- else if (strcmp(args[1], "errors") == 0) {
- if (*args[2])
- s->data_ctx.errors.iid = atoi(args[2]);
- else
- s->data_ctx.errors.iid = -1;
- s->data_ctx.errors.px = NULL;
- s->ana_state = STATS_ST_REP;
- buffer_install_hijacker(s, s->rep, stats_dump_errors_to_buffer);
- }
- else { /* neither "stat" nor "info" nor "sess" */
- return 0;
- }
- }
- else { /* not "show" */
- return 0;
- }
- return 1;
-}
-
-/* Processes the stats interpreter on the statistics socket.
- * In order to ease the transition, we simply simulate the server status
- * for now. It only knows states STATS_ST_INIT, STATS_ST_REQ, STATS_ST_REP, and
- * STATS_ST_CLOSE. It removes the AN_REQ_UNIX_STATS bit from req->analysers
- * once done. It always returns 0.
- */
-int uxst_req_analyser_stats(struct session *s, struct buffer *req, int an_bit)
-{
- char *line, *p;
-
- switch (s->ana_state) {
- case STATS_ST_INIT:
- /* Stats output not initialized yet */
- memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
- s->data_source = DATA_SRC_STATS;
- s->ana_state = STATS_ST_REQ;
- buffer_write_dis(s->req);
- /* fall through */
-
- case STATS_ST_REQ:
- /* Now, stats are initialized, hijack is not set, and
- * we are waiting for a complete request line.
- */
-
- line = s->req->data;
- p = memchr(line, '\n', s->req->l);
-
- if (p) {
- *p = '\0';
- if (!unix_sock_parse_request(s, line)) {
- /* invalid request */
- stream_int_retnclose(s->req->prod, &unix_sock_usage);
- s->ana_state = 0;
- req->analysers = 0;
- return 0;
- }
- }
-
- /* processing a valid or incomplete request */
- if ((req->flags & BF_FULL) || /* invalid request */
- (req->flags & BF_READ_ERROR) || /* input error */
- (req->flags & BF_READ_TIMEOUT) || /* read timeout */
- tick_is_expired(req->analyse_exp, now_ms) || /* request timeout */
- (req->flags & BF_SHUTR)) { /* input closed */
- buffer_shutw_now(s->rep);
- s->ana_state = 0;
- req->analysers = 0;
- return 0;
- }
- /* don't forward nor abort */
- req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
- return 0;
-
- case STATS_ST_REP:
- /* do nothing while response is being processed */
- return 0;
-
- case STATS_ST_CLOSE:
- /* end of dump */
- s->req->analysers &= ~an_bit;
- s->ana_state = 0;
- break;
- }
- return 0;
-}
-
-
__attribute__((constructor))
static void __uxst_protocol_init(void)
{
diff --git a/src/session.c b/src/session.c
index 56bf102..809ee2b 100644
--- a/src/session.c
+++ b/src/session.c
@@ -22,13 +22,13 @@
#include <proto/acl.h>
#include <proto/backend.h>
#include <proto/buffers.h>
+#include <proto/dumpstats.h>
#include <proto/hdr_idx.h>
#include <proto/log.h>
#include <proto/session.h>
#include <proto/pipe.h>
#include <proto/proto_http.h>
#include <proto/proto_tcp.h>
-#include <proto/proto_uxst.h>
#include <proto/proxy.h>
#include <proto/queue.h>
#include <proto/server.h>
@@ -841,9 +841,9 @@
break;
}
- if (s->req->analysers & AN_REQ_UNIX_STATS) {
- last_ana |= AN_REQ_UNIX_STATS;
- if (!uxst_req_analyser_stats(s, s->req, AN_REQ_UNIX_STATS))
+ if (s->req->analysers & AN_REQ_STATS_SOCK) {
+ last_ana |= AN_REQ_STATS_SOCK;
+ if (!stats_sock_req_analyser(s, s->req, AN_REQ_STATS_SOCK))
break;
}