☠☠ backed out by 980d33b2ca6c ☠ ☠ | |
author | Daniel Stenberg <daniel@haxx.se> |
Tue, 14 Oct 2014 04:44:00 -0400 | |
changeset 210350 | 8754d79ca14c1b58d13408533637066b3ddce47b |
parent 210349 | f8bb9368beb1f0e7d4d50efccf69beee0af5d372 |
child 210351 | 1ac8890ee0a354c51824bc0597ea00c5b72110dc |
push id | 27651 |
push user | kwierso@gmail.com |
push date | Wed, 15 Oct 2014 00:18:02 +0000 |
treeherder | mozilla-central@62f0b771583c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sworkman |
bugs | 1008091 |
milestone | 36.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
|
--- a/netwerk/build/moz.build +++ b/netwerk/build/moz.build @@ -53,16 +53,21 @@ if CONFIG['MOZ_ENABLE_QTNETWORK']: '../system/qt', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': LOCAL_INCLUDES += [ '../system/android', ] +elif CONFIG['OS_ARCH'] == 'Linux': + LOCAL_INCLUDES += [ + '../system/linux', + ] + if CONFIG['NECKO_COOKIES']: LOCAL_INCLUDES += [ '../cookie', ] if CONFIG['NECKO_WIFI']: LOCAL_INCLUDES += [ '../wifi',
--- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -372,16 +372,19 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNo #include "nsNetworkLinkService.h" NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetworkLinkService, Init) #elif defined(MOZ_ENABLE_QTNETWORK) #include "nsQtNetworkLinkService.h" NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsQtNetworkLinkService, Init) #elif defined(MOZ_WIDGET_ANDROID) #include "nsAndroidNetworkLinkService.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidNetworkLinkService) +#elif defined(XP_LINUX) +#include "nsNotifyAddrListener_Linux.h" +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNotifyAddrListener, Init) #endif /////////////////////////////////////////////////////////////////////////////// #ifdef NECKO_PROTOCOL_ftp #include "nsFTPDirListingConv.h" nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result); #endif @@ -793,16 +796,18 @@ NS_DEFINE_NAMED_CID(NS_RTSPPROTOCOLHANDL #if defined(XP_WIN) NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); #elif defined(MOZ_WIDGET_COCOA) NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); #elif defined(MOZ_ENABLE_QTNETWORK) NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); #elif defined(MOZ_WIDGET_ANDROID) NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); +#elif defined(XP_LINUX) +NS_DEFINE_NAMED_CID(NS_NETWORK_LINK_SERVICE_CID); #endif NS_DEFINE_NAMED_CID(NS_SERIALIZATION_HELPER_CID); NS_DEFINE_NAMED_CID(NS_REDIRECTCHANNELREGISTRAR_CID); NS_DEFINE_NAMED_CID(NS_CACHE_STORAGE_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_NETWORKPREDICTOR_CID); static const mozilla::Module::CIDEntry kNeckoCIDs[] = { { &kNS_IOSERVICE_CID, false, nullptr, nsIOServiceConstructor }, @@ -937,16 +942,18 @@ static const mozilla::Module::CIDEntry k #if defined(XP_WIN) { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsNotifyAddrListenerConstructor }, #elif defined(MOZ_WIDGET_COCOA) { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsNetworkLinkServiceConstructor }, #elif defined(MOZ_ENABLE_QTNETWORK) { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsQtNetworkLinkServiceConstructor }, #elif defined(MOZ_WIDGET_ANDROID) { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsAndroidNetworkLinkServiceConstructor }, +#elif defined(XP_LINUX) + { &kNS_NETWORK_LINK_SERVICE_CID, false, nullptr, nsNotifyAddrListenerConstructor }, #endif { &kNS_SERIALIZATION_HELPER_CID, false, nullptr, nsSerializationHelperConstructor }, { &kNS_REDIRECTCHANNELREGISTRAR_CID, false, nullptr, RedirectChannelRegistrarConstructor }, { &kNS_CACHE_STORAGE_SERVICE_CID, false, nullptr, CacheStorageServiceConstructor }, { &kNS_NETWORKPREDICTOR_CID, false, nullptr, mozilla::net::Predictor::Create }, { nullptr } }; @@ -1084,16 +1091,18 @@ static const mozilla::Module::ContractID #if defined(XP_WIN) { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, #elif defined(MOZ_WIDGET_COCOA) { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, #elif defined(MOZ_ENABLE_QTNETWORK) { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, #elif defined(MOZ_WIDGET_ANDROID) { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, +#elif defined(XP_LINUX) + { NS_NETWORK_LINK_SERVICE_CONTRACTID, &kNS_NETWORK_LINK_SERVICE_CID }, #endif { NS_SERIALIZATION_HELPER_CONTRACTID, &kNS_SERIALIZATION_HELPER_CID }, { NS_REDIRECTCHANNELREGISTRAR_CONTRACTID, &kNS_REDIRECTCHANNELREGISTRAR_CID }, { NS_CACHE_STORAGE_SERVICE_CONTRACTID, &kNS_CACHE_STORAGE_SERVICE_CID }, { NS_CACHE_STORAGE_SERVICE_CONTRACTID2, &kNS_CACHE_STORAGE_SERVICE_CID }, { NS_NETWORKPREDICTOR_CONTRACTID, &kNS_NETWORKPREDICTOR_CID }, { nullptr } };
new file mode 100644 --- /dev/null +++ b/netwerk/system/linux/moz.build @@ -0,0 +1,14 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +if CONFIG['OS_ARCH'] == 'Linux': + SOURCES += [ + 'nsNotifyAddrListener_Linux.cpp', + ] + +FAIL_ON_WARNINGS = True + +FINAL_LIBRARY = 'xul'
new file mode 100644 --- /dev/null +++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.cpp @@ -0,0 +1,269 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set et sw=4 ts=4: */ +/* 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 "nsThreadUtils.h" +#include "nsIObserverService.h" +#include "nsServiceManagerUtils.h" +#include "nsNotifyAddrListener_Linux.h" +#include "nsString.h" +#include "nsAutoPtr.h" +#include "mozilla/Services.h" +#include "mozilla/Preferences.h" + +using namespace mozilla; + +#define NETWORK_NOTIFY_CHANGED_PREF "network.notify.changed" + + +NS_IMPL_ISUPPORTS(nsNotifyAddrListener, + nsINetworkLinkService, + nsIRunnable, + nsIObserver) + +nsNotifyAddrListener::nsNotifyAddrListener() + : mLinkUp(true) // assume true by default + , mStatusKnown(false) + , mAllowChangedEvent(true) +{ +} + +nsNotifyAddrListener::~nsNotifyAddrListener() +{ + NS_ASSERTION(!mThread, "nsNotifyAddrListener thread shutdown failed"); + + close(mShutdownPipe[0]); + close(mShutdownPipe[1]); +} + +NS_IMETHODIMP +nsNotifyAddrListener::GetIsLinkUp(bool *aIsUp) +{ + // XXX This function has not yet been implemented for this platform + *aIsUp = mLinkUp; + return NS_OK; +} + +NS_IMETHODIMP +nsNotifyAddrListener::GetLinkStatusKnown(bool *aIsUp) +{ + // XXX This function has not yet been implemented for this platform + *aIsUp = mStatusKnown; + return NS_OK; +} + +NS_IMETHODIMP +nsNotifyAddrListener::GetLinkType(uint32_t *aLinkType) +{ + NS_ENSURE_ARG_POINTER(aLinkType); + + // XXX This function has not yet been implemented for this platform + *aLinkType = nsINetworkLinkService::LINK_TYPE_UNKNOWN; + return NS_OK; +} + +void nsNotifyAddrListener::OnNetlinkMessage(int aNetlinkSocket) +{ + struct nlmsghdr *nlh; + struct rtmsg *route_entry; + char buffer[4095]; + + NS_ASSERTION(aNetlinkSocket >= 0, "bad aNetlinkSocket"); + + // Receiving netlink socket data + ssize_t rc = recv(aNetlinkSocket, buffer, sizeof(buffer), 0); + if (rc < 0) { + // LOG this? + return; + } + size_t netlink_bytes = rc; + + nlh = reinterpret_cast<struct nlmsghdr *>(buffer); + + bool networkChange = false; + + for (; NLMSG_OK(nlh, netlink_bytes); + nlh = NLMSG_NEXT(nlh, netlink_bytes)) { + + if (NLMSG_DONE == nlh->nlmsg_type) { + break; + } + + switch(nlh->nlmsg_type) { + case RTM_DELROUTE: + case RTM_NEWROUTE: + // Get the route data + route_entry = static_cast<struct rtmsg *>(NLMSG_DATA(nlh)); + + // We are just intrested in main routing table + if (route_entry->rtm_table != RT_TABLE_MAIN) + continue; + + networkChange = true; + break; + + case RTM_NEWADDR: + networkChange = true; + break; + + default: + continue; + } + } + + if (networkChange && mAllowChangedEvent) { + SendEvent(NS_NETWORK_LINK_DATA_CHANGED); + } +} + +NS_IMETHODIMP +nsNotifyAddrListener::Run() +{ + PR_SetCurrentThreadName("Link Monitor"); + + int netlinkSocket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (netlinkSocket < 0) { + return NS_ERROR_FAILURE; + } + + struct sockaddr_nl addr; + memset(&addr, 0, sizeof(addr)); // clear addr + + addr.nl_family = AF_NETLINK; + addr.nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR | + RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE; + + if (bind(netlinkSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + // failure! + close(netlinkSocket); + return NS_ERROR_FAILURE; + } + + // switch the socket into non-blocking + int flags = fcntl(netlinkSocket, F_GETFL, 0); + (void)fcntl(netlinkSocket, F_SETFL, flags | O_NONBLOCK); + + + struct pollfd fds[2]; + fds[0].fd = mShutdownPipe[0]; + fds[0].events = POLLIN; + fds[0].revents = 0; + + fds[1].fd = netlinkSocket; + fds[1].events = POLLIN; + fds[1].revents = 0; + + nsresult rv = NS_OK; + bool shutdown = false; + while (!shutdown) { + int rc = poll(fds, 2, -1); + if (rc > 0) { + if (fds[0].revents & POLLIN) { + // shutdown, abort the loop! + shutdown = true; + } else if (fds[1].revents & POLLIN) { + OnNetlinkMessage(netlinkSocket); + } + } else if (rc < 0) { + rv = NS_ERROR_FAILURE; + break; + } + } + + close(netlinkSocket); + + return rv; +} + +NS_IMETHODIMP +nsNotifyAddrListener::Observe(nsISupports *subject, + const char *topic, + const char16_t *data) +{ + if (!strcmp("xpcom-shutdown-threads", topic)) { + Shutdown(); + } + + return NS_OK; +} + +nsresult +nsNotifyAddrListener::Init(void) +{ + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (!observerService) + return NS_ERROR_FAILURE; + + nsresult rv = observerService->AddObserver(this, "xpcom-shutdown-threads", + false); + NS_ENSURE_SUCCESS(rv, rv); + + Preferences::AddBoolVarCache(&mAllowChangedEvent, + NETWORK_NOTIFY_CHANGED_PREF, true); + + rv = NS_NewThread(getter_AddRefs(mThread), this); + NS_ENSURE_SUCCESS(rv, rv); + + if (-1 == pipe(mShutdownPipe)) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + +nsresult +nsNotifyAddrListener::Shutdown(void) +{ + // remove xpcom shutdown observer + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (observerService) + observerService->RemoveObserver(this, "xpcom-shutdown-threads"); + + // awake the thread to make it terminate + write(mShutdownPipe[1], "1", 1); + + nsresult rv = mThread->Shutdown(); + + // Have to break the cycle here, otherwise nsNotifyAddrListener holds + // onto the thread and the thread holds onto the nsNotifyAddrListener + // via its mRunnable + mThread = nullptr; + + return rv; +} + +/* Sends the given event. Assumes aEventID never goes out of scope (static + * strings are ideal). + */ +nsresult +nsNotifyAddrListener::SendEvent(const char *aEventID) +{ + if (!aEventID) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + nsCOMPtr<nsIRunnable> event = new ChangeEvent(this, aEventID); + if (NS_FAILED(rv = NS_DispatchToMainThread(event))) + NS_WARNING("Failed to dispatch ChangeEvent"); + return rv; +} + +NS_IMETHODIMP +nsNotifyAddrListener::ChangeEvent::Run() +{ + nsCOMPtr<nsIObserverService> observerService = + mozilla::services::GetObserverService(); + if (observerService) + observerService->NotifyObservers( + mService, NS_NETWORK_LINK_TOPIC, + NS_ConvertASCIItoUTF16(mEventID).get()); + return NS_OK; +}
new file mode 100644 --- /dev/null +++ b/netwerk/system/linux/nsNotifyAddrListener_Linux.h @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set et sw=4 ts=4: */ +/* 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/. */ +#ifndef NSNOTIFYADDRLISTENER_LINUX_H_ +#define NSNOTIFYADDRLISTENER_LINUX_H_ + +#include <sys/socket.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <arpa/inet.h> +#include <unistd.h> + +#include "nsINetworkLinkService.h" +#include "nsIRunnable.h" +#include "nsIObserver.h" +#include "nsThreadUtils.h" +#include "nsCOMPtr.h" +#include "mozilla/TimeStamp.h" + +class nsNotifyAddrListener : public nsINetworkLinkService, + public nsIRunnable, + public nsIObserver +{ + virtual ~nsNotifyAddrListener(); + +public: + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSINETWORKLINKSERVICE + NS_DECL_NSIRUNNABLE + NS_DECL_NSIOBSERVER + + nsNotifyAddrListener(); + nsresult Init(void); + +private: + class ChangeEvent : public nsRunnable { + public: + NS_DECL_NSIRUNNABLE + ChangeEvent(nsINetworkLinkService *aService, const char *aEventID) + : mService(aService), mEventID(aEventID) { + } + private: + nsCOMPtr<nsINetworkLinkService> mService; + const char *mEventID; + }; + + // Called when xpcom-shutdown-threads is received. + nsresult Shutdown(void); + + // Sends the network event. + nsresult SendEvent(const char *aEventID); + + // Deals with incoming NETLINK messages. + void OnNetlinkMessage(int NetlinkSocket); + + nsCOMPtr<nsIThread> mThread; + + // The network is up. + bool mLinkUp; + + // The network's up/down status is known. + bool mStatusKnown; + + // A pipe to signal shutdown with. + int mShutdownPipe[2]; + + // Network changed events are enabled + bool mAllowChangedEvent; +}; + +#endif /* NSNOTIFYADDRLISTENER_LINUX_H_ */
--- a/netwerk/system/moz.build +++ b/netwerk/system/moz.build @@ -11,8 +11,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco DIRS += ['mac'] if CONFIG['MOZ_ENABLE_QTNETWORK']: DIRS += ['qt'] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': DIRS += ['android'] +elif CONFIG['OS_ARCH'] == 'Linux': + DIRS += ['linux']