Improve online status and location checks
This commit is contained in:
@@ -241,7 +241,7 @@ func addLocation(dl *DeviceLocation) {
|
|||||||
func GetApproximateInternetLocation() (net.IP, error) {
|
func GetApproximateInternetLocation() (net.IP, error) {
|
||||||
loc, ok := GetInternetLocation()
|
loc, ok := GetInternetLocation()
|
||||||
if !ok || loc.Best() == nil {
|
if !ok || loc.Best() == nil {
|
||||||
return nil, errors.New("no location data available")
|
return nil, errors.New("no device location data available")
|
||||||
}
|
}
|
||||||
return loc.Best().IP, nil
|
return loc.Best().IP, nil
|
||||||
}
|
}
|
||||||
@@ -259,7 +259,7 @@ func GetInternetLocation() (deviceLocations *DeviceLocations, ok bool) {
|
|||||||
// Get all assigned addresses.
|
// Get all assigned addresses.
|
||||||
v4s, v6s, err := GetAssignedAddresses()
|
v4s, v6s, err := GetAssignedAddresses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warningf("netenv: failed to get assigned addresses: %s", err)
|
log.Warningf("netenv: failed to get assigned addresses for device location: %s", err)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,27 +267,24 @@ func GetInternetLocation() (deviceLocations *DeviceLocations, ok bool) {
|
|||||||
v4ok, v6ok := getLocationFromInterfaces()
|
v4ok, v6ok := getLocationFromInterfaces()
|
||||||
|
|
||||||
// Try other methods for missing locations.
|
// Try other methods for missing locations.
|
||||||
if len(v4s) > 0 {
|
if len(v4s) > 0 && !v4ok {
|
||||||
if !v4ok {
|
_, err = getLocationFromTraceroute()
|
||||||
_, err = getLocationFromTraceroute()
|
if err != nil {
|
||||||
if err != nil {
|
log.Warningf("netenv: failed to get IPv4 device location from traceroute: %s", err)
|
||||||
log.Warningf("netenv: failed to get IPv4 from traceroute: %s", err)
|
} else {
|
||||||
} else {
|
v4ok = true
|
||||||
v4ok = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get location from timezone as final fallback.
|
||||||
if !v4ok {
|
if !v4ok {
|
||||||
v4ok = getLocationFromTimezone(packet.IPv4)
|
getLocationFromTimezone(packet.IPv4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(v6s) > 0 && !v6ok {
|
if len(v6s) > 0 && !v6ok {
|
||||||
// TODO
|
// TODO: Find more ways to get IPv6 device location
|
||||||
log.Warningf("netenv: could not get IPv6 location")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have any locations.
|
// Get location from timezone as final fallback.
|
||||||
if !v4ok && !v6ok {
|
getLocationFromTimezone(packet.IPv6)
|
||||||
return nil, false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return gathered locations.
|
// Return gathered locations.
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ var (
|
|||||||
onlineStatusInvestigationTrigger = make(chan struct{}, 1)
|
onlineStatusInvestigationTrigger = make(chan struct{}, 1)
|
||||||
onlineStatusInvestigationInProgress = abool.NewBool(false)
|
onlineStatusInvestigationInProgress = abool.NewBool(false)
|
||||||
onlineStatusInvestigationWg sync.WaitGroup
|
onlineStatusInvestigationWg sync.WaitGroup
|
||||||
|
onlineStatusNotification *notifications.Notification
|
||||||
|
|
||||||
captivePortal = &CaptivePortal{}
|
captivePortal = &CaptivePortal{}
|
||||||
captivePortalLock sync.Mutex
|
captivePortalLock sync.Mutex
|
||||||
@@ -186,7 +187,7 @@ func CheckAndGetOnlineStatus() OnlineStatus {
|
|||||||
func updateOnlineStatus(status OnlineStatus, portalURL *url.URL, comment string) {
|
func updateOnlineStatus(status OnlineStatus, portalURL *url.URL, comment string) {
|
||||||
changed := false
|
changed := false
|
||||||
|
|
||||||
// status
|
// Update online status.
|
||||||
currentStatus := atomic.LoadInt32(onlineStatus)
|
currentStatus := atomic.LoadInt32(onlineStatus)
|
||||||
if status != OnlineStatus(currentStatus) && atomic.CompareAndSwapInt32(onlineStatus, currentStatus, int32(status)) {
|
if status != OnlineStatus(currentStatus) && atomic.CompareAndSwapInt32(onlineStatus, currentStatus, int32(status)) {
|
||||||
// status changed!
|
// status changed!
|
||||||
@@ -196,10 +197,10 @@ func updateOnlineStatus(status OnlineStatus, portalURL *url.URL, comment string)
|
|||||||
changed = true
|
changed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// captive portal
|
// Update captive portal.
|
||||||
setCaptivePortal(portalURL)
|
setCaptivePortal(portalURL)
|
||||||
|
|
||||||
// trigger event
|
// Trigger events.
|
||||||
if changed {
|
if changed {
|
||||||
module.TriggerEvent(OnlineStatusChangedEvent, status)
|
module.TriggerEvent(OnlineStatusChangedEvent, status)
|
||||||
if status == StatusPortal {
|
if status == StatusPortal {
|
||||||
@@ -209,6 +210,9 @@ func updateOnlineStatus(status OnlineStatus, portalURL *url.URL, comment string)
|
|||||||
}
|
}
|
||||||
triggerNetworkChangeCheck()
|
triggerNetworkChangeCheck()
|
||||||
|
|
||||||
|
// Notify user.
|
||||||
|
notifyOnlineStatus(status)
|
||||||
|
|
||||||
// Trigger update check when coming (semi) online.
|
// Trigger update check when coming (semi) online.
|
||||||
if Online() {
|
if Online() {
|
||||||
_ = updates.TriggerUpdate(false)
|
_ = updates.TriggerUpdate(false)
|
||||||
@@ -216,11 +220,54 @@ func updateOnlineStatus(status OnlineStatus, portalURL *url.URL, comment string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func notifyOnlineStatus(status OnlineStatus) {
|
||||||
|
var eventID, title, message string
|
||||||
|
|
||||||
|
// Check if status is worth notifying.
|
||||||
|
switch status {
|
||||||
|
case StatusOffline:
|
||||||
|
eventID = "netenv:online-status:offline"
|
||||||
|
title = "Device is Offline"
|
||||||
|
message = "Portmaster did not detect any network connectivity."
|
||||||
|
case StatusLimited:
|
||||||
|
eventID = "netenv:online-status:limited"
|
||||||
|
title = "Limited network connectivity."
|
||||||
|
message = "Portmaster did detect local network connectivity, but could not detect connectivity to the Internet."
|
||||||
|
default:
|
||||||
|
// Delete notification, if present.
|
||||||
|
if onlineStatusNotification != nil {
|
||||||
|
onlineStatusNotification.Delete()
|
||||||
|
onlineStatusNotification = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update notification if not present or online status changed.
|
||||||
|
switch {
|
||||||
|
case onlineStatusNotification == nil:
|
||||||
|
// Continue creating new notification.
|
||||||
|
case onlineStatusNotification.EventID == eventID:
|
||||||
|
// Notification stays the same, stick with the old one.
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
// Delete old notification before triggering updated one.
|
||||||
|
onlineStatusNotification.Delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create update status notification.
|
||||||
|
onlineStatusNotification = notifications.Notify(¬ifications.Notification{
|
||||||
|
EventID: eventID,
|
||||||
|
Type: notifications.Info,
|
||||||
|
Title: title,
|
||||||
|
Message: message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func setCaptivePortal(portalURL *url.URL) {
|
func setCaptivePortal(portalURL *url.URL) {
|
||||||
captivePortalLock.Lock()
|
captivePortalLock.Lock()
|
||||||
defer captivePortalLock.Unlock()
|
defer captivePortalLock.Unlock()
|
||||||
|
|
||||||
// delete
|
// Delete captive portal if no url is supplied.
|
||||||
if portalURL == nil {
|
if portalURL == nil {
|
||||||
captivePortal = &CaptivePortal{}
|
captivePortal = &CaptivePortal{}
|
||||||
if captivePortalNotification != nil {
|
if captivePortalNotification != nil {
|
||||||
@@ -230,12 +277,12 @@ func setCaptivePortal(portalURL *url.URL) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// return if unchanged
|
// Only set captive portal once per detection.
|
||||||
if portalURL.String() == captivePortal.URL {
|
if captivePortal.URL != "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// set
|
// Compile captive portal data.
|
||||||
captivePortal = &CaptivePortal{
|
captivePortal = &CaptivePortal{
|
||||||
URL: portalURL.String(),
|
URL: portalURL.String(),
|
||||||
}
|
}
|
||||||
@@ -247,7 +294,7 @@ func setCaptivePortal(portalURL *url.URL) {
|
|||||||
captivePortal.Domain = portalURL.Hostname()
|
captivePortal.Domain = portalURL.Hostname()
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify
|
// Notify user about portal.
|
||||||
captivePortalNotification = notifications.Notify(¬ifications.Notification{
|
captivePortalNotification = notifications.Notify(¬ifications.Notification{
|
||||||
EventID: "netenv:captive-portal",
|
EventID: "netenv:captive-portal",
|
||||||
Type: notifications.Info,
|
Type: notifications.Info,
|
||||||
|
|||||||
Reference in New Issue
Block a user