0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-08 12:18:42 +00:00

client.c: show memory somehow works in cbor, bird command prompt for cbor has little bugs

This commit is contained in:
Katerina Kubecova 2023-12-20 16:17:12 +01:00
parent 401ff80ed6
commit 0d74089e9a
11 changed files with 294 additions and 40 deletions

View File

@ -20,6 +20,7 @@
#include "lib/string.h"
#include "client/client.h"
static int input_hidden_end;
static int prompt_active;

View File

@ -22,6 +22,7 @@
#include "client/client.h"
#include "sysdep/unix/unix.h"
#define INPUT_BUF_LEN 2048
struct termios tty_save;
@ -63,6 +64,7 @@ lastnb(char *str, int i)
void
input_read(void)
{
printf("input read ok");
char buf[INPUT_BUF_LEN];
if ((fgets(buf, INPUT_BUF_LEN, stdin) == NULL) || (buf[0] == 0))
@ -97,6 +99,7 @@ input_read(void)
submit_command(buf);
}
static struct termios stored_tty;
static int more_active = 0;

View File

@ -34,17 +34,17 @@
#include "lib/resource.h"
#include "lib/string.h"
#include "client/client.h"
#include "client/print_cbor.c"
#include "sysdep/unix/unix.h"
#define SERVER_READ_BUF_LEN 4096
static char *opt_list = "s:vrlY";
static char *opt_list = "s:vrl";
static int verbose, restricted, once;
static char *init_cmd;
static char *server_path = PATH_CONTROL_SOCKET;
static char *server_path_yi = "bird-yang.ctl";
static int server_fd;
static byte server_read_buf[SERVER_READ_BUF_LEN];
static byte *server_read_pos = server_read_buf;
@ -53,7 +53,7 @@ int init = 1; /* During intial sequence */
int busy = 1; /* Executing BIRD command */
int interactive; /* Whether stdin is terminal */
int last_code; /* Last return code */
int yi_mode; /* Convert to cbor and push to yi socket (and convert answer back) */
int cbor_mode; /* Convert to cbor and push to yi socket (and convert answer back) */
static int num_lines, skip_input;
int term_lns, term_cls;
@ -64,7 +64,7 @@ int term_lns, term_cls;
static void
usage(char *name)
{
fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r] [-l] [-Y]\n", name);
fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r] [-l]\n", name);
exit(1);
}
@ -73,7 +73,6 @@ parse_args(int argc, char **argv)
{
int server_changed = 0;
int c;
yi_mode = 0;
while ((c = getopt(argc, argv, opt_list)) >= 0)
switch (c)
@ -92,17 +91,9 @@ parse_args(int argc, char **argv)
if (!server_changed)
server_path = xbasename(server_path);
break;
case 'Y':
yi_mode = 1;
if (!server_changed)
server_path = xbasename(server_path_yi);
break;
default:
usage(argv[0]);
}
yi_mode = 1;
server_path = server_path_yi; //TODO delete - only for testing purposes
fprintf(stderr, "Socket: %s \n", server_path_yi);
/* If some arguments are not options, we take it as commands */
if (optind < argc)
@ -149,17 +140,90 @@ handle_internal_command(char *cmd)
return 0;
}
uint compare_string(byte *str1, uint length, const char *str2) {
if (length < strlen(str2)) {
return 0;
}
for (size_t i = 0; i < strlen(str2); i++) {
if (str1[i]!=str2[i]) {
return 0;
}
}
return 1;
}
void
make_cmd_cbor(char *cmd_buffer)
{
printf("input got line yi\n%s\n", cmd_buffer);
size_t l = strlen(cmd_buffer);
char cbor_buf[l*10];
struct linpool *lp = lp_new(&root_pool);
struct cbor_writer *w = cbor_init(cbor_buf, l*10, lp);
cbor_open_block_with_length(w, 1);
printf("main block opened");
cbor_add_string(w, "command:do");
cbor_open_block(w);
char *show = "show ";
int buf_pt = 0;
if (compare_string(cmd_buffer, l, show))
{
printf("show recognised\n");
buf_pt += strlen(show);
l -= strlen(show);
if (compare_string(&cmd_buffer[buf_pt], l, "memory"))
{
printf("show memory...\n");
cbor_string_int(w, "command", SHOW_MEMORY);
cbor_close_block_or_list(w);
lp_flush(lp);
server_send(cbor_buf);
return;
}
else if (compare_string(&cmd_buffer[buf_pt], l, "status"))
{
cbor_string_int(w, "command", SHOW_STATUS);
cbor_close_block_or_list(w);
lp_flush(lp);
server_send(cbor_buf);
return;
}
else if (compare_string(&cmd_buffer[buf_pt], l, "symbols"))
{
cbor_string_int(w, "command", SHOW_SYMBOLS);
cbor_close_block_or_list(w);
lp_flush(lp);
server_send(cbor_buf);
}
else if (compare_string(&cmd_buffer[buf_pt], l, "ospf"))
{
cbor_string_int(w, "command", SHOW_OSPF);
}
else
{
printf("this command is not implemented yet");
}
}
lp_flush(lp);
printf("this command is not implemented yet");
}
static void
submit_server_command(char *cmd)
{
/*
printf("command %s\n", cmd);
if (cbor_mode)
TODO: make the server command actually cbor;
*/
{
make_cmd_cbor(cmd);
return;
}
busy = 1;
num_lines = 2;
fprintf(stderr, "Socket: %s \n", server_path_yi);
fprintf(stderr, "cmd: %s \n", cmd);
server_send(cmd);
}
@ -193,6 +257,7 @@ submit_command(char *cmd_raw)
free(cmd);
}
static void
init_commands(void)
{
@ -281,7 +346,7 @@ server_connect(void)
DIE("Unable to connect to server control socket (%s)", server_path);
if (fcntl(server_fd, F_SETFL, O_NONBLOCK) < 0)
DIE("fcntl");
fprintf(stdout, "Socket: %s connected ok\n", server_path_yi);
fprintf(stdout, "Socket: %s connected ok\n", server_path);
}
@ -292,6 +357,7 @@ server_got_reply(char *x)
{
int code;
int len = 0;
fprintf(stdout, "got reply<%s>", x);
if (*x == '+') /* Async reply */
PRINTF(len, ">>> %s\n", x+1);
@ -324,9 +390,35 @@ server_got_reply(char *x)
}
}
void
server_got_binary(int c)
{
// TODO check cbor hello
if (cbor_mode == 0)
{
byte expected[] = {0x87, 0x42, 0x49, 0x52, 0x44, 0x0D, 0x0A, 0x1A, 0x0A, 0x01};
if (c < 10)
die("too short header");
for (int i = 0; i < 9; i++)
{
if (server_read_buf[i] != expected[i])
die("wrong header");
}
if (server_read_buf[9] != expected[9])
die("unknown version of binary communication");
cbor_mode = 1;
}
else {
print_cbor_response(server_read_buf, c);
}
busy = 0;
skip_input = 0;
}
static void
server_read(void)
{
printf("server read\n");
int c;
byte *start, *p;
@ -469,6 +561,7 @@ main(int argc, char **argv)
interactive = isatty(0);
parse_args(argc, argv);
cmd_build_tree();
resource_init();
server_connect();
select_loop();
return 0;

78
client/print_cbor.c Normal file
View File

@ -0,0 +1,78 @@
#include "nest/cbor_parse.c"
void print_with_size(byte *string, int len)
{
for (int i = 0; i < len; i++)
{
if (string[i] != '_')
putc(string[i], stdout);
else
putc(' ', stdout);
}
}
void print_show_memory(struct buff_reader *buf_read)
{
printf("BIRD memory usage\n");
printf(" Effective Overhead\n");
struct value val = get_value(buf_read);
ASSERT(val.major == BLOCK);
val = get_value(buf_read); // header, may be it should be deleted
ASSERT(val.major == TEXT);
buf_read->pt+=val.val;
val = get_value(buf_read);
ASSERT(val.major == TEXT);
buf_read->pt+=val.val;
val = get_value(buf_read); // body
ASSERT(val.major == TEXT);
buf_read->pt+=val.val;
val = get_value(buf_read);
ASSERT(val.major == BLOCK);
val = get_value(buf_read);
while (val.major == TEXT && buf_read->pt < buf_read->size)
{
print_with_size(&buf_read->buff[buf_read->pt], val.val);
for (unsigned long i = 0; i < strlen(" ") - val.val; i++)
{
putc(' ', stdout);
}
buf_read->pt+=val.val;
val = get_value(buf_read); // block open
val = get_value(buf_read);
ASSERT(val.major == TEXT);
buf_read->pt+=val.val;
val = get_value(buf_read);
ASSERT(val.major == UINT);
printf("%7li B ", val.val);
val = get_value(buf_read);
ASSERT(val.major == TEXT);
buf_read->pt+=val.val;
val = get_value(buf_read);
ASSERT(val.major == UINT);
printf("%7li B\n", val.val);
val = get_value(buf_read);
}
}
void print_cbor_response(byte *cbor, int len)
{
struct buff_reader buf_read;
buf_read.buff = cbor;
buf_read.size = len;
buf_read.pt = 0;
struct value val = get_value(&buf_read);
printf("%i %li\n", val.major, val.val);
ASSERT(val.major == BLOCK);
ASSERT(val.val <=1);
val = get_value(&buf_read);
ASSERT(val.major == TEXT);
if (compare_buff_str(&buf_read, val.val, "show_memory:message"))
{
buf_read.pt += val.val;
print_show_memory(&buf_read);
}
}

View File

@ -9,7 +9,7 @@ struct cbor_writer {
struct linpool *lp;
};
void write_item(struct cbor_writer *writer, int8_t major, u64 num);
void write_item(struct cbor_writer *writer, uint8_t major, u64 num);
void check_memory(struct cbor_writer *writer, int add_size);
@ -147,8 +147,9 @@ void cbor_nonterminated_string(struct cbor_writer *writer, const char *string, u
writer->pt+=length;
}
void write_item(struct cbor_writer *writer, int8_t major, u64 num)
void write_item(struct cbor_writer *writer, uint8_t major, u64 num)
{
//log("write major %i %li", major, num);
major = major<<5;
check_memory(writer, 10);
if (num > ((u64)1<<(4*8))-1)
@ -200,6 +201,7 @@ void write_item(struct cbor_writer *writer, int8_t major, u64 num)
writer->pt++;
return;
}
//log("write item major %i num %i writer->pt %i writer->capacity %i writer %i", major, num, writer->pt, writer->capacity, writer);
major += num; // we can store the num as additional value
writer->cbor[writer->pt] = major;
writer->pt++;

View File

@ -35,6 +35,7 @@ cmd_show_memory_cbor(byte *tbuf, uint capacity, struct linpool *lp)
{
log("in cmd_show_memory_cbor");
struct cbor_writer *w = cbor_init(tbuf, capacity, lp);
log("w->pt %i w->cbor %i", w->pt, w->cbor);
cbor_open_block_with_length(w, 1);
cbor_add_string(w, "show_memory:message");
@ -67,6 +68,7 @@ cmd_show_memory_cbor(byte *tbuf, uint capacity, struct linpool *lp)
cbor_close_block_or_list(w); // we do not know for sure, that standby memory will be printed, so we do not know number of block items. If we know that, we open the block for 6 (or 5) items and we do not close anything
cbor_write_to_file(w, "show_memory.cbor");
log("show memory written");
return w->pt;
}

View File

@ -49,8 +49,6 @@ get_value(struct buff_reader *reader)
struct value val;
byte *buff = reader->buff;
val.major = buff[reader->pt]>>5;
log("in get value are zou here?");
log("major is %x", val.major);
int first_byte_val = buff[reader->pt] - (val.major<<5);
if (first_byte_val <=23) {
val.val = first_byte_val;
@ -61,19 +59,29 @@ get_value(struct buff_reader *reader)
reader->pt+=2;
} else if (first_byte_val == 0x19)
{
val.val = buff[reader->pt+1]>>8 + buff[reader->pt+2];
reader->pt+=3;
val.val = buff[reader->pt+1];
val.val = val.val << 8;
val.val += buff[reader->pt+2];
reader->pt += 3;
} else if (first_byte_val == 0x1a)
{
val.val = buff[reader->pt+1]>>24 + buff[reader->pt+2]>>16 + buff[reader->pt+3]>>8 + buff[reader->pt+4];
val.val = 0;
for (int i = 1; i < 4; i++)
{
val.val += buff[reader->pt+i];
val.val = val.val << 8;
}
val.val += buff[reader->pt+4];
reader->pt+=5;
} else if (first_byte_val == 0x1b)
{
for(int i = 1; i<=8; i++) {
val.val += buff[reader->pt+i]>>(64-(i*8));
for(int i = 1; i < 8; i++) {
val.val += buff[reader->pt+i];
val.val = val.val << 8;
}
val.val += buff[reader->pt+8];
reader->pt+=9;
} else if (first_byte_val == 0xff)
} else if (first_byte_val == 0x1f)
{
val.val = -1;
reader->pt++;
@ -109,12 +117,13 @@ void skip_optional_args(struct buff_reader *rbuf_read, int items_in_block)
}
} else
{
log("items in block %i", items_in_block);
ASSERT(items_in_block == -1); // assert the block was not open to exact num of items, because it cant be just for command (we would returned) and we did not find more items.
rbuf_read->pt--; // we read one byte from future, we need to shift pointer back. The val should be break, but we are not going to close the block, because it was not opened here.
}
}
struct arg_list *parse_args(struct buff_reader *rbuf_read, int items_in_block, struct linpool *lp)
struct arg_list *parse_arguments(struct buff_reader *rbuf_read, int items_in_block, struct linpool *lp)
{
// We are in opened block, which could be empty or contain arguments <"args":[{"arg":"string"}]>
struct arg_list *arguments = (struct arg_list*)lp_alloc(lp, sizeof(struct arg_list));
@ -213,10 +222,10 @@ do_command(struct buff_reader *rbuf_read, struct buff_reader *tbuf_read, int ite
skip_optional_args(rbuf_read, items_in_block);
return cmd_show_status_cbor(tbuf_read->buff, tbuf_read->size, lp);
case SHOW_SYMBOLS:
args = parse_args(rbuf_read, items_in_block, lp);
args = parse_arguments(rbuf_read, items_in_block, lp);
return cmd_show_symbols_cbor(tbuf_read->buff, tbuf_read->size, args, lp);
case SHOW_OSPF:
args = parse_args(rbuf_read, items_in_block, lp);
args = parse_arguments(rbuf_read, items_in_block, lp);
log("args %i, pt %i", args, args->pt);
return cmd_show_ospf_cbor(tbuf_read->buff, tbuf_read->size, args, lp);
return 0;
@ -229,7 +238,7 @@ do_command(struct buff_reader *rbuf_read, struct buff_reader *tbuf_read, int ite
uint
parse_cbor(uint size, byte *rbuf, byte *tbuf, uint tbsize, struct linpool* lp)
{
log("cbor parse");
log("cbor parse, tb size %i tb %i", tbsize, tbuf);
struct buff_reader rbuf_read;
struct buff_reader tbuf_read;
rbuf_read.buff = rbuf;
@ -263,7 +272,8 @@ parse_cbor(uint size, byte *rbuf, byte *tbuf, uint tbsize, struct linpool* lp)
val = get_value(&rbuf_read);
ASSERT(val.major == TEXT);
items_in_block--;
if (items_in_block!=-1)
items_in_block--;
ASSERT(compare_buff_str(&rbuf_read, val.val, "command"));
rbuf_read.pt+=val.val;
@ -275,6 +285,8 @@ parse_cbor(uint size, byte *rbuf, byte *tbuf, uint tbsize, struct linpool* lp)
}
}
}
lp_flush(lp);
log("parsed");
return tbuf_read.pt;
}

