diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 930b44dbce..135fc341e5 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -129,7 +129,7 @@ void AudioMixer::run() { // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); - NodeList::getInstance()->sendDomainServerCheckIn(); + NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData()); if (Logging::shouldSendStats() && numStatCollections > 0) { // if we should be sending stats to Logstash send the appropriate average now diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 604301a391..49c0b02d0c 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -119,7 +119,7 @@ void AvatarMixer::run() { // send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) { gettimeofday(&lastDomainServerCheckIn, NULL); - NodeList::getInstance()->sendDomainServerCheckIn(); + NodeList::getInstance()->sendDomainServerCheckIn(this->getUUID().toRfc4122().constData()); } if (nodeList->getNodeSocket()->receive(nodeAddress, packetData, &receivedBytes) && diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 04072dab49..938b6d35ab 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -155,7 +155,7 @@ int main(int argc, const char* argv[]) { Assignment avatarMixerAssignment(Assignment::CreateCommand, Assignment::AvatarMixerType, Assignment::LocalLocation); - + Assignment voxelServerAssignment(Assignment::CreateCommand, Assignment::VoxelServerType, Assignment::LocalLocation); @@ -247,77 +247,107 @@ int main(int argc, const char* argv[]) { nodePublicAddress.sin_addr.s_addr = 0; } - Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress, - (sockaddr*) &nodeLocalAddress, - nodeType, - nodeList->getLastNodeID()); + bool matchedUUID = true; - // if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it - if (newNode) { - if (newNode->getNodeID() == nodeList->getLastNodeID()) { - nodeList->increaseNodeID(); + if ((nodeType == NODE_TYPE_AVATAR_MIXER || nodeType == NODE_TYPE_AUDIO_MIXER) && + !nodeList->soloNodeOfType(nodeType)) { + // if this is an audio-mixer or an avatar-mixer and we don't have one yet + // we need to check the GUID of the assignment in the queue + // (if it exists) to make sure there is a match + + // reset matchedUUID to false so there is no match by default + matchedUUID = false; + + // pull the UUID passed with the check in + QUuid checkInUUID = QUuid::fromRfc4122(QByteArray((const char*) packetData + numBytesSenderHeader + + sizeof(NODE_TYPE), + NUM_BYTES_RFC4122_UUID)); + + // lock the assignment queue + ::assignmentQueueMutex.lock(); + + std::deque::iterator assignment = ::assignmentQueue.begin(); + + Assignment::Type matchType = nodeType == NODE_TYPE_AUDIO_MIXER + ? Assignment::AudioMixerType : Assignment::AvatarMixerType; + + + // enumerate the assignments and see if there is a type and UUID match + while (assignment != ::assignmentQueue.end()) { + + if ((*assignment)->getType() == matchType + && (*assignment)->getUUID() == checkInUUID) { + // type and UUID match + matchedUUID = true; + + // remove this assignment from the queue + ::assignmentQueue.erase(assignment); + + break; + } else { + // no match, keep looking + assignment++; + } } - int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); + // unlock the assignment queue + ::assignmentQueueMutex.unlock(); + } + + if (matchedUUID) { + Node* newNode = nodeList->addOrUpdateNode((sockaddr*) &nodePublicAddress, + (sockaddr*) &nodeLocalAddress, + nodeType, + nodeList->getLastNodeID()); - currentBufferPos = broadcastPacket + numHeaderBytes; - startPointer = currentBufferPos; - - unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + sizeof(NODE_TYPE) - + numBytesSocket + sizeof(unsigned char); - int numInterestTypes = *(nodeTypesOfInterest - 1); - - if (numInterestTypes > 0) { - // if the node has sent no types of interest, assume they want nothing but their own ID back - for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { - if (!node->matches((sockaddr*) &nodePublicAddress, (sockaddr*) &nodeLocalAddress, nodeType) && - memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { - // this is not the node themselves - // and this is an node of a type in the passed node types of interest - // or the node did not pass us any specific types they are interested in - - if (memchr(SOLO_NODE_TYPES, node->getType(), sizeof(SOLO_NODE_TYPES)) == NULL) { - // this is an node of which there can be multiple, just add them to the packet + // if addOrUpdateNode returns NULL this was a solo node we already have, don't talk back to it + if (newNode) { + if (newNode->getNodeID() == nodeList->getLastNodeID()) { + nodeList->increaseNodeID(); + } + + int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_DOMAIN); + + currentBufferPos = broadcastPacket + numHeaderBytes; + startPointer = currentBufferPos; + + int numBytesUUID = (nodeType == NODE_TYPE_AUDIO_MIXER || nodeType == NODE_TYPE_AVATAR_MIXER) + ? NUM_BYTES_RFC4122_UUID + : 0; + + unsigned char* nodeTypesOfInterest = packetData + numBytesSenderHeader + numBytesUUID + + sizeof(NODE_TYPE) + numBytesSocket + sizeof(unsigned char); + int numInterestTypes = *(nodeTypesOfInterest - 1); + + if (numInterestTypes > 0) { + // if the node has sent no types of interest, assume they want nothing but their own ID back + for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) { + if (!node->matches((sockaddr*) &nodePublicAddress, (sockaddr*) &nodeLocalAddress, nodeType) && + memchr(nodeTypesOfInterest, node->getType(), numInterestTypes)) { + // don't send avatar nodes to other avatars, that will come from avatar mixer if (nodeType != NODE_TYPE_AGENT || node->getType() != NODE_TYPE_AGENT) { currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, &(*node)); } - } else { - // solo node, we need to only send newest - if (newestSoloNodes[node->getType()] == NULL || - newestSoloNodes[node->getType()]->getWakeMicrostamp() < node->getWakeMicrostamp()) { - // we have to set the newer solo node to add it to the broadcast later - newestSoloNodes[node->getType()] = &(*node); - } } } + + } - for (std::map::iterator soloNode = newestSoloNodes.begin(); - soloNode != newestSoloNodes.end(); - soloNode++) { - // this is the newest alive solo node, add them to the packet - currentBufferPos = addNodeToBroadcastPacket(currentBufferPos, soloNode->second); - } + // update last receive to now + uint64_t timeNow = usecTimestampNow(); + newNode->setLastHeardMicrostamp(timeNow); + + // add the node ID to the end of the pointer + currentBufferPos += packNodeId(currentBufferPos, newNode->getNodeID()); + + // send the constructed list back to this node + nodeList->getNodeSocket()->send((sockaddr*)&replyDestinationSocket, + broadcastPacket, + (currentBufferPos - startPointer) + numHeaderBytes); } - - // update last receive to now - uint64_t timeNow = usecTimestampNow(); - newNode->setLastHeardMicrostamp(timeNow); - - if (packetData[0] == PACKET_TYPE_DOMAIN_REPORT_FOR_DUTY - && memchr(SOLO_NODE_TYPES, nodeType, sizeof(SOLO_NODE_TYPES))) { - newNode->setWakeMicrostamp(timeNow); - } - - // add the node ID to the end of the pointer - currentBufferPos += packNodeId(currentBufferPos, newNode->getNodeID()); - - // send the constructed list back to this node - nodeList->getNodeSocket()->send((sockaddr*)&replyDestinationSocket, - broadcastPacket, - (currentBufferPos - startPointer) + numHeaderBytes); } } else if (packetData[0] == PACKET_TYPE_REQUEST_ASSIGNMENT) { @@ -358,6 +388,13 @@ int main(int argc, const char* argv[]) { } else { // remove the assignment from the queue ::assignmentQueue.erase(assignment); + + if ((*assignment)->getType() != Assignment::VoxelServerType) { + // keep audio-mixer and avatar-mixer assignments in the queue + // until we get a check-in from that GUID + // but stick it at the back so the others have a chance to go out + ::assignmentQueue.push_back(*assignment); + } } // stop looping, we've handed out an assignment @@ -398,7 +435,8 @@ int main(int argc, const char* argv[]) { ::assignmentQueue.erase(assignment); delete *assignment; } - } else { + } else if ((*assignment)->getType() == Assignment::VoxelServerType) { + // this is a voxel server assignment // remove the assignment from the queue ::assignmentQueue.erase(assignment); } diff --git a/libraries/shared/src/Assignment.cpp b/libraries/shared/src/Assignment.cpp index f8aabf370f..68e1108334 100644 --- a/libraries/shared/src/Assignment.cpp +++ b/libraries/shared/src/Assignment.cpp @@ -14,8 +14,6 @@ const char IPv4_ADDRESS_DESIGNATOR = 4; const char IPv6_ADDRESS_DESIGNATOR = 6; -const int NUM_BYTES_RFC4122_UUID = 16; - Assignment::Assignment(Assignment::Command command, Assignment::Type type, Assignment::Location location) : _command(command), _type(type), diff --git a/libraries/shared/src/Assignment.h b/libraries/shared/src/Assignment.h index 5854ea270d..5370c1a16c 100644 --- a/libraries/shared/src/Assignment.h +++ b/libraries/shared/src/Assignment.h @@ -15,6 +15,8 @@ #include "NodeList.h" +const int NUM_BYTES_RFC4122_UUID = 16; + /// Holds information used for request, creation, and deployment of assignments class Assignment : public QObject { Q_OBJECT diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index cce0aecf14..d5a8bf99a2 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -268,7 +268,7 @@ void NodeList::setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNo _nodeTypesOfInterest[numNodeTypesOfInterest] = '\0'; } -void NodeList::sendDomainServerCheckIn() { +void NodeList::sendDomainServerCheckIn(const char* assignmentUUID) { static bool printedDomainServerIP = false; // Lookup the IP address of the domain server if we need to @@ -297,9 +297,9 @@ void NodeList::sendDomainServerCheckIn() { const int IP_ADDRESS_BYTES = 4; - // check in packet has header, node type, port, IP, node types of interest, null termination - int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + sizeof(uint16_t) + - IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char); + // 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 + sizeof(uint16_t) + IP_ADDRESS_BYTES + numBytesNodesOfInterest + sizeof(unsigned char); checkInPacket = new unsigned char[numPacketBytes]; unsigned char* packetPosition = checkInPacket; @@ -313,7 +313,13 @@ void NodeList::sendDomainServerCheckIn() { *(packetPosition++) = _ownerType; - packetPosition += packSocket(checkInPacket + numHeaderBytes + sizeof(NODE_TYPE), + if (assignmentUUID) { + // if we've got an assignment UUID to send add that here + memcpy(packetPosition, assignmentUUID, NUM_BYTES_RFC4122_UUID); + packetPosition += NUM_BYTES_RFC4122_UUID; + } + + packetPosition += packSocket(checkInPacket + (packetPosition - checkInPacket), getLocalAddress(), htons(_nodeSocket.getListeningPort())); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index bf64e5bb40..7233e7af69 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -97,7 +97,7 @@ public: void setNodeTypesOfInterest(const char* nodeTypesOfInterest, int numNodeTypesOfInterest); - void sendDomainServerCheckIn(); + void sendDomainServerCheckIn(const char* assignmentUUID = NULL); int processDomainServerList(unsigned char *packetData, size_t dataBytes); void setAssignmentServerSocket(sockaddr* serverSocket) { _assignmentServerSocket = serverSocket; } diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index fd261e4385..d31d499814 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -26,7 +26,7 @@ PACKET_VERSION versionForPacketType(PACKET_TYPE type) { return 1; case PACKET_TYPE_VOXEL_STATS: - return 2; + return 2; default: return 0; }