Merge branch 'jerrykuku:master' into master

This commit is contained in:
柒一昂 2022-06-09 10:23:07 +08:00 committed by GitHub
commit 72d2ded0f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 255 additions and 254 deletions

View File

@ -1,308 +1,309 @@
-- Copyright (C) 2018 jerrykuku <jerrykuku@qq.com>
-- Licensed to the public under the GNU General Public License v3.
-- Licensed to the public under the GNU General Public License v3.0
module('luci.controller.vssr', package.seeall)
function index()
if not nixio.fs.access('/etc/config/vssr') then
return
end
if not nixio.fs.access('/etc/config/vssr') then
return
end
local page = entry({'admin', 'services', 'vssr'}, alias('admin', 'services', 'vssr', 'client'), _('Hello World'), 0) -- 首页
page.dependent = true
page.acl_depends = {'luci-app-vssr'}
local page = entry({'admin', 'services', 'vssr'}, alias('admin', 'services', 'vssr', 'client'), _('Hello World'), 0) -- 首页
page.dependent = true
page.acl_depends = { 'luci-app-vssr' }
entry({'admin', 'services', 'vssr', 'client'}, cbi('vssr/client'), _('SSR Client'), 10).leaf = true -- 基本设置
entry({'admin', 'services', 'vssr', 'servers'}, cbi('vssr/servers'), _('Severs Nodes'), 11).leaf = true -- 服务器节点
entry({'admin', 'services', 'vssr', 'servers'}, arcombine(cbi('vssr/servers'), cbi('vssr/client-config')), _('Severs Nodes'), 11).leaf = true -- 编辑节点
entry({'admin', 'services', 'vssr', 'subscribe_config'}, cbi('vssr/subscribe-config', {hideapplybtn = true, hidesavebtn = true, hideresetbtn = true}), _('Subscribe'), 12).leaf = true -- 订阅设置
entry({'admin', 'services', 'vssr', 'control'}, cbi('vssr/control'), _('Access Control'), 13).leaf = true -- 访问控制
entry({'admin', 'services', 'vssr', 'router'}, cbi('vssr/router'), _('Router Config'), 14).leaf = true -- 访问控制
entry({'admin', 'services', 'vssr', 'socks5'}, cbi('vssr/socks5'), _('Local Proxy'), 15).leaf = true -- Socks5代理
entry({'admin', 'services', 'vssr', 'advanced'}, cbi('vssr/advanced'), _('Advanced Settings'), 16).leaf = true -- 高级设置
entry({'admin', 'services', 'vssr', 'server'}, arcombine(cbi('vssr/server'), cbi('vssr/server-config')), _('SSR Server'), 20).leaf = true -- 服务端
entry({'admin', 'services', 'vssr', 'log'}, cbi('vssr/log'), _('Log'), 30).leaf = true -- 日志
--entry({'admin', 'services', 'vssr', 'licence'}, template('vssr/licence'), _('Licence'), 40).leaf = true
entry({'admin', 'services', 'vssr', 'refresh'}, call('refresh_data')) -- 更新白名单和GFWLIST
entry({'admin', 'services', 'vssr', 'checkport'}, call('check_port')) -- 检测单个端口并返回Ping
entry({'admin', 'services', 'vssr', 'run'}, call('act_status')) -- 检测全局服务器状态
entry({'admin', 'services', 'vssr', 'change'}, call('change_node')) -- 切换节点
entry({'admin', 'services', 'vssr', 'allserver'}, call('get_servers')) -- 获取所有节点Json
entry({'admin', 'services', 'vssr', 'subscribe'}, call('get_subscribe')) -- 执行订阅
entry({'admin', 'services', 'vssr', 'flag'}, call('get_flag')) -- 获取节点国旗 iso code
entry({'admin', 'services', 'vssr', 'ip'}, call('check_ip')) -- 获取ip情况
entry({'admin', 'services', 'vssr', 'switch'}, call('switch')) -- 设置节点为自动切换
entry({'admin', 'services', 'vssr', 'delnode'}, call('del_node')) -- 删除某个节点
entry({'admin', 'services', 'vssr', 'client'}, cbi('vssr/client'), _('SSR Client'), 10).leaf = true -- 基本设置
entry({'admin', 'services', 'vssr', 'servers'}, cbi('vssr/servers'), _('Severs Nodes'), 11).leaf = true -- 服务器节点
entry({'admin', 'services', 'vssr', 'servers'}, arcombine(cbi('vssr/servers'), cbi('vssr/client-config')), _('Severs Nodes'), 11).leaf = true -- 编辑节点
entry({'admin', 'services', 'vssr', 'subscribe_config'}, cbi('vssr/subscribe-config', {hideapplybtn = true, hidesavebtn = true, hideresetbtn = true}), _('Subscribe'), 12).leaf = true -- 订阅设置
entry({'admin', 'services', 'vssr', 'control'}, cbi('vssr/control'), _('Access Control'), 13).leaf = true -- 访问控制
entry({'admin', 'services', 'vssr', 'router'}, cbi('vssr/router'), _('Router Config'), 14).leaf = true -- 访问控制
entry({'admin', 'services', 'vssr', 'socks5'}, cbi('vssr/socks5'), _('Local Proxy'), 15).leaf = true -- Socks5代理
entry({'admin', 'services', 'vssr', 'advanced'}, cbi('vssr/advanced'), _('Advanced Settings'), 16).leaf = true -- 高级设置
entry({'admin', 'services', 'vssr', 'server'}, arcombine(cbi('vssr/server'), cbi('vssr/server-config')), _('SSR Server'), 20).leaf = true -- 服务端
entry({'admin', 'services', 'vssr', 'log'}, cbi('vssr/log'), _('Log'), 30).leaf = true -- 日志
--entry({'admin', 'services', 'vssr', 'licence'}, template('vssr/licence'), _('Licence'), 40).leaf = true
entry({'admin', 'services', 'vssr', 'refresh'}, call('refresh_data')) -- 更新白名单和GFWLIST
entry({'admin', 'services', 'vssr', 'checkport'}, call('check_port')) -- 检测单个端口并返回Ping
entry({'admin', 'services', 'vssr', 'run'}, call('act_status')) -- 检测全局服务器状态
entry({'admin', 'services', 'vssr', 'change'}, call('change_node')) -- 切换节点
entry({'admin', 'services', 'vssr', 'allserver'}, call('get_servers')) -- 获取所有节点Json
entry({'admin', 'services', 'vssr', 'subscribe'}, call('get_subscribe')) -- 执行订阅
entry({'admin', 'services', 'vssr', 'flag'}, call('get_flag')) -- 获取节点国旗 iso code
entry({'admin', 'services', 'vssr', 'ip'}, call('check_ip')) -- 获取ip情况
entry({'admin', 'services', 'vssr', 'switch'}, call('switch')) -- 设置节点为自动切换
entry({'admin', 'services', 'vssr', 'delnode'}, call('del_node')) -- 删除某个节点
end
-- 执行订阅
function get_subscribe()
local cjson = require 'luci.jsonc'
local e = {}
local name = 'vssr'
local uci = luci.model.uci.cursor()
local auto_update = luci.http.formvalue('auto_update')
local auto_update_time = luci.http.formvalue('auto_update_time')
local proxy = luci.http.formvalue('proxy')
local subscribe_url = luci.http.formvalue('subscribe_url')
local filter_words = luci.http.formvalue('filter_words')
if subscribe_url ~= '[]' then
uci:delete(name, '@server_subscribe[0]', subscribe_url)
uci:set(name, '@server_subscribe[0]', 'auto_update', auto_update)
uci:set(name, '@server_subscribe[0]', 'auto_update_time', auto_update_time)
uci:set(name, '@server_subscribe[0]', 'proxy', proxy)
uci:set(name, '@server_subscribe[0]', 'filter_words', filter_words)
uci:set_list(name, '@server_subscribe[0]', 'subscribe_url', cjson.parse(subscribe_url))
uci:commit(name)
luci.sys.exec('/usr/bin/lua /usr/share/vssr/subscribe.lua >/www/check_update.htm 2>/dev/null &')
e.error = 0
else
e.error = 1
end
luci.http.prepare_content('application/json')
luci.http.write_json(e)
local cjson = require 'luci.jsonc'
local e = {}
local name = 'vssr'
local uci = luci.model.uci.cursor()
local auto_update = luci.http.formvalue('auto_update')
local auto_update_time = luci.http.formvalue('auto_update_time')
local proxy = luci.http.formvalue('proxy')
local subscribe_url = luci.http.formvalue('subscribe_url')
local filter_words = luci.http.formvalue('filter_words')
if subscribe_url ~= '[]' then
uci:delete(name, '@server_subscribe[0]', subscribe_url)
uci:set(name, '@server_subscribe[0]', 'auto_update', auto_update)
uci:set(name, '@server_subscribe[0]', 'auto_update_time', auto_update_time)
uci:set(name, '@server_subscribe[0]', 'proxy', proxy)
uci:set(name, '@server_subscribe[0]', 'filter_words', filter_words)
uci:set_list(name, '@server_subscribe[0]', 'subscribe_url', cjson.parse(subscribe_url))
uci:commit(name)
luci.sys.exec('/usr/bin/lua /usr/share/vssr/subscribe.lua >/www/check_update.htm 2>/dev/null &')
e.error = 0
else
e.error = 1
end
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
-- 获取所有节点
function get_servers()
local uci = luci.model.uci.cursor()
local server_table = {}
uci:foreach(
'vssr',
'servers',
function(s)
local e = {}
e['name'] = s['.name']
table.insert(server_table, e)
end
)
luci.http.prepare_content('application/json')
luci.http.write_json(server_table)
local uci = luci.model.uci.cursor()
local server_table = {}
uci:foreach(
'vssr',
'servers',
function(s)
local e = {}
e['name'] = s['.name']
table.insert(server_table, e)
end
)
luci.http.prepare_content('application/json')
luci.http.write_json(server_table)
end
-- 删除指定节点
function del_node()
local e = {}
local uci = luci.model.uci.cursor()
local node = luci.http.formvalue('node')
e.status = false
e.node = node
if node ~= '' then
uci:delete('vssr', node)
uci:save('vssr')
uci:commit('vssr')
e.status = true
end
luci.http.prepare_content('application/json')
luci.http.write_json(e)
local e = {}
local uci = luci.model.uci.cursor()
local node = luci.http.formvalue('node')
e.status = false
e.node = node
if node ~= '' then
uci:delete('vssr', node)
uci:save('vssr')
uci:commit('vssr')
e.status = true
end
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
-- 切换节点
function change_node()
local sockets = require 'socket'
local e = {}
local uci = luci.model.uci.cursor()
local sid = luci.http.formvalue('set')
local server = luci.http.formvalue('server')
e.status = false
e.sid = sid
if sid ~= '' and server ~= '' then
uci:set('vssr', '@global[0]', server .. '_server', sid)
if (server ~= 'global' and server ~= 'udp_relay') then
uci:set('vssr', '@global[0]', 'v2ray_flow', '1')
end
uci:commit('vssr')
luci.sys.call('/etc/init.d/vssr restart >/www/restartlog.htm 2>&1')
e.status = true
end
luci.http.prepare_content('application/json')
luci.http.write_json(e)
local sockets = require 'socket'
local e = {}
local uci = luci.model.uci.cursor()
local sid = luci.http.formvalue('set')
local server = luci.http.formvalue('server')
e.status = false
e.sid = sid
if sid ~= '' and server ~= '' then
uci:set('vssr', '@global[0]', server .. '_server', sid)
if (server ~= 'global' and server ~= 'udp_relay') then
uci:set('vssr', '@global[0]', 'v2ray_flow', '1')
end
uci:commit('vssr')
luci.sys.call('/etc/init.d/vssr restart >/www/restartlog.htm 2>&1')
e.status = true
end
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
-- 设置节点为自动切换
function switch()
local e = {}
local uci = luci.model.uci.cursor()
local sid = luci.http.formvalue('node')
local isSwitch = uci:get('vssr', sid, 'switch_enable')
local toSwitch = (isSwitch == '1') and '0' or '1'
uci:set('vssr', sid, 'switch_enable', toSwitch)
uci:commit('vssr')
if isSwitch == '1' then
e.switch = false
else
e.switch = true
end
e.status = true
luci.http.prepare_content('application/json')
luci.http.write_json(e)
local e = {}
local uci = luci.model.uci.cursor()
local sid = luci.http.formvalue('node')
local isSwitch = uci:get('vssr', sid, 'switch_enable')
local toSwitch = (isSwitch == '1') and '0' or '1'
uci:set('vssr', sid, 'switch_enable', toSwitch)
uci:commit('vssr')
if isSwitch == '1' then
e.switch = false
else
e.switch = true
end
e.status = true
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
-- 检测全局服务器状态
function act_status()
math.randomseed(os.time())
local e = {}
-- 全局服务器
e.global = luci.sys.call('busybox ps -w | grep vssr_t | grep -v grep >/dev/null') == 0
-- 检测PDNSD状态
e.pdnsd = luci.sys.call('pidof pdnsd >/dev/null') == 0
-- 检测游戏模式状态
e.game = luci.sys.call('busybox ps -w | grep vssr_u | grep -v grep >/dev/null') == 0
-- 检测Socks5
e.socks5 = luci.sys.call('busybox ps -w | grep vssr_s | grep -v grep >/dev/null') == 0
luci.http.prepare_content('application/json')
luci.http.write_json(e)
math.randomseed(os.time())
local e = {}
-- 全局服务器
e.global = luci.sys.call('busybox ps -w | grep vssr_t | grep -v grep >/dev/null') == 0
-- 检测PDNSD状态
e.pdnsd = luci.sys.call('pidof pdnsd >/dev/null') == 0
-- 检测游戏模式状态
e.game = luci.sys.call('busybox ps -w | grep vssr_u | grep -v grep >/dev/null') == 0
-- 检测Socks5
e.socks5 = luci.sys.call('busybox ps -w | grep vssr_s | grep -v grep >/dev/null') == 0
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
-- 检测单个节点状态并返回连接速度
function check_port()
local sockets = require 'socket'
local vssr = require 'vssrutil'
local set = luci.http.formvalue('host')
local port = luci.http.formvalue('port')
local retstring = ''
local t0 = sockets.gettime()
ret = vssr.check_site(set, port)
local t1 = sockets.gettime()
retstring = tostring(ret) == 'true' and '1' or '0'
local tt = t1 - t0
luci.http.prepare_content('application/json')
luci.http.write_json({ret = retstring, used = math.floor(tt * 1000 + 0.5)})
local sockets = require 'socket'
local vssr = require 'vssrutil'
local set = luci.http.formvalue('host')
local port = luci.http.formvalue('port')
local retstring = ''
local t0 = sockets.gettime()
ret = vssr.check_site(set, port)
local t1 = sockets.gettime()
retstring = tostring(ret) == 'true' and '1' or '0'
local tt = t1 - t0
luci.http.prepare_content('application/json')
luci.http.write_json({ret = retstring, used = math.floor(tt * 1000 + 0.5)})
end
-- 读取 GeoLite2 库 国旗图标
function get_iso(ip)
local mm = require 'maxminddb'
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
local res = db:lookup(ip)
return string.lower(res:get('country', 'iso_code'))
local mm = require 'maxminddb'
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
local res = db:lookup(ip)
return string.lower(res:get('country', 'iso_code'))
end
-- 读取 GeoLite2 库 国旗名称
function get_cname(ip)
local mm = require 'maxminddb'
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
local res = db:lookup(ip)
return string.lower(res:get('country', 'names', 'zh-CN'))
local mm = require 'maxminddb'
local db = mm.open('/usr/share/vssr/GeoLite2-Country.mmdb')
local res = db:lookup(ip)
return string.lower(res:get('country', 'names', 'zh-CN'))
end
-- 获取当前代理状态 与节点ip
function check_ip()
local e = {}
local d = {}
local vssr = require 'vssrutil'
local port = 80
local ip = vssr.wget('http://api.ipify.org/')
d.flag = 'un'
d.country = 'Unknown'
if (ip ~= '') then
local status, code = pcall(get_iso, ip)
if (status) then
d.flag = code
end
local status1, country = pcall(get_cname, ip)
if (status1) then
d.country = country
end
end
e.outboard = ip
e.outboardip = d
e.baidu = vssr.check_site('www.baidu.com', port)
e.taobao = vssr.check_site('www.taobao.com', port)
e.google = vssr.check_site('www.google.com', port)
e.youtube = vssr.check_site('www.youtube.com', port)
luci.http.prepare_content('application/json')
luci.http.write_json(e)
local e = {}
local d = {}
local vssr = require 'vssrutil'
local port = 80
local ip = vssr.wget('http://api.ipify.org/')
d.flag = 'un'
d.country = 'Unknown'
if (ip ~= '') then
local status, code = pcall(get_iso, ip)
if (status) then
d.flag = code
end
local status1, country = pcall(get_cname, ip)
if (status1) then
d.country = country
end
end
e.outboard = ip
e.outboardip = d
e.baidu = vssr.check_site('www.baidu.com', port)
e.taobao = vssr.check_site('www.taobao.com', port)
e.google = vssr.check_site('www.google.com', port)
e.youtube = vssr.check_site('www.youtube.com', port)
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
-- 获取节点国旗 iso code
function get_flag()
local e = {}
local vssr = require 'vssrutil'
local host = luci.http.formvalue('host')
local remark = luci.http.formvalue('remark')
e.host = host
e.flag = vssr.get_flag(remark, host)
luci.http.prepare_content('application/json')
luci.http.write_json(e)
local e = {}
local vssr = require 'vssrutil'
local host = luci.http.formvalue('host')
local remark = luci.http.formvalue('remark')
e.host = host
e.flag = vssr.get_flag(remark, host)
luci.http.prepare_content('application/json')
luci.http.write_json(e)
end
-- 刷新检测文件
function refresh_data()
local uci = luci.model.uci.cursor()
local set = luci.http.formvalue('set')
local icount = 0
local uci = luci.model.uci.cursor()
local set = luci.http.formvalue('set')
local icount = 0
if set == 'gfw_data' then
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
luci.sys.call('/usr/bin/vssr-gfw')
icount = luci.sys.exec('cat /tmp/gfwnew.txt | wc -l')
if tonumber(icount) > 1000 then
oldcount = luci.sys.exec('cat /etc/vssr/gfw_list.conf | wc -l')
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec('cp -f /tmp/gfwnew.txt /etc/vssr/gfw_list.conf')
retstring = tostring(math.ceil(tonumber(icount) / 2))
else
retstring = '0'
end
else
retstring = '-1'
end
luci.sys.exec('rm -f /tmp/gfwnew.txt ')
else
retstring = '-1'
end
elseif set == 'ip_data' then
local ip_data_url = uci:get('vssr', '@socks5_proxy[0]', 'ip_data_url')
refresh_cmd = "wget-ssl -O- '" .. ip_data_url .. "' > /tmp/china_ssr.txt 2>/dev/null"
sret = luci.sys.call(refresh_cmd)
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
if sret == 0 and tonumber(icount) > 1000 then
oldcount = luci.sys.exec('cat /etc/vssr/china_ssr.txt | wc -l')
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec('cp -f /tmp/china_ssr.txt /etc/vssr/china_ssr.txt')
retstring = tostring(tonumber(icount))
else
retstring = '0'
end
else
retstring = '-1'
end
luci.sys.exec('rm -f /tmp/china_ssr.txt ')
else
local need_process = 0
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
need_process = 1
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
if need_process == 1 then
luci.sys.call('/usr/bin/vssr-ad')
end
icount = luci.sys.exec('cat /tmp/ad.conf | wc -l')
if tonumber(icount) > 1000 then
if nixio.fs.access('/etc/vssr/ad.conf') then
oldcount = luci.sys.exec('cat /etc/vssr/ad.conf | wc -l')
else
oldcount = 0
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec('cp -f /tmp/ad.conf /etc/vssr/ad.conf')
retstring = tostring(math.ceil(tonumber(icount)))
if oldcount == 0 then
luci.sys.call('/etc/init.d/dnsmasq restart')
end
else
retstring = '0'
end
else
retstring = '-1'
end
luci.sys.exec('rm -f /tmp/ad.conf')
else
retstring = '-1'
end
end
luci.http.prepare_content('application/json')
luci.http.write_json({ret = retstring, retcount = icount})
if set == 'gfw_data' then
refresh_cmd = 'wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O /tmp/gfw.b64'
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
luci.sys.call('/usr/bin/vssr-gfw')
icount = luci.sys.exec('cat /tmp/gfwnew.txt | wc -l')
if tonumber(icount) > 1000 then
oldcount = luci.sys.exec('cat /etc/vssr/gfw_list.conf | wc -l')
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec('cp -f /tmp/gfwnew.txt /etc/vssr/gfw_list.conf')
retstring = tostring(math.ceil(tonumber(icount) / 2))
else
retstring = '0'
end
else
retstring = '-1'
end
luci.sys.exec('rm -f /tmp/gfwnew.txt ')
else
retstring = '-1'
end
elseif set == 'ip_data' then
local ip_data_url = uci:get("vssr", "@socks5_proxy[0]", "ip_data_url")
refresh_cmd = "wget-ssl -O- '" .. ip_data_url .. "' > /tmp/china_ssr.txt 2>/dev/null"
sret = luci.sys.call(refresh_cmd)
icount = luci.sys.exec('cat /tmp/china_ssr.txt | wc -l')
if sret == 0 and tonumber(icount) > 1000 then
oldcount = luci.sys.exec('cat /etc/vssr/china_ssr.txt | wc -l')
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec('cp -f /tmp/china_ssr.txt /etc/vssr/china_ssr.txt')
retstring = tostring(tonumber(icount))
else
retstring = '0'
end
else
retstring = '-1'
end
luci.sys.exec('rm -f /tmp/china_ssr.txt ')
else
local need_process = 0
refresh_cmd = 'wget-ssl --no-check-certificate -O - https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt > /tmp/adnew.conf'
need_process = 1
sret = luci.sys.call(refresh_cmd .. ' 2>/dev/null')
if sret == 0 then
if need_process == 1 then
luci.sys.call('/usr/bin/vssr-ad')
end
icount = luci.sys.exec('cat /tmp/ad.conf | wc -l')
if tonumber(icount) > 1000 then
if nixio.fs.access('/etc/vssr/ad.conf') then
oldcount = luci.sys.exec('cat /etc/vssr/ad.conf | wc -l')
else
oldcount = 0
end
if tonumber(icount) ~= tonumber(oldcount) then
luci.sys.exec('cp -f /tmp/ad.conf /etc/vssr/ad.conf')
retstring = tostring(math.ceil(tonumber(icount)))
if oldcount == 0 then
luci.sys.call('/etc/init.d/dnsmasq restart')
end
else
retstring = '0'
end
else
retstring = '-1'
end
luci.sys.exec('rm -f /tmp/ad.conf')
else
retstring = '-1'
end
end
luci.http.prepare_content('application/json')
luci.http.write_json({ret = retstring, retcount = icount})
end

View File

@ -354,7 +354,7 @@ start_shunt() {
ss | ssr)
bin=$(find_bin "ss-local")
[ "$server_type" == "ssr" ] && bin=$(find_bin "ssr-local")
g_threads=$threads
if [ "$shunt_type" != "global" ]; then
g_threads=1
@ -709,4 +709,4 @@ stop() {
del_cron
unset_lock
}
}