From 9dbbf8c65c8abbe6cf26f8059fee14ff5aa0da93 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 25 Oct 2013 09:22:23 -0700 Subject: [PATCH 1/8] don't alloc memory for checkInPacket, make it stack to function --- libraries/shared/src/NodeList.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index fb0b5176cf..fcd55116ad 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -492,10 +492,10 @@ void NodeList::sendDomainServerCheckIn() { // check in packet has header, optional UUID, node type, port, IP, node types of interest, null termination int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + - NUM_BYTES_RFC4122_UUID + (2 * (sizeof(uint16_t) + IP_ADDRESS_BYTES)) + - numBytesNodesOfInterest + sizeof(unsigned char); + NUM_BYTES_RFC4122_UUID + (2 * (sizeof(uint16_t) + IP_ADDRESS_BYTES)) + + numBytesNodesOfInterest + sizeof(unsigned char); - unsigned char* checkInPacket = new unsigned char[numPacketBytes]; + unsigned char checkInPacket[numPacketBytes]; unsigned char* packetPosition = checkInPacket; PACKET_TYPE nodePacketType = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES))) @@ -533,8 +533,6 @@ void NodeList::sendDomainServerCheckIn() { _nodeSocket.send(_domainIP.toString().toLocal8Bit().constData(), _domainPort, checkInPacket, packetPosition - checkInPacket); - - delete[] checkInPacket; // clean up const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5; static unsigned int numDomainCheckins = 0; From dc420beaf2cc4901309d0ba65a2dd61ef64fcc6e Mon Sep 17 00:00:00 2001 From: Don Park Date: Fri, 25 Oct 2013 10:09:34 -0700 Subject: [PATCH 2/8] updateWindowTitle() --- interface/src/Application.cpp | 13 +++++++++++++ interface/src/Application.h | 1 + 2 files changed, 14 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9b66b80c4c..67caadcd44 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3791,6 +3791,19 @@ void Application::attachNewHeadToNode(Node* newNode) { } } +void Application::updateWindowTitle(){ + QString title = ""; + QString username = _profile.getUsername(); + if(!username.isEmpty()){ + title += _profile.getUsername(); + title += " @ "; + } + title += _profile.getLastDomain(); + + qDebug("Application title set to: %s.\n", title.toStdString().c_str()); + _window->setWindowTitle(title); +} + void Application::domainChanged(QString domain) { qDebug("Application title set to: %s.\n", domain.toStdString().c_str()); _window->setWindowTitle(domain); diff --git a/interface/src/Application.h b/interface/src/Application.h index 6118bfb8b3..3333de3d7a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -206,6 +206,7 @@ private: void initDisplay(); void init(); + void updateWindowTitle(); void update(float deltaTime); From 67050f5cd22629df4580ee1d70b40c9422acbc9c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 25 Oct 2013 10:34:58 -0700 Subject: [PATCH 3/8] fix Assignment ctor from data to properly parse payload --- assignment-client/src/Agent.cpp | 33 ++++++++++++++--------------- domain-server/src/DomainServer.cpp | 2 +- libraries/shared/src/Assignment.cpp | 3 ++- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 5b778b0552..baf04372d2 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -159,26 +159,25 @@ void Agent::run() { // find the audio-mixer in the NodeList so we can inject audio at it Node* audioMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); + if (audioMixer && audioMixer->getActiveSocket()) { emit willSendAudioDataCallback(); + } + + int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow(); + if (usecToSleep > 0) { + usleep(usecToSleep); + } + + if (audioMixer && audioMixer->getActiveSocket() && scriptedAudioInjector.hasSamplesToInject()) { + // we have an audio mixer and samples to inject, send those off + scriptedAudioInjector.injectAudio(NodeList::getInstance()->getNodeSocket(), audioMixer->getActiveSocket()); - if (scriptedAudioInjector.hasSamplesToInject()) { - int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow(); - if (usecToSleep > 0) { - usleep(usecToSleep); - } - - scriptedAudioInjector.injectAudio(NodeList::getInstance()->getNodeSocket(), audioMixer->getActiveSocket()); - - // clear out the audio injector so that it doesn't re-send what we just sent - scriptedAudioInjector.clear(); - } - } else if (audioMixer) { - int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow(); - if (usecToSleep > 0) { - usleep(usecToSleep); - } - + // clear out the audio injector so that it doesn't re-send what we just sent + scriptedAudioInjector.clear(); + } + + if (audioMixer && !audioMixer->getActiveSocket()) { // don't have an active socket for the audio-mixer, ping it now NodeList::getInstance()->pingPublicAndLocalSocketsForInactiveNode(audioMixer); } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8f02c30b4c..d91d020a22 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -724,7 +724,7 @@ int DomainServer::run() { Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); if (assignmentToDeploy) { - + // give this assignment out, either the type matches or the requestor said they will take any int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); int numAssignmentBytes = assignmentToDeploy->packToBuffer(broadcastPacket + numHeaderBytes); diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 223488e4c5..07e96e4963 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -90,6 +90,7 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) : if (dataBuffer[numBytesRead] != '\0') { // read the pool from the data buffer setPool((const char*) dataBuffer + numBytesRead); + numBytesRead += strlen(_pool) + sizeof('\0'); } else { // skip past the null pool and null out our pool setPool(NULL); @@ -192,7 +193,7 @@ int Assignment::packToBuffer(unsigned char* buffer) { numPackedBytes += NUM_BYTES_RFC4122_UUID; } - if (_pool) { + if (hasPool()) { // pack the pool for this assignment, it exists int numBytesNullTerminatedPool = strlen(_pool) + sizeof('\0'); memcpy(buffer + numPackedBytes, _pool, numBytesNullTerminatedPool); From 8aad3e146f3d3b4d9c1975ee7c032d9dddec7fcc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 25 Oct 2013 10:49:35 -0700 Subject: [PATCH 4/8] avoid a divide by zero in PacketSender --- libraries/shared/src/PacketSender.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/shared/src/PacketSender.cpp b/libraries/shared/src/PacketSender.cpp index 5f6de128ba..ecd92a1f05 100644 --- a/libraries/shared/src/PacketSender.cpp +++ b/libraries/shared/src/PacketSender.cpp @@ -74,6 +74,8 @@ bool PacketSender::process() { // we can determine how many packets we need to send per call to achieve our desired // packets per second send rate. int callsPerSecond = USECS_PER_SECOND / averageCallTime; + // make sure our number of calls per second doesn't cause a divide by zero + glm::clamp(callsPerSecond, 1, _packetsPerSecond); packetsPerCall = ceil(_packetsPerSecond / callsPerSecond); // send at least one packet per call, if we have it From 248f59325cb6c0a40a04c1333434f94b085e2cac Mon Sep 17 00:00:00 2001 From: Don Park Date: Fri, 25 Oct 2013 11:05:50 -0700 Subject: [PATCH 5/8] update the window title when the domain changes or the username changes --- interface/src/Application.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 67caadcd44..4399895999 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -194,7 +194,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : // call Menu getInstance static method to set up the menu _window->setMenuBar(Menu::getInstance()); - + // Check to see if the user passed in a command line option for loading a local // Voxel File. _voxelsFilename = getCmdOption(argc, constArgv, "-i"); @@ -534,6 +534,7 @@ void Application::resetProfile(const QString& username) { // call the destructor on the old profile and construct a new one (&_profile)->~Profile(); new (&_profile) Profile(username); + updateWindowTitle(); } void Application::controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, @@ -3805,12 +3806,11 @@ void Application::updateWindowTitle(){ } void Application::domainChanged(QString domain) { - qDebug("Application title set to: %s.\n", domain.toStdString().c_str()); - _window->setWindowTitle(domain); - // update the user's last domain in their Profile (which will propagate to data-server) _profile.updateDomain(domain); + updateWindowTitle(); + // reset the environment so that we don't erroneously end up with multiple _environment.resetToDefault(); } From e44b0af9b6f2f74c937bd79083dd943084306735 Mon Sep 17 00:00:00 2001 From: Don Park Date: Fri, 25 Oct 2013 11:36:50 -0700 Subject: [PATCH 6/8] make updateWindowTitle public, call it after Menu loads data into the Profile --- interface/src/Application.h | 3 ++- interface/src/Menu.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 3333de3d7a..fb258f0353 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -109,6 +109,8 @@ public: void touchEndEvent(QTouchEvent* event); void touchUpdateEvent(QTouchEvent* event); + void updateWindowTitle(); + void wheelEvent(QWheelEvent* event); const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel); @@ -206,7 +208,6 @@ private: void initDisplay(); void init(); - void updateWindowTitle(); void update(float deltaTime); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1775c250f1..a31ff61ae8 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -532,6 +532,7 @@ void Menu::loadSettings(QSettings* settings) { Application::getInstance()->getAvatar()->loadData(settings); Application::getInstance()->getSwatch()->loadData(settings); Application::getInstance()->getProfile()->loadData(settings); + Application::getInstance()->updateWindowTitle(); NodeList::getInstance()->loadData(settings); } From dcccfb7ef041bde6f3e5f1ce239d14ed63ddac7f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 25 Oct 2013 14:03:49 -0700 Subject: [PATCH 7/8] temporarily force external child storage --- libraries/voxels/src/VoxelNode.cpp | 69 ++++++++++++++++-------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 7245d2aa56..4e46c4e450 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -351,6 +351,7 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const { int indexTwo = getNthBit(_childBitmask, 2); if (_childrenExternal) { + //assert(_children.external); if (indexOne == childIndex) { result = _children.external[0]; } else if (indexTwo == childIndex) { @@ -375,6 +376,7 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const { int indexThree = getNthBit(_childBitmask, 3); if (_childrenExternal) { + //assert(_children.external); if (indexOne == childIndex) { result = _children.external[0]; } else if (indexTwo == childIndex) { @@ -430,9 +432,11 @@ void VoxelNode::storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo) { const int64_t minOffset = std::numeric_limits::min(); const int64_t maxOffset = std::numeric_limits::max(); - if (isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset)) { + bool forceExternal = true; + if (!forceExternal && isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset)) { // if previously external, then clean it up... if (_childrenExternal) { + //assert(_children.external); const int previousChildCount = 2; _externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*); delete[] _children.external; @@ -539,7 +543,9 @@ void VoxelNode::storeThreeChildren(VoxelNode* childOne, VoxelNode* childTwo, Vox const int64_t minOffset = -1048576; // what can fit in 20 bits // std::numeric_limits::min(); const int64_t maxOffset = 1048576; // what can fit in 20 bits // std::numeric_limits::max(); - if (isBetween(offsetOne, maxOffset, minOffset) && + bool forceExternal = true; + if (!forceExternal && + isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset) && isBetween(offsetThree, maxOffset, minOffset)) { // if previously external, then clean it up... @@ -601,7 +607,9 @@ void VoxelNode::checkStoreFourChildren(VoxelNode* childOne, VoxelNode* childTwo, const int64_t minOffset = std::numeric_limits::min(); const int64_t maxOffset = std::numeric_limits::max(); - if (isBetween(offsetOne, maxOffset, minOffset) && + bool forceExternal = true; + if (!forceExternal && + isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset) && isBetween(offsetThree, maxOffset, minOffset) && isBetween(offsetFour, maxOffset, minOffset) @@ -720,7 +728,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { storeTwoChildren(childOne, childTwo); } else if (previousChildCount == 2 && newChildCount == 1) { // If we had 2 children, and we're removing one, then we know we can go down to single mode - assert(child == NULL); // this is the only logical case + //assert(child == NULL); // this is the only logical case int indexTwo = getNthBit(previousChildMask, 2); bool keepChildOne = indexTwo == childIndex; @@ -743,31 +751,19 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { int indexOne = getNthBit(previousChildMask, 1); bool replaceChildOne = indexOne == childIndex; - // If we previously had an external array, then just replace the right one... that's easy. - if (_childrenExternal) { - // technically, we could look to see if these are now in the offsets to handle be encoded, but - // we're going to go ahead and keep this as an array. - if (replaceChildOne) { - _children.external[0] = child; - } else { - _children.external[1] = child; - } - } else { - // If we were previously encoded as offsets, then we need to see if we can still encode as offsets - VoxelNode* childOne; - VoxelNode* childTwo; - - if (replaceChildOne) { - childOne = child; - childTwo = (VoxelNode*)((uint8_t*)this + _children.offsetsTwoChildren[1]); - } else { - childOne = (VoxelNode*)((uint8_t*)this + _children.offsetsTwoChildren[0]); - childTwo = child; - } + // Get the existing two children out of their encoding... + VoxelNode* childOne; + VoxelNode* childTwo; + retrieveTwoChildren(childOne, childTwo); - _twoChildrenOffsetCount--; // will end up one or the other - storeTwoChildren(childOne, childTwo); + if (replaceChildOne) { + childOne = child; + } else { + childTwo = child; } + + storeTwoChildren(childOne, childTwo); + } else if (previousChildCount == 2 && newChildCount == 3) { // If we had 2 children, and now have 3, then we know we are going to an external case... @@ -893,7 +889,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { _externalChildrenCount++; } else if (previousChildCount == 4 && newChildCount == 3) { // If we had 4 children, and now have 3, then we know we are going from an external case to a potential internal case - assert(_childrenExternal); + //assert(_children.external && _childrenExternal && previousChildCount == 4); // We need to determine which children we had, and which one we got rid of... int indexOne = getNthBit(previousChildMask, 1); @@ -928,10 +924,11 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { _children.external = NULL; _externalChildrenCount--; _externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*); - - storeThreeChildren(childOne, childTwo, childThree); } else if (previousChildCount == newChildCount) { + //assert(_children.external && _childrenExternal && previousChildCount >= 4); + //assert(previousChildCount == newChildCount); + // 4 or more children, one item being replaced, we know we're stored externally, we just need to find the one // that needs to be replaced and replace it. for (int ordinal = 1; ordinal <= 8; ordinal++) { @@ -944,6 +941,10 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { } } } else if (previousChildCount < newChildCount) { + // Growing case... previous must be 4 or greater + //assert(_children.external && _childrenExternal && previousChildCount >= 4); + //assert(previousChildCount == newChildCount-1); + // 4 or more children, one item being added, we know we're stored externally, we just figure out where to insert // this child pointer into our external list VoxelNode** newExternalList = new VoxelNode*[newChildCount]; @@ -975,13 +976,16 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { _externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*); } else if (previousChildCount > newChildCount) { + //assert(_children.external && _childrenExternal && previousChildCount >= 4); + //assert(previousChildCount == newChildCount+1); + // 4 or more children, one item being removed, we know we're stored externally, we just figure out which // item to remove from our external list VoxelNode** newExternalList = new VoxelNode*[newChildCount]; for (int ordinal = 1; ordinal <= previousChildCount; ordinal++) { int index = getNthBit(previousChildMask, ordinal); - assert(index != -1); + //assert(index != -1); if (index < childIndex) { newExternalList[ordinal - 1] = _children.external[ordinal - 1]; } else { @@ -997,7 +1001,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) { _externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*); _externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*); } else { - assert(false); + //assert(false); qDebug("THIS SHOULD NOT HAPPEN previousChildCount == %d && newChildCount == %d\n",previousChildCount, newChildCount); } @@ -1024,7 +1028,6 @@ VoxelNode* VoxelNode::addChildAtIndex(int childIndex) { childAt = new VoxelNode(childOctalCode(getOctalCode(), childIndex)); childAt->setVoxelSystem(getVoxelSystem()); // our child is always part of our voxel system NULL ok - setChildAtIndex(childIndex, childAt); _isDirty = true; From b8a87294e6cd7c645664339cc0ca8a865fe2644d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 25 Oct 2013 14:22:56 -0700 Subject: [PATCH 8/8] added guard to protect against external child access --- libraries/voxels/src/VoxelNode.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index 4e46c4e450..e83ffc1c16 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -409,7 +409,12 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const { for (int ordinal = 1; ordinal <= childCount; ordinal++) { int index = getNthBit(_childBitmask, ordinal); if (index == childIndex) { - result = _children.external[ordinal-1]; + int externalIndex = ordinal-1; + if (externalIndex < childCount && externalIndex >= 0) { + result = _children.external[externalIndex]; + } else { + qDebug("getChildAtIndex() attempt to access external client out of bounds externalIndex=%d <<<<<<<<<< WARNING!!! \n",externalIndex); + } break; } }