From ccd4d4626763a1cdc40330730272b290927f5482 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 13 Mar 2015 08:33:00 -0400 Subject: [PATCH] Bug 1139453 - Send network UP/DOWN events on desktop Linux. r=valentin --- .../linux/nsNotifyAddrListener_Linux.cpp | 53 +++++++++++++++++++ .../system/linux/nsNotifyAddrListener_Linux.h | 3 ++ 2 files changed, 56 insertions(+) diff --git a/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp index 2fbf8d9340e..ca32f98582b 100644 --- a/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp +++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp @@ -8,6 +8,10 @@ #include #include #include +#ifndef MOZ_WIDGET_GONK +#include +#include +#endif #include "nsThreadUtils.h" #include "nsIObserverService.h" @@ -96,6 +100,51 @@ nsNotifyAddrListener::GetLinkType(uint32_t *aLinkType) 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; @@ -149,6 +198,10 @@ void nsNotifyAddrListener::OnNetlinkMessage(int aNetlinkSocket) if (networkChange && mAllowChangedEvent) { SendEvent(NS_NETWORK_LINK_DATA_CHANGED); } + + if (networkChange) { + checkLink(); + } } NS_IMETHODIMP diff --git a/netwerk/system/linux/nsNotifyAddrListener_Linux.h b/netwerk/system/linux/nsNotifyAddrListener_Linux.h index b303f127ab0..d6181b5e68b 100644 --- a/netwerk/system/linux/nsNotifyAddrListener_Linux.h +++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.h @@ -55,6 +55,9 @@ private: // 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);