Fixes bug in CLI TX buffer management.

This commit is contained in:
Ondrej Zajicek 2009-07-14 14:18:54 +02:00
parent 70670bf317
commit 6baef17ecf
3 changed files with 55 additions and 30 deletions

View file

@ -47,6 +47,20 @@
* The @this_cli variable points to a &cli structure of the session being * The @this_cli variable points to a &cli structure of the session being
* currently parsed, but it's of course available only in command handlers * currently parsed, but it's of course available only in command handlers
* not entered using the @cont hook. * not entered using the @cont hook.
*
* TX buffer management works as follows: At cli.tx_buf there is a
* list of TX buffers (struct cli_out), cli.tx_write is the buffer
* currently used by the producer (cli_printf(), cli_alloc_out()) and
* cli.tx_pos is the buffer currently used by the consumer
* (cli_write(), in system dependent code). The producer uses
* cli_out.wpos ptr as the current write position and the consumer
* uses cli_out.outpos ptr as the current read position. When the
* producer produces something, it calls cli_write_trigger(). If there
* is not enough space in the current buffer, the producer allocates
* the new one. When the consumer processes everything in the buffer
* queue, it calls cli_written(), tha frees all buffers (except the
* first one) and schedules cli.event .
*
*/ */
#include "nest/bird.h" #include "nest/bird.h"
@ -196,6 +210,14 @@ cli_free_out(cli *c)
c->async_msg_size = 0; c->async_msg_size = 0;
} }
void
cli_written(cli *c)
{
cli_free_out(c);
ev_schedule(c->event);
}
static byte *cli_rh_pos; static byte *cli_rh_pos;
static unsigned int cli_rh_len; static unsigned int cli_rh_len;
static int cli_rh_trick_flag; static int cli_rh_trick_flag;
@ -263,11 +285,8 @@ cli_event(void *data)
else else
cli_command(c); cli_command(c);
} }
if (cli_write(c))
{ cli_write_trigger(c);
cli_free_out(c);
ev_schedule(c->event);
}
} }
cli * cli *
@ -296,13 +315,6 @@ cli_kick(cli *c)
ev_schedule(c->event); ev_schedule(c->event);
} }
void
cli_written(cli *c)
{
cli_free_out(c);
ev_schedule(c->event);
}
static list cli_log_hooks; static list cli_log_hooks;
static int cli_log_inited; static int cli_log_inited;

View file

@ -62,7 +62,7 @@ void cli_echo(unsigned int class, byte *msg);
/* Functions provided by sysdep layer */ /* Functions provided by sysdep layer */
int cli_write(cli *); void cli_write_trigger(cli *);
int cli_get_command(cli *); int cli_get_command(cli *);
#endif #endif

View file

@ -178,22 +178,44 @@ cmd_reconfig(char *name, int type)
static sock *cli_sk; static sock *cli_sk;
static char *path_control_socket = PATH_CONTROL_SOCKET; static char *path_control_socket = PATH_CONTROL_SOCKET;
int
static void
cli_write(cli *c) cli_write(cli *c)
{ {
sock *s = c->priv; sock *s = c->priv;
if (c->tx_pos) while (c->tx_pos)
{ {
struct cli_out *o = c->tx_pos; struct cli_out *o = c->tx_pos;
int len = o->wpos - o->outpos;
s->tbuf = o->outpos; s->tbuf = o->outpos;
if (sk_send(s, o->wpos - o->outpos) > 0) o->outpos = o->wpos;
{
c->tx_pos = o->next; if (sk_send(s, len) <= 0)
ev_schedule(c->event); return;
}
c->tx_pos = o->next;
} }
return !c->tx_pos;
/* Everything is written */
s->tbuf = NULL;
cli_written(c);
}
void
cli_write_trigger(cli *c)
{
sock *s = c->priv;
if (s->tbuf == NULL)
cli_write(c);
}
static void
cli_tx(sock *s)
{
cli_write(s->data);
} }
int int
@ -232,15 +254,6 @@ cli_rx(sock *s, int size UNUSED)
return 0; return 0;
} }
static void
cli_tx(sock *s)
{
cli *c = s->data;
if (cli_write(c))
cli_written(c);
}
static void static void
cli_err(sock *s, int err) cli_err(sock *s, int err)
{ {