From db757e9e7bf5a1a2a2363ac1a2e01130a2e14093 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Mar 2014 17:18:45 -0700 Subject: [PATCH 1/9] increase NodeList send buffer size by default to 128KB --- libraries/shared/src/NodeList.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index e80f25709a..e26e6be547 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -83,6 +83,17 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : // clear our NodeList when logout is requested connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); + // change the socket send buffer size to be 128KB + const int LARGER_SNDBUF_SIZE = 131072; + + setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &LARGER_SNDBUF_SIZE, sizeof(LARGER_SNDBUF_SIZE)); + + int newBufferSize = 0; + unsigned int sizeOfInt = sizeof(newBufferSize); + getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &newBufferSize, &sizeOfInt); + + qDebug() << "Changed socket send buffer size to" << newBufferSize << "bytes"; + _packetStatTimer.start(); } From 46077a7fb0c97018409a7fafc2b5a992a29fb934 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Mar 2014 17:24:17 -0700 Subject: [PATCH 2/9] output old size when notifying for send buffer size change --- libraries/shared/src/NodeList.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index e26e6be547..89b0ff2fbc 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -84,15 +84,18 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); // change the socket send buffer size to be 128KB + int oldBufferSize = 0; + unsigned int sizeOfInt = sizeof(oldBufferSize); + getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &oldBufferSize, &sizeOfInt); + const int LARGER_SNDBUF_SIZE = 131072; setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &LARGER_SNDBUF_SIZE, sizeof(LARGER_SNDBUF_SIZE)); int newBufferSize = 0; - unsigned int sizeOfInt = sizeof(newBufferSize); getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &newBufferSize, &sizeOfInt); - qDebug() << "Changed socket send buffer size to" << newBufferSize << "bytes"; + qDebug() << "Changed socket send buffer size from" << oldBufferSize << "to" << newBufferSize << "bytes"; _packetStatTimer.start(); } From ed9c805539ecb25c787823a08940ce39a80873b7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Mar 2014 17:29:35 -0700 Subject: [PATCH 3/9] attempt to set send buffer size to 1MB --- libraries/shared/src/NodeList.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 89b0ff2fbc..d25c3f7e1d 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -83,12 +83,12 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : // clear our NodeList when logout is requested connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); - // change the socket send buffer size to be 128KB + // change the socket send buffer size to be 1MB int oldBufferSize = 0; unsigned int sizeOfInt = sizeof(oldBufferSize); getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &oldBufferSize, &sizeOfInt); - const int LARGER_SNDBUF_SIZE = 131072; + const int LARGER_SNDBUF_SIZE = 1048576; setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &LARGER_SNDBUF_SIZE, sizeof(LARGER_SNDBUF_SIZE)); From e2b230445fc0663c6c4b2d285c9d6eaaab351fa8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Mar 2014 10:28:59 -0700 Subject: [PATCH 4/9] add a method to Agent for last read frame loudness --- assignment-client/src/Agent.cpp | 13 ++++- assignment-client/src/Agent.h | 6 +++ assignment-client/src/audio/AudioMixer.cpp | 4 +- .../src/audio/AudioMixerClientData.cpp | 2 +- libraries/audio/src/AudioRingBuffer.cpp | 33 ++----------- libraries/audio/src/AudioRingBuffer.h | 6 +-- libraries/audio/src/MixedAudioRingBuffer.cpp | 49 +++++++++++++++++++ libraries/audio/src/MixedAudioRingBuffer.h | 26 ++++++++++ .../audio/src/PositionalAudioRingBuffer.cpp | 27 ++++++++++ .../audio/src/PositionalAudioRingBuffer.h | 5 ++ 10 files changed, 132 insertions(+), 39 deletions(-) create mode 100644 libraries/audio/src/MixedAudioRingBuffer.cpp create mode 100644 libraries/audio/src/MixedAudioRingBuffer.h diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index b23f9d210a..18051d816c 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -26,7 +26,8 @@ Agent::Agent(const QByteArray& packet) : ThreadedAssignment(packet), _voxelEditSender(), - _particleEditSender() + _particleEditSender(), + _receivedAudioBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO) { // be the parent of the script engine so it gets moved when we do _scriptEngine.setParent(this); @@ -113,6 +114,16 @@ void Agent::readPendingDatagrams() { _voxelViewer.processDatagram(mutablePacket, sourceNode); } + } else if (datagramPacketType == PacketTypeMixedAudio) { + // parse the data and grab the average loudness + _receivedAudioBuffer.parseData(receivedPacket); + + // pretend like we have read the samples from this buffer so it does not fill + static int16_t garbageAudioBuffer[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO]; + _receivedAudioBuffer.readSamples(garbageAudioBuffer, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO); + + // let this continue through to the NodeList so it updates last heard timestamp + // for the sending audio mixer } else { NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); } diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 0a61bd73f7..9e5f31213c 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ class Agent : public ThreadedAssignment { Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar) Q_PROPERTY(bool isPlayingAvatarSound READ isPlayingAvatarSound) Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream) + Q_PROPERTY(float lastReceivedAudioLoudness READ getLastReceivedAudioLoudness) public: Agent(const QByteArray& packet); @@ -41,6 +43,8 @@ public: bool isListeningToAudioStream() const { return _scriptEngine.isListeningToAudioStream(); } void setIsListeningToAudioStream(bool isListeningToAudioStream) { _scriptEngine.setIsListeningToAudioStream(isListeningToAudioStream); } + + float getLastReceivedAudioLoudness() const { return _receivedAudioBuffer.getLastReadFrameAverageLoudness(); } virtual void aboutToFinish(); @@ -56,6 +60,8 @@ private: ParticleTreeHeadlessViewer _particleViewer; VoxelTreeHeadlessViewer _voxelViewer; + + MixedAudioRingBuffer _receivedAudioBuffer; }; #endif /* defined(__hifi__Agent__) */ diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 82674e5141..f183abade9 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -93,7 +93,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf distanceBetween = EPSILON; } - if (bufferToAdd->getAverageLoudness() / distanceBetween <= _minAudibilityThreshold) { + if (bufferToAdd->getNextOutputTrailingLoudness() / distanceBetween <= _minAudibilityThreshold) { // according to mixer performance we have decided this does not get to be mixed in // bail out return; @@ -324,7 +324,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { if ((*otherNode != *node || otherNodeBuffer->shouldLoopbackForNode()) && otherNodeBuffer->willBeAddedToMix() - && otherNodeBuffer->getAverageLoudness() > 0) { + && otherNodeBuffer->getNextOutputTrailingLoudness() > 0) { addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); } } diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 381c80cb09..4a9f1f84de 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -92,7 +92,7 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam // calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL // that would be mixed in - _ringBuffers[i]->updateAverageLoudnessForBoundarySamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _ringBuffers[i]->updateNextOutputTrailingLoudness(); } } } diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 4732cc77d1..376b60ffa1 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -18,9 +18,9 @@ AudioRingBuffer::AudioRingBuffer(int numFrameSamples) : NodeData(), _sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES), + _numFrameSamples(numFrameSamples), _isStarved(true), - _hasStarted(false), - _averageLoudness(0) + _hasStarted(false) { if (numFrameSamples) { _buffer = new int16_t[_sampleCapacity]; @@ -56,33 +56,6 @@ int AudioRingBuffer::parseData(const QByteArray& packet) { return writeData(packet.data() + numBytesPacketHeader, packet.size() - numBytesPacketHeader); } -void AudioRingBuffer::updateAverageLoudnessForBoundarySamples(int numSamples) { - // ForBoundarySamples means that we expect the number of samples not to roll of the end of the ring buffer - float nextLoudness = 0; - - for (int i = 0; i < numSamples; ++i) { - nextLoudness += fabsf(_nextOutput[i]); - } - - nextLoudness /= numSamples; - nextLoudness /= MAX_SAMPLE_VALUE; - - const int TRAILING_AVERAGE_FRAMES = 100; - const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; - const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; - const float LOUDNESS_EPSILON = 0.01f; - - if (nextLoudness >= _averageLoudness) { - _averageLoudness = nextLoudness; - } else { - _averageLoudness = (_averageLoudness * PREVIOUS_FRAMES_RATIO) + (CURRENT_FRAME_RATIO * nextLoudness); - - if (_averageLoudness < LOUDNESS_EPSILON) { - _averageLoudness = 0; - } - } -} - qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) { return readData((char*) destination, maxSamples * sizeof(int16_t)); } @@ -112,7 +85,7 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) { return numReadSamples * sizeof(int16_t); } -qint64 AudioRingBuffer::writeSamples(const int16_t* source, qint64 maxSamples) { +qint64 AudioRingBuffer::writeSamples(const int16_t* source, qint64 maxSamples) { return writeData((const char*) source, maxSamples * sizeof(int16_t)); } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index efc85ac94b..e55eeda40e 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -49,9 +49,6 @@ public: // assume callers using this will never wrap around the end const int16_t* getNextOutput() { return _nextOutput; } const int16_t* getBuffer() { return _buffer; } - - void updateAverageLoudnessForBoundarySamples(int numSamples); - float getAverageLoudness() const { return _averageLoudness; } qint64 readSamples(int16_t* destination, qint64 maxSamples); qint64 writeSamples(const int16_t* source, qint64 maxSamples); @@ -81,13 +78,12 @@ protected: int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const; int _sampleCapacity; + int _numFrameSamples; int16_t* _nextOutput; int16_t* _endOfLastWrite; int16_t* _buffer; bool _isStarved; bool _hasStarted; - - float _averageLoudness; }; #endif /* defined(__interface__AudioRingBuffer__) */ diff --git a/libraries/audio/src/MixedAudioRingBuffer.cpp b/libraries/audio/src/MixedAudioRingBuffer.cpp new file mode 100644 index 0000000000..0ffab23519 --- /dev/null +++ b/libraries/audio/src/MixedAudioRingBuffer.cpp @@ -0,0 +1,49 @@ +// +// MixedAudioRingBuffer.cpp +// hifi +// +// Created by Stephen Birarda on 2014-03-26. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#include "MixedAudioRingBuffer.h" + +MixedAudioRingBuffer::MixedAudioRingBuffer(int numFrameSamples) : + AudioRingBuffer(numFrameSamples), + _lastReadFrameAverageLoudness(0.0f) +{ + +} + +qint64 MixedAudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) { + // calculate the average loudness for the frame about to go out + + // read from _nextOutput either _numFrameSamples or to the end of the buffer + int samplesFromNextOutput = _buffer + _sampleCapacity - _nextOutput; + if (samplesFromNextOutput > _numFrameSamples) { + samplesFromNextOutput = _numFrameSamples; + } + + float averageLoudness = 0.0f; + + for (int s = 0; s < samplesFromNextOutput; s++) { + averageLoudness += fabsf(_nextOutput[s]); + } + + // read samples from the beginning of the buffer, if any + int samplesFromBeginning = _numFrameSamples - samplesFromNextOutput; + + if (samplesFromBeginning > 0) { + for (int b = 0; b < samplesFromBeginning; b++) { + averageLoudness += fabsf(_buffer[b]); + } + } + + // divide by the number of samples and the MAX_SAMPLE_VALUE to get a float from 0 - 1 + averageLoudness /= (float) _numFrameSamples; + averageLoudness /= (float) MAX_SAMPLE_VALUE; + + _lastReadFrameAverageLoudness = averageLoudness; + + return AudioRingBuffer::readSamples(destination, maxSamples); +} \ No newline at end of file diff --git a/libraries/audio/src/MixedAudioRingBuffer.h b/libraries/audio/src/MixedAudioRingBuffer.h new file mode 100644 index 0000000000..c116361689 --- /dev/null +++ b/libraries/audio/src/MixedAudioRingBuffer.h @@ -0,0 +1,26 @@ +// +// MixedAudioRingBuffer.h +// hifi +// +// Created by Stephen Birarda on 2014-03-26. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__MixedAudioRingBuffer__ +#define __hifi__MixedAudioRingBuffer__ + +#include "AudioRingBuffer.h" + +class MixedAudioRingBuffer : public AudioRingBuffer { + Q_OBJECT +public: + MixedAudioRingBuffer(int numFrameSamples); + + float getLastReadFrameAverageLoudness() const { return _lastReadFrameAverageLoudness; } + + qint64 readSamples(int16_t* destination, qint64 maxSamples); +private: + float _lastReadFrameAverageLoudness; +}; + +#endif /* defined(__hifi__MixedAudioRingBuffer__) */ diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index d1729ddfef..7bdedfc793 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -72,6 +72,33 @@ int PositionalAudioRingBuffer::parsePositionalData(const QByteArray& positionalB return packetStream.device()->pos(); } +void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() { + // ForBoundarySamples means that we expect the number of samples not to roll of the end of the ring buffer + float nextLoudness = 0; + + for (int i = 0; i < _numFrameSamples; ++i) { + nextLoudness += fabsf(_nextOutput[i]); + } + + nextLoudness /= _numFrameSamples; + nextLoudness /= MAX_SAMPLE_VALUE; + + const int TRAILING_AVERAGE_FRAMES = 100; + const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; + const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; + const float LOUDNESS_EPSILON = 0.01f; + + if (nextLoudness >= _nextOutputTrailingLoudness) { + _nextOutputTrailingLoudness = nextLoudness; + } else { + _nextOutputTrailingLoudness = (_nextOutputTrailingLoudness * PREVIOUS_FRAMES_RATIO) + (CURRENT_FRAME_RATIO * nextLoudness); + + if (_nextOutputTrailingLoudness < LOUDNESS_EPSILON) { + _nextOutputTrailingLoudness = 0; + } + } +} + bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) { if (!isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + numJitterBufferSamples)) { if (_shouldOutputStarveDebug) { diff --git a/libraries/audio/src/PositionalAudioRingBuffer.h b/libraries/audio/src/PositionalAudioRingBuffer.h index e3fffa1689..a82df0b857 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.h +++ b/libraries/audio/src/PositionalAudioRingBuffer.h @@ -28,6 +28,9 @@ public: int parsePositionalData(const QByteArray& positionalByteArray); int parseListenModeData(const QByteArray& listenModeByteArray); + void updateNextOutputTrailingLoudness(); + float getNextOutputTrailingLoudness() const { return _nextOutputTrailingLoudness; } + bool shouldBeAddedToMix(int numJitterBufferSamples); bool willBeAddedToMix() const { return _willBeAddedToMix; } @@ -50,6 +53,8 @@ protected: bool _willBeAddedToMix; bool _shouldLoopbackForNode; bool _shouldOutputStarveDebug; + + float _nextOutputTrailingLoudness; }; #endif /* defined(__hifi__PositionalAudioRingBuffer__) */ From c4b8ff895256e1d4701fb78dac1d66cf85168c69 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Mar 2014 10:53:43 -0700 Subject: [PATCH 5/9] cast setsocktopt and getsockopt calls to fix windows build --- libraries/shared/src/NodeList.cpp | 13 ++++++++----- libraries/shared/src/NodeList.h | 2 ++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index d25c3f7e1d..6b54b8e8ae 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -83,21 +83,24 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : // clear our NodeList when logout is requested connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); + _packetStatTimer.start(); +} + +void NodeList::changeSendSocketBufferSize(int numSendBytes) { // change the socket send buffer size to be 1MB int oldBufferSize = 0; unsigned int sizeOfInt = sizeof(oldBufferSize); - getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &oldBufferSize, &sizeOfInt); + getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&oldBufferSize), &sizeOfInt); const int LARGER_SNDBUF_SIZE = 1048576; - setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &LARGER_SNDBUF_SIZE, sizeof(LARGER_SNDBUF_SIZE)); + setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&LARGER_SNDBUF_SIZE), + sizeof(LARGER_SNDBUF_SIZE)); int newBufferSize = 0; - getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, &newBufferSize, &sizeOfInt); + getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&newBufferSize), &sizeOfInt); qDebug() << "Changed socket send buffer size from" << oldBufferSize << "to" << newBufferSize << "bytes"; - - _packetStatTimer.start(); } bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index d892223f75..a108fd72c4 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -161,6 +161,8 @@ private: void requestAuthForDomainServer(); void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode); void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode); + + void changeSendSocketBufferSize(int numSendBytes); NodeHash _nodeHash; QMutex _nodeHashMutex; From e03e82a29bbfaed008ae863a2de1db751761acaf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Mar 2014 11:02:34 -0700 Subject: [PATCH 6/9] ifdef to handle getsockopt format requirements on windows --- libraries/shared/src/NodeList.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 6b54b8e8ae..4690e6ea20 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -89,7 +89,13 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : void NodeList::changeSendSocketBufferSize(int numSendBytes) { // change the socket send buffer size to be 1MB int oldBufferSize = 0; + +#ifdef Q_OS_WIN + int sizeOfInt = sizeof(oldBufferSize); +#else unsigned int sizeOfInt = sizeof(oldBufferSize); +#endif + getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&oldBufferSize), &sizeOfInt); const int LARGER_SNDBUF_SIZE = 1048576; From cb617c9e17349aa52220847f891370252c214a53 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Mar 2014 11:37:30 -0700 Subject: [PATCH 7/9] add a button on DS admin page to kill all nodes --- domain-server/resources/web/index.shtml | 4 ++ domain-server/resources/web/js/tables.js | 14 +++++++ domain-server/src/DomainServer.cpp | 49 ++++++++++++++---------- libraries/shared/src/NodeList.cpp | 4 +- libraries/shared/src/NodeList.h | 3 +- 5 files changed, 49 insertions(+), 25 deletions(-) diff --git a/domain-server/resources/web/index.shtml b/domain-server/resources/web/index.shtml index 29c39f6c02..bba4dc4d22 100644 --- a/domain-server/resources/web/index.shtml +++ b/domain-server/resources/web/index.shtml @@ -1,5 +1,9 @@

