Skip to content

Commit

Permalink
feat(network): implemented state notifier and updater
Browse files Browse the repository at this point in the history
  • Loading branch information
aeddi committed Apr 10, 2019
1 parent 05d9ebb commit a566ca6
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 4 deletions.
9 changes: 9 additions & 0 deletions core/network/state/logger.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

170 changes: 170 additions & 0 deletions core/network/state/notifee.go
@@ -0,0 +1,170 @@
package state

import (
"go.uber.org/zap"
"sync"
)

type Notifee interface {
HandleConnectivityChange(ConnectivityState)
HandleInternetChange(State)
HandleVPNChange(State)
HandleMDNSChange(State)
HandleMeteredChange(State)
HandleRoamingChange(State)
HandleTrustedChange(State)
HandleNetTypeChange(NetType)
HandleCellTypeChange(CellType)
HandleBluetoothChange(BleState)
}

type notifier struct {
lock sync.Mutex
notifees []Notifee
}

func (nr *notifier) notifyConnectivityChange(cs ConnectivityState) {
nr.lock.Lock()

logger().Info("connectivity state change:",
zap.String("Internet", StateToString(cs.Internet)),
zap.String("VPN", StateToString(cs.VPN)),
zap.String("MDNS", StateToString(cs.MDNS)),
zap.String("Metered", StateToString(cs.Metered)),
zap.String("Roaming", StateToString(cs.Roaming)),
zap.String("Trusted", StateToString(cs.Trusted)),
zap.String("Network", NetTypeToString(cs.Network)),
zap.String("Cellular", CellTypeToString(cs.Cellular)),
zap.String("Bluetooth", BleStateToString(cs.Bluetooth)),
)
for _, notifee := range nr.notifees {
notifee.HandleConnectivityChange(cs)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyInternetChange(s State) {
nr.lock.Lock()

logger().Debug("notify internet state change:", zap.String("new state", StateToString(s)))
for _, notifee := range nr.notifees {
notifee.HandleInternetChange(s)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyVPNChange(s State) {
nr.lock.Lock()

logger().Debug("notify vpn state change:", zap.String("new state", StateToString(s)))
for _, notifee := range nr.notifees {
notifee.HandleVPNChange(s)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyMDNSChange(s State) {
nr.lock.Lock()

logger().Debug("notify mdns state change:", zap.String("new state", StateToString(s)))
for _, notifee := range nr.notifees {
notifee.HandleMDNSChange(s)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyMeteredChange(s State) {
nr.lock.Lock()

logger().Debug("notify metered state change:", zap.String("new state", StateToString(s)))
for _, notifee := range nr.notifees {
notifee.HandleMeteredChange(s)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyRoamingChange(s State) {
nr.lock.Lock()

logger().Debug("notify roaming state change:", zap.String("new state", StateToString(s)))
for _, notifee := range nr.notifees {
notifee.HandleRoamingChange(s)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyTrustedChange(s State) {
nr.lock.Lock()

logger().Debug("notify trusted state change:", zap.String("new state", StateToString(s)))
for _, notifee := range nr.notifees {
notifee.HandleTrustedChange(s)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyNetTypeChange(n NetType) {
nr.lock.Lock()

logger().Debug("notify network type change:", zap.String("new type", NetTypeToString(n)))
for _, notifee := range nr.notifees {
notifee.HandleNetTypeChange(n)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyCellTypeChange(c CellType) {
nr.lock.Lock()

logger().Debug("notify cellular type change:", zap.String("new type", CellTypeToString(c)))
for _, notifee := range nr.notifees {
notifee.HandleCellTypeChange(c)
}

nr.lock.Unlock()
}

func (nr *notifier) notifyBluetoothChange(b BleState) {
nr.lock.Lock()

logger().Debug("notify bluetooth state change:", zap.String("new state", BleStateToString(b)))
for _, notifee := range nr.notifees {
notifee.HandleBluetoothChange(b)
}

nr.lock.Unlock()
}

func (nr *notifier) RegisterNotifee(ne Notifee) {
nr.lock.Lock()

nr.notifees = append(nr.notifees, ne)

nr.lock.Unlock()
}

func (nr *notifier) UnregisterNotifee(ne Notifee) {
nr.lock.Lock()

found := -1
for index, notifee := range nr.notifees {
if notifee == ne {
found = index
break
}
}

if found != -1 {
nr.notifees = append(nr.notifees[:found], nr.notifees[found+1:]...)
}

nr.lock.Unlock()
}
27 changes: 23 additions & 4 deletions core/network/state/state.go
Expand Up @@ -3,6 +3,7 @@ package state
type State int
type NetType int
type CellType int
type BleState int

const (
Unknown State = 0
Expand All @@ -16,9 +17,14 @@ const (
Cellular NetType = 4

UnknownCellType CellType = 0
Cell2G CellType = 1
Cell3G CellType = 2
Cell4G CellType = 3
None CellType = 1
Cell2G CellType = 2
Cell3G CellType = 3
Cell4G CellType = 4

UnknownBleState BleState = 0
BleOn BleState = 1
BleOff BleState = 2
)

type ConnectivityState struct {
Expand All @@ -30,7 +36,7 @@ type ConnectivityState struct {
Trusted State
Network NetType
Cellular CellType
Bluetooth State
Bluetooth BleState
}

func StateToString(s State) string {
Expand Down Expand Up @@ -61,6 +67,8 @@ func NetTypeToString(n NetType) string {

func CellTypeToString(c CellType) string {
switch c {
case None:
return "none"
case Cell2G:
return "2G"
case Cell3G:
Expand All @@ -71,3 +79,14 @@ func CellTypeToString(c CellType) string {
return "unknown"
}
}

func BleStateToString(b BleState) string {
switch b {
case BleOn:
return "on"
case BleOff:
return "off"
default:
return "unknown"
}
}
110 changes: 110 additions & 0 deletions core/network/state/updater.go
@@ -0,0 +1,110 @@
package state

import (
"encoding/json"
"sync"
)

type NetworkUpdater struct {
lock sync.Mutex
state ConnectivityState
notif notifier
}

var global NetworkUpdater

func Global() *NetworkUpdater { return &global }

func (nu *NetworkUpdater) GetState() ConnectivityState {
nu.lock.Lock()
stateCopy := nu.state
nu.lock.Unlock()

return stateCopy
}

func (nu *NetworkUpdater) UpdateConnectivityState(connState string) {
var newState ConnectivityState

if err := json.Unmarshal([]byte(connState), &newState); err != nil {
logger().Error("update connectivity state: JSON unmarshaling failed")
return
}

nu.lock.Lock()

if newState.Internet != nu.state.Internet || newState.Internet == Unknown {
go func() {
// Asynchronously call the time consuming function isInternetReachable() (ping latency/timeout)
if newState.Internet == Unknown {
if isInternetReachable() {
newState.Internet = On
} else {
newState.Internet = Off
}
}

if newState.Internet != nu.state.Internet {
nu.state.Internet = newState.Internet
nu.notif.notifyInternetChange(newState.Internet)
}
}()
}

if newState.VPN != nu.state.VPN {
nu.state.VPN = newState.VPN
nu.notif.notifyVPNChange(newState.VPN)
}

if newState.MDNS != nu.state.MDNS || newState.MDNS == Unknown {
go func() {
// Asynchronously call the time consuming function isMDNSCompatible() (ping latency/timeout)
if newState.MDNS == Unknown && newState.Network != UnknownNetType && newState.Network != Cellular {
if isMDNSCompatible() {
newState.MDNS = On
} else {
newState.MDNS = Off
}
}

if newState.MDNS != nu.state.MDNS {
nu.state.MDNS = newState.MDNS
nu.notif.notifyMDNSChange(newState.MDNS)
}
}()
}

if newState.Metered != nu.state.Metered {
nu.state.Metered = newState.Metered
nu.notif.notifyMeteredChange(newState.Metered)
}

if newState.Roaming != nu.state.Roaming {
nu.state.Roaming = newState.Roaming
nu.notif.notifyRoamingChange(newState.Roaming)
}

if newState.Trusted != nu.state.Trusted {
nu.state.Trusted = newState.Trusted
nu.notif.notifyTrustedChange(newState.Trusted)
}

if (newState.Network != nu.state.Network || newState.Cellular != nu.state.Cellular) && newState.Network == Cellular {
nu.notif.notifyCellTypeChange(newState.Cellular)
}
nu.state.Cellular = newState.Cellular

if newState.Network != nu.state.Network {
nu.state.Network = newState.Network
nu.notif.notifyNetTypeChange(newState.Network)
}

nu.lock.Unlock()
}

func (nu *NetworkUpdater) UpdateBluetoothState(bleState int) {
if State(bleState) != nu.state.Bluetooth {
nu.state.Bluetooth = State(bleState)
nu.notif.notifyBluetoothChange(State(bleState))
}
}

0 comments on commit a566ca6

Please sign in to comment.