diff --git a/package/gluon-status-page-api/Makefile b/package/gluon-status-page-api/Makefile new file mode 100644 index 00000000..91a7095a --- /dev/null +++ b/package/gluon-status-page-api/Makefile @@ -0,0 +1,30 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-status-page-api +PKG_VERSION:=1 +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/gluon-status-page-api + SECTION:=gluon + CATEGORY:=Gluon + TITLE:=API for gluon-status-page + DEPENDS:=+gluon-core +uhttpd +gluon-neighbour-info +gluon-announced +libiwinfo +libjson-c +endef + +define Build/Prepare + mkdir -p $(PKG_BUILD_DIR) + $(CP) ./src/* $(PKG_BUILD_DIR)/ +endef + +define Package/gluon-status-page-api/install + $(INSTALL_DIR) $(1)/lib/gluon/status-page/www/cgi-bin/dyn + $(INSTALL_BIN) $(PKG_BUILD_DIR)/neighbours-batadv $(1)/lib/gluon/status-page/www/cgi-bin/dyn/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/stations $(1)/lib/gluon/status-page/www/cgi-bin/dyn/ + $(CP) ./files/* $(1)/ +endef + +$(eval $(call BuildPackage,gluon-status-page-api)) diff --git a/package/gluon-status-page/files/lib/gluon/announce/nodeinfo.d/software/status-page b/package/gluon-status-page-api/files/lib/gluon/announce/nodeinfo.d/software/status-page similarity index 100% rename from package/gluon-status-page/files/lib/gluon/announce/nodeinfo.d/software/status-page rename to package/gluon-status-page-api/files/lib/gluon/announce/nodeinfo.d/software/status-page diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo b/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo similarity index 100% rename from package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo rename to package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics b/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics similarity index 100% rename from package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics rename to package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/interfaces b/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/interfaces similarity index 100% rename from package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/interfaces rename to package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/interfaces diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/nodeinfo b/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/nodeinfo similarity index 100% rename from package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/nodeinfo rename to package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/nodeinfo diff --git a/package/gluon-status-page/files/lib/gluon/upgrade/500-status-page b/package/gluon-status-page-api/files/lib/gluon/upgrade/500-status-page-api similarity index 88% rename from package/gluon-status-page/files/lib/gluon/upgrade/500-status-page rename to package/gluon-status-page-api/files/lib/gluon/upgrade/500-status-page-api index 71eca5b1..a5000012 100755 --- a/package/gluon-status-page/files/lib/gluon/upgrade/500-status-page +++ b/package/gluon-status-page-api/files/lib/gluon/upgrade/500-status-page-api @@ -9,7 +9,7 @@ uci batch <<-EOF set uhttpd.main.home=/lib/gluon/status-page/www - set uhttpd.main.max_requests=12 + set uhttpd.main.max_requests=32 commit uhttpd EOF diff --git a/package/gluon-status-page-api/src/Makefile b/package/gluon-status-page-api/src/Makefile new file mode 100644 index 00000000..f0bee975 --- /dev/null +++ b/package/gluon-status-page-api/src/Makefile @@ -0,0 +1,12 @@ +CFLAGS += -std=c99 -D_BSD_SOURCE + +CFLAGS += $(shell pkg-config --cflags json-c) +LDFLAGS += $(shell pkg-config --libs json-c) + +all: neighbours-batadv stations + +neighbours-batadv: neighbours-batadv.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^ $(LDLIBS) + +stations: stations.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^ $(LDLIBS) -liwinfo diff --git a/package/gluon-status-page-api/src/neighbours-batadv.c b/package/gluon-status-page-api/src/neighbours-batadv.c new file mode 100755 index 00000000..a386b5e0 --- /dev/null +++ b/package/gluon-status-page-api/src/neighbours-batadv.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#define STR(x) #x +#define XSTR(x) STR(x) + +static json_object *neighbours(void) { + struct json_object *obj = json_object_new_object(); + + FILE *f; + + f = fopen("/sys/kernel/debug/batman_adv/bat0/originators" , "r"); + + if (f == NULL) { + perror("Can not open bat0/originators"); + exit(1); + } + + while (!feof(f)) { + char mac1[18]; + char mac2[18]; + char ifname[IF_NAMESIZE+1]; + int tq; + double lastseen; + + int count = fscanf(f, "%17s%*[\t ]%lfs%*[\t (]%d) %17s%*[[ ]%" XSTR(IF_NAMESIZE) "[^]]]", mac1, &lastseen, &tq, mac2, ifname); + + if (count != 5) + continue; + + if (strcmp(mac1, mac2) == 0) { + struct json_object *neigh = json_object_new_object(); + + json_object_object_add(neigh, "tq", json_object_new_int(tq)); + json_object_object_add(neigh, "lastseen", json_object_new_double(lastseen)); + json_object_object_add(neigh, "ifname", json_object_new_string(ifname)); + + json_object_object_add(obj, mac1, neigh); + } + } + + fclose(f); + + return obj; +} + +int main(void) { + struct json_object *obj; + + printf("Access-Control-Allow-Origin: *\n"); + printf("Content-type: text/event-stream\n\n"); + + while (1) { + obj = neighbours(); + printf("data: %s\n\n", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN)); + fflush(stdout); + json_object_put(obj); + sleep(1); + } + + return 0; +} diff --git a/package/gluon-status-page-api/src/stations.c b/package/gluon-status-page-api/src/stations.c new file mode 100755 index 00000000..9cae3680 --- /dev/null +++ b/package/gluon-status-page-api/src/stations.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include + +#define STR(x) #x +#define XSTR(x) STR(x) + +#define BATIF_PREFIX "/sys/class/net/bat0/lower_" + +static struct json_object *get_stations(const struct iwinfo_ops *iw, const char *ifname) { + int len; + char buf[IWINFO_BUFSIZE]; + struct json_object *stations = json_object_new_object(); + + if (iw->assoclist(ifname, buf, &len) == -1) + return stations; + + // This is just: for entry in assoclist(ifname) + for (struct iwinfo_assoclist_entry *entry = (struct iwinfo_assoclist_entry *)buf; + (char*)(entry+1) <= buf + len; entry++) { + struct json_object *station = json_object_new_object(); + + json_object_object_add(station, "signal", json_object_new_int(entry->signal)); + json_object_object_add(station, "noise", json_object_new_int(entry->noise)); + json_object_object_add(station, "inactive", json_object_new_int(entry->inactive)); + + char macstr[18]; + + snprintf(macstr, sizeof(macstr), "%02x:%02x:%02x:%02x:%02x:%02x", + entry->mac[0], entry->mac[1], entry->mac[2], + entry->mac[3], entry->mac[4], entry->mac[5]); + + json_object_object_add(stations, macstr, station); + } + + return stations; +} + +static void badrequest() { + printf("Status: 400 Bad Request\n\n"); + exit(1); +} + +bool interface_is_valid(const char *ifname) { + if (strlen(ifname) > IF_NAMESIZE) + return false; + + if (strchr(ifname, '/') != NULL) + return false; + + char *path = alloca(1 + strlen(BATIF_PREFIX) + strlen(ifname)); + sprintf(path, "%s%s", BATIF_PREFIX, ifname); + + return access(path, F_OK) == 0; +} + +int main(void) { + char *ifname = getenv("QUERY_STRING"); + + if (ifname == NULL) + badrequest(); + + if (!interface_is_valid(ifname)) + badrequest(); + + const struct iwinfo_ops *iw = iwinfo_backend(ifname); + + if (iw == NULL) + badrequest(); + + printf("Access-Control-Allow-Origin: *\n"); + printf("Content-type: text/event-stream\n\n"); + + while (true) { + struct json_object *obj; + obj = get_stations(iw, ifname); + printf("data: %s\n\n", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN)); + fflush(stdout); + json_object_put(obj); + usleep(150000); + } + + return 0; +} diff --git a/package/gluon-status-page/Makefile b/package/gluon-status-page/Makefile index 2543ea2a..bfcdd91b 100644 --- a/package/gluon-status-page/Makefile +++ b/package/gluon-status-page/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-status-page -PKG_VERSION:=1 +PKG_VERSION:=2 PKG_RELEASE:=1 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) @@ -12,7 +12,7 @@ define Package/gluon-status-page SECTION:=gluon CATEGORY:=Gluon TITLE:=Adds a status page showing information about the node. - DEPENDS:=+gluon-core +uhttpd +gluon-neighbour-info +gluon-announce +libiwinfo-lua +luci-lib-jsonc + DEPENDS:=+gluon-status-page-api endef define Package/gluon-status-page/description diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv deleted file mode 100755 index 3bcdf89b..00000000 --- a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/lua - -local json = require 'luci.jsonc' -local nixio = require 'nixio' - -function neighbours() - local neighbours = {} - local list = io.lines("/sys/kernel/debug/batman_adv/bat0/originators") - for line in list do - local mac1, lastseen, tq, mac2, ifname = - line:match("^([0-9a-f:]+) +(%d+%.%d+)s +%( *(%d+)%) +([0-9a-f:]+) +%[ *(.-)%]") - - if mac1 ~= nil and mac1 == mac2 then - neighbours[mac1] = { tq = tonumber(tq) - , lastseen = tonumber(lastseen) - , ifname = ifname - } - end - end - - return neighbours -end - -io.write("Access-Control-Allow-Origin: *\n") -io.write("Content-type: text/event-stream\n\n") - -while true do - local neighbours = json.stringify(neighbours()) - io.write("data: " .. neighbours .. "\n\n") - io.flush() - nixio.nanosleep(1, 0) -end diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/stations b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/stations deleted file mode 100755 index 637de649..00000000 --- a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/stations +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/lua - -util = require 'luci.util' -json = require 'luci.jsonc' -nixio = require 'nixio' -iwinfo = require 'iwinfo' - -function badrequest() - io.write("Status: 400 Bad Request\n\n") - os.exit(1) -end - -function get_stations(iw, ifname) - local stations = {} - - for k, v in pairs(iw.assoclist(ifname)) do - stations[k:lower()] = {signal = v.signal, noise = v.noise, inactive = v.inactive} - end - - return stations -end - -local ifname = os.getenv("QUERY_STRING") - -if ifname == nil then badrequest() end - -local list = util.exec('batctl if') -local found = false -for _, line in ipairs(util.split(list)) do - if ifname == line:match('^(.-):') then - found = true - break - end -end - -if found == false then badrequest() end - -local wifitype = iwinfo.type(ifname) - -if wifitype == nil then badrequest() end - -local iw = iwinfo[wifitype] - -io.write("Access-Control-Allow-Origin: *\n") -io.write("Content-type: text/event-stream\n\n") - -while true do - local stations = json.stringify(get_stations(iw, ifname)) - io.write("data: " .. stations .. "\n\n") - io.flush() - nixio.nanosleep(0, 150e6) -end