Autogenerated with:
cp dom/.clang-format netwerk/ && mach format netwerk/**.{cpp,h,mm}
Manual fixes:
* mozurl/cbindgen.toml (including headers earlier)
* NetlinkService.h (forward-declaring a necessary struct)
* nsIWebSocketChannel.idl (forward-declaring OriginAttributes).
* nsAsyncRedirectVerifyHelper.h (forward-declaring nsIEventTarget)
* CapsuleEncoder.h gets a missing Capsule forward-decl.
* WebSocketConnectionBase.h gets some missing includes.
* HappyEyeballsConnectionAttempt gets some missing includes.
* nsUDPSocket missed nsSocketTransportService2.h for OnSocketThread().
* HttpInfo missed a forward declaration.
* MockHttpAuth missed an nsCOMPtr include.
* nsHttpAuthManager missed a forward declaration for nsIHttpAuthCache.
* WebTransportSessionProxy was using mozilla::Mutex in a member without
including it.
* win32 fixes to keep include order because windows headers suck.
* nsInputStreamPump needs an Atomics.h include.
Differential Revision: https://phabricator.services.mozilla.com/D311696
260 lines
6.2 KiB
C++
260 lines
6.2 KiB
C++
/* 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 "Tickler.h"
|
|
|
|
#ifdef MOZ_USE_WIFI_TICKLER
|
|
# include "mozilla/java/GeckoAppShellWrappers.h"
|
|
# include "mozilla/jni/Utils.h"
|
|
# include "nsComponentManagerUtils.h"
|
|
# include "nsINamed.h"
|
|
# include "nsIPrefBranch.h"
|
|
# include "nsIPrefService.h"
|
|
# include "nsServiceManagerUtils.h"
|
|
# include "nsThreadUtils.h"
|
|
# include "nsXULAppAPI.h"
|
|
# include "prnetdb.h"
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
|
|
Tickler::Tickler()
|
|
: mLock("Tickler::mLock"),
|
|
mActive(false),
|
|
mCanceled(false),
|
|
mEnabled(false),
|
|
mDelay(16),
|
|
mDuration(TimeDuration::FromMilliseconds(400)),
|
|
mFD(nullptr) {
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
}
|
|
|
|
Tickler::~Tickler() {
|
|
// non main thread uses of the tickler should hold weak
|
|
// references to it if they must hold a reference at all
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
if (mThread) {
|
|
mThread->AsyncShutdown();
|
|
mThread = nullptr;
|
|
}
|
|
|
|
if (mTimer) mTimer->Cancel();
|
|
if (mFD) PR_Close(mFD);
|
|
}
|
|
|
|
nsresult Tickler::Init() {
|
|
if (!XRE_IsParentProcess()) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
if (jni::IsAvailable()) {
|
|
java::GeckoAppShell::EnableNetworkNotifications();
|
|
}
|
|
|
|
// Allocate resources before acquiring the lock.
|
|
PRFileDesc* fd = PR_OpenUDPSocket(PR_AF_INET);
|
|
if (!fd) return NS_ERROR_FAILURE;
|
|
|
|
// make sure new socket has a ttl of 1
|
|
// failure is not fatal.
|
|
PRSocketOptionData opt;
|
|
opt.option = PR_SockOpt_IpTimeToLive;
|
|
opt.value.ip_ttl = 1;
|
|
PR_SetSocketOption(fd, &opt);
|
|
|
|
nsCOMPtr<nsIThread> thread;
|
|
nsresult rv = NS_NewNamedThread("wifi tickler", getter_AddRefs(thread));
|
|
if (NS_FAILED(rv)) {
|
|
PR_Close(fd);
|
|
return rv;
|
|
}
|
|
|
|
nsCOMPtr<nsITimer> timer = NS_NewTimer(thread);
|
|
if (!timer) {
|
|
thread->AsyncShutdown();
|
|
PR_Close(fd);
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
MutexAutoLock lock(mLock);
|
|
MOZ_ASSERT(!mTimer);
|
|
MOZ_ASSERT(!mActive);
|
|
MOZ_ASSERT(!mThread);
|
|
MOZ_ASSERT(!mFD);
|
|
|
|
mFD = fd;
|
|
mThread = thread;
|
|
mTimer.swap(timer);
|
|
|
|
mAddr.inet.family = PR_AF_INET;
|
|
mAddr.inet.port = PR_htons(4886);
|
|
mAddr.inet.ip = 0;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void Tickler::Tickle() {
|
|
MutexAutoLock lock(mLock);
|
|
MOZ_ASSERT(mThread);
|
|
mLastTickle = TimeStamp::Now();
|
|
if (!mActive) MaybeStartTickler();
|
|
}
|
|
|
|
void Tickler::PostCheckTickler() {
|
|
mLock.AssertCurrentThreadOwns();
|
|
mThread->Dispatch(NewRunnableMethod("net::Tickler::CheckTickler", this,
|
|
&Tickler::CheckTickler),
|
|
NS_DISPATCH_NORMAL);
|
|
return;
|
|
}
|
|
|
|
void Tickler::MaybeStartTicklerUnlocked() {
|
|
MutexAutoLock lock(mLock);
|
|
MaybeStartTickler();
|
|
}
|
|
|
|
void Tickler::MaybeStartTickler() {
|
|
mLock.AssertCurrentThreadOwns();
|
|
if (!NS_IsMainThread()) {
|
|
NS_DispatchToMainThread(
|
|
NewRunnableMethod("net::Tickler::MaybeStartTicklerUnlocked", this,
|
|
&Tickler::MaybeStartTicklerUnlocked));
|
|
return;
|
|
}
|
|
|
|
if (!mPrefs) mPrefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
if (mPrefs) {
|
|
int32_t val;
|
|
bool boolVal;
|
|
|
|
if (NS_SUCCEEDED(
|
|
mPrefs->GetBoolPref("network.tickle-wifi.enabled", &boolVal)))
|
|
mEnabled = boolVal;
|
|
|
|
if (NS_SUCCEEDED(
|
|
mPrefs->GetIntPref("network.tickle-wifi.duration", &val))) {
|
|
if (val < 1) val = 1;
|
|
if (val > 100000) val = 100000;
|
|
mDuration = TimeDuration::FromMilliseconds(val);
|
|
}
|
|
|
|
if (NS_SUCCEEDED(mPrefs->GetIntPref("network.tickle-wifi.delay", &val))) {
|
|
if (val < 1) val = 1;
|
|
if (val > 1000) val = 1000;
|
|
mDelay = static_cast<uint32_t>(val);
|
|
}
|
|
}
|
|
|
|
PostCheckTickler();
|
|
}
|
|
|
|
void Tickler::CheckTickler() {
|
|
MutexAutoLock lock(mLock);
|
|
MOZ_ASSERT(mThread == NS_GetCurrentThread());
|
|
|
|
bool shouldRun =
|
|
(!mCanceled) && ((TimeStamp::Now() - mLastTickle) <= mDuration);
|
|
|
|
if ((shouldRun && mActive) || (!shouldRun && !mActive))
|
|
return; // no change in state
|
|
|
|
if (mActive)
|
|
StopTickler();
|
|
else
|
|
StartTickler();
|
|
}
|
|
|
|
void Tickler::Cancel() {
|
|
MutexAutoLock lock(mLock);
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
mCanceled = true;
|
|
if (mThread) PostCheckTickler();
|
|
}
|
|
|
|
void Tickler::StopTickler() {
|
|
mLock.AssertCurrentThreadOwns();
|
|
MOZ_ASSERT(mThread == NS_GetCurrentThread());
|
|
MOZ_ASSERT(mTimer);
|
|
MOZ_ASSERT(mActive);
|
|
|
|
mTimer->Cancel();
|
|
mActive = false;
|
|
}
|
|
|
|
class TicklerTimer final : public nsITimerCallback, public nsINamed {
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
NS_DECL_NSITIMERCALLBACK
|
|
|
|
explicit TicklerTimer(Tickler* t) : mTickler(t) {}
|
|
|
|
// nsINamed
|
|
NS_IMETHOD GetName(nsACString& aName) override {
|
|
aName.AssignLiteral("TicklerTimer");
|
|
return NS_OK;
|
|
}
|
|
|
|
private:
|
|
~TicklerTimer() {}
|
|
|
|
ThreadSafeWeakPtr<Tickler> mTickler;
|
|
};
|
|
|
|
void Tickler::StartTickler() {
|
|
mLock.AssertCurrentThreadOwns();
|
|
MOZ_ASSERT(mThread == NS_GetCurrentThread());
|
|
MOZ_ASSERT(!mActive);
|
|
MOZ_ASSERT(mTimer);
|
|
|
|
auto tickler = MakeRefPtr<TicklerTimer>(this);
|
|
if (NS_SUCCEEDED(mTimer->InitWithCallback(tickler, mEnabled ? mDelay : 1000,
|
|
nsITimer::TYPE_REPEATING_SLACK)))
|
|
mActive = true;
|
|
}
|
|
|
|
// argument should be in network byte order
|
|
void Tickler::SetIPV4Address(uint32_t address) { mAddr.inet.ip = address; }
|
|
|
|
// argument should be in network byte order
|
|
void Tickler::SetIPV4Port(uint16_t port) { mAddr.inet.port = port; }
|
|
|
|
NS_IMPL_ISUPPORTS(TicklerTimer, nsITimerCallback, nsINamed)
|
|
|
|
NS_IMETHODIMP TicklerTimer::Notify(nsITimer* timer) {
|
|
RefPtr<Tickler> tickler(mTickler);
|
|
if (!tickler) return NS_ERROR_FAILURE;
|
|
MutexAutoLock lock(tickler->mLock);
|
|
|
|
if (!tickler->mFD) {
|
|
tickler->StopTickler();
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
if (tickler->mCanceled ||
|
|
((TimeStamp::Now() - tickler->mLastTickle) > tickler->mDuration)) {
|
|
tickler->StopTickler();
|
|
return NS_OK;
|
|
}
|
|
|
|
if (!tickler->mEnabled) return NS_OK;
|
|
|
|
PR_SendTo(tickler->mFD, "", 0, 0, &tickler->mAddr, 0);
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace net
|
|
} // namespace mozilla
|
|
|
|
#else // not defined MOZ_USE_WIFI_TICKLER
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
NS_IMPL_ISUPPORTS0(Tickler)
|
|
} // namespace net
|
|
} // namespace mozilla
|
|
|
|
#endif // defined MOZ_USE_WIFI_TICKLER
|