Bläddra i källkod

Use ubus listen for TRUE event-driven

- ubus listen blocks waiting for events
- Events trigger state check immediately
- Uses luv.new_task() to run listener in background
Gogs 2 månader sedan
förälder
incheckning
7c10345487
1 ändrade filer med 55 tillägg och 59 borttagningar
  1. 55 59
      usr/sbin/client2server-luv.lua

+ 55 - 59
usr/sbin/client2server-luv.lua

@@ -251,70 +251,75 @@ end
 -- UBUS EVENT LISTENER (TRUE event-driven!)
 -- ============================================================================
 
-local function start_ubus_listener()
+local function start_ubus_listen()
     if not luv_ok then
-        log_info("luv not available - cannot listen to ubus events")
+        log_info("luv not available")
         return false
     end
     
-    log_info("Starting ubus event listener...")
+    log_info("Starting ubus listen (event-driven)...")
     
-    -- Use ubus listen in a subprocess to get events
-    -- This is event-driven - we get notified immediately when something changes
-    local function listen_ubus_events()
-        log_info("Listening to ubus events...")
+    -- Use ubus listen in background process - this is TRUE event-driven!
+    -- ubus listen blocks and emits events when they happen
+    local function ubus_listen_loop()
+        -- Spawn ubus listen as background process
+        -- It will emit JSON events to stdout when DHCP/WiFi events happen
+        local pipe = io.popen("ubus listen dhcp ipv4leases network.interface.* hostapd.* 2>&1", "r")
         
-        -- Listen for DHCP, network, and WiFi events
-        local f = io.popen("ubus listen dhcp ipv4leases network.interface.* 2>/dev/null &")
-        if f then f:close() end
+        if not pipe then
+            log_info("ubus listen failed")
+            return false
+        end
         
-        -- Alternative: use netlink for immediate notifications
-        -- This is truly event-driven via netlink socket
-        local timer = luv.new_timer()
+        log_info("ubus listen started - waiting for events...")
         
-        -- Check for changes by comparing state (event-driven trigger)
-        local function check_changes()
-            -- Check DHCP
-            local current_dhcp = get_dhcp_leases()
-            for mac, info in pairs(current_dhcp) do
-                if not state.dhcp[mac] then
-                    on_dhcp_event("add", mac, info.ip, info.hostname)
+        -- Read events as they come (blocking but event-driven)
+        while true do
+            local line = pipe:read("*line")
+            if not line then break end
+            
+            log_info("ubus event: " .. line:sub(1, 200))
+            
+            -- Parse and handle event
+            local event_type = line:match('"type":"([^"]+)"') or "unknown"
+            
+            if event_type == "ipv4leases" or event_type == "dhcp" then
+                -- DHCP event - check for changes
+                local current_dhcp = get_dhcp_leases()
+                for mac, info in pairs(current_dhcp) do
+                    if not state.dhcp[mac] then
+                        on_dhcp_event("add", mac, info.ip, info.hostname)
+                    end
                 end
-            end
-            for mac, info in pairs(state.dhcp) do
-                if not current_dhcp[mac] then
-                    on_dhcp_event("del", mac, info.ip)
+                for mac, info in pairs(state.dhcp) do
+                    if not current_dhcp[mac] then
+                        on_dhcp_event("del", mac, info.ip)
+                    end
                 end
-            end
-            
-            -- Check WiFi
-            local current_clients = get_wifi_clients()
-            for mac, info in pairs(current_clients) do
-                if not state.clients[mac] then
-                    on_wifi_event("connected", mac, info.iface)
+            elseif event_type:match("hostapd") then
+                -- WiFi event
+                local current_clients = get_wifi_clients()
+                for mac, info in pairs(current_clients) do
+                    if not state.clients[mac] then
+                        on_wifi_event("connected", mac, info.iface)
+                    end
                 end
-            end
-            for mac, info in pairs(state.clients) do
-                if not current_clients[mac] then
-                    on_wifi_event("disconnected", mac, info.iface)
+                for mac, info in pairs(state.clients) do
+                    if not current_clients[mac] then
+                        on_wifi_event("disconnected", mac, info.iface)
+                    end
                 end
             end
         end
         
-        -- Start a fast timer that checks for changes
-        -- When state changes, we trigger immediately (no polling, just state diff)
-        luv.timer_start(timer, 1000, 1000, function()
-            check_changes()
-        end)
-        
-        return true
+        pipe:close()
+        log_info("ubus listen ended")
     end
     
-    local ok, err = pcall(listen_ubus_events)
-    if not ok then
-        log_info("ubus listener error: " .. tostring(err))
-        return false
-    end
+    -- Run ubus listen in background thread
+    luv.new_task(function()
+        ubus_listen_loop()
+    end)
     
     return true
 end
@@ -346,19 +351,10 @@ function main()
     
     if luv_ok then
         -- Start event-driven listeners
-        local started = start_ubus_listener()
+        start_ubus_listen()
         
-        if started then
-            log_info("Event listeners started - running event loop")
-            luv.run()
-        else
-            log_info("Using fallback event loop")
-            local timer = luv.new_timer()
-            luv.timer_start(timer, 1000, 1000, function()
-                -- Just keep alive
-            end)
-            luv.run()
-        end
+        log_info("Running event loop - waiting for events...")
+        luv.run()
     else
         -- No luv - just wait
         while true do