'use strict'; import { connect } from 'ubus'; import * as fs from 'fs'; const methods = { get_log: { call: function() { let p = fs.popen("logread -e 'ssserver' | grep -E 'ssserver(\\[[0-9]+\\])?: ' | tail -n 150"); let log = ''; if (p) { log = p.read('all'); p.close(); } return { log: log }; } }, get_ciphers: { call: function() { let ciphers = []; let p = fs.popen('/usr/bin/ssserver --help 2>&1'); if (p) { let output = p.read('all'); p.close(); let start = index(output, '--encrypt-method'); if (start >= 0) { let sub = substr(output, start); let res = match(sub, /possible values: (([^\]\r\n]|[\r\n])+)/); if (res) { let list = split(res[1], /,\s*/); for (let c in list) { let val = rtrim(ltrim(c)); // Clean up possible newlines and extra spaces val = replace(val, /\s+/g, ""); if (val) push(ciphers, val); } } } } // Fallback if parsing fails or returns nothing if (length(ciphers) == 0) { ciphers = [ 'chacha20-ietf-poly1305', 'aes-256-gcm', 'aes-128-gcm', '2022-blake3-aes-128-gcm', '2022-blake3-aes-256-gcm', '2022-blake3-chacha20-poly1305' ]; } return { ciphers: ciphers }; } }, get_tfo_status: { call: function() { let val = rtrim(fs.readfile('/proc/sys/net/ipv4/tcp_fastopen') || '0'); return { value: +val }; } }, get_lan_ip: { call: function() { let u = connect(); let ip = ''; if (u) { let status = u.call('network.interface.lan', 'status'); if (status && type(status['ipv4-address']) === 'array' && length(status['ipv4-address']) > 0) { ip = status['ipv4-address'][0].address; } u.disconnect(); } return { ip: ip }; } }, get_status: { call: function() { let u = connect(); let running = false; let pid = null; if (u) { let res = u.call('service', 'list', { name: 'ssserver' }); if (res && res.ssserver && res.ssserver.instances) { let inst = res.ssserver.instances.instance1; if (inst && inst.running) { running = true; pid = inst.pid; } } u.disconnect(); } return { running: running, pid: pid }; } }, service_action: { args: { action: '' }, call: function(req) { let action = req.args?.action ?? ''; if (action != 'start' && action != 'stop' && action != 'restart' && action != 'reload') return { success: false, error: 'invalid action' }; let rc = system('/etc/init.d/ssserver ' + action + ' >/dev/null 2>&1'); return { success: (rc === 0), applied: (rc === 0) }; } } }; return { 'luci.ssserver': methods };