From: Remy D. Farley Date: Sun, 7 Jan 2024 11:50:55 +0000 (+0000) Subject: luci-proto-yggdrasil: add `yggdrasil-jumper` support X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=f5ccfd3df4453ac44b271fd4743bf96a1b0a1199;p=project%2Fluci.git luci-proto-yggdrasil: add `yggdrasil-jumper` support Signed-off-by: Remy D. Farley --- diff --git a/protocols/luci-proto-yggdrasil/Makefile b/protocols/luci-proto-yggdrasil/Makefile index ecd20fb655..7519940217 100644 --- a/protocols/luci-proto-yggdrasil/Makefile +++ b/protocols/luci-proto-yggdrasil/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Support for Yggdrasil Network LUCI_DEPENDS:=+yggdrasil LUCI_PKGARCH:=all -PKG_VERSION:=1.0.0 +PKG_VERSION:=1.1.0 PKG_PROVIDES:=luci-proto-yggdrasil diff --git a/protocols/luci-proto-yggdrasil/htdocs/luci-static/resources/protocol/yggdrasil.js b/protocols/luci-proto-yggdrasil/htdocs/luci-static/resources/protocol/yggdrasil.js index 849242abff..66159764ce 100644 --- a/protocols/luci-proto-yggdrasil/htdocs/luci-static/resources/protocol/yggdrasil.js +++ b/protocols/luci-proto-yggdrasil/htdocs/luci-static/resources/protocol/yggdrasil.js @@ -158,6 +158,42 @@ var getPeers = rpc.declare({ expect:{peers:[]} }); +var callIsJumperInstalled = rpc.declare({ + object:'luci.yggdrasil-jumper', + method:'isInstalled', + expect:{isInstalled: false} +}); + +var callValidateJumperConfig = rpc.declare({ + object:'luci.yggdrasil-jumper', + method:'validateConfig', + params:['config'], + expect:{output: "Unknown error."} +}); + +function validateJumperConfig(section) { + var last_input = "", last_output = ""; + + return function(section_id, input) { + if (last_input != input) { + last_input = input + + callValidateJumperConfig(input).then(function(output) { + last_output = output; + + var option = section.getUIElement(section_id).jumper_config; + option.triggerValidation(section_id); + }); + } + + if (last_output.length == 0) { + return true; + } + + return _(last_output); + }; +}; + return network.registerProtocol('yggdrasil', { getI18n: function() { @@ -257,6 +293,87 @@ return network.registerProtocol('yggdrasil', o=ss.option(form.Value,"password",_("Password")); o.optional=true; + // Jumper tab + try { + s.tab('jumper',_('Jumper')); + } catch(e) {}; + + o=s.taboption( + 'jumper', + form.HiddenValue, + 'hidden_value', + ' ', + _('%s is an independent project that aims to transparently reduce latency of a connection over Yggdrasil network, utilizing NAT traversal to bypass intermediary nodes.'.format('Yggdrasil Jumper')) + + ' ' + _('It periodically probes for active sessions and automatically establishes direct peerings over internet with remote nodes running Yggdrasil Jumper without requiring firewall or port configuration.') + ); + + o=s.taboption( + 'jumper', + form.Flag, + 'jumper_enable', + _('Enable Yggdrasil Jumper'), + _('The checkbox cannot be modified unless the yggdrasil-jumper package is installed.') + ); + o.default=false; + o.rmempty=false; + o.readonly=true; + + // Unlock enable option if jumper is installed + callIsJumperInstalled().then(function(isInstalled) { + if (isInstalled) { + var o = s.children.find(function(o) { return o.option == "jumper_enable"; }); + o.readonly = false; + // Explicit rerendering request isn't needed because the protocol tab + // is constructed only after all async functions is done + } + }); + + o=s.taboption( + 'jumper', + form.ListValue, + 'jumper_loglevel', + _('Log level'), + _('') + ); + o.value('off', _('Off')); + o.value('error', _('Error')); + o.value('warn', _('Warn')); + o.value('info', _('Info')); + o.value('debug', _('Debug')); + o.value('trace', _('Trace')); + o.default='info'; + o.rmempty=false; + + o=s.taboption( + 'jumper', + form.Flag, + 'allocate_listen_addresses', + _('Allocate listen addresses'), + _('Allow Yggdrasil Jumper to automatically configure Yggdrasil with proper listen address and random port.') + ); + o.default=true; + o.rmempty=false; + + o=s.taboption( + 'jumper', + form.Flag, + 'jumper_autofill_listen_addresses', + _('Autofill listen addresses'), + _('Retrieve the listener addresses from the Yggdrasil interface configuration.') + ); + o.default=true; + o.rmempty=false; + + o=s.taboption( + 'jumper', + form.TextValue, + 'jumper_config', + _('Extra config'), + _('Additional configuration settings (in TOML format).') + ); + o.optional=true; + o.validate=validateJumperConfig(s); + return; }, deleteConfiguration: function() { diff --git a/protocols/luci-proto-yggdrasil/root/usr/libexec/rpcd/luci.yggdrasil-jumper b/protocols/luci-proto-yggdrasil/root/usr/libexec/rpcd/luci.yggdrasil-jumper new file mode 100755 index 0000000000..62c35b0e28 --- /dev/null +++ b/protocols/luci-proto-yggdrasil/root/usr/libexec/rpcd/luci.yggdrasil-jumper @@ -0,0 +1,44 @@ +#!/bin/sh + +. /usr/share/libubox/jshn.sh + +isInstalled() { + [ -f /usr/sbin/yggdrasil-jumper ] +} + +case "$1" in + list) + json_init + json_add_object "isInstalled" + json_close_object + json_add_object "validateConfig" + json_add_string "config" + json_close_object + json_dump + ;; + call) + case "$2" in + isInstalled) + json_init + json_add_boolean "isInstalled" "$(isInstalled && echo 1 || echo 0)" + json_dump + ;; + validateConfig) + read -r input + json_load "$input" + json_get_vars config + + output="Can't locate `yggdrasil-jumper`" + isInstalled && \ + output="$(echo "$config" \ + | yggdrasil-jumper --validate --config - 2&>1 \ + | sed -E 's/(.{100}[^ ]*) /\1\n/g')" + + json_init + json_add_string output "$output" + json_dump + ;; + esac + ;; +esac + diff --git a/protocols/luci-proto-yggdrasil/root/usr/share/rpcd/acl.d/luci-proto-yggdrasil.json b/protocols/luci-proto-yggdrasil/root/usr/share/rpcd/acl.d/luci-proto-yggdrasil.json index 0351d8610d..cb8bd9ff56 100644 --- a/protocols/luci-proto-yggdrasil/root/usr/share/rpcd/acl.d/luci-proto-yggdrasil.json +++ b/protocols/luci-proto-yggdrasil/root/usr/share/rpcd/acl.d/luci-proto-yggdrasil.json @@ -3,7 +3,8 @@ "description": "Grant access to LuCI Yggdrasil procedures", "write": { "ubus": { - "luci.yggdrasil": [ "generateKeyPair", "getPeers" ] + "luci.yggdrasil": [ "generateKeyPair", "getPeers" ], + "luci.yggdrasil-jumper": [ "isInstalled", "validateConfig" ] } } }