Commit 018e9813 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk@630 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 2e7ad94b
......@@ -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);
}
......@@ -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[];
......@@ -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));
}
......
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment