Flesh out Device and AccessPoint objects, JSON marshalling, basic signals.

This commit is contained in:
Tom Wambold 2016-05-25 16:47:07 -04:00
parent f8e3a86e11
commit e9eb8e5842
12 changed files with 325 additions and 18 deletions

View file

@ -1,18 +1,59 @@
package gonetworkmanager
import (
"encoding/json"
"github.com/godbus/dbus"
)
const (
AccessPointInterface = NetworkManagerInterface + ".AccessPoint"
AccessPointPropertyFlags = AccessPointInterface + ".Flags"
AccessPointPropertyWPAFlags = AccessPointInterface + ".WpaFlags"
AccessPointPropertyRSNFlags = AccessPointInterface + ".RsnFlags"
AccessPointPropertySSID = AccessPointInterface + ".Ssid"
AccessPointPropertyFrequency = AccessPointInterface + ".Frequency"
AccessPointPropertyHWAddress = AccessPointInterface + ".HwAddress"
AccessPointPropertyMode = AccessPointInterface + ".Mode"
AccessPointPropertyMaxBitrate = AccessPointInterface + ".MaxBitrate"
AccessPointPropertyStrength = AccessPointInterface + ".Strength"
)
type AccessPoint interface {
// GetFlags gets flags describing the capabilities of the access point.
GetFlags() uint32
// GetWPAFlags gets flags describing the access point's capabilities
// according to WPA (Wifi Protected Access).
GetWPAFlags() uint32
// GetRSNFlags gets flags describing the access point's capabilities
// according to the RSN (Robust Secure Network) protocol.
GetRSNFlags() uint32
// GetSSID returns the Service Set Identifier identifying the access point.
GetSSID() string
// GetFrequency gets the radio channel frequency in use by the access point,
// in MHz.
GetFrequency() uint32
// GetHWAddress gets the hardware address (BSSID) of the access point.
GetHWAddress() string
// GetMode describes the operating mode of the access point.
GetMode() Nm80211Mode
// GetMaxBitrate gets the maximum bitrate this access point is capable of, in
// kilobits/second (Kb/s).
GetMaxBitrate() uint32
// GetStrength gets the current signal quality of the access point, in
// percent.
GetStrength() uint8
MarshalJSON() ([]byte, error)
}
func NewAccessPoint(objectPath dbus.ObjectPath) (AccessPoint, error) {
@ -24,6 +65,52 @@ type accessPoint struct {
dbusBase
}
func (a *accessPoint) GetFlags() uint32 {
return a.getUint32Property(AccessPointPropertyFlags)
}
func (a *accessPoint) GetWPAFlags() uint32 {
return a.getUint32Property(AccessPointPropertyWPAFlags)
}
func (a *accessPoint) GetRSNFlags() uint32 {
return a.getUint32Property(AccessPointPropertyRSNFlags)
}
func (a *accessPoint) GetSSID() string {
return string(a.getSliceByteProperty(AccessPointPropertySSID))
}
func (a *accessPoint) GetFrequency() uint32 {
return a.getUint32Property(AccessPointPropertyFrequency)
}
func (a *accessPoint) GetHWAddress() string {
return a.getStringProperty(AccessPointPropertyHWAddress)
}
func (a *accessPoint) GetMode() Nm80211Mode {
return Nm80211Mode(a.getUint32Property(AccessPointPropertyMode))
}
func (a *accessPoint) GetMaxBitrate() uint32 {
return a.getUint32Property(AccessPointPropertyMaxBitrate)
}
func (a *accessPoint) GetStrength() uint8 {
return a.getUint8Property(AccessPointPropertyStrength)
}
func (a *accessPoint) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"Flags": a.GetFlags(),
"WPAFlags": a.GetWPAFlags(),
"RSNFlags": a.GetRSNFlags(),
"SSID": a.GetSSID(),
"Frequency": a.GetFrequency(),
"HWAddress": a.GetHWAddress(),
"Mode": a.GetMode().String(),
"MaxBitrate": a.GetMaxBitrate(),
"Strength": a.GetStrength(),
})
}

View file

@ -1,6 +1,8 @@
package gonetworkmanager
import (
"encoding/json"
"github.com/godbus/dbus"
)
@ -19,6 +21,8 @@ type Connection interface {
// network, as those are often protected. Secrets must be requested
// separately using the GetSecrets() call.
GetSettings() ConnectionSettings
MarshalJSON() ([]byte, error)
}
func NewConnection(objectPath dbus.ObjectPath) (Connection, error) {
@ -46,3 +50,7 @@ func (c *connection) GetSettings() ConnectionSettings {
return rv
}
func (c *connection) MarshalJSON() ([]byte, error) {
return json.Marshal(c.GetSettings())
}

View file

@ -1,6 +1,8 @@
package gonetworkmanager
import (
"encoding/json"
"github.com/godbus/dbus"
)
@ -48,6 +50,8 @@ type Device interface {
// GetAvailableConnections gets an array of object paths of every configured
// connection that is currently 'available' through this device.
GetAvailableConnections() []Connection
MarshalJSON() ([]byte, error)
}
func NewDevice(objectPath dbus.ObjectPath) (Device, error) {
@ -99,3 +103,17 @@ func (d *device) GetAvailableConnections() []Connection {
return conns
}
func (d *device) marshalMap() map[string]interface{} {
return map[string]interface{}{
"Interface": d.GetInterface(),
"State": d.GetState().String(),
"IP4Config": d.GetIP4Config(),
"DeviceType": d.GetDeviceType().String(),
"AvailableConnections": d.GetAvailableConnections(),
}
}
func (d *device) MarshalJSON() ([]byte, error) {
return json.Marshal(d.marshalMap())
}

View file

@ -1,6 +1,8 @@
package gonetworkmanager
import (
"encoding/json"
"github.com/godbus/dbus"
)
@ -44,6 +46,8 @@ type IP4Config interface {
// GetDomains gets a list of domains this address belongs to.
GetDomains() []string
MarshalJSON() ([]byte, error)
}
func NewIP4Config(objectPath dbus.ObjectPath) (IP4Config, error) {
@ -100,3 +104,12 @@ func (c *ip4Config) GetNameservers() []string {
func (c *ip4Config) GetDomains() []string {
return c.getSliceStringProperty(IP4ConfigPropertyDomains)
}
func (c *ip4Config) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"Addresses": c.GetAddresses(),
"Routes": c.GetRoutes(),
"Nameservers": c.GetNameservers(),
"Domains": c.GetDomains(),
})
}

View file

@ -1,6 +1,8 @@
package gonetworkmanager
import (
"encoding/json"
"github.com/godbus/dbus"
)
@ -21,6 +23,11 @@ type NetworkManager interface {
// NetworkManager daemon, based on the state of network devices under it's
// management.
GetState() NmState
Subscribe() <-chan *dbus.Signal
Unsubscribe()
MarshalJSON() ([]byte, error)
}
func NewNetworkManager() (NetworkManager, error) {
@ -30,6 +37,8 @@ func NewNetworkManager() (NetworkManager, error) {
type networkManager struct {
dbusBase
sigChan chan *dbus.Signal
}
func (n *networkManager) GetDevices() []Device {
@ -52,3 +61,27 @@ func (n *networkManager) GetDevices() []Device {
func (n *networkManager) GetState() NmState {
return NmState(n.getUint32Property(NetworkManagerPropertyState))
}
func (n *networkManager) Subscribe() <-chan *dbus.Signal {
if n.sigChan != nil {
return n.sigChan
}
n.subscribeNamespace(NetworkManagerObjectPath)
n.sigChan = make(chan *dbus.Signal, 10)
n.conn.Signal(n.sigChan)
return n.sigChan
}
func (n *networkManager) Unsubscribe() {
n.conn.RemoveSignal(n.sigChan)
n.sigChan = nil
}
func (n *networkManager) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"NetworkState": n.GetState().String(),
"Devices": n.GetDevices(),
})
}

View file

@ -1,6 +1,8 @@
package gonetworkmanager
import (
"encoding/json"
"github.com/godbus/dbus"
)
@ -45,3 +47,9 @@ func (d *wirelessDevice) GetAccessPoints() []AccessPoint {
return aps
}
func (d *wirelessDevice) MarshalJSON() ([]byte, error) {
m := d.device.marshalMap()
m["AccessPoints"] = d.GetAccessPoints()
return json.Marshal(m)
}

View file

@ -65,3 +65,38 @@ const (
NmDeviceTypeGeneric NmDeviceType = 14
NmDeviceTypeTeam NmDeviceType = 15
)
//go:generate stringer -type=Nm80211APFlags
type Nm80211APFlags uint32
const (
Nm80211APFlagsNone Nm80211APFlags = 0x0
Nm80211APFlagsPrivacy Nm80211APFlags = 0x1
)
//go:generate stringer -type=Nm80211APSec
type Nm80211APSec uint32
const (
Nm80211APSecNone Nm80211APSec = 0x0
Nm80211APSecPairWEP40 Nm80211APSec = 0x1
Nm80211APSecPairWEP104 Nm80211APSec = 0x2
Nm80211APSecPairTKIP Nm80211APSec = 0x4
Nm80211APSecPairCCMP Nm80211APSec = 0x8
Nm80211APSecGroupWEP40 Nm80211APSec = 0x10
Nm80211APSecGroupWEP104 Nm80211APSec = 0x20
Nm80211APSecGroupTKIP Nm80211APSec = 0x40
Nm80211APSecGroupCCMP Nm80211APSec = 0x80
Nm80211APSecKeyMgmtPSK Nm80211APSec = 0x100
Nm80211APSecKeyMgmt8021X Nm80211APSec = 0x200
)
//go:generate stringer -type=Nm80211Mode
type Nm80211Mode uint32
const (
Nm80211ModeUnknown Nm80211Mode = 0
Nm80211ModeAdhoc Nm80211Mode = 1
Nm80211ModeInfra Nm80211Mode = 2
Nm80211ModeAp Nm80211Mode = 3
)

View file

@ -1,9 +0,0 @@
package gonetworkmanager
import (
"errors"
)
var (
ErrVariantType = errors.New("unexpected variant type")
)

16
nm80211apflags_string.go Normal file
View file

@ -0,0 +1,16 @@
// Code generated by "stringer -type=Nm80211APFlags"; DO NOT EDIT
package gonetworkmanager
import "fmt"
const _Nm80211APFlags_name = "Nm80211APFlagsNoneNm80211APFlagsPrivacy"
var _Nm80211APFlags_index = [...]uint8{0, 18, 39}
func (i Nm80211APFlags) String() string {
if i >= Nm80211APFlags(len(_Nm80211APFlags_index)-1) {
return fmt.Sprintf("Nm80211APFlags(%d)", i)
}
return _Nm80211APFlags_name[_Nm80211APFlags_index[i]:_Nm80211APFlags_index[i+1]]
}

54
nm80211apsec_string.go Normal file
View file

@ -0,0 +1,54 @@
// Code generated by "stringer -type=Nm80211APSec"; DO NOT EDIT
package gonetworkmanager
import "fmt"
const (
_Nm80211APSec_name_0 = "Nm80211APSecNoneNm80211APSecPairWEP40Nm80211APSecPairWEP104"
_Nm80211APSec_name_1 = "Nm80211APSecPairTKIP"
_Nm80211APSec_name_2 = "Nm80211APSecPairCCMP"
_Nm80211APSec_name_3 = "Nm80211APSecGroupWEP40"
_Nm80211APSec_name_4 = "Nm80211APSecGroupWEP104"
_Nm80211APSec_name_5 = "Nm80211APSecGroupTKIP"
_Nm80211APSec_name_6 = "Nm80211APSecGroupCCMP"
_Nm80211APSec_name_7 = "Nm80211APSecKeyMgmtPSK"
_Nm80211APSec_name_8 = "Nm80211APSecKeyMgmt8021X"
)
var (
_Nm80211APSec_index_0 = [...]uint8{0, 16, 37, 59}
_Nm80211APSec_index_1 = [...]uint8{0, 20}
_Nm80211APSec_index_2 = [...]uint8{0, 20}
_Nm80211APSec_index_3 = [...]uint8{0, 22}
_Nm80211APSec_index_4 = [...]uint8{0, 23}
_Nm80211APSec_index_5 = [...]uint8{0, 21}
_Nm80211APSec_index_6 = [...]uint8{0, 21}
_Nm80211APSec_index_7 = [...]uint8{0, 22}
_Nm80211APSec_index_8 = [...]uint8{0, 24}
)
func (i Nm80211APSec) String() string {
switch {
case 0 <= i && i <= 2:
return _Nm80211APSec_name_0[_Nm80211APSec_index_0[i]:_Nm80211APSec_index_0[i+1]]
case i == 4:
return _Nm80211APSec_name_1
case i == 8:
return _Nm80211APSec_name_2
case i == 16:
return _Nm80211APSec_name_3
case i == 32:
return _Nm80211APSec_name_4
case i == 64:
return _Nm80211APSec_name_5
case i == 128:
return _Nm80211APSec_name_6
case i == 256:
return _Nm80211APSec_name_7
case i == 512:
return _Nm80211APSec_name_8
default:
return fmt.Sprintf("Nm80211APSec(%d)", i)
}
}

16
nm80211mode_string.go Normal file
View file

@ -0,0 +1,16 @@
// Code generated by "stringer -type=Nm80211Mode"; DO NOT EDIT
package gonetworkmanager
import "fmt"
const _Nm80211Mode_name = "Nm80211ModeUnknownNm80211ModeAdhocNm80211ModeInfraNm80211ModeAp"
var _Nm80211Mode_index = [...]uint8{0, 18, 34, 50, 63}
func (i Nm80211Mode) String() string {
if i >= Nm80211Mode(len(_Nm80211Mode_index)-1) {
return fmt.Sprintf("Nm80211Mode(%d)", i)
}
return _Nm80211Mode_name[_Nm80211Mode_index[i]:_Nm80211Mode_index[i+1]]
}

View file

@ -2,11 +2,16 @@ package gonetworkmanager
import (
"encoding/binary"
"fmt"
"net"
"github.com/godbus/dbus"
)
const (
dbusMethodAddMatch = "org.freedesktop.DBus.AddMatch"
)
type dbusBase struct {
conn *dbus.Conn
obj dbus.BusObject
@ -36,6 +41,17 @@ func (d *dbusBase) callError(value interface{}, method string, args ...interface
return d.obj.Call(method, 0, args...).Store(value)
}
func (d *dbusBase) subscribe(iface, member string) {
rule := fmt.Sprintf("type='signal',interface='%s',path='%s',member='%s'",
iface, d.obj.Path(), NetworkManagerInterface)
d.conn.BusObject().Call(dbusMethodAddMatch, 0, rule)
}
func (d *dbusBase) subscribeNamespace(namespace string) {
rule := fmt.Sprintf("type='signal',path_namespace='%s'", namespace)
d.conn.BusObject().Call(dbusMethodAddMatch, 0, rule)
}
func (d *dbusBase) getProperty(iface string) interface{} {
variant, err := d.obj.GetProperty(iface)
if err != nil {
@ -47,7 +63,7 @@ func (d *dbusBase) getProperty(iface string) interface{} {
func (d *dbusBase) getObjectProperty(iface string) dbus.ObjectPath {
value, ok := d.getProperty(iface).(dbus.ObjectPath)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
@ -55,7 +71,7 @@ func (d *dbusBase) getObjectProperty(iface string) dbus.ObjectPath {
func (d *dbusBase) getSliceObjectProperty(iface string) []dbus.ObjectPath {
value, ok := d.getProperty(iface).([]dbus.ObjectPath)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
@ -63,7 +79,7 @@ func (d *dbusBase) getSliceObjectProperty(iface string) []dbus.ObjectPath {
func (d *dbusBase) getStringProperty(iface string) string {
value, ok := d.getProperty(iface).(string)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
@ -71,7 +87,15 @@ func (d *dbusBase) getStringProperty(iface string) string {
func (d *dbusBase) getSliceStringProperty(iface string) []string {
value, ok := d.getProperty(iface).([]string)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
func (d *dbusBase) getUint8Property(iface string) uint8 {
value, ok := d.getProperty(iface).(uint8)
if !ok {
panic(makeErrVariantType(iface))
}
return value
}
@ -79,7 +103,7 @@ func (d *dbusBase) getSliceStringProperty(iface string) []string {
func (d *dbusBase) getUint32Property(iface string) uint32 {
value, ok := d.getProperty(iface).(uint32)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
@ -87,7 +111,7 @@ func (d *dbusBase) getUint32Property(iface string) uint32 {
func (d *dbusBase) getSliceUint32Property(iface string) []uint32 {
value, ok := d.getProperty(iface).([]uint32)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
@ -95,7 +119,7 @@ func (d *dbusBase) getSliceUint32Property(iface string) []uint32 {
func (d *dbusBase) getSliceSliceUint32Property(iface string) [][]uint32 {
value, ok := d.getProperty(iface).([][]uint32)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
@ -103,11 +127,15 @@ func (d *dbusBase) getSliceSliceUint32Property(iface string) [][]uint32 {
func (d *dbusBase) getSliceByteProperty(iface string) []byte {
value, ok := d.getProperty(iface).([]byte)
if !ok {
panic(ErrVariantType)
panic(makeErrVariantType(iface))
}
return value
}
func makeErrVariantType(iface string) error {
return fmt.Errorf("unexpected variant type for '%s'", iface)
}
func ip4ToString(ip uint32) string {
bs := []byte{0, 0, 0, 0}
binary.LittleEndian.PutUint32(bs, ip)