capture network bandwidth stats from NodeList rather than various places

This commit is contained in:
Seth Alves 2015-01-31 20:02:04 -08:00
parent 105b2c5fd7
commit bee895ba0a
17 changed files with 239 additions and 159 deletions

2
.gitignore vendored
View file

@ -38,3 +38,5 @@ interface/resources/visage/*
# Ignore interfaceCache for Linux users # Ignore interfaceCache for Linux users
interface/interfaceCache/ interface/interfaceCache/
TAGS

View file

@ -433,6 +433,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(this, SIGNAL(aboutToQuit()), this, SLOT(saveScripts())); connect(this, SIGNAL(aboutToQuit()), this, SLOT(saveScripts()));
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit())); connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
// hook up bandwidth estimator
connect(nodeList.data(), SIGNAL(dataSent(const quint8, const int)),
&_bandwidthRecorder, SLOT(updateOutboundData(const quint8, const int)));
connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)),
&_bandwidthRecorder, SLOT(updateInboundData(const quint8, const int)));
// check first run... // check first run...
bool firstRun = SettingHandles::firstRun.get(); bool firstRun = SettingHandles::firstRun.get();
if (firstRun) { if (firstRun) {
@ -771,25 +777,8 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum)
void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) {
foreach(NodeType_t type, destinationNodeTypes) { foreach(NodeType_t type, destinationNodeTypes) {
// Perform the broadcast for one type // Perform the broadcast for one type
int nReceivingNodes = DependencyManager::get<NodeList>()->broadcastToNodes(packet, NodeSet() << type); DependencyManager::get<NodeList>()->broadcastToNodes(packet, NodeSet() << type);
// Feed number of bytes to corresponding channel of the bandwidth meter, if any (done otherwise)
double bandwidth_amount = nReceivingNodes * packet.size();
switch (type) {
case NodeType::Agent:
case NodeType::AvatarMixer:
_bandwidthRecorder.avatarsChannel->output.updateValue(bandwidth_amount);
_bandwidthRecorder.totalChannel->input.updateValue(bandwidth_amount);
break;
case NodeType::EntityServer:
_bandwidthRecorder.octreeChannel->output.updateValue(bandwidth_amount);
_bandwidthRecorder.totalChannel->output.updateValue(bandwidth_amount);
break;
default:
continue;
}
} }
} }
@ -2383,10 +2372,6 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
// make sure we still have an active socket // make sure we still have an active socket
nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node); nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
// Feed number of bytes to corresponding channel of the bandwidth meter
_bandwidthRecorder.octreeChannel->output.updateValue(packetLength);
_bandwidthRecorder.totalChannel->output.updateValue(packetLength);
} }
}); });
} }
@ -3374,8 +3359,6 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin
} }
void Application::packetSent(quint64 length) { void Application::packetSent(quint64 length) {
_bandwidthRecorder.octreeChannel->output.updateValue(length);
_bandwidthRecorder.totalChannel->output.updateValue(length);
} }
const QString SETTINGS_KEY = "Settings"; const QString SETTINGS_KEY = "Settings";

View file

@ -768,9 +768,6 @@ void Audio::handleAudioInput() {
int packetBytes = currentPacketPtr - audioDataPacket; int packetBytes = currentPacketPtr - audioDataPacket;
nodeList->writeDatagram(audioDataPacket, packetBytes, audioMixer); nodeList->writeDatagram(audioDataPacket, packetBytes, audioMixer);
_outgoingAvatarAudioSequenceNumber++; _outgoingAvatarAudioSequenceNumber++;
Application::getInstance()->getBandwidthRecorder()->audioChannel->output.updateValue(packetBytes);
Application::getInstance()->getBandwidthRecorder()->totalChannel->output.updateValue(packetBytes);
} }
delete[] inputAudioSamples; delete[] inputAudioSamples;
} }
@ -828,9 +825,6 @@ void Audio::addReceivedAudioToStream(const QByteArray& audioByteArray) {
// Audio output must exist and be correctly set up if we're going to process received audio // Audio output must exist and be correctly set up if we're going to process received audio
_receivedAudioStream.parseData(audioByteArray); _receivedAudioStream.parseData(audioByteArray);
} }
Application::getInstance()->getBandwidthRecorder()->audioChannel->input.updateValue(audioByteArray.size());
Application::getInstance()->getBandwidthRecorder()->totalChannel->input.updateValue(audioByteArray.size());
} }
void Audio::parseAudioEnvironmentData(const QByteArray &packet) { void Audio::parseAudioEnvironmentData(const QByteArray &packet) {

View file

@ -1,64 +0,0 @@
//
// BandwidthMeter.cpp
// interface/src/ui
//
// Created by Seth Alves on 2015-1-30
// Copyright 2015 High Fidelity, Inc.
//
// Based on code by Tobias Schwinger
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <GeometryCache.h>
#include "BandwidthRecorder.h"
BandwidthRecorder::Channel::Channel(char const* const caption,
char const* unitCaption,
double unitScale,
unsigned colorRGBA) :
caption(caption),
unitCaption(unitCaption),
unitScale(unitScale),
colorRGBA(colorRGBA)
{
}
BandwidthRecorder::BandwidthRecorder() {
}
BandwidthRecorder::~BandwidthRecorder() {
delete audioChannel;
delete avatarsChannel;
delete octreeChannel;
delete metavoxelsChannel;
delete totalChannel;
}
BandwidthRecorder::Stream::Stream(float msToAverage) : _value(0.0f), _msToAverage(msToAverage) {
_prevTime.start();
}
void BandwidthRecorder::Stream::updateValue(double amount) {
// Determine elapsed time
double dt = (double)_prevTime.nsecsElapsed() / 1000000.0; // ns to ms
// Ignore this value when timer imprecision yields dt = 0
if (dt == 0.0) {
return;
}
_prevTime.start();
// Compute approximate average
_value = glm::mix(_value, amount / dt,
glm::clamp(dt / _msToAverage, 0.0, 1.0));
}

View file

@ -39,8 +39,7 @@ void DatagramProcessor::processDatagrams() {
while (DependencyManager::get<NodeList>()->getNodeSocket().hasPendingDatagrams()) { while (DependencyManager::get<NodeList>()->getNodeSocket().hasPendingDatagrams()) {
incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
nodeList->getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(), nodeList->readDatagram(incomingPacket, senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
_inPacketCount++; _inPacketCount++;
_inByteCount += incomingPacket.size(); _inByteCount += incomingPacket.size();
@ -73,7 +72,7 @@ void DatagramProcessor::processDatagrams() {
if (audioMixer) { if (audioMixer) {
audioMixer->setLastHeardMicrostamp(usecTimestampNow()); audioMixer->setLastHeardMicrostamp(usecTimestampNow());
audioMixer->recordBytesReceived(incomingPacket.size()); // audioMixer->recordBytesReceived(incomingPacket.size());
} }
break; break;
@ -82,8 +81,8 @@ void DatagramProcessor::processDatagrams() {
// this will keep creatorTokenIDs to IDs mapped correctly // this will keep creatorTokenIDs to IDs mapped correctly
EntityItemID::handleAddEntityResponse(incomingPacket); EntityItemID::handleAddEntityResponse(incomingPacket);
application->getEntities()->getTree()->handleAddEntityResponse(incomingPacket); application->getEntities()->getTree()->handleAddEntityResponse(incomingPacket);
application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size()); // application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size());
application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size()); // application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
break; break;
case PacketTypeEntityData: case PacketTypeEntityData:
case PacketTypeEntityErase: case PacketTypeEntityErase:
@ -97,8 +96,8 @@ void DatagramProcessor::processDatagrams() {
// add this packet to our list of octree packets and process them on the octree data processing // add this packet to our list of octree packets and process them on the octree data processing
application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket); application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket);
} }
application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size()); // application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size());
application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size()); // application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
break; break;
} }
case PacketTypeMetavoxelData: case PacketTypeMetavoxelData:
@ -113,15 +112,15 @@ void DatagramProcessor::processDatagrams() {
if (avatarMixer) { if (avatarMixer) {
avatarMixer->setLastHeardMicrostamp(usecTimestampNow()); avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
avatarMixer->recordBytesReceived(incomingPacket.size()); // avatarMixer->recordBytesReceived(incomingPacket.size());
QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram", QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram",
Q_ARG(const QByteArray&, incomingPacket), Q_ARG(const QByteArray&, incomingPacket),
Q_ARG(const QWeakPointer<Node>&, avatarMixer)); Q_ARG(const QWeakPointer<Node>&, avatarMixer));
} }
application->_bandwidthRecorder.avatarsChannel->input.updateValue(incomingPacket.size()); // application->_bandwidthRecorder.avatarsChannel->input.updateValue(incomingPacket.size());
application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size()); // application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
break; break;
} }
case PacketTypeDomainConnectionDenied: { case PacketTypeDomainConnectionDenied: {

View file

@ -899,8 +899,6 @@ int MetavoxelSystemClient::parseData(const QByteArray& packet) {
} else { } else {
QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet)); QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet));
} }
Application::getInstance()->getBandwidthRecorder()->metavoxelsChannel->input.updateValue(packet.size());
Application::getInstance()->getBandwidthRecorder()->totalChannel->input.updateValue(packet.size());
} }
return packet.size(); return packet.size();
} }
@ -1016,8 +1014,6 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {
} else { } else {
DependencyManager::get<NodeList>()->writeDatagram(data, _node); DependencyManager::get<NodeList>()->writeDatagram(data, _node);
} }
Application::getInstance()->getBandwidthRecorder()->metavoxelsChannel->output.updateValue(data.size());
Application::getInstance()->getBandwidthRecorder()->totalChannel->output.updateValue(data.size());
} }
} }

View file

@ -47,8 +47,8 @@ QLabel* BandwidthDialog::ChannelDisplay::setupLabel(QFormLayout* form) {
void BandwidthDialog::ChannelDisplay::setLabelText() { void BandwidthDialog::ChannelDisplay::setLabelText() {
std::string strBuf = std::string strBuf =
std::to_string ((int) (ch->input.getValue() * ch->unitScale)) + "/" + std::to_string ((int) (ch->getAverageInputKilobitsPerSecond() * ch->unitScale)) + "/" +
std::to_string ((int) (ch->output.getValue() * ch->unitScale)) + " " + ch->unitCaption; std::to_string ((int) (ch->getAverageOutputKilobitsPerSecond() * ch->unitScale)) + " " + ch->unitCaption;
label->setText(strBuf.c_str()); label->setText(strBuf.c_str());
} }
@ -68,6 +68,7 @@ BandwidthDialog::BandwidthDialog(QWidget* parent, BandwidthRecorder* model) :
avatarsChannelDisplay = new ChannelDisplay(_model->avatarsChannel, form); avatarsChannelDisplay = new ChannelDisplay(_model->avatarsChannel, form);
octreeChannelDisplay = new ChannelDisplay(_model->octreeChannel, form); octreeChannelDisplay = new ChannelDisplay(_model->octreeChannel, form);
metavoxelsChannelDisplay = new ChannelDisplay(_model->metavoxelsChannel, form); metavoxelsChannelDisplay = new ChannelDisplay(_model->metavoxelsChannel, form);
otherChannelDisplay = new ChannelDisplay(_model->otherChannel, form);
totalChannelDisplay = new ChannelDisplay(_model->totalChannel, form); totalChannelDisplay = new ChannelDisplay(_model->totalChannel, form);
} }
@ -77,6 +78,7 @@ BandwidthDialog::~BandwidthDialog() {
delete avatarsChannelDisplay; delete avatarsChannelDisplay;
delete octreeChannelDisplay; delete octreeChannelDisplay;
delete metavoxelsChannelDisplay; delete metavoxelsChannelDisplay;
delete otherChannelDisplay;
delete totalChannelDisplay; delete totalChannelDisplay;
} }
@ -86,6 +88,7 @@ void BandwidthDialog::paintEvent(QPaintEvent* event) {
avatarsChannelDisplay->setLabelText(); avatarsChannelDisplay->setLabelText();
octreeChannelDisplay->setLabelText(); octreeChannelDisplay->setLabelText();
metavoxelsChannelDisplay->setLabelText(); metavoxelsChannelDisplay->setLabelText();
otherChannelDisplay->setLabelText();
totalChannelDisplay->setLabelText(); totalChannelDisplay->setLabelText();
this->QDialog::paintEvent(event); this->QDialog::paintEvent(event);

View file

@ -42,6 +42,7 @@ public:
ChannelDisplay* avatarsChannelDisplay; ChannelDisplay* avatarsChannelDisplay;
ChannelDisplay* octreeChannelDisplay; ChannelDisplay* octreeChannelDisplay;
ChannelDisplay* metavoxelsChannelDisplay; ChannelDisplay* metavoxelsChannelDisplay;
ChannelDisplay* otherChannelDisplay;
// sums of all the other channels // sums of all the other channels
ChannelDisplay* totalChannelDisplay; ChannelDisplay* totalChannelDisplay;

View file

@ -216,6 +216,8 @@ void Stats::display(
QLocale locale(QLocale::English); QLocale locale(QLocale::English);
std::stringstream octreeStats; std::stringstream octreeStats;
BandwidthRecorder* bandwidthRecorder = Application::getInstance()->getBandwidthRecorder();
if (_lastHorizontalOffset != horizontalOffset) { if (_lastHorizontalOffset != horizontalOffset) {
resetWidth(glCanvas->width(), horizontalOffset); resetWidth(glCanvas->width(), horizontalOffset);
_lastHorizontalOffset = horizontalOffset; _lastHorizontalOffset = horizontalOffset;
@ -440,8 +442,12 @@ void Stats::display(
SharedNodePointer avatarMixer = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::AvatarMixer); SharedNodePointer avatarMixer = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::AvatarMixer);
if (avatarMixer) { if (avatarMixer) {
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps", sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
roundf(avatarMixer->getAverageKilobitsPerSecond()), // roundf(avatarMixer->getAverageKilobitsPerSecond()),
roundf(avatarMixer->getAveragePacketsPerSecond())); // roundf(avatarMixer->getAveragePacketsPerSecond())
roundf(bandwidthRecorder->audioChannel->getAverageInputKilobitsPerSecond() +
bandwidthRecorder->audioChannel->getAverageOutputKilobitsPerSecond()),
roundf(bandwidthRecorder->audioChannel->getAverageInputPacketsPerSecond() +
bandwidthRecorder->audioChannel->getAverageOutputPacketsPerSecond()));
} else { } else {
sprintf(avatarMixerStats, "No Avatar Mixer"); sprintf(avatarMixerStats, "No Avatar Mixer");
} }

View file

@ -0,0 +1,123 @@
//
// BandwidthMeter.cpp
// interface/src/ui
//
// Created by Seth Alves on 2015-1-30
// Copyright 2015 High Fidelity, Inc.
//
// Based on code by Tobias Schwinger
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// #include <GeometryCache.h>
#include "BandwidthRecorder.h"
BandwidthRecorder::Channel::Channel(char const* const caption,
char const* unitCaption,
double unitScale,
unsigned colorRGBA) :
caption(caption),
unitCaption(unitCaption),
unitScale(unitScale),
colorRGBA(colorRGBA)
{
}
float BandwidthRecorder::Channel::getAverageInputPacketsPerSecond() {
return (1 / _input.getEventDeltaAverage());
}
float BandwidthRecorder::Channel::getAverageOutputPacketsPerSecond() {
return (1 / _output.getEventDeltaAverage());
}
float BandwidthRecorder::Channel::getAverageInputKilobitsPerSecond() {
return (_input.getAverageSampleValuePerSecond() * (8.0f / 1000));
}
float BandwidthRecorder::Channel::getAverageOutputKilobitsPerSecond() {
return (_output.getAverageSampleValuePerSecond() * (8.0f / 1000));
}
void BandwidthRecorder::Channel::updateInputAverage(const float sample) {
_input.updateAverage(sample);
}
void BandwidthRecorder::Channel::updateOutputAverage(const float sample) {
_output.updateAverage(sample);
}
BandwidthRecorder::BandwidthRecorder() {
}
BandwidthRecorder::~BandwidthRecorder() {
delete audioChannel;
delete avatarsChannel;
delete octreeChannel;
delete metavoxelsChannel;
delete totalChannel;
}
void BandwidthRecorder::updateInboundData(const quint8 channelType, const int sample) {
totalChannel->updateInputAverage(sample);
// see Node.h NodeType
switch (channelType) {
case NodeType::DomainServer:
case NodeType::EntityServer:
octreeChannel->updateInputAverage(sample);
break;
case NodeType::MetavoxelServer:
case NodeType::EnvironmentServer:
metavoxelsChannel->updateInputAverage(sample);
break;
case NodeType::AudioMixer:
audioChannel->updateInputAverage(sample);
break;
case NodeType::Agent:
case NodeType::AvatarMixer:
avatarsChannel->updateInputAverage(sample);
break;
case NodeType::Unassigned:
default:
otherChannel->updateInputAverage(sample);
break;
}
}
void BandwidthRecorder::updateOutboundData(const quint8 channelType, const int sample) {
totalChannel->updateOutputAverage(sample);
// see Node.h NodeType
switch (channelType) {
case NodeType::DomainServer:
case NodeType::EntityServer:
octreeChannel->updateOutputAverage(sample);
break;
case NodeType::MetavoxelServer:
case NodeType::EnvironmentServer:
metavoxelsChannel->updateOutputAverage(sample);
break;
case NodeType::AudioMixer:
audioChannel->updateOutputAverage(sample);
break;
case NodeType::Agent:
case NodeType::AvatarMixer:
avatarsChannel->updateOutputAverage(sample);
break;
case NodeType::Unassigned:
default:
otherChannel->updateOutputAverage(sample);
break;
}
}

View file

@ -14,42 +14,46 @@
#ifndef hifi_BandwidthRecorder_h #ifndef hifi_BandwidthRecorder_h
#define hifi_BandwidthRecorder_h #define hifi_BandwidthRecorder_h
#include <QObject>
#include <QElapsedTimer> #include <QElapsedTimer>
#include "Node.h"
#include "SimpleMovingAverage.h"
const double DEFAULT_UNIT_SCALE = 8000.0 / 1024.0; const double DEFAULT_UNIT_SCALE = 1.0;
const unsigned int COLOR0 = 0x33cc99ff; const unsigned int COLOR0 = 0x33cc99ff;
const unsigned int COLOR1 = 0xffef40c0; const unsigned int COLOR1 = 0xffef40c0;
const unsigned int COLOR2 = 0xd0d0d0a0; const unsigned int COLOR2 = 0xd0d0d0a0;
class BandwidthRecorder { class BandwidthRecorder : public QObject {
Q_OBJECT
public: public:
BandwidthRecorder(); BandwidthRecorder();
~BandwidthRecorder(); ~BandwidthRecorder();
// keep track of data rate in one direction
class Stream {
public:
Stream(float msToAverage = 3000.0f);
void updateValue(double amount);
double getValue() const { return _value; }
private:
double _value; // Current value.
double _msToAverage; // Milliseconds to average.
QElapsedTimer _prevTime; // Time of last feed.
};
// keep track of data rate in two directions as well as units and style to use during display // keep track of data rate in two directions as well as units and style to use during display
class Channel { class Channel {
public: public:
Channel(char const* const caption, char const* unitCaption, double unitScale, unsigned colorRGBA); Channel(char const* const caption, char const* unitCaption, double unitScale, unsigned colorRGBA);
Stream input; float getAverageInputPacketsPerSecond();
Stream output; float getAverageOutputPacketsPerSecond();
float getAverageInputKilobitsPerSecond();
float getAverageOutputKilobitsPerSecond();
void updateInputAverage(const float sample);
void updateOutputAverage(const float sample);
// XXX make these private
char const* const caption; char const* const caption;
char const* unitCaption; char const* unitCaption;
double unitScale; double unitScale;
unsigned colorRGBA; unsigned colorRGBA;
private:
SimpleMovingAverage _input;
SimpleMovingAverage _output;
}; };
// create the channels we keep track of // create the channels we keep track of
@ -57,7 +61,12 @@ class BandwidthRecorder {
Channel* avatarsChannel = new Channel("Avatars", "Kbps", DEFAULT_UNIT_SCALE, COLOR1); Channel* avatarsChannel = new Channel("Avatars", "Kbps", DEFAULT_UNIT_SCALE, COLOR1);
Channel* octreeChannel = new Channel("Octree", "Kbps", DEFAULT_UNIT_SCALE, COLOR2); Channel* octreeChannel = new Channel("Octree", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
Channel* metavoxelsChannel = new Channel("Metavoxels", "Kbps", DEFAULT_UNIT_SCALE, COLOR2); Channel* metavoxelsChannel = new Channel("Metavoxels", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
Channel* otherChannel = new Channel("Other", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
Channel* totalChannel = new Channel("Total", "Kbps", DEFAULT_UNIT_SCALE, COLOR2); Channel* totalChannel = new Channel("Total", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
public slots:
void updateInboundData(const quint8 channelType, const int bytes);
void updateOutboundData(const quint8 channelType, const int bytes);
}; };
#endif #endif

View file

@ -208,6 +208,22 @@ bool LimitedNodeList::packetVersionAndHashMatch(const QByteArray& packet) {
return false; return false;
} }
// qint64 LimitedNodeList::readDatagram(char* data, qint64 maxSize, QHostAddress* address = 0, quint16 * port = 0) {
qint64 LimitedNodeList::readDatagram(QByteArray& incomingPacket, QHostAddress* address = 0, quint16 * port = 0) {
qint64 result = getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(), address, port);
SharedNodePointer sendingNode = sendingNodeForPacket(incomingPacket);
if (sendingNode) {
emit dataReceived(sendingNode->getType(), incomingPacket.size());
}
else {
emit dataReceived(NodeType::Unassigned, incomingPacket.size());
}
return result;
}
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr, qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr,
const QUuid& connectionSecret) { const QUuid& connectionSecret) {
QByteArray datagramCopy = datagram; QByteArray datagramCopy = datagram;
@ -231,10 +247,11 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSock
return bytesWritten; return bytesWritten;
} }
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram,
const HifiSockAddr& overridenSockAddr) { const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr) {
if (destinationNode) { if (destinationNode) {
// if we don't have an ovveriden address, assume they want to send to the node's active socket // if we don't have an overridden address, assume they want to send to the node's active socket
const HifiSockAddr* destinationSockAddr = &overridenSockAddr; const HifiSockAddr* destinationSockAddr = &overridenSockAddr;
if (overridenSockAddr.isNull()) { if (overridenSockAddr.isNull()) {
if (destinationNode->getActiveSocket()) { if (destinationNode->getActiveSocket()) {
@ -245,6 +262,8 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const SharedNo
return 0; return 0;
} }
} }
emit dataSent(destinationNode->getType(), datagram.size());
return writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret()); return writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret());
} }
@ -303,7 +322,7 @@ int LimitedNodeList::updateNodeWithDataFromPacket(const SharedNodePointer& match
QMutexLocker locker(&matchingNode->getMutex()); QMutexLocker locker(&matchingNode->getMutex());
matchingNode->setLastHeardMicrostamp(usecTimestampNow()); matchingNode->setLastHeardMicrostamp(usecTimestampNow());
matchingNode->recordBytesReceived(packet.size()); // matchingNode->recordBytesReceived(packet.size());
if (!matchingNode->getLinkedData() && linkedDataCreateCallback) { if (!matchingNode->getLinkedData() && linkedDataCreateCallback) {
linkedDataCreateCallback(matchingNode.data()); linkedDataCreateCallback(matchingNode.data());

View file

@ -82,6 +82,8 @@ public:
QUdpSocket& getDTLSSocket(); QUdpSocket& getDTLSSocket();
bool packetVersionAndHashMatch(const QByteArray& packet); bool packetVersionAndHashMatch(const QByteArray& packet);
qint64 readDatagram(QByteArray& incomingPacket, QHostAddress* address, quint16 * port);
qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode, qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
const HifiSockAddr& overridenSockAddr = HifiSockAddr()); const HifiSockAddr& overridenSockAddr = HifiSockAddr());
@ -180,6 +182,9 @@ signals:
void localSockAddrChanged(const HifiSockAddr& localSockAddr); void localSockAddrChanged(const HifiSockAddr& localSockAddr);
void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); void publicSockAddrChanged(const HifiSockAddr& publicSockAddr);
void dataSent(const quint8 channel_type, const int bytes);
void dataReceived(const quint8 channel_type, const int bytes);
protected: protected:
LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0); LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0);

View file

@ -47,7 +47,7 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
_activeSocket(NULL), _activeSocket(NULL),
_symmetricSocket(), _symmetricSocket(),
_connectionSecret(), _connectionSecret(),
_bytesReceivedMovingAverage(NULL), // _bytesReceivedMovingAverage(NULL),
_linkedData(NULL), _linkedData(NULL),
_isAlive(true), _isAlive(true),
_pingMs(-1), // "Uninitialized" _pingMs(-1), // "Uninitialized"
@ -60,32 +60,32 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
Node::~Node() { Node::~Node() {
delete _linkedData; delete _linkedData;
delete _bytesReceivedMovingAverage; // delete _bytesReceivedMovingAverage;
} }
void Node::recordBytesReceived(int bytesReceived) { // void Node::recordBytesReceived(int bytesReceived) {
if (!_bytesReceivedMovingAverage) { // if (!_bytesReceivedMovingAverage) {
_bytesReceivedMovingAverage = new SimpleMovingAverage(100); // _bytesReceivedMovingAverage = new SimpleMovingAverage(100);
} // }
_bytesReceivedMovingAverage->updateAverage((float) bytesReceived); // _bytesReceivedMovingAverage->updateAverage((float) bytesReceived);
} // }
float Node::getAveragePacketsPerSecond() { // float Node::getAveragePacketsPerSecond() {
if (_bytesReceivedMovingAverage) { // if (_bytesReceivedMovingAverage) {
return (1 / _bytesReceivedMovingAverage->getEventDeltaAverage()); // return (1 / _bytesReceivedMovingAverage->getEventDeltaAverage());
} else { // } else {
return 0; // return 0;
} // }
} // }
float Node::getAverageKilobitsPerSecond() { // float Node::getAverageKilobitsPerSecond() {
if (_bytesReceivedMovingAverage) { // if (_bytesReceivedMovingAverage) {
return (_bytesReceivedMovingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000)); // return (_bytesReceivedMovingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000));
} else { // } else {
return 0; // return 0;
} // }
} // }
void Node::updateClockSkewUsec(int clockSkewSample) { void Node::updateClockSkewUsec(int clockSkewSample) {
_clockSkewMovingPercentile.updatePercentile((float)clockSkewSample); _clockSkewMovingPercentile.updatePercentile((float)clockSkewSample);

View file

@ -63,9 +63,9 @@ public:
bool isAlive() const { return _isAlive; } bool isAlive() const { return _isAlive; }
void setAlive(bool isAlive) { _isAlive = isAlive; } void setAlive(bool isAlive) { _isAlive = isAlive; }
void recordBytesReceived(int bytesReceived); // void recordBytesReceived(int bytesReceived);
float getAverageKilobitsPerSecond(); // float getAverageKilobitsPerSecond();
float getAveragePacketsPerSecond(); // float getAveragePacketsPerSecond();
int getPingMs() const { return _pingMs; } int getPingMs() const { return _pingMs; }
void setPingMs(int pingMs) { _pingMs = pingMs; } void setPingMs(int pingMs) { _pingMs = pingMs; }
@ -99,7 +99,7 @@ private:
HifiSockAddr _symmetricSocket; HifiSockAddr _symmetricSocket;
QUuid _connectionSecret; QUuid _connectionSecret;
SimpleMovingAverage* _bytesReceivedMovingAverage; // SimpleMovingAverage* _bytesReceivedMovingAverage;
NodeData* _linkedData; NodeData* _linkedData;
bool _isAlive; bool _isAlive;
int _pingMs; int _pingMs;

View file

@ -108,6 +108,9 @@ void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer&
} }
void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) { void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
emit dataReceived(NodeType::AudioMixer, packet.size()); // XXX
switch (packetTypeForPacket(packet)) { switch (packetTypeForPacket(packet)) {
case PacketTypeDomainList: { case PacketTypeDomainList: {
processDomainServerList(packet); processDomainServerList(packet);
@ -157,6 +160,7 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
break; break;
} }
case PacketTypeUnverifiedPing: { case PacketTypeUnverifiedPing: {
// send back a reply // send back a reply
QByteArray replyPacket = constructPingReplyPacket(packet, _domainHandler.getICEClientID()); QByteArray replyPacket = constructPingReplyPacket(packet, _domainHandler.getICEClientID());
writeUnverifiedDatagram(replyPacket, senderSockAddr); writeUnverifiedDatagram(replyPacket, senderSockAddr);

View file

@ -8,7 +8,7 @@ do
done done
find . -name *.cpp -print | while read I find . -name *.cpp -print | grep -v 'moc_' | while read I
do do
etags --append "$I" etags --append "$I"
done done