1023 lines
32 KiB
Lua
Executable File
1023 lines
32 KiB
Lua
Executable File
#!/usr/bin/lua
|
|
|
|
local px = require "posix"
|
|
local uci = require 'luci.model.uci'
|
|
local util = require 'luci.util'
|
|
local io = require 'io'
|
|
local socket = require 'socket'
|
|
local json = require 'json'
|
|
local fs = require "nixio.fs"
|
|
local ubus = require "ubus"
|
|
|
|
local g_ubus
|
|
local g_cursor
|
|
local g_wan_busy_threshold = 100
|
|
local g_wan_busy_zero_num = 20
|
|
local g_speedtest_interval = 24*60*60
|
|
local g_current_date = 0
|
|
local g_current_day_trynum = 0
|
|
local g_current_day_num = 0
|
|
local g_nextmins_speedtest = 0
|
|
local g_lasttime_speedtest = 0
|
|
local g_ubus_wanup_msg = 1
|
|
local g_max_log_num = 0
|
|
local g_current_log_num = 0
|
|
local MAX_TRYNUM_PERDAY = 1
|
|
local MAX_NUM_PERDAY = 1
|
|
local MAX_BAND_ERROR = 0.7
|
|
local g_user_band_up = 0
|
|
local g_user_band_down = 0
|
|
local g_begin_time = "02:00"
|
|
local g_end_time = "06:00"
|
|
local g_debug_file_id = nil
|
|
local g_debug_file = false
|
|
local g_debug = false
|
|
local g_need_test_again = false
|
|
local TEST_AGAIN_TICKS = 180
|
|
|
|
local PREPARE_SPEEDTEST_XML_INTERVEL = 30
|
|
local g_prepare_speedtest_xml_cnter = 0
|
|
local g_prepare_speedtest_xml_last_try = 0
|
|
local g_prepare_speedtest_xml_trycnt = 0
|
|
|
|
local g_test_again_ticks = TEST_AGAIN_TICKS
|
|
|
|
local cfg = {
|
|
['host'] = "127.0.0.1",
|
|
['port'] = "1036",
|
|
['cmd_nettb'] = "/usr/sbin/nettb",
|
|
['cmd_upload'] = "/usr/bin/upload_speedtest",
|
|
['cmd_download'] = "/usr/bin/download_speedtest",
|
|
['cmd_speedtesturls'] = "/usr/bin/prepare_speedtest_xml",
|
|
['cmd_miqos_set'] = "/etc/init.d/miqos change_band ",
|
|
['cmd_miqos_get'] = "/etc/init.d/miqos show_band ",
|
|
['tmp_log'] = "/tmp/speedtest.log",
|
|
['cfg_file'] = "/etc/config/ab",
|
|
['tmp_cfg_dir'] = "/tmp/etc/config/",
|
|
['tmp_cfg_file'] = "/tmp/etc/config/ab",
|
|
['tmp_speedtest_xml'] = "/tmp/speedtest_urls.xml"
|
|
}
|
|
|
|
local SPEEDTEST_VER='STD'
|
|
if #arg >= 1 then
|
|
if arg[1] == 'oversea' then
|
|
SPEEDTEST_VER='OVERSEA'
|
|
end
|
|
end
|
|
|
|
function time_to_mins(stime)
|
|
local _,_,hour = string.find(stime, '([0-9]+):')
|
|
local _,_,min = string.find(stime, ':([0-9]+)')
|
|
|
|
return (60*tonumber(hour)+tonumber(min))
|
|
end
|
|
|
|
function mins_to_time(mins)
|
|
local hour,min = 0,0
|
|
min = mins%60
|
|
hour = (mins-min)/60
|
|
|
|
return string.format("%2d:%2d", hour, min)
|
|
end
|
|
|
|
function log_to_file(fileid, msg)
|
|
local file_size = fileid:seek("end")
|
|
|
|
if file_size > 1024*1024 then
|
|
return
|
|
end
|
|
fileid:write(os.date("%x %X").." : "..msg.."\n")
|
|
end
|
|
|
|
--logger
|
|
--[[1 Alert, 3 Error 7 Debug ]]--
|
|
px.openlog("speedtest","np",LOG_USER)
|
|
function logger(loglevel,msg)
|
|
if loglevel == 10 then
|
|
if g_debug then
|
|
px.syslog(3,msg)
|
|
if g_debug_file and g_debug_file_id then
|
|
log_to_file(g_debug_file_id, msg)
|
|
end
|
|
end
|
|
else
|
|
px.syslog(loglevel,msg)
|
|
end
|
|
end
|
|
|
|
function execl2(command)
|
|
local pp = io.popen(command)
|
|
local line = ""
|
|
local data = {}
|
|
|
|
while true do
|
|
line = pp:read()
|
|
if line == nil then
|
|
break
|
|
end
|
|
data[#data+1] = line
|
|
end
|
|
pp:close()
|
|
return data
|
|
end
|
|
|
|
-- 读取cfg到tmp的meory文件夹中
|
|
function cfg2tmp()
|
|
local r1,r2,r3 = fs.mkdirr(cfg.tmp_cfg_dir)
|
|
if not r1 then
|
|
logger(3, 'fatal error: mkdir failed, code:' .. r2 .. ',msg:'..r3)
|
|
return nil
|
|
end
|
|
|
|
r1,r2,r3 = fs.copy(cfg.cfg_file, cfg.tmp_cfg_file)
|
|
if not r1 then
|
|
logger(3,'fatal error: copy cfg file 2 /tmp memory failed. code:' .. r2 .. ',msg:'..r3)
|
|
return nil
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- 拷贝最新配置到memory中
|
|
function tmp2cfg()
|
|
if not fs.copy(cfg.tmp_cfg_file, cfg.cfg_file) then
|
|
logger(3,'fatal error: copy /tmp cfg file 2 /etc/config/ failed. exit.')
|
|
return nil
|
|
end
|
|
return true
|
|
end
|
|
|
|
function copytab(st)
|
|
local tab={}
|
|
for k,v in pairs(st or {}) do
|
|
if type(v) ~= 'table' then tab[k]=v
|
|
else tab[k]=copytab(v) end
|
|
end
|
|
return tab
|
|
end
|
|
|
|
function get_conf_std(conf,type,opt,default)
|
|
local x=uci.cursor()
|
|
local s,e = pcall(function() return x:get(conf,type,opt) end)
|
|
return e or default
|
|
end
|
|
|
|
-- execute command without anyoutput
|
|
function exec_cmd(tblist, ignore_error)
|
|
local status = 0
|
|
for _,v in pairs(tblist) do
|
|
local cmd = v
|
|
|
|
if g_debug then
|
|
logger(3, '++' .. cmd)
|
|
cmd = cmd .. ' >/dev/null 2>>' .. cfg.tmp_log
|
|
else
|
|
cmd = cmd .. " &>/dev/null "
|
|
end
|
|
|
|
if os.execute(cmd) ~= 0 and ignore_error ~= 1 then
|
|
if g_debug then
|
|
os.execute('echo "^^^ '.. cmd .. ' ^^^ " >>' .. cfg.tmp_log)
|
|
end
|
|
logger(3, '[ERROR]: ' .. cmd .. ' failed!')
|
|
dump_qdisc()
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
--split string with chars '$p'
|
|
string.split = function(s, p)
|
|
local rt= {}
|
|
string.gsub(s, '[^'..p..']+', function(w) table.insert(rt, w) end )
|
|
return rt
|
|
end
|
|
|
|
function system_exit()
|
|
logger(3,'======== Process Exit. =====')
|
|
|
|
if g_debug_file_id then
|
|
g_debug_file_id:flush()
|
|
g_debug_file_id:close()
|
|
end
|
|
os.exit()
|
|
end
|
|
|
|
function system_init()
|
|
if g_debug then
|
|
os.execute("echo auto speedtest starting..... >>" .. cfg.tmp_log)
|
|
end
|
|
|
|
if g_debug and g_debug_file then
|
|
g_debug_file_id = io.open(cfg.tmp_log, "a")
|
|
end
|
|
|
|
-- 将配置文件copy到tmp内存中,并初始化cursor
|
|
--[[ if not cfg2tmp() then
|
|
return false
|
|
end
|
|
--]]
|
|
|
|
g_cursor = uci.cursor()
|
|
if not g_cursor then
|
|
logger(3,'set uci cursor failed. exit.')
|
|
return false
|
|
end
|
|
|
|
if is_user_band_manual() then
|
|
g_user_band_up = 1
|
|
g_user_band_down = 1
|
|
logger(10,'user set band manual!')
|
|
else
|
|
logger(10,'user didnt set band manual!')
|
|
end
|
|
--[[
|
|
if not g_cursor:set_confdir(cfg.tmp_cfg_dir) then
|
|
logger(3,'set tmp config dir failed. exit.')
|
|
return false
|
|
end
|
|
--]]
|
|
g_ubus = ubus.connect()
|
|
if not g_ubus then
|
|
logger(3, 'failed to connect to ubusd!')
|
|
return false
|
|
end
|
|
|
|
logger(10, "************ auto speedtest startup **************")
|
|
g_current_date = tonumber(os.date("%d"))
|
|
g_nextmins_speedtest = get_nexttime_speedtest()
|
|
|
|
local lasttime = g_cursor:get("ab","settings","last_speedtest_time")
|
|
g_lasttime_speedtest = tonumber(lasttime)
|
|
|
|
local maxlog = g_cursor:get("ab","settings","max_log_num")
|
|
g_max_log_num = tonumber(maxlog)
|
|
|
|
local curntlog = g_cursor:get("ab","settings","current_log_num")
|
|
g_current_log_num = tonumber(curntlog)
|
|
|
|
if g_current_log_num > g_max_log_num then
|
|
g_current_log_num = 1
|
|
end
|
|
|
|
logger(10, "init get lasttime: "..lasttime.." lastdate: "..os.date("%x %X", g_lasttime_speedtest))
|
|
logger(10, "max log num: "..g_max_log_num.." current log num: "..g_current_log_num)
|
|
|
|
-- SIGTERM to clear and exit
|
|
px.signal(px.SIGTERM,
|
|
function ()
|
|
logger(3,'signal TERM to stop auto speed test.')
|
|
system_exit()
|
|
end)
|
|
|
|
px.signal(px.SIGINT,
|
|
function ()
|
|
logger(3,'signal INT to stop auto speed test.')
|
|
system_exit()
|
|
end)
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
function get_list_wan_rate()
|
|
local ret = g_ubus:call("trafficd", "list_wan_rate", {})
|
|
|
|
if ret and ret.rate then
|
|
return ret.rate
|
|
end
|
|
|
|
return nil;
|
|
end
|
|
|
|
function get_lasttime_speedtest()
|
|
return g_lasttime_speedtest
|
|
end
|
|
|
|
function set_lasttime_speedtest()
|
|
g_lasttime_speedtest = os.time()
|
|
|
|
local date = string.format("%s", os.date("%x %X", g_lasttime_speedtest))
|
|
|
|
g_cursor:set("ab","settings","last_speedtest_date",date)
|
|
g_cursor:set("ab","settings","last_speedtest_time",tostring(g_lasttime_speedtest))
|
|
g_cursor:commit('ab')
|
|
logger(10, "set lasttime: "..g_lasttime_speedtest.." lastdate: "..os.date("%x %X", g_lasttime_speedtest))
|
|
end
|
|
|
|
-- choose a ramdom time between g_begin_time and g_end_time,
|
|
-- in case all routers start speedtest at the same moment
|
|
function get_nexttime_speedtest()
|
|
local start_mins = time_to_mins(g_begin_time)
|
|
local end_mins = time_to_mins(g_end_time)
|
|
|
|
math.randomseed(os.time())
|
|
local next_mins = math.random(start_mins, end_mins)
|
|
|
|
logger(10, "start mins: "..g_begin_time.." "..time_to_mins(g_begin_time))
|
|
logger(10, "end mins: "..g_end_time.." "..time_to_mins(g_end_time))
|
|
logger(10, "next mins: "..mins_to_time(next_mins).." "..next_mins)
|
|
|
|
return next_mins
|
|
end
|
|
|
|
--if speed test failed this time, we choose another time between now time and end time
|
|
function get_nexttime_case_fail()
|
|
local start_mins = time_to_mins(g_begin_time)
|
|
local end_mins = time_to_mins(g_end_time)
|
|
|
|
local date = os.date("%X")
|
|
local _,_,hour = string.find(date, '^([0-9]+):')
|
|
local _,_,min = string.find(date, '^[0-9]+:([0-9]+):')
|
|
local now_mins = 60*hour + min
|
|
|
|
if (now_mins > start_mins) and (now_mins < end_mins) then
|
|
start_mins = now_mins
|
|
end
|
|
|
|
math.randomseed(os.time())
|
|
local next_mins = math.random(start_mins, end_mins)
|
|
|
|
logger(10, "start mins: "..g_begin_time.." "..time_to_mins(g_begin_time))
|
|
logger(10, "end mins: "..g_end_time.." "..time_to_mins(g_end_time))
|
|
logger(10, "now mins: "..mins_to_time(now_mins).." "..now_mins)
|
|
logger(10, "next mins: "..mins_to_time(next_mins).." "..next_mins)
|
|
|
|
return next_mins
|
|
end
|
|
|
|
function uci_commit_save(flag)
|
|
if flag then
|
|
g_cursor:commit('ab')
|
|
|
|
-- tmp下的配置改变,复写回/etc下
|
|
--[[ if not tmp2cfg() then
|
|
logger(1, 'copy tmp cfg to /etc/config/ failed.')
|
|
end
|
|
--]]
|
|
end
|
|
end
|
|
|
|
function get_uptime()
|
|
local upt=io.open('/proc/uptime')
|
|
local n=upt:read('*n')
|
|
upt:close()
|
|
return math.ceil(n)
|
|
end
|
|
|
|
function newset()
|
|
local reverse = {}
|
|
local set = {}
|
|
return setmetatable(set, {__index = {
|
|
insert = function(set, value)
|
|
if not reverse[value] then
|
|
table.insert(set, value)
|
|
reverse[value] = table.getn(set)
|
|
end
|
|
end,
|
|
remove = function(set, value)
|
|
local index = reverse[value]
|
|
if index then
|
|
reverse[value] = nil
|
|
local top = table.remove(set)
|
|
if top ~= value then
|
|
reverse[top] = index
|
|
set[index] = top
|
|
end
|
|
end
|
|
end
|
|
}})
|
|
end
|
|
|
|
function is_user_band_manual()
|
|
local manual = g_cursor:get("xiaoqiang","common","MANUAL")
|
|
if manual then
|
|
local ucfg = tonumber(manual)
|
|
if ucfg and ucfg == 1 then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
function is_lasttest_long_enough()
|
|
local last_time = get_lasttime_speedtest()
|
|
local now_time = os.time()
|
|
local year2000 = os.time{year=2000, month=1,day=1,hour=0}
|
|
|
|
if now_time < year2000 then
|
|
logger(10, "NTP is not ready now time: "..os.date("%x %X",now_time))
|
|
return false
|
|
end
|
|
|
|
if last_time == 0 then
|
|
logger(10, "Long enough now time: "..os.date("%x %X",now_time).." last time: "..os.date("%x %X",last_time))
|
|
return true
|
|
end
|
|
|
|
if (last_time+g_speedtest_interval) < now_time then
|
|
logger(10, "Long enough now time: "..os.date("%x %X",now_time).." last time: "..os.date("%x %X",last_time))
|
|
return true
|
|
end
|
|
|
|
logger(10, "Not long enough now time: "..os.date("%x %X",now_time).." last time: "..os.date("%x %X",last_time))
|
|
return false
|
|
end
|
|
|
|
function is_wan_busy()
|
|
local sum,avg,max,zeronum,min = 0,0,0,0,9999999
|
|
local listrate = get_list_wan_rate()
|
|
|
|
if listrate and #listrate ~= 0 then
|
|
for k,v in ipairs(listrate) do
|
|
if v > max then
|
|
max = v
|
|
end
|
|
|
|
if v < min then
|
|
min = v
|
|
end
|
|
|
|
if v==0 then
|
|
zeronum = zeronum+1
|
|
end
|
|
sum = sum + v
|
|
logger(10, k..": "..v)
|
|
end
|
|
|
|
avg = sum/#listrate
|
|
logger(10, "is_wan_busy: avg: "..avg.." max: "..max.." min: "..min.." zeronum: "..zeronum)
|
|
|
|
if (avg < g_wan_busy_threshold) and (zeronum >= g_wan_busy_zero_num)then
|
|
return false
|
|
else
|
|
logger(3, "stat_points_privacy network_speedtest=2|wanbusy|"..os.date("%x %X").."|"..avg.."|"..max.."|"..min.."|"..zeronum)
|
|
logger(10, "dotdata: network_speedtest=2|wanbusy|"..os.date("%x %X").."|"..avg.."|"..max.."|"..min.."|"..zeronum)
|
|
return true
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function is_just_power_up()
|
|
local start_time = get_uptime()
|
|
|
|
if start_time < 160 then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function is_time_to_speedtest()
|
|
local date = os.date("%X")
|
|
local _,_,hour = string.find(date, '^([0-9]+):')
|
|
local _,_,min = string.find(date, '^[0-9]+:([0-9]+):')
|
|
local now_mins = 60*tonumber(hour) + tonumber(min)
|
|
|
|
if (now_mins >= g_nextmins_speedtest) and (now_mins <= time_to_mins(g_end_time)) then
|
|
return true
|
|
end
|
|
|
|
logger(10, "Not time for speedtest now: "..date.." begin: "..g_begin_time.." end: "..g_end_time.." next: "..mins_to_time(g_nextmins_speedtest))
|
|
return false
|
|
end
|
|
|
|
function is_internet_connected()
|
|
local cmd = cfg.cmd_nettb
|
|
local res = execl2(cmd)
|
|
|
|
if next(res)~=nil then
|
|
for k,v in pairs(res) do
|
|
logger(10, "got nettb info: "..v)
|
|
end
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
function is_band_result_valid(new_up, new_down, old_up, old_down, flag)
|
|
|
|
if flag == 3 then
|
|
return true
|
|
end
|
|
|
|
if (new_up > 32) and (new_down > 128) then
|
|
|
|
logger(10, "band result valid!")
|
|
logger(10, "old_up: "..old_up.." old_down: "..old_down)
|
|
logger(10, "new_up: "..new_up.." new_down: "..new_down)
|
|
return true
|
|
end
|
|
|
|
logger(10, "band result invalid!")
|
|
logger(10, "old_up: "..old_up.." old_down: "..old_down)
|
|
logger(10, "new_up: "..new_up.." new_down: "..new_down)
|
|
logger(3, "stat_points_privacy network_speedtest="..flag.."|banderr|"..os.date("%x %X").."|"..old_up.."|"..old_down.."|"..new_up.."|"..new_down)
|
|
logger(10, "dotdata: network_speedtest="..flag.."|banderr|"..os.date("%x %X").."|"..old_up.."|"..old_down.."|"..new_up.."|"..new_down)
|
|
return false
|
|
end
|
|
|
|
-- if band result is unacceptable, we do speed test again after 1 hour
|
|
function is_band_result_acceptable(new_up, new_down, old_up, old_down, flag)
|
|
|
|
if flag == 3 then
|
|
return true
|
|
end
|
|
|
|
if (new_up > 0.5*old_up) and (new_down > 0.5*old_down) then
|
|
|
|
logger(10, "band result acceptable!")
|
|
logger(10, "old_up: "..old_up.." old_down: "..old_down)
|
|
logger(10, "new_up: "..new_up.." new_down: "..new_down)
|
|
return true
|
|
end
|
|
|
|
logger(10, "band result unacceptable!")
|
|
logger(10, "old_up: "..old_up.." old_down: "..old_down)
|
|
logger(10, "new_up: "..new_up.." new_down: "..new_down)
|
|
logger(3, "stat_points_privacy network_speedtest="..flag.."|banderr|"..os.date("%x %X").."|"..old_up.."|"..old_down.."|"..new_up.."|"..new_down)
|
|
logger(10, "dotdata: network_speedtest="..flag.."|banderr|"..os.date("%x %X").."|"..old_up.."|"..old_down.."|"..new_up.."|"..new_down)
|
|
return false
|
|
end
|
|
|
|
function get_miqosband()
|
|
local upband, downband = 0, 0
|
|
local cmd = cfg.cmd_miqos_get
|
|
local res = execl2(cmd)
|
|
|
|
logger(10, cmd)
|
|
if res and next(res)~=nil then
|
|
for k,v in ipairs(res) do
|
|
local _,_,tmp = string.find(v, 'status=([0-9]+)')
|
|
local _,_,up = string.find(v, 'uplink=([0-9]+%.?[0-9]+)')
|
|
local _,_,down = string.find(v, 'downlink=([0-9]+%.?[0-9]+)')
|
|
|
|
if tmp then
|
|
status = tonumber(tmp)
|
|
end
|
|
|
|
if up then
|
|
upband = tonumber(up)
|
|
end
|
|
|
|
if down then
|
|
downband = tonumber(down)
|
|
end
|
|
end
|
|
|
|
if status == 0 then
|
|
--logger(10, "Get miqos band up: "..upband.." down: "..downband)
|
|
return upband, downband
|
|
end
|
|
end
|
|
|
|
--logger(10, "Get miqos band up: 0 down: 0")
|
|
return 0, 0
|
|
end
|
|
|
|
function set_miqosband(up_band, down_band, flag)
|
|
local cmd = cfg.cmd_miqos_set.." "..up_band.." "..down_band
|
|
local res = execl2(cmd)
|
|
local status = 1
|
|
|
|
logger(10, cmd)
|
|
if res and next(res)~=nil then
|
|
for k,v in ipairs(res) do
|
|
local _,_,tmp = string.find(v, 'status=([0-9]+)')
|
|
if tmp then
|
|
status = tonumber(tmp)
|
|
end
|
|
end
|
|
|
|
if status == 0 then
|
|
logger(10, "set miqos band succeed!")
|
|
|
|
local info = os.date("%x %X: ").."flag: "..flag.." up: "..up_band.." down: "..down_band
|
|
if g_current_log_num > g_max_log_num then
|
|
g_current_log_num = 1
|
|
end
|
|
g_cursor:set("ab","settings","log"..g_current_log_num, info)
|
|
g_current_log_num = g_current_log_num + 1
|
|
g_cursor:set("ab","settings","current_log_num", g_current_log_num)
|
|
g_cursor:commit('ab')
|
|
|
|
set_lasttime_speedtest()
|
|
if not is_user_band_manual() then
|
|
local tmpup = string.format("%.2f", up_band/1024)
|
|
local tmpdown = string.format("%.2f", down_band/1024)
|
|
g_cursor:set("xiaoqiang","common","BANDWIDTH2", tmpup)
|
|
g_cursor:set("xiaoqiang","common","BANDWIDTH", tmpdown)
|
|
g_cursor:commit('xiaoqiang')
|
|
logger(10, "set xiaoqiang band up: "..tmpup.." down: "..tmpdown)
|
|
else
|
|
logger(10, "user band manual,dont set xiaoqiang config")
|
|
end
|
|
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function do_speed_test_upload()
|
|
local cmd = cfg.cmd_upload
|
|
local res = execl2(cmd)
|
|
local band = 0
|
|
|
|
if next(res)~=nil then
|
|
for k,v in pairs(res) do
|
|
local _,_,tmp = string.find(v, 'tx:([0-9]+%.[0-9]+)')
|
|
if tmp then
|
|
band = tonumber(tmp) or 0
|
|
end
|
|
--logger(10, "got upload info: "..v)
|
|
end
|
|
--logger(10,"got up band: "..band)
|
|
return band
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
function do_speed_test_download()
|
|
local cmd = cfg.cmd_download
|
|
local res = execl2(cmd)
|
|
local band = 0
|
|
|
|
if next(res)~=nil then
|
|
for k,v in pairs(res) do
|
|
local _,_,tmp = string.find(v, 'rx:([0-9]+%.[0-9]+)')
|
|
if tmp then
|
|
band = tonumber(tmp) or 0
|
|
end
|
|
--logger(10, "got download info: "..v)
|
|
end
|
|
--logger(10,"got down band: "..band)
|
|
return band
|
|
else
|
|
return 0
|
|
end
|
|
end
|
|
|
|
--flag: 1.speedtest when power on 2.speedtest when time up 3.speedtest on cmd
|
|
-- 4.speedtest again in 1 hour if last band result unacceptable
|
|
--return 1 means failed, return 0 means succeed
|
|
function do_speed_test(flag)
|
|
local upband,downband = 0,0
|
|
|
|
logger(10, "do speed test!")
|
|
|
|
local miqos_upband,miqos_downband = get_miqosband()
|
|
|
|
if flag ~= 3 then
|
|
if miqos_upband==0 or miqos_downband==0 then
|
|
-- logger(3, "stat_points_privacy network_speedtest="..flag.."|miqosinvalid|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|0|0")
|
|
logger(10, "network_speedtest="..flag.."|miqosinvalid|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|0|0")
|
|
-- return 1
|
|
end
|
|
end
|
|
|
|
os.execute("/etc/init.d/miqos stop")
|
|
downband = do_speed_test_download()
|
|
upband = do_speed_test_upload()
|
|
os.execute("/etc/init.d/miqos start")
|
|
|
|
logger(10, "test upband: "..upband.." test downband: "..downband)
|
|
logger(10, "miqos upband: "..miqos_upband.." miqos downband: "..miqos_downband)
|
|
|
|
if upband==0 or downband==0 then
|
|
logger(10, "speedtest or miqos band invalid!")
|
|
if flag ~= 3 then
|
|
logger(3, "stat_points_privacy network_speedtest="..flag.."|bandinvalid|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
logger(10, "dotdata: network_speedtest="..flag.."|bandinvalid|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
end
|
|
return 1
|
|
else
|
|
if is_band_result_valid(upband,downband,miqos_upband,miqos_downband,flag) then
|
|
if flag == 4 or flag == 3 then
|
|
local res = set_miqosband(upband, downband, flag)
|
|
if res then
|
|
logger(3, "stat_points_privacy network_speedtest="..flag.."|success|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
logger(10, "dotdata: network_speedtest="..flag.."|success|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
return 0
|
|
else
|
|
if flag~= 3 then
|
|
logger(3, "stat_points_privacy network_speedtest="..flag.."|miqoserr1|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
logger(10, "dotdata: network_speedtest="..flag.."|miqoserr1|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
end
|
|
return 1
|
|
end
|
|
else
|
|
if is_band_result_acceptable(upband,downband,miqos_upband,miqos_downband,flag) then
|
|
local res = set_miqosband(upband, downband, flag)
|
|
if res then
|
|
logger(3, "stat_points_privacy network_speedtest="..flag.."|success|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
logger(10, "dotdata: network_speedtest="..flag.."|success|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
return 0
|
|
else
|
|
logger(3, "stat_points_privacy network_speedtest="..flag.."|miqoserr1|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
logger(10, "dotdata: network_speedtest="..flag.."|miqoserr1|"..os.date("%x %X").."|"..miqos_upband.."|"..miqos_downband.."|"..upband.."|"..downband)
|
|
return 1
|
|
end
|
|
else
|
|
g_need_test_again = true
|
|
g_test_again_ticks = TEST_AGAIN_TICKS
|
|
logger(10, "band result unacceptable, test again 1 hour later!")
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return 1
|
|
end
|
|
|
|
function speedtest_by_cmd()
|
|
|
|
if (g_user_band_down ~= 0) or (g_user_band_up ~= 0) then
|
|
logger(10, "speedtest cmd user band is not zero: "..g_user_band_up.." "..g_user_band_down..", do nothing!")
|
|
return 1
|
|
end
|
|
|
|
if not is_internet_connected() then
|
|
logger(10, "speedtest cmd Internet is not connected, do nothing!")
|
|
return 2
|
|
end
|
|
|
|
local res = do_speed_test(3)
|
|
return res
|
|
end
|
|
|
|
|
|
function try_speedtest()
|
|
|
|
if (g_user_band_down ~= 0) or (g_user_band_up ~= 0) then
|
|
logger(10, "user band is not zero: "..g_user_band_up.." "..g_user_band_down..", do nothing!")
|
|
return
|
|
end
|
|
|
|
if not is_lasttest_long_enough() then
|
|
return
|
|
end
|
|
|
|
if (g_current_day_num >= MAX_NUM_PERDAY) or (g_current_day_trynum >= MAX_TRYNUM_PERDAY)then
|
|
logger(10, "Exceed max num perday! cur: "..g_current_day_num.."("..MAX_NUM_PERDAY..") trycur: "..g_current_day_trynum.."("..MAX_TRYNUM_PERDAY..")")
|
|
return
|
|
end
|
|
|
|
-- during the just startup time, we dont detect if wan is busy
|
|
if g_ubus_wanup_msg == 1 and is_just_power_up() then
|
|
if not is_internet_connected() then
|
|
logger(10, "Wanup but Internet is not connected, do nothing!")
|
|
return
|
|
end
|
|
logger(10, "Got wan up msg, do speed test!")
|
|
g_ubus_wanup_msg = 0
|
|
do_speed_test(1)
|
|
g_current_day_num = g_current_day_num +1
|
|
return
|
|
end
|
|
|
|
if is_time_to_speedtest() then
|
|
if not is_internet_connected() then
|
|
logger(10, "Internet is not connected, do nothing!")
|
|
logger(3, "stat_points_privacy network_speedtest=2|uninternet|"..os.date("%x %X"))
|
|
logger(10, "dotdata: network_speedtest=2|uninternet|"..os.date("%x %X"))
|
|
g_current_day_trynum = g_current_day_trynum + 1
|
|
return
|
|
end
|
|
|
|
if is_wan_busy() then
|
|
g_current_day_trynum = g_current_day_trynum + 1
|
|
logger(10, "Wan is busy, do nothing! ")
|
|
g_nextmins_speedtest = get_nexttime_speedtest()
|
|
else
|
|
logger(10, "Wan is free, do speed test!")
|
|
do_speed_test(2)
|
|
g_current_day_num = g_current_day_num +1
|
|
g_nextmins_speedtest = get_nexttime_speedtest()
|
|
end
|
|
end
|
|
end
|
|
|
|
--if last band result unacceptable, we do speed test again in 1 hour
|
|
function try_speedtest_again()
|
|
|
|
if (g_user_band_down ~= 0) or (g_user_band_up ~= 0) then
|
|
logger(10, "user band is not zero: "..g_user_band_up.." "..g_user_band_down..", do nothing!")
|
|
return
|
|
end
|
|
|
|
if true then
|
|
if not is_internet_connected() then
|
|
logger(10, "Internet is not connected, do nothing!")
|
|
logger(3, "stat_points_privacy network_speedtest=2|uninternet|"..os.date("%x %X"))
|
|
logger(10, "dotdata: network_speedtest=2|uninternet|"..os.date("%x %X"))
|
|
return
|
|
end
|
|
|
|
if is_wan_busy() then
|
|
logger(10, "Wan is busy, do nothing! ")
|
|
else
|
|
logger(10, "Wan is free, do speed test!")
|
|
do_speed_test(4)
|
|
end
|
|
end
|
|
end
|
|
|
|
function prepare_speedtest_urls()
|
|
local cmd = cfg.cmd_speedtesturls
|
|
|
|
if g_prepare_speedtest_xml_trycnt > 3 then
|
|
logger(10, "try num is enough do nothing: "..g_prepare_speedtest_xml_trycnt)
|
|
return
|
|
end
|
|
|
|
g_prepare_speedtest_xml_cnter = g_prepare_speedtest_xml_cnter + 1
|
|
if SPEEDTEST_VER ~= "OVERSEA" then
|
|
logger(10, "prepare urls is not oerversea version !")
|
|
return
|
|
end
|
|
|
|
filexml = io.open(cfg.tmp_speedtest_xml)
|
|
if filexml then
|
|
filexml:close()
|
|
logger(10, "prepare urls already got url xml !")
|
|
return
|
|
end
|
|
|
|
if not is_internet_connected() then
|
|
logger(10, "prepare urls Internet is not connected, do nothing!")
|
|
return
|
|
end
|
|
|
|
if g_prepare_speedtest_xml_trycnt ~= 0 then
|
|
if g_prepare_speedtest_xml_cnter - g_prepare_speedtest_xml_last_try < PREPARE_SPEEDTEST_XML_INTERVEL then
|
|
logger(10, "its not time for getting xml cnter: "..g_prepare_speedtest_xml_cnter.." last: "..g_prepare_speedtest_xml_last_try)
|
|
return
|
|
end
|
|
end
|
|
|
|
g_prepare_speedtest_xml_trycnt = g_prepare_speedtest_xml_trycnt + 1
|
|
g_prepare_speedtest_xml_last_try = g_prepare_speedtest_xml_cnter
|
|
logger(3, "start getting speedtest url xml !")
|
|
local res = execl2(cmd)
|
|
filexml = io.open(cfg.tmp_speedtest_xml)
|
|
if filexml then
|
|
filexml:close()
|
|
logger(3, "get speedtest url xml ok!")
|
|
else
|
|
logger(3, "get speedtest url xml failed!")
|
|
end
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- loop work for speed test
|
|
-----------------------------------------------------------------------------
|
|
function main_loop()
|
|
|
|
local server = assert(socket.bind(cfg.host, cfg.port))
|
|
server:settimeout(1)
|
|
|
|
-- tables f
|
|
local set=newset()
|
|
set:insert(server) -- add 'server' into select events
|
|
|
|
local gc_timer=0
|
|
while true do
|
|
logger(10, "--------- main loop ---------")
|
|
local readable, _, error = socket.select(set, nil , 20)
|
|
gc_timer = gc_timer + 1
|
|
if gc_timer >= 20 then
|
|
gc_timer = 0
|
|
local tmp_cnt = collectgarbage("count")
|
|
logger(10, "LUA GC count: " .. tmp_cnt)
|
|
tmp_cnt = collectgarbage("collect")
|
|
logger(10, "LUA GC collect: " .. tmp_cnt)
|
|
end
|
|
|
|
for _,v in ipairs(readable) do
|
|
|
|
if v == server then
|
|
logger(3, 'new client come in ...')
|
|
local clt=v:accept()
|
|
if clt then
|
|
clt:settimeout(1)
|
|
set:insert(clt)
|
|
else
|
|
logger(3, 'accept client error.')
|
|
end
|
|
else
|
|
local data,error = v:receive()
|
|
|
|
if error then
|
|
v:close()
|
|
logger(3, 'client is disconnected.')
|
|
set:remove(v)
|
|
else
|
|
local args=string.split(data,' ')
|
|
if not args[1] then
|
|
v:send(json.encode({status=3}))
|
|
else
|
|
logger(10, "Recv cmd: "..args[1])
|
|
if args[1] == 'status' then
|
|
logger(3,'======== COMMAND status============')
|
|
local stats = string.format("\ng_begin_time : %s\n",g_begin_time)
|
|
stats = stats..string.format("g_end_time : %s\n",g_end_time)
|
|
stats = stats..string.format("g_lasttime_speedtest : %s\n",os.date("%x %X", g_lasttime_speedtest))
|
|
stats = stats..string.format("g_nextmins_speedtest : %s\n",mins_to_time(g_nextmins_speedtest))
|
|
stats = stats..string.format("g_current_date : %d\n",g_current_date)
|
|
stats = stats..string.format("g_current_day_trynum : %d\n",g_current_day_trynum)
|
|
stats = stats..string.format("g_current_day_num : %d\n",g_current_day_num)
|
|
stats = stats..string.format("g_max_log_num : %d\n",g_max_log_num)
|
|
stats = stats..string.format("g_current_log_num : %d\n",g_current_log_num)
|
|
stats = stats..string.format("g_user_band_up : %d\n",g_user_band_up)
|
|
stats = stats..string.format("g_user_band_down : %d\n",g_user_band_down)
|
|
|
|
v:send(json.encode({status=2,data=stats}))
|
|
elseif args[1] == 'stop' then
|
|
logger(3,'======== COMMAND stop ============')
|
|
v:send(json.encode({status=0}) .. "\n")
|
|
v:close()
|
|
system_exit() -- exit system
|
|
elseif args[1] == 'wan_up' then
|
|
logger(3,'======== COMMAND wan_up============')
|
|
g_ubus_wanup_msg = 1
|
|
v:send(json.encode({status=0}) .. "\n")
|
|
elseif args[1] == 'debug_on' then
|
|
logger(3,'======== COMMAND debug_on============')
|
|
g_debug = true
|
|
v:send(json.encode({status=0}) .. "\n")
|
|
elseif args[1] == 'debug_off' then
|
|
logger(3,'======== COMMAND debug_off============')
|
|
g_debug = false
|
|
v:send(json.encode({status=0}) .. "\n")
|
|
elseif args[1] == 'do_speedtest' then
|
|
logger(3,'======== COMMAND do_speedtest============')
|
|
local res = speedtest_by_cmd()
|
|
v:send(json.encode({status=res}) .. "\n")
|
|
elseif args[1] == 'set_userband' then
|
|
logger(3,'======== COMMAND set_userband============')
|
|
g_user_band_up = tonumber(args[2]) or 0
|
|
g_user_band_down = tonumber(args[3]) or 0
|
|
v:send(json.encode({status=0}) .. "\n")
|
|
elseif args[1] == 'next_time' then
|
|
logger(3,'======== COMMAND nexttime============')
|
|
g_nextmins_speedtest = time_to_mins(args[2])
|
|
v:send(json.encode({status=0, data=args[2].." "..g_nextmins_speedtest}) .. "\n")
|
|
else
|
|
v:send(json.encode({status=2,data='Not supported command.'}))
|
|
end
|
|
end
|
|
|
|
v:send('\n')
|
|
v:close()
|
|
set:remove(v)
|
|
end
|
|
end
|
|
end
|
|
|
|
prepare_speedtest_urls()
|
|
local date = tonumber(os.date("%d"))
|
|
if g_current_date ~= date then
|
|
logger(10, "date change from "..g_current_date.." to "..date)
|
|
g_current_day_trynum = 0
|
|
g_current_day_num = 0
|
|
g_current_date = date
|
|
end
|
|
|
|
if g_need_test_again then
|
|
if g_test_again_ticks > 1 then
|
|
g_test_again_ticks = g_test_again_ticks - 1
|
|
logger(10, "test again ticks left: "..g_test_again_ticks)
|
|
else
|
|
g_need_test_again = false
|
|
g_test_again_ticks = TEST_AGAIN_TICKS
|
|
logger(10, "try speed test again! ")
|
|
try_speedtest_again()
|
|
end
|
|
|
|
end
|
|
try_speedtest()
|
|
end
|
|
end
|
|
|
|
function main()
|
|
if system_init() then
|
|
local s, e = pcall(function() main_loop() end)
|
|
if not s
|
|
then
|
|
logger(3,e)
|
|
print("pcall exit!")
|
|
end
|
|
else
|
|
print("system initial failed. exit.")
|
|
logger(3, 'system initial failed. exit.')
|
|
end
|
|
end
|
|
|
|
main()
|
|
|