diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 30c59fa6f1..b324bab245 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include "AudioRingBuffer.h" @@ -168,167 +169,166 @@ void AudioMixer::run() { && (otherNode != node || (otherNode == node && nodeRingBuffer->shouldLoopbackForNode()))) { PositionalAudioRingBuffer* otherNodeBuffer = (PositionalAudioRingBuffer*) otherNode->getLinkedData(); // based on our listen mode we will do this mixing... - if (nodeRingBuffer->isListeningToNode(*otherNode)) { - float bearingRelativeAngleToSource = 0.0f; - float attenuationCoefficient = 1.0f; - int numSamplesDelay = 0; - float weakChannelAmplitudeRatio = 1.0f; + + float bearingRelativeAngleToSource = 0.0f; + float attenuationCoefficient = 1.0f; + int numSamplesDelay = 0; + float weakChannelAmplitudeRatio = 1.0f; + + stk::TwoPole* otherNodeTwoPole = NULL; + + if (otherNode != node) { - stk::TwoPole* otherNodeTwoPole = NULL; + glm::vec3 listenerPosition = nodeRingBuffer->getPosition(); + glm::vec3 relativePosition = otherNodeBuffer->getPosition() - nodeRingBuffer->getPosition(); + glm::quat inverseOrientation = glm::inverse(nodeRingBuffer->getOrientation()); - // only do axis/distance attenuation when in normal mode - if (otherNode != node && nodeRingBuffer->getListeningMode() == AudioRingBuffer::NORMAL) { - - glm::vec3 listenerPosition = nodeRingBuffer->getPosition(); - glm::vec3 relativePosition = otherNodeBuffer->getPosition() - nodeRingBuffer->getPosition(); - glm::quat inverseOrientation = glm::inverse(nodeRingBuffer->getOrientation()); - - float distanceSquareToSource = glm::dot(relativePosition, relativePosition); - float radius = 0.0f; - - if (otherNode->getType() == NODE_TYPE_AUDIO_INJECTOR) { - InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) otherNodeBuffer; - radius = injectedBuffer->getRadius(); - attenuationCoefficient *= injectedBuffer->getAttenuationRatio(); - } - - if (radius == 0 || (distanceSquareToSource > radius * radius)) { - // this is either not a spherical source, or the listener is outside the sphere - - if (radius > 0) { - // this is a spherical source - the distance used for the coefficient - // needs to be the closest point on the boundary to the source - - // ovveride the distance to the node with the distance to the point on the - // boundary of the sphere - distanceSquareToSource -= (radius * radius); - - } else { - // calculate the angle delivery for off-axis attenuation - glm::vec3 rotatedListenerPosition = glm::inverse(otherNodeBuffer->getOrientation()) - * relativePosition; - - float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedListenerPosition)); - - const float MAX_OFF_AXIS_ATTENUATION = 0.2f; - const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; - - float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + - (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / 90.0f)); - - // multiply the current attenuation coefficient by the calculated off axis coefficient - attenuationCoefficient *= offAxisCoefficient; - } - - glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - - const float DISTANCE_SCALE = 2.5f; - const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f; - const float DISTANCE_LOG_BASE = 2.5f; - const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE); - - // calculate the distance coefficient using the distance to this node - float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, - DISTANCE_SCALE_LOG + - (0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); - distanceCoefficient = std::min(1.0f, distanceCoefficient); - - // multiply the current attenuation coefficient by the distance coefficient - attenuationCoefficient *= distanceCoefficient; - - // project the rotated source position vector onto the XZ plane - rotatedSourcePosition.y = 0.0f; - - // produce an oriented angle about the y-axis - bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), - glm::normalize(rotatedSourcePosition), - glm::vec3(0.0f, 1.0f, 0.0f)); - - const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; - - // figure out the number of samples of delay and the ratio of the amplitude - // in the weak channel for audio spatialization - float sinRatio = fabsf(sinf(glm::radians(bearingRelativeAngleToSource))); - numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; - weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); - - // grab the TwoPole object for this source, add it if it doesn't exist - TwoPoleNodeMap& nodeTwoPoles = nodeRingBuffer->getTwoPoles(); - TwoPoleNodeMap::iterator twoPoleIterator = nodeTwoPoles.find(otherNode->getNodeID()); - - if (twoPoleIterator == nodeTwoPoles.end()) { - // setup the freeVerb effect for this source for this client - otherNodeTwoPole = nodeTwoPoles[otherNode->getNodeID()] = new stk::TwoPole; - } else { - otherNodeTwoPole = twoPoleIterator->second; - } - - // calculate the reasonance for this TwoPole based on angle to source - float TWO_POLE_CUT_OFF_FREQUENCY = 800.0f; - float TWO_POLE_MAX_FILTER_STRENGTH = 0.4f; - - otherNodeTwoPole->setResonance(TWO_POLE_CUT_OFF_FREQUENCY, - TWO_POLE_MAX_FILTER_STRENGTH - * fabsf(bearingRelativeAngleToSource) / 180.0f, - true); - } + float distanceSquareToSource = glm::dot(relativePosition, relativePosition); + float radius = 0.0f; + + if (otherNode->getType() == NODE_TYPE_AUDIO_INJECTOR) { + InjectedAudioRingBuffer* injectedBuffer = (InjectedAudioRingBuffer*) otherNodeBuffer; + radius = injectedBuffer->getRadius(); + attenuationCoefficient *= injectedBuffer->getAttenuationRatio(); } - int16_t* sourceBuffer = otherNodeBuffer->getNextOutput(); - - int16_t* goodChannel = (bearingRelativeAngleToSource > 0.0f) - ? clientSamples - : clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; - int16_t* delayedChannel = (bearingRelativeAngleToSource > 0.0f) - ? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL - : clientSamples; - - int16_t* delaySamplePointer = otherNodeBuffer->getNextOutput() == otherNodeBuffer->getBuffer() - ? otherNodeBuffer->getBuffer() + RING_BUFFER_LENGTH_SAMPLES - numSamplesDelay - : otherNodeBuffer->getNextOutput() - numSamplesDelay; - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - // load up the stkFrameBuffer with this source's samples - stkFrameBuffer[s] = (stk::StkFloat) sourceBuffer[s]; - } - - // perform the TwoPole effect on the stkFrameBuffer - if (otherNodeTwoPole) { - otherNodeTwoPole->tick(stkFrameBuffer); - } - - for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { - if (s < numSamplesDelay) { - // pull the earlier sample for the delayed channel - int earlierSample = delaySamplePointer[s] * attenuationCoefficient * weakChannelAmplitudeRatio; + if (radius == 0 || (distanceSquareToSource > radius * radius)) { + // this is either not a spherical source, or the listener is outside the sphere + + if (radius > 0) { + // this is a spherical source - the distance used for the coefficient + // needs to be the closest point on the boundary to the source - delayedChannel[s] = glm::clamp(delayedChannel[s] + earlierSample, - MIN_SAMPLE_VALUE, - MAX_SAMPLE_VALUE); + // ovveride the distance to the node with the distance to the point on the + // boundary of the sphere + distanceSquareToSource -= (radius * radius); + + } else { + // calculate the angle delivery for off-axis attenuation + glm::vec3 rotatedListenerPosition = glm::inverse(otherNodeBuffer->getOrientation()) + * relativePosition; + + float angleOfDelivery = glm::angle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedListenerPosition)); + + const float MAX_OFF_AXIS_ATTENUATION = 0.2f; + const float OFF_AXIS_ATTENUATION_FORMULA_STEP = (1 - MAX_OFF_AXIS_ATTENUATION) / 2.0f; + + float offAxisCoefficient = MAX_OFF_AXIS_ATTENUATION + + (OFF_AXIS_ATTENUATION_FORMULA_STEP * (angleOfDelivery / 90.0f)); + + // multiply the current attenuation coefficient by the calculated off axis coefficient + attenuationCoefficient *= offAxisCoefficient; } - int16_t currentSample = stkFrameBuffer[s] * attenuationCoefficient; + glm::vec3 rotatedSourcePosition = inverseOrientation * relativePosition; - goodChannel[s] = glm::clamp(goodChannel[s] + currentSample, - MIN_SAMPLE_VALUE, - MAX_SAMPLE_VALUE); + const float DISTANCE_SCALE = 2.5f; + const float GEOMETRIC_AMPLITUDE_SCALAR = 0.3f; + const float DISTANCE_LOG_BASE = 2.5f; + const float DISTANCE_SCALE_LOG = logf(DISTANCE_SCALE) / logf(DISTANCE_LOG_BASE); - if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - int sumSample = delayedChannel[s + numSamplesDelay] - + (currentSample * weakChannelAmplitudeRatio); - delayedChannel[s + numSamplesDelay] = glm::clamp(sumSample, - MIN_SAMPLE_VALUE, - MAX_SAMPLE_VALUE); + // calculate the distance coefficient using the distance to this node + float distanceCoefficient = powf(GEOMETRIC_AMPLITUDE_SCALAR, + DISTANCE_SCALE_LOG + + (0.5f * logf(distanceSquareToSource) / logf(DISTANCE_LOG_BASE)) - 1); + distanceCoefficient = std::min(1.0f, distanceCoefficient); + + // multiply the current attenuation coefficient by the distance coefficient + attenuationCoefficient *= distanceCoefficient; + + // project the rotated source position vector onto the XZ plane + rotatedSourcePosition.y = 0.0f; + + // produce an oriented angle about the y-axis + bearingRelativeAngleToSource = glm::orientedAngle(glm::vec3(0.0f, 0.0f, -1.0f), + glm::normalize(rotatedSourcePosition), + glm::vec3(0.0f, 1.0f, 0.0f)); + + const float PHASE_AMPLITUDE_RATIO_AT_90 = 0.5; + + // figure out the number of samples of delay and the ratio of the amplitude + // in the weak channel for audio spatialization + float sinRatio = fabsf(sinf(glm::radians(bearingRelativeAngleToSource))); + numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); + + // grab the TwoPole object for this source, add it if it doesn't exist + TwoPoleNodeMap& nodeTwoPoles = nodeRingBuffer->getTwoPoles(); + TwoPoleNodeMap::iterator twoPoleIterator = nodeTwoPoles.find(otherNode->getUUID()); + + if (twoPoleIterator == nodeTwoPoles.end()) { + // setup the freeVerb effect for this source for this client + otherNodeTwoPole = nodeTwoPoles[otherNode->getUUID()] = new stk::TwoPole; + } else { + otherNodeTwoPole = twoPoleIterator->second; } - if (s >= BUFFER_LENGTH_SAMPLES_PER_CHANNEL - PHASE_DELAY_AT_90) { - // this could be a delayed sample on the next pass - // so store the affected back in the ARB - otherNodeBuffer->getNextOutput()[s] = (int16_t) stkFrameBuffer[s]; - } + // calculate the reasonance for this TwoPole based on angle to source + float TWO_POLE_CUT_OFF_FREQUENCY = 800.0f; + float TWO_POLE_MAX_FILTER_STRENGTH = 0.4f; + + otherNodeTwoPole->setResonance(TWO_POLE_CUT_OFF_FREQUENCY, + TWO_POLE_MAX_FILTER_STRENGTH + * fabsf(bearingRelativeAngleToSource) / 180.0f, + true); } } + + int16_t* sourceBuffer = otherNodeBuffer->getNextOutput(); + + int16_t* goodChannel = (bearingRelativeAngleToSource > 0.0f) + ? clientSamples + : clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + int16_t* delayedChannel = (bearingRelativeAngleToSource > 0.0f) + ? clientSamples + BUFFER_LENGTH_SAMPLES_PER_CHANNEL + : clientSamples; + + int16_t* delaySamplePointer = otherNodeBuffer->getNextOutput() == otherNodeBuffer->getBuffer() + ? otherNodeBuffer->getBuffer() + RING_BUFFER_LENGTH_SAMPLES - numSamplesDelay + : otherNodeBuffer->getNextOutput() - numSamplesDelay; + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { + // load up the stkFrameBuffer with this source's samples + stkFrameBuffer[s] = (stk::StkFloat) sourceBuffer[s]; + } + + // perform the TwoPole effect on the stkFrameBuffer + if (otherNodeTwoPole) { + otherNodeTwoPole->tick(stkFrameBuffer); + } + + for (int s = 0; s < BUFFER_LENGTH_SAMPLES_PER_CHANNEL; s++) { + if (s < numSamplesDelay) { + // pull the earlier sample for the delayed channel + int earlierSample = delaySamplePointer[s] * attenuationCoefficient * weakChannelAmplitudeRatio; + + delayedChannel[s] = glm::clamp(delayedChannel[s] + earlierSample, + MIN_SAMPLE_VALUE, + MAX_SAMPLE_VALUE); + } + + int16_t currentSample = stkFrameBuffer[s] * attenuationCoefficient; + + goodChannel[s] = glm::clamp(goodChannel[s] + currentSample, + MIN_SAMPLE_VALUE, + MAX_SAMPLE_VALUE); + + if (s + numSamplesDelay < BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { + int sumSample = delayedChannel[s + numSamplesDelay] + + (currentSample * weakChannelAmplitudeRatio); + delayedChannel[s + numSamplesDelay] = glm::clamp(sumSample, + MIN_SAMPLE_VALUE, + MAX_SAMPLE_VALUE); + } + + if (s >= BUFFER_LENGTH_SAMPLES_PER_CHANNEL - PHASE_DELAY_AT_90) { + // this could be a delayed sample on the next pass + // so store the affected back in the ARB + otherNodeBuffer->getNextOutput()[s] = (int16_t) stkFrameBuffer[s]; + } + } + } } @@ -357,13 +357,12 @@ void AudioMixer::run() { packetData[0] == PACKET_TYPE_MICROPHONE_AUDIO_WITH_ECHO) { unsigned char* currentBuffer = packetData + numBytesForPacketHeader(packetData); - uint16_t sourceID; - memcpy(&sourceID, currentBuffer, sizeof(sourceID)); + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*) currentBuffer, NUM_BYTES_RFC4122_UUID)); - Node* avatarNode = nodeList->addOrUpdateNode(nodeAddress, - nodeAddress, + Node* avatarNode = nodeList->addOrUpdateNode(nodeUUID, NODE_TYPE_AGENT, - sourceID); + nodeAddress, + nodeAddress); nodeList->updateNodeWithData(nodeAddress, packetData, receivedBytes); @@ -372,30 +371,13 @@ void AudioMixer::run() { avatarNode->setAlive(false); } } else if (packetData[0] == PACKET_TYPE_INJECT_AUDIO) { - Node* matchingInjector = NULL; + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*) packetData + numBytesForPacketHeader(packetData), + NUM_BYTES_RFC4122_UUID)); - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getLinkedData()) { - - InjectedAudioRingBuffer* ringBuffer = (InjectedAudioRingBuffer*) node->getLinkedData(); - if (memcmp(ringBuffer->getStreamIdentifier(), - packetData + numBytesForPacketHeader(packetData), - STREAM_IDENTIFIER_NUM_BYTES) == 0) { - // this is the matching stream, assign to matchingInjector and stop looking - matchingInjector = &*node; - break; - } - } - } - - if (!matchingInjector) { - matchingInjector = nodeList->addOrUpdateNode(NULL, - NULL, - NODE_TYPE_AUDIO_INJECTOR, - nodeList->getLastNodeID()); - nodeList->increaseNodeID(); - - } + Node* matchingInjector = nodeList->addOrUpdateNode(nodeUUID, + NODE_TYPE_AUDIO_INJECTOR, + NULL, + NULL); // give the new audio data to the matching injector node nodeList->updateNodeWithData(matchingInjector, packetData, receivedBytes); diff --git a/assignment-client/src/audio/AvatarAudioRingBuffer.h b/assignment-client/src/audio/AvatarAudioRingBuffer.h index cfb6d7717c..a3e39073de 100644 --- a/assignment-client/src/audio/AvatarAudioRingBuffer.h +++ b/assignment-client/src/audio/AvatarAudioRingBuffer.h @@ -12,9 +12,11 @@ #include #include +#include + #include "PositionalAudioRingBuffer.h" -typedef std::map TwoPoleNodeMap; +typedef std::map TwoPoleNodeMap; class AvatarAudioRingBuffer : public PositionalAudioRingBuffer { public: diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 5c7e47a42a..cdbefdf73d 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "AvatarData.h" @@ -22,7 +23,9 @@ const char AVATAR_MIXER_LOGGING_NAME[] = "avatar-mixer"; unsigned char* addNodeToBroadcastPacket(unsigned char *currentPosition, Node *nodeToAdd) { - currentPosition += packNodeId(currentPosition, nodeToAdd->getNodeID()); + QByteArray rfcUUID = nodeToAdd->getUUID().toRfc4122(); + memcpy(currentPosition, rfcUUID.constData(), rfcUUID.size()); + currentPosition += rfcUUID.size(); AvatarData *nodeData = (AvatarData *)nodeToAdd->getLinkedData(); currentPosition += nodeData->getBroadcastData(currentPosition); @@ -103,7 +106,7 @@ void AvatarMixer::run() { unsigned char* packetData = new unsigned char[MAX_PACKET_SIZE]; - uint16_t nodeID = 0; + QUuid nodeUUID; Node* avatarNode = NULL; timeval lastDomainServerCheckIn = {}; @@ -124,11 +127,11 @@ void AvatarMixer::run() { packetVersionMatch(packetData)) { switch (packetData[0]) { case PACKET_TYPE_HEAD_DATA: - // grab the node ID from the packet - unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID); + nodeUUID = QUuid::fromRfc4122(QByteArray((char*) packetData + numBytesForPacketHeader(packetData), + NUM_BYTES_RFC4122_UUID)); // add or update the node in our list - avatarNode = nodeList->addOrUpdateNode(&nodeAddress, &nodeAddress, NODE_TYPE_AGENT, nodeID); + avatarNode = nodeList->addOrUpdateNode(nodeUUID, NODE_TYPE_AGENT, &nodeAddress, &nodeAddress); // parse positional data from an node nodeList->updateNodeWithData(avatarNode, packetData, receivedBytes); @@ -137,12 +140,11 @@ void AvatarMixer::run() { break; case PACKET_TYPE_AVATAR_URLS: case PACKET_TYPE_AVATAR_FACE_VIDEO: - // grab the node ID from the packet - unpackNodeId(packetData + numBytesForPacketHeader(packetData), &nodeID); - + nodeUUID = QUuid::fromRfc4122(QByteArray((char*) packetData + numBytesForPacketHeader(packetData), + NUM_BYTES_RFC4122_UUID)); // let everyone else know about the update for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (node->getActiveSocket() && node->getNodeID() != nodeID) { + if (node->getActiveSocket() && node->getUUID() != nodeUUID) { nodeList->getNodeSocket()->send(node->getActiveSocket(), packetData, receivedBytes); } } diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 03578c4e8a..7597ea47f5 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -91,6 +91,8 @@ void childClient() { nodeList->setDomainIP(QHostAddress((sockaddr*) &senderSocket)); nodeList->setDomainPort(ntohs(senderSocket.sin_port)); + nodeList->setOwnerUUID(deployedAssignment->getUUID()); + qDebug("Destination IP for assignment is %s\n", nodeList->getDomainIP().toString().toStdString().c_str()); // run the deployed assignment diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 3736b77e03..240befe800 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -154,7 +154,7 @@ void DomainServer::civetwebUploadHandler(struct mg_connection *connection, const } void DomainServer::nodeAdded(Node* node) { - NodeList::getInstance()->increaseNodeID(); + } void DomainServer::nodeKilled(Node* node) { @@ -187,7 +187,11 @@ void DomainServer::nodeKilled(Node* node) { unsigned char* DomainServer::addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) { *currentPosition++ = nodeToAdd->getType(); - currentPosition += packNodeId(currentPosition, nodeToAdd->getNodeID()); + + QByteArray rfcUUID = nodeToAdd->getUUID().toRfc4122(); + memcpy(currentPosition, rfcUUID.constData(), rfcUUID.size()); + currentPosition += rfcUUID.size(); + currentPosition += packSocket(currentPosition, nodeToAdd->getPublicSocket()); currentPosition += packSocket(currentPosition, nodeToAdd->getLocalSocket()); @@ -291,11 +295,8 @@ void DomainServer::prepopulateStaticAssignmentFile() { _staticAssignmentFile.close(); } -Assignment* DomainServer::matchingStaticAssignmentForCheckIn(NODE_TYPE nodeType, const uchar* checkInData) { +Assignment* DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NODE_TYPE nodeType) { // pull the UUID passed with the check in - QUuid checkInUUID = QUuid::fromRfc4122(QByteArray((const char*) checkInData + numBytesForPacketHeader(checkInData) + - sizeof(NODE_TYPE), - NUM_BYTES_RFC4122_UUID)); if (_hasCompletedRestartHold) { _assignmentQueueMutex.lock(); @@ -395,19 +396,14 @@ void DomainServer::removeAssignmentFromQueue(Assignment* removableAssignment) { bool DomainServer::checkInWithUUIDMatchesExistingNode(sockaddr* nodePublicSocket, sockaddr* nodeLocalSocket, - const uchar* checkInData) { - // pull the UUID passed with the check in - QUuid checkInUUID = QUuid::fromRfc4122(QByteArray((const char*) checkInData + numBytesForPacketHeader(checkInData) + - sizeof(NODE_TYPE), - NUM_BYTES_RFC4122_UUID)); - + const QUuid& checkInUUID) { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getLinkedData() && socketMatch(node->getPublicSocket(), nodePublicSocket) && socketMatch(node->getLocalSocket(), nodeLocalSocket) - && ((Assignment*) node->getLinkedData())->getUUID() == checkInUUID) { + && node->getUUID() == checkInUUID) { // this is a matching existing node if the public socket, local socket, and UUID match return true; } @@ -515,7 +511,9 @@ int DomainServer::run() { nodeType = *(packetData + numBytesSenderHeader); - int packetIndex = numBytesSenderHeader + sizeof(NODE_TYPE) + NUM_BYTES_RFC4122_UUID; + int packetIndex = numBytesSenderHeader + sizeof(NODE_TYPE); + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray(((char*) packetData + packetIndex), NUM_BYTES_RFC4122_UUID)); + packetIndex += NUM_BYTES_RFC4122_UUID; int numBytesPrivateSocket = unpackSocket(packetData + packetIndex, (sockaddr*) &nodePublicAddress); packetIndex += numBytesPrivateSocket; @@ -531,16 +529,16 @@ int DomainServer::run() { Assignment* matchingStaticAssignment = NULL; - if (memchr(STATICALLY_ASSIGNED_NODES, nodeType, sizeof(STATICALLY_ASSIGNED_NODES)) == NULL || - ((matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeType, packetData)) || - checkInWithUUIDMatchesExistingNode((sockaddr*) &nodePublicAddress, - (sockaddr*) &nodeLocalAddress, - packetData))) { - - Node* checkInNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress, - (sockaddr*) &nodeLocalAddress, + if (memchr(STATICALLY_ASSIGNED_NODES, nodeType, sizeof(STATICALLY_ASSIGNED_NODES)) == NULL + || ((matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType)) + || checkInWithUUIDMatchesExistingNode((sockaddr*) &nodePublicAddress, + (sockaddr*) &nodeLocalAddress, + nodeUUID))) + { + Node* checkInNode = nodeList->addOrUpdateNode(nodeUUID, nodeType, - nodeList->getLastNodeID()); + (sockaddr*) &nodePublicAddress, + (sockaddr*) &nodeLocalAddress); if (matchingStaticAssignment) { // this was a newly added node with a matching static assignment @@ -584,9 +582,6 @@ int DomainServer::run() { uint64_t timeNow = usecTimestampNow(); checkInNode->setLastHeardMicrostamp(timeNow); - // add the node ID to the end of the pointer - currentBufferPos += packNodeId(currentBufferPos, checkInNode->getNodeID()); - // send the constructed list back to this node nodeList->getNodeSocket()->send((sockaddr*)&senderAddress, broadcastPacket, diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 540ca67acd..205d9e8f6e 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -42,10 +42,10 @@ private: static DomainServer* domainServerInstance; void prepopulateStaticAssignmentFile(); - Assignment* matchingStaticAssignmentForCheckIn(NODE_TYPE nodeType, const uchar* checkInUUID); + Assignment* matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NODE_TYPE nodeType); Assignment* deployableAssignmentForRequest(Assignment& requestAssignment); void removeAssignmentFromQueue(Assignment* removableAssignment); - bool checkInWithUUIDMatchesExistingNode(sockaddr* nodePublicSocket, sockaddr* nodeLocalSocket, const uchar* checkInData); + bool checkInWithUUIDMatchesExistingNode(sockaddr* nodePublicSocket, sockaddr* nodeLocalSocket, const QUuid& checkInUUI); void possiblyAddStaticAssignmentsBackToQueueAfterRestart(timeval* startTime); void cleanup(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c40cc2e81e..c297f771ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -54,7 +54,7 @@ #include #include #include - +#include #include #include "Application.h" @@ -1160,8 +1160,9 @@ void Application::sendAvatarFaceVideoMessage(int frameCount, const QByteArray& d packetPosition += populateTypeAndVersion(packetPosition, PACKET_TYPE_AVATAR_FACE_VIDEO); - *(uint16_t*)packetPosition = NodeList::getInstance()->getOwnerID(); - packetPosition += sizeof(uint16_t); + QByteArray rfcUUID = NodeList::getInstance()->getOwnerUUID().toRfc4122(); + memcpy(packetPosition, rfcUUID.constData(), rfcUUID.size()); + packetPosition += rfcUUID.size(); *(uint32_t*)packetPosition = frameCount; packetPosition += sizeof(uint32_t); @@ -1295,12 +1296,13 @@ static Avatar* processAvatarMessageHeader(unsigned char*& packetData, size_t& da dataBytes -= numBytesPacketHeader; // read the node id - uint16_t nodeID = *(uint16_t*)packetData; - packetData += sizeof(nodeID); - dataBytes -= sizeof(nodeID); + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*) packetData, NUM_BYTES_RFC4122_UUID)); + + packetData += NUM_BYTES_RFC4122_UUID; + dataBytes -= NUM_BYTES_RFC4122_UUID; // make sure the node exists - Node* node = NodeList::getInstance()->nodeWithID(nodeID); + Node* node = NodeList::getInstance()->nodeWithUUID(nodeUUID); if (!node || !node->getLinkedData()) { return NULL; } @@ -1560,29 +1562,6 @@ void Application::deleteVoxels() { deleteVoxelUnderCursor(); } -void Application::setListenModeNormal() { - _audio.setListenMode(AudioRingBuffer::NORMAL); -} - -void Application::setListenModePoint() { - _audio.setListenMode(AudioRingBuffer::OMNI_DIRECTIONAL_POINT); - _audio.setListenRadius(1.0); -} - -void Application::setListenModeSingleSource() { - _audio.setListenMode(AudioRingBuffer::SELECTED_SOURCES); - _audio.clearListenSources(); - - glm::vec3 mouseRayOrigin = _myAvatar.getMouseRayOrigin(); - glm::vec3 mouseRayDirection = _myAvatar.getMouseRayDirection(); - glm::vec3 eyePositionIgnored; - uint16_t nodeID; - - if (findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeID)) { - _audio.addListenSource(nodeID); - } -} - void Application::initDisplay() { glEnable(GL_BLEND); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); @@ -1688,7 +1667,7 @@ const float MAX_AVATAR_EDIT_VELOCITY = 1.0f; const float MAX_VOXEL_EDIT_DISTANCE = 20.0f; const float HEAD_SPHERE_RADIUS = 0.07; -static uint16_t DEFAULT_NODE_ID_REF = 1; +static QUuid DEFAULT_NODE_ID_REF; void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, glm::vec3& eyePosition) { @@ -1697,7 +1676,7 @@ void Application::updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, cons } Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, - glm::vec3& eyePosition, uint16_t& nodeID = DEFAULT_NODE_ID_REF) { + glm::vec3& eyePosition, QUuid& nodeUUID = DEFAULT_NODE_ID_REF) { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { @@ -1710,7 +1689,7 @@ Avatar* Application::findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, con eyePosition = avatar->getHead().getEyePosition(); _lookatIndicatorScale = avatar->getHead().getScale(); _lookatOtherPosition = headPosition; - nodeID = avatar->getOwningNode()->getNodeID(); + nodeUUID = avatar->getOwningNode()->getUUID(); return avatar; } } @@ -1759,12 +1738,12 @@ void Application::renderFollowIndicator() { Avatar* avatar = (Avatar *) node->getLinkedData(); Avatar* leader = NULL; - if (avatar->getLeaderID() != UNKNOWN_NODE_ID) { - if (avatar->getLeaderID() == NodeList::getInstance()->getOwnerID()) { + if (!avatar->getLeaderUUID().isNull()) { + if (avatar->getLeaderUUID() == NodeList::getInstance()->getOwnerUUID()) { leader = &_myAvatar; } else { for (NodeList::iterator it = nodeList->begin(); it != nodeList->end(); ++it) { - if(it->getNodeID() == avatar->getLeaderID() + if(it->getUUID() == avatar->getLeaderUUID() && it->getType() == NODE_TYPE_AGENT) { leader = (Avatar*) it->getLinkedData(); } @@ -2244,26 +2223,27 @@ void Application::updateAvatar(float deltaTime) { _myAvatar.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); NodeList* nodeList = NodeList::getInstance(); - if (nodeList->getOwnerID() != UNKNOWN_NODE_ID) { - // if I know my ID, send head/hand data to the avatar mixer and voxel server - unsigned char broadcastString[MAX_PACKET_SIZE]; - unsigned char* endOfBroadcastStringWrite = broadcastString; - - endOfBroadcastStringWrite += populateTypeAndVersion(endOfBroadcastStringWrite, PACKET_TYPE_HEAD_DATA); - - endOfBroadcastStringWrite += packNodeId(endOfBroadcastStringWrite, nodeList->getOwnerID()); - - endOfBroadcastStringWrite += _myAvatar.getBroadcastData(endOfBroadcastStringWrite); - - const char nodeTypesOfInterest[] = { NODE_TYPE_VOXEL_SERVER, NODE_TYPE_AVATAR_MIXER }; - controlledBroadcastToNodes(broadcastString, endOfBroadcastStringWrite - broadcastString, - nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); - - // once in a while, send my urls - const float AVATAR_URLS_SEND_INTERVAL = 1.0f; // seconds - if (shouldDo(AVATAR_URLS_SEND_INTERVAL, deltaTime)) { - Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL()); - } + + // send head/hand data to the avatar mixer and voxel server + unsigned char broadcastString[MAX_PACKET_SIZE]; + unsigned char* endOfBroadcastStringWrite = broadcastString; + + endOfBroadcastStringWrite += populateTypeAndVersion(endOfBroadcastStringWrite, PACKET_TYPE_HEAD_DATA); + + QByteArray ownerUUID = nodeList->getOwnerUUID().toRfc4122(); + memcpy(endOfBroadcastStringWrite, ownerUUID.constData(), ownerUUID.size()); + endOfBroadcastStringWrite += ownerUUID.size(); + + endOfBroadcastStringWrite += _myAvatar.getBroadcastData(endOfBroadcastStringWrite); + + const char nodeTypesOfInterest[] = { NODE_TYPE_VOXEL_SERVER, NODE_TYPE_AVATAR_MIXER }; + controlledBroadcastToNodes(broadcastString, endOfBroadcastStringWrite - broadcastString, + nodeTypesOfInterest, sizeof(nodeTypesOfInterest)); + + // once in a while, send my urls + const float AVATAR_URLS_SEND_INTERVAL = 1.0f; // seconds + if (shouldDo(AVATAR_URLS_SEND_INTERVAL, deltaTime)) { + Avatar::sendAvatarURLsMessage(_myAvatar.getVoxels()->getVoxelURL()); } } @@ -3557,8 +3537,8 @@ void Application::toggleFollowMode() { _pieMenu.getY() / (float)_glWidget->height(), mouseRayOrigin, mouseRayDirection); glm::vec3 eyePositionIgnored; - uint16_t nodeIDIgnored; - Avatar* leadingAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeIDIgnored); + QUuid nodeUUIDIgnored; + Avatar* leadingAvatar = findLookatTargetAvatar(mouseRayOrigin, mouseRayDirection, eyePositionIgnored, nodeUUIDIgnored); _myAvatar.follow(leadingAvatar); } @@ -3626,10 +3606,10 @@ void Application::nodeAdded(Node* node) { void Application::nodeKilled(Node* node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { - uint16_t nodeID = node->getNodeID(); + QUuid nodeUUID = node->getUUID(); // see if this is the first we've heard of this node... - if (_voxelServerJurisdictions.find(nodeID) != _voxelServerJurisdictions.end()) { - unsigned char* rootCode = _voxelServerJurisdictions[nodeID].getRootOctalCode(); + if (_voxelServerJurisdictions.find(nodeUUID) != _voxelServerJurisdictions.end()) { + unsigned char* rootCode = _voxelServerJurisdictions[nodeUUID].getRootOctalCode(); VoxelPositionSize rootDetails; voxelDetailsForCode(rootCode, rootDetails); @@ -3659,13 +3639,13 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng // quick fix for crash... why would voxelServer be NULL? if (voxelServer) { - uint16_t nodeID = voxelServer->getNodeID(); + QUuid nodeUUID = voxelServer->getUUID(); VoxelPositionSize rootDetails; voxelDetailsForCode(_voxelSceneStats.getJurisdictionRoot(), rootDetails); // see if this is the first we've heard of this node... - if (_voxelServerJurisdictions.find(nodeID) == _voxelServerJurisdictions.end()) { + if (_voxelServerJurisdictions.find(nodeUUID) == _voxelServerJurisdictions.end()) { printf("stats from new voxel server... v[%f, %f, %f, %f]\n", rootDetails.x, rootDetails.y, rootDetails.z, rootDetails.s); @@ -3682,7 +3662,7 @@ int Application::parseVoxelStats(unsigned char* messageData, ssize_t messageLeng // details from the VoxelSceneStats to construct the JurisdictionMap JurisdictionMap jurisdictionMap; jurisdictionMap.copyContents(_voxelSceneStats.getJurisdictionRoot(), _voxelSceneStats.getJurisdictionEndNodes()); - _voxelServerJurisdictions[nodeID] = jurisdictionMap; + _voxelServerJurisdictions[nodeUUID] = jurisdictionMap; } return statsMessageLength; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 595f337bf5..0aae683844 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -171,9 +171,6 @@ public slots: void doKillLocalVoxels(); void decreaseVoxelSize(); void increaseVoxelSize(); - void setListenModeNormal(); - void setListenModePoint(); - void setListenModeSingleSource(); private slots: @@ -213,7 +210,7 @@ private: void updateLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, glm::vec3& eyePosition); Avatar* findLookatTargetAvatar(const glm::vec3& mouseRayOrigin, const glm::vec3& mouseRayDirection, - glm::vec3& eyePosition, uint16_t& nodeID); + glm::vec3& eyePosition, QUuid &nodeUUID); bool isLookingAtMyAvatar(Avatar* avatar); void renderLookatIndicator(glm::vec3 pointOfInterest, Camera& whichCamera); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index b4866432da..152ce8d74b 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -124,31 +124,10 @@ inline void Audio::performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* o unsigned char* currentPacketPtr = dataPacket + populateTypeAndVersion(dataPacket, packetType); // pack Source Data - uint16_t ownerID = NodeList::getInstance()->getOwnerID(); - memcpy(currentPacketPtr, &ownerID, sizeof(ownerID)); - currentPacketPtr += (sizeof(ownerID)); - leadingBytes += (sizeof(ownerID)); - - // pack Listen Mode Data - memcpy(currentPacketPtr, &_listenMode, sizeof(_listenMode)); - currentPacketPtr += (sizeof(_listenMode)); - leadingBytes += (sizeof(_listenMode)); - - if (_listenMode == AudioRingBuffer::OMNI_DIRECTIONAL_POINT) { - memcpy(currentPacketPtr, &_listenRadius, sizeof(_listenRadius)); - currentPacketPtr += (sizeof(_listenRadius)); - leadingBytes += (sizeof(_listenRadius)); - } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { - int listenSourceCount = _listenSources.size(); - memcpy(currentPacketPtr, &listenSourceCount, sizeof(listenSourceCount)); - currentPacketPtr += (sizeof(listenSourceCount)); - leadingBytes += (sizeof(listenSourceCount)); - for (int i = 0; i < listenSourceCount; i++) { - memcpy(currentPacketPtr, &_listenSources[i], sizeof(_listenSources[i])); - currentPacketPtr += sizeof(_listenSources[i]); - leadingBytes += sizeof(_listenSources[i]); - } - } + QByteArray rfcUUID = NodeList::getInstance()->getOwnerUUID().toRfc4122(); + memcpy(currentPacketPtr, rfcUUID.constData(), rfcUUID.size()); + currentPacketPtr += rfcUUID.size(); + leadingBytes += rfcUUID.size(); // memcpy the three float positions memcpy(currentPacketPtr, &headPosition, sizeof(headPosition)); @@ -347,24 +326,6 @@ void Audio::reset() { _ringBuffer.reset(); } -void Audio::addListenSource(int sourceID) { - _listenSources.push_back(sourceID); -} - -void Audio::clearListenSources() { - _listenSources.clear(); -} - -void Audio::removeListenSource(int sourceID) { - for (int i = 0; i < _listenSources.size(); i++) { - if (_listenSources[i] == sourceID) { - _listenSources.erase(_listenSources.begin() + i); - return; - } - } -} - - Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _stream(NULL), _ringBuffer(true), @@ -395,9 +356,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples) : _collisionSoundDuration(0.0f), _proceduralEffectSample(0), _heartbeatMagnitude(0.0f), - _muted(false), - _listenMode(AudioRingBuffer::NORMAL), - _listenRadius(0.0f) + _muted(false) { outputPortAudioError(Pa_Initialize()); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 7c66c7e375..6dad16f366 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -68,13 +68,6 @@ public: // in which case 'true' is returned - otherwise the return value is 'false'. // The results of the analysis are written to the log. bool eventuallyAnalyzePing(); - - void setListenMode(AudioRingBuffer::ListenMode mode) { _listenMode = mode; } - void setListenRadius(float radius) { _listenRadius = radius; } - void addListenSource(int sourceID); - void removeListenSource(int sourceID); - void clearListenSources(); - private: PaStream* _stream; @@ -117,10 +110,6 @@ private: GLuint _muteTextureId; QRect _iconBounds; - AudioRingBuffer::ListenMode _listenMode; - float _listenRadius; - std::vector _listenSources; - // Audio callback in class context. inline void performIO(int16_t* inputLeft, int16_t* outputLeft, int16_t* outputRight); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f9479865c6..f3bae87d4c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -442,21 +442,6 @@ Menu::Menu() : QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools"); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoAudio); - addActionToQMenuAndActionHash(audioDebugMenu, - MenuOption::ListenModeNormal, - Qt::CTRL | Qt::Key_1, - appInstance, - SLOT(setListenModeNormal())); - addActionToQMenuAndActionHash(audioDebugMenu, - MenuOption::ListenModePoint, - Qt::CTRL | Qt::Key_2, - appInstance, - SLOT(setListenModePoint())); - addActionToQMenuAndActionHash(audioDebugMenu, - MenuOption::ListenModeSingleSource, - Qt::CTRL | Qt::Key_3, - appInstance, - SLOT(setListenModeSingleSource())); QMenu* voxelProtoOptionsMenu = developerMenu->addMenu("Voxel Server Protocol Options"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 81d213c026..86e40ee928 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -176,9 +176,6 @@ namespace MenuOption { const QString Gravity = "Use Gravity"; const QString GroundPlane = "Ground Plane"; const QString ParticleCloud = "Particle Cloud"; - const QString ListenModeNormal = "Listen Mode Normal"; - const QString ListenModePoint = "Listen Mode Point"; - const QString ListenModeSingleSource = "Listen Mode Single Source"; const QString Log = "Log"; const QString Login = "Login"; const QString LookAtIndicator = "Look-at Indicator"; diff --git a/interface/src/VoxelPacketProcessor.cpp b/interface/src/VoxelPacketProcessor.cpp index e33f377edc..58c0f850d5 100644 --- a/interface/src/VoxelPacketProcessor.cpp +++ b/interface/src/VoxelPacketProcessor.cpp @@ -47,13 +47,11 @@ void VoxelPacketProcessor::processPacket(sockaddr& senderAddress, unsigned char* if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { Node* voxelServer = NodeList::getInstance()->nodeWithAddress(&senderAddress); if (voxelServer && socketMatch(voxelServer->getActiveSocket(), &senderAddress)) { - int nodeID = voxelServer->getNodeID(); if (packetData[0] == PACKET_TYPE_ENVIRONMENT_DATA) { app->_environment.parseData(&senderAddress, packetData, messageLength); } else { - app->_voxels.setDataSourceID(nodeID); app->_voxels.parseData(packetData, messageLength); - app->_voxels.setDataSourceID(UNKNOWN_NODE_ID); + app->_voxels.setDataSourceID(0); } } } diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 574615d113..278bc51454 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -82,7 +82,7 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels) VoxelNode::addUpdateHook(this); _abandonedVBOSlots = 0; _falseColorizeBySource = false; - _dataSourceID = UNKNOWN_NODE_ID; + _dataSourceID = 0; _voxelServerCount = 0; _viewFrustum = Application::getInstance()->getViewFrustum(); @@ -1442,7 +1442,7 @@ void VoxelSystem::falseColorizeBySource() { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { - uint16_t nodeID = node->getNodeID(); + uint16_t nodeID = 0; // hardcoded since removal of 16 bit node IDs int groupColor = voxelServerCount % NUMBER_OF_COLOR_GROUPS; args.colors[nodeID] = groupColors[groupColor]; @@ -2299,8 +2299,7 @@ void VoxelSystem::falseColorizeOccludedV2() { void VoxelSystem::nodeAdded(Node* node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { - uint16_t nodeID = node->getNodeID(); - qDebug("VoxelSystem... voxel server %u added...\n", nodeID); + qDebug("VoxelSystem... voxel server %s added...\n", node->getUUID().toString().toLocal8Bit().constData()); _voxelServerCount++; } } @@ -2322,14 +2321,14 @@ bool VoxelSystem::killSourceVoxelsOperation(VoxelNode* node, void* extraData) { void VoxelSystem::nodeKilled(Node* node) { if (node->getType() == NODE_TYPE_VOXEL_SERVER) { _voxelServerCount--; - uint16_t nodeID = node->getNodeID(); - qDebug("VoxelSystem... voxel server %u removed...\n", nodeID); + qDebug("VoxelSystem... voxel server %s removed...\n", node->getUUID().toString().toLocal8Bit().constData()); if (_voxelServerCount > 0) { // Kill any voxels from the local tree that match this nodeID - pthread_mutex_lock(&_treeLock); - _tree->recurseTreeWithOperation(killSourceVoxelsOperation, &nodeID); - pthread_mutex_unlock(&_treeLock); + // commenting out for removal of 16 bit node IDs +// pthread_mutex_lock(&_treeLock); +// _tree->recurseTreeWithOperation(killSourceVoxelsOperation, 0); +// pthread_mutex_unlock(&_treeLock); _tree->setDirtyBit(); setupNewVoxelsForDrawing(); } else { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9c755a24c1..2e082a7369 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -61,19 +61,13 @@ const float chatMessageScale = 0.0015; const float chatMessageHeight = 0.20; void Avatar::sendAvatarURLsMessage(const QUrl& voxelURL) { - uint16_t ownerID = NodeList::getInstance()->getOwnerID(); - - if (ownerID == UNKNOWN_NODE_ID) { - return; // we don't yet know who we are - } - QByteArray message; char packetHeader[MAX_PACKET_HEADER_BYTES]; int numBytesPacketHeader = populateTypeAndVersion((unsigned char*) packetHeader, PACKET_TYPE_AVATAR_URLS); message.append(packetHeader, numBytesPacketHeader); - message.append((const char*)&ownerID, sizeof(ownerID)); + message.append(NodeList::getInstance()->getOwnerUUID().toRfc4122()); QDataStream out(&message, QIODevice::WriteOnly | QIODevice::Append); out << voxelURL; @@ -283,13 +277,13 @@ void Avatar::follow(Avatar* leadingAvatar) { _leadingAvatar = leadingAvatar; if (_leadingAvatar != NULL) { - _leaderID = leadingAvatar->getOwningNode()->getNodeID(); + _leaderUUID = leadingAvatar->getOwningNode()->getUUID(); _stringLength = glm::length(_position - _leadingAvatar->getPosition()) / _scale; if (_stringLength > MAX_STRING_LENGTH) { _stringLength = MAX_STRING_LENGTH; } } else { - _leaderID = UNKNOWN_NODE_ID; + _leaderUUID = QUuid(); } } diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 452037f436..b6be6cf1d3 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -329,16 +329,7 @@ void Head::setScale (float scale) { void Head::createMohawk() { - uint16_t nodeId = UNKNOWN_NODE_ID; - if (_owningAvatar->getOwningNode()) { - nodeId = _owningAvatar->getOwningNode()->getNodeID(); - } else { - nodeId = NodeList::getInstance()->getOwnerID(); - if (nodeId == UNKNOWN_NODE_ID) { - return; - } - } - srand(nodeId); + srand(time(NULL)); float height = _scale * (0.08f + randFloat() * 0.05f); float variance = 0.03 + randFloat() * 0.03f; const float RAD_PER_TRIANGLE = (2.3f + randFloat() * 0.2f) / (float)MOHAWK_TRIANGLES; diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index e3b137fe4d..d7fd003515 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -10,8 +10,10 @@ #include #include +#include #include #include +#include #include "AudioInjector.h" @@ -23,8 +25,6 @@ AudioInjector::AudioInjector(const char* filename) : _indexOfNextSlot(0), _isInjectingAudio(false) { - loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES); - std::fstream sourceFile; sourceFile.open(filename, std::ios::in | std::ios::binary); @@ -53,8 +53,6 @@ AudioInjector::AudioInjector(int maxNumSamples) : _indexOfNextSlot(0), _isInjectingAudio(false) { - loadRandomIdentifier(_streamIdentifier, STREAM_IDENTIFIER_NUM_BYTES); - _audioSampleArray = new int16_t[maxNumSamples]; memset(_audioSampleArray, 0, _numTotalSamples * sizeof(int16_t)); } @@ -71,7 +69,7 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination // calculate the number of bytes required for additional data int leadingBytes = numBytesForPacketHeader((unsigned char*) &PACKET_TYPE_INJECT_AUDIO) - + sizeof(_streamIdentifier) + + NUM_BYTES_RFC4122_UUID + sizeof(_position) + sizeof(_orientation) + sizeof(_radius) @@ -82,8 +80,9 @@ void AudioInjector::injectAudio(UDPSocket* injectorSocket, sockaddr* destination unsigned char* currentPacketPtr = dataPacket + populateTypeAndVersion(dataPacket, PACKET_TYPE_INJECT_AUDIO); // copy the identifier for this injector - memcpy(currentPacketPtr, &_streamIdentifier, sizeof(_streamIdentifier)); - currentPacketPtr += sizeof(_streamIdentifier); + QByteArray rfcUUID = NodeList::getInstance()->getOwnerUUID().toRfc4122(); + memcpy(currentPacketPtr, rfcUUID.constData(), rfcUUID.size()); + currentPacketPtr += rfcUUID.size(); memcpy(currentPacketPtr, &_position, sizeof(_position)); currentPacketPtr += sizeof(_position); diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index 8847ce14b9..be265fe57f 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -19,8 +19,6 @@ #include "AudioRingBuffer.h" -const int STREAM_IDENTIFIER_NUM_BYTES = 8; - const int MAX_INJECTOR_VOLUME = 0xFF; const int INJECT_INTERVAL_USECS = floorf((BUFFER_LENGTH_SAMPLES_PER_CHANNEL / SAMPLE_RATE) * 1000000); @@ -61,7 +59,6 @@ public slots: int16_t& sampleAt(const int index); void insertSample(const int index, int sample); private: - unsigned char _streamIdentifier[STREAM_IDENTIFIER_NUM_BYTES]; int16_t* _audioSampleArray; int _numTotalSamples; glm::vec3 _position; diff --git a/libraries/audio/src/InjectedAudioRingBuffer.cpp b/libraries/audio/src/InjectedAudioRingBuffer.cpp index 7e93c7716c..3d94d63579 100644 --- a/libraries/audio/src/InjectedAudioRingBuffer.cpp +++ b/libraries/audio/src/InjectedAudioRingBuffer.cpp @@ -14,8 +14,7 @@ InjectedAudioRingBuffer::InjectedAudioRingBuffer() : _radius(0.0f), - _attenuationRatio(0), - _streamIdentifier() + _attenuationRatio(0) { } @@ -23,10 +22,6 @@ InjectedAudioRingBuffer::InjectedAudioRingBuffer() : int InjectedAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer); - // pull stream identifier from the packet - memcpy(&_streamIdentifier, currentBuffer, sizeof(_streamIdentifier)); - currentBuffer += sizeof(_streamIdentifier); - // use parsePositionalData in parent PostionalAudioRingBuffer class to pull common positional data currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); diff --git a/libraries/audio/src/InjectedAudioRingBuffer.h b/libraries/audio/src/InjectedAudioRingBuffer.h index e1df9ac5b9..28284cf404 100644 --- a/libraries/audio/src/InjectedAudioRingBuffer.h +++ b/libraries/audio/src/InjectedAudioRingBuffer.h @@ -21,7 +21,6 @@ public: float getRadius() const { return _radius; } float getAttenuationRatio() const { return _attenuationRatio; } - const unsigned char* getStreamIdentifier() const { return _streamIdentifier; } private: // disallow copying of InjectedAudioRingBuffer objects InjectedAudioRingBuffer(const InjectedAudioRingBuffer&); @@ -29,7 +28,6 @@ private: float _radius; float _attenuationRatio; - unsigned char _streamIdentifier[STREAM_IDENTIFIER_NUM_BYTES]; }; #endif /* defined(__hifi__InjectedAudioRingBuffer__) */ diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 9980b48a3e..21f6ac2dc5 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -17,9 +17,7 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer() : AudioRingBuffer(false), _position(0.0f, 0.0f, 0.0f), _orientation(0.0f, 0.0f, 0.0f, 0.0f), - _willBeAddedToMix(false), - _listenMode(AudioRingBuffer::NORMAL), - _listenRadius(0.0f) + _willBeAddedToMix(false) { } @@ -27,65 +25,15 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer() : PositionalAudioRingBuffer::~PositionalAudioRingBuffer() { } -bool PositionalAudioRingBuffer::isListeningToNode(Node& other) const { - switch (_listenMode) { - default: - case AudioRingBuffer::NORMAL: - return true; - break; - - case AudioRingBuffer::OMNI_DIRECTIONAL_POINT: { - PositionalAudioRingBuffer* otherNodeBuffer = (PositionalAudioRingBuffer*) other.getLinkedData(); - float distance = glm::distance(_position, otherNodeBuffer->_position); - return distance <= _listenRadius; - break; - } - case AudioRingBuffer::SELECTED_SOURCES: - for (int i = 0; i < _listenSources.size(); i++) { - if (other.getNodeID() == _listenSources[i]) { - return true; - } - } - return false; - break; - } -} - - int PositionalAudioRingBuffer::parseData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer + numBytesForPacketHeader(sourceBuffer); currentBuffer += sizeof(uint16_t); // the source ID - currentBuffer += parseListenModeData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parsePositionalData(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); currentBuffer += parseAudioSamples(currentBuffer, numBytes - (currentBuffer - sourceBuffer)); return currentBuffer - sourceBuffer; } -int PositionalAudioRingBuffer::parseListenModeData(unsigned char* sourceBuffer, int numBytes) { - unsigned char* currentBuffer = sourceBuffer; - - memcpy(&_listenMode, currentBuffer, sizeof(_listenMode)); - currentBuffer += sizeof(_listenMode); - - if (_listenMode == AudioRingBuffer::OMNI_DIRECTIONAL_POINT) { - memcpy(&_listenRadius, currentBuffer, sizeof(_listenRadius)); - currentBuffer += sizeof(_listenRadius); - } else if (_listenMode == AudioRingBuffer::SELECTED_SOURCES) { - int listenSourcesCount; - memcpy(&listenSourcesCount, currentBuffer, sizeof(listenSourcesCount)); - currentBuffer += sizeof(listenSourcesCount); - for (int i = 0; i < listenSourcesCount; i++) { - int sourceID; - memcpy(&sourceID, currentBuffer, sizeof(sourceID)); - currentBuffer += sizeof(sourceID); - _listenSources.push_back(sourceID); - } - } - - return currentBuffer - sourceBuffer; -} - int PositionalAudioRingBuffer::parsePositionalData(unsigned char* sourceBuffer, int numBytes) { unsigned char* currentBuffer = sourceBuffer; diff --git a/libraries/audio/src/PositionalAudioRingBuffer.h b/libraries/audio/src/PositionalAudioRingBuffer.h index b43cd60660..1cd0751e9b 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.h +++ b/libraries/audio/src/PositionalAudioRingBuffer.h @@ -30,9 +30,6 @@ public: const glm::vec3& getPosition() const { return _position; } const glm::quat& getOrientation() const { return _orientation; } - - bool isListeningToNode(Node& other) const; - ListenMode getListeningMode() const { return _listenMode; } protected: // disallow copying of PositionalAudioRingBuffer objects @@ -42,10 +39,6 @@ protected: glm::vec3 _position; glm::quat _orientation; bool _willBeAddedToMix; - - ListenMode _listenMode; - float _listenRadius; - std::vector _listenSources; }; #endif /* defined(__hifi__PositionalAudioRingBuffer__) */ diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 46aad2d86f..e3872ae2b3 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -13,9 +13,10 @@ #include #include #include +#include +#include #include "AvatarData.h" -#include using namespace std; @@ -29,7 +30,7 @@ AvatarData::AvatarData(Node* owningNode) : _bodyPitch(0.0), _bodyRoll(0.0), _newScale(1.0f), - _leaderID(UNKNOWN_NODE_ID), + _leaderUUID(), _handState(0), _cameraPosition(0,0,0), _cameraOrientation(), @@ -61,7 +62,10 @@ void AvatarData::sendData() { unsigned char* endOfPacket = packet; endOfPacket += populateTypeAndVersion(endOfPacket, PACKET_TYPE_HEAD_DATA); - endOfPacket += packNodeId(endOfPacket, NodeList::getInstance()->getOwnerID()); + + QByteArray rfcUUID = NodeList::getInstance()->getOwnerUUID().toRfc4122(); + memcpy(endOfPacket, rfcUUID.constData(), rfcUUID.size()); + endOfPacket += rfcUUID.size(); int numPacketBytes = (endOfPacket - packet) + getBroadcastData(endOfPacket); @@ -103,8 +107,8 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _newScale); // Follow mode info - memcpy(destinationBuffer, &_leaderID, sizeof(uint16_t)); - destinationBuffer += sizeof(uint16_t); + memcpy(destinationBuffer, _leaderUUID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID); + destinationBuffer += sizeof(NUM_BYTES_RFC4122_UUID); // Head rotation (NOTE: This needs to become a quaternion to save two bytes) destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->_yaw); @@ -224,7 +228,6 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += sizeof(uint16_t); // UUID - const int NUM_BYTES_RFC4122_UUID = 16; _uuid = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID)); sourceBuffer += NUM_BYTES_RFC4122_UUID; @@ -241,8 +244,8 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _newScale); // Follow mode info - memcpy(&_leaderID, sourceBuffer, sizeof(uint16_t)); - sourceBuffer += sizeof(uint16_t); + _leaderUUID = QUuid::fromRfc4122(QByteArray((char*) sourceBuffer, NUM_BYTES_RFC4122_UUID)); + sourceBuffer += NUM_BYTES_RFC4122_UUID; // Head rotation (NOTE: This needs to become a quaternion to save two bytes) float headYaw, headPitch, headRoll; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index f3ccab1504..1914ae0d61 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -120,7 +120,7 @@ public: bool getWantDelta() const { return _wantDelta; } bool getWantLowResMoving() const { return _wantLowResMoving; } bool getWantOcclusionCulling() const { return _wantOcclusionCulling; } - uint16_t getLeaderID() const { return _leaderID; } + const QUuid& getLeaderUUID() const { return _leaderUUID; } void setHeadData(HeadData* headData) { _headData = headData; } void setHandData(HandData* handData) { _handData = handData; } @@ -147,7 +147,7 @@ protected: float _newScale; // Following mode infos - uint16_t _leaderID; + QUuid _leaderUUID; // Hand state (are we grabbing something or not) char _handState; diff --git a/libraries/shared/NodeList.cpp b/libraries/shared/NodeList.cpp new file mode 100644 index 0000000000..39e3cf9578 --- /dev/null +++ b/libraries/shared/NodeList.cpp @@ -0,0 +1,873 @@ +// +// NodeList.cpp +// hifi +// +// Created by Stephen Birarda on 2/15/13. +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include + +#include +#include + +#include "Assignment.h" +#include "Logging.h" +#include "NodeList.h" +#include "NodeTypes.h" +#include "PacketHeaders.h" +#include "SharedUtil.h" + +#ifdef _WIN32 +#include "Syssocket.h" +#else +#include +#endif + +const char SOLO_NODE_TYPES[2] = { + NODE_TYPE_AVATAR_MIXER, + NODE_TYPE_AUDIO_MIXER +}; + +const QString DEFAULT_DOMAIN_HOSTNAME = "root.highfidelity.io"; +const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102; + +bool silentNodeThreadStopFlag = false; +bool pingUnknownNodeThreadStopFlag = false; + +NodeList* NodeList::_sharedInstance = NULL; + +NodeList* NodeList::createInstance(char ownerType, unsigned short int socketListenPort) { + if (!_sharedInstance) { + _sharedInstance = new NodeList(ownerType, socketListenPort); + } else { + qDebug("NodeList createInstance called with existing instance."); + } + + return _sharedInstance; +} + +NodeList* NodeList::getInstance() { + if (!_sharedInstance) { + qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer."); + } + + return _sharedInstance; +} + +NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : + _domainHostname(DEFAULT_DOMAIN_HOSTNAME), + _domainIP(), + _domainPort(DEFAULT_DOMAIN_SERVER_PORT), + _nodeBuckets(), + _numNodes(0), + _nodeSocket(newSocketListenPort), + _ownerType(newOwnerType), + _nodeTypesOfInterest(NULL), + _ownerID(UNKNOWN_NODE_ID), + _lastNodeID(UNKNOWN_NODE_ID + 1), + _numNoReplyDomainCheckIns(0), + _assignmentServerSocket(NULL), + _checkInPacket(NULL), + _numBytesCheckInPacket(0), + _publicAddress(), + _publicPort(0) +{ + +} + +NodeList::~NodeList() { + delete _nodeTypesOfInterest; + + clear(); + + // stop the spawned threads, if they were started + stopSilentNodeRemovalThread(); +} + +void NodeList::setDomainHostname(const QString& domainHostname) { + + if (domainHostname != _domainHostname) { + int colonIndex = domainHostname.indexOf(':'); + + if (colonIndex > 0) { + // the user has included a custom DS port with the hostname + + // the new hostname is everything up to the colon + _domainHostname = domainHostname.left(colonIndex); + + // grab the port by reading the string after the colon + _domainPort = atoi(domainHostname.mid(colonIndex + 1, domainHostname.size()).toLocal8Bit().constData()); + + qDebug() << "Updated hostname to" << _domainHostname << "and port to" << _domainPort << "\n"; + + } else { + // no port included with the hostname, simply set the member variable and reset the domain server port to default + _domainHostname = domainHostname; + _domainPort = DEFAULT_DOMAIN_SERVER_PORT; + } + + // clear the NodeList so nodes from this domain are killed + clear(); + + // reset our _domainIP to the null address so that a lookup happens on next check in + _domainIP.clear(); + notifyDomainChanged(); + } +} + +void NodeList::timePingReply(sockaddr *nodeAddress, unsigned char *packetData) { + for(NodeList::iterator node = begin(); node != end(); node++) { + if (socketMatch(node->getPublicSocket(), nodeAddress) || + socketMatch(node->getLocalSocket(), nodeAddress)) { + + int pingTime = usecTimestampNow() - *(uint64_t*)(packetData + numBytesForPacketHeader(packetData)); + + node->setPingMs(pingTime / 1000); + break; + } + } +} + +void NodeList::processNodeData(sockaddr* senderAddress, unsigned char* packetData, size_t dataBytes) { + switch (packetData[0]) { + case PACKET_TYPE_DOMAIN: { + // only process the DS if this is our current domain server + if (_domainIP == QHostAddress(senderAddress)) { + processDomainServerList(packetData, dataBytes); + } + + break; + } + case PACKET_TYPE_PING: { + // send it right back + populateTypeAndVersion(packetData, PACKET_TYPE_PING_REPLY); + _nodeSocket.send(senderAddress, packetData, dataBytes); + break; + } + case PACKET_TYPE_PING_REPLY: { + // activate the appropriate socket for this node, if not yet updated + activateSocketFromPingReply(senderAddress); + + // set the ping time for this node for stat collection + timePingReply(senderAddress, packetData); + break; + } + case PACKET_TYPE_STUN_RESPONSE: { + // a STUN packet begins with 00, we've checked the second zero with packetVersionMatch + // pass it along so it can be processed into our public address and port + processSTUNResponse(packetData, dataBytes); + break; + } + } +} + +void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes) { + + // find the avatar mixer in our node list and update the lastRecvTime from it + Node* bulkSendNode = nodeWithAddress(senderAddress); + + if (bulkSendNode) { + bulkSendNode->setLastHeardMicrostamp(usecTimestampNow()); + bulkSendNode->recordBytesReceived(numTotalBytes); + + int numBytesPacketHeader = numBytesForPacketHeader(packetData); + + unsigned char* startPosition = packetData; + unsigned char* currentPosition = startPosition + numBytesPacketHeader; + unsigned char packetHolder[numTotalBytes]; + + // we've already verified packet version for the bulk packet, so all head data in the packet is also up to date + populateTypeAndVersion(packetHolder, PACKET_TYPE_HEAD_DATA); + + uint16_t nodeID = -1; + + while ((currentPosition - startPosition) < numTotalBytes) { + unpackNodeId(currentPosition, &nodeID); + memcpy(packetHolder + numBytesPacketHeader, + currentPosition, + numTotalBytes - (currentPosition - startPosition)); + + Node* matchingNode = nodeWithID(nodeID); + + if (!matchingNode) { + // we're missing this node, we need to add it to the list + matchingNode = addOrUpdateNode(NULL, NULL, NODE_TYPE_AGENT, nodeID); + } + + currentPosition += updateNodeWithData(matchingNode, + packetHolder, + numTotalBytes - (currentPosition - startPosition)); + + } + } +} + +int NodeList::updateNodeWithData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes) { + // find the node by the sockaddr + Node* matchingNode = nodeWithAddress(senderAddress); + + if (matchingNode) { + return updateNodeWithData(matchingNode, packetData, dataBytes); + } else { + return 0; + } +} + +int NodeList::updateNodeWithData(Node *node, unsigned char *packetData, int dataBytes) { + node->lock(); + + node->setLastHeardMicrostamp(usecTimestampNow()); + + if (node->getActiveSocket()) { + node->recordBytesReceived(dataBytes); + } + + if (!node->getLinkedData() && linkedDataCreateCallback) { + linkedDataCreateCallback(node); + } + + int numParsedBytes = node->getLinkedData()->parseData(packetData, dataBytes); + + node->unlock(); + + return numParsedBytes; +} + +Node* NodeList::nodeWithAddress(sockaddr *senderAddress) { + for(NodeList::iterator node = begin(); node != end(); node++) { + if (node->getActiveSocket() && socketMatch(node->getActiveSocket(), senderAddress)) { + return &(*node); + } + } + + return NULL; +} + +Node* NodeList::nodeWithUUID(uint16_t nodeID) { + for(NodeList::iterator node = begin(); node != end(); node++) { + if (node->getNodeID() == nodeID) { + return &(*node); + } + } + + return NULL; +} + +int NodeList::getNumAliveNodes() const { + int numAliveNodes = 0; + + for (NodeList::iterator node = begin(); node != end(); node++) { + if (node->isAlive()) { + ++numAliveNodes; + } + } + + return numAliveNodes; +} + +void NodeList::clear() { + qDebug() << "Clearing the NodeList. Deleting all nodes in list.\n"; + + // delete all of the nodes in the list, set the pointers back to NULL and the number of nodes to 0 + for (int i = 0; i < _numNodes; i++) { + Node** nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET]; + Node* node = nodeBucket[i % NODES_PER_BUCKET]; + + node->lock(); + delete node; + + node = NULL; + } + + _numNodes = 0; +} + +void NodeList::reset() { + clear(); + _numNoReplyDomainCheckIns = 0; + + delete[] _checkInPacket; + _checkInPacket = NULL; + + _numBytesCheckInPacket = 0; + + delete _nodeTypesOfInterest; + _nodeTypesOfInterest = NULL; +} + +void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest) { + delete _nodeTypesOfInterest; + + _nodeTypesOfInterest = new char[numNodeTypesOfInterest + sizeof(char)]; + memcpy(_nodeTypesOfInterest, nodeTypesOfInterest, numNodeTypesOfInterest); + _nodeTypesOfInterest[numNodeTypesOfInterest] = '\0'; +} + +const uint32_t RFC_5389_MAGIC_COOKIE_NETWORK_ORDER = htonl(0x2112A442); +const int NUM_BYTES_STUN_HEADER = 20; + +void NodeList::sendSTUNRequest() { + const char STUN_SERVER_HOSTNAME[] = "root.highfidelity.io"; + const unsigned short STUN_SERVER_PORT = 3478; + + unsigned char stunRequestPacket[NUM_BYTES_STUN_HEADER]; + + int packetIndex = 0; + + // leading zeros + message type + const uint16_t REQUEST_MESSAGE_TYPE = htons(0x0001); + memcpy(stunRequestPacket + packetIndex, &REQUEST_MESSAGE_TYPE, sizeof(REQUEST_MESSAGE_TYPE)); + packetIndex += sizeof(REQUEST_MESSAGE_TYPE); + + // message length (no additional attributes are included) + uint16_t messageLength = 0; + memcpy(stunRequestPacket + packetIndex, &messageLength, sizeof(messageLength)); + packetIndex += sizeof(messageLength); + + memcpy(stunRequestPacket + packetIndex, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)); + packetIndex += sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); + + // transaction ID (random 12-byte unsigned integer) + const uint NUM_TRANSACTION_ID_BYTES = 12; + unsigned char transactionID[NUM_TRANSACTION_ID_BYTES]; + loadRandomIdentifier(transactionID, NUM_TRANSACTION_ID_BYTES); + memcpy(stunRequestPacket + packetIndex, &transactionID, sizeof(transactionID)); + + // lookup the IP for the STUN server + static QHostInfo stunInfo = QHostInfo::fromName(STUN_SERVER_HOSTNAME); + + for (int i = 0; i < stunInfo.addresses().size(); i++) { + if (stunInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { + QString stunIPAddress = stunInfo.addresses()[i].toString(); + + qDebug("Sending a stun request to %s\n", stunIPAddress.toLocal8Bit().constData()); + + _nodeSocket.send(stunIPAddress.toLocal8Bit().constData(), + STUN_SERVER_PORT, + stunRequestPacket, + sizeof(stunRequestPacket)); + + break; + } + } +} + +void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) { + // check the cookie to make sure this is actually a STUN response + // and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS + const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4; + const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0020); + + if (memcmp(packetData + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, + &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, + sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0 + && memcmp(packetData + NUM_BYTES_STUN_HEADER, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) { + + const int NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH = 4; + const int NUM_BYTES_FAMILY_ALIGN = 1; + const uint8_t IPV4_FAMILY_NETWORK_ORDER = htons(0x01) >> 8; + + int byteIndex = NUM_BYTES_STUN_HEADER + NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH + NUM_BYTES_FAMILY_ALIGN; + + uint8_t addressFamily = 0; + memcpy(&addressFamily, packetData + byteIndex, sizeof(addressFamily)); + + byteIndex += sizeof(addressFamily); + + if (addressFamily == IPV4_FAMILY_NETWORK_ORDER) { + // grab the X-Port + uint16_t xorMappedPort = 0; + memcpy(&xorMappedPort, packetData + byteIndex, sizeof(xorMappedPort)); + + _publicPort = ntohs(xorMappedPort) ^ (ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER) >> 16); + + byteIndex += sizeof(xorMappedPort); + + // grab the X-Address + uint32_t xorMappedAddress = 0; + memcpy(&xorMappedAddress, packetData + byteIndex, sizeof(xorMappedAddress)); + + uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); + _publicAddress = QHostAddress(stunAddress); + + qDebug("Public socket received from STUN server is %s:%hu\n", + _publicAddress.toString().toLocal8Bit().constData(), + _publicPort); + } + } +} + +void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { + static bool printedDomainServerIP = false; + + // Lookup the IP address of the domain server if we need to + if (_domainIP.isNull()) { + qDebug("Looking up DS hostname %s.\n", _domainHostname.toLocal8Bit().constData()); + + QHostInfo domainServerHostInfo = QHostInfo::fromName(_domainHostname); + + for (int i = 0; i < domainServerHostInfo.addresses().size(); i++) { + if (domainServerHostInfo.addresses()[i].protocol() == QAbstractSocket::IPv4Protocol) { + _domainIP = domainServerHostInfo.addresses()[i]; + + qDebug("DS at %s is at %s\n", _domainHostname.toLocal8Bit().constData(), + _domainIP.toString().toLocal8Bit().constData()); + + printedDomainServerIP = true; + + break; + } + + // if we got here without a break out of the for loop then we failed to lookup the address + if (i == domainServerHostInfo.addresses().size() - 1) { + qDebug("Failed domain server lookup\n"); + } + } + } else if (!printedDomainServerIP) { + qDebug("Domain Server IP: %s\n", _domainIP.toString().toLocal8Bit().constData()); + printedDomainServerIP = true; + } + + if (_publicAddress.isNull()) { + // we don't know our public socket and we need to send it to the domain server + // send a STUN request to figure it out + sendSTUNRequest(); + } else { + // construct the DS check in packet if we need to + if (!_checkInPacket) { + int numBytesNodesOfInterest = _nodeTypesOfInterest ? strlen((char*) _nodeTypesOfInterest) : 0; + + const int IP_ADDRESS_BYTES = 4; + + // 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); + + _checkInPacket = new unsigned char[numPacketBytes]; + unsigned char* packetPosition = _checkInPacket; + + PACKET_TYPE nodePacketType = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES))) + ? PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY + : PACKET_TYPE_DOMAIN_LIST_REQUEST; + + packetPosition += populateTypeAndVersion(packetPosition, nodePacketType); + + *(packetPosition++) = _ownerType; + + if (!assignmentUUID) { + // if we don't have an assignment UUID just send the null one + assignmentUUID = QUuid().toRfc4122().constData(); + } + + // send our assignment UUID or the null one + memcpy(packetPosition, assignmentUUID, NUM_BYTES_RFC4122_UUID); + packetPosition += NUM_BYTES_RFC4122_UUID; + + // pack our public address to send to domain-server + packetPosition += packSocket(_checkInPacket + (packetPosition - _checkInPacket), + htonl(_publicAddress.toIPv4Address()), htons(_publicPort)); + + // pack our local address to send to domain-server + packetPosition += packSocket(_checkInPacket + (packetPosition - _checkInPacket), + getLocalAddress(), + htons(_nodeSocket.getListeningPort())); + + // add the number of bytes for node types of interest + *(packetPosition++) = numBytesNodesOfInterest; + + // copy over the bytes for node types of interest, if required + if (numBytesNodesOfInterest > 0) { + memcpy(packetPosition, + _nodeTypesOfInterest, + numBytesNodesOfInterest); + packetPosition += numBytesNodesOfInterest; + } + + _numBytesCheckInPacket = packetPosition - _checkInPacket; + } + + _nodeSocket.send(_domainIP.toString().toLocal8Bit().constData(), _domainPort, _checkInPacket, _numBytesCheckInPacket); + + // increment the count of un-replied check-ins + _numNoReplyDomainCheckIns++; + } +} + +int NodeList::processDomainServerList(unsigned char* packetData, size_t dataBytes) { + // this is a packet from the domain server, reset the count of un-replied check-ins + _numNoReplyDomainCheckIns = 0; + + int readNodes = 0; + + char nodeType; + uint16_t nodeId; + + // assumes only IPv4 addresses + sockaddr_in nodePublicSocket; + nodePublicSocket.sin_family = AF_INET; + sockaddr_in nodeLocalSocket; + nodeLocalSocket.sin_family = AF_INET; + + unsigned char* readPtr = packetData + numBytesForPacketHeader(packetData); + unsigned char* startPtr = packetData; + + while((readPtr - startPtr) < dataBytes - sizeof(uint16_t)) { + nodeType = *readPtr++; + readPtr += unpackNodeId(readPtr, (uint16_t*) &nodeId); + readPtr += unpackSocket(readPtr, (sockaddr*) &nodePublicSocket); + readPtr += unpackSocket(readPtr, (sockaddr*) &nodeLocalSocket); + + // if the public socket address is 0 then it's reachable at the same IP + // as the domain server + if (nodePublicSocket.sin_addr.s_addr == 0) { + nodePublicSocket.sin_addr.s_addr = htonl(_domainIP.toIPv4Address()); + } + + addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId); + } + + // read out our ID from the packet + unpackNodeId(readPtr, &_ownerID); + + return readNodes; +} + +const sockaddr_in DEFAULT_LOCAL_ASSIGNMENT_SOCKET = socketForHostnameAndHostOrderPort(LOCAL_ASSIGNMENT_SERVER_HOSTNAME, + DEFAULT_DOMAIN_SERVER_PORT); +void NodeList::sendAssignment(Assignment& assignment) { + unsigned char assignmentPacket[MAX_PACKET_SIZE]; + + PACKET_TYPE assignmentPacketType = assignment.getCommand() == Assignment::CreateCommand + ? PACKET_TYPE_CREATE_ASSIGNMENT + : PACKET_TYPE_REQUEST_ASSIGNMENT; + + int numHeaderBytes = populateTypeAndVersion(assignmentPacket, assignmentPacketType); + int numAssignmentBytes = assignment.packToBuffer(assignmentPacket + numHeaderBytes); + + sockaddr* assignmentServerSocket = (_assignmentServerSocket == NULL) + ? (sockaddr*) &DEFAULT_LOCAL_ASSIGNMENT_SOCKET + : _assignmentServerSocket; + + _nodeSocket.send(assignmentServerSocket, assignmentPacket, numHeaderBytes + numAssignmentBytes); +} + +void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) const { + + uint64_t currentTime = 0; + + // setup a ping packet to send to this node + unsigned char pingPacket[numBytesForPacketHeader((uchar*) &PACKET_TYPE_PING) + sizeof(currentTime)]; + int numHeaderBytes = populateTypeAndVersion(pingPacket, PACKET_TYPE_PING); + + currentTime = usecTimestampNow(); + memcpy(pingPacket + numHeaderBytes, ¤tTime, sizeof(currentTime)); + + // send the ping packet to the local and public sockets for this node + _nodeSocket.send(node->getLocalSocket(), pingPacket, sizeof(pingPacket)); + _nodeSocket.send(node->getPublicSocket(), pingPacket, sizeof(pingPacket)); +} + +Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, char nodeType, uint16_t nodeId) { + NodeList::iterator node = end(); + + if (publicSocket) { + for (node = begin(); node != end(); node++) { + if (node->matches(publicSocket, localSocket, nodeType)) { + // we already have this node, stop checking + break; + } + } + } + + if (node == end()) { + // we didn't have this node, so add them + Node* newNode = new Node(publicSocket, localSocket, nodeType, nodeId); + + addNodeToList(newNode); + + return newNode; + } else { + if (node->getType() == NODE_TYPE_AUDIO_MIXER || + node->getType() == NODE_TYPE_VOXEL_SERVER) { + // until the Audio class also uses our nodeList, we need to update + // the lastRecvTimeUsecs for the audio mixer so it doesn't get killed and re-added continously + node->setLastHeardMicrostamp(usecTimestampNow()); + } + + // we had this node already, do nothing for now + return &*node; + } +} + +void NodeList::addNodeToList(Node* newNode) { + // find the correct array to add this node to + int bucketIndex = _numNodes / NODES_PER_BUCKET; + + if (!_nodeBuckets[bucketIndex]) { + _nodeBuckets[bucketIndex] = new Node*[NODES_PER_BUCKET](); + } + + _nodeBuckets[bucketIndex][_numNodes % NODES_PER_BUCKET] = newNode; + + ++_numNodes; + + qDebug() << "Added" << *newNode << "\n"; + + notifyHooksOfAddedNode(newNode); +} + +unsigned NodeList::broadcastToNodes(unsigned char* broadcastData, size_t dataBytes, const char* nodeTypes, int numNodeTypes) { + unsigned n = 0; + for(NodeList::iterator node = begin(); node != end(); node++) { + // only send to the NodeTypes we are asked to send to. + if (node->getActiveSocket() != NULL) { + if (memchr(nodeTypes, node->getType(), numNodeTypes)) { + // we know which socket is good for this node, send there + _nodeSocket.send(node->getActiveSocket(), broadcastData, dataBytes); + ++n; + } + } else { + // we don't have an active link to this node, ping it to set that up + pingPublicAndLocalSocketsForInactiveNode(&(*node)); + } + } + return n; +} + +void NodeList::activateSocketFromPingReply(sockaddr *nodeAddress) { + for(NodeList::iterator node = begin(); node != end(); node++) { + if (!node->getActiveSocket()) { + // check both the public and local addresses for each node to see if we find a match + // prioritize the private address so that we prune erroneous local matches + if (socketMatch(node->getPublicSocket(), nodeAddress)) { + node->activatePublicSocket(); + break; + } else if (socketMatch(node->getLocalSocket(), nodeAddress)) { + node->activateLocalSocket(); + break; + } + } + } +} + +Node* NodeList::soloNodeOfType(char nodeType) { + if (memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES)) != NULL) { + for(NodeList::iterator node = begin(); node != end(); node++) { + if (node->getType() == nodeType) { + return &(*node); + } + } + } + + return NULL; +} + +void* removeSilentNodes(void *args) { + NodeList* nodeList = (NodeList*) args; + uint64_t checkTimeUsecs = 0; + int sleepTime = 0; + + while (!silentNodeThreadStopFlag) { + + checkTimeUsecs = usecTimestampNow(); + + for(NodeList::iterator node = nodeList->begin(); node != nodeList->end(); ++node) { + node->lock(); + + if ((usecTimestampNow() - node->getLastHeardMicrostamp()) > NODE_SILENCE_THRESHOLD_USECS) { + + qDebug() << "Killed " << *node << "\n"; + + nodeList->notifyHooksOfKilledNode(&*node); + + node->setAlive(false); + } + + node->unlock(); + } + + sleepTime = NODE_SILENCE_THRESHOLD_USECS - (usecTimestampNow() - checkTimeUsecs); + + #ifdef _WIN32 + + Sleep( static_cast(1000.0f*sleepTime) ); + + #else + + if (sleepTime > 0) { + usleep(sleepTime); + } + + #endif + } + + pthread_exit(0); + return NULL; +} + +void NodeList::startSilentNodeRemovalThread() { + pthread_create(&removeSilentNodesThread, NULL, removeSilentNodes, (void*) this); +} + +void NodeList::stopSilentNodeRemovalThread() { + silentNodeThreadStopFlag = true; + pthread_join(removeSilentNodesThread, NULL); + +} + +const QString QSETTINGS_GROUP_NAME = "NodeList"; +const QString DOMAIN_SERVER_SETTING_KEY = "domainServerHostname"; + +void NodeList::loadData(QSettings *settings) { + settings->beginGroup(DOMAIN_SERVER_SETTING_KEY); + + QString domainServerHostname = settings->value(DOMAIN_SERVER_SETTING_KEY).toString(); + + if (domainServerHostname.size() > 0) { + _domainHostname = domainServerHostname; + notifyDomainChanged(); + } + + settings->endGroup(); +} + +void NodeList::saveData(QSettings* settings) { + settings->beginGroup(DOMAIN_SERVER_SETTING_KEY); + + if (_domainHostname != DEFAULT_DOMAIN_HOSTNAME) { + // the user is using a different hostname, store it + settings->setValue(DOMAIN_SERVER_SETTING_KEY, QVariant(_domainHostname)); + } else { + // the user has switched back to default, remove the current setting + settings->remove(DOMAIN_SERVER_SETTING_KEY); + } + + settings->endGroup(); +} + +NodeList::iterator NodeList::begin() const { + Node** nodeBucket = NULL; + + for (int i = 0; i < _numNodes; i++) { + if (i % NODES_PER_BUCKET == 0) { + nodeBucket = _nodeBuckets[i / NODES_PER_BUCKET]; + } + + if (nodeBucket[i % NODES_PER_BUCKET]->isAlive()) { + return NodeListIterator(this, i); + } + } + + // there's no alive node to start from - return the end + return end(); +} + +NodeList::iterator NodeList::end() const { + return NodeListIterator(this, _numNodes); +} + +NodeListIterator::NodeListIterator(const NodeList* nodeList, int nodeIndex) : + _nodeIndex(nodeIndex) { + _nodeList = nodeList; +} + +NodeListIterator& NodeListIterator::operator=(const NodeListIterator& otherValue) { + _nodeList = otherValue._nodeList; + _nodeIndex = otherValue._nodeIndex; + return *this; +} + +bool NodeListIterator::operator==(const NodeListIterator &otherValue) { + return _nodeIndex == otherValue._nodeIndex; +} + +bool NodeListIterator::operator!=(const NodeListIterator &otherValue) { + return !(*this == otherValue); +} + +Node& NodeListIterator::operator*() { + Node** nodeBucket = _nodeList->_nodeBuckets[_nodeIndex / NODES_PER_BUCKET]; + return *nodeBucket[_nodeIndex % NODES_PER_BUCKET]; +} + +Node* NodeListIterator::operator->() { + Node** nodeBucket = _nodeList->_nodeBuckets[_nodeIndex / NODES_PER_BUCKET]; + return nodeBucket[_nodeIndex % NODES_PER_BUCKET]; +} + +NodeListIterator& NodeListIterator::operator++() { + skipDeadAndStopIncrement(); + return *this; +} + +NodeList::iterator NodeListIterator::operator++(int) { + NodeListIterator newIterator = NodeListIterator(*this); + skipDeadAndStopIncrement(); + return newIterator; +} + +void NodeListIterator::skipDeadAndStopIncrement() { + while (_nodeIndex != _nodeList->_numNodes) { + ++_nodeIndex; + + if (_nodeIndex == _nodeList->_numNodes) { + break; + } else if ((*(*this)).isAlive()) { + // skip over the dead nodes + break; + } + } +} + +void NodeList::addDomainListener(DomainChangeListener* listener) { + _domainListeners.push_back(listener); + QString domain = _domainHostname.isEmpty() ? _domainIP.toString() : _domainHostname; + listener->domainChanged(domain); +} + +void NodeList::removeDomainListener(DomainChangeListener* listener) { + for (int i = 0; i < _domainListeners.size(); i++) { + if (_domainListeners[i] == listener) { + _domainListeners.erase(_domainListeners.begin() + i); + return; + } + } +} + +void NodeList::addHook(NodeListHook* hook) { + _hooks.push_back(hook); +} + +void NodeList::removeHook(NodeListHook* hook) { + for (int i = 0; i < _hooks.size(); i++) { + if (_hooks[i] == hook) { + _hooks.erase(_hooks.begin() + i); + return; + } + } +} + +void NodeList::notifyHooksOfAddedNode(Node* node) { + for (int i = 0; i < _hooks.size(); i++) { + //printf("NodeList::notifyHooksOfAddedNode() i=%d\n", i); + _hooks[i]->nodeAdded(node); + } +} + +void NodeList::notifyHooksOfKilledNode(Node* node) { + for (int i = 0; i < _hooks.size(); i++) { + //printf("NodeList::notifyHooksOfKilledNode() i=%d\n", i); + _hooks[i]->nodeKilled(node); + } +} + +void NodeList::notifyDomainChanged() { + for (int i = 0; i < _domainListeners.size(); i++) { + _domainListeners[i]->domainChanged(_domainHostname); + } +} diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index 6a7f62c91b..83f1e4087c 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -8,6 +8,7 @@ #include "PacketHeaders.h" #include "SharedUtil.h" +#include "UUID.h" #include diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index cc528e9bd4..749622db46 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -15,7 +15,6 @@ #include "NodeList.h" -const int NUM_BYTES_RFC4122_UUID = 16; const int MAX_PAYLOAD_BYTES = 1024; /// Holds information used for request, creation, and deployment of assignments diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index 0cef53182d..9d9c9e9ae4 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -23,19 +23,9 @@ #include -int unpackNodeId(unsigned char* packedData, uint16_t* nodeId) { - memcpy(nodeId, packedData, sizeof(uint16_t)); - return sizeof(uint16_t); -} - -int packNodeId(unsigned char* packStore, uint16_t nodeId) { - memcpy(packStore, &nodeId, sizeof(uint16_t)); - return sizeof(uint16_t); -} - -Node::Node(sockaddr* publicSocket, sockaddr* localSocket, char type, uint16_t nodeID) : +Node::Node(const QUuid& uuid, char type, sockaddr* publicSocket, sockaddr* localSocket) : _type(type), - _nodeID(nodeID), + _uuid(uuid), _wakeMicrostamp(usecTimestampNow()), _lastHeardMicrostamp(usecTimestampNow()), _activeSocket(NULL), @@ -157,7 +147,8 @@ QDebug operator<<(QDebug debug, const Node &node) { char localAddressBuffer[16] = {'\0'}; unsigned short localAddressPort = loadBufferWithSocketInfo(localAddressBuffer, node.getLocalSocket()); - debug << "#" << node.getNodeID() << node.getTypeName() << node.getType(); + debug.nospace() << node.getTypeName() << " (" << node.getType() << ")"; + debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug.nospace() << publicAddressBuffer << ":" << publicAddressPort; debug.nospace() << " / " << localAddressBuffer << ":" << localAddressPort; return debug.nospace(); diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index 2de75bcec1..1a204f569b 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -19,13 +19,14 @@ #endif #include +#include #include "NodeData.h" #include "SimpleMovingAverage.h" class Node { public: - Node(sockaddr* publicSocket, sockaddr* localSocket, char type, uint16_t nodeID); + Node(const QUuid& uuid, char type, sockaddr* publicSocket, sockaddr* localSocket); ~Node(); bool operator==(const Node& otherNode); @@ -36,8 +37,8 @@ public: void setType(char type) { _type = type; } const char* getTypeName() const; - uint16_t getNodeID() const { return _nodeID; } - void setNodeID(uint16_t nodeID) { _nodeID = nodeID;} + const QUuid& getUUID() const { return _uuid; } + void setUUID(const QUuid& uuid) { _uuid = uuid; } uint64_t getWakeMicrostamp() const { return _wakeMicrostamp; } void setWakeMicrostamp(uint64_t wakeMicrostamp) { _wakeMicrostamp = wakeMicrostamp; } @@ -78,7 +79,7 @@ private: Node& operator=(Node otherNode); char _type; - uint16_t _nodeID; + QUuid _uuid; uint64_t _wakeMicrostamp; uint64_t _lastHeardMicrostamp; sockaddr* _publicSocket; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 7de25d2af1..a448d83b3d 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -20,6 +20,7 @@ #include "NodeTypes.h" #include "PacketHeaders.h" #include "SharedUtil.h" +#include "UUID.h" #ifdef _WIN32 #include "Syssocket.h" @@ -67,8 +68,7 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) : _nodeSocket(newSocketListenPort), _ownerType(newOwnerType), _nodeTypesOfInterest(NULL), - _ownerID(UNKNOWN_NODE_ID), - _lastNodeID(UNKNOWN_NODE_ID + 1), + _ownerUUID(QUuid::createUuid()), _numNoReplyDomainCheckIns(0), _assignmentServerSocket(NULL), _checkInPacket(NULL), @@ -183,19 +183,18 @@ void NodeList::processBulkNodeData(sockaddr *senderAddress, unsigned char *packe // we've already verified packet version for the bulk packet, so all head data in the packet is also up to date populateTypeAndVersion(packetHolder, PACKET_TYPE_HEAD_DATA); - uint16_t nodeID = -1; - while ((currentPosition - startPosition) < numTotalBytes) { - unpackNodeId(currentPosition, &nodeID); + memcpy(packetHolder + numBytesPacketHeader, currentPosition, numTotalBytes - (currentPosition - startPosition)); - Node* matchingNode = nodeWithID(nodeID); + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)currentPosition, NUM_BYTES_RFC4122_UUID)); + Node* matchingNode = nodeWithUUID(nodeUUID); if (!matchingNode) { // we're missing this node, we need to add it to the list - matchingNode = addOrUpdateNode(NULL, NULL, NODE_TYPE_AGENT, nodeID); + matchingNode = addOrUpdateNode(nodeUUID, NODE_TYPE_AGENT, NULL, NULL); } currentPosition += updateNodeWithData(matchingNode, @@ -247,9 +246,9 @@ Node* NodeList::nodeWithAddress(sockaddr *senderAddress) { return NULL; } -Node* NodeList::nodeWithID(uint16_t nodeID) { +Node* NodeList::nodeWithUUID(const QUuid& nodeUUID) { for(NodeList::iterator node = begin(); node != end(); node++) { - if (node->getNodeID() == nodeID) { + if (node->getUUID() == nodeUUID) { return &(*node); } } @@ -297,6 +296,9 @@ void NodeList::reset() { delete _nodeTypesOfInterest; _nodeTypesOfInterest = NULL; + + // refresh the owner UUID + _ownerUUID = QUuid::createUuid(); } void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest) { @@ -362,46 +364,63 @@ void NodeList::processSTUNResponse(unsigned char* packetData, size_t dataBytes) const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4; const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0020); + int attributeStartIndex = NUM_BYTES_STUN_HEADER; + if (memcmp(packetData + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, - sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0 - && memcmp(packetData + NUM_BYTES_STUN_HEADER, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) { + sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0) { - const int NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH = 4; - const int NUM_BYTES_FAMILY_ALIGN = 1; - const uint8_t IPV4_FAMILY_NETWORK_ORDER = htons(0x01) >> 8; - - int byteIndex = NUM_BYTES_STUN_HEADER + NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH + NUM_BYTES_FAMILY_ALIGN; - - uint8_t addressFamily = 0; - memcpy(&addressFamily, packetData + byteIndex, sizeof(addressFamily)); - - byteIndex += sizeof(addressFamily); - - if (addressFamily == IPV4_FAMILY_NETWORK_ORDER) { - // grab the X-Port - uint16_t xorMappedPort = 0; - memcpy(&xorMappedPort, packetData + byteIndex, sizeof(xorMappedPort)); - - _publicPort = ntohs(xorMappedPort) ^ (ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER) >> 16); - - byteIndex += sizeof(xorMappedPort); - - // grab the X-Address - uint32_t xorMappedAddress = 0; - memcpy(&xorMappedAddress, packetData + byteIndex, sizeof(xorMappedAddress)); - - uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); - _publicAddress = QHostAddress(stunAddress); - - qDebug("Public socket received from STUN server is %s:%hu\n", - _publicAddress.toString().toLocal8Bit().constData(), - _publicPort); + // enumerate the attributes to find XOR_MAPPED_ADDRESS_TYPE + while (attributeStartIndex < dataBytes) { + if (memcmp(packetData + attributeStartIndex, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) { + const int NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH = 4; + const int NUM_BYTES_FAMILY_ALIGN = 1; + const uint8_t IPV4_FAMILY_NETWORK_ORDER = htons(0x01) >> 8; + + int byteIndex = attributeStartIndex + NUM_BYTES_STUN_ATTR_TYPE_AND_LENGTH + NUM_BYTES_FAMILY_ALIGN; + + uint8_t addressFamily = 0; + memcpy(&addressFamily, packetData + byteIndex, sizeof(addressFamily)); + + byteIndex += sizeof(addressFamily); + + if (addressFamily == IPV4_FAMILY_NETWORK_ORDER) { + // grab the X-Port + uint16_t xorMappedPort = 0; + memcpy(&xorMappedPort, packetData + byteIndex, sizeof(xorMappedPort)); + + _publicPort = ntohs(xorMappedPort) ^ (ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER) >> 16); + + byteIndex += sizeof(xorMappedPort); + + // grab the X-Address + uint32_t xorMappedAddress = 0; + memcpy(&xorMappedAddress, packetData + byteIndex, sizeof(xorMappedAddress)); + + uint32_t stunAddress = ntohl(xorMappedAddress) ^ ntohl(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER); + _publicAddress = QHostAddress(stunAddress); + + qDebug("Public socket received from STUN server is %s:%hu\n", + _publicAddress.toString().toLocal8Bit().constData(), + _publicPort); + + break; + } + } else { + // push forward attributeStartIndex by the length of this attribute + const int NUM_BYTES_ATTRIBUTE_TYPE = 2; + + uint16_t attributeLength = 0; + memcpy(&attributeLength, packetData + attributeStartIndex + NUM_BYTES_ATTRIBUTE_TYPE, sizeof(attributeLength)); + attributeLength = ntohs(attributeLength); + + attributeStartIndex += NUM_BYTES_MESSAGE_TYPE_AND_LENGTH + attributeLength; + } } } } -void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { +void NodeList::sendDomainServerCheckIn() { static bool printedDomainServerIP = false; // Lookup the IP address of the domain server if we need to @@ -459,14 +478,10 @@ void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { *(packetPosition++) = _ownerType; - if (!assignmentUUID) { - // if we don't have an assignment UUID just send the null one - assignmentUUID = QUuid().toRfc4122().constData(); - } - - // send our assignment UUID or the null one - memcpy(packetPosition, assignmentUUID, NUM_BYTES_RFC4122_UUID); - packetPosition += NUM_BYTES_RFC4122_UUID; + // send our owner UUID or the null one + QByteArray rfcOwnerUUID = _ownerUUID.toRfc4122(); + memcpy(packetPosition, rfcOwnerUUID.constData(), rfcOwnerUUID.size()); + packetPosition += rfcOwnerUUID.size(); // pack our public address to send to domain-server packetPosition += packSocket(_checkInPacket + (packetPosition - _checkInPacket), @@ -505,7 +520,6 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte int readNodes = 0; char nodeType; - uint16_t nodeId; // assumes only IPv4 addresses sockaddr_in nodePublicSocket; @@ -518,7 +532,9 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte while((readPtr - startPtr) < dataBytes - sizeof(uint16_t)) { nodeType = *readPtr++; - readPtr += unpackNodeId(readPtr, (uint16_t*) &nodeId); + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*) readPtr, NUM_BYTES_RFC4122_UUID)); + readPtr += NUM_BYTES_RFC4122_UUID; + readPtr += unpackSocket(readPtr, (sockaddr*) &nodePublicSocket); readPtr += unpackSocket(readPtr, (sockaddr*) &nodeLocalSocket); @@ -528,11 +544,9 @@ int NodeList::processDomainServerList(unsigned char* packetData, size_t dataByte nodePublicSocket.sin_addr.s_addr = htonl(_domainIP.toIPv4Address()); } - addOrUpdateNode((sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket, nodeType, nodeId); + addOrUpdateNode(nodeUUID, nodeType, (sockaddr*) &nodePublicSocket, (sockaddr*) &nodeLocalSocket); } - // read out our ID from the packet - unpackNodeId(readPtr, &_ownerID); return readNodes; } @@ -572,7 +586,7 @@ void NodeList::pingPublicAndLocalSocketsForInactiveNode(Node* node) const { _nodeSocket.send(node->getPublicSocket(), pingPacket, sizeof(pingPacket)); } -Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, char nodeType, uint16_t nodeId) { +Node* NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, sockaddr* publicSocket, sockaddr* localSocket) { NodeList::iterator node = end(); if (publicSocket) { @@ -586,7 +600,7 @@ Node* NodeList::addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, c if (node == end()) { // we didn't have this node, so add them - Node* newNode = new Node(publicSocket, localSocket, nodeType, nodeId); + Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); addNodeToList(newNode); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 7a2e8a16c6..ff931dfe8e 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -42,8 +42,6 @@ extern const unsigned short DEFAULT_DOMAIN_SERVER_PORT; const char LOCAL_ASSIGNMENT_SERVER_HOSTNAME[] = "localhost"; -const int UNKNOWN_NODE_ID = 0; - const int MAX_SILENT_DOMAIN_SERVER_CHECK_INS = 5; class Assignment; @@ -83,12 +81,9 @@ public: unsigned short getDomainPort() const { return _domainPort; } void setDomainPort(unsigned short domainPort) { _domainPort = domainPort; } - - uint16_t getLastNodeID() const { return _lastNodeID; } - void increaseNodeID() { (++_lastNodeID == UNKNOWN_NODE_ID) ? ++_lastNodeID : _lastNodeID; } - uint16_t getOwnerID() const { return _ownerID; } - void setOwnerID(uint16_t ownerID) { _ownerID = ownerID; } + const QUuid& getOwnerUUID() const { return _ownerUUID; } + void setOwnerUUID(const QUuid& ownerUUID) { _ownerUUID = ownerUUID; } UDPSocket* getNodeSocket() { return &_nodeSocket; } @@ -106,7 +101,7 @@ public: void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest); - void sendDomainServerCheckIn(const char* assignmentUUID = NULL); + void sendDomainServerCheckIn(); int processDomainServerList(unsigned char *packetData, size_t dataBytes); void setAssignmentServerSocket(sockaddr* serverSocket) { _assignmentServerSocket = serverSocket; } @@ -115,9 +110,9 @@ public: void pingPublicAndLocalSocketsForInactiveNode(Node* node) const; Node* nodeWithAddress(sockaddr *senderAddress); - Node* nodeWithID(uint16_t nodeID); + Node* nodeWithUUID(const QUuid& nodeUUID); - Node* addOrUpdateNode(sockaddr* publicSocket, sockaddr* localSocket, char nodeType, uint16_t nodeId); + Node* addOrUpdateNode(const QUuid& uuid, char nodeType, sockaddr* publicSocket, sockaddr* localSocket); void processNodeData(sockaddr *senderAddress, unsigned char *packetData, size_t dataBytes); void processBulkNodeData(sockaddr *senderAddress, unsigned char *packetData, int numTotalBytes); @@ -166,8 +161,7 @@ private: UDPSocket _nodeSocket; char _ownerType; char* _nodeTypesOfInterest; - uint16_t _ownerID; - uint16_t _lastNodeID; + QUuid _ownerUUID; pthread_t removeSilentNodesThread; pthread_t checkInWithDomainServerThread; int _numNoReplyDomainCheckIns; diff --git a/libraries/shared/src/UUID.h b/libraries/shared/src/UUID.h index 985f44ae7b..cacadf5a04 100644 --- a/libraries/shared/src/UUID.h +++ b/libraries/shared/src/UUID.h @@ -11,6 +11,8 @@ #include +const int NUM_BYTES_RFC4122_UUID = 16; + QString uuidStringWithoutCurlyBraces(const QUuid& uuid); #endif /* defined(__hifi__UUID__) */ diff --git a/libraries/voxel-server-library/src/VoxelNodeData.cpp b/libraries/voxel-server-library/src/VoxelNodeData.cpp index 811e3bc63a..1995dcc867 100644 --- a/libraries/voxel-server-library/src/VoxelNodeData.cpp +++ b/libraries/voxel-server-library/src/VoxelNodeData.cpp @@ -32,8 +32,8 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : void VoxelNodeData::initializeVoxelSendThread(VoxelServer* voxelServer) { // Create voxel sending thread... - uint16_t nodeID = getOwningNode()->getNodeID(); - _voxelSendThread = new VoxelSendThread(nodeID, voxelServer); + QUuid nodeUUID = getOwningNode()->getUUID(); + _voxelSendThread = new VoxelSendThread(nodeUUID, voxelServer); _voxelSendThread->initialize(true); } diff --git a/libraries/voxel-server-library/src/VoxelSendThread.cpp b/libraries/voxel-server-library/src/VoxelSendThread.cpp index ac2c56d2d3..d4cf3b491d 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.cpp +++ b/libraries/voxel-server-library/src/VoxelSendThread.cpp @@ -18,15 +18,15 @@ extern EnvironmentData environmentData[3]; #include "VoxelServer.h" #include "VoxelServerConsts.h" -VoxelSendThread::VoxelSendThread(uint16_t nodeID, VoxelServer* myServer) : - _nodeID(nodeID), +VoxelSendThread::VoxelSendThread(const QUuid& nodeUUID, VoxelServer* myServer) : + _nodeUUID(nodeUUID), _myServer(myServer) { } bool VoxelSendThread::process() { uint64_t lastSendTime = usecTimestampNow(); - Node* node = NodeList::getInstance()->nodeWithID(_nodeID); + Node* node = NodeList::getInstance()->nodeWithUUID(_nodeUUID); VoxelNodeData* nodeData = NULL; if (node) { diff --git a/libraries/voxel-server-library/src/VoxelSendThread.h b/libraries/voxel-server-library/src/VoxelSendThread.h index 37824abedb..8de3968dcb 100644 --- a/libraries/voxel-server-library/src/VoxelSendThread.h +++ b/libraries/voxel-server-library/src/VoxelSendThread.h @@ -21,13 +21,13 @@ /// Threaded processor for sending voxel packets to a single client class VoxelSendThread : public virtual GenericThread { public: - VoxelSendThread(uint16_t nodeID, VoxelServer* myServer); + VoxelSendThread(const QUuid& nodeUUID, VoxelServer* myServer); protected: /// Implements generic processing behavior for this thread. virtual bool process(); private: - uint16_t _nodeID; + QUuid _nodeUUID; VoxelServer* _myServer; void handlePacketSend(Node* node, VoxelNodeData* nodeData, int& trueBytesSent, int& truePacketsSent); diff --git a/libraries/voxel-server-library/src/VoxelServer.cpp b/libraries/voxel-server-library/src/VoxelServer.cpp index 91c8f5b71a..12a25f035c 100644 --- a/libraries/voxel-server-library/src/VoxelServer.cpp +++ b/libraries/voxel-server-library/src/VoxelServer.cpp @@ -11,8 +11,9 @@ #include #include -#include -#include +#include +#include +#include #include #include @@ -25,6 +26,7 @@ #include #include #include +#include #ifdef _WIN32 #include "Syssocket.h" @@ -384,12 +386,13 @@ void VoxelServer::run() { if (packetData[0] == PACKET_TYPE_HEAD_DATA) { // If we got a PACKET_TYPE_HEAD_DATA, then we're talking to an NODE_TYPE_AVATAR, and we // need to make sure we have it in our nodeList. - uint16_t nodeID = 0; - unpackNodeId(packetData + numBytesPacketHeader, &nodeID); - Node* node = NodeList::getInstance()->addOrUpdateNode(&senderAddress, - &senderAddress, - NODE_TYPE_AGENT, - nodeID); + QUuid nodeUUID = QUuid::fromRfc4122(QByteArray((char*)packetData + numBytesPacketHeader, + NUM_BYTES_RFC4122_UUID)); + + Node* node = NodeList::getInstance()->addOrUpdateNode(nodeUUID, + NODE_TYPE_AGENT, + &senderAddress, + &senderAddress); NodeList::getInstance()->updateNodeWithData(node, packetData, packetLength); diff --git a/libraries/voxels/src/JurisdictionListener.cpp b/libraries/voxels/src/JurisdictionListener.cpp index ea8bea3a2d..0a14d0809e 100644 --- a/libraries/voxels/src/JurisdictionListener.cpp +++ b/libraries/voxels/src/JurisdictionListener.cpp @@ -33,7 +33,7 @@ void JurisdictionListener::nodeAdded(Node* node) { } void JurisdictionListener::nodeKilled(Node* node) { - _jurisdictions.erase(_jurisdictions.find(node->getNodeID())); + _jurisdictions.erase(_jurisdictions.find(node->getUUID())); } bool JurisdictionListener::queueJurisdictionRequest() { @@ -66,10 +66,10 @@ void JurisdictionListener::processPacket(sockaddr& senderAddress, unsigned char* if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION) { Node* node = NodeList::getInstance()->nodeWithAddress(&senderAddress); if (node) { - uint16_t nodeID = node->getNodeID(); + QUuid nodeUUID = node->getUUID(); JurisdictionMap map; map.unpackFromMessage(packetData, packetLength); - _jurisdictions[nodeID] = map; + _jurisdictions[nodeUUID] = map; } } } diff --git a/libraries/voxels/src/JurisdictionMap.h b/libraries/voxels/src/JurisdictionMap.h index a3e96933a9..7b88321d5b 100644 --- a/libraries/voxels/src/JurisdictionMap.h +++ b/libraries/voxels/src/JurisdictionMap.h @@ -12,7 +12,9 @@ #include #include #include + #include +#include class JurisdictionMap { public: @@ -71,7 +73,7 @@ private: /// Map between node IDs and their reported JurisdictionMap. Typically used by classes that need to know which nodes are /// managing which jurisdictions. -typedef std::map NodeToJurisdictionMap; +typedef std::map NodeToJurisdictionMap; #endif /* defined(__hifi__JurisdictionMap__) */ diff --git a/libraries/voxels/src/JurisdictionSender.cpp b/libraries/voxels/src/JurisdictionSender.cpp index df48c27c47..150d04440f 100644 --- a/libraries/voxels/src/JurisdictionSender.cpp +++ b/libraries/voxels/src/JurisdictionSender.cpp @@ -27,9 +27,9 @@ void JurisdictionSender::processPacket(sockaddr& senderAddress, unsigned char* if (packetData[0] == PACKET_TYPE_VOXEL_JURISDICTION_REQUEST) { Node* node = NodeList::getInstance()->nodeWithAddress(&senderAddress); if (node) { - uint16_t nodeID = node->getNodeID(); + QUuid nodeUUID = node->getUUID(); lock(); - _nodesRequestingJurisdictions.insert(nodeID); + _nodesRequestingJurisdictions.insert(nodeUUID); unlock(); } } @@ -52,11 +52,11 @@ bool JurisdictionSender::process() { } int nodeCount = 0; - for (std::set::iterator nodeIterator = _nodesRequestingJurisdictions.begin(); + for (std::set::iterator nodeIterator = _nodesRequestingJurisdictions.begin(); nodeIterator != _nodesRequestingJurisdictions.end(); nodeIterator++) { - uint16_t nodeID = *nodeIterator; - Node* node = NodeList::getInstance()->nodeWithID(nodeID); + QUuid nodeUUID = *nodeIterator; + Node* node = NodeList::getInstance()->nodeWithUUID(nodeUUID); if (node->getActiveSocket() != NULL) { sockaddr* nodeAddress = node->getActiveSocket(); diff --git a/libraries/voxels/src/JurisdictionSender.h b/libraries/voxels/src/JurisdictionSender.h index 34f5a9f06f..9678eb15e2 100644 --- a/libraries/voxels/src/JurisdictionSender.h +++ b/libraries/voxels/src/JurisdictionSender.h @@ -35,6 +35,6 @@ protected: private: JurisdictionMap* _jurisdictionMap; - std::set _nodesRequestingJurisdictions; + std::set _nodesRequestingJurisdictions; }; #endif // __shared__JurisdictionSender__ diff --git a/libraries/voxels/src/VoxelEditPacketSender.cpp b/libraries/voxels/src/VoxelEditPacketSender.cpp index 3c435ca0af..a222c903d1 100644 --- a/libraries/voxels/src/VoxelEditPacketSender.cpp +++ b/libraries/voxels/src/VoxelEditPacketSender.cpp @@ -17,8 +17,8 @@ #include "VoxelEditPacketSender.h" -EditPacketBuffer::EditPacketBuffer(PACKET_TYPE type, unsigned char* buffer, ssize_t length, uint16_t nodeID) { - _nodeID = nodeID; +EditPacketBuffer::EditPacketBuffer(PACKET_TYPE type, unsigned char* buffer, ssize_t length, QUuid nodeUUID) { + _nodeUUID = nodeUUID; _currentType = type; _currentSize = length; memcpy(_currentBuffer, buffer, length); @@ -98,12 +98,12 @@ bool VoxelEditPacketSender::voxelServersExist() const { // This method is called when the edit packet layer has determined that it has a fully formed packet destined for // a known nodeID. However, we also want to handle the case where the -void VoxelEditPacketSender::queuePacketToNode(uint16_t nodeID, unsigned char* buffer, ssize_t length) { +void VoxelEditPacketSender::queuePacketToNode(const QUuid& nodeUUID, unsigned char* buffer, ssize_t length) { NodeList* nodeList = NodeList::getInstance(); for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getActiveSocket() != NULL && node->getType() == NODE_TYPE_VOXEL_SERVER && - ((node->getNodeID() == nodeID) || (nodeID == (uint16_t)UNKNOWN_NODE_ID)) ) { + ((node->getUUID() == nodeUUID) || (nodeUUID.isNull()))) { sockaddr* nodeAddress = node->getActiveSocket(); queuePacketForSending(*nodeAddress, buffer, length); } @@ -170,14 +170,14 @@ void VoxelEditPacketSender::queuePacketToNodes(unsigned char* buffer, ssize_t le for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getActiveSocket() != NULL && node->getType() == NODE_TYPE_VOXEL_SERVER) { - uint16_t nodeID = node->getNodeID(); + QUuid nodeUUID = node->getUUID(); bool isMyJurisdiction = true; // we need to get the jurisdiction for this // here we need to get the "pending packet" for this server - const JurisdictionMap& map = (*_voxelServerJurisdictions)[nodeID]; + const JurisdictionMap& map = (*_voxelServerJurisdictions)[nodeUUID]; isMyJurisdiction = (map.isMyJurisdiction(octCode, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN); if (isMyJurisdiction) { - queuePacketToNode(nodeID, buffer, length); + queuePacketToNode(nodeUUID, buffer, length); } } } @@ -216,18 +216,18 @@ void VoxelEditPacketSender::queueVoxelEditMessage(PACKET_TYPE type, unsigned cha for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { // only send to the NodeTypes that are NODE_TYPE_VOXEL_SERVER if (node->getActiveSocket() != NULL && node->getType() == NODE_TYPE_VOXEL_SERVER) { - uint16_t nodeID = node->getNodeID(); + QUuid nodeUUID = node->getUUID(); bool isMyJurisdiction = true; if (_voxelServerJurisdictions) { // we need to get the jurisdiction for this // here we need to get the "pending packet" for this server - const JurisdictionMap& map = (*_voxelServerJurisdictions)[nodeID]; + const JurisdictionMap& map = (*_voxelServerJurisdictions)[nodeUUID]; isMyJurisdiction = (map.isMyJurisdiction(codeColorBuffer, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN); } if (isMyJurisdiction) { - EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeID]; - packetBuffer._nodeID = nodeID; + EditPacketBuffer& packetBuffer = _pendingEditPackets[nodeUUID]; + packetBuffer._nodeUUID = nodeUUID; // If we're switching type, then we send the last one and start over if ((type != packetBuffer._currentType && packetBuffer._currentSize > 0) || @@ -255,14 +255,14 @@ void VoxelEditPacketSender::releaseQueuedMessages() { if (!voxelServersExist()) { _releaseQueuedMessagesPending = true; } else { - for (std::map::iterator i = _pendingEditPackets.begin(); i != _pendingEditPackets.end(); i++) { + for (std::map::iterator i = _pendingEditPackets.begin(); i != _pendingEditPackets.end(); i++) { releaseQueuedPacket(i->second); } } } void VoxelEditPacketSender::releaseQueuedPacket(EditPacketBuffer& packetBuffer) { - queuePacketToNode(packetBuffer._nodeID, &packetBuffer._currentBuffer[0], packetBuffer._currentSize); + queuePacketToNode(packetBuffer._nodeUUID, &packetBuffer._currentBuffer[0], packetBuffer._currentSize); packetBuffer._currentSize = 0; packetBuffer._currentType = PACKET_TYPE_UNKNOWN; } diff --git a/libraries/voxels/src/VoxelEditPacketSender.h b/libraries/voxels/src/VoxelEditPacketSender.h index 97853af74a..7a5713d4c9 100644 --- a/libraries/voxels/src/VoxelEditPacketSender.h +++ b/libraries/voxels/src/VoxelEditPacketSender.h @@ -19,9 +19,9 @@ /// Used for construction of edit voxel packets class EditPacketBuffer { public: - EditPacketBuffer() { _currentSize = 0; _currentType = PACKET_TYPE_UNKNOWN; _nodeID = UNKNOWN_NODE_ID; } - EditPacketBuffer(PACKET_TYPE type, unsigned char* codeColorBuffer, ssize_t length, uint16_t nodeID = UNKNOWN_NODE_ID); - uint16_t _nodeID; + EditPacketBuffer() : _nodeUUID(), _currentType(PACKET_TYPE_UNKNOWN), _currentSize(0) { } + EditPacketBuffer(PACKET_TYPE type, unsigned char* codeColorBuffer, ssize_t length, const QUuid nodeUUID = QUuid()); + QUuid _nodeUUID; PACKET_TYPE _currentType; unsigned char _currentBuffer[MAX_PACKET_SIZE]; ssize_t _currentSize; @@ -86,7 +86,7 @@ public: private: bool _shouldSend; - void queuePacketToNode(uint16_t nodeID, unsigned char* buffer, ssize_t length); + void queuePacketToNode(const QUuid& nodeID, unsigned char* buffer, ssize_t length); void queuePacketToNodes(unsigned char* buffer, ssize_t length); void initializePacket(EditPacketBuffer& packetBuffer, PACKET_TYPE type); void releaseQueuedPacket(EditPacketBuffer& packetBuffer); // releases specific queued packet @@ -94,7 +94,7 @@ private: void processPreServerExistsPackets(); // These are packets which are destined from know servers but haven't been released because they're still too small - std::map _pendingEditPackets; + std::map _pendingEditPackets; // These are packets that are waiting to be processed because we don't yet know if there are voxel servers int _maxPendingMessages; diff --git a/libraries/voxels/src/VoxelNode.cpp b/libraries/voxels/src/VoxelNode.cpp index ad83b5a9cf..3f3397fedb 100644 --- a/libraries/voxels/src/VoxelNode.cpp +++ b/libraries/voxels/src/VoxelNode.cpp @@ -56,7 +56,7 @@ void VoxelNode::init(unsigned char * octalCode) { _voxelSystem = NULL; _isDirty = true; _shouldRender = false; - _sourceID = UNKNOWN_NODE_ID; + _sourceID = 0; // hardcoded to 0 for removal of 16 bit node ID calculateAABox(); markWithChangedTime(); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 3b79722686..6b3623ebe3 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1555,7 +1555,7 @@ bool VoxelTree::readFromSVOFile(const char* fileName) { unsigned char* entireFile = new unsigned char[fileLength]; file.read((char*)entireFile, fileLength); bool wantImportProgress = true; - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, UNKNOWN_NODE_ID, wantImportProgress); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, NULL, 0, wantImportProgress); readBitstreamToTree(entireFile, fileLength, args); delete[] entireFile; @@ -1815,7 +1815,7 @@ void VoxelTree::copyFromTreeIntoSubTree(VoxelTree* sourceTree, VoxelNode* destin // ask destination tree to read the bitstream bool wantImportProgress = true; - ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationNode, UNKNOWN_NODE_ID, wantImportProgress); + ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS, destinationNode, 0, wantImportProgress); readBitstreamToTree(&outputBuffer[0], bytesWritten, args); } } diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 318b8fc5eb..2e42269440 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -108,7 +108,7 @@ public: bool includeColor = WANT_COLOR, bool includeExistsBits = WANT_EXISTS_BITS, VoxelNode* destinationNode = NULL, - uint16_t sourceID = UNKNOWN_NODE_ID, + uint16_t sourceID = 0, // hardcoded to 0 for removal of 16 bit node ID bool wantImportProgress = false) : includeColor(includeColor), includeExistsBits(includeExistsBits),