From: phk Date: Fri, 4 Aug 2006 06:53:26 +0000 (+0000) Subject: Change the CLI protocol in a subtle but useful way: X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bacbff5002626f6395f8d991514f6d206ec77257;p=varnish Change the CLI protocol in a subtle but useful way: The first line of the response has a fixed format ("%-3d %-8u\n") and consequently fixed length (CLI_LINE0_LEN == 13). This makes parsing responses more efficient. Add a function in common_cli to do so. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@630 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/common_cli.c b/varnish-cache/bin/varnishd/common_cli.c index 932b169d..2ff16d52 100644 --- a/varnish-cache/bin/varnishd/common_cli.c +++ b/varnish-cache/bin/varnishd/common_cli.c @@ -52,9 +52,14 @@ cli_writeres(int fd, struct cli *cli) { int i, l; struct iovec iov[3]; - char res[32]; + char res[CLI_LINE0_LEN + 2]; /* + * NUL + one more so we can catch + * any misformats by snprintf + */ - sprintf(res, "%d %d\n", cli->result, sbuf_len(cli->sb)); + i = snprintf(res, sizeof res, + "%-3d %-8d\n", cli->result, sbuf_len(cli->sb)); + assert(i == CLI_LINE0_LEN); iov[0].iov_base = (void*)(uintptr_t)res; iov[1].iov_base = (void*)(uintptr_t)sbuf_data(cli->sb); iov[2].iov_base = (void*)(uintptr_t)"\n"; @@ -65,3 +70,36 @@ cli_writeres(int fd, struct cli *cli) i = writev(fd, iov, 3); return (i != l); } + +int +cli_readres(int fd, unsigned *status, char **ptr) +{ + char res[CLI_LINE0_LEN + 1]; /* For NUL */ + int i, j; + unsigned u, v; + char *p; + + i = read(fd, res, CLI_LINE0_LEN); + if (i < 0) + return (i); + assert(i == CLI_LINE0_LEN); /* XXX: handle */ + assert(res[3] == ' '); + assert(res[CLI_LINE0_LEN - 1] == '\n'); + j = sscanf(res, "%u %u\n", &u, &v); + assert(j == 2); + if (status != NULL) + *status = u; + p = malloc(v + 1); + assert(p != NULL); + i = read(fd, p, v + 1); + if (i < 0) + return (i); + assert(i == v + 1); + assert(p[v] == '\n'); + p[v] = '\0'; + if (ptr == NULL) + free(p); + else + *ptr = p; + return (0); +} diff --git a/varnish-cache/bin/varnishd/common_cli.h b/varnish-cache/bin/varnishd/common_cli.h index 5c62b13f..fedeaaa8 100644 --- a/varnish-cache/bin/varnishd/common_cli.h +++ b/varnish-cache/bin/varnishd/common_cli.h @@ -13,4 +13,5 @@ struct cli { void cli_suspend(struct cli *cli); void cli_resume(struct cli *cli); int cli_writeres(int fd, struct cli *cli); +int cli_readres(int fd, unsigned *status, char **ptr); extern struct cli_proto CLI_cmds[]; diff --git a/varnish-cache/bin/varnishd/mgt_cli.c b/varnish-cache/bin/varnishd/mgt_cli.c index 0b6b3b22..e6630b17 100644 --- a/varnish-cache/bin/varnishd/mgt_cli.c +++ b/varnish-cache/bin/varnishd/mgt_cli.c @@ -37,18 +37,21 @@ mcf_server_startstop(struct cli *cli, char **av, void *priv) } /*-------------------------------------------------------------------- - * Passthru of cli commands. + * Passthru of cli commands. It is more or less just undoing what + * the cli parser did, but such is life... */ static void mcf_passthru(struct cli *cli, char **av, void *priv) { - char buf[BUFSIZ], *bp, *be; - char *p; + char *p, *q, *r; unsigned u, v; - int i, j, k; + int i; + + (void)priv; AZ(pthread_mutex_lock(&cli_mtx)); + /* Request */ if (cli_o <= 0) { AZ(pthread_mutex_unlock(&cli_mtx)); @@ -56,46 +59,37 @@ mcf_passthru(struct cli *cli, char **av, void *priv) cli_out(cli, "Cache process not running"); return; } - (void)priv; - bp = buf; - be = bp + sizeof buf; + v = 0; + for (u = 1; av[u] != NULL; u++) + v += strlen(av[u]) + 3; + p = malloc(v); + assert(p != NULL); + q = p; for (u = 1; av[u] != NULL; u++) { - v = strlen(av[u]); - if (5 + bp + 4 * v > be) { - *bp = '\0'; - v = bp - buf; - i = write(cli_o, buf, v); - assert(i == v); - bp = buf; - } - *bp++ = '"'; - for (p = av[u]; *p; p++) { - switch (*p) { - case '\\': *bp++ = '\\'; *bp++ = '\\'; break; - case '\n': *bp++ = '\\'; *bp++ = 'n'; break; - case '"': *bp++ = '\\'; *bp++ = '"'; break; - default: *bp++ = *p; break; + *q++ = '"'; + for (r = av[u]; *r; r++) { + switch (*r) { + case '\\': *q++ = '\\'; *q++ = '\\'; break; + case '\n': *q++ = '\\'; *q++ = 'n'; break; + case '"': *q++ = '\\'; *q++ = '"'; break; + default: *q++ = *r; break; } } - *bp++ = '"'; - *bp++ = ' '; - } - if (bp != buf) { - *bp++ = '\n'; - v = bp - buf; - i = write(cli_o, buf, v); - assert(i == v); + *q++ = '"'; + *q++ = ' '; } - - /* Response */ - i = read(cli_i, buf, sizeof buf - 1); - assert(i > 0); - buf[i] = '\0'; - j = sscanf(buf, "%u %u\n%n", &u, &v, &k); - assert(j == 2); - assert(i == k + v + 1); + *q++ = '\n'; + v = q - p; + i = write(cli_o, p, v); + assert(i == v); + free(p); + + i = cli_readres(cli_i, &u, &p); + assert(i == 0); cli_result(cli, u); - cli_out(cli, "%*.*s", v, v, buf + k); + cli_out(cli, "%s", p); + free(p); + AZ(pthread_mutex_unlock(&cli_mtx)); } diff --git a/varnish-cache/include/cli.h b/varnish-cache/include/cli.h index b6c54ea9..146011b0 100644 --- a/varnish-cache/include/cli.h +++ b/varnish-cache/include/cli.h @@ -181,3 +181,6 @@ enum cli_status_e { CLIS_OK = 200, CLIS_CANT = 300 }; + +/* Length of first line of response */ +#define CLI_LINE0_LEN 13