Răsfoiți Sursa

Fix luv.run() pcall syntax error

Gogs 2 luni în urmă
părinte
comite
765cb4f628
1 a modificat fișierele cu 75 adăugiri și 79 ștergeri
  1. 75 79
      usr/sbin/client2server-luv.lua

+ 75 - 79
usr/sbin/client2server-luv.lua

@@ -1,6 +1,6 @@
 --[[
     client2server-luv - Lua WebSocket Event Forwarder for OpenWrt with luv async
-    
+
     Features:
     - WebSocket connection to central server
     - Auto-reconnect on disconnect
@@ -8,7 +8,7 @@
     - DHCP/WiFi/Interface event tracking
     - ASYNC monitoring via luv (libuv bindings)
     - Parallel polling for 50+ devices
-    
+
     Copyright (c) 2026 Luis Rosales - MIT License
 ]]
 
@@ -112,7 +112,7 @@ local buffer = {
 function buffer.load()
     local f = io.open(cfg.buffer_file, "r")
     if not f then return end
-    
+
     for line in f:lines() do
         if line and line ~= "" then
             table.insert(buffer.events, line)
@@ -125,7 +125,7 @@ end
 function buffer.save()
     local f = io.open(cfg.buffer_file, "w")
     if not f then return end
-    
+
     for _, event in ipairs(buffer.events) do
         f:write(event .. "\n")
     end
@@ -135,22 +135,22 @@ end
 
 function buffer.add(json_event)
     table.insert(buffer.events, json_event)
-    
+
     -- Limit buffer size
     while #buffer.events > cfg.max_buffer do
         table.remove(buffer.events, 1)
     end
-    
+
     buffer.dirty = true
 end
 
 function buffer.flush(send_fn)
     if #buffer.events == 0 then return end
-    
+
     local to_send = buffer.events
     buffer.events = {}
     buffer.dirty = false
-    
+
     for _, event in ipairs(to_send) do
         local ok, err = pcall(send_fn, event)
         if not ok or err then
@@ -158,7 +158,7 @@ function buffer.flush(send_fn)
             table.insert(buffer.events, event)
         end
     end
-    
+
     buffer.save()
 end
 
@@ -227,19 +227,19 @@ local function poll_single_device(device_id, device_ip)
         'ubus call network.interface.%s status 2>/dev/null',
         device_id
     )
-    
+
     local f = io.popen(cmd)
     if not f then
         return { status = "error", ip = device_ip }
     end
-    
+
     local result = f:read("*all")
     f:close()
-    
+
     local parsed = json_decode(result)
     parsed.status = "online"
     parsed.ip = device_ip
-    
+
     return parsed
 end
 
@@ -252,23 +252,23 @@ local function poll_devices_parallel(device_list)
         end
         return
     end
-    
+
     poll_results = {}
     poll_count = 0
     poll_total = #device_list
-    
+
     log("info", "Starting parallel poll of " .. poll_total .. " devices")
-    
+
     -- Poll each device in parallel using luv async
     for _, dev in ipairs(device_list) do
         local device_id = dev.id
         local device_ip = dev.ip
