mirror of
https://github.com/overte-org/overte.git
synced 2025-04-16 13:56:24 +02:00
tweaks to domain-server authentication flow
This commit is contained in:
parent
217a7862e5
commit
a6c1e3e87f
7 changed files with 253 additions and 191 deletions
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<Assignment::Type>& excludedTypes) {
|
||||
|
@ -292,24 +286,156 @@ void DomainServer::populateDefaultStaticAssignmentsExcludingTypes(const QSet<Ass
|
|||
}
|
||||
}
|
||||
|
||||
void DomainServer::requestAuthenticationFromPotentialNode(const HifiSockAddr& senderSockAddr) {
|
||||
// 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::getInstance()->getNodeSocket().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<DomainServerNodeData*>(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<DomainServerNodeData*>(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<NodeType_t*>(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<DomainServerNodeData*>(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<DomainServerNodeData*>(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<SharedAssignmentPointer>::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<SharedAssignmentPointer>::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
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QQueue>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QUrl>
|
||||
|
@ -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<Assignment::Type>& excludedTypes);
|
||||
void readConfigFile(const QString& path, QSet<Assignment::Type>& 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<QUuid, SharedAssignmentPointer> _staticAssignmentHash;
|
||||
QQueue<SharedAssignmentPointer> _assignmentQueue;
|
||||
|
||||
bool _hasCompletedRestartHold;
|
||||
|
||||
QUrl _nodeAuthenticationURL;
|
||||
|
||||
QStringList _argumentList;
|
||||
|
||||
QHash<QString, QJsonObject> _redeemedTokenResponses;
|
||||
private slots:
|
||||
void requestCreationFromDataServer();
|
||||
void processCreateResponseFromDataServer(const QJsonObject& jsonObject);
|
||||
void processTokenRedeemResponse(const QJsonObject& jsonObject);
|
||||
|
||||
void readAvailableDatagrams();
|
||||
void addStaticAssignmentsBackToQueueAfterRestart();
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__DomainServer__) */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -90,7 +90,7 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
|
|||
}
|
||||
|
||||
const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>() << 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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue