mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Implemented echoing of log messages to CLI connections. Just try `echo all'.
This commit is contained in:
169
nest/cli.c
169
nest/cli.c
@@ -15,6 +15,34 @@
|
||||
|
||||
pool *cli_pool;
|
||||
|
||||
static byte *
|
||||
cli_alloc_out(cli *c, int size)
|
||||
{
|
||||
struct cli_out *o;
|
||||
|
||||
if (!(o = c->tx_write) || o->wpos + size > o->end)
|
||||
{
|
||||
if (!o && c->tx_buf)
|
||||
o = c->tx_buf;
|
||||
else
|
||||
{
|
||||
o = mb_alloc(c->pool, sizeof(struct cli_out) + CLI_TX_BUF_SIZE);
|
||||
if (c->tx_write)
|
||||
c->tx_write->next = o;
|
||||
else
|
||||
c->tx_buf = o;
|
||||
o->next = NULL;
|
||||
o->wpos = o->outpos = o->buf;
|
||||
o->end = o->buf + CLI_TX_BUF_SIZE;
|
||||
}
|
||||
c->tx_write = o;
|
||||
if (!c->tx_pos)
|
||||
c->tx_pos = o;
|
||||
}
|
||||
o->wpos += size;
|
||||
return o->wpos - size;
|
||||
}
|
||||
|
||||
void
|
||||
cli_printf(cli *c, int code, char *msg, ...)
|
||||
{
|
||||
@@ -22,7 +50,6 @@ cli_printf(cli *c, int code, char *msg, ...)
|
||||
byte buf[1024];
|
||||
int cd = code;
|
||||
int size, cnt;
|
||||
struct cli_out *o;
|
||||
|
||||
va_start(args, msg);
|
||||
if (cd < 0)
|
||||
@@ -46,27 +73,44 @@ cli_printf(cli *c, int code, char *msg, ...)
|
||||
}
|
||||
size += cnt;
|
||||
buf[size++] = '\n';
|
||||
if (!(o = c->tx_write) || o->wpos + size > o->end)
|
||||
memcpy(cli_alloc_out(c, size), buf, size);
|
||||
}
|
||||
|
||||
static void
|
||||
cli_copy_message(cli *c)
|
||||
{
|
||||
byte *p, *q;
|
||||
unsigned int cnt = 2;
|
||||
|
||||
if (c->ring_overflow)
|
||||
{
|
||||
if (!o && c->tx_buf)
|
||||
o = c->tx_buf;
|
||||
else
|
||||
{
|
||||
o = mb_alloc(c->pool, sizeof(struct cli_out) + CLI_TX_BUF_SIZE);
|
||||
if (c->tx_write)
|
||||
c->tx_write->next = o;
|
||||
else
|
||||
c->tx_buf = o;
|
||||
o->next = NULL;
|
||||
o->wpos = o->outpos = o->buf;
|
||||
o->end = o->buf + CLI_TX_BUF_SIZE;
|
||||
}
|
||||
c->tx_write = o;
|
||||
if (!c->tx_pos)
|
||||
c->tx_pos = o;
|
||||
byte buf[64];
|
||||
int n = bsprintf(buf, "<%d messages lost>\n", c->ring_overflow);
|
||||
c->ring_overflow = 0;
|
||||
memcpy(cli_alloc_out(c, n), buf, n);
|
||||
}
|
||||
memcpy(o->wpos, buf, size);
|
||||
o->wpos += size;
|
||||
p = c->ring_read;
|
||||
while (*p)
|
||||
{
|
||||
cnt++;
|
||||
p++;
|
||||
if (p == c->ring_end)
|
||||
p = c->ring_buf;
|
||||
ASSERT(p != c->ring_write);
|
||||
}
|
||||
c->async_msg_size += cnt;
|
||||
q = cli_alloc_out(c, cnt);
|
||||
*q++ = '+';
|
||||
p = c->ring_read;
|
||||
do
|
||||
{
|
||||
*q = *p++;
|
||||
if (p == c->ring_end)
|
||||
p = c->ring_buf;
|
||||
}
|
||||
while (*q++);
|
||||
c->ring_read = p;
|
||||
q[-1] = '\n';
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -83,7 +127,7 @@ cli_free_out(cli *c)
|
||||
|
||||
if (o = c->tx_buf)
|
||||
{
|
||||
c->tx_write = NULL;
|
||||
c->tx_write = c->tx_pos = NULL;
|
||||
o->wpos = o->outpos = o->buf;
|
||||
while (p = o->next)
|
||||
{
|
||||
@@ -91,6 +135,7 @@ cli_free_out(cli *c)
|
||||
mb_free(p);
|
||||
}
|
||||
}
|
||||
c->async_msg_size = 0;
|
||||
}
|
||||
|
||||
static byte *cli_rh_pos;
|
||||
@@ -140,6 +185,10 @@ cli_event(void *data)
|
||||
cli *c = data;
|
||||
int err;
|
||||
|
||||
while (c->ring_read != c->ring_write &&
|
||||
c->async_msg_size < CLI_MAX_ASYNC_QUEUE)
|
||||
cli_copy_message(c);
|
||||
|
||||
if (c->tx_pos)
|
||||
;
|
||||
else if (c->cont)
|
||||
@@ -168,16 +217,15 @@ cli_new(void *priv)
|
||||
pool *p = rp_new(cli_pool, "CLI");
|
||||
cli *c = mb_alloc(p, sizeof(cli));
|
||||
|
||||
bzero(c, sizeof(cli));
|
||||
c->pool = p;
|
||||
c->priv = priv;
|
||||
c->event = ev_new(p);
|
||||
c->event->hook = cli_event;
|
||||
c->event->data = c;
|
||||
c->tx_buf = c->tx_pos = c->tx_write = NULL;
|
||||
c->cont = cli_hello;
|
||||
c->cleanup = NULL;
|
||||
c->last_reply = 0;
|
||||
c->parser_pool = lp_new(c->pool, 4096);
|
||||
c->rx_buf = mb_alloc(c->pool, CLI_RX_BUF_SIZE);
|
||||
ev_schedule(c->event);
|
||||
return c;
|
||||
}
|
||||
@@ -196,9 +244,80 @@ cli_written(cli *c)
|
||||
ev_schedule(c->event);
|
||||
}
|
||||
|
||||
static list cli_log_hooks;
|
||||
static int cli_log_inited;
|
||||
|
||||
void
|
||||
cli_set_log_echo(cli *c, unsigned int mask, unsigned int size)
|
||||
{
|
||||
if (c->ring_buf)
|
||||
{
|
||||
mb_free(c->ring_buf);
|
||||
c->ring_buf = c->ring_end = c->ring_read = c->ring_write = NULL;
|
||||
rem_node(&c->n);
|
||||
}
|
||||
c->log_mask = mask;
|
||||
if (mask && size)
|
||||
{
|
||||
c->ring_buf = mb_alloc(c->pool, size);
|
||||
c->ring_end = c->ring_buf + size;
|
||||
c->ring_read = c->ring_write = c->ring_buf;
|
||||
add_tail(&cli_log_hooks, &c->n);
|
||||
c->log_threshold = size / 8;
|
||||
}
|
||||
c->ring_overflow = 0;
|
||||
}
|
||||
|
||||
void
|
||||
cli_echo(unsigned int class, byte *msg)
|
||||
{
|
||||
unsigned len, free, i, l;
|
||||
cli *c;
|
||||
byte *m;
|
||||
|
||||
if (!cli_log_inited || EMPTY_LIST(cli_log_hooks))
|
||||
return;
|
||||
len = strlen(msg) + 1;
|
||||
WALK_LIST(c, cli_log_hooks)
|
||||
{
|
||||
if (!(c->log_mask & (1 << class)))
|
||||
continue;
|
||||
if (c->ring_read <= c->ring_write)
|
||||
free = (c->ring_end - c->ring_buf) - (c->ring_write - c->ring_read + 1);
|
||||
else
|
||||
free = c->ring_read - c->ring_write - 1;
|
||||
if (len > free ||
|
||||
free < c->log_threshold && class < (unsigned) L_INFO[0])
|
||||
{
|
||||
c->ring_overflow++;
|
||||
continue;
|
||||
}
|
||||
if (c->ring_read == c->ring_write)
|
||||
ev_schedule(c->event);
|
||||
m = msg;
|
||||
l = len;
|
||||
while (l)
|
||||
{
|
||||
if (c->ring_read <= c->ring_write)
|
||||
i = c->ring_end - c->ring_write;
|
||||
else
|
||||
i = c->ring_read - c->ring_write;
|
||||
if (i > l)
|
||||
i = l;
|
||||
memcpy(c->ring_write, m, i);
|
||||
m += i;
|
||||
l -= i;
|
||||
c->ring_write += i;
|
||||
if (c->ring_write == c->ring_end)
|
||||
c->ring_write = c->ring_buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cli_free(cli *c)
|
||||
{
|
||||
cli_set_log_echo(c, 0, 0);
|
||||
if (c->cleanup)
|
||||
c->cleanup(c);
|
||||
rfree(c->pool);
|
||||
@@ -208,4 +327,6 @@ void
|
||||
cli_init(void)
|
||||
{
|
||||
cli_pool = rp_new(&root_pool, "CLI");
|
||||
init_list(&cli_log_hooks);
|
||||
cli_log_inited = 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user