NetWatcher: detect when networkmanager has lost network connection

This is a better approach to finding both when NM has lost a network
connection, and when a new network connection is made by NM.

Tested with network-manager 0.9.8.8.

This commit was sponsored by Cedric Staub.
This commit is contained in:
Joey Hess 2014-04-12 17:58:19 -04:00
parent a33b30d0c4
commit bb44df206d
2 changed files with 37 additions and 25 deletions

View file

@ -22,7 +22,6 @@ import Utility.NotificationBroadcaster
import Utility.DBus import Utility.DBus
import DBus.Client import DBus.Client
import DBus import DBus
import Data.Word (Word32)
import Assistant.NetMessager import Assistant.NetMessager
#else #else
#ifdef linux_HOST_OS #ifdef linux_HOST_OS
@ -63,15 +62,19 @@ dbusThread = do
where where
go client = ifM (checkNetMonitor client) go client = ifM (checkNetMonitor client)
( do ( do
listenNMConnections client <~> handleconn callback <- asIO1 connchange
listenWicdConnections client <~> handleconn liftIO $ do
listenNMConnections client callback
listenWicdConnections client callback
, do , do
liftAnnex $ liftAnnex $
warning "No known network monitor available through dbus; falling back to polling" warning "No known network monitor available through dbus; falling back to polling"
) )
handleconn = do connchange False = do
debug ["detected network connection"] debug ["detected network disconnection"]
sendRemoteControl LOSTNET sendRemoteControl LOSTNET
connchange True = do
debug ["detected network connection"]
notifyNetMessagerRestart notifyNetMessagerRestart
handleConnection handleConnection
sendRemoteControl RESUME sendRemoteControl RESUME
@ -99,31 +102,40 @@ checkNetMonitor client = do
networkmanager = "org.freedesktop.NetworkManager" networkmanager = "org.freedesktop.NetworkManager"
wicd = "org.wicd.daemon" wicd = "org.wicd.daemon"
{- Listens for new NetworkManager connections. -} {- Listens for NetworkManager connections and diconnections.
listenNMConnections :: Client -> IO () -> IO () -
listenNMConnections client callback = - Connection example (once fully connected):
listen client matcher $ \event -> - [Variant {"ActivatingConnection": Variant (ObjectPath "/"), "PrimaryConnection": Variant (ObjectPath "/org/freedesktop/NetworkManager/ActiveConnection/34"), "State": Variant 70}]
when (Just True == anyM activeconnection (signalBody event)) $ -
callback - Disconnection example:
- [Variant {"ActiveConnections": Variant []}]
-}
listenNMConnections :: Client -> (Bool -> IO ()) -> IO ()
listenNMConnections client setconnected =
listen client matcher $ \event -> mapM_ handle
(map dictionaryItems $ mapMaybe fromVariant $ signalBody event)
where where
matcher = matchAny matcher = matchAny
{ matchInterface = Just "org.freedesktop.NetworkManager.Connection.Active" { matchInterface = Just "org.freedesktop.NetworkManager"
, matchMember = Just "PropertiesChanged" , matchMember = Just "PropertiesChanged"
} }
nm_connection_activated = toVariant (2 :: Word32) nm_active_connections_key = toVariant ("ActiveConnections" :: String)
nm_state_key = toVariant ("State" :: String) nm_activatingconnection_key = toVariant ("ActivatingConnection" :: String)
activeconnection v = do noconnections = Just $ toVariant $ toVariant ([] :: [ObjectPath])
m <- fromVariant v rootconnection = Just $ toVariant $ toVariant $ objectPath_ "/"
vstate <- lookup nm_state_key $ dictionaryItems m handle m
state <- fromVariant vstate | lookup nm_active_connections_key m == noconnections =
return $ state == nm_connection_activated setconnected False
| lookup nm_activatingconnection_key m == rootconnection =
setconnected True
| otherwise = noop
{- Listens for new Wicd connections. -} {- Listens for Wicd connections (not currently disconnections). -}
listenWicdConnections :: Client -> IO () -> IO () listenWicdConnections :: Client -> (Bool -> IO ()) -> IO ()
listenWicdConnections client callback = listenWicdConnections client callback =
listen client matcher $ \event -> listen client matcher $ \event ->
when (any (== wicd_success) (signalBody event)) $ when (any (== wicd_success) (signalBody event)) $
callback callback False >> callback True
where where
matcher = matchAny matcher = matchAny
{ matchInterface = Just "org.wicd.daemon" { matchInterface = Just "org.wicd.daemon"

View file

@ -164,9 +164,9 @@ No pushing is done for CHANGED, since git handles ssh natively.
TODO: TODO:
* The NetWatcher does not detect network loss, only network gain, * For wicd, the NetWatcher does not detect network loss, only network gain.
so PAUSE is only sent when a new network is detected, followed So PAUSE is only sent when a new network is detected, followed
immediately by RESUME. immediately by RESUME. This was already fixed for networkmanager.
* Remote system might not be available. Find a smart way to detect it, * Remote system might not be available. Find a smart way to detect it,
ideally w/o generating network traffic. One way might be to check ideally w/o generating network traffic. One way might be to check
if the ssh connection caching control socket exists, for example. if the ssh connection caching control socket exists, for example.