v1.7. New optional checking feature: URL test.

This commit is contained in:
gSpot
2025-10-08 22:42:15 +03:00
parent 87d28fb618
commit b69fcf0bb2
14 changed files with 332 additions and 94 deletions

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=internet-detector
PKG_VERSION:=1.6.7
PKG_VERSION:=1.7.0
PKG_RELEASE:=1
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>

View File

@@ -8,6 +8,7 @@ config instance 'internet'
option description 'Default instance'
list hosts '8.8.8.8'
list hosts '1.1.1.1'
list urls 'https://www.google.com'
option check_type '0'
option tcp_port '53'
option interval_up '30'

View File

@@ -12,32 +12,8 @@ local uci = require("uci")
-- Default settings
local InternetDetector = {
mode = 0, -- 0: disabled, 1: Service, 2: UI detector
loggingLevel = 6,
hostname = "OpenWrt",
appName = "internet-detector",
libDir = "/usr/lib/lua",
pingCmd = "/bin/ping",
pingParams = "-c 1",
uiRunTime = 30,
noModules = false,
uiAvailModules = { mod_public_ip = true },
debug = false,
serviceConfig = {
hosts = {
[1] = "8.8.8.8",
[2] = "1.1.1.1",
},
check_type = 0, -- 0: TCP, 1: ICMP
tcp_port = 53,
icmp_packet_size = 56,
interval_up = 30,
interval_down = 5,
connection_attempts = 2,
connection_timeout = 2,
iface = nil,
instance = nil,
},
logLevels = {
emerg = { level = syslog.LOG_EMERG, num = 0 },
alert = { level = syslog.LOG_ALERT, num = 1 },
@@ -48,8 +24,41 @@ local InternetDetector = {
info = { level = syslog.LOG_INFO, num = 6 },
debug = { level = syslog.LOG_DEBUG, num = 7 },
},
pingCmd = "/bin/ping",
pingParams = "-c 1",
curlExec = "/usr/bin/curl",
curlParams = '-s --no-keepalive --head --user-agent "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0"',
mode = 0, -- 0: disabled, 1: Service, 2: UI detector
loggingLevel = 6,
hostname = "OpenWrt",
uiRunTime = 30,
noModules = false,
uiAvailModules = { mod_public_ip = true },
debug = false,
serviceConfig = {
hosts = {
[1] = "8.8.8.8",
[2] = "1.1.1.1",
},
urls = {
[1] = "https://www.google.com",
},
check_type = 0, -- 0: TCP, 1: ICMP
tcp_port = 53,
icmp_packet_size = 56,
interval_up = 30,
interval_down = 5,
connection_attempts = 2,
connection_timeout = 2,
proxy_type = nil,
proxy_host = nil,
proxy_port = nil,
iface = nil,
instance = nil,
},
modules = {},
parsedHosts = {},
proxyString = "",
uiCounter = 0,
pidFile = nil,
statusFile = nil,
@@ -213,6 +222,13 @@ function InternetDetector:parseHosts()
end
end
function InternetDetector:parseUrls()
self.parsedHosts = {}
for k, v in ipairs(self.serviceConfig.urls) do
self.parsedHosts[k] = { addr = v }
end
end
function InternetDetector:pingHost(host)
local ping = string.format(
"%s %s -W %d -s %d%s %s > /dev/null 2>&1",
@@ -240,6 +256,7 @@ function InternetDetector:TCPConnectionToHost(host, port)
"GETADDRINFO ERROR: %s, %s", errMsg, errNum))
else
local family = saTable[1].family
if family then
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_STREAM, 0)
@@ -307,6 +324,60 @@ function InternetDetector:TCPConnectionToHost(host, port)
return retCode
end
function InternetDetector:httpRequest(url)
local retCode = 1, data
local curl = string.format(
'%s%s%s --connect-timeout %s %s "%s"; printf "\n$?";',
self.curlExec,
self.serviceConfig.iface and (" --interface " .. self.serviceConfig.iface) or "",
self.proxyString,
self.serviceConfig.connection_timeout,
self.curlParams,
url
)
local fh = io.popen(curl, "r")
if fh then
data = fh:read("*a")
fh:close()
if data ~= nil then
local s, e = data:find("[0-9]+\n?$")
retCode = tonumber(data:sub(s))
data = data:sub(0, s - 2)
if not data or data == "" then
data = nil
end
end
else
retCode = 1
end
self:debugOutput(string.format(
"--- Curl ---\ntime = %s\n%s\nretCode = %s\ndata = [\n%s]\n",
os.time(),
curl,
retCode,
tostring(data)))
return retCode, data
end
function InternetDetector:getHTTPCode(data)
local httpCode
local respHeader = data:match("^HTTP/[^%c]+")
if respHeader then
httpCode = respHeader:match("%d%d%d")
end
return tonumber(httpCode)
end
function InternetDetector:checkURL(url)
local httpCode
local retCode, data = self:httpRequest(url)
if retCode == 0 and data then
httpCode = self:getHTTPCode(data)
end
return (httpCode ~= 200) and 1 or 0
end
function InternetDetector:exit()
for _, e in ipairs(self.modules) do
e:onExit()
@@ -339,7 +410,25 @@ function InternetDetector:mainLoop()
local checking = false
local hostNum = 1
local attempt = 1
local checkFunc = (self.serviceConfig.check_type == 1) and self.pingHost or self.TCPConnectionToHost
local checkFunc = self.TCPConnectionToHost
if self.serviceConfig.check_type == 1 then
checkFunc = self.pingHost
self:parseHosts()
elseif self.serviceConfig.check_type == 2 then
checkFunc = self.checkURL
self:parseUrls()
if (self.serviceConfig.proxy_type and self.serviceConfig.proxy_host and
self.serviceConfig.proxy_port) then
self.proxyString = string.format(
" --proxy %s://%s:%d",
self.serviceConfig.proxy_type,
self.serviceConfig.proxy_host,
self.serviceConfig.proxy_port)
end
else
self:parseHosts()
end
self:writeValueToFile(
self.statusFile, self:statusJson(currentStatus, self.serviceConfig.instance))
@@ -599,6 +688,11 @@ function InternetDetector:preRun()
os.exit(1)
end
end
if self.serviceConfig.check_type == 2 and not unistd.access(self.curlExec, "x") then
io.stderr:write(string.format(
"Error, %s is not available. You need to install curl.\n", self.curlExec))
os.exit(1)
end
local ok, commonDir = pcall(dirent.files, self.commonDir)
if ok then
local instancePattern = "^" .. self.appNamePattern .. "%." .. self.serviceConfig.instance .. "%.[%d]+%.pid$"
@@ -689,7 +783,6 @@ end
function InternetDetector:setServiceConfig(instance)
if self:loadInstanceConfig(instance) then
self:parseHosts()
if self.mode == 2 then
self.loggingLevel = 0
self.noModules = true

View File

@@ -10,7 +10,10 @@ local Module = {
noModules = false,
debug = false,
serviceConfig = {
iface = nil,
iface = nil,
proxy_type = nil,
proxy_host = nil,
proxy_port = nil,
},
},
syslog = function(level, msg) return true end,
@@ -24,7 +27,7 @@ local Module = {
requestAttempts = 2,
timeout = 3,
curlExec = "/usr/bin/curl",
curlParams = "-s",
curlParams = '-s --no-keepalive --user-agent "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0"',
providers = {
opendns1 = {
name = "opendns1", type = "dns", host = "myip.opendns.com",
@@ -88,6 +91,7 @@ local Module = {
ipScript = "",
enableIpScript = false,
status = nil,
_proxyString = "",
_provider = nil,
_qtype = false,
_currentIp = nil,
@@ -177,6 +181,7 @@ function Module:sendUDPMessage(message, server, port)
"GETADDRINFO ERROR: %s, %s", errMsg, errNum))
else
local family = saTable[1].family
if family then
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_DGRAM, 0)
@@ -266,12 +271,13 @@ function Module:decodeMessage(message)
local NSCOUNT = message:sub(17, 20)
local ARCOUNT = message:sub(21, 24)
-- Question section
local questionSectionStarts = 25
local questionParts = self:parseParts(message, questionSectionStarts, {})
local qtypeStarts = questionSectionStarts + (#table.concat(questionParts)) + (#questionParts * 2) + 1
local qclassStarts = qtypeStarts + 4
-- Answer section
local answerSectionStarts = qclassStarts + 4
local numAnswers = math.max(
tonumber(ANCOUNT, 16), tonumber(NSCOUNT, 16), tonumber(ARCOUNT, 16))
@@ -351,9 +357,10 @@ end
function Module:httpRequest(url)
local retCode = 1, data
local curl = string.format(
'%s%s --connect-timeout %s %s "%s"; printf "\n$?";',
'%s%s%s --connect-timeout %s %s "%s"; printf "\n$?";',
self.curlExec,
self.config.serviceConfig.iface and (" --interface " .. self.config.serviceConfig.iface) or "",
self._proxyString,
self.timeout,
self.curlParams,
url
@@ -373,6 +380,14 @@ function Module:httpRequest(url)
else
retCode = 1
end
self.debugOutput(string.format(
"--- Curl ---\ntime = %s\n%s\nretCode = %s\ndata = [\n%s]\n",
os.time(),
curl,
retCode,
tostring(data))
)
return retCode, data
end
@@ -454,6 +469,15 @@ function Module:init(t)
self._enabled = false
end
end
if (self.config.serviceConfig.proxy_type and
self.config.serviceConfig.proxy_host and
self.config.serviceConfig.proxy_port) then
self._proxyString = string.format(
" --proxy %s://%s:%d",
self.config.serviceConfig.proxy_type,
self.config.serviceConfig.proxy_host,
self.config.serviceConfig.proxy_port)
end
end
function Module:run(currentStatus, lastStatus, timeDiff, timeNow, inetChecked)