зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1218356 - P2 - Implement the RTCDataChannel stats;r=dminor
Note that transportId is not implemented and is not a stat but a key back into the stats report. It identifies the related transport stats object. We don't have transport stats, so this can not be implemented at the moment. Differential Revision: https://phabricator.services.mozilla.com/D57116
This commit is contained in:
Родитель
ee658e6245
Коммит
46b83b6604
|
@ -2567,6 +2567,29 @@ RefPtr<dom::RTCStatsPromise> PeerConnectionImpl::GetSenderStats(
|
|||
});
|
||||
}
|
||||
|
||||
static UniquePtr<dom::RTCStatsCollection> GetDataChannelStats_s(
|
||||
const RefPtr<DataChannelConnection>& aDataConnection,
|
||||
const DOMHighResTimeStamp aTimestamp) {
|
||||
UniquePtr<dom::RTCStatsCollection> report(new dom::RTCStatsCollection);
|
||||
if (aDataConnection) {
|
||||
aDataConnection->AppendStatsToReport(report, aTimestamp);
|
||||
}
|
||||
return report;
|
||||
}
|
||||
|
||||
RefPtr<dom::RTCStatsPromise> PeerConnectionImpl::GetDataChannelStats(
|
||||
const RefPtr<DataChannelConnection>& aDataChannelConnection,
|
||||
const DOMHighResTimeStamp aTimestamp) {
|
||||
// Gather stats from DataChannels
|
||||
return InvokeAsync(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[aDataChannelConnection, aTimestamp]() {
|
||||
return dom::RTCStatsPromise::CreateAndResolve(
|
||||
GetDataChannelStats_s(aDataChannelConnection, aTimestamp),
|
||||
__func__);
|
||||
});
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::RecordConduitTelemetry() {
|
||||
if (!mMedia) {
|
||||
return;
|
||||
|
@ -2663,6 +2686,8 @@ RefPtr<dom::RTCStatsReportPromise> PeerConnectionImpl::GetStats(
|
|||
} else {
|
||||
promises.AppendElement(mTransportHandler->GetIceStats("", now));
|
||||
}
|
||||
|
||||
promises.AppendElement(GetDataChannelStats(mDataConnection, now));
|
||||
}
|
||||
|
||||
// This is what we're going to return; all the stuff in |promises| will be
|
||||
|
@ -2760,6 +2785,8 @@ RefPtr<dom::RTCStatsReportPromise> PeerConnectionImpl::GetStats(
|
|||
report->mRtpContributingSourceStats, idGen);
|
||||
AssignWithOpaqueIds(stats->mTrickledIceCandidateStats,
|
||||
report->mTrickledIceCandidateStats, idGen);
|
||||
AssignWithOpaqueIds(stats->mDataChannelStats,
|
||||
report->mDataChannelStats, idGen);
|
||||
if (!report->mRawLocalCandidates.AppendElements(
|
||||
stats->mRawLocalCandidates, fallible) ||
|
||||
!report->mRawRemoteCandidates.AppendElements(
|
||||
|
|
|
@ -450,6 +450,9 @@ class PeerConnectionImpl final
|
|||
const RefPtr<MediaPipelineReceive>& aPipeline);
|
||||
RefPtr<dom::RTCStatsPromise> GetSenderStats(
|
||||
const RefPtr<MediaPipelineTransmit>& aPipeline);
|
||||
RefPtr<dom::RTCStatsPromise> GetDataChannelStats(
|
||||
const RefPtr<DataChannelConnection>& aDataChannelConnection,
|
||||
const DOMHighResTimeStamp aTimestamp);
|
||||
nsresult CalculateFingerprint(const std::string& algorithm,
|
||||
std::vector<uint8_t>* fingerprint) const;
|
||||
nsresult ConfigureJsepSessionCodecs();
|
||||
|
|
|
@ -43,9 +43,12 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "mozilla/RandomNum.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/RTCDataChannelBinding.h"
|
||||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||
#ifdef MOZ_PEERCONNECTION
|
||||
# include "mtransport/runnable_utils.h"
|
||||
# include "signaling/src/peerconnection/MediaTransportHandler.h"
|
||||
|
@ -648,6 +651,60 @@ void DataChannelConnection::SetMaxMessageSize(bool aMaxMessageSizeSet,
|
|||
|
||||
uint64_t DataChannelConnection::GetMaxMessageSize() { return mMaxMessageSize; }
|
||||
|
||||
void DataChannelConnection::AppendStatsToReport(
|
||||
const UniquePtr<dom::RTCStatsCollection>& aReport,
|
||||
const DOMHighResTimeStamp aTimestamp) const {
|
||||
ASSERT_WEBRTC(NS_IsMainThread());
|
||||
nsString temp;
|
||||
for (const RefPtr<DataChannel>& chan : mChannels.GetAll()) {
|
||||
// If channel is empty, ignore
|
||||
if (!chan) {
|
||||
continue;
|
||||
}
|
||||
mozilla::dom::RTCDataChannelStats stats;
|
||||
nsString id = NS_LITERAL_STRING("dc");
|
||||
id.AppendInt(chan->GetStream());
|
||||
stats.mId.Construct(id);
|
||||
chan->GetLabel(temp);
|
||||
stats.mTimestamp.Construct(aTimestamp);
|
||||
stats.mType.Construct(mozilla::dom::RTCStatsType::Data_channel);
|
||||
stats.mLabel.Construct(temp);
|
||||
chan->GetProtocol(temp);
|
||||
stats.mProtocol.Construct(temp);
|
||||
stats.mDataChannelIdentifier.Construct(chan->GetStream());
|
||||
{
|
||||
using State = mozilla::dom::RTCDataChannelState;
|
||||
State state;
|
||||
switch (chan->GetReadyState()) {
|
||||
case CONNECTING:
|
||||
state = State::Connecting;
|
||||
break;
|
||||
case OPEN:
|
||||
state = State::Open;
|
||||
break;
|
||||
case CLOSING:
|
||||
state = State::Closing;
|
||||
break;
|
||||
case CLOSED:
|
||||
state = State::Closed;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unknown DataChannel state");
|
||||
continue;
|
||||
};
|
||||
stats.mState.Construct(state);
|
||||
}
|
||||
auto counters = chan->GetTrafficCounters();
|
||||
stats.mMessagesSent.Construct(counters.mMessagesSent);
|
||||
stats.mBytesSent.Construct(counters.mBytesSent);
|
||||
stats.mMessagesReceived.Construct(counters.mMessagesReceived);
|
||||
stats.mBytesReceived.Construct(counters.mBytesReceived);
|
||||
if (!aReport->mDataChannelStats.AppendElement(stats, fallible)) {
|
||||
mozalloc_handle_oom(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_PEERCONNECTION
|
||||
|
||||
bool DataChannelConnection::ConnectToTransport(const std::string& aTransportId,
|
||||
|
@ -1697,6 +1754,12 @@ void DataChannelConnection::HandleDataMessage(const void* data, size_t length,
|
|||
return;
|
||||
}
|
||||
|
||||
channel->WithTrafficCounters(
|
||||
[&data_length](DataChannel::TrafficCounters& counters) {
|
||||
counters.mMessagesReceived++;
|
||||
counters.mBytesReceived += data_length;
|
||||
});
|
||||
|
||||
// Notify onmessage
|
||||
DC_DEBUG(("%s: sending ON_DATA_%s%s for %p", __FUNCTION__,
|
||||
(type == DataChannelOnMessageAvailable::ON_DATA_STRING) ? "STRING"
|
||||
|
@ -2890,13 +2953,22 @@ int DataChannelConnection::SendDataMsgCommon(uint16_t stream,
|
|||
}
|
||||
|
||||
auto& channel = *channelPtr;
|
||||
|
||||
int err = 0;
|
||||
if (isBinary) {
|
||||
return SendDataMsg(channel, data, len, DATA_CHANNEL_PPID_BINARY_PARTIAL,
|
||||
DATA_CHANNEL_PPID_BINARY);
|
||||
err = SendDataMsg(channel, data, len, DATA_CHANNEL_PPID_BINARY_PARTIAL,
|
||||
DATA_CHANNEL_PPID_BINARY);
|
||||
} else {
|
||||
err = SendDataMsg(channel, data, len, DATA_CHANNEL_PPID_DOMSTRING_PARTIAL,
|
||||
DATA_CHANNEL_PPID_DOMSTRING);
|
||||
}
|
||||
return SendDataMsg(channel, data, len, DATA_CHANNEL_PPID_DOMSTRING_PARTIAL,
|
||||
DATA_CHANNEL_PPID_DOMSTRING);
|
||||
if (!err) {
|
||||
channel.WithTrafficCounters([&len](DataChannel::TrafficCounters& counters) {
|
||||
counters.mMessagesSent++;
|
||||
counters.mBytesSent += len;
|
||||
});
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void DataChannelConnection::Stop() {
|
||||
|
@ -3266,6 +3338,11 @@ void DataChannel::SendOrQueue(DataChannelOnMessageAvailable* aMessage) {
|
|||
mMainThreadEventTarget->Dispatch(runnable.forget());
|
||||
}
|
||||
|
||||
DataChannel::TrafficCounters DataChannel::GetTrafficCounters() const {
|
||||
MutexAutoLock lock(mStatsLock);
|
||||
return mTrafficCounters;
|
||||
}
|
||||
|
||||
bool DataChannel::EnsureValidStream(ErrorResult& aRv) {
|
||||
MOZ_ASSERT(mConnection);
|
||||
if (mConnection && mStream != INVALID_STREAM) {
|
||||
|
@ -3275,4 +3352,10 @@ bool DataChannel::EnsureValidStream(ErrorResult& aRv) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void DataChannel::WithTrafficCounters(
|
||||
const std::function<void(TrafficCounters&)>& aFn) {
|
||||
MutexAutoLock lock(mStatsLock);
|
||||
aFn(mTrafficCounters);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -51,6 +51,9 @@ class DataChannel;
|
|||
class DataChannelOnMessageAvailable;
|
||||
class MediaPacket;
|
||||
class MediaTransportHandler;
|
||||
namespace dom {
|
||||
struct RTCStatsCollection;
|
||||
};
|
||||
|
||||
// For sending outgoing messages.
|
||||
// This class only holds a reference to the data and the info structure but does
|
||||
|
@ -153,6 +156,8 @@ class DataChannelConnection final : public net::NeckoTargetHolder
|
|||
void SetMaxMessageSize(bool aMaxMessageSizeSet, uint64_t aMaxMessageSize);
|
||||
uint64_t GetMaxMessageSize();
|
||||
|
||||
void AppendStatsToReport(const UniquePtr<dom::RTCStatsCollection>& aReport,
|
||||
const DOMHighResTimeStamp aTimestamp) const;
|
||||
#ifdef ALLOW_DIRECT_SCTP_LISTEN_CONNECT
|
||||
// These block; they require something to decide on listener/connector
|
||||
// (though you can do simultaneous Connect()). Do not call these from
|
||||
|
@ -305,7 +310,7 @@ class DataChannelConnection final : public net::NeckoTargetHolder
|
|||
void HandleNotification(const union sctp_notification* notif, size_t n);
|
||||
|
||||
#ifdef SCTP_DTLS_SUPPORTED
|
||||
bool IsSTSThread() {
|
||||
bool IsSTSThread() const {
|
||||
bool on = false;
|
||||
if (mSTS) {
|
||||
mSTS->IsOnCurrentThread(&on);
|
||||
|
@ -426,7 +431,8 @@ class DataChannel {
|
|||
mIsRecvBinary(false),
|
||||
mBufferedThreshold(0), // default from spec
|
||||
mBufferedAmount(0),
|
||||
mMainThreadEventTarget(connection->GetNeckoTarget()) {
|
||||
mMainThreadEventTarget(connection->GetNeckoTarget()),
|
||||
mStatsLock("netwer::sctp::DataChannel::mStatsLock") {
|
||||
NS_ASSERTION(mConnection, "NULL connection");
|
||||
}
|
||||
|
||||
|
@ -508,6 +514,15 @@ class DataChannel {
|
|||
|
||||
void SendOrQueue(DataChannelOnMessageAvailable* aMessage);
|
||||
|
||||
struct TrafficCounters {
|
||||
uint32_t mMessagesSent = 0;
|
||||
uint64_t mBytesSent = 0;
|
||||
uint32_t mMessagesReceived = 0;
|
||||
uint64_t mBytesReceived = 0;
|
||||
};
|
||||
|
||||
TrafficCounters GetTrafficCounters() const;
|
||||
|
||||
protected:
|
||||
// These are both mainthread only
|
||||
DataChannelListener* mListener;
|
||||
|
@ -516,6 +531,7 @@ class DataChannel {
|
|||
private:
|
||||
nsresult AddDataToBinaryMsg(const char* data, uint32_t size);
|
||||
bool EnsureValidStream(ErrorResult& aRv);
|
||||
void WithTrafficCounters(const std::function<void(TrafficCounters&)>&);
|
||||
|
||||
RefPtr<DataChannelConnection> mConnection;
|
||||
nsCString mLabel;
|
||||
|
@ -538,6 +554,8 @@ class DataChannel {
|
|||
nsTArray<UniquePtr<BufferedOutgoingMsg>>
|
||||
mBufferedData; // GUARDED_BY(mConnection->mLock)
|
||||
nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
|
||||
mutable Mutex mStatsLock; // protects mTrafficCounters
|
||||
TrafficCounters mTrafficCounters;
|
||||
};
|
||||
|
||||
// used to dispatch notifications of incoming data to the main thread
|
||||
|
|
Загрузка…
Ссылка в новой задаче