diff options
Diffstat (limited to 'netwerk/base/NetworkDataCountLayer.cpp')
-rw-r--r-- | netwerk/base/NetworkDataCountLayer.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/netwerk/base/NetworkDataCountLayer.cpp b/netwerk/base/NetworkDataCountLayer.cpp new file mode 100644 index 0000000000..bee8bd1ee5 --- /dev/null +++ b/netwerk/base/NetworkDataCountLayer.cpp @@ -0,0 +1,138 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 "NetworkDataCountLayer.h" +#include "nsSocketTransportService2.h" +#include "prmem.h" +#include "prio.h" + +namespace mozilla { +namespace net { + +static PRDescIdentity sNetworkDataCountLayerIdentity; +static PRIOMethods sNetworkDataCountLayerMethods; +static PRIOMethods* sNetworkDataCountLayerMethodsPtr = nullptr; + +class NetworkDataCountSecret { + public: + NetworkDataCountSecret() = default; + + uint64_t mSentBytes = 0; + uint64_t mReceivedBytes = 0; +}; + +static PRInt32 NetworkDataCountSend(PRFileDesc* fd, const void* buf, + PRInt32 amount, PRIntn flags, + PRIntervalTime timeout) { + MOZ_RELEASE_ASSERT(fd->identity == sNetworkDataCountLayerIdentity); + + NetworkDataCountSecret* secret = + reinterpret_cast<NetworkDataCountSecret*>(fd->secret); + + PRInt32 rv = + (fd->lower->methods->send)(fd->lower, buf, amount, flags, timeout); + if (rv > 0) { + secret->mSentBytes += rv; + } + return rv; +} + +static PRInt32 NetworkDataCountWrite(PRFileDesc* fd, const void* buf, + PRInt32 amount) { + return NetworkDataCountSend(fd, buf, amount, 0, PR_INTERVAL_NO_WAIT); +} + +static PRInt32 NetworkDataCountRecv(PRFileDesc* fd, void* buf, PRInt32 amount, + PRIntn flags, PRIntervalTime timeout) { + MOZ_RELEASE_ASSERT(fd->identity == sNetworkDataCountLayerIdentity); + + NetworkDataCountSecret* secret = + reinterpret_cast<NetworkDataCountSecret*>(fd->secret); + + PRInt32 rv = + (fd->lower->methods->recv)(fd->lower, buf, amount, flags, timeout); + if (rv > 0) { + secret->mReceivedBytes += rv; + } + return rv; +} + +static PRInt32 NetworkDataCountRead(PRFileDesc* fd, void* buf, PRInt32 amount) { + return NetworkDataCountRecv(fd, buf, amount, 0, PR_INTERVAL_NO_WAIT); +} + +static PRStatus NetworkDataCountClose(PRFileDesc* fd) { + if (!fd) { + return PR_FAILURE; + } + + PRFileDesc* layer = PR_PopIOLayer(fd, PR_TOP_IO_LAYER); + + MOZ_RELEASE_ASSERT(layer && layer->identity == sNetworkDataCountLayerIdentity, + "NetworkDataCount Layer not on top of stack"); + + NetworkDataCountSecret* secret = + reinterpret_cast<NetworkDataCountSecret*>(layer->secret); + layer->secret = nullptr; + layer->dtor(layer); + delete secret; + return fd->methods->close(fd); +} + +nsresult AttachNetworkDataCountLayer(PRFileDesc* fd) { + if (!sNetworkDataCountLayerMethodsPtr) { + sNetworkDataCountLayerIdentity = + PR_GetUniqueIdentity("NetworkDataCount Layer"); + sNetworkDataCountLayerMethods = *PR_GetDefaultIOMethods(); + sNetworkDataCountLayerMethods.send = NetworkDataCountSend; + sNetworkDataCountLayerMethods.write = NetworkDataCountWrite; + sNetworkDataCountLayerMethods.recv = NetworkDataCountRecv; + sNetworkDataCountLayerMethods.read = NetworkDataCountRead; + sNetworkDataCountLayerMethods.close = NetworkDataCountClose; + sNetworkDataCountLayerMethodsPtr = &sNetworkDataCountLayerMethods; + } + + PRFileDesc* layer = PR_CreateIOLayerStub(sNetworkDataCountLayerIdentity, + sNetworkDataCountLayerMethodsPtr); + + if (!layer) { + return NS_ERROR_FAILURE; + } + + NetworkDataCountSecret* secret = new NetworkDataCountSecret(); + + layer->secret = reinterpret_cast<PRFilePrivate*>(secret); + + PRStatus status = PR_PushIOLayer(fd, PR_NSPR_IO_LAYER, layer); + + if (status == PR_FAILURE) { + delete secret; + PR_Free(layer); // PR_CreateIOLayerStub() uses PR_Malloc(). + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +void NetworkDataCountSent(PRFileDesc* fd, uint64_t& sentBytes) { + PRFileDesc* ndcFd = PR_GetIdentitiesLayer(fd, sNetworkDataCountLayerIdentity); + MOZ_RELEASE_ASSERT(ndcFd); + + NetworkDataCountSecret* secret = + reinterpret_cast<NetworkDataCountSecret*>(ndcFd->secret); + sentBytes = secret->mSentBytes; +} + +void NetworkDataCountReceived(PRFileDesc* fd, uint64_t& receivedBytes) { + PRFileDesc* ndcFd = PR_GetIdentitiesLayer(fd, sNetworkDataCountLayerIdentity); + MOZ_RELEASE_ASSERT(ndcFd); + + NetworkDataCountSecret* secret = + reinterpret_cast<NetworkDataCountSecret*>(ndcFd->secret); + receivedBytes = secret->mReceivedBytes; +} + +} // namespace net +} // namespace mozilla |