Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(network): implemented state notifier and updater
- Loading branch information
Showing
4 changed files
with
312 additions
and
4 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)) | ||
} | ||
} |