diff --git a/dae/Makefile b/dae/Makefile index ba0701b6..319531d5 100644 --- a/dae/Makefile +++ b/dae/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dae PKG_VERSION:=2026.08.28 -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE:=dae-src-2026.08.28-d6aca8a10b35.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src @@ -127,7 +127,6 @@ define Package/dae/install $(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR)) $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/dae $(1)/usr/bin/dae - $(INSTALL_BIN) $(CURDIR)/files/dae-guard $(1)/usr/bin/dae-guard $(INSTALL_DIR) $(1)/etc/dae $(INSTALL_CONF) $(PKG_BUILD_DIR)/example.dae $(1)/etc/dae/example.dae diff --git a/dae/files/dae-guard b/dae/files/dae-guard deleted file mode 100644 index 6d6f2cd7..00000000 --- a/dae/files/dae-guard +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh - -STATE="/var/run/daede-dae.ready" -LOG="/var/log/dae/dae.log" -READY="Total startup time:" -PID="$$" -watcher_pid= - -mark_state() { - local value="$1" tmp="${STATE}.${PID}" - printf '%s %s\n' "$PID" "$value" > "$tmp" && mv -f "$tmp" "$STATE" -} - -watch_ready() { - local offset size - offset="$(wc -c < "$LOG" 2>/dev/null || echo 0)" - mark_state starting - ( - while kill -0 "$PID" 2>/dev/null; do - size="$(wc -c < "$LOG" 2>/dev/null || echo 0)" - [ "$size" -lt "$offset" ] && offset=0 - if [ -r "$LOG" ] && tail -c "+$((offset + 1))" "$LOG" 2>/dev/null | grep -Fq "$READY"; then - # Check before and after the atomic publish. If dae exits during this - # window, remove the ready marker rather than leaving a false positive. - [ "$(cat "$STATE" 2>/dev/null)" = "$PID starting" ] || exit 1 - kill -0 "$PID" 2>/dev/null || exit 1 - mark_state ready || exit 1 - kill -0 "$PID" 2>/dev/null || { rm -f "$STATE" "$STATE".*; exit 1; } - [ "$(cat "$STATE" 2>/dev/null)" = "$PID ready" ] || exit 1 - exit 0 - fi - sleep 1 - done - ) >/dev/null 2>&1 & - watcher_pid=$! -} - -watch_ready -exec /usr/bin/dae "$@" diff --git a/dae/files/dae.init b/dae/files/dae.init index 73fbe0dd..138d41cb 100644 --- a/dae/files/dae.init +++ b/dae/files/dae.init @@ -7,7 +7,7 @@ START=99 extra_command "hot_reload" "Hot-reload service" CONF="dae" -PROG="/usr/bin/dae-guard" +PROG="/usr/bin/dae" LOG_DIR="/var/log/dae" start_service() { @@ -20,11 +20,12 @@ start_service() { local config_file config_get config_file "config" "config_file" "/etc/dae/config.dae" - /usr/bin/dae validate -c "$config_file" || return 1 + "$PROG" validate -c "$config_file" || return 1 local log_maxbackups log_maxsize config_get log_maxbackups "config" "log_maxbackups" "1" config_get log_maxsize "config" "log_maxsize" "1" + procd_open_instance "$CONF" procd_set_param env DAE_LOCATION_ASSET="/usr/share/v2ray" TZ="$(uci -q get system.@system[0].zonename)" procd_set_param command "$PROG" run @@ -57,7 +58,6 @@ stop_service() { fi # clean orphaned dae0 ip link del dae0 2>/dev/null || true - rm -f /var/run/daede-dae.ready /var/run/daede-dae.ready.* } service_triggers() { @@ -65,5 +65,5 @@ service_triggers() { } hot_reload() { - /etc/init.d/dae running && /usr/bin/dae reload "$(cat /var/run/dae.pid)" + /etc/init.d/dae running && "$PROG" reload "$(cat /var/run/dae.pid)" } diff --git a/daed/Makefile b/daed/Makefile index d7ce034f..118150e7 100644 --- a/daed/Makefile +++ b/daed/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=daed PKG_VERSION:=2026.08.28 -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE:=daed-src-2026.08.28-73f01b995c34.tar.gz PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src diff --git a/daed/files/daed-guard b/daed/files/daed-guard index 34076ff9..cc6e5cf5 100644 --- a/daed/files/daed-guard +++ b/daed/files/daed-guard @@ -2,68 +2,16 @@ . /usr/share/daed/cleanup.sh -STATE="/var/run/daede-daed.ready" -LOG="/var/log/daed/daed.log" -READY="Reload: Finished" -PID="$$" -watcher_pid= - -mark_state() { - local value="$1" tmp="${STATE}.${PID}" - printf '%s %s\n' "$PID" "$value" > "$tmp" && mv -f "$tmp" "$STATE" -} - -watch_ready() { - local offset size - offset="$(wc -c < "$LOG" 2>/dev/null || echo 0)" - ( - while kill -0 "$PID" 2>/dev/null; do - size="$(wc -c < "$LOG" 2>/dev/null || echo 0)" - [ "$size" -lt "$offset" ] && offset=0 - if [ -r "$LOG" ] && tail -c "+$((offset + 1))" "$LOG" 2>/dev/null | grep -Fq "$READY"; then - [ "$(cat "$STATE" 2>/dev/null)" = "$PID starting" ] && mark_state ready - exit 0 - fi - sleep 1 - done - ) >/dev/null 2>&1 & - watcher_pid=$! -} - -stop_watcher() { - [ -n "$watcher_pid" ] || return 0 - kill "$watcher_pid" 2>/dev/null - wait "$watcher_pid" 2>/dev/null - watcher_pid= -} - -mark_state starting - if ! daed_cleanup_runtime; then echo "daed: stale network state could not be removed" >&2 exit 1 fi -watch_ready - # Keep daed as a child so a panic or unexpected exit is followed by an # immediate teardown of all kernel/runtime state before procd can respawn us. child_pid= -term_requested=0 cleanup_child() { - term_requested=1 - [ -n "$child_pid" ] || return 0 - kill "$child_pid" 2>/dev/null - # Do not let an interrupted wait leave a daed child behind. Four one-second - # polls give a graceful TERM about four seconds before the bounded KILL. - local attempt=0 - while kill -0 "$child_pid" 2>/dev/null && [ "$attempt" -lt 4 ]; do - sleep 1 - attempt=$((attempt + 1)) - done - if kill -0 "$child_pid" 2>/dev/null; then - kill -9 "$child_pid" 2>/dev/null - fi + [ -n "$child_pid" ] && kill "$child_pid" 2>/dev/null } trap cleanup_child TERM INT @@ -71,21 +19,8 @@ trap cleanup_child TERM INT child_pid=$! wait "$child_pid" status=$? -# A signal can interrupt ash's wait even though the trap has already asked the -# child to exit. Confirm the process is gone and reap it a second time before -# publishing stopping or running cleanup. -if [ "$term_requested" = 1 ]; then - cleanup_child - wait "$child_pid" 2>/dev/null - reap_status=$? - [ "$status" -eq 0 ] && status="$reap_status" -fi child_pid= trap - TERM INT -# The watcher may have observed the marker at the same time as the child -# exited. Reap it before publishing stopping so it cannot overwrite that state. -stop_watcher -mark_state stopping if ! daed_cleanup_runtime; then echo "daed: runtime cleanup after exit failed" >&2 diff --git a/daed/files/daed.init b/daed/files/daed.init index c91702be..887158d8 100644 --- a/daed/files/daed.init +++ b/daed/files/daed.init @@ -21,6 +21,7 @@ start_service() { config_get listen_addr "config" "listen_addr" "0.0.0.0:2023" config_get log_maxbackups "config" "log_maxbackups" "1" config_get log_maxsize "config" "log_maxsize" "5" + procd_open_instance "$CONF" procd_set_param env DAE_LOCATION_ASSET="/usr/share/v2ray" TZ="$(uci -q get system.@system[0].zonename)" procd_set_param command "$PROG" run @@ -44,9 +45,6 @@ start_service() { stop_service() { rm -f "$LOG" daed_cleanup_runtime - local status=$? - rm -f /var/run/daede-daed.ready /var/run/daede-daed.ready.* - return "$status" } restart() { diff --git a/doc/lucky1.png b/doc/lucky1.png deleted file mode 100644 index a5b41b6e..00000000 Binary files a/doc/lucky1.png and /dev/null differ diff --git a/doc/lucky2.png b/doc/lucky2.png deleted file mode 100644 index ba4c026f..00000000 Binary files a/doc/lucky2.png and /dev/null differ diff --git a/doc/lucky3.png b/doc/lucky3.png deleted file mode 100644 index 6fa7982f..00000000 Binary files a/doc/lucky3.png and /dev/null differ diff --git a/doc/taskplan1.png b/doc/taskplan1.png new file mode 100644 index 00000000..1f8db7be Binary files /dev/null and b/doc/taskplan1.png differ diff --git a/doc/taskplan2.png b/doc/taskplan2.png new file mode 100644 index 00000000..edb45d6d Binary files /dev/null and b/doc/taskplan2.png differ diff --git a/doc/taskplan3.png b/doc/taskplan3.png new file mode 100644 index 00000000..d4794702 Binary files /dev/null and b/doc/taskplan3.png differ diff --git a/doc/view.png b/doc/view.png new file mode 100644 index 00000000..169e112f Binary files /dev/null and b/doc/view.png differ diff --git a/doc/view2.png b/doc/view2.png new file mode 100644 index 00000000..9058c632 Binary files /dev/null and b/doc/view2.png differ diff --git a/luci-app-daede/Makefile b/luci-app-daede/Makefile index 3b39a983..0aa1fd31 100644 --- a/luci-app-daede/Makefile +++ b/luci-app-daede/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-daede PKG_VERSION:=1.15 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_MAINTAINER:=kenzok8 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) diff --git a/luci-app-daede/htdocs/luci-static/resources/view/daede/backend.js b/luci-app-daede/htdocs/luci-static/resources/view/daede/backend.js index fd298086..f141f745 100644 --- a/luci-app-daede/htdocs/luci-static/resources/view/daede/backend.js +++ b/luci-app-daede/htdocs/luci-static/resources/view/daede/backend.js @@ -23,9 +23,7 @@ const BACKENDS = { pkg: 'daed', hasWebUI: true, useNetns: true, - defaultListen: '0.0.0.0:2023', - readyState: '/var/run/daede-daed.ready', - readyPattern: /Reload: Finished/ + defaultListen: '0.0.0.0:2023' }, dae: { name: 'dae', @@ -36,9 +34,7 @@ const BACKENDS = { pkg: 'dae', config: '/etc/dae/config.dae', hasWebUI: false, - useNetns: false, - readyState: '/var/run/daede-dae.ready', - readyPattern: /Total startup time:/ + useNetns: false } }; @@ -68,56 +64,6 @@ function serviceStatus(name) { }); } -function serviceLogOffset(be) { - if (!be || !be.log) - return Promise.resolve(0); - - return L.resolveDefault(fs.read_direct(be.log, 'text'), '').then(function(content) { - return String(content || '').length; - }); -} - -function serviceReady(be, afterOffset, pid) { - if (!be || !be.log || !be.readyPattern) - return Promise.resolve(false); - - const expectedPid = Number(pid) || 0; - const notFound = function(error) { - const code = String(error && (error.code || error.errno || error.name) || '').toUpperCase(); - const message = String(error && (error.message || error) || '').toUpperCase(); - return code === 'ENOENT' || code === '-2' || code === 'NOTFOUNDERROR' || - /ENOENT|NO SUCH FILE|RESOURCE NOT FOUND/.test(message); - }; - const readState = be.readyState - ? fs.stat(be.readyState).then(function(stat) { - // A successful stat makes the state file authoritative. A subsequent - // read error must fail closed instead of falling back to an old log line. - if (!stat) - return { present: true, error: true }; - return fs.read_direct(be.readyState, 'text').then(function(value) { - return { present: true, value: String(value || '').trim() }; - }, function() { - return { present: true, error: true }; - }); - }, function(error) { - return notFound(error) ? { present: false } : { present: true, error: true }; - }) - : Promise.resolve({ present: true, error: true }); - - return readState.then(function(result) { - if (result.present) - return !result.error && expectedPid > 0 && result.value === expectedPid + ' ready'; - - // Compatibility fallback for a luci-app upgrade before the matching dae or - // daed package. It is allowed only when stat explicitly reported ENOENT. - return L.resolveDefault(fs.read_direct(be.log, 'text'), '').then(function(content) { - const text = String(content || ''); - const offset = Number(afterOffset) || 0; - return be.readyPattern.test(text.slice(text.length < offset ? 0 : offset)); - }); - }); -} - function detectInstalledBackends() { return Promise.all([ exists(BACKENDS.dae.initd), @@ -190,7 +136,5 @@ return baseclass.extend({ detectRunning: detectRunning, detectBackend: detectBackend, setActiveBackend: setActiveBackend, - serviceStatus: serviceStatus, - serviceLogOffset: serviceLogOffset, - serviceReady: serviceReady + serviceStatus: serviceStatus }); diff --git a/luci-app-daede/htdocs/luci-static/resources/view/daede/styles.js b/luci-app-daede/htdocs/luci-static/resources/view/daede/styles.js index d9ae9276..2525f899 100644 --- a/luci-app-daede/htdocs/luci-static/resources/view/daede/styles.js +++ b/luci-app-daede/htdocs/luci-static/resources/view/daede/styles.js @@ -16,7 +16,6 @@ const CSS = [ '.dd-status-row .dd-grow{flex:1 1 auto}', '.dd-badge{display:inline-flex;align-items:center;gap:5px;padding:2px 10px;border-radius:999px;font-size:10.5px;font-weight:700;letter-spacing:.3px;border:1px solid transparent;line-height:1.3}', '.dd-badge-run{color:#3da66a;border-color:rgba(61,166,106,.5)}', - '.dd-badge-wait{color:#d6a23d;border-color:rgba(214,162,61,.55)}', '.dd-badge-stop{color:#d96d6d;border-color:rgba(217,109,109,.55)}', '.dd-badge-dot{width:6px;height:6px;border-radius:50%;background:currentColor;display:inline-block}', '.dd-meta{font-size:11.5px;opacity:.7;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono",monospace}', diff --git a/luci-app-daede/htdocs/luci-static/resources/view/daede/widgets.js b/luci-app-daede/htdocs/luci-static/resources/view/daede/widgets.js index 1464174d..0686bb6c 100644 --- a/luci-app-daede/htdocs/luci-static/resources/view/daede/widgets.js +++ b/luci-app-daede/htdocs/luci-static/resources/view/daede/widgets.js @@ -23,7 +23,8 @@ function execInit(be, action) { } function restartService(be) { - return execChecked(be.initd, ['restart']); + return execChecked(be.initd, ['restart']) + .then(function() { return waitForService(be, true, 80); }); } function rejectIfOtherRunning(be, running) { @@ -59,26 +60,14 @@ function toggleService(be, turnOn) { .then(function() { return execChecked(be.initd, [action]); }); } -function waitForService(be, turnOn, attempts, readyAfter) { +function waitForService(be, turnOn, attempts) { return backend.serviceStatus(be.name).then(function(state) { - if (!turnOn && !state.running) - return state; - if (turnOn && state.running) - return backend.serviceReady(be, readyAfter, state.pid).then(function(ready) { - if (ready) { - state.ready = true; - return state; - } - return null; - }); - return null; - }).then(function(state) { - if (state) + if (!!state.running === turnOn) return state; if (attempts <= 0) throw new Error(turnOn ? _('Service did not start in time.') : _('Service did not stop in time.')); return new Promise(function(resolve) { setTimeout(resolve, 250); }) - .then(function() { return waitForService(be, turnOn, attempts - 1, readyAfter); }); + .then(function() { return waitForService(be, turnOn, attempts - 1); }); }); } @@ -167,21 +156,6 @@ function renderStatusCard(ctx, listenAddr) { let busy = false; let lastError = ''; let refreshGeneration = 0; - const boundaryKey = 'daede.ready-boundary.' + window.location.host + '.' + be.name; - let readyBoundary = null; - try { - const savedBoundary = window.localStorage.getItem(boundaryKey); - if (savedBoundary !== null && /^\d+$/.test(savedBoundary)) - readyBoundary = Number(savedBoundary); - } catch (e) {} - const rememberBoundary = function(offset) { - readyBoundary = Number(offset) || 0; - try { window.localStorage.setItem(boundaryKey, String(readyBoundary)); } catch (e) {} - }; - const clearBoundary = function() { - readyBoundary = null; - try { window.localStorage.removeItem(boundaryKey); } catch (e) {} - }; const body = E('div', { 'id': 'dd-status-body' }, E('em', {}, _('Collecting data…'))); const card = E('div', { 'class': 'dd-card dd-status-card' }, [ E('h4', { 'class': 'dd-card-title' }, _('Service Status')), @@ -191,10 +165,7 @@ function renderStatusCard(ctx, listenAddr) { const render = function(state) { while (body.firstChild) body.removeChild(body.firstChild); - const starting = !!state.starting; - const badge = starting - ? E('span', { 'class': 'dd-badge dd-badge-wait' }, [ E('span', { 'class': 'dd-badge-dot' }), _('Starting…') ]) - : state.running + const badge = state.running ? E('span', { 'class': 'dd-badge dd-badge-run' }, [ E('span', { 'class': 'dd-badge-dot' }), _('RUNNING') ]) : E('span', { 'class': 'dd-badge dd-badge-stop' }, [ E('span', { 'class': 'dd-badge-dot' }), _('STOPPED') ]); @@ -206,12 +177,7 @@ function renderStatusCard(ctx, listenAddr) { meta.push(E('span', { 'class': 'dd-meta' }, [ E('span', { 'class': 'dd-meta-label' }, 'PID'), state.pid ])); const swErr = E('span', { 'class': 'dd-meta dd-err', 'style': lastError ? '' : 'display:none' }, lastError); - const sw = E('button', { - 'class': 'dd-switch' + (state.running ? ' is-on' : ''), - 'type': 'button', - 'aria-label': _('Toggle service'), - 'disabled': busy ? '' : null - }, [ + const sw = E('button', { 'class': 'dd-switch' + (state.running ? ' is-on' : ''), 'type': 'button', 'aria-label': _('Toggle service') }, [ E('span', { 'class': 'dd-switch-knob' }) ]); sw.addEventListener('click', function(ev) { @@ -219,25 +185,21 @@ function renderStatusCard(ctx, listenAddr) { if (busy) return; refreshGeneration++; busy = true; + sw.disabled = true; lastError = ''; + swErr.style.display = 'none'; const turnOn = !state.running; - /* Keep process liveness separate from data-plane readiness. The process - appears in procd before dae has attached its rules, so show the real - transition until the backend's final startup marker is logged. */ - render({ running: turnOn, pid: 0, starting: turnOn }); - if (!turnOn) - clearBoundary(); - const boundary = turnOn ? backend.serviceLogOffset(be) : Promise.resolve(0); - boundary.then(function(offset) { - if (turnOn) - rememberBoundary(offset); - return toggleService(be, turnOn) - .then(function() { return waitForService(be, turnOn, turnOn ? 240 : 40, offset); }); - }) - .then(function() { - busy = false; - clearBoundary(); - return refresh(true); + /* instant optimistic feedback — the start/stop chain (esp. dae's eBPF + load) takes a few seconds; flip the switch and show a pending label + right away instead of looking frozen */ + sw.classList.toggle('is-on', turnOn); + const lbl = sw.parentNode && sw.parentNode.querySelector('.dd-switch-label'); + if (lbl) lbl.textContent = '…'; + toggleService(be, turnOn) + .then(function() { return waitForService(be, turnOn, 40); }) + .then(function() { + busy = false; + return refresh(true); }) .catch(function(e) { busy = false; @@ -252,7 +214,7 @@ function renderStatusCard(ctx, listenAddr) { E('span', { 'class': 'dd-grow' }), swErr, E('span', { 'class': 'dd-switch-wrap' }, [ - E('span', { 'class': 'dd-switch-label' }, starting ? _('Starting…') : (state.running ? 'ON' : 'OFF')), + E('span', { 'class': 'dd-switch-label' }, state.running ? 'ON' : 'OFF'), sw ]) ]); @@ -261,7 +223,7 @@ function renderStatusCard(ctx, listenAddr) { body.appendChild(E('div', { 'class': 'dd-status-meta' }, meta)); const actions = []; - if (be.hasWebUI && state.running && !starting) { + if (be.hasWebUI && state.running) { const port = (listenAddr || be.defaultListen).split(':').slice(-1)[0]; actions.push(E('a', { 'class': 'cbi-button cbi-button-action', @@ -270,23 +232,19 @@ function renderStatusCard(ctx, listenAddr) { 'rel': 'noreferrer noopener' }, _('Open WebUI'))); } - if (state.running && !starting) { + if (state.running) { const restart = E('button', { 'class': 'cbi-button cbi-button-positive' }, _('Restart')); restart.addEventListener('click', function(ev) { ev.preventDefault(); if (busy) return; busy = true; + restart.disabled = true; lastError = ''; - render({ running: true, pid: 0, starting: true }); - backend.serviceLogOffset(be).then(function(offset) { - rememberBoundary(offset); - return restartService(be) - .then(function() { return waitForService(be, true, 240, offset); }); - }) - .then(function() { - busy = false; - clearBoundary(); - return refresh(true); + swErr.style.display = 'none'; + restartService(be) + .then(function() { + busy = false; + return refresh(true); }) .catch(function(e) { busy = false; @@ -296,7 +254,7 @@ function renderStatusCard(ctx, listenAddr) { }); actions.push(restart); } - if (state.running && !starting && be.name === 'dae') { + if (state.running && be.name === 'dae') { const hot = E('button', { 'class': 'cbi-button cbi-button-action' }, _('Hot Reload')); hot.addEventListener('click', function(ev) { ev.preventDefault(); @@ -305,7 +263,7 @@ function renderStatusCard(ctx, listenAddr) { }); actions.push(hot); } - if (state.running && !starting && be.name === 'dae') { + if (state.running && be.name === 'dae') { const ckBtn = E('button', { 'class': 'cbi-button cbi-button-action' }, _('Test YouTube')); const ckRes = E('span', { 'class': 'dd-meta', style: 'margin-left:8px;display:none' }, ''); ckBtn.addEventListener('click', function(ev) { @@ -350,18 +308,7 @@ function renderStatusCard(ctx, listenAddr) { const generation = refreshGeneration; return backend.serviceStatus(be.name).then(function(state) { if (generation !== refreshGeneration || (busy && !force)) return; - if (!state.running) { - clearBoundary(); - render(state); - return; - } - return backend.serviceReady(be, readyBoundary, state.pid).then(function(ready) { - if (generation !== refreshGeneration || (busy && !force)) return; - state.starting = !ready; - if (ready) - clearBoundary(); - render(state); - }); + render(state); }); }; diff --git a/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json b/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json index ca7070f1..dd748864 100644 --- a/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json +++ b/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json @@ -10,8 +10,6 @@ "/etc/dae/example.dae": [ "read" ], "/var/log/dae/dae.log": [ "read" ], "/var/log/daed/daed.log": [ "read" ], - "/var/run/daede-dae.ready": [ "read" ], - "/var/run/daede-daed.ready": [ "read" ], "/usr/share/v2ray/geoip.dat": [ "read" ], "/usr/share/v2ray/geosite.dat": [ "read" ], "/sys/kernel/btf/vmlinux": [ "read" ], diff --git a/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm b/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm index cbe293d3..b18d4229 100644 --- a/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm +++ b/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm @@ -7,7 +7,7 @@ }, xray: { label: '<%:Xray-core%>', - help: '<%:The online upgrade downloads the matching Xray-core linux archive for the current ARCH from the official GitHub release page.%>' + help: '<%:The online upgrade downloads and installs the matching Xray-core package for this system from fw876/helloworld releases.%>' }, mihomo: { label: '<%:Mihomo%>', @@ -15,7 +15,7 @@ }, naiveproxy: { label: '<%:NaiveProxy%>', - help: '<%:The online upgrade tracks the latest NaiveProxy release and prefers OpenWrt static archives matching the current ARCH before falling back to other release assets.%>' + help: '<%:The online upgrade downloads and installs the matching NaiveProxy package for this system from fw876/helloworld releases.%>' } }; diff --git a/luci-app-ssr-plus/po/templates/ssr-plus.pot b/luci-app-ssr-plus/po/templates/ssr-plus.pot index 6a1451bd..013227a8 100644 --- a/luci-app-ssr-plus/po/templates/ssr-plus.pot +++ b/luci-app-ssr-plus/po/templates/ssr-plus.pot @@ -2667,8 +2667,8 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:10 msgid "" -"The online upgrade downloads the matching Xray-core linux archive for the " -"current ARCH from the official GitHub release page." +"The online upgrade downloads and installs the matching Xray-core package for " +"this system from fw876/helloworld releases." msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:14 @@ -2680,9 +2680,8 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:18 msgid "" -"The online upgrade tracks the latest NaiveProxy release and prefers OpenWrt " -"static archives matching the current ARCH before falling back to other " -"release assets." +"The online upgrade downloads and installs the matching NaiveProxy package " +"for this system from fw876/helloworld releases." msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/clash_main_panel.htm:816 diff --git a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po index 27c64da9..8cd8c8ea 100644 --- a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po +++ b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po @@ -2689,11 +2689,10 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:10 msgid "" -"The online upgrade downloads the matching Xray-core linux archive for the " -"current ARCH from the official GitHub release page." +"The online upgrade downloads and installs the matching Xray-core package for " +"this system from fw876/helloworld releases." msgstr "" -"在线升级会根据当前架构,从 Xray-core 官方 GitHub 发布页下载匹配的 Linux 压缩" -"包。" +"在线升级会从 fw876/helloworld 发布页下载并安装适配当前系统的 Xray-core 软件包。" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:14 msgid "" @@ -2706,12 +2705,10 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:18 msgid "" -"The online upgrade tracks the latest NaiveProxy release and prefers OpenWrt " -"static archives matching the current ARCH before falling back to other " -"release assets." +"The online upgrade downloads and installs the matching NaiveProxy package " +"for this system from fw876/helloworld releases." msgstr "" -"在线升级会跟踪最新 NaiveProxy 发布版,并优先选择与当前架构匹配的 OpenWrt " -"static 压缩包,找不到时再回退到其他发布资产。" +"在线升级会从 fw876/helloworld 发布页下载并安装适配当前系统的 NaiveProxy 软件包。" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/clash_main_panel.htm:816 #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/clash_main_panel.htm:871 diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/update_components.sh b/luci-app-ssr-plus/root/usr/share/shadowsocksr/update_components.sh index aac9979e..5a130b1d 100644 --- a/luci-app-ssr-plus/root/usr/share/shadowsocksr/update_components.sh +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/update_components.sh @@ -2,13 +2,11 @@ set -u -XRAY_RELEASE_PAGE="https://github.com/XTLS/Xray-core/releases/latest" +XRAY_RELEASE_PAGE="https://github.com/fw876/helloworld/releases/latest" MIHOMO_RELEASE_PAGE="https://github.com/MetaCubeX/mihomo/releases/latest" -NAIVEPROXY_RELEASE_API="https://api.github.com/repos/klzgrad/naiveproxy/releases/latest" HELLOWORLD_RELEASE_API="https://api.github.com/repos/fw876/helloworld/releases/latest" XRAY_BINARY="/usr/bin/xray" MIHOMO_BINARY="/usr/bin/mihomo" -NAIVEPROXY_BINARY="/usr/bin/naive" # Geo 数据文件 URL GEOIP_REPO="Loyalsoldier/geoip" @@ -71,9 +69,6 @@ mirror_wrap_url() { ;; jsdelivr) case "$raw_url" in - https://github.com/XTLS/Xray-core/releases/download/*) - printf '%s' "$raw_url" | sed 's#https://github.com/XTLS/Xray-core/releases/download/\(v[^/]*\)/\(.*\)#https://fastly.jsdelivr.net/gh/XTLS/Xray-core@\1/\2#' - ;; https://github.com/MetaCubeX/mihomo/releases/download/*) printf '%s' "$raw_url" | sed 's#https://github.com/MetaCubeX/mihomo/releases/download/\(v[^/]*\)/\(.*\)#https://fastly.jsdelivr.net/gh/MetaCubeX/mihomo@\1/\2#' ;; @@ -141,10 +136,6 @@ get_openwrt_arch() { printf '%s' "$arch" } -is_openwrt_env() { - [ -r /etc/openwrt_release ] || command -v opkg >/dev/null 2>&1 -} - detect_package_manager() { if command -v apk >/dev/null 2>&1; then printf '%s' 'apk' @@ -209,81 +200,32 @@ get_mihomo_current_version() { } get_naiveproxy_current_version() { - local binary + local pm version binary + + pm="$(detect_package_manager 2>/dev/null || true)" + case "$pm" in + apk) + version="$(apk list -I naiveproxy 2>/dev/null | sed -n 's/^naiveproxy-\([^[:space:]]*\).*$/\1/p' | sed -n '1p')" + ;; + opkg) + version="$(opkg status naiveproxy 2>/dev/null | sed -n 's/^Version:[[:space:]]*//p' | sed -n '1p')" + ;; + esac + + if [ -n "${version:-}" ]; then + printf '%s' "$version" + return 0 + fi binary="$(find_naiveproxy_binary)" || return 1 "$binary" --version 2>&1 | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?' | sed -n '1p' return 0 } -map_xray_asset() { - case "$1" in - x86_64*|amd64*) - printf '%s' 'Xray-linux-64.zip' - ;; - i386*|i486*|i586*|i686*|x86*) - printf '%s' 'Xray-linux-32.zip' - ;; - aarch64*|arm64*) - printf '%s' 'Xray-linux-arm64-v8a.zip' - ;; - *armv7*|*cortex-a*|*neon*|*vfpv3*|*vfpv4*) - printf '%s' 'Xray-linux-arm32-v7a.zip' - ;; - *armv6*|*arm1176*) - printf '%s' 'Xray-linux-arm32-v6.zip' - ;; - *armv5*|*arm926*|*xscale*) - printf '%s' 'Xray-linux-arm32-v5.zip' - ;; - mips64el*|mips64le*) - printf '%s' 'Xray-linux-mips64le.zip' - ;; - mips64*) - printf '%s' 'Xray-linux-mips64.zip' - ;; - mipsel*|mips32el*|mips32le*) - printf '%s' 'Xray-linux-mips32le.zip' - ;; - mips*) - printf '%s' 'Xray-linux-mips32.zip' - ;; - riscv64*) - printf '%s' 'Xray-linux-riscv64.zip' - ;; - loongarch64*|loong64*) - printf '%s' 'Xray-linux-loong64.zip' - ;; - powerpc64*|ppc64*) - printf '%s' 'Xray-linux-ppc64.zip' - ;; - s390x*) - printf '%s' 'Xray-linux-s390x.zip' - ;; - *) - return 1 - ;; - esac -} - require_cmd() { command -v "$1" >/dev/null 2>&1 } -select_unzip_cmd() { - if require_cmd unzip; then - printf '%s' 'unzip -oq' - return 0 - fi - - if busybox unzip >/dev/null 2>&1; then - printf '%s' 'busybox unzip -o' - return 0 - fi - - return 1 -} - select_gzip_cmd() { if require_cmd gzip; then printf '%s' 'gzip -dc' @@ -298,34 +240,6 @@ select_gzip_cmd() { return 1 } -select_xz_cmd() { - if require_cmd xz; then - printf '%s' 'xz -dc' - return 0 - fi - - if busybox xz >/dev/null 2>&1; then - printf '%s' 'busybox xz -dc' - return 0 - fi - - return 1 -} - -select_tar_cmd() { - if require_cmd tar; then - printf '%s' 'tar' - return 0 - fi - - if busybox tar --help >/dev/null 2>&1; then - printf '%s' 'busybox tar' - return 0 - fi - - return 1 -} - select_wget_cmd() { if require_cmd wget-ssl; then printf '%s' 'wget-ssl' @@ -1080,22 +994,72 @@ get_xray_latest_tag() { local location tag location="$(effective_url "$XRAY_RELEASE_PAGE")" || return 1 - tag="$(printf '%s' "$location" | sed -n 's#.*/tag/\(v[0-9][^/]*\)$#\1#p' | sed -n '1p')" + tag="$(printf '%s' "$location" | sed -n 's#.*/tag/\([^/]*\)$#\1#p' | sed -n '1p')" [ -n "$tag" ] || return 1 printf '%s' "$tag" } -get_xray_latest_info() { - local tag version asset url arch +select_xray_asset() { + local asset_list="$1" + local pm="$2" + local arch="$3" + local candidate + case "$pm" in + apk) + candidate="$(printf '%s\n' "$asset_list" | grep -E '^xray-core-[^[:space:]]+\.apk$' | grep -F "_${arch}.apk" | sed -n '1p')" + ;; + opkg) + candidate="$(printf '%s\n' "$asset_list" | grep -E '^xray-core_[^[:space:]]+\.ipk$' | grep -F "_${arch}.ipk" | sed -n '1p')" + ;; + *) + return 1 + ;; + esac + + [ -n "$candidate" ] || return 1 + printf '%s' "$candidate" +} + +xray_asset_version() { + local asset="$1" + local arch="$2" + local version + + case "$asset" in + xray-core_*_"$arch".ipk) + version="${asset#xray-core_}" + version="${version%_${arch}.ipk}" + ;; + xray-core-*_"$arch".apk) + version="${asset#xray-core-}" + version="${version%_${arch}.apk}" + ;; + *) + return 1 + ;; + esac + + version="$(printf '%s' "$version" | sed 's/-r[0-9][0-9]*$//')" + [ -n "$version" ] || return 1 + printf '%s' "$version" +} + +get_xray_latest_info() { + local pm tag version asset asset_list release_html url arch + + pm="$(detect_package_manager)" || return 2 arch="$(get_openwrt_arch)" - asset="$(map_xray_asset "$arch")" || return 2 tag="$(get_xray_latest_tag)" || return 3 - version="$(trim_version "$tag")" - url="$(mirror_wrap_url "https://github.com/XTLS/Xray-core/releases/download/$tag/$asset")" + release_html="$(fetch_text "https://github.com/fw876/helloworld/releases/expanded_assets/$tag")" || return 3 + asset_list="$(printf '%s\n' "$release_html" | sed -n 's#.*href="/fw876/helloworld/releases/download/[^/]*/\([^"]*\)".*#\1#p')" + asset="$(select_xray_asset "$asset_list" "$pm" "$arch")" || return 4 + version="$(xray_asset_version "$asset" "$arch")" || return 4 + url="$(mirror_wrap_url "https://github.com/fw876/helloworld/releases/download/$tag/$asset")" [ -n "$tag" ] && [ -n "$version" ] && [ -n "$url" ] || return 4 + log_kv package_manager "$pm" log_kv arch "$arch" log_kv asset "$asset" log_kv latest_version "$version" @@ -1181,112 +1145,64 @@ get_mihomo_latest_info() { return 0 } -map_naiveproxy_linux_asset() { - case "$1" in - x86_64*|amd64*) - printf '%s' 'x64' +select_naiveproxy_asset() { + local asset_list="$1" + local pm="$2" + local arch="$3" + local candidate + + case "$pm" in + apk) + candidate="$(printf '%s\n' "$asset_list" | grep -E '^naiveproxy-[^[:space:]]+\.apk$' | grep -F "_${arch}.apk" | sed -n '1p')" ;; - i386*|i486*|i586*|i686*|x86*) - printf '%s' 'x86' - ;; - aarch64*|arm64*) - printf '%s' 'arm64' - ;; - *armv7*|*cortex-a*|*neon*|*vfpv3*|*vfpv4*) - printf '%s' 'arm' - ;; - mips64el*|mips64le*) - printf '%s' 'mips64el' - ;; - mipsel*|mips32el*|mips32le*) - printf '%s' 'mipsel' - ;; - riscv64*) - printf '%s' 'riscv64' - ;; - loongarch64*|loong64*) - printf '%s' 'loong64' + opkg) + candidate="$(printf '%s\n' "$asset_list" | grep -E '^naiveproxy_[^[:space:]]+\.ipk$' | grep -F "_${arch}.ipk" | sed -n '1p')" ;; *) return 1 ;; esac + + [ -n "$candidate" ] || return 1 + printf '%s' "$candidate" } -normalize_naiveproxy_openwrt_arch() { - local arch="${1%%+*}" - printf '%s' "$arch" -} +naiveproxy_asset_version() { + local asset="$1" + local arch="$2" + local version -naiveproxy_openwrt_arch_candidates() { - local normalized - - normalized="$(normalize_naiveproxy_openwrt_arch "$1")" - printf '%s\n' "$normalized" - - case "$normalized" in - aarch64_*) - [ "$normalized" = "aarch64_generic" ] || printf '%s\n' 'aarch64_generic' + case "$asset" in + naiveproxy_*_"$arch".ipk) + version="${asset#naiveproxy_}" + version="${version%_${arch}.ipk}" ;; - x86|i386|i486|i586|i686) - printf '%s\n' 'x86' + naiveproxy-*_"$arch".apk) + version="${asset#naiveproxy-}" + version="${version%_${arch}.apk}" + ;; + *) + return 1 ;; esac -} -asset_list_has() { - local asset_list="$1" - local candidate="$2" - - printf '%s\n' "$asset_list" | grep -Fx "$candidate" >/dev/null 2>&1 -} - -select_naiveproxy_asset() { - local asset_list="$1" - local tag="$2" - local arch="$3" - local candidate linux_arch candidate_arch - - if is_openwrt_env; then - for candidate_arch in $(naiveproxy_openwrt_arch_candidates "$arch"); do - candidate="naiveproxy-${tag}-openwrt-${candidate_arch}-static.tar.xz" - if asset_list_has "$asset_list" "$candidate"; then - printf '%s' "$candidate" - return 0 - fi - - candidate="naiveproxy-${tag}-openwrt-${candidate_arch}.tar.xz" - if asset_list_has "$asset_list" "$candidate"; then - printf '%s' "$candidate" - return 0 - fi - done - fi - - linux_arch="$(map_naiveproxy_linux_asset "$arch" 2>/dev/null || true)" - if [ -n "$linux_arch" ]; then - candidate="naiveproxy-${tag}-linux-${linux_arch}.tar.xz" - if asset_list_has "$asset_list" "$candidate"; then - printf '%s' "$candidate" - return 0 - fi - fi - - return 1 + [ -n "$version" ] || return 1 + printf '%s' "$version" } get_naiveproxy_latest_info() { - local arch release_json tag version asset asset_list url + local pm arch tag version asset asset_list release_html url + pm="$(detect_package_manager)" || return 2 arch="$(get_openwrt_arch)" - release_json="$(fetch_text "$NAIVEPROXY_RELEASE_API")" || return 3 - tag="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"\([^"]*\)".*/\1/p' | sed -n '1p')" - [ -n "$tag" ] || return 3 - version="$(trim_version "$tag")" - asset_list="$(printf '%s\n' "$release_json" | sed -n 's/.*"name":[[:space:]]*"\([^"]*\.tar\.xz\)".*/\1/p')" - asset="$(select_naiveproxy_asset "$asset_list" "$tag" "$arch")" || return 4 - url="$(mirror_wrap_url "https://github.com/klzgrad/naiveproxy/releases/download/$tag/$asset")" + tag="$(get_xray_latest_tag)" || return 3 + release_html="$(fetch_text "https://github.com/fw876/helloworld/releases/expanded_assets/$tag")" || return 3 + asset_list="$(printf '%s\n' "$release_html" | sed -n 's#.*href="/fw876/helloworld/releases/download/[^/]*/\([^"]*\)".*#\1#p')" + asset="$(select_naiveproxy_asset "$asset_list" "$pm" "$arch")" || return 4 + version="$(naiveproxy_asset_version "$asset" "$arch")" || return 4 + url="$(mirror_wrap_url "https://github.com/fw876/helloworld/releases/download/$tag/$asset")" + log_kv package_manager "$pm" log_kv arch "$arch" log_kv asset "$asset" log_kv latest_version "$version" @@ -1529,12 +1445,13 @@ mainprogram_upgrade() { } xray_info() { - local current installed latest_output latest_rc latest_version arch asset can_upgrade + local pm current installed latest_output latest_rc latest_version arch asset can_upgrade installed=0 current="" + pm="$(detect_package_manager 2>/dev/null || true)" arch="$(get_openwrt_arch)" - asset="$(map_xray_asset "$arch" 2>/dev/null || true)" + asset="" if current="$(get_xray_current_version)" && [ -n "$current" ]; then installed=1 fi @@ -1545,13 +1462,14 @@ xray_info() { log_kv component xray log_kv installed "$installed" log_kv current_version "$current" + log_kv package_manager "$pm" log_kv arch "$arch" log_kv asset "$asset" if [ $latest_rc -ne 0 ]; then log_kv can_upgrade 0 case "$latest_rc" in - 2) log_kv error 'unsupported_arch' ;; + 2) log_kv error 'unsupported_package_manager' ;; 3) log_kv error 'fetch_failed' ;; 4) log_kv error 'asset_not_found' ;; *) log_kv error 'unknown_error' ;; @@ -1560,6 +1478,7 @@ xray_info() { fi latest_version="$(printf '%s\n' "$latest_output" | sed -n 's/^latest_version=//p' | sed -n '1p')" + pm="$(printf '%s\n' "$latest_output" | sed -n 's/^package_manager=//p' | sed -n '1p')" arch="$(printf '%s\n' "$latest_output" | sed -n 's/^arch=//p' | sed -n '1p')" asset="$(printf '%s\n' "$latest_output" | sed -n 's/^asset=//p' | sed -n '1p')" can_upgrade=0 @@ -1619,10 +1538,11 @@ mihomo_info() { } naiveproxy_info() { - local current installed latest_output latest_rc latest_version arch asset can_upgrade + local pm current installed latest_output latest_rc latest_version arch asset can_upgrade installed=0 current="" + pm="$(detect_package_manager 2>/dev/null || true)" arch="$(get_openwrt_arch)" if current="$(get_naiveproxy_current_version)" && [ -n "$current" ]; then installed=1 @@ -1634,12 +1554,14 @@ naiveproxy_info() { log_kv component naiveproxy log_kv installed "$installed" log_kv current_version "$current" + log_kv package_manager "$pm" log_kv arch "$arch" log_kv asset '' if [ $latest_rc -ne 0 ]; then log_kv can_upgrade 0 case "$latest_rc" in + 2) log_kv error 'unsupported_package_manager' ;; 3) log_kv error 'fetch_failed' ;; 4) log_kv error 'asset_not_found' ;; *) log_kv error 'unknown_error' ;; @@ -1648,6 +1570,7 @@ naiveproxy_info() { fi latest_version="$(printf '%s\n' "$latest_output" | sed -n 's/^latest_version=//p' | sed -n '1p')" + pm="$(printf '%s\n' "$latest_output" | sed -n 's/^package_manager=//p' | sed -n '1p')" arch="$(printf '%s\n' "$latest_output" | sed -n 's/^arch=//p' | sed -n '1p')" asset="$(printf '%s\n' "$latest_output" | sed -n 's/^asset=//p' | sed -n '1p')" can_upgrade=0 @@ -1663,12 +1586,12 @@ naiveproxy_info() { } xray_local_info() { - local current installed arch asset + local pm current installed arch installed=0 current="" + pm="$(detect_package_manager 2>/dev/null || true)" arch="$(get_openwrt_arch)" - asset="$(map_xray_asset "$arch" 2>/dev/null || true)" if current="$(get_xray_current_version)" && [ -n "$current" ]; then installed=1 fi @@ -1677,8 +1600,9 @@ xray_local_info() { log_kv installed "$installed" log_kv current_version "$current" log_kv latest_version '' + log_kv package_manager "$pm" log_kv arch "$arch" - log_kv asset "$asset" + log_kv asset '' log_kv can_upgrade 0 log_kv error '' } @@ -1707,10 +1631,11 @@ mihomo_local_info() { } naiveproxy_local_info() { - local current installed arch + local pm current installed arch installed=0 current="" + pm="$(detect_package_manager 2>/dev/null || true)" arch="$(get_openwrt_arch)" if current="$(get_naiveproxy_current_version)" && [ -n "$current" ]; then installed=1 @@ -1720,6 +1645,7 @@ naiveproxy_local_info() { log_kv installed "$installed" log_kv current_version "$current" log_kv latest_version '' + log_kv package_manager "$pm" log_kv arch "$arch" log_kv asset '' log_kv can_upgrade 0 @@ -1727,14 +1653,14 @@ naiveproxy_local_info() { } xray_upgrade() { - local latest_output latest_rc latest_version download_url tmp_dir zip_file unzip_cmd backup_file current_before current_after + local latest_output latest_rc latest_version download_url package_manager asset tmp_dir package_file current_before current_after latest_output="$(get_xray_latest_info 2>/dev/null)" latest_rc=$? if [ $latest_rc -ne 0 ]; then log_kv success 0 case "$latest_rc" in - 2) log_kv message 'Unsupported ARCH' ;; + 2) log_kv message 'Unsupported package manager' ;; 3) log_kv message 'Failed to fetch release metadata' ;; 4) log_kv message 'Matching release asset not found' ;; *) log_kv message 'Unknown error' ;; @@ -1742,14 +1668,10 @@ xray_upgrade() { return 0 fi - if ! unzip_cmd="$(select_unzip_cmd)"; then - log_kv success 0 - log_kv message 'Missing unzip support' - return 0 - fi - latest_version="$(printf '%s\n' "$latest_output" | sed -n 's/^latest_version=//p' | sed -n '1p')" download_url="$(printf '%s\n' "$latest_output" | sed -n 's/^download_url=//p' | sed -n '1p')" + package_manager="$(printf '%s\n' "$latest_output" | sed -n 's/^package_manager=//p' | sed -n '1p')" + asset="$(printf '%s\n' "$latest_output" | sed -n 's/^asset=//p' | sed -n '1p')" current_before="$(get_xray_current_version 2>/dev/null || true)" if [ -n "$current_before" ] && ! version_gt "$latest_version" "$current_before"; then log_kv success 1 @@ -1767,52 +1689,25 @@ xray_upgrade() { return 0 fi - zip_file="$tmp_dir/xray.zip" - backup_file="$tmp_dir/xray.backup" - + package_file="$tmp_dir/$asset" trap "rm -rf '$tmp_dir'" EXIT INT TERM - if ! download_file "$download_url" "$zip_file"; then + if ! download_file "$download_url" "$package_file"; then log_kv success 0 log_kv message 'Download failed' return 0 fi - if ! sh -c "$unzip_cmd \"$zip_file\" -d \"$tmp_dir\" >/dev/null 2>&1"; then - log_kv success 0 - log_kv message 'Extract failed' - return 0 - fi - - if [ ! -f "$tmp_dir/xray" ]; then - log_kv success 0 - log_kv message 'xray binary not found in archive' - return 0 - fi - - chmod 0755 "$tmp_dir/xray" || true - if [ -x "$XRAY_BINARY" ]; then - cp -fp "$XRAY_BINARY" "$backup_file" 2>/dev/null || true - fi - - if ! cp -f "$tmp_dir/xray" "$XRAY_BINARY"; then - if [ -f "$backup_file" ]; then - cp -f "$backup_file" "$XRAY_BINARY" 2>/dev/null || true - fi + if [ ! -s "$package_file" ] || ! mainprogram_install_package "$package_manager" "$package_file"; then log_kv success 0 log_kv message 'Install failed' return 0 fi - chmod 0755 "$XRAY_BINARY" || true current_after="$(get_xray_current_version 2>/dev/null || true)" if [ -z "$current_after" ]; then - if [ -f "$backup_file" ]; then - cp -f "$backup_file" "$XRAY_BINARY" 2>/dev/null || true - chmod 0755 "$XRAY_BINARY" || true - fi log_kv success 0 - log_kv message 'Installed binary failed to run' + log_kv message 'Installed package check failed' return 0 fi @@ -1824,6 +1719,9 @@ xray_upgrade() { log_kv previous_version "$current_before" log_kv current_version "$current_after" log_kv latest_version "$latest_version" + log_kv package_manager "$package_manager" + log_kv arch "$(get_openwrt_arch)" + log_kv asset "$asset" log_kv message 'Upgrade completed' return 0 } @@ -1940,13 +1838,14 @@ mihomo_upgrade() { } naiveproxy_upgrade() { - local latest_output latest_rc latest_version download_url tmp_dir archive_file xz_cmd tar_cmd backup_file current_before current_after target_binary extracted_binary + local latest_output latest_rc latest_version download_url package_manager asset tmp_dir package_file current_before current_after latest_output="$(get_naiveproxy_latest_info 2>/dev/null)" latest_rc=$? if [ $latest_rc -ne 0 ]; then log_kv success 0 case "$latest_rc" in + 2) log_kv message 'Unsupported package manager' ;; 3) log_kv message 'Failed to fetch release metadata' ;; 4) log_kv message 'Matching release asset not found' ;; *) log_kv message 'Unknown error' ;; @@ -1954,20 +1853,10 @@ naiveproxy_upgrade() { return 0 fi - if ! xz_cmd="$(select_xz_cmd)"; then - log_kv success 0 - log_kv message 'Missing xz support' - return 0 - fi - - if ! tar_cmd="$(select_tar_cmd)"; then - log_kv success 0 - log_kv message 'Extract failed' - return 0 - fi - latest_version="$(printf '%s\n' "$latest_output" | sed -n 's/^latest_version=//p' | sed -n '1p')" download_url="$(printf '%s\n' "$latest_output" | sed -n 's/^download_url=//p' | sed -n '1p')" + package_manager="$(printf '%s\n' "$latest_output" | sed -n 's/^package_manager=//p' | sed -n '1p')" + asset="$(printf '%s\n' "$latest_output" | sed -n 's/^asset=//p' | sed -n '1p')" current_before="$(get_naiveproxy_current_version 2>/dev/null || true)" if [ -n "$current_before" ] && ! version_gt "$latest_version" "$current_before"; then log_kv success 1 @@ -1978,9 +1867,6 @@ naiveproxy_upgrade() { return 0 fi - target_binary="$(find_naiveproxy_binary 2>/dev/null || true)" - [ -n "$target_binary" ] || target_binary="$NAIVEPROXY_BINARY" - tmp_dir="$(mktemp -d /tmp/ssrplus-naiveproxy.XXXXXX)" if [ -z "$tmp_dir" ] || [ ! -d "$tmp_dir" ]; then log_kv success 0 @@ -1988,65 +1874,25 @@ naiveproxy_upgrade() { return 0 fi - archive_file="$tmp_dir/naiveproxy.tar.xz" - backup_file="$tmp_dir/naive.backup" - extracted_binary="" - + package_file="$tmp_dir/$asset" trap "rm -rf '$tmp_dir'" EXIT INT TERM - if ! download_file "$download_url" "$archive_file"; then + if ! download_file "$download_url" "$package_file"; then log_kv success 0 log_kv message 'Download failed' return 0 fi - mkdir -p "$tmp_dir/extract" || { - log_kv success 0 - log_kv message 'Failed to create temp directory' - return 0 - } - - if ! sh -c "cd \"$tmp_dir/extract\" && $xz_cmd \"$archive_file\" | $tar_cmd -xf - >/dev/null 2>&1"; then - log_kv success 0 - log_kv message 'Extract failed' - return 0 - fi - - extracted_binary="$(find "$tmp_dir/extract" -type f -name naive | sed -n '1p')" - if [ -z "$extracted_binary" ] || [ ! -s "$extracted_binary" ]; then - log_kv success 0 - log_kv message 'naive binary not found in archive' - return 0 - fi - - mkdir -p "$(dirname "$target_binary")" || true - chmod 0755 "$extracted_binary" || true - if [ -x "$target_binary" ]; then - cp -fp "$target_binary" "$backup_file" 2>/dev/null || true - fi - - if ! cp -f "$extracted_binary" "$target_binary"; then - if [ -f "$backup_file" ]; then - cp -f "$backup_file" "$target_binary" 2>/dev/null || true - fi + if [ ! -s "$package_file" ] || ! mainprogram_install_package "$package_manager" "$package_file"; then log_kv success 0 log_kv message 'Install failed' return 0 fi - chmod 0755 "$target_binary" || true - if [ "$target_binary" != "$NAIVEPROXY_BINARY" ] && [ ! -x "$NAIVEPROXY_BINARY" ]; then - ln -sf "$target_binary" "$NAIVEPROXY_BINARY" 2>/dev/null || true - fi - current_after="$(get_naiveproxy_current_version 2>/dev/null || true)" if [ -z "$current_after" ]; then - if [ -f "$backup_file" ]; then - cp -f "$backup_file" "$target_binary" 2>/dev/null || true - chmod 0755 "$target_binary" || true - fi log_kv success 0 - log_kv message 'Installed binary failed to run' + log_kv message 'Installed package check failed' return 0 fi @@ -2058,6 +1904,9 @@ naiveproxy_upgrade() { log_kv previous_version "$current_before" log_kv current_version "$current_after" log_kv latest_version "$latest_version" + log_kv package_manager "$package_manager" + log_kv arch "$(get_openwrt_arch)" + log_kv asset "$asset" log_kv message 'Upgrade completed' return 0 }