#include "lib/string.h"
#include "client/client.h"
+
static int input_hidden_end;
static int prompt_active;
#include "client/client.h"
#include "sysdep/unix/unix.h"
+
#define INPUT_BUF_LEN 2048
struct termios tty_save;
void
input_read(void)
{
+ printf("input read ok");
char buf[INPUT_BUF_LEN];
if ((fgets(buf, INPUT_BUF_LEN, stdin) == NULL) || (buf[0] == 0))
submit_command(buf);
}
+
static struct termios stored_tty;
static int more_active = 0;
#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;
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;
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);
}
{
int server_changed = 0;
int c;
- yi_mode = 0;
while ((c = getopt(argc, argv, opt_list)) >= 0)
switch (c)
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)
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);
}
free(cmd);
}
+
static void
init_commands(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);
}
{
int code;
int len = 0;
+ fprintf(stdout, "got reply<%s>", x);
if (*x == '+') /* Async reply */
PRINTF(len, ">>> %s\n", x+1);
}
}
+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;
interactive = isatty(0);
parse_args(argc, argv);
cmd_build_tree();
+ resource_init();
server_connect();
select_loop();
return 0;
--- /dev/null
+
+#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);
+ }
+}
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);
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)
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++;
{
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");
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;
}
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;
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++;
}
} 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));
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;
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;
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;
}
}
}
+ lp_flush(lp);
+ log("parsed");
return tbuf_read.pt;
}
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);
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;
cli_write_trigger(c);
}
+static void
+yi_event(void *data)
+{
+ cli *c = data;
+ if (c->cont)
+ c->cont(c);
+}
+
cli *
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)
{
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));
}
/* 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 *);
/* 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;
}
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;
}
write_ptr = fopen("out.cbor", "wb");
fwrite("", 0, 1, write_ptr);
fclose(write_ptr);
+ log("yi inited, tbuf %i", s->tbuf);
}
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);
}