From 0e3d70176cafb618236cf27e0250b9f03a5c3e72 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2019 22:22:23 +0100 Subject: [PATCH 1/2] bmx7: update to git snapshot as of 2018-12-29 consolidated commits from master branch: 25916fb bmx7: update to git snapshot as of 2018-12-29 (dfe8097 bmx7: Avoid namespace collision with libubox.) (43449bc treewide: Basic cleanup and alignment to package guidelines (#383)) 440ad46 bmx7: add config trigger Signed-off-by: Daniel Golle --- bmx7/Makefile | 13 +- ...e-list_add_tail-and-struct-list_head.patch | 461 ------------------ .../bmx6/usr/lib/lua/luci/model/bmx6json.lua | 1 + luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info | 11 +- .../resources/bmx6/js/bmx6-graph.js | 2 +- 5 files changed, 16 insertions(+), 472 deletions(-) delete mode 100644 bmx7/patches/100-rename-list_add_tail-and-struct-list_head.patch diff --git a/bmx7/Makefile b/bmx7/Makefile index 8f2a1ec..d9337e9 100644 --- a/bmx7/Makefile +++ b/bmx7/Makefile @@ -27,13 +27,12 @@ PKG_NAME:=bmx7 PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=git://github.com/bmx-routing/bmx7.git -#PKG_SOURCE_URL:=file:///usr/src/bmx-routing/bmx7.git +PKG_SOURCE_URL:=https://github.com/bmx-routing/bmx7.git -PKG_REV:=9883383dc26df16da67b9ef7ba99efe62f79c4e7 -PKG_MIRROR_HASH:=012178aba42016d3e0961715f99bf1e322c2c6c22b1cc6635375468360cb4d68 -PKG_VERSION:=r2018042501 -PKG_RELEASE:=3 +PKG_REV:=7711e1f12b29e668f3090b5b94b783f4470a31ce +PKG_MIRROR_HASH:=6269b210679fa391f92dfc66d2b629038f51201c93bb279fa55cd608c4f90827 +PKG_VERSION:=r2018122901 +PKG_RELEASE:=1 PKG_LICENSE:=GPL-2.0 PKG_SOURCE_VERSION:=$(PKG_REV) @@ -45,7 +44,7 @@ include $(INCLUDE_DIR)/package.mk TARGET_CFLAGS += $(FPIC) -MAKE_ARGS += EXTRA_CFLAGS="$(TARGET_CFLAGS) -I. -I$(STAGING_DIR)/usr/include -DCRYPTLIB=MBEDTLS_2_4_0 -DCORE_LIMIT=20000 -DTRAFFIC_DUMP -DNO_TRACE_FUNCTION_CALLS -DBMX7_LIB_IWINFO" +MAKE_ARGS += EXTRA_CFLAGS="$(TARGET_CFLAGS) -I. -I$(STAGING_DIR)/usr/include -DCRYPTLIB=MBEDTLS_2_8_0 -DCORE_LIMIT=20000 -DTRAFFIC_DUMP -DNO_TRACE_FUNCTION_CALLS -DBMX7_LIB_IWINFO" MAKE_ARGS += \ EXTRA_LDFLAGS="$(TARGET_LDFLAGS) -L$(STAGING_DIR)/usr/lib -liwinfo" \ diff --git a/bmx7/patches/100-rename-list_add_tail-and-struct-list_head.patch b/bmx7/patches/100-rename-list_add_tail-and-struct-list_head.patch deleted file mode 100644 index ffb4584..0000000 --- a/bmx7/patches/100-rename-list_add_tail-and-struct-list_head.patch +++ /dev/null @@ -1,461 +0,0 @@ -From 53f5a6ef74acff4c7294f4346a3d88fa04ad49c9 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Tue, 14 Aug 2018 12:19:49 +0200 -Subject: [PATCH] rename list_add_tail and struct list_head - -Rename some list stuff to avoid namespace collision with libubox ---- - control.c | 18 +++++++++--------- - control.h | 12 ++++++------ - lib/bmx7_tun/tun.c | 2 +- - list.c | 26 +++++++++++++------------- - list.h | 36 ++++++++++++++++++------------------ - msg.h | 2 +- - plugin.c | 8 ++++---- - plugin.h | 2 +- - schedule.c | 2 +- - tun.h | 2 +- - 10 files changed, 55 insertions(+), 55 deletions(-) - -diff --git a/control.c b/control.c -index ee9df30..9ab778d 100644 ---- a/control.c -+++ b/control.c -@@ -73,7 +73,7 @@ uint32_t My_pid = 0; - - LIST_SIMPEL(ctrl_list, struct ctrl_node, list, list); - --struct list_head dbgl_clients[DBGL_MAX + 1]; -+struct bmx_list_head dbgl_clients[DBGL_MAX + 1]; - static struct dbg_histogram dbgl_history[2][DBG_HIST_SIZE]; - - static uint8_t debug_system_active = NO; -@@ -136,7 +136,7 @@ void add_dbgl_node(struct ctrl_node *cn, int dbgl) - - dn->cn = cn; - cn->dbgl = dbgl; -- list_add_tail(&dbgl_clients[dbgl], &dn->list); -+ bmx_list_add_tail(&dbgl_clients[dbgl], &dn->list); - - if (dbgl == DBGL_SYS || dbgl == DBGL_CHANGES) { - dbgf_all(DBGT_INFO, "resetting muted dbg history"); -@@ -255,7 +255,7 @@ struct ctrl_node *create_ctrl_node(int fd, void (*cn_fd_handler) (struct ctrl_no - { - struct ctrl_node *cn = debugMallocReset(sizeof(struct ctrl_node), -300010); - -- list_add_tail(&ctrl_list, &cn->list); -+ bmx_list_add_tail(&ctrl_list, &cn->list); - - cn->fd = fd; - cn->cn_fd_handler = cn_fd_handler; -@@ -571,7 +571,7 @@ void debug_output(uint32_t check_len, struct ctrl_node *cn, int8_t dbgl, int8_t - if (level == DBGL_SYS && mute_dbgl_sys == DBG_HIST_MUTED) - continue; - -- list_for_each(list_pos, /*(struct list_head *)*/&(dbgl_clients[level])) -+ list_for_each(list_pos, /*(struct bmx_list_head *)*/&(dbgl_clients[level])) - { - - struct dbgl_node *dn = list_entry(list_pos, struct dbgl_node, list); -@@ -990,7 +990,7 @@ void register_option(struct opt_type *opt, const char * category_name) - - opt->d.parent_opt = tmp_opt; - -- list_add_tail(&tmp_opt->d.childs_type_list, &opt->d.list); -+ bmx_list_add_tail(&tmp_opt->d.childs_type_list, &opt->d.list); - - } else { - -@@ -1017,7 +1017,7 @@ void register_option(struct opt_type *opt, const char * category_name) - } - - if (!tmp_opt) -- list_add_tail(&opt_list, &opt->d.list); -+ bmx_list_add_tail(&opt_list, &opt->d.list); - - } - -@@ -1094,7 +1094,7 @@ struct opt_type *get_option(struct opt_type *parent_opt, uint8_t short_opt, char - - struct list_node *list_pos; - int32_t len = 0; -- struct list_head *list; -+ struct bmx_list_head *list; - struct opt_type *opt = NULL; - char *equalp = NULL; - char s[MAX_ARG_SIZE] = ""; -@@ -1305,7 +1305,7 @@ struct opt_child *add_opt_child(struct opt_type *opt, struct opt_parent *p) - - c->opt = opt; - c->parent_instance = p; -- list_add_tail(&p->childs_instance_list, &c->list); -+ bmx_list_add_tail(&p->childs_instance_list, &c->list); - - return c; - } -@@ -1347,7 +1347,7 @@ struct opt_parent *add_opt_parent(struct opt_type *opt) - - LIST_INIT_HEAD(p->childs_instance_list, struct opt_child, list, list); - -- list_add_tail(&opt->d.parents_instance_list, &p->list); -+ bmx_list_add_tail(&opt->d.parents_instance_list, &p->list); - - return p; - } -diff --git a/control.h b/control.h -index df0176f..4ef0854 100644 ---- a/control.h -+++ b/control.h -@@ -49,7 +49,7 @@ typedef uint32_t TIME_SEC_T; - - extern int unix_sock; - --extern struct list_head ctrl_list; -+extern struct bmx_list_head ctrl_list; - - extern int32_t Client_mode; - -@@ -115,7 +115,7 @@ struct ctrl_node { - int8_t dbgl; - }; - --extern struct list_head dbgl_clients[DBGL_MAX + 1]; -+extern struct bmx_list_head dbgl_clients[DBGL_MAX + 1]; - - struct dbgl_node { - struct list_node list; -@@ -227,7 +227,7 @@ struct ctrl_node *create_ctrl_node(int fd, void (*cn_fd_handler) (struct ctrl_no - - #define MAX_UNIX_MSG_SIZE 2000 - --extern struct list_head opt_list; -+extern struct bmx_list_head opt_list; - - - /* opt_t types: -@@ -292,7 +292,7 @@ struct opt_child { - struct opt_parent { - struct list_node list; - -- struct list_head childs_instance_list; -+ struct bmx_list_head childs_instance_list; - - char *val; //key - -@@ -311,9 +311,9 @@ struct opt_data { - - struct opt_type *parent_opt; //REMOVE THIS and use casting instead ! - -- struct list_head childs_type_list; //if this opt is a section type, then further sub-opts types can be listed here -+ struct bmx_list_head childs_type_list; //if this opt is a section type, then further sub-opts types can be listed here - -- struct list_head parents_instance_list; // -+ struct bmx_list_head parents_instance_list; // - }; - - struct opt_type { -diff --git a/lib/bmx7_tun/tun.c b/lib/bmx7_tun/tun.c -index 2aa740c..265c47a 100644 ---- a/lib/bmx7_tun/tun.c -+++ b/lib/bmx7_tun/tun.c -@@ -126,7 +126,7 @@ void set_tunXin6_net_adv_list_handl(uint8_t del, void **adv_list_ptr) - n = debugMallocReset(sizeof( struct tunXin6_net_adv_list_node), -300517); - - n->adv_list = adv_list; -- list_add_tail((&tunXin6_net_adv_list_list), &n->list); -+ bmx_list_add_tail((&tunXin6_net_adv_list_list), &n->list); - } - - STATIC_FUNC -diff --git a/list.c b/list.c -index 5e0665d..b698874 100644 ---- a/list.c -+++ b/list.c -@@ -39,7 +39,7 @@ - * @head: list head of maintained nodes - * @node: a node maintained in the list or NULL - */ --void * list_iterate(struct list_head *head, void *node) -+void * list_iterate(struct bmx_list_head *head, void *node) - { - struct list_node *ln = (node ? - ((struct list_node*) (((char*) node) + head->list_node_offset)) : -@@ -53,7 +53,7 @@ void * list_iterate(struct list_head *head, void *node) - return(((char*) ln->next) - head->list_node_offset); - } - --void *list_find_next(struct list_head *head, void* key, void *node) -+void *list_find_next(struct bmx_list_head *head, void* key, void *node) - { - while ((node = list_iterate(head, node))) { - -@@ -68,7 +68,7 @@ void *list_find_next(struct list_head *head, void* key, void *node) - * @head: list head to add it after - * @new: new entry to be added - */ --void list_add_head(struct list_head *head, struct list_node *new) -+void list_add_head(struct bmx_list_head *head, struct list_node *new) - { - - new->next = head->next; -@@ -82,12 +82,12 @@ void list_add_head(struct list_head *head, struct list_node *new) - } - - /** -- * list_add_tail - add a new entry -+ * bmx_list_add_tail - add a new entry - * @head: list head to add it before - * @new: new entry to be added - */ - --void list_add_tail(struct list_head *head, struct list_node *new) -+void bmx_list_add_tail(struct bmx_list_head *head, struct list_node *new) - { - new->next = (struct list_node *) head; - head->last->next = new; -@@ -96,7 +96,7 @@ void list_add_tail(struct list_head *head, struct list_node *new) - head->items++; - } - --void list_add_after(struct list_head *head, struct list_node *ln, struct list_node *new) -+void list_add_after(struct bmx_list_head *head, struct list_node *ln, struct list_node *new) - { - new->next = ln->next; - ln->next = new; -@@ -112,7 +112,7 @@ void list_add_after(struct list_head *head, struct list_node *ln, struct list_no - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ --void list_del_next(struct list_head *head, struct list_node *ln) -+void list_del_next(struct bmx_list_head *head, struct list_node *ln) - { - assertion(-502641, (ln->next != (struct list_node*) head)); - -@@ -126,7 +126,7 @@ void list_del_next(struct list_head *head, struct list_node *ln) - head->items--; - } - --void *list_del_head(struct list_head *head) -+void *list_del_head(struct bmx_list_head *head) - { - if (LIST_EMPTY(head)) - return NULL; -@@ -147,7 +147,7 @@ void *list_del_head(struct list_head *head) - */ - - /* UNTESTED --void * plist_iterate(struct list_head *head, struct plist_node **pln) -+void * plist_iterate(struct bmx_list_head *head, struct plist_node **pln) - { - - if (head->last == (struct list_node*) -@@ -169,17 +169,17 @@ static struct plist_node *plist_node_create(void *item) - return plh; - } - --void plist_add_head(struct list_head *head, void *item) -+void plist_add_head(struct bmx_list_head *head, void *item) - { - list_add_head(head, &((plist_node_create(item))->list)); - } - --void plist_add_tail(struct list_head *head, void *item) -+void plist_add_tail(struct bmx_list_head *head, void *item) - { -- list_add_tail(head, &((plist_node_create(item))->list)); -+ bmx_list_add_tail(head, &((plist_node_create(item))->list)); - } - --void * plist_del_head(struct list_head *head) -+void * plist_del_head(struct bmx_list_head *head) - { - struct plist_node *pln = list_del_head(head); - -diff --git a/list.h b/list.h -index d40306c..770dc9f 100644 ---- a/list.h -+++ b/list.h -@@ -28,7 +28,7 @@ - - - #ifndef _LIST_H --#define _LIST_H -+#define _LIST_H_ - - #include - -@@ -36,7 +36,7 @@ struct list_node { - struct list_node *next; - }; - --struct list_head { -+struct bmx_list_head { - struct list_node *next; - struct list_node *last; - uint16_t items; -@@ -52,7 +52,7 @@ struct plist_node { - - - --#define LIST_SIMPEL(ptr, element_type, list_field, key_field ) struct list_head ptr = { \ -+#define LIST_SIMPEL(ptr, element_type, list_field, key_field ) struct bmx_list_head ptr = { \ - .next = (struct list_node *)&ptr, \ - .last = (struct list_node *)&ptr, \ - .items = 0, \ -@@ -75,14 +75,14 @@ struct plist_node { - #define list_get_first(head) ((void*)((LIST_EMPTY(head)) ? NULL : (((char*) (head)->next) - (head)->list_node_offset) )) - #define list_get_last(head) ((void*)((LIST_EMPTY(head)) ? NULL : (((char*) (head)->last) - (head)->list_node_offset) )) - --void *list_iterate(struct list_head *head, void *node); --void *list_find_next(struct list_head *head, void* key, void *node); -+void *list_iterate(struct bmx_list_head *head, void *node); -+void *list_find_next(struct bmx_list_head *head, void* key, void *node); - --void list_add_head(struct list_head *head, struct list_node * new); --void list_add_tail(struct list_head *head, struct list_node * new); --void list_add_after(struct list_head *head, struct list_node *pos, struct list_node * new); --void list_del_next(struct list_head *head, struct list_node *pos); --void *list_del_head(struct list_head *head); -+void list_add_head(struct bmx_list_head *head, struct list_node * new); -+void bmx_list_add_tail(struct bmx_list_head *head, struct list_node * new); -+void list_add_after(struct bmx_list_head *head, struct list_node *pos, struct list_node * new); -+void list_del_next(struct bmx_list_head *head, struct list_node *pos); -+void *list_del_head(struct bmx_list_head *head); - - - #define plist_get_first(head) (LIST_EMPTY(head) ? NULL : \ -@@ -91,17 +91,17 @@ void *list_del_head(struct list_head *head); - #define plist_get_last(head) (LIST_EMPTY(head) ? NULL : \ - ((struct plist_node*)(((char*) (head)->prev) - (head)->list_node_offset))-item ) - --void * plist_iterate(struct list_head *head, struct plist_node **pln); -+void * plist_iterate(struct bmx_list_head *head, struct plist_node **pln); - --void plist_add_head(struct list_head *head, void *item); --void plist_add_tail(struct list_head *head, void *item); --void *plist_del_head(struct list_head *head); -+void plist_add_head(struct bmx_list_head *head, void *item); -+void plist_add_tail(struct bmx_list_head *head, void *item); -+void *plist_del_head(struct bmx_list_head *head); - - - - /** - * list_entry - get the struct for this entry -- * @ptr: the &struct list_head pointer. -+ * @ptr: the &struct bmx_list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -@@ -109,7 +109,7 @@ void *plist_del_head(struct list_head *head); - - /** - * list_for_each - iterate over a list -- * @pos: the &struct list_head to use as a loop counter. -+ * @pos: the &struct bmx_list_head to use as a loop counter. - * @head: the head for your list. - */ - #define list_for_each(pos, head) \ -@@ -123,8 +123,8 @@ void *plist_del_head(struct list_head *head); - - /** - * list_for_each_safe - iterate over a list safe against removal of list entry -- * @pos: the &struct list_head to use as a loop counter. -- * @n: another &struct list_head to use as temporary storage -+ * @pos: the &struct bmx_list_head to use as a loop counter. -+ * @n: another &struct bmx_list_head to use as temporary storage - * @head: the head for your list. - */ - #define list_for_each_safe(pos, n, head) \ -diff --git a/msg.h b/msg.h -index d36f6e2..b881cef 100644 ---- a/msg.h -+++ b/msg.h -@@ -357,7 +357,7 @@ struct tx_frame_iterator { - // MUST be initialized: - // remains unchanged: - const char *caller; -- struct list_head *tx_task_list; -+ struct bmx_list_head *tx_task_list; - struct tx_task_node *ttn; - // struct desc_contents *descContents; - struct frame_db *db; -diff --git a/plugin.c b/plugin.c -index 5016956..102cdba 100644 ---- a/plugin.c -+++ b/plugin.c -@@ -74,7 +74,7 @@ void _set_thread_hook(int32_t cb_type, void (*cb_handler) (void), int8_t del, st - cleanup_all(-500143); - } - -- list_for_each_safe(list_pos, tmp_pos, (struct list_head*) cb_list) -+ list_for_each_safe(list_pos, tmp_pos, (struct bmx_list_head*) cb_list) - { - cbn = list_entry(list_pos, struct cb_node, list); - -@@ -82,7 +82,7 @@ void _set_thread_hook(int32_t cb_type, void (*cb_handler) (void), int8_t del, st - - if (del) { - -- list_del_next(((struct list_head*) cb_list), prev_pos); -+ list_del_next(((struct bmx_list_head*) cb_list), prev_pos); - debugFree(cbn, -300069); - return; - -@@ -103,7 +103,7 @@ void _set_thread_hook(int32_t cb_type, void (*cb_handler) (void), int8_t del, st - - cbn->cb_type = cb_type; - cbn->cb_handler = cb_handler; -- list_add_tail(((struct list_head*) cb_list), &cbn->list); -+ bmx_list_add_tail(((struct bmx_list_head*) cb_list), &cbn->list); - - } - -@@ -261,7 +261,7 @@ int activate_plugin(struct plugin *p, void *dlhandle, const char *dl_name) - pn->plugin = p; - pn->dlhandle = dlhandle; - -- list_add_tail(&plugin_list, &pn->list); -+ bmx_list_add_tail(&plugin_list, &pn->list); - - dbgf_all(DBGT_INFO, "%s SUCCESS", pn->plugin->plugin_name); - -diff --git a/plugin.h b/plugin.h -index 5028d4e..b5c9727 100644 ---- a/plugin.h -+++ b/plugin.h -@@ -74,7 +74,7 @@ struct cb_fd_node { - void (*cb_fd_handler) (int32_t fd); - }; - --extern struct list_head cb_fd_list; -+extern struct bmx_list_head cb_fd_list; - // cb_fd_handler is called when fd received data - // called function may remove itself - void set_fd_hook(int32_t fd, void (*cb_fd_handler) (int32_t fd), int8_t del); -diff --git a/schedule.c b/schedule.c -index 8e3f7a6..8868b01 100644 ---- a/schedule.c -+++ b/schedule.c -@@ -205,7 +205,7 @@ void task_register(TIME_T timeout, void (* task) (void *), void *data, int32_t t - } - - if ((tmp_tn == NULL) || (U32_LE(tmp_tn->expire, tn->expire))) -- list_add_tail(&task_list, &tn->list); -+ bmx_list_add_tail(&task_list, &tn->list); - - } - -diff --git a/tun.h b/tun.h -index 06b8c6f..102ee87 100644 ---- a/tun.h -+++ b/tun.h -@@ -309,7 +309,7 @@ struct tunXin6_net_adv_list_node { - }; - - --extern struct list_head tunXin6_net_adv_list_list; -+extern struct bmx_list_head tunXin6_net_adv_list_list; - - struct tun_bit_key_nodes { - struct tun_search_node *tsn; diff --git a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/bmx6json.lua b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/bmx6json.lua index a4a8e43..a61362b 100644 --- a/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/bmx6json.lua +++ b/luci-app-bmx6/bmx6/usr/lib/lua/luci/model/bmx6json.lua @@ -59,6 +59,7 @@ function get(field, host) if json_url[1] == "http" then raw,err = wget(url..field,1000) + sys.exec("") else if json_url[1] == "exec" then diff --git a/luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info b/luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info index 9c615e4..ceebbbb 100755 --- a/luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info +++ b/luci-app-bmx6/bmx6/www/cgi-bin/bmx6-info @@ -43,7 +43,7 @@ print_query() { i=$(( $i + 1 )) done echo -n " ] }" - + # If /all has been specified, printing all the files together } || { comma="" @@ -77,7 +77,7 @@ if [ "$QUERY" == 'myself' ]; then echo -n "{\"myself\":{\"hostname\":\"$hostname\",\"ip6\":\"$ip6\",\"ip4\":\"$ip4\",\"net6\":\"$cidr6\",\"net4\":\"$cidr4\"}}" exit 0 fi - + if [ "$QUERY" == 'info' ]; then echo -n '{ "info": [ ' print_query status @@ -100,7 +100,12 @@ if [ "$QUERY" == 'neighbours' ]; then fi if [ "$QUERY" == 'tunnels' ]; then - bmx6 -c --jshow tunnels /r=0 + tunnels=$(bmx6 -c --jshow tunnels /r=0) + if [ -z $tunnels ]; then + echo '{ "tunnels" : [] }' + else + echo $tunnels + fi exit 0 fi diff --git a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/bmx6-graph.js b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/bmx6-graph.js index 80233ff..e3ff009 100644 --- a/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/bmx6-graph.js +++ b/luci-app-bmx6/bmx6/www/luci-static/resources/bmx6/js/bmx6-graph.js @@ -48,7 +48,7 @@ function init() { divwait = document.getElementById("wait"); - XHR.get('/cgi-bin/luci/status/bmx6/topology', null, function(nodesRequest, nodesData) { + XHR.get('/cgi-bin/luci/admin/network/BMX6/topology', null, function(nodesRequest, nodesData) { nodes = nodesData; XHR.get('/cgi-bin/bmx6-info?$myself&', null, function(myselfRequest, myselfData) { From 71f9aae5e4eb2ebf799384dcdd00915daceb94b9 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sat, 2 Mar 2019 22:30:16 +0100 Subject: [PATCH 2/2] luci-app-bmx7: update to v0.1-alpha consolidated commits from master branch: fce1287 luci-app-bmx7: show mDNS menu if available 3e259f8 luci-app-bmx7: fix bmx7-info script's "$info" call a7d7f4b luci-app-bmx7: fix bmx7-info script's indentation 9345df9 luci-app-bmx7: update version, dependencies and maintainer a1e1020 luci-app-bmx7: refactory, multiple fixes and add topology graph Signed-off-by: Daniel Golle --- luci-app-bmx7/Makefile | 6 +- .../usr/lib/lua/luci/controller/bmx7.lua | 38 +- .../view/admin_status/index/bmx7_nodes.htm | 40 ++ .../usr/lib/lua/luci/view/bmx7/nodes_j.htm | 76 +-- .../usr/lib/lua/luci/view/bmx7/status_j.htm | 198 +++--- .../usr/lib/lua/luci/view/bmx7/topology.htm | 54 ++ .../usr/lib/lua/luci/view/bmx7/tunnels_j.htm | 76 +++ luci-app-bmx7/files/www/cgi-bin/bmx7-info | 29 +- .../resources/bmx7/css/netjsongraph-theme.css | 59 ++ .../resources/bmx7/css/netjsongraph.css | 62 ++ .../resources/bmx7/js/netjsongraph.js | 568 ++++++++++++++++++ .../luci-static/resources/bmx7/js/polling.js | 40 +- 12 files changed, 1030 insertions(+), 216 deletions(-) create mode 100644 luci-app-bmx7/files/usr/lib/lua/luci/view/admin_status/index/bmx7_nodes.htm create mode 100644 luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/topology.htm create mode 100644 luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/tunnels_j.htm create mode 100644 luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph-theme.css create mode 100644 luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph.css create mode 100644 luci-app-bmx7/files/www/luci-static/resources/bmx7/js/netjsongraph.js diff --git a/luci-app-bmx7/Makefile b/luci-app-bmx7/Makefile index a9e96f7..dbd71c8 100644 --- a/luci-app-bmx7/Makefile +++ b/luci-app-bmx7/Makefile @@ -21,7 +21,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-bmx7 -PKG_RELEASE:=0.0-alpha +PKG_RELEASE:=0.1-alpha PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_LICENSE:=GPL-2.0+ @@ -33,8 +33,8 @@ define Package/luci-app-bmx7 CATEGORY:=LuCI SUBMENU:=3. Applications TITLE:= LuCI support for BMX7 - DEPENDS:=+luci-lib-json +luci-mod-admin-full +luci-lib-httpclient +bmx7 - MAINTAINER:= Roger Pueyo Centelles + DEPENDS:=+luci-lib-json +luci-mod-admin-full +bmx7 +bmx7-json + MAINTAINER:= Roger Pueyo and Pau Escrich endef define Package/luci-app-bmx7/description diff --git a/luci-app-bmx7/files/usr/lib/lua/luci/controller/bmx7.lua b/luci-app-bmx7/files/usr/lib/lua/luci/controller/bmx7.lua index ed62628..482fb5d 100644 --- a/luci-app-bmx7/files/usr/lib/lua/luci/controller/bmx7.lua +++ b/luci-app-bmx7/files/usr/lib/lua/luci/controller/bmx7.lua @@ -59,10 +59,28 @@ function index() entry(place,call("action_status_j"),"Status",0) table.remove(place) - -- Nodes list - table.insert(place,"Nodes") - entry(place,call("action_nodes_j"),"Nodes",1) + -- Topology + table.insert(place,"Topology") + entry(place,call("topology"),"Topology",1) table.remove(place) + + -- Nodes + table.insert(place,"Nodes") + entry(place,call("action_nodes_j"),"Nodes",2) + table.remove(place) + + -- Tunnels + table.insert(place,"Gateways") + entry(place,call("action_tunnels_j"),"Gateways",3) + table.remove(place) + + -- Integrate bmx7-mdns if present + if nixio.fs.stat("/usr/lib/lua/luci/model/cbi/bmx7-mdns.lua","type") ~= nil then + table.insert(place,"mDNS") + entry(place, cbi("bmx7-mdns"), "mesh DNS", 1).dependent=false + table.remove(place) + end + end @@ -70,8 +88,14 @@ function action_status_j() luci.template.render("bmx7/status_j", {}) end -function action_nodes_j() - local http = require "luci.http" - local link_non_js = "/cgi-bin/luci" .. http.getenv("PATH_INFO") .. '/nodes_nojs' - luci.template.render("bmx7/nodes_j", {link_non_js=link_non_js}) +function action_tunnels_j() + luci.template.render("bmx7/tunnels_j", {}) +end + +function topology() + luci.template.render("bmx7/topology", {}) +end + +function action_nodes_j() + luci.template.render("bmx7/nodes_j", {}) end diff --git a/luci-app-bmx7/files/usr/lib/lua/luci/view/admin_status/index/bmx7_nodes.htm b/luci-app-bmx7/files/usr/lib/lua/luci/view/admin_status/index/bmx7_nodes.htm new file mode 100644 index 0000000..8a6aefa --- /dev/null +++ b/luci-app-bmx7/files/usr/lib/lua/luci/view/admin_status/index/bmx7_nodes.htm @@ -0,0 +1,40 @@ +
+
+ <%:Bmx7 mesh nodes%> +
+
+
+
<%:Name%>
+
<%:Short ID%>
+
<%:S/s/T/t%>
+
<%:Primary IPv6%>
+
<%:Via Neighbour%>
+
<%:Device%>
+
<%:Metric%>
+
<%:Last Ref%>
+
+
+
+
+
+ + + diff --git a/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/nodes_j.htm b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/nodes_j.htm index 347af42..a631c93 100644 --- a/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/nodes_j.htm +++ b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/nodes_j.htm @@ -27,19 +27,16 @@ +

Mesh nodes

@@ -70,40 +64,38 @@ Tip: click the icon to see individual node information.
-
+ + +
<%:Originators%> - - - - - - - - - - - - - - - - -
<%:Name%><%:Short ID%><%:S/s/T/t%><%:Primary IPv6 address%><%:Via neighbour%><%:Metric%><%:Last desc.%><%:Last ref.%><%: %>

<%:Collecting data...%>
-
+
+
+
+
+
<%:Name%>
+
<%:Short ID%>
+
<%:S/s/T/t%>
+
<%:Primary IPv6%>
+
<%:Via Neighbour%>
+
<%:Metric%>
+
<%:Last Desc%>
+
<%:Last Ref%>
+
<%: %>
+
+
+
+ <%+footer%> - diff --git a/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/status_j.htm b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/status_j.htm index c6920f9..b7609d7 100644 --- a/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/status_j.htm +++ b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/status_j.htm @@ -2,30 +2,6 @@ - -
@@ -38,145 +14,117 @@
-
+
<%:Node configuration%> - - - - - - - - - - - -
<%:Short ID%><%:Node name%><%:Primary IPv6 address%><%:Node key%><%:BMX7 revision%>

<%:Collecting data...%>
-
+
+
+
+
<%:Short ID%>
+
<%:Node name%>
+
<%:Primary IPv6 address%>
+
<%:Node key%>
+
<%:Short DHash%>
+
<%:BMX7 revision%>
+
+
+
+
-
+ +
<%:Node status%> - - - - - - - - - - +
+
+
+
<%:Nodes seen%>
+
<%:Neighbours%>
+
<%:Tunnelled IPv6 address%>
+
<%:Tunnelled IPv4 address%>
+
<%:Uptime%>
+
<%:CPU usage%>
+
<%:Memory usage%>
+
<%:Tx queue%>
+
+
+
+ - - - - -
<%:Nodes seen%><%:Neighbours%><%:Tunnelled IPv6 address%><%:Tunnelled IPv4 address%><%:Uptime%><%:CPU usage%><%:Memory usage%><%:Tx queue%>

<%:Collecting data...%>
-
+
+ <%:Network interfaces%> +
+
+
+
<%:Interface%>
+
<%:State%>
+
<%:Type%>
+
<%:Max rate%>
+
<%:LinkLocal Ipv6%>
+
<%:RX BpP%>
+
<%:TX BpP%>
+
+
+
+
-
- <%:Interfaces%> - - - - - - - - - - - - - -
<%:Interface%><%:State%><%:Type%><%:Max. rate%><%:Link-local IPv6 address%><%:Rx BpP%><%:Tx BpP%>

<%:Collecting data...%>
-
- -
+
<%:Links%> - - - - - - - - - - - - - - - - -
- +
+ +
+ <%+footer%> diff --git a/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/topology.htm b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/topology.htm new file mode 100644 index 0000000..58ce9fd --- /dev/null +++ b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/topology.htm @@ -0,0 +1,54 @@ +<%+header%> + + + + + + +<%+footer%> + diff --git a/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/tunnels_j.htm b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/tunnels_j.htm new file mode 100644 index 0000000..aaa79a8 --- /dev/null +++ b/luci-app-bmx7/files/usr/lib/lua/luci/view/bmx7/tunnels_j.htm @@ -0,0 +1,76 @@ +<%# + Copyright (C) 2011 Pau Escrich + Contributors Lluis Esquerda + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + The full GNU General Public License is included in this distribution in + the file called "COPYING". +-%> + + +<%+header%> + + + +
+

Gateway announcements

+
Networks announced by mesh nodes
+ +
+ <%:Announcements%> +
+
+
+
<%:Status%>
+
<%:Name%>
+
<%:Node%>
+
<%:Network%>
+
<%:Bandwith%>
+
<%:Local net%>
+
<%:Path Metric%>
+
<%:Tun Metric%>
+
<%:Rating%>
+
+
+
+
+ +
+ + + +<%+footer%> diff --git a/luci-app-bmx7/files/www/cgi-bin/bmx7-info b/luci-app-bmx7/files/www/cgi-bin/bmx7-info index 8c501c5..7388ed1 100755 --- a/luci-app-bmx7/files/www/cgi-bin/bmx7-info +++ b/luci-app-bmx7/files/www/cgi-bin/bmx7-info @@ -1,7 +1,7 @@ #!/bin/sh # Copyright © 2011 Pau Escrich # Contributors Jo-Philipp Wich -# Roger Pueyo Centelles +# Roger Pueyo Centelles # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -34,13 +34,12 @@ else QUERY="${QUERY_STRING%%=*}" echo "Content-type: application/json" echo "" - fi check_path() { - [ -d "$1" ] && path=$(cd $1; pwd) - [ -f "$1" ] && path=$(cd $1/..; pwd) - [ $(echo "$path" | grep -c "^$BMX7_DIR") -ne 1 ] && exit 1 + [ -d "$1" ] && path=$(cd $1; pwd) + [ -f "$1" ] && path=$(cd $1/..; pwd) + [ $(echo "$path" | grep -c "^$BMX7_DIR") -ne 1 ] && exit 1 } print_mem() { @@ -52,19 +51,19 @@ print_mem() { print_query() { # If the query is a directory [ -d "$BMX7_DIR/$1" ] && - { + { # If /all has not been specified [ -z "$QALL" ] && { total=$(ls $BMX7_DIR/$1 | wc -w) i=1 - echo -n "{ \"$1\": [ " - for f in $(ls $BMX7_DIR/$1); do + echo -n "{ \"$1\": [ " + for f in $(ls $BMX7_DIR/$1); do echo -n "{ \"name\": \"$f\" }" [ $i -lt $total ] && echo -n ',' i=$(( $i + 1 )) - done - echo -n " ] }" + done + echo -n " ] }" # If /all has been specified, printing all the files together } || { @@ -80,10 +79,10 @@ print_query() { done echo -n " ]" } - } + } # If the query is a file, just printing the file - [ -f "$BMX7_DIR/$1" ] && cat "$BMX7_DIR/$1"; + [ -f "$BMX7_DIR/$1" ] && [ -s "$BMX7_DIR/$1" ] && cat "$BMX7_DIR/$1" && return 0 || return 1 } if [ "${QUERY##*/}" == "all" ]; then @@ -95,10 +94,8 @@ if [ "$QUERY" == '$info' ]; then echo '{ "info": [ ' print_query status echo -n "," - print_query interfaces - echo -n "," - print_query links - echo -n "," + print_query interfaces && echo -n "," || echo -n '{ "interfaces": "" },' + print_query links && echo -n "," || echo -n '{ "links": "" },' print_mem echo "] }" fi diff --git a/luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph-theme.css b/luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph-theme.css new file mode 100644 index 0000000..276d362 --- /dev/null +++ b/luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph-theme.css @@ -0,0 +1,59 @@ +.njg-overlay{ + background: #fbfbfb; + border-radius: 2px; + border: 1px solid #ccc; + color: #6d6357; + font-family: Arial, sans-serif; + font-family: sans-serif; + font-size: 14px; + line-height: 20px; + height: auto; + max-width: 400px; + min-width: 200px; + padding: 0 15px; + right: 10px; + top: 10px; + width: auto; +} + +.njg-metadata{ + background: #fbfbfb; + border-radius: 2px; + border: 1px solid #ccc; + color: #6d6357; + display: none; + font-family: Arial, sans-serif; + font-family: sans-serif; + font-size: 14px; + height: auto; + left: 10px; + max-width: 500px; + min-width: 200px; + padding: 0 15px; + top: 10px; + width: auto; +} + +.njg-node{ + stroke-opacity: 0.5; + stroke-width: 7px; + stroke: #fff; +} + +.njg-node:hover, +.njg-node.njg-open { + stroke: rgba(0, 0, 0, 0.2); +} + +.njg-link{ + cursor: pointer; + stroke: #999; + stroke-width: 2; + stroke-opacity: 0.25; +} + +.njg-link:hover, +.njg-link.njg-open{ + stroke-width: 4 !important; + stroke-opacity: 0.5; +} diff --git a/luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph.css b/luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph.css new file mode 100644 index 0000000..556c520 --- /dev/null +++ b/luci-app-bmx7/files/www/luci-static/resources/bmx7/css/netjsongraph.css @@ -0,0 +1,62 @@ +.njg-hidden { + display: none !important; + visibility: hidden !important; +} + +.njg-tooltip{ + font-family: sans-serif; + font-size: 10px; + fill: #000; + opacity: 0.5; + text-anchor: middle; +} + +.njg-overlay{ + display: none; + position: absolute; + z-index: 11; +} + +.njg-close{ + cursor: pointer; + position: absolute; + right: 10px; + top: 10px; +} +.njg-close:before { content: "\2716"; } + +.njg-metadata{ + display: none; + position: absolute; + z-index: 12; +} + +.njg-node{ cursor: pointer } +.njg-link{ cursor: pointer } + +#njg-select-group { + text-align: center; + box-shadow: 0 0 10px #ccc; + position: fixed; + left: 50%; + top: 50%; + width: 50%; + margin-top: -7.5em; + margin-left: -25%; + padding: 5em 2em; +} + +#njg-select-group select { + font-size: 2em; + padding: 10px 15px; + width: 50%; + cursor: pointer; +} + +#njg-select-group option { + padding: 0.5em; +} + +#njg-select-group option[value=""] { + color: #aaa; +} diff --git a/luci-app-bmx7/files/www/luci-static/resources/bmx7/js/netjsongraph.js b/luci-app-bmx7/files/www/luci-static/resources/bmx7/js/netjsongraph.js new file mode 100644 index 0000000..66d0a5f --- /dev/null +++ b/luci-app-bmx7/files/www/luci-static/resources/bmx7/js/netjsongraph.js @@ -0,0 +1,568 @@ +// version 0.1 +(function () { + /** + * vanilla JS implementation of jQuery.extend() + */ + d3._extend = function(defaults, options) { + var extended = {}, + prop; + for(prop in defaults) { + if(Object.prototype.hasOwnProperty.call(defaults, prop)) { + extended[prop] = defaults[prop]; + } + } + for(prop in options) { + if(Object.prototype.hasOwnProperty.call(options, prop)) { + extended[prop] = options[prop]; + } + } + return extended; + }; + + /** + * @function + * @name d3._pxToNumber + * Convert strings like "10px" to 10 + * + * @param {string} val The value to convert + * @return {int} The converted integer + */ + d3._pxToNumber = function(val) { + return parseFloat(val.replace('px')); + }; + + /** + * @function + * @name d3._windowHeight + * + * Get window height + * + * @return {int} The window innerHeight + */ + d3._windowHeight = function() { + return window.innerHeight || document.documentElement.clientHeight || 600; + }; + + /** + * @function + * @name d3._getPosition + * + * Get the position of `element` relative to `container` + * + * @param {object} element + * @param {object} container + */ + d3._getPosition = function(element, container) { + var n = element.node(), + nPos = n.getBoundingClientRect(); + cPos = container.node().getBoundingClientRect(); + return { + top: nPos.top - cPos.top, + left: nPos.left - cPos.left, + width: nPos.width, + bottom: nPos.bottom - cPos.top, + height: nPos.height, + right: nPos.right - cPos.left + }; + }; + + /** + * netjsongraph.js main function + * + * @constructor + * @param {string} url The NetJSON file url + * @param {object} opts The object with parameters to override {@link d3.netJsonGraph.opts} + */ + d3.netJsonGraph = function(url, opts) { + /** + * Default options + * + * @param {string} el "body" The container element el: "body" [description] + * @param {bool} metadata true Display NetJSON metadata at startup? + * @param {bool} defaultStyle true Use css style? + * @param {bool} animationAtStart false Animate nodes or not on load + * @param {array} scaleExtent [0.25, 5] The zoom scale's allowed range. @see {@link https://github.com/mbostock/d3/wiki/Zoom-Behavior#scaleExtent} + * @param {int} charge -130 The charge strength to the specified value. @see {@link https://github.com/mbostock/d3/wiki/Force-Layout#charge} + * @param {int} linkDistance 50 The target distance between linked nodes to the specified value. @see {@link https://github.com/mbostock/d3/wiki/Force-Layout#linkDistance} + * @param {float} linkStrength 0.2 The strength (rigidity) of links to the specified value in the range. @see {@link https://github.com/mbostock/d3/wiki/Force-Layout#linkStrength} + * @param {float} friction 0.9 The friction coefficient to the specified value. @see {@link https://github.com/mbostock/d3/wiki/Force-Layout#friction} + * @param {string} chargeDistance Infinity The maximum distance over which charge forces are applied. @see {@link https://github.com/mbostock/d3/wiki/Force-Layout#chargeDistance} + * @param {float} theta 0.8 The Barnes–Hut approximation criterion to the specified value. @see {@link https://github.com/mbostock/d3/wiki/Force-Layout#theta} + * @param {float} gravity 0.1 The gravitational strength to the specified numerical value. @see {@link https://github.com/mbostock/d3/wiki/Force-Layout#gravity} + * @param {int} circleRadius 8 The radius of circles (nodes) in pixel + * @param {string} labelDx "0" SVG dx (distance on x axis) attribute of node labels in graph + * @param {string} labelDy "-1.3em" SVG dy (distance on y axis) attribute of node labels in graph + * @param {function} onInit Callback function executed on initialization + * @param {function} onLoad Callback function executed after data has been loaded + * @param {function} onEnd Callback function executed when initial animation is complete + * @param {function} linkDistanceFunc By default high density areas have longer links + * @param {function} redraw Called when panning and zooming + * @param {function} prepareData Used to convert NetJSON NetworkGraph to the javascript data + * @param {function} onClickNode Called when a node is clicked + * @param {function} onClickLink Called when a link is clicked + */ + opts = d3._extend({ + el: "body", + metadata: true, + defaultStyle: true, + animationAtStart: true, + scaleExtent: [0.25, 5], + charge: -130, + linkDistance: 50, + linkStrength: 0.2, + friction: 0.9, // d3 default + chargeDistance: Infinity, // d3 default + theta: 0.8, // d3 default + gravity: 0.1, + circleRadius: 8, + labelDx: "0", + labelDy: "-1.3em", + nodeClassProperty: null, + linkClassProperty: null, + /** + * @function + * @name onInit + * + * Callback function executed on initialization + * @param {string|object} url The netJson remote url or object + * @param {object} opts The object of passed arguments + * @return {function} + */ + onInit: function(url, opts) {}, + /** + * @function + * @name onLoad + * + * Callback function executed after data has been loaded + * @param {string|object} url The netJson remote url or object + * @param {object} opts The object of passed arguments + * @return {function} + */ + onLoad: function(url, opts) {}, + /** + * @function + * @name onEnd + * + * Callback function executed when initial animation is complete + * @param {string|object} url The netJson remote url or object + * @param {object} opts The object of passed arguments + * @return {function} + */ + onEnd: function(url, opts) {}, + /** + * @function + * @name linkDistanceFunc + * + * By default, high density areas have longer links + */ + linkDistanceFunc: function(d){ + var val = opts.linkDistance; + if(d.source.linkCount >= 4 && d.target.linkCount >= 4) { + return val * 2; + } + return val; + }, + /** + * @function + * @name redraw + * + * Called on zoom and pan + */ + redraw: function() { + panner.attr("transform", + "translate(" + d3.event.translate + ") " + + "scale(" + d3.event.scale + ")" + ); + }, + /** + * @function + * @name prepareData + * + * Convert NetJSON NetworkGraph to the data structure consumed by d3 + * + * @param graph {object} + */ + prepareData: function(graph) { + var nodesMap = {}, + nodes = graph.nodes.slice(), // copy + links = graph.links.slice(), // copy + nodes_length = graph.nodes.length, + links_length = graph.links.length; + + for(var i = 0; i < nodes_length; i++) { + // count how many links every node has + nodes[i].linkCount = 0; + nodesMap[nodes[i].id] = i; + } + for(var c = 0; c < links_length; c++) { + var sourceIndex = nodesMap[links[c].source], + targetIndex = nodesMap[links[c].target]; + // ensure source and target exist + if(!nodes[sourceIndex]) { throw("source '" + links[c].source + "' not found"); } + if(!nodes[targetIndex]) { throw("target '" + links[c].target + "' not found"); } + links[c].source = nodesMap[links[c].source]; + links[c].target = nodesMap[links[c].target]; + // add link count to both ends + nodes[sourceIndex].linkCount++; + nodes[targetIndex].linkCount++; + } + return { "nodes": nodes, "links": links }; + }, + /** + * @function + * @name onClickNode + * + * Called when a node is clicked + */ + onClickNode: function(n) { + var overlay = d3.select(".njg-overlay"), + overlayInner = d3.select(".njg-overlay > .njg-inner"), + html = "

id: " + n.id + "

"; + if(n.label) { html += "

label: " + n.label + "

"; } + if(n.properties) { + for(var key in n.properties) { + if(!n.properties.hasOwnProperty(key)) { continue; } + html += "

"+key.replace(/_/g, " ")+": " + n.properties[key] + "

"; + } + } + if(n.linkCount) { html += "

links: " + n.linkCount + "

"; } + if(n.local_addresses) { + html += "

local addresses:
" + n.local_addresses.join('
') + "

"; + } + overlayInner.html(html); + overlay.classed("njg-hidden", false); + overlay.style("display", "block"); + // set "open" class to current node + removeOpenClass(); + d3.select(this).classed("njg-open", true); + }, + /** + * @function + * @name onClickLink + * + * Called when a node is clicked + */ + onClickLink: function(l) { + var overlay = d3.select(".njg-overlay"), + overlayInner = d3.select(".njg-overlay > .njg-inner"), + html = "

source: " + (l.source.label || l.source.id) + "

"; + html += "

target: " + (l.target.label || l.target.id) + "

"; + html += "

cost: " + l.cost + "

"; + if(l.properties) { + for(var key in l.properties) { + if(!l.properties.hasOwnProperty(key)) { continue; } + html += "

"+ key.replace(/_/g, " ") +": " + l.properties[key] + "

"; + } + } + overlayInner.html(html); + overlay.classed("njg-hidden", false); + overlay.style("display", "block"); + // set "open" class to current link + removeOpenClass(); + d3.select(this).classed("njg-open", true); + } + }, opts); + + // init callback + opts.onInit(url, opts); + + if(!opts.animationAtStart) { + opts.linkStrength = 2; + opts.friction = 0.3; + opts.gravity = 0; + } + if(opts.el == "body") { + var body = d3.select(opts.el), + rect = body.node().getBoundingClientRect(); + if (d3._pxToNumber(d3.select("body").style("height")) < 60) { + body.style("height", d3._windowHeight() - rect.top - rect.bottom + "px"); + } + } + var el = d3.select(opts.el).style("position", "relative"), + width = d3._pxToNumber(el.style('width')), + height = d3._pxToNumber(el.style('height')), + force = d3.layout.force() + .charge(opts.charge) + .linkStrength(opts.linkStrength) + .linkDistance(opts.linkDistanceFunc) + .friction(opts.friction) + .chargeDistance(opts.chargeDistance) + .theta(opts.theta) + .gravity(opts.gravity) + // width is easy to get, if height is 0 take the height of the body + .size([width, height]), + zoom = d3.behavior.zoom().scaleExtent(opts.scaleExtent), + // panner is the element that allows zooming and panning + panner = el.append("svg") + .attr("width", width) + .attr("height", height) + .call(zoom.on("zoom", opts.redraw)) + .append("g") + .style("position", "absolute"), + svg = d3.select(opts.el + " svg"), + drag = force.drag(), + overlay = d3.select(opts.el).append("div").attr("class", "njg-overlay"), + closeOverlay = overlay.append("a").attr("class", "njg-close"), + overlayInner = overlay.append("div").attr("class", "njg-inner"), + metadata = d3.select(opts.el).append("div").attr("class", "njg-metadata"), + metadataInner = metadata.append("div").attr("class", "njg-inner"), + closeMetadata = metadata.append("a").attr("class", "njg-close"), + // container of ungrouped networks + str = [], + selected = [], + /** + * @function + * @name removeOpenClass + * + * Remove open classes from nodes and links + */ + removeOpenClass = function () { + d3.selectAll("svg .njg-open").classed("njg-open", false); + }; + processJson = function(graph) { + /** + * Init netJsonGraph + */ + init = function(url, opts) { + d3.netJsonGraph(url, opts); + }; + /** + * Remove all instances + */ + destroy = function() { + force.stop(); + d3.select("#selectGroup").remove(); + d3.select(".njg-overlay").remove(); + d3.select(".njg-metadata").remove(); + overlay.remove(); + overlayInner.remove(); + metadata.remove(); + svg.remove(); + node.remove(); + link.remove(); + nodes = []; + links = []; + }; + /** + * Destroy and e-init all instances + * @return {[type]} [description] + */ + reInit = function() { + destroy(); + init(url, opts); + }; + + var data = opts.prepareData(graph), + links = data.links, + nodes = data.nodes; + + // disable some transitions while dragging + drag.on('dragstart', function(n){ + d3.event.sourceEvent.stopPropagation(); + zoom.on('zoom', null); + }) + // re-enable transitions when dragging stops + .on('dragend', function(n){ + zoom.on('zoom', opts.redraw); + }) + .on("drag", function(d) { + // avoid pan & drag conflict + d3.select(this).attr("x", d.x = d3.event.x).attr("y", d.y = d3.event.y); + }); + + force.nodes(nodes).links(links).start(); + + var link = panner.selectAll(".link") + .data(links) + .enter().append("line") + .attr("class", function (link) { + var baseClass = "njg-link", + addClass = null; + value = link.properties && link.properties[opts.linkClassProperty]; + if (opts.linkClassProperty && value) { + // if value is stirng use that as class + if (typeof(value) === "string") { + addClass = value; + } + else if (typeof(value) === "number") { + addClass = opts.linkClassProperty + value; + } + else if (value === true) { + addClass = opts.linkClassProperty; + } + return baseClass + " " + addClass; + } + return baseClass; + }) + .on("click", opts.onClickLink), + groups = panner.selectAll(".node") + .data(nodes) + .enter() + .append("g"); + node = groups.append("circle") + .attr("class", function (node) { + var baseClass = "njg-node", + addClass = null; + value = node.properties && node.properties[opts.nodeClassProperty]; + if (opts.nodeClassProperty && value) { + // if value is stirng use that as class + if (typeof(value) === "string") { + addClass = value; + } + else if (typeof(value) === "number") { + addClass = opts.nodeClassProperty + value; + } + else if (value === true) { + addClass = opts.nodeClassProperty; + } + return baseClass + " " + addClass; + } + return baseClass; + }) + .attr("r", opts.circleRadius) + .on("click", opts.onClickNode) + .call(drag); + + var labels = groups.append('text') + .text(function(n){ return n.label || n.id }) + .attr('dx', opts.labelDx) + .attr('dy', opts.labelDy) + .attr('class', 'njg-tooltip'); + + // Close overlay + closeOverlay.on("click", function() { + removeOpenClass(); + overlay.classed("njg-hidden", true); + }); + // Close Metadata panel + closeMetadata.on("click", function() { + // Reinitialize the page + if(graph.type === "NetworkCollection") { + reInit(); + } + else { + removeOpenClass(); + metadata.classed("njg-hidden", true); + } + }); + // default style + // TODO: probably change defaultStyle + // into something else + if(opts.defaultStyle) { + var colors = d3.scale.category20c(); + node.style({ + "fill": function(d){ return colors(d.linkCount); }, + "cursor": "pointer" + }); + } + // Metadata style + if(opts.metadata) { + metadata.attr("class", "njg-metadata").style("display", "block"); + } + + var attrs = ["protocol", + "version", + "revision", + "metric", + "router_id", + "topology_id"], + html = ""; + if(graph.label) { + html += "

" + graph.label + "

"; + } + for(var i in attrs) { + var attr = attrs[i]; + if(graph[attr]) { + html += "

" + attr + ": " + graph[attr] + "

"; + } + } + // Add nodes and links count + html += "

nodes: " + graph.nodes.length + "

"; + html += "

links: " + graph.links.length + "

"; + metadataInner.html(html); + metadata.classed("njg-hidden", false); + + // onLoad callback + opts.onLoad(url, opts); + + force.on("tick", function() { + link.attr("x1", function(d) { + return d.source.x; + }) + .attr("y1", function(d) { + return d.source.y; + }) + .attr("x2", function(d) { + return d.target.x; + }) + .attr("y2", function(d) { + return d.target.y; + }); + + node.attr("cx", function(d) { + return d.x; + }) + .attr("cy", function(d) { + return d.y; + }); + + labels.attr("transform", function(d) { + return "translate(" + d.x + "," + d.y + ")"; + }); + }) + .on("end", function(){ + force.stop(); + // onEnd callback + opts.onEnd(url, opts); + }); + + return force; + }; + + if(typeof(url) === "object") { + processJson(url); + } + else { + /** + * Parse the provided json file + * and call processJson() function + * + * @param {string} url The provided json file + * @param {function} error + */ + d3.json(url, function(error, graph) { + if(error) { throw error; } + /** + * Check if the json contains a NetworkCollection + */ + if(graph.type === "NetworkCollection") { + var selectGroup = body.append("div").attr("id", "njg-select-group"), + select = selectGroup.append("select") + .attr("id", "select"); + str = graph; + select.append("option") + .attr({ + "value": "", + "selected": "selected", + "name": "default", + "disabled": "disabled" + }) + .html("Choose the network to display"); + graph.collection.forEach(function(structure) { + select.append("option").attr("value", structure.type).html(structure.type); + // Collect each network json structure + selected[structure.type] = structure; + }); + select.on("change", function() { + selectGroup.attr("class", "njg-hidden"); + // Call selected json structure + processJson(selected[this.options[this.selectedIndex].value]); + }); + } + else { + processJson(graph); + } + }); + } + }; +})(); diff --git a/luci-app-bmx7/files/www/luci-static/resources/bmx7/js/polling.js b/luci-app-bmx7/files/www/luci-static/resources/bmx7/js/polling.js index 4a382eb..234391a 100644 --- a/luci-app-bmx7/files/www/luci-static/resources/bmx7/js/polling.js +++ b/luci-app-bmx7/files/www/luci-static/resources/bmx7/js/polling.js @@ -41,35 +41,41 @@ In the code st is the data obtained from the json call */ -function TablePooler (time, jsonurl, getparams, table_id, callback) { - this.table = document.getElementById(table_id); +function TablePooler (time, jsonurl, getparams, div_id, callback) { + this.div_id = div_id; + this.div = document.getElementById(div_id); this.callback = callback; this.jsonurl = jsonurl; this.getparams = getparams; this.time = time; - /* clear all rows */ - this.clear = function(){ - while( this.table.rows.length > 1 ) this.table.deleteRow(1); - } - this.start = function(){ XHR.poll(this.time, this.jsonurl, this.getparams, function(x, st){ var data = this.callback(st); - var content, tr, td; - this.clear(); + var content; for (var i = 0; i < data.length; i++){ - tr = this.table.insertRow(-1); - tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1); - + rowId = "trDiv_" + this.div_id + i; + rowDiv = document.getElementById(rowId); + if (rowDiv === null) { + rowDiv = document.createElement("div"); + rowDiv.id = rowId; + rowDiv.className = "tr"; + this.div.appendChild(rowDiv); + } for (var j = 0; j < data[i].length; j++){ - td = tr.insertCell(-1); - if (data[i][j].length == 2) { - td.colSpan = data[i][j][1]; - content = data[i][j][0]; + cellId = "tdDiv_" + this.div_id + i + j; + cellDiv = document.getElementById(cellId); + if (cellDiv === null) { + cellDiv = document.createElement("div"); + cellDiv.id = cellId; + cellDiv.className = "td"; + rowDiv.appendChild(cellDiv); + } + if (typeof data[i][j] !== 'undefined' && data[i][j].length == 2) { + content = data[i][j][0] + "/" + data[i][j][1]; } else content = data[i][j]; - td.innerHTML = content; + cellDiv.innerHTML = content; } } }.bind(this));