View File

@ -54,13 +54,13 @@ void cbor_add_net(struct cbor_writer *writer, const net_addr *N) {
switch (n->n.type)
{
case NET_IP4:
cbor_add_ipv4_prefix(writer, n->ip4.prefix.addr, n->ip4.pxlen);
cbor_add_ipv4_prefix(writer, n->ip4.prefix, n->ip4.pxlen);
return;
case NET_IP6:
cbor_add_ipv6_prefix(writer, n->ip6.prefix, n->ip6.pxlen);
return;
case NET_VPN4:
cbor_add_ipv4_prefix(writer, n->vpn4.prefix.addr, n->vpn4.pxlen);
cbor_add_ipv4_prefix(writer, n->vpn4.prefix, n->vpn4.pxlen);
return;
case NET_VPN6:
cbor_add_ipv6_prefix(writer, n->vpn6.prefix, n->vpn6.pxlen);

View File

@ -233,6 +233,37 @@ cli_written(cli *c)
ev_schedule(c->event);
}
int
yi_hello_message(byte *buff)
{
// 0x87: the high bit set to detect 8-bit faults
// BIRD: signature
// 0x0D0A1A0A: detect line ending conversions (see PNG)
// 0x01: version of the protocol (1 = CBOR based on YANG)
byte b[] = {0x87, 0x42, 0x49, 0x52, 0x44, 0x0D, 0x0A, 0x1A, 0x0A, 0x01};
memcpy(buff, b, 10);
return 10;
}
static void
yi_hello(cli *c)
{
log("yi hello");
sock *s = c->priv;
int len = yi_hello_message(s->tbuf);
if (sk_send(s, len) <= 0)
{
log("yi send hello failed");
return;
}
c->cont = NULL;
cli_free_out(c);
log("yi hello ok");
}
static byte *cli_rh_pos;
static uint cli_rh_len;
@ -309,6 +340,14 @@ cli_event(void *data)
cli_write_trigger(c);
}
static void
yi_event(void *data)
{
cli *c = data;
if (c->cont)
c->cont(c);
}
cli *
cli_new(void *priv)
{
@ -329,6 +368,26 @@ cli_new(void *priv)
return c;
}
cli *
new_cli_yi(void *priv)
{
pool *p = rp_new(cli_pool, "YI");
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 = yi_event;
c->event->data = c;
c->cont = yi_hello;
c->parser_pool = lp_new_default(c->pool);
c->show_pool = lp_new_default(c->pool);
c->rx_buf = mb_alloc(c->pool, CLI_RX_BUF_SIZE);
ev_schedule(c->event);
return c;
}
void
cli_kick(cli *c)
{
@ -338,6 +397,7 @@ cli_kick(cli *c)
uint
yi_process(uint size, byte *rbuf, byte *tbuf, uint tbsize) {
log("capacity %i buffer %i", tbsize, tbuf);
return parse_cbor(size, rbuf, tbuf, tbsize, lp_new(yi_pool));
}

View File

@ -65,6 +65,7 @@ static inline void cli_separator(cli *c)
/* Functions provided to sysdep layer */
cli *cli_new(void *);
cli *new_cli_yi(void *);
void cli_init(void);
void yi_init(void);
void cli_free(cli *);

View File

@ -490,9 +490,10 @@ yi_rx(sock *s, uint size)
/* zpracuj data délky len začínající na s->rbuf */
/* zapiš výsledek do s->tbuf */
log("in yi rx!");
log("size tbuf %ui", s->tbsize);
log("size tbuf %ui %i", s->tbsize, s->tbuf);
uint tx_len = yi_process(size, s->rbuf, s->tbuf, s->tbsize);
sk_send(s, tx_len);
log("sended");
return 1;
}
@ -553,12 +554,12 @@ yi_connect(sock *s, uint size UNUSED)
s->rx_hook = yi_rx;
s->tx_hook = cli_tx;
s->err_hook = cli_err;
s->data = c = cli_new(s);
s->data = c = new_cli_yi(s);
s->pool = c->pool;
s->fast_rx = 1;
c->rx_pos = c->rx_buf;
rmove(s, c->pool);
log("connect ok");
log("connect ok, tb %i", s->tbuf);
return 1;
}
@ -595,6 +596,7 @@ yi_init_unix(uid_t use_uid, gid_t use_gid)
write_ptr = fopen("out.cbor", "wb");
fwrite("", 0, 1, write_ptr);
fclose(write_ptr);
log("yi inited, tbuf %i", s->tbuf);
}
@ -989,13 +991,13 @@ main(int argc, char **argv)
if (!parse_and_exit)
{
test_old_bird(path_control_socket);
cli_init_unix(use_uid, use_gid);
//cli_init_unix(use_uid, use_gid);
if (path_control_socket_yi)
{
yi_init_unix(use_uid, use_gid);
}
else { //todo delete
path_control_socket_yi = "bird-yang.ctl";
path_control_socket_yi = "bird.ctl";
log(L_INFO "before function");
yi_init_unix(use_uid, use_gid);
}