mirror of
https://github.com/overte-org/overte.git
synced 2025-04-16 09:07:19 +02:00
hook up domain request for node to authenticate
This commit is contained in:
parent
4c135dd3a7
commit
7c69028dc5
4 changed files with 134 additions and 109 deletions
|
@ -175,4 +175,5 @@ void AssignmentClient::assignmentCompleted() {
|
|||
// reset our NodeList by switching back to unassigned and clearing the list
|
||||
nodeList->setOwnerType(NodeType::Unassigned);
|
||||
nodeList->reset();
|
||||
nodeList->resetNodeInterestSet();
|
||||
}
|
||||
|
|
|
@ -69,8 +69,6 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
} else if ((argumentIndex = argumentList.indexOf(CUSTOM_AUTH_OPTION)) != -1) {
|
||||
_nodeAuthenticationHostname = argumentList.value(argumentIndex + 1);
|
||||
}
|
||||
|
||||
qDebug() << "the node authentication hostname is" << _nodeAuthenticationHostname;
|
||||
|
||||
NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort);
|
||||
|
||||
|
@ -254,109 +252,126 @@ void DomainServer::readAvailableDatagrams() {
|
|||
PacketType requestType = packetTypeForPacket(receivedPacket);
|
||||
if (requestType == PacketTypeDomainListRequest) {
|
||||
|
||||
// this is an RFD or domain list request packet, and there is a version match
|
||||
QDataStream packetStream(receivedPacket);
|
||||
packetStream.skipRawData(numBytesForPacketHeader(receivedPacket));
|
||||
|
||||
QUuid nodeUUID = uuidFromPacketHeader(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 (!_nodeAuthenticationHostname.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);
|
||||
|
||||
// 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)) {
|
||||
QDataStream authPacketStream(&authenticationRequestPacket, QIODevice::Append);
|
||||
authPacketStream << _nodeAuthenticationHostname;
|
||||
|
||||
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();
|
||||
}
|
||||
qDebug() << "Asking node at" << senderSockAddr << "to authenticate.";
|
||||
|
||||
SharedNodePointer checkInNode = nodeList->addOrUpdateNode(nodeUUID,
|
||||
nodeType,
|
||||
nodePublicAddress,
|
||||
nodeLocalAddress);
|
||||
// send the authentication request back to the node
|
||||
nodeList->getNodeSocket().writeDatagram(authenticationRequestPacket,
|
||||
senderSockAddr.getAddress(), senderSockAddr.getPort());
|
||||
|
||||
// resize our broadcast packet in preparation to set it up again
|
||||
broadcastPacket.resize(numBroadcastPacketHeaderBytes);
|
||||
} else {
|
||||
// this is an RFD or domain list request packet, and there is a match
|
||||
QDataStream packetStream(receivedPacket);
|
||||
packetStream.skipRawData(numBytesForPacketHeader(receivedPacket));
|
||||
|
||||
if (matchingStaticAssignment) {
|
||||
// this was a newly added node with a matching static assignment
|
||||
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
|
||||
|
||||
// remove the matching assignment from the assignment queue so we don't take the next check in
|
||||
// (if it exists)
|
||||
if (_hasCompletedRestartHold) {
|
||||
removeMatchingAssignmentFromQueue(matchingStaticAssignment);
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
quint8 numInterestTypes = 0;
|
||||
packetStream >> numInterestTypes;
|
||||
SharedAssignmentPointer matchingStaticAssignment;
|
||||
|
||||
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;
|
||||
// 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());
|
||||
}
|
||||
|
||||
// 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 == PacketTypeRequestAssignment) {
|
||||
|
||||
// construct the requested assignment from the packet data
|
||||
|
|
|
@ -68,11 +68,9 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
|
|||
{
|
||||
_nodeSocket.bind(QHostAddress::AnyIPv4, newSocketListenPort);
|
||||
qDebug() << "NodeList socket is listening on" << _nodeSocket.localPort();
|
||||
}
|
||||
|
||||
|
||||
NodeList::~NodeList() {
|
||||
clear();
|
||||
|
||||
// clear our NodeList when the domain changes
|
||||
connect(&_domainInfo, &DomainInfo::hostnameChanged, this, &NodeList::reset);
|
||||
}
|
||||
|
||||
bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
|
||||
|
@ -87,7 +85,8 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
|
|||
}
|
||||
|
||||
const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>() << PacketTypeDomainList
|
||||
<< PacketTypeDomainListRequest << PacketTypeStunResponse << PacketTypeDataServerConfirm
|
||||
<< PacketTypeDomainListRequest << PacketTypeDomainServerAuthRequest
|
||||
<< PacketTypeStunResponse << PacketTypeDataServerConfirm
|
||||
<< PacketTypeDataServerGet << PacketTypeDataServerPut << PacketTypeDataServerSend
|
||||
<< PacketTypeCreateAssignment << PacketTypeRequestAssignment;
|
||||
|
||||
|
@ -196,6 +195,18 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
|
|||
|
||||
break;
|
||||
}
|
||||
case PacketTypeDomainServerAuthRequest: {
|
||||
// the domain-server has asked us to auth via a data-server
|
||||
QDataStream authPacketStream(packet);
|
||||
authPacketStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
|
||||
QString authenticationHostname;
|
||||
authPacketStream >> authenticationHostname;
|
||||
|
||||
qDebug() << "Domain server wants us to auth with" << authenticationHostname;
|
||||
|
||||
break;
|
||||
}
|
||||
case PacketTypePing: {
|
||||
// send back a reply
|
||||
SharedNodePointer matchingNode = sendingNodeForPacket(packet);
|
||||
|
@ -288,10 +299,8 @@ void NodeList::reset() {
|
|||
clear();
|
||||
_numNoReplyDomainCheckIns = 0;
|
||||
|
||||
_nodeTypesOfInterest.clear();
|
||||
|
||||
// refresh the owner UUID
|
||||
_sessionUUID = QUuid::createUuid();
|
||||
// refresh the owner UUID to the NULL UUID
|
||||
_sessionUUID = QUuid();
|
||||
}
|
||||
|
||||
void NodeList::addNodeTypeToInterestSet(NodeType_t nodeTypeToAdd) {
|
||||
|
|
|
@ -88,11 +88,10 @@ public:
|
|||
int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; }
|
||||
DomainInfo& getDomainInfo() { return _domainInfo; }
|
||||
|
||||
void reset();
|
||||
|
||||
const NodeSet& getNodeInterestSet() const { return _nodeTypesOfInterest; }
|
||||
void addNodeTypeToInterestSet(NodeType_t nodeTypeToAdd);
|
||||
void addSetOfNodeTypesToNodeInterestSet(const NodeSet& setOfNodeTypes);
|
||||
void resetNodeInterestSet() { _nodeTypesOfInterest.clear(); }
|
||||
|
||||
int processDomainServerList(const QByteArray& packet);
|
||||
|
||||
|
@ -121,6 +120,8 @@ public:
|
|||
void loadData(QSettings* settings);
|
||||
void saveData(QSettings* settings);
|
||||
public slots:
|
||||
void reset();
|
||||
|
||||
void sendDomainServerCheckIn();
|
||||
void pingInactiveNodes();
|
||||
void removeSilentNodes();
|
||||
|
@ -130,20 +131,22 @@ signals:
|
|||
void uuidChanged(const QUuid& ownerUUID);
|
||||
void nodeAdded(SharedNodePointer);
|
||||
void nodeKilled(SharedNodePointer);
|
||||
|
||||
private:
|
||||
static NodeList* _sharedInstance;
|
||||
|
||||
NodeList(char ownerType, unsigned short int socketListenPort);
|
||||
~NodeList();
|
||||
NodeList(NodeList const&); // Don't implement, needed to avoid copies of singleton
|
||||
void operator=(NodeList const&); // Don't implement, needed to avoid copies of singleton
|
||||
void sendSTUNRequest();
|
||||
void processSTUNResponse(const QByteArray& packet);
|
||||
|
||||
qint64 NodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr,
|
||||
const QUuid& connectionSecret);
|
||||
qint64 writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr,
|
||||
const QUuid& connectionSecret);
|
||||
|
||||
NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill);
|
||||
|
||||
void clear();
|
||||
|
||||
NodeHash _nodeHash;
|
||||
QMutex _nodeHashMutex;
|
||||
|
@ -159,10 +162,7 @@ private:
|
|||
unsigned int _stunRequestsSinceSuccess;
|
||||
|
||||
void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode);
|
||||
void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode);
|
||||
void resetDomainData(char domainField[], const char* domainData);
|
||||
void domainLookup();
|
||||
void clear();
|
||||
void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode);
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__NodeList__) */
|
||||
|
|
Loading…
Reference in a new issue