diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 660ee970a8..b9fd09e883 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -121,7 +121,7 @@ void AssignmentClient::readPendingDatagrams() { // switch our nodelist domain IP and port to whoever sent us the assignment nodeList->getDomainInfo().setSockAddr(senderSockAddr); - nodeList->setSessionUUID(_currentAssignment->getUUID()); + nodeList->getDomainInfo().setAssignmentUUID(_currentAssignment->getUUID()); qDebug() << "Destination IP for assignment is" << nodeList->getDomainInfo().getIP().toString(); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 972305382c..48b025a3a9 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -27,12 +27,6 @@ #include "DomainServer.h" -const int RESTART_HOLD_TIME_MSECS = 5 * 1000; - -const char* VOXEL_SERVER_CONFIG = "voxelServerConfig"; -const char* PARTICLE_SERVER_CONFIG = "particleServerConfig"; -const char* METAVOXEL_SERVER_CONFIG = "metavoxelServerConfig"; - const quint16 DOMAIN_SERVER_HTTP_PORT = 8080; DomainServer::DomainServer(int argc, char* argv[]) : @@ -40,8 +34,8 @@ DomainServer::DomainServer(int argc, char* argv[]) : _HTTPManager(DOMAIN_SERVER_HTTP_PORT, QString("%1/resources/web/").arg(QCoreApplication::applicationDirPath()), this), _staticAssignmentHash(), _assignmentQueue(), - _hasCompletedRestartHold(false), - _nodeAuthenticationURL(DEFAULT_NODE_AUTH_URL) + _nodeAuthenticationURL(DEFAULT_NODE_AUTH_URL), + _redeemedTokenResponses() { _argumentList = arguments(); int argumentIndex = 0; @@ -149,8 +143,8 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { connect(&nodeList->getNodeSocket(), SIGNAL(readyRead()), SLOT(readAvailableDatagrams())); - // fire a single shot timer to add static assignments back into the queue after a restart - QTimer::singleShot(RESTART_HOLD_TIME_MSECS, this, SLOT(addStaticAssignmentsBackToQueueAfterRestart())); + // add whatever static assignments that have been parsed to the queue + addStaticAssignmentsToQueue(); } void DomainServer::parseCommandLineTypeConfigs(const QStringList& argumentList, QSet& excludedTypes) { @@ -292,24 +286,156 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSetgetNodeSocket().writeDatagram(authenticationRequestPacket, + senderSockAddr.getAddress(), senderSockAddr.getPort()); +} + const NodeSet STATICALLY_ASSIGNED_NODES = NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::VoxelServer << NodeType::ParticleServer << NodeType::MetavoxelServer; + +void DomainServer::addNodeToNodeListAndConfirmConnection(const QByteArray& packet, const HifiSockAddr& senderSockAddr, + const QJsonObject& authJsonObject) { + + NodeType_t nodeType; + HifiSockAddr publicSockAddr, localSockAddr; + + int numPreInterestBytes = parseNodeDataFromByteArray(nodeType, publicSockAddr, localSockAddr, packet, senderSockAddr); + + QUuid nodeUUID = uuidFromPacketHeader(packet); + SharedAssignmentPointer matchingAssignment; + + if (!nodeUUID.isNull() && (matchingAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType))) { + // this is an assigned node, make sure the UUID sent is for an assignment we're actually trying to give out + nodeUUID = uuidFromPacketHeader(packet); + + if (matchingAssignment) { + // this was a newly added node with a matching assignment + + // remove the matching assignment from the assignment queue so we don't take the next check in + // (if it exists) + removeMatchingAssignmentFromQueue(matchingAssignment); + } + } + + // create a new session UUID for this node + nodeUUID = QUuid::createUuid(); + + SharedNodePointer newNode = NodeList::getInstance()->addOrUpdateNode(nodeUUID, nodeType, publicSockAddr, localSockAddr); + + // reply back to the user with a PacketTypeDomainList + sendDomainListToNode(newNode, senderSockAddr, nodeInterestListFromPacket(packet, numPreInterestBytes)); +} + +int DomainServer::parseNodeDataFromByteArray(NodeType_t& nodeType, HifiSockAddr& publicSockAddr, + HifiSockAddr& localSockAddr, const QByteArray& packet, + const HifiSockAddr& senderSockAddr) { + QDataStream packetStream(packet); + packetStream.skipRawData(numBytesForPacketHeader(packet)); + + packetStream >> nodeType; + packetStream >> publicSockAddr >> localSockAddr; + + if (publicSockAddr.getAddress().isNull()) { + // this node wants to use us its STUN server + // so set the node public address to whatever we perceive the public address to be + + // if the sender is on our box then leave its public address to 0 so that + // other users attempt to reach it on the same address they have for the domain-server + if (senderSockAddr.getAddress().isLoopback()) { + publicSockAddr.setAddress(QHostAddress()); + } else { + publicSockAddr.setAddress(senderSockAddr.getAddress()); + } + } + + return packetStream.device()->pos(); +} + +NodeSet DomainServer::nodeInterestListFromPacket(const QByteArray& packet, int numPreceedingBytes) { + QDataStream packetStream(packet); + packetStream.skipRawData(numPreceedingBytes); + + quint8 numInterestTypes = 0; + packetStream >> numInterestTypes; + + quint8 nodeType; + NodeSet nodeInterestSet; + + for (int i = 0; i < numInterestTypes; i++) { + packetStream >> nodeType; + nodeInterestSet.insert((NodeType_t) nodeType); + } + + return nodeInterestSet; +} + +void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr &senderSockAddr, + const NodeSet& nodeInterestList) { + + QByteArray broadcastPacket = byteArrayWithPopluatedHeader(PacketTypeDomainList); + + // always send the node their own UUID back + QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); + broadcastDataStream << node->getUUID(); + + DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); + + NodeList* nodeList = NodeList::getInstance(); + + if (nodeInterestList.size() > 0) { + // if the node has any interest types, send back those nodes as well + foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { + if (otherNode->getUUID() != node->getUUID() && nodeInterestList.contains(otherNode->getType())) { + + // don't send avatar nodes to other avatars, that will come from avatar mixer + broadcastDataStream << *otherNode.data(); + + // pack the secret that these two nodes will use to communicate with each other + QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID()); + if (secretUUID.isNull()) { + // generate a new secret UUID these two nodes can use + secretUUID = QUuid::createUuid(); + + // set that on the current Node's sessionSecretHash + nodeData->getSessionSecretHash().insert(otherNode->getUUID(), secretUUID); + + // set it on the other Node's sessionSecretHash + reinterpret_cast(otherNode->getLinkedData()) + ->getSessionSecretHash().insert(node->getUUID(), secretUUID); + + } + + broadcastDataStream << secretUUID; + } + } + } + + +} + void DomainServer::readAvailableDatagrams() { NodeList* nodeList = NodeList::getInstance(); AccountManager& accountManager = AccountManager::getInstance(); - HifiSockAddr senderSockAddr, nodePublicAddress, nodeLocalAddress; - - static QByteArray broadcastPacket = byteArrayWithPopluatedHeader(PacketTypeDomainList); - static int numBroadcastPacketHeaderBytes = broadcastPacket.size(); + HifiSockAddr senderSockAddr; static QByteArray assignmentPacket = byteArrayWithPopluatedHeader(PacketTypeCreateAssignment); static int numAssignmentPacketHeaderBytes = assignmentPacket.size(); QByteArray receivedPacket; - NodeType_t nodeType; while (nodeList->getNodeSocket().hasPendingDatagrams()) { receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); @@ -318,142 +444,60 @@ void DomainServer::readAvailableDatagrams() { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { PacketType requestType = packetTypeForPacket(receivedPacket); - if (requestType == PacketTypeDomainListRequest) { - - QUuid nodeUUID = uuidFromPacketHeader(receivedPacket); - - if (!_nodeAuthenticationURL.isEmpty() && - (nodeUUID.isNull() || !nodeList->nodeWithUUID(nodeUUID))) { - // this is a node we do not recognize and we need authentication - ask them to do so - // by providing them the hostname they should authenticate with - QByteArray authenticationRequestPacket = byteArrayWithPopluatedHeader(PacketTypeDomainServerAuthRequest); - - QDataStream authPacketStream(&authenticationRequestPacket, QIODevice::Append); - authPacketStream << _nodeAuthenticationURL; - - qDebug() << "Asking node at" << senderSockAddr << "to authenticate."; - - // send the authentication request back to the node - nodeList->getNodeSocket().writeDatagram(authenticationRequestPacket, - senderSockAddr.getAddress(), senderSockAddr.getPort()); - - } else { - // this is an RFD or domain list request packet, and there is a match - QDataStream packetStream(receivedPacket); - packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); - - packetStream >> nodeType; - packetStream >> nodePublicAddress >> nodeLocalAddress; - - if (nodePublicAddress.getAddress().isNull()) { - // this node wants to use us its STUN server - // so set the node public address to whatever we perceive the public address to be - - // if the sender is on our box then leave its public address to 0 so that - // other users attempt to reach it on the same address they have for the domain-server - if (senderSockAddr.getAddress().isLoopback()) { - nodePublicAddress.setAddress(QHostAddress()); - } else { - nodePublicAddress.setAddress(senderSockAddr.getAddress()); - } - } - - SharedAssignmentPointer matchingStaticAssignment; - - // check if this is a non-statically assigned node, a node that is assigned and checking in for the first time - // or a node that has already checked in and is continuing to report for duty - if (!STATICALLY_ASSIGNED_NODES.contains(nodeType) - || (matchingStaticAssignment = matchingStaticAssignmentForCheckIn(nodeUUID, nodeType)) - || nodeList->getInstance()->nodeWithUUID(nodeUUID)) { - - if (nodeUUID.isNull()) { - // this is a check in from an unidentified node - // we need to generate a session UUID for this node - nodeUUID = QUuid::createUuid(); - } - - SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID, - nodeType, - nodePublicAddress, - nodeLocalAddress); - - // resize our broadcast packet in preparation to set it up again - broadcastPacket.resize(numBroadcastPacketHeaderBytes); - - if (matchingStaticAssignment) { - // this was a newly added node with a matching static assignment - - // remove the matching assignment from the assignment queue so we don't take the next check in - // (if it exists) - if (_hasCompletedRestartHold) { - removeMatchingAssignmentFromQueue(matchingStaticAssignment); - } - } - - quint8 numInterestTypes = 0; - packetStream >> numInterestTypes; - - NodeType_t* nodeTypesOfInterest = reinterpret_cast(receivedPacket.data() - + packetStream.device()->pos()); - - // always send the node their own UUID back - QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); - broadcastDataStream << checkInNode->getUUID(); - - DomainServerNodeData* nodeData = reinterpret_cast(checkInNode->getLinkedData()); - - if (numInterestTypes > 0) { - // if the node has any interest types, send back those nodes as well - foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { - if (otherNode->getUUID() != nodeUUID && - memchr(nodeTypesOfInterest, otherNode->getType(), numInterestTypes)) { - - // don't send avatar nodes to other avatars, that will come from avatar mixer - broadcastDataStream << *otherNode.data(); - - // pack the secret that these two nodes will use to communicate with each other - QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID()); - if (secretUUID.isNull()) { - // generate a new secret UUID these two nodes can use - secretUUID = QUuid::createUuid(); - - // set that on the current Node's sessionSecretHash - nodeData->getSessionSecretHash().insert(otherNode->getUUID(), secretUUID); - - // set it on the other Node's sessionSecretHash - reinterpret_cast(otherNode->getLinkedData()) - ->getSessionSecretHash().insert(nodeUUID, secretUUID); - - } - - broadcastDataStream << secretUUID; - } - } - } - - // update last receive to now - quint64 timeNow = usecTimestampNow(); - checkInNode->setLastHeardMicrostamp(timeNow); - - // send the constructed list back to this node - nodeList->getNodeSocket().writeDatagram(broadcastPacket, - senderSockAddr.getAddress(), senderSockAddr.getPort()); - } - } - } else if (requestType == PacketTypeDomainConnectRequest) { + + if (requestType == PacketTypeDomainConnectRequest) { QDataStream packetStream(receivedPacket); packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); - QByteArray registrationToken; - packetStream >> registrationToken; + quint8 hasRegistrationToken; + packetStream >> hasRegistrationToken; - // make a request against the data-server to get information required to connect to this node - JSONCallbackParameters tokenCallbackParams; - tokenCallbackParams.jsonCallbackReceiver = this; - tokenCallbackParams.jsonCallbackMethod = "processTokenRedeemResponse"; + if (requiresAuthentication() && !hasRegistrationToken) { + // we need authentication and this node did not give us a registration token - tell it to auth + requestAuthenticationFromPotentialNode(senderSockAddr); + } else if (requiresAuthentication()) { + QByteArray registrationToken; + packetStream >> registrationToken; + + QString registrationTokenString(registrationToken.toHex()); + QJsonObject jsonForRedeemedToken = _redeemedTokenResponses.value(registrationTokenString); + + // check if we have redeemed this token and are ready to check the node in + if (jsonForRedeemedToken.isEmpty()) { + // make a request against the data-server to get information required to connect to this node + JSONCallbackParameters tokenCallbackParams; + tokenCallbackParams.jsonCallbackReceiver = this; + tokenCallbackParams.jsonCallbackMethod = "processTokenRedeemResponse"; + + QString redeemURLString = QString("/api/v1/nodes/redeem/%1.json").arg(registrationTokenString); + accountManager.authenticatedRequest(redeemURLString, QNetworkAccessManager::GetOperation); + } else { + // we've redeemed the token for this node and are ready to start communicating with it + // add the node to our NodeList + addNodeToNodeListAndConfirmConnection(receivedPacket, senderSockAddr, jsonForRedeemedToken); + } + } else { + // we don't require authentication - add this node to our NodeList + // and send back session UUID right away + addNodeToNodeListAndConfirmConnection(receivedPacket, senderSockAddr); + } - QString redeemURLString = QString("/api/v1/nodes/redeem/%1.json").arg(QString(registrationToken.toHex())); - accountManager.authenticatedRequest(redeemURLString, QNetworkAccessManager::GetOperation); + } else if (requestType == PacketTypeDomainListRequest) { + QUuid nodeUUID = uuidFromPacketHeader(receivedPacket); + NodeType_t throwawayNodeType; + HifiSockAddr nodePublicAddress, nodeLocalAddress; + + int numNodeInfoBytes = parseNodeDataFromByteArray(throwawayNodeType, nodePublicAddress, nodeLocalAddress, + receivedPacket, senderSockAddr); + + SharedNodePointer checkInNode = nodeList->updateSocketsForNode(nodeUUID, nodePublicAddress, nodeLocalAddress); + + // update last receive to now + quint64 timeNow = usecTimestampNow(); + checkInNode->setLastHeardMicrostamp(timeNow); + + + sendDomainListToNode(checkInNode, senderSockAddr, nodeInterestListFromPacket(receivedPacket, numNodeInfoBytes)); } else if (requestType == PacketTypeRequestAssignment) { @@ -713,25 +757,16 @@ void DomainServer::nodeKilled(SharedNodePointer node) { } SharedAssignmentPointer DomainServer::matchingStaticAssignmentForCheckIn(const QUuid& checkInUUID, NodeType_t nodeType) { - if (_hasCompletedRestartHold) { - // look for a match in the assignment hash - - QQueue::iterator i = _assignmentQueue.begin(); - - while (i != _assignmentQueue.end()) { - if (i->data()->getType() == Assignment::typeForNodeType(nodeType) && i->data()->getUUID() == checkInUUID) { - return _assignmentQueue.takeAt(i - _assignmentQueue.begin()); - } else { - ++i; - } - } - } else { - SharedAssignmentPointer matchingStaticAssignment = _staticAssignmentHash.value(checkInUUID); - if (matchingStaticAssignment && matchingStaticAssignment->getType() == nodeType) { - return matchingStaticAssignment; + QQueue::iterator i = _assignmentQueue.begin(); + + while (i != _assignmentQueue.end()) { + if (i->data()->getType() == Assignment::typeForNodeType(nodeType) && i->data()->getUUID() == checkInUUID) { + return _assignmentQueue.takeAt(i - _assignmentQueue.begin()); + } else { + ++i; } } - + return SharedAssignmentPointer(); } @@ -794,8 +829,7 @@ void DomainServer::removeMatchingAssignmentFromQueue(const SharedAssignmentPoint } } -void DomainServer::addStaticAssignmentsBackToQueueAfterRestart() { - _hasCompletedRestartHold = true; +void DomainServer::addStaticAssignmentsToQueue() { // if the domain-server has just restarted, // check if there are static assignments that we need to throw into the assignment queue diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 3dd32b0561..823bb7c74a 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,8 @@ class DomainServer : public QCoreApplication, public HTTPRequestHandler { public: DomainServer(int argc, char* argv[]); + bool requiresAuthentication() const { return !_nodeAuthenticationURL.isEmpty(); } + bool handleHTTPRequest(HTTPConnection* connection, const QString& path); void exit(int retCode = 0); @@ -39,6 +42,15 @@ public slots: private: void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid()); + void requestAuthenticationFromPotentialNode(const HifiSockAddr& senderSockAddr); + void addNodeToNodeListAndConfirmConnection(const QByteArray& packet, const HifiSockAddr& senderSockAddr, + const QJsonObject& authJsonObject = QJsonObject()); + int parseNodeDataFromByteArray(NodeType_t& nodeType, HifiSockAddr& publicSockAddr, + HifiSockAddr& localSockAddr, const QByteArray& packet, const HifiSockAddr& senderSockAddr); + NodeSet nodeInterestListFromPacket(const QByteArray& packet, int numPreceedingBytes); + void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr, + const NodeSet& nodeInterestList); + void parseCommandLineTypeConfigs(const QStringList& argumentList, QSet& excludedTypes); void readConfigFile(const QString& path, QSet& excludedTypes); QString readServerAssignmentConfig(const QJsonObject& jsonObject, const QString& nodeName); @@ -50,6 +62,7 @@ private: SharedAssignmentPointer deployableAssignmentForRequest(const Assignment& requestAssignment); void removeMatchingAssignmentFromQueue(const SharedAssignmentPointer& removableAssignment); void refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment); + void addStaticAssignmentsToQueue(); QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); @@ -59,18 +72,17 @@ private: QHash _staticAssignmentHash; QQueue _assignmentQueue; - bool _hasCompletedRestartHold; - QUrl _nodeAuthenticationURL; QStringList _argumentList; + + QHash _redeemedTokenResponses; private slots: void requestCreationFromDataServer(); void processCreateResponseFromDataServer(const QJsonObject& jsonObject); void processTokenRedeemResponse(const QJsonObject& jsonObject); void readAvailableDatagrams(); - void addStaticAssignmentsBackToQueueAfterRestart(); }; #endif /* defined(__hifi__DomainServer__) */ diff --git a/libraries/shared/src/DomainInfo.cpp b/libraries/shared/src/DomainInfo.cpp index 8eb7032011..cdc835c718 100644 --- a/libraries/shared/src/DomainInfo.cpp +++ b/libraries/shared/src/DomainInfo.cpp @@ -13,6 +13,7 @@ DomainInfo::DomainInfo() : _uuid(), _sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)), + _assignmentUUID(), _connectionSecret(), _registrationToken(), _rootAuthenticationURL(), @@ -25,6 +26,7 @@ void DomainInfo::reset() { _uuid = QUuid(); _hostname = QString(); _sockAddr.setAddress(QHostAddress::Null); + _assignmentUUID = QUuid(); _connectionSecret = QString(); _registrationToken = QByteArray(); _rootAuthenticationURL = QUrl(); diff --git a/libraries/shared/src/DomainInfo.h b/libraries/shared/src/DomainInfo.h index fe1ec83e8b..4a0e89f8e0 100644 --- a/libraries/shared/src/DomainInfo.h +++ b/libraries/shared/src/DomainInfo.h @@ -40,6 +40,9 @@ public: unsigned short getPort() const { return _sockAddr.getPort(); } + const QUuid& getAssignmentUUID() const { return _assignmentUUID; } + void setAssignmentUUID(const QUuid& assignmentUUID) { _assignmentUUID = assignmentUUID; } + const QUuid& getConnectionSecret() const { return _connectionSecret; } void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } @@ -58,6 +61,7 @@ private: QUuid _uuid; QString _hostname; HifiSockAddr _sockAddr; + QUuid _assignmentUUID; QUuid _connectionSecret; QByteArray _registrationToken; QUrl _rootAuthenticationURL; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 0d34f5a92a..7674727fe0 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -90,7 +90,7 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { } const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeDomainList - << PacketTypeDomainListRequest << PacketTypeDomainServerAuthRequest << PacketTypeDomainConnectRequest + << PacketTypeDomainServerAuthRequest << PacketTypeDomainConnectRequest << PacketTypeStunResponse << PacketTypeDataServerConfirm << PacketTypeDataServerGet << PacketTypeDataServerPut << PacketTypeDataServerSend << PacketTypeCreateAssignment << PacketTypeRequestAssignment; @@ -484,16 +484,22 @@ void NodeList::sendDomainServerCheckIn() { || !_domainInfo.getRegistrationToken().isEmpty() ) { // construct the DS check in packet - PacketType domainPacketType = _domainInfo.getRegistrationToken().isEmpty() - ? PacketTypeDomainListRequest : PacketTypeDomainConnectRequest; + PacketType domainPacketType = _sessionUUID.isNull() ? PacketTypeDomainConnectRequest : PacketTypeDomainListRequest; - QByteArray domainServerPacket = byteArrayWithPopluatedHeader(domainPacketType); + QUuid packetUUID = (domainPacketType == PacketTypeDomainListRequest) + ? _sessionUUID : _domainInfo.getAssignmentUUID(); + + QByteArray domainServerPacket = byteArrayWithPopluatedHeader(domainPacketType, packetUUID); QDataStream packetStream(&domainServerPacket, QIODevice::Append); if (domainPacketType == PacketTypeDomainConnectRequest) { - // we have a registration token to present to the domain-server - // send that along in each packet until we get a list back from the domain-server - packetStream << _domainInfo.getRegistrationToken(); + // we may need a registration token to present to the domain-server + packetStream << (quint8) !_domainInfo.getRegistrationToken().isEmpty(); + + if (!_domainInfo.getRegistrationToken().isEmpty()) { + // if we have a registration token send that along in the request + packetStream << _domainInfo.getRegistrationToken(); + } } // pack our data to send to the domain-server @@ -679,9 +685,8 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { _nodeHashMutex.lock(); - SharedNodePointer matchingNode = _nodeHash.value(uuid); - - if (!matchingNode) { + if (!_nodeHash.contains(uuid)) { + // we didn't have this node, so add them Node* newNode = new Node(uuid, nodeType, publicSocket, localSocket); SharedNodePointer newNodeSharedPointer(newNode, &QObject::deleteLater); @@ -698,29 +703,32 @@ SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, } else { _nodeHashMutex.unlock(); + return updateSocketsForNode(uuid, publicSocket, localSocket); + } +} + +SharedNodePointer NodeList::updateSocketsForNode(const QUuid& uuid, + const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket) { + + SharedNodePointer matchingNode = nodeWithUUID(uuid); + + if (matchingNode) { + // perform appropriate updates to this node QMutexLocker locker(&matchingNode->getMutex()); - - if (matchingNode->getType() == NodeType::AudioMixer || - matchingNode->getType() == NodeType::VoxelServer || - matchingNode->getType() == NodeType::MetavoxelServer) { - // 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 - matchingNode->setLastHeardMicrostamp(usecTimestampNow()); - } - + // check if we need to change this node's public or local sockets if (publicSocket != matchingNode->getPublicSocket()) { matchingNode->setPublicSocket(publicSocket); qDebug() << "Public socket change for node" << *matchingNode; } - + if (localSocket != matchingNode->getLocalSocket()) { matchingNode->setLocalSocket(localSocket); qDebug() << "Local socket change for node" << *matchingNode; } - // we had this node already, do nothing for now - return matchingNode; } + + return matchingNode; } unsigned NodeList::broadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 855da13aa3..a66bcf3535 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -106,6 +106,8 @@ public: SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); + SharedNodePointer updateSocketsForNode(const QUuid& uuid, + const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket); void processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet); void processKillNode(const QByteArray& datagram);