Bug 1139453 - Send network UP/DOWN events on desktop Linux. r=valentin
authorDaniel Stenberg <daniel@haxx.se>
Fri, 13 Mar 2015 08:33:00 -0400
changeset 233572 a80860d9add6800c365fbc3ae109ae952c95a2b0
parent 233571 c05f34c01e6d741a10278a87019bb296b6d3c00d
child 233573 781b06b48e029ecc813bf52aa1fa7f49ab2f7631
push id28417
push userryanvm@gmail.com
push dateFri, 13 Mar 2015 19:52:44 +0000
treeherdermozilla-central@977add19414a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvalentin
bugs1139453
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1139453 - Send network UP/DOWN events on desktop Linux. r=valentin
netwerk/system/linux/nsNotifyAddrListener_Linux.cpp
netwerk/system/linux/nsNotifyAddrListener_Linux.h
--- a/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp
+++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp
@@ -3,16 +3,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdarg.h>
 #include <fcntl.h>
 #include <poll.h>
 #include <errno.h>
+#ifndef MOZ_WIDGET_GONK
+#include <ifaddrs.h>
+#include <net/if.h>
+#endif
 
 #include "nsThreadUtils.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsNotifyAddrListener_Linux.h"
 #include "nsString.h"
 #include "nsAutoPtr.h"
 #include "prlog.h"
@@ -91,16 +95,61 @@ nsNotifyAddrListener::GetLinkType(uint32
 {
   NS_ENSURE_ARG_POINTER(aLinkType);
 
   // XXX This function has not yet been implemented for this platform
   *aLinkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN;
   return NS_OK;
 }
 
+//
+// Check if there's a network interface available to do networking on.
+//
+void nsNotifyAddrListener::checkLink(void)
+{
+#ifdef MOZ_WIDGET_GONK
+    // b2g instead has NetworkManager.js which handles UP/DOWN
+#else
+    struct ifaddrs *list;
+    struct ifaddrs *ifa;
+    bool link = false;
+    bool prevLinkUp = mLinkUp;
+
+    if(getifaddrs(&list))
+        return;
+
+    // Walk through the linked list, maintaining head pointer so we can free
+    // list later
+
+    for (ifa = list; ifa != NULL; ifa = ifa->ifa_next) {
+        int family;
+        if (ifa->ifa_addr == NULL)
+            continue;
+
+        family = ifa->ifa_addr->sa_family;
+
+        if ((family == AF_INET || family == AF_INET6) &&
+            (ifa->ifa_flags & IFF_UP) &&
+            !(ifa->ifa_flags & IFF_LOOPBACK)) {
+            // An interface that is UP and not loopback
+            link = true;
+            break;
+        }
+    }
+    mLinkUp = link;
+    freeifaddrs(list);
+
+    if (prevLinkUp != mLinkUp) {
+        // UP/DOWN status changed, send appropriate UP/DOWN event
+        SendEvent(mLinkUp ?
+                  NS_NETWORK_LINK_DATA_UP : NS_NETWORK_LINK_DATA_DOWN);
+    }
+#endif
+}
+
 void nsNotifyAddrListener::OnNetlinkMessage(int aNetlinkSocket)
 {
     struct  nlmsghdr *nlh;
     struct  rtmsg *route_entry;
 
     // The buffer size below, (4095) was chosen partly based on testing and
     // partly on existing sample source code using this size. It needs to be
     // large enough to hold the netlink messages from the kernel.
@@ -144,16 +193,20 @@ void nsNotifyAddrListener::OnNetlinkMess
         default:
             continue;
         }
     }
 
     if (networkChange && mAllowChangedEvent) {
         SendEvent(NS_NETWORK_LINK_DATA_CHANGED);
     }
+
+    if (networkChange) {
+        checkLink();
+    }
 }
 
 NS_IMETHODIMP
 nsNotifyAddrListener::Run()
 {
     int netlinkSocket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
     if (netlinkSocket < 0) {
         return NS_ERROR_FAILURE;
--- a/netwerk/system/linux/nsNotifyAddrListener_Linux.h
+++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.h
@@ -50,16 +50,19 @@ private:
     };
 
     // Called when xpcom-shutdown-threads is received.
     nsresult Shutdown(void);
 
     // Sends the network event.
     nsresult SendEvent(const char *aEventID);
 
+    // Checks if there's a network "link"
+    void checkLink(void);
+
     // Deals with incoming NETLINK messages.
     void OnNetlinkMessage(int NetlinkSocket);
 
     nsCOMPtr<nsIThread> mThread;
 
     // The network is up.
     bool mLinkUp;