Nodes

+
+ diff --git a/domain-server/resources/web/js/tables.js b/domain-server/resources/web/js/tables.js index ae5095592b..18e67ac6e7 100644 --- a/domain-server/resources/web/js/tables.js +++ b/domain-server/resources/web/js/tables.js @@ -49,4 +49,18 @@ $(document).ready(function(){ } }); }); + + $(document.body).on('click', '#kill-all-btn', function() { + var confirmed_kill = confirm("Are you sure?"); + + if (confirmed_kill == true) { + $.ajax({ + url: "/nodes/", + type: 'DELETE', + success: function(result) { + console.log("Successful request to delete all nodes."); + } + }); + } + }); }); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 913ca44e12..035e6c9a20 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -657,6 +657,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url const QString URI_ASSIGNMENT = "/assignment"; const QString URI_NODES = "/nodes"; + const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; + if (connection->requestOperation() == QNetworkAccessManager::GetOperation) { if (url.path() == "/assignments.json") { // user is asking for json list of assignments @@ -726,9 +728,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return true; } else { - const QString NODE_REGEX_STRING = - QString("\\%1\\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}).json\\/?$").arg(URI_NODES); - QRegExp nodeShowRegex(NODE_REGEX_STRING); + const QString NODE_JSON_REGEX_STRING = QString("\\%1\\/(%2).json\\/?$").arg(URI_NODES).arg(UUID_REGEX_STRING); + QRegExp nodeShowRegex(NODE_JSON_REGEX_STRING); if (nodeShowRegex.indexIn(url.path()) != -1) { QUuid matchingUUID = QUuid(nodeShowRegex.cap(1)); @@ -801,29 +802,35 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return true; } } else if (connection->requestOperation() == QNetworkAccessManager::DeleteOperation) { - if (url.path().startsWith(URI_NODES)) { - // this is a request to DELETE a node by UUID + const QString ALL_NODE_DELETE_REGEX_STRING = QString("\\%1\\/?$").arg(URI_NODES); + const QString NODE_DELETE_REGEX_STRING = QString("\\%1\\/(%2)\\/$").arg(URI_NODES).arg(UUID_REGEX_STRING); + + QRegExp allNodesDeleteRegex(ALL_NODE_DELETE_REGEX_STRING); + QRegExp nodeDeleteRegex(NODE_DELETE_REGEX_STRING); + + if (nodeDeleteRegex.indexIn(url.path()) != -1) { + // this is a request to DELETE one node by UUID - // pull the UUID from the url - QUuid deleteUUID = QUuid(url.path().mid(URI_NODES.size() + sizeof('/'))); + // pull the captured string, if it exists + QUuid deleteUUID = QUuid(nodeDeleteRegex.cap(1)); - if (!deleteUUID.isNull()) { - SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID); + SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID); + + if (nodeToKill) { + // start with a 200 response + connection->respond(HTTPConnection::StatusCode200); - if (nodeToKill) { - // start with a 200 response - connection->respond(HTTPConnection::StatusCode200); - - // we have a valid UUID and node - kill the node that has this assignment - QMetaObject::invokeMethod(NodeList::getInstance(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID)); - - // successfully processed request - return true; - } + // we have a valid UUID and node - kill the node that has this assignment + QMetaObject::invokeMethod(NodeList::getInstance(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID)); + + // successfully processed request + return true; } - // bad request, couldn't pull a node ID - connection->respond(HTTPConnection::StatusCode400); + return true; + } else if (allNodesDeleteRegex.indexIn(url.path()) != -1) { + qDebug() << "Received request to kill all nodes."; + NodeList::getInstance()->eraseAllNodes(); return true; } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index e80f25709a..e150e42464 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -359,7 +359,7 @@ NodeHash NodeList::getNodeHash() { return NodeHash(_nodeHash); } -void NodeList::clear() { +void NodeList::eraseAllNodes() { qDebug() << "Clearing the NodeList. Deleting all nodes in list."; QMutexLocker locker(&_nodeHashMutex); @@ -373,7 +373,7 @@ void NodeList::clear() { } void NodeList::reset() { - clear(); + eraseAllNodes(); _numNoReplyDomainCheckIns = 0; // refresh the owner UUID to the NULL UUID diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index d892223f75..2eccc32aa4 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -128,6 +128,7 @@ public: void saveData(QSettings* settings); public slots: void reset(); + void eraseAllNodes(); void sendDomainServerCheckIn(); void pingInactiveNodes(); @@ -154,8 +155,6 @@ private: const QUuid& connectionSecret); NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill); - - void clear(); void processDomainServerAuthRequest(const QByteArray& packet); void requestAuthForDomainServer(); From 962c7350f3302385614c6197f6809b62ebf94e14 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Mar 2014 11:53:57 -0700 Subject: [PATCH 8/9] wait on broadcastThread before destroying AvatarMixer, closes #2499 --- assignment-client/src/avatars/AvatarMixer.cpp | 15 +++++++++------ assignment-client/src/avatars/AvatarMixer.h | 4 +++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index aaf58a7f42..c4c0dcda24 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -32,6 +32,7 @@ const unsigned int AVATAR_DATA_SEND_INTERVAL_MSECS = (1.0f / 60.0f) * 1000; AvatarMixer::AvatarMixer(const QByteArray& packet) : ThreadedAssignment(packet), + _broadcastThread(), _lastFrameTimestamp(QDateTime::currentMSecsSinceEpoch()), _trailingSleepRatio(1.0f), _performanceThrottlingRatio(0.0f), @@ -44,6 +45,11 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) : connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); } +AvatarMixer::~AvatarMixer() { + _broadcastThread.quit(); + _broadcastThread.wait(); +} + void attachAvatarDataToNode(Node* newNode) { if (!newNode->getLinkedData()) { newNode->setLinkedData(new AvatarMixerClientData()); @@ -309,18 +315,15 @@ void AvatarMixer::run() { nodeList->linkedDataCreateCallback = attachAvatarDataToNode; - // create a thead for broadcast of avatar data - QThread* broadcastThread = new QThread(this); - // setup the timer that will be fired on the broadcast thread QTimer* broadcastTimer = new QTimer(); broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS); - broadcastTimer->moveToThread(broadcastThread); + broadcastTimer->moveToThread(&_broadcastThread); // connect appropriate signals and slots connect(broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection); - connect(broadcastThread, SIGNAL(started()), broadcastTimer, SLOT(start())); + connect(&_broadcastThread, SIGNAL(started()), broadcastTimer, SLOT(start())); // start the broadcastThread - broadcastThread->start(); + _broadcastThread.start(); } diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 4171df49af..c9a145d2da 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -15,7 +15,7 @@ class AvatarMixer : public ThreadedAssignment { public: AvatarMixer(const QByteArray& packet); - + ~AvatarMixer(); public slots: /// runs the avatar mixer void run(); @@ -30,6 +30,8 @@ public slots: private: void broadcastAvatarData(); + QThread _broadcastThread; + quint64 _lastFrameTimestamp; float _trailingSleepRatio; From 6e161e7c6194743f3a73fb6ec4d3ba4f1fa9a173 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 26 Mar 2014 12:05:55 -0700 Subject: [PATCH 9/9] actually attempt to change send buffer size --- libraries/shared/src/NodeList.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 4690e6ea20..dbbf329b4a 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -83,6 +83,9 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : // clear our NodeList when logout is requested connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); + const int LARGER_SNDBUF_SIZE = 1048576; + changeSendSocketBufferSize(LARGER_SNDBUF_SIZE); + _packetStatTimer.start(); } @@ -98,10 +101,8 @@ void NodeList::changeSendSocketBufferSize(int numSendBytes) { getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&oldBufferSize), &sizeOfInt); - const int LARGER_SNDBUF_SIZE = 1048576; - - setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&LARGER_SNDBUF_SIZE), - sizeof(LARGER_SNDBUF_SIZE)); + setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&numSendBytes), + sizeof(numSendBytes)); int newBufferSize = 0; getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&newBufferSize), &sizeOfInt);