-        
+
         -- Run in async task
         luv.new_task(function()
             local result = poll_single_device(device_id, device_ip)
             poll_results[device_id] = result
-            
+
             poll_count = poll_count + 1
             if poll_count == poll_total then
                 log("info", "All " .. poll_total .. " devices polled")
@@ -287,28 +287,28 @@ local function monitor_wifi_events()
         log("warn", "luv not available for WiFi monitoring")
         return
     end
-    
+
     -- Use luv to watch ubus for wireless events
     -- Note: ubus doesn't support event subscription directly,
     -- so we poll hostapd status periodically
-    
+
     local timer = luv.new_timer()
     local last_clients = {}
-    
+
     luv.timer_start(timer, 10000, 10000, function()
         -- Poll wireless clients
         local f = io.popen("ubus call hostapd.wlan0-1 get_clients 2>/dev/null")
         if f then
             local result = f:read("*all")
             f:close()
-            
+
             if result and result ~= "" then
                 -- Parse clients and detect changes
                 local current_clients = {}
                 for mac in result:gmatch('"([^"]+)":') do
                     current_clients[mac] = true
                 end
-                
+
                 -- Detect new connections
                 for mac, _ in pairs(current_clients) do
                     if not last_clients[mac] then
@@ -320,7 +320,7 @@ local function monitor_wifi_events()
                         buffer.add(ev)
                     end
                 end
-                
+
                 -- Detect disconnections
                 for mac, _ in pairs(last_clients) do
                     if not current_clients[mac] then
@@ -332,12 +332,12 @@ local function monitor_wifi_events()
                         buffer.add(ev)
                     end
                 end
-                
+
                 last_clients = current_clients
             end
         end
     end)
-    
+
     log("info", "WiFi event monitor started")
 end
 
@@ -351,20 +351,20 @@ local function monitor_dhcp_leases()
         monitor_dhcp_sequential()
         return
     end
-    
+
     local lease_file = "/var/lib/dnsmasq/dnsmasq.leases"
     local old_leases = {}
     local last_mtime = 0
-    
+
     -- Use luv fs_event to watch file changes
     local fs_event = luv.new_fs_event()
-    
+
     luv.fs_event_start(fs_event, lease_file, function(err)
         if err then
             log("err", "DHCP fs_event error: " .. err)
             return
         end
-        
+
         -- File changed, process leases
         process_leases(old_leases, function(mac, ip, hostname, action)
             local ev = build_event("dhcp_lease", {
@@ -376,10 +376,10 @@ local function monitor_dhcp_leases()
             log("info", "DHCP: " .. action .. " - " .. mac .. " -> " .. ip)
             buffer.add(ev)
         end)
-        
+
         old_leases = read_leases()
     end)
-    
+
     log("info", "DHCP lease monitor started")
 end
 
@@ -388,7 +388,7 @@ local function read_leases()
     local leases = {}
     local f = io.open("/var/lib/dnsmasq/dnsmasq.leases", "r")
     if not f then return leases end
-    
+
     for line in f:lines() do
         local ts, mac, ip, name = line:match("(%d+)%s+(%S+)%s+(%S+)%s+(%S+)")
         if mac then
@@ -402,14 +402,14 @@ end
 -- Helper: process leases and detect changes
 local function process_leases(old_leases, callback)
     local leases = read_leases()
-    
+
     -- New leases
     for mac, info in pairs(leases) do
         if not old_leases[mac] then
             callback(mac, info.ip, info.hostname, "new")
         end
     end
-    
+
     -- Expired leases
     for mac, info in pairs(old_leases) do
         if not leases[mac] then
@@ -421,7 +421,7 @@ end
 -- Fallback: sequential DHCP monitoring
 local function monitor_dhcp_sequential()
     local old_leases = {}
-    
+
     while true do
         process_leases(old_leases, function(mac, ip, hostname, action)
             local ev = build_event("dhcp_lease", {
@@ -433,7 +433,7 @@ local function monitor_dhcp_sequential()
             log("info", "DHCP: " .. action .. " - " .. mac .. " -> " .. ip)
             buffer.add(ev)
         end)
-        
+
         old_leases = read_leases()
         os.execute("sleep " .. cfg.dhcp_poll_interval)
     end
@@ -451,17 +451,17 @@ local function monitor_wan()
         monitor_wan_sequential()
         return
     end
-    
+
     local timer = luv.new_timer()
-    
+
     luv.timer_start(timer, cfg.wan_poll_interval * 1000, cfg.wan_poll_interval * 1000, function()
         local f = io.popen("ubus call network.interface.wan status 2>/dev/null")
         if f then
             local status = f:read("*all")
             f:close()
-            
+
             local is_up = status:match('"up":%s*true') ~= nil
-            
+
             if is_up ~= last_wan_state then
                 local ev = build_event("wan_status", {
                     up = is_up
@@ -472,7 +472,7 @@ local function monitor_wan()
             end
         end
     end)
-    
+
     log("info", "WAN monitor started")
 end
 
@@ -483,9 +483,9 @@ local function monitor_wan_sequential()
         if f then
             local status = f:read("*all")
             f:close()
-            
+
             local is_up = status:match('"up":%s*true') ~= nil
-            
+
             if is_up ~= last_wan_state then
                 local ev = build_event("wan_status", {
                     up = is_up
@@ -495,7 +495,7 @@ local function monitor_wan_sequential()
                 last_wan_state = is_up
             end
         end
-        
+
         os.execute("sleep " .. cfg.wan_poll_interval)
     end
 end
@@ -511,15 +511,15 @@ local function poll_network_status()
         if f then f:close() end
         return
     end
-    
+
     local timer = luv.new_timer()
-    
+
     luv.timer_start(timer, cfg.poll_interval * 1000, cfg.poll_interval * 1000, function()
         local f = io.popen("ubus call network getStatus 2>/dev/null")
         if f then
             local status = f:read("*all")
             f:close()
-            
+
             if status and status ~= "" then
                 local ev = build_event("network_status", {
                     status = status
@@ -528,7 +528,7 @@ local function poll_network_status()
             end
         end
     end)
-    
+
     log("info", "Network status poller started")
 end
 
@@ -540,16 +540,16 @@ local function main()
     log("info", "client2server-luv starting...")
     log("info", "Router: " .. cfg.router_id)
     log("info", "Server: " .. cfg.url)
-    
+
     if luv_ok then
         log("info", "luv available - using async mode")
     else
         log("warn", "luv NOT available - using blocking mode")
     end
-    
+
     -- Load buffered events
     buffer.load()
-    
+
     -- Save PID
     local pf = io.open("/var/run/client2server-luv.pid", "w")
     if pf then
@@ -559,10 +559,10 @@ local function main()
         pf:write(pid:gsub("%s+", ""))
         pf:close()
     end
-    
+
     local sock = nil
     local retries = 0
-    
+
     if luv_ok then
         -- Use luv event loop
         -- luv.run() starts the event loop. The callbacks we registered
@@ -573,50 +573,46 @@ local function main()
             monitor_dhcp_leases()
             monitor_wan()
             poll_network_status()
-            
+
             -- Keep the event loop running
             local idle = luv.new_idle()
             luv.idle_start(idle, function()
                 -- Idle work - just keep loop alive
             end)
         end
-        
+
         -- Start monitors first, then run the event loop
         start_monitors()
-        
+
         -- luv.run() - start the event loop (no arguments)
-        local ok, err = pcall(luv.run)
+        local ok, err = pcall(function() luv.run() end)
         if not ok then
             log("err", "luv.run error: " .. tostring(err))
-            -- Fallback: sequential mode
-            while true do
-                os.execute("sleep 60")
-            end
         end
-            
-            -- WebSocket connection and keepalive
+        
+        -- WebSocket connection and keepalive
             while true do
                 log("info", "Connecting to server...")
-                
+
                 if ws_client then
                     sock = ws.connect(cfg.url)
                 end
-                
+
                 if sock then
                     log("info", "Connected!")
                     retries = 0
-                    
+
                     -- Flush buffer
                     buffer.flush(function(data)
                         return ws.send(sock, data)
                     end)
-                    
+
                     -- Keep alive loop
                     local loop_count = 0
                     while ws.connected(sock) and loop_count < (cfg.ping_interval / 5) do
                         luv.sleep(5000)
                         loop_count = loop_count + 1
-                        
+
                         -- Periodic flush
                         buffer.flush(function(data)
                             return ws.send(sock, data)
@@ -626,14 +622,14 @@ local function main()
                     log("err", "Connection failed")
                     retries = retries + 1
                 end
-                
+
                 -- Cleanup and reconnect
                 ws.close(sock)
                 sock = nil
-                
+
                 -- Save buffer on disconnect
                 buffer.save()
-                
+
                 -- Delay before reconnect
                 luv.sleep(cfg.reconnect_delay * 1000)
             end
@@ -644,27 +640,27 @@ local function main()
             -- Sequential monitoring
             monitor_dhcp_sequential()
             monitor_wan_sequential()
-            
+
             -- WebSocket connection
             log("info", "Connecting to server...")
-            
+
             if ws_client then
                 sock = ws.connect(cfg.url)
             end
-            
+
             if sock then
                 log("info", "Connected!")
                 retries = 0
-                
+
                 buffer.flush(function(data)
                     return ws.send(sock, data)
                 end)
-                
+
                 local loop_count = 0
                 while ws.connected(sock) and loop_count < (cfg.ping_interval / 5) do
                     os.execute("sleep 5")
                     loop_count = loop_count + 1
-                    
+
                     buffer.flush(function(data)
                         return ws.send(sock, data)
                     end)
@@ -673,7 +669,7 @@ local function main()
                 log("err", "Connection failed")
                 retries = retries + 1
             end
-            
+
             ws.close(sock)
             buffer.save()
             os.execute("sleep " .. cfg.reconnect_delay)