initial commit
This commit is contained in:
321
internal/server/network/backend_networkmanager_signals.go
Normal file
321
internal/server/network/backend_networkmanager_signals.go
Normal file
@@ -0,0 +1,321 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/Wifx/gonetworkmanager/v2"
|
||||
"github.com/godbus/dbus/v5"
|
||||
)
|
||||
|
||||
func (b *NetworkManagerBackend) startSignalPump() error {
|
||||
conn, err := dbus.ConnectSystemBus()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.dbusConn = conn
|
||||
|
||||
signals := make(chan *dbus.Signal, 256)
|
||||
b.signals = signals
|
||||
conn.Signal(signals)
|
||||
|
||||
if err := conn.AddMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
); err != nil {
|
||||
conn.RemoveSignal(signals)
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
if err := conn.AddMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath("/org/freedesktop/NetworkManager/Settings")),
|
||||
dbus.WithMatchInterface("org.freedesktop.NetworkManager.Settings"),
|
||||
dbus.WithMatchMember("NewConnection"),
|
||||
); err != nil {
|
||||
conn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
conn.RemoveSignal(signals)
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
if err := conn.AddMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath("/org/freedesktop/NetworkManager/Settings")),
|
||||
dbus.WithMatchInterface("org.freedesktop.NetworkManager.Settings"),
|
||||
dbus.WithMatchMember("ConnectionRemoved"),
|
||||
); err != nil {
|
||||
conn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
conn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath("/org/freedesktop/NetworkManager/Settings")),
|
||||
dbus.WithMatchInterface("org.freedesktop.NetworkManager.Settings"),
|
||||
dbus.WithMatchMember("NewConnection"),
|
||||
)
|
||||
conn.RemoveSignal(signals)
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
if b.wifiDevice != nil {
|
||||
dev := b.wifiDevice.(gonetworkmanager.Device)
|
||||
if err := conn.AddMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
); err != nil {
|
||||
conn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
conn.RemoveSignal(signals)
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if b.ethernetDevice != nil {
|
||||
dev := b.ethernetDevice.(gonetworkmanager.Device)
|
||||
if err := conn.AddMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
); err != nil {
|
||||
conn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
if b.wifiDevice != nil {
|
||||
dev := b.wifiDevice.(gonetworkmanager.Device)
|
||||
conn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
}
|
||||
conn.RemoveSignal(signals)
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
b.sigWG.Add(1)
|
||||
go func() {
|
||||
defer b.sigWG.Done()
|
||||
for {
|
||||
select {
|
||||
case <-b.stopChan:
|
||||
return
|
||||
case sig, ok := <-signals:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if sig == nil {
|
||||
continue
|
||||
}
|
||||
b.handleDBusSignal(sig)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) stopSignalPump() {
|
||||
if b.dbusConn == nil {
|
||||
return
|
||||
}
|
||||
|
||||
b.dbusConn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dbusNMPath)),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
|
||||
if b.wifiDevice != nil {
|
||||
dev := b.wifiDevice.(gonetworkmanager.Device)
|
||||
b.dbusConn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
}
|
||||
|
||||
if b.ethernetDevice != nil {
|
||||
dev := b.ethernetDevice.(gonetworkmanager.Device)
|
||||
b.dbusConn.RemoveMatchSignal(
|
||||
dbus.WithMatchObjectPath(dbus.ObjectPath(dev.GetPath())),
|
||||
dbus.WithMatchInterface(dbusPropsInterface),
|
||||
dbus.WithMatchMember("PropertiesChanged"),
|
||||
)
|
||||
}
|
||||
|
||||
if b.signals != nil {
|
||||
b.dbusConn.RemoveSignal(b.signals)
|
||||
close(b.signals)
|
||||
}
|
||||
|
||||
b.sigWG.Wait()
|
||||
|
||||
b.dbusConn.Close()
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleDBusSignal(sig *dbus.Signal) {
|
||||
if sig.Name == "org.freedesktop.NetworkManager.Settings.NewConnection" ||
|
||||
sig.Name == "org.freedesktop.NetworkManager.Settings.ConnectionRemoved" {
|
||||
b.ListVPNProfiles()
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(sig.Body) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
iface, ok := sig.Body[0].(string)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
changes, ok := sig.Body[1].(map[string]dbus.Variant)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
switch iface {
|
||||
case dbusNMInterface:
|
||||
b.handleNetworkManagerChange(changes)
|
||||
|
||||
case dbusNMDeviceInterface:
|
||||
b.handleDeviceChange(changes)
|
||||
|
||||
case dbusNMWirelessInterface:
|
||||
b.handleWiFiChange(changes)
|
||||
|
||||
case dbusNMAccessPointInterface:
|
||||
b.handleAccessPointChange(changes)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleNetworkManagerChange(changes map[string]dbus.Variant) {
|
||||
var needsUpdate bool
|
||||
|
||||
for key := range changes {
|
||||
switch key {
|
||||
case "PrimaryConnection", "State", "ActiveConnections":
|
||||
needsUpdate = true
|
||||
case "WirelessEnabled":
|
||||
nm := b.nmConn.(gonetworkmanager.NetworkManager)
|
||||
if enabled, err := nm.GetPropertyWirelessEnabled(); err == nil {
|
||||
b.stateMutex.Lock()
|
||||
b.state.WiFiEnabled = enabled
|
||||
b.stateMutex.Unlock()
|
||||
needsUpdate = true
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if needsUpdate {
|
||||
b.updatePrimaryConnection()
|
||||
if _, exists := changes["State"]; exists {
|
||||
b.updateEthernetState()
|
||||
b.updateWiFiState()
|
||||
}
|
||||
if _, exists := changes["ActiveConnections"]; exists {
|
||||
b.updateVPNConnectionState()
|
||||
b.ListActiveVPN()
|
||||
}
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleDeviceChange(changes map[string]dbus.Variant) {
|
||||
var needsUpdate bool
|
||||
var stateChanged bool
|
||||
|
||||
for key := range changes {
|
||||
switch key {
|
||||
case "State":
|
||||
stateChanged = true
|
||||
needsUpdate = true
|
||||
case "Ip4Config":
|
||||
needsUpdate = true
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if needsUpdate {
|
||||
b.updateEthernetState()
|
||||
b.updateWiFiState()
|
||||
if stateChanged {
|
||||
b.updatePrimaryConnection()
|
||||
}
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleWiFiChange(changes map[string]dbus.Variant) {
|
||||
var needsStateUpdate bool
|
||||
var needsNetworkUpdate bool
|
||||
|
||||
for key := range changes {
|
||||
switch key {
|
||||
case "ActiveAccessPoint":
|
||||
needsStateUpdate = true
|
||||
needsNetworkUpdate = true
|
||||
case "AccessPoints":
|
||||
needsNetworkUpdate = true
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if needsStateUpdate {
|
||||
b.updateWiFiState()
|
||||
}
|
||||
if needsNetworkUpdate {
|
||||
b.updateWiFiNetworks()
|
||||
}
|
||||
if needsStateUpdate || needsNetworkUpdate {
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *NetworkManagerBackend) handleAccessPointChange(changes map[string]dbus.Variant) {
|
||||
_, hasStrength := changes["Strength"]
|
||||
if !hasStrength {
|
||||
return
|
||||
}
|
||||
|
||||
b.stateMutex.RLock()
|
||||
oldSignal := b.state.WiFiSignal
|
||||
b.stateMutex.RUnlock()
|
||||
|
||||
b.updateWiFiState()
|
||||
|
||||
b.stateMutex.RLock()
|
||||
newSignal := b.state.WiFiSignal
|
||||
b.stateMutex.RUnlock()
|
||||
|
||||
if signalChangeSignificant(oldSignal, newSignal) {
|
||||
if b.onStateChange != nil {
|
||||
b.onStateChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user