This repository has been archived on 2025-03-19. You can view files and clone it, but cannot push or open issues or pull requests.
gonetworkmanager/ActiveConnection.go
Felix Rosén ba0310894b fix(SubscribeState): add the path to the recieved chan type
also remove the check for the signal to be the current path
since this will block us from receiving updates to the actual object

before it only signaled on when we deactivated, since the activation
happens on another device.
2021-12-13 20:16:38 +01:00

274 lines
8.1 KiB
Go

package gonetworkmanager
import (
"fmt"
"github.com/godbus/dbus/v5"
)
const (
ActiveConnectionInterface = NetworkManagerInterface + ".Connection.Active"
/* Properties */
ActiveConnectionPropertyConnection = ActiveConnectionInterface + ".Connection" // readable o
ActiveConnectionPropertySpecificObject = ActiveConnectionInterface + ".SpecificObject" // readable o
ActiveConnectionPropertyId = ActiveConnectionInterface + ".Id" // readable s
ActiveConnectionPropertyUuid = ActiveConnectionInterface + ".Uuid" // readable s
ActiveConnectionPropertyType = ActiveConnectionInterface + ".Type" // readable s
ActiveConnectionPropertyDevices = ActiveConnectionInterface + ".Devices" // readable ao
ActiveConnectionPropertyState = ActiveConnectionInterface + ".State" // readable u
ActiveConnectionPropertyStateFlags = ActiveConnectionInterface + ".StateFlags" // readable u
ActiveConnectionPropertyDefault = ActiveConnectionInterface + ".Default" // readable b
ActiveConnectionPropertyIp4Config = ActiveConnectionInterface + ".Ip4Config" // readable o
ActiveConnectionPropertyDhcp4Config = ActiveConnectionInterface + ".Dhcp4Config" // readable o
ActiveConnectionPropertyDefault6 = ActiveConnectionInterface + ".Default6" // readable b
ActiveConnectionPropertyIp6Config = ActiveConnectionInterface + ".Ip6Config" // readable o
ActiveConnectionPropertyDhcp6Config = ActiveConnectionInterface + ".Dhcp6Config" // readable o
ActiveConnectionPropertyVpn = ActiveConnectionInterface + ".Vpn" // readable b
ActiveConnectionPropertyMaster = ActiveConnectionInterface + ".Master" // readable o
/* Signals */
ActiveConnectionSignalStateChanged = "StateChanged" // u state, u reason
)
type ActiveConnection interface {
GetPath() dbus.ObjectPath
// GetConnectionSettings gets connection object of the connection.
GetPropertyConnection() (Connection, error)
// GetSpecificObject gets a specific object associated with the active connection.
GetPropertySpecificObject() (AccessPoint, error)
// GetID gets the ID of the connection.
GetPropertyID() (string, error)
// GetUUID gets the UUID of the connection.
GetPropertyUUID() (string, error)
// GetType gets the type of the connection.
GetPropertyType() (string, error)
// GetDevices gets array of device objects which are part of this active connection.
GetPropertyDevices() ([]Device, error)
// GetState gets the state of the connection.
GetPropertyState() (NmActiveConnectionState, error)
// GetStateFlags gets the state flags of the connection.
GetPropertyStateFlags() (uint32, error)
// GetDefault gets the default IPv4 flag of the connection.
GetPropertyDefault() (bool, error)
// GetIP4Config gets the IP4Config of the connection.
GetPropertyIP4Config() (IP4Config, error)
// GetDHCP4Config gets the DHCP6Config of the connection.
GetPropertyDHCP4Config() (DHCP4Config, error)
// GetDefault gets the default IPv6 flag of the connection.
GetPropertyDefault6() (bool, error)
// GetIP6Config gets the IP6Config of the connection.
GetPropertyIP6Config() (IP6Config, error)
// GetDHCP6Config gets the DHCP4Config of the connection.
GetPropertyDHCP6Config() (DHCP6Config, error)
// GetVPN gets the VPN flag of the connection.
GetPropertyVPN() (bool, error)
// GetMaster gets the master device of the connection.
GetPropertyMaster() (Device, error)
SubscribeState(receiver chan StateChange, exit chan struct{}) (err error)
}
func NewActiveConnection(objectPath dbus.ObjectPath) (ActiveConnection, error) {
var a activeConnection
return &a, a.init(NetworkManagerInterface, objectPath)
}
type activeConnection struct {
dbusBase
}
func (a *activeConnection) GetPath() dbus.ObjectPath {
return a.obj.Path()
}
func (a *activeConnection) GetPropertyConnection() (Connection, error) {
path, err := a.getObjectProperty(ActiveConnectionPropertyConnection)
if err != nil {
return nil, err
}
con, err := NewConnection(path)
if err != nil {
return nil, err
}
return con, nil
}
func (a *activeConnection) GetPropertySpecificObject() (AccessPoint, error) {
path, err := a.getObjectProperty(ActiveConnectionPropertySpecificObject)
if err != nil {
return nil, err
}
ap, err := NewAccessPoint(path)
if err != nil {
return nil, err
}
return ap, nil
}
func (a *activeConnection) GetPropertyID() (string, error) {
return a.getStringProperty(ActiveConnectionPropertyId)
}
func (a *activeConnection) GetPropertyUUID() (string, error) {
return a.getStringProperty(ActiveConnectionPropertyUuid)
}
func (a *activeConnection) GetPropertyType() (string, error) {
return a.getStringProperty(ActiveConnectionPropertyType)
}
func (a *activeConnection) GetPropertyDevices() ([]Device, error) {
paths, err := a.getSliceObjectProperty(ActiveConnectionPropertyDevices)
if err != nil {
return nil, err
}
devices := make([]Device, len(paths))
for i, path := range paths {
devices[i], err = DeviceFactory(path)
if err != nil {
return nil, err
}
}
return devices, nil
}
func (a *activeConnection) GetPropertyState() (NmActiveConnectionState, error) {
v, err := a.getUint32Property(ActiveConnectionPropertyState)
return NmActiveConnectionState(v), err
}
func (a *activeConnection) GetPropertyStateFlags() (uint32, error) {
return a.getUint32Property(ActiveConnectionPropertyStateFlags)
}
func (a *activeConnection) GetPropertyDefault() (bool, error) {
b, err := a.getProperty(ActiveConnectionPropertyDefault)
if err != nil {
return false, err
}
return b.(bool), nil
}
func (a *activeConnection) GetPropertyIP4Config() (IP4Config, error) {
path, err := a.getObjectProperty(ActiveConnectionPropertyIp4Config)
if err != nil || path == "/" {
return nil, err
}
return NewIP4Config(path)
}
func (a *activeConnection) GetPropertyDHCP4Config() (DHCP4Config, error) {
path, err := a.getObjectProperty(ActiveConnectionPropertyDhcp4Config)
if err != nil || path == "/" {
return nil, err
}
return NewDHCP4Config(path)
}
func (a *activeConnection) GetPropertyDefault6() (bool, error) {
return a.getBoolProperty(ActiveConnectionPropertyDefault6)
}
func (a *activeConnection) GetPropertyIP6Config() (IP6Config, error) {
path, err := a.getObjectProperty(ActiveConnectionPropertyIp6Config)
if err != nil || path == "/" {
return nil, err
}
return NewIP6Config(path)
}
func (a *activeConnection) GetPropertyDHCP6Config() (DHCP6Config, error) {
path, err := a.getObjectProperty(ActiveConnectionPropertyDhcp6Config)
if err != nil || path == "/" {
return nil, err
}
return NewDHCP6Config(path)
}
func (a *activeConnection) GetPropertyVPN() (bool, error) {
ret, err := a.getProperty(ActiveConnectionPropertyVpn)
if err != nil {
return false, err
}
return ret.(bool), nil
}
func (a *activeConnection) GetPropertyMaster() (Device, error) {
path, err := a.getObjectProperty(ActiveConnectionPropertyMaster)
if err != nil || path == "/" {
return nil, err
}
return DeviceFactory(path)
}
type StateChange struct {
Path dbus.ObjectPath
State NmActiveConnectionState
Reason NmActiveConnectionStateReason
}
func (a *activeConnection) SubscribeState(receiver chan StateChange, exit chan struct{}) (err error) {
channel := make(chan *dbus.Signal, 1)
a.conn.Signal(channel)
err = a.conn.AddMatchSignal(
dbus.WithMatchInterface(ActiveConnectionInterface),
dbus.WithMatchMember(ActiveConnectionSignalStateChanged),
dbus.WithMatchObjectPath(a.GetPath()),
)
if err != nil {
return err
}
go func() {
for {
select {
case signal, ok := <-channel:
if !ok {
err = fmt.Errorf("connection closed for %s", ActiveConnectionSignalStateChanged)
return
}
if signal.Name != ActiveConnectionInterface+"."+ActiveConnectionSignalStateChanged {
continue
}
stateChange := StateChange{
Path: signal.Path,
State: NmActiveConnectionState(signal.Body[0].(uint32)),
Reason: NmActiveConnectionStateReason(signal.Body[1].(uint32)),
}
receiver <- stateChange
case <-exit:
a.conn.RemoveSignal(channel)
close(channel)
return
}
}
}()
return
}