Feature #2443
closedNetworkMonitor class to detect network state changes
Added by Alex Afanasyev almost 10 years ago. Updated almost 10 years ago.
100%
Description
The immediate use of this class will be in ndn-autoconfig (daemon mode), but it can be used by other applications too.
Here is the interface for this class:
/**
* @brief Network state change monitor
*
* When network change is detected, onNetworkStateChanged signal will be fired.
* Monitoring is run for the lifetime of the NetworkMonitor instance.
*
* @note Implementation of this class is platform dependent and not all supported platforms
* are supported:
* - OS X: CFNotificationCenterAddObserver
* - Linux: dbus
*/
class NetworkMonitor
{
public:
/**
* @brief Construct instance and start monitoring for network state changes
* @param io io_service thread that will dispatch events
*/
NetworkMonitor(boost::asio::io_service& io);
/**
* @brief Terminate network state monitoring
*/
~NetworkMonitor();
Signal<NetworkMonitor> onNetworkStateChanged;
};
Updated by Alex Afanasyev almost 10 years ago
I already implemented OSX part and now trying to figure out the best way to make use of DBus. My current proposal is to import a slightly modified version of https://github.com/bkietz/boost-dbus repo (BOOST 1.0 license, which is compatible and we are already using other components with this license).
I was initially trying to use just libdbus (it still be needed), but got stuck with basic things.
Updated by Junxiao Shi almost 10 years ago
Define what is "network state change".
Implementation of this class is platform dependent and not all supported platforms are supported
When NetworkMonitor is used on a non-supported platform, does the constructor throw an exception?
Otherwise, add a static bool isSupported()
method so that caller can determine whether this utility can be relied upon.
Updated by Alex Afanasyev almost 10 years ago
Unfortunately, I don't have exact definition. However, these should include IP address changes and interfaces going up/down. OSX triggers me 2 events when I disconnect my wired connection and 6 after it is connected (after interface is up, after it got some initial address, after it got normal address.. i don't know why 6 exactly).
For non-supported platforms, I was planning simply doing nothing without any message... I will add isSupported() method.
Updated by Junxiao Shi almost 10 years ago
Unfortunately, I don't have exact definition. However, these should include IP address changes and interfaces going up/down. OSX triggers me 2 events when I disconnect my wired connection and 6 after it is connected (after interface is up, after it got some initial address, after it got normal address.. i don't know why 6 exactly).
The documentation should at least say what conditions must cause NetworkMonitor
to emit a signal.
Integration tests can then be developed to test those conditions.
Feasibility of automated tests is a separate question.
Updated by Davide Pesavento almost 10 years ago
An 'isSupported` method sounds useful.
It's not clear what you mean by using dbus on Linux. dbus is just an IPC mechanism, what do you do with it?
Updated by Davide Pesavento almost 10 years ago
Also note that libdbus itself is not supposed to be used by applications directly, quoting from http://www.freedesktop.org/wiki/Software/dbus/ :
It should be noted that the low-level implementation [i.e. libdbus] is not primarily designed for application authors to use. Rather, it is a basis for binding authors and a reference for reimplementations. If you are able to do so it is recommended that you use one of the higher level bindings or implementations.
Updated by Alex Afanasyev almost 10 years ago
It's not clear what you mean by using dbus on Linux. dbus is just an IPC mechanism, what do you do with it?
I meant that on Linux I'm planning (implementing it) using dbus IPC to receive notifications from org.freedesktop.NetworkManager (http://people.redhat.com/dcbw/NetworkManager/NetworkManager%20DBUS%20API.txt). This doesn't cover all linuxes, but should have pretty good coverage for the desktop systems, where we actually need network monitoring (in ndn-autoconfig daemon mode).
Updated by Alex Afanasyev almost 10 years ago
- % Done changed from 50 to 90
I'm kind of finished with both OS X and Linux parts now. Will do some code cleanup before submitting for the review.
Updated by Junxiao Shi almost 10 years ago
How do you plan to test this utility?
I feel some semi-automated or manual testing is needed.
Make a standalone testing tool (under integrated-tests):
- call
isSupported()
, exit with 1 if it returns false - connect to the signal, print current time whenever the signal is emitted
- quit upon CTRL+C
This shall be accompanied by a document of:
- a list of conditions that MUST trigger a signal, eg. NIC added, NIC became up, IPv4 address added, IPv6 address added, etc
- a list of conditions that MUST NOT trigger a signal, eg. another process joined a multicast group
Updated by Alex Afanasyev almost 10 years ago
I realized that in some cases, NetworkManager constructor needs to throw an error. Specifically in dbus case, there is an exception when an app cannot connect to the selected bus. Therefore, I'm implementing a generic NetworkManager::Error exception potentially thrown in the constructor that will indicate that something is not right with monitoring.
Updated by Davide Pesavento almost 10 years ago
Alex Afanasyev wrote:
I meant that on Linux I'm planning (implementing it) using dbus IPC to receive notifications from org.freedesktop.NetworkManager (http://people.redhat.com/dcbw/NetworkManager/NetworkManager%20DBUS%20API.txt). This doesn't cover all linuxes, but should have pretty good coverage for the desktop systems, where we actually need network monitoring (in ndn-autoconfig daemon mode).
Not everyone uses NM... anyway, the best way to do this would be to subscribe to the kernel's netlink notifications. That way you don't need dbus and you don't depend on any other userspace components.
Also, having more fine-grained signals for the different changes would be nice (see also my old comments in #1584).
Updated by Alex Afanasyev almost 10 years ago
- a list of conditions that MUST NOT trigger a signal, eg. another process joined a multicast group
I don't think we need to specify these conditions. At least I don't quite know the exact conditions for notifications and we just really need positive signals. I would say we are ok with having more notifications that we need.
Updated by Junxiao Shi almost 10 years ago
- a list of conditions that MUST NOT trigger a signal, eg. another process joined a multicast group
I don't think we need to specify these conditions. At least I don't quite know the exact conditions for notifications and we just really need positive signals. I would say we are ok with having more notifications that we need.
A negative list is necessary, otherwise I could make a NetworkMonitor which emits a signal every millisecond, and claims it a correct solution.
Updated by Alex Afanasyev almost 10 years ago
- Status changed from In Progress to Code review
- % Done changed from 90 to 100
Updated by Junxiao Shi almost 10 years ago
The following MANUAL TEST procedure is recommended:
- ensure laptop is connected to WiFi, and Ethernet cable is unplugged
- run
build/tests/integrated/network-monitor
- disconnect from WiFi; expect the program to display one or more log lines
- connect to WiFi; expect the program to display one or more log lines
- physically disable WiFi card (most laptops have a keyboard shortcut or button for this); expect the program to display one or more log lines
- plug in Ethernet cable; expect the program to display one or more log lines
- unplug Ethernet cable; expect the program to display one or more log lines
Updated by Alex Afanasyev almost 10 years ago
I have abandoned my effort to use NetworkMonitor (too many unnecessary complexities with working with dbus) and have implemented basis detector using rtnetlink as Davide originally suggested. I did basic test and it seem to be working pretty good.
Updated by Junxiao Shi almost 10 years ago
During the manual test of commit:55bd7f3e391993832e69e73565640b32df385324, I notice that one action could lead to 8~20 signals.
I suggest adding a throttling facility in NetworkMonitor
class.
This ensures no more than one signal can be emitted in every 10 seconds.
Upon each notification from Impl
, run the following procedure:
- if last signal was emitted more than 10 seconds ago, go to step 4
- if another instance of this procedure is running, abort that instance
- wait 10 seconds
- emit the signal
Updated by Alex Afanasyev almost 10 years ago
I was expecting such throttling to be implemented by the user of this class (as I did in ndn-autoconf).
Updated by Junxiao Shi almost 10 years ago
Please compare the benefit and drawback between:
- throttle in
NetworkMonitor
- throttle in user of
NetworkMonitor
Updated by Davide Pesavento almost 10 years ago
I agree with Alex. Even if there are several changes in a short period of time, the monitor should report all of them. If frequent changes are a problem for a particular consumer of this facility, it's the consumer's responsibility to throttle its own responses to the event.
Updated by Alex Afanasyev almost 10 years ago
- Status changed from Code review to Closed