mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-04-10 18:41:57 +02:00
add option for domain-server to enforce DTLS
This commit is contained in:
parent
da30d21f6e
commit
6c08e2a407
11 changed files with 180 additions and 247 deletions
|
@ -5,7 +5,7 @@
|
|||
# Once done this will define
|
||||
#
|
||||
# GNUTLS_FOUND - system found GnuTLS
|
||||
# GNUTLS_INCLUDE_DIRS - the GnuTLS include directory
|
||||
# GNUTLS_INCLUDE_DIR - the GnuTLS include directory
|
||||
# GNUTLS_LIBRARY - Link this to use GnuTLS
|
||||
#
|
||||
# Created on 3/31/2014 by Stephen Birarda
|
||||
|
|
|
@ -180,6 +180,18 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
|||
domainServerPort = _argumentList.value(argumentIndex + 1).toUShort();
|
||||
}
|
||||
|
||||
unsigned short domainServerDTLSPort = -1;
|
||||
|
||||
if (_isUsingDTLS) {
|
||||
domainServerDTLSPort = DEFAULT_DOMAIN_SERVER_DTLS_PORT;
|
||||
|
||||
const QString CUSTOM_DTLS_PORT_OPTION = "--dtlsPort";
|
||||
|
||||
if ((argumentIndex = _argumentList.indexOf(CUSTOM_DTLS_PORT_OPTION)) != -1) {
|
||||
domainServerDTLSPort = _argumentList.value(argumentIndex + 1).toUShort();
|
||||
}
|
||||
}
|
||||
|
||||
QSet<Assignment::Type> parsedTypes(QSet<Assignment::Type>() << Assignment::AgentType);
|
||||
parseCommandLineTypeConfigs(_argumentList, parsedTypes);
|
||||
|
||||
|
@ -191,7 +203,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
|||
|
||||
populateDefaultStaticAssignmentsExcludingTypes(parsedTypes);
|
||||
|
||||
NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort);
|
||||
NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort, domainServerDTLSPort);
|
||||
|
||||
// create a random UUID for this session for the domain-server
|
||||
nodeList->setSessionUUID(sessionUUID);
|
||||
|
@ -519,10 +531,6 @@ void DomainServer::readAvailableDatagrams() {
|
|||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
HifiSockAddr senderSockAddr;
|
||||
|
||||
static QByteArray assignmentPacket = byteArrayWithPopulatedHeader(PacketTypeCreateAssignment);
|
||||
static int numAssignmentPacketHeaderBytes = assignmentPacket.size();
|
||||
|
||||
QByteArray receivedPacket;
|
||||
|
||||
while (nodeList->getNodeSocket().hasPendingDatagrams()) {
|
||||
|
@ -530,22 +538,42 @@ void DomainServer::readAvailableDatagrams() {
|
|||
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
|
||||
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
||||
|
||||
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
||||
PacketType requestType = packetTypeForPacket(receivedPacket);
|
||||
if (!_isUsingDTLS) {
|
||||
// not using DTLS, process datagram normally
|
||||
processDatagram(receivedPacket, senderSockAddr);
|
||||
} else {
|
||||
// we're using DTLS, so tell the sender to get back to us using DTLS
|
||||
static QByteArray dtlsRequiredPacket = byteArrayWithPopulatedHeader(PacketTypeDomainServerRequireDTLS);
|
||||
static int numBytesDTLSHeader = numBytesForPacketHeaderGivenPacketType(PacketTypeDomainServerRequireDTLS);
|
||||
|
||||
if (requestType == PacketTypeDomainConnectRequest) {
|
||||
QDataStream packetStream(receivedPacket);
|
||||
packetStream.skipRawData(numBytesForPacketHeader(receivedPacket));
|
||||
|
||||
quint8 hasRegistrationToken;
|
||||
packetStream >> hasRegistrationToken;
|
||||
|
||||
// we don't require authentication - add this node to our NodeList
|
||||
// and send back session UUID right away
|
||||
addNodeToNodeListAndConfirmConnection(receivedPacket, senderSockAddr);
|
||||
|
||||
} else if (requestType == PacketTypeDomainListRequest) {
|
||||
QUuid nodeUUID = uuidFromPacketHeader(receivedPacket);
|
||||
if (dtlsRequiredPacket.size() == numBytesDTLSHeader) {
|
||||
// pack the port that we accept DTLS traffic on
|
||||
unsigned short dtlsPort = nodeList->getDTLSSocket().localPort();
|
||||
dtlsRequiredPacket.replace(numBytesDTLSHeader, sizeof(dtlsPort), reinterpret_cast<const char*>(&dtlsPort));
|
||||
}
|
||||
|
||||
nodeList->getNodeSocket().writeDatagram(dtlsRequiredPacket, senderSockAddr.getAddress(), senderSockAddr.getPort());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::readAvailableDTLSDatagrams() {
|
||||
|
||||
}
|
||||
|
||||
void DomainServer::processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr) {
|
||||
NodeList* nodeList = NodeList::getInstance();
|
||||
|
||||
static QByteArray assignmentPacket = byteArrayWithPopulatedHeader(PacketTypeCreateAssignment);
|
||||
static int numAssignmentPacketHeaderBytes = assignmentPacket.size();
|
||||
|
||||
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
||||
PacketType requestType = packetTypeForPacket(receivedPacket);
|
||||
|
||||
if (requestType == PacketTypeDomainListRequest) {
|
||||
QUuid nodeUUID = uuidFromPacketHeader(receivedPacket);
|
||||
|
||||
if (!nodeUUID.isNull() && nodeList->nodeWithUUID(nodeUUID)) {
|
||||
NodeType_t throwawayNodeType;
|
||||
HifiSockAddr nodePublicAddress, nodeLocalAddress;
|
||||
|
||||
|
@ -553,69 +581,68 @@ void DomainServer::readAvailableDatagrams() {
|
|||
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 {
|
||||
// new node - add this node to our NodeList
|
||||
// and send back session UUID right away
|
||||
addNodeToNodeListAndConfirmConnection(receivedPacket, senderSockAddr);
|
||||
}
|
||||
|
||||
} else if (requestType == PacketTypeRequestAssignment) {
|
||||
|
||||
// construct the requested assignment from the packet data
|
||||
Assignment requestAssignment(receivedPacket);
|
||||
|
||||
// Suppress these for Assignment::AgentType to once per 5 seconds
|
||||
static quint64 lastNoisyMessage = usecTimestampNow();
|
||||
quint64 timeNow = usecTimestampNow();
|
||||
const quint64 NOISY_TIME_ELAPSED = 5 * USECS_PER_SECOND;
|
||||
bool noisyMessage = false;
|
||||
if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastNoisyMessage) > NOISY_TIME_ELAPSED) {
|
||||
qDebug() << "Received a request for assignment type" << requestAssignment.getType()
|
||||
<< "from" << senderSockAddr;
|
||||
noisyMessage = true;
|
||||
}
|
||||
|
||||
SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
|
||||
|
||||
if (assignmentToDeploy) {
|
||||
qDebug() << "Deploying assignment -" << *assignmentToDeploy.data() << "- to" << senderSockAddr;
|
||||
|
||||
} else if (requestType == PacketTypeRequestAssignment) {
|
||||
// give this assignment out, either the type matches or the requestor said they will take any
|
||||
assignmentPacket.resize(numAssignmentPacketHeaderBytes);
|
||||
|
||||
// construct the requested assignment from the packet data
|
||||
Assignment requestAssignment(receivedPacket);
|
||||
QDataStream assignmentStream(&assignmentPacket, QIODevice::Append);
|
||||
|
||||
// Suppress these for Assignment::AgentType to once per 5 seconds
|
||||
static quint64 lastNoisyMessage = usecTimestampNow();
|
||||
quint64 timeNow = usecTimestampNow();
|
||||
const quint64 NOISY_TIME_ELAPSED = 5 * USECS_PER_SECOND;
|
||||
bool noisyMessage = false;
|
||||
assignmentStream << *assignmentToDeploy.data();
|
||||
|
||||
nodeList->getNodeSocket().writeDatagram(assignmentPacket,
|
||||
senderSockAddr.getAddress(), senderSockAddr.getPort());
|
||||
} else {
|
||||
if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastNoisyMessage) > NOISY_TIME_ELAPSED) {
|
||||
qDebug() << "Received a request for assignment type" << requestAssignment.getType()
|
||||
qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
|
||||
<< "from" << senderSockAddr;
|
||||
noisyMessage = true;
|
||||
}
|
||||
|
||||
SharedAssignmentPointer assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
|
||||
|
||||
if (assignmentToDeploy) {
|
||||
qDebug() << "Deploying assignment -" << *assignmentToDeploy.data() << "- to" << senderSockAddr;
|
||||
|
||||
// give this assignment out, either the type matches or the requestor said they will take any
|
||||
assignmentPacket.resize(numAssignmentPacketHeaderBytes);
|
||||
|
||||
QDataStream assignmentStream(&assignmentPacket, QIODevice::Append);
|
||||
|
||||
assignmentStream << *assignmentToDeploy.data();
|
||||
|
||||
nodeList->getNodeSocket().writeDatagram(assignmentPacket,
|
||||
senderSockAddr.getAddress(), senderSockAddr.getPort());
|
||||
} else {
|
||||
if (requestAssignment.getType() != Assignment::AgentType || (timeNow - lastNoisyMessage) > NOISY_TIME_ELAPSED) {
|
||||
qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
|
||||
<< "from" << senderSockAddr;
|
||||
noisyMessage = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (noisyMessage) {
|
||||
lastNoisyMessage = timeNow;
|
||||
}
|
||||
} else if (requestType == PacketTypeNodeJsonStats) {
|
||||
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
|
||||
if (matchingNode) {
|
||||
reinterpret_cast<DomainServerNodeData*>(matchingNode->getLinkedData())->parseJSONStatsPacket(receivedPacket);
|
||||
}
|
||||
}
|
||||
|
||||
if (noisyMessage) {
|
||||
lastNoisyMessage = timeNow;
|
||||
}
|
||||
} else if (requestType == PacketTypeNodeJsonStats) {
|
||||
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
|
||||
if (matchingNode) {
|
||||
reinterpret_cast<DomainServerNodeData*>(matchingNode->getLinkedData())->parseJSONStatsPacket(receivedPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::readAvailableDTLSDatagrams() {
|
||||
|
||||
}
|
||||
|
||||
QJsonObject DomainServer::jsonForSocket(const HifiSockAddr& socket) {
|
||||
QJsonObject socketJSON;
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ private:
|
|||
bool optionallySetupDTLS();
|
||||
bool readX509KeyAndCertificate();
|
||||
|
||||
void requestAuthenticationFromPotentialNode(const HifiSockAddr& senderSockAddr);
|
||||
void processDatagram(const QByteArray& receivedPacket, const HifiSockAddr& senderSockAddr);
|
||||
|
||||
void addNodeToNodeListAndConfirmConnection(const QByteArray& packet, const HifiSockAddr& senderSockAddr,
|
||||
const QJsonObject& authJsonObject = QJsonObject());
|
||||
int parseNodeDataFromByteArray(NodeType_t& nodeType, HifiSockAddr& publicSockAddr,
|
||||
|
|
|
@ -67,6 +67,7 @@ foreach(EXTERNAL_SOURCE_SUBDIR ${EXTERNAL_SOURCE_SUBDIRS})
|
|||
endforeach(EXTERNAL_SOURCE_SUBDIR)
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Gui Multimedia Network OpenGL Script Svg WebKit WebKitWidgets Xml UiTools)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
# grab the ui files in resources/ui
|
||||
file (GLOB_RECURSE QT_UI_FILES ui/*.ui)
|
||||
|
@ -187,7 +188,7 @@ include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes"
|
|||
|
||||
# include external library headers
|
||||
# use system flag so warnings are supressed
|
||||
include_directories(SYSTEM "${FACESHIFT_INCLUDE_DIRS}")
|
||||
include_directories(SYSTEM "${FACESHIFT_INCLUDE_DIRS}" "${GNUTLS_INCLUDE_DIR}")
|
||||
|
||||
target_link_libraries(
|
||||
${TARGET_NAME}
|
||||
|
@ -195,6 +196,7 @@ target_link_libraries(
|
|||
"${ZLIB_LIBRARIES}"
|
||||
Qt5::Core Qt5::Gui Qt5::Multimedia Qt5::Network Qt5::OpenGL
|
||||
Qt5::Script Qt5::Svg Qt5::WebKit Qt5::WebKitWidgets Qt5::Xml Qt5::UiTools
|
||||
"${GNUTLS_LIBRARY}"
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
@ -11,6 +11,7 @@ set(TARGET_NAME shared)
|
|||
project(${TARGET_NAME})
|
||||
|
||||
find_package(Qt5 COMPONENTS Network Widgets Xml)
|
||||
find_package(GnuTLS REQUIRED)
|
||||
|
||||
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
|
||||
setup_hifi_library(${TARGET_NAME})
|
||||
|
@ -32,4 +33,5 @@ if (UNIX AND NOT APPLE)
|
|||
target_link_libraries(${TARGET_NAME} "${CMAKE_THREAD_LIBS_INIT}")
|
||||
endif (UNIX AND NOT APPLE)
|
||||
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets)
|
||||
include_directories("${GNUTLS_INCLUDE_DIR}")
|
||||
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets "${GNUTLS_LIBRARY}")
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include "AccountManager.h"
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
#include "DomainInfo.h"
|
||||
|
||||
|
@ -16,22 +16,14 @@ DomainInfo::DomainInfo() :
|
|||
_uuid(),
|
||||
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
|
||||
_assignmentUUID(),
|
||||
_connectionSecret(),
|
||||
_registrationToken(),
|
||||
_rootAuthenticationURL(),
|
||||
_publicKey(),
|
||||
_requiresDTLS(false),
|
||||
_isConnected(false)
|
||||
{
|
||||
// clear appropriate variables after a domain-server logout
|
||||
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete, this, &DomainInfo::logout);
|
||||
|
||||
}
|
||||
|
||||
void DomainInfo::clearConnectionInfo() {
|
||||
_uuid = QUuid();
|
||||
_connectionSecret = QUuid();
|
||||
_registrationToken = QByteArray();
|
||||
_rootAuthenticationURL = QUrl();
|
||||
_publicKey = QString();
|
||||
_isConnected = false;
|
||||
}
|
||||
|
||||
|
@ -39,13 +31,7 @@ void DomainInfo::reset() {
|
|||
clearConnectionInfo();
|
||||
_hostname = QString();
|
||||
_sockAddr.setAddress(QHostAddress::Null);
|
||||
}
|
||||
|
||||
void DomainInfo::parseAuthInformationFromJsonObject(const QJsonObject& jsonObject) {
|
||||
QJsonObject dataObject = jsonObject["data"].toObject();
|
||||
_connectionSecret = QUuid(dataObject["connection_secret"].toString());
|
||||
_registrationToken = QByteArray::fromHex(dataObject["registration_token"].toString().toUtf8());
|
||||
_publicKey = dataObject["public_key"].toString();
|
||||
_requiresDTLS = false;
|
||||
}
|
||||
|
||||
void DomainInfo::setSockAddr(const HifiSockAddr& sockAddr) {
|
||||
|
@ -114,13 +100,15 @@ void DomainInfo::setIsConnected(bool isConnected) {
|
|||
}
|
||||
}
|
||||
|
||||
void DomainInfo::logout() {
|
||||
// clear any information related to auth for this domain, assuming it had requested auth
|
||||
if (!_rootAuthenticationURL.isEmpty()) {
|
||||
_rootAuthenticationURL = QUrl();
|
||||
_connectionSecret = QUuid();
|
||||
_registrationToken = QByteArray();
|
||||
_publicKey = QString();
|
||||
_isConnected = false;
|
||||
}
|
||||
}
|
||||
void DomainInfo::parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket) {
|
||||
// figure out the port that the DS wants us to use for us to talk to them with DTLS
|
||||
int numBytesPacketHeader = numBytesForPacketHeader(dtlsRequirementPacket);
|
||||
|
||||
unsigned short dtlsPort = 0;
|
||||
memcpy(&dtlsPort, dtlsRequirementPacket.data() + numBytesPacketHeader, sizeof(dtlsPort));
|
||||
|
||||
_sockAddr.setPort(dtlsPort);
|
||||
_requiresDTLS = true;
|
||||
|
||||
qDebug() << "domain-server DTLS port changed to" << dtlsPort << "- DTLS enabled.";
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
const QString DEFAULT_DOMAIN_HOSTNAME = "alpha.highfidelity.io";
|
||||
const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102;
|
||||
const unsigned short DEFAULT_DOMAIN_SERVER_DTLS_PORT = 40103;
|
||||
|
||||
class DomainInfo : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -26,8 +27,6 @@ public:
|
|||
|
||||
void clearConnectionInfo();
|
||||
|
||||
void parseAuthInformationFromJsonObject(const QJsonObject& jsonObject);
|
||||
|
||||
const QUuid& getUUID() const { return _uuid; }
|
||||
void setUUID(const QUuid& uuid) { _uuid = uuid; }
|
||||
|
||||
|
@ -45,21 +44,13 @@ public:
|
|||
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; }
|
||||
|
||||
const QByteArray& getRegistrationToken() const { return _registrationToken; }
|
||||
|
||||
const QUrl& getRootAuthenticationURL() const { return _rootAuthenticationURL; }
|
||||
void setRootAuthenticationURL(const QUrl& rootAuthenticationURL) { _rootAuthenticationURL = rootAuthenticationURL; }
|
||||
|
||||
bool isConnected() const { return _isConnected; }
|
||||
void setIsConnected(bool isConnected);
|
||||
|
||||
void parseDTLSRequirementPacket(const QByteArray& dtlsRequirementPacket);
|
||||
|
||||
private slots:
|
||||
void completedHostnameLookup(const QHostInfo& hostInfo);
|
||||
|
||||
void logout();
|
||||
signals:
|
||||
void hostnameChanged(const QString& hostname);
|
||||
void connectedToDomain(const QString& hostname);
|
||||
|
@ -70,10 +61,7 @@ private:
|
|||
QString _hostname;
|
||||
HifiSockAddr _sockAddr;
|
||||
QUuid _assignmentUUID;
|
||||
QUuid _connectionSecret;
|
||||
QByteArray _registrationToken;
|
||||
QUrl _rootAuthenticationURL;
|
||||
QString _publicKey;
|
||||
bool _requiresDTLS;
|
||||
bool _isConnected;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,11 +34,11 @@ const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data-web.highfidelity.io");
|
|||
|
||||
NodeList* NodeList::_sharedInstance = NULL;
|
||||
|
||||
NodeList* NodeList::createInstance(char ownerType, unsigned short int socketListenPort) {
|
||||
NodeList* NodeList::createInstance(char ownerType, unsigned short socketListenPort, unsigned short dtlsPort) {
|
||||
if (!_sharedInstance) {
|
||||
NodeType::init();
|
||||
|
||||
_sharedInstance = new NodeList(ownerType, socketListenPort);
|
||||
_sharedInstance = new NodeList(ownerType, socketListenPort, dtlsPort);
|
||||
|
||||
// register the SharedNodePointer meta-type for signals/slots
|
||||
qRegisterMetaType<SharedNodePointer>();
|
||||
|
@ -58,7 +58,7 @@ NodeList* NodeList::getInstance() {
|
|||
}
|
||||
|
||||
|
||||
NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
|
||||
NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned short dtlsListenPort) :
|
||||
_nodeHash(),
|
||||
_nodeHashMutex(QMutex::Recursive),
|
||||
_nodeSocket(this),
|
||||
|
@ -74,9 +74,15 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
|
|||
_numCollectedBytes(0),
|
||||
_packetStatTimer()
|
||||
{
|
||||
_nodeSocket.bind(QHostAddress::AnyIPv4, newSocketListenPort);
|
||||
_nodeSocket.bind(QHostAddress::AnyIPv4, socketListenPort);
|
||||
qDebug() << "NodeList socket is listening on" << _nodeSocket.localPort();
|
||||
|
||||
if (dtlsListenPort > 0) {
|
||||
// we have a specfic DTLS port, bind that socket now
|
||||
_dtlsSocket.bind(QHostAddress::AnyIPv4, dtlsListenPort);
|
||||
qDebug() << "NodeList DTLS socket is listening on" << _dtlsSocket.localPort();
|
||||
}
|
||||
|
||||
// clear our NodeList when the domain changes
|
||||
connect(&_domainInfo, &DomainInfo::hostnameChanged, this, &NodeList::reset);
|
||||
|
||||
|
@ -141,7 +147,7 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
|
|||
}
|
||||
|
||||
const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
|
||||
<< PacketTypeDomainServerAuthRequest << PacketTypeDomainConnectRequest
|
||||
<< PacketTypeDomainServerRequireDTLS << PacketTypeDomainList << PacketTypeDomainListRequest
|
||||
<< PacketTypeStunResponse << PacketTypeDataServerConfirm
|
||||
<< PacketTypeDataServerGet << PacketTypeDataServerPut << PacketTypeDataServerSend
|
||||
<< PacketTypeCreateAssignment << PacketTypeRequestAssignment;
|
||||
|
@ -158,31 +164,6 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
|
|||
<< uuidFromPacketHeader(packet);
|
||||
}
|
||||
} else {
|
||||
if (checkType == PacketTypeDomainList) {
|
||||
|
||||
if (_domainInfo.getRootAuthenticationURL().isEmpty() && _domainInfo.getUUID().isNull()) {
|
||||
// if this is a domain-server that doesn't require auth,
|
||||
// pull the UUID from this packet and set it as our domain-server UUID
|
||||
_domainInfo.setUUID(uuidFromPacketHeader(packet));
|
||||
|
||||
// we also know this domain-server requires no authentication
|
||||
// so set the account manager root URL to the default one
|
||||
AccountManager::getInstance().setAuthURL(DEFAULT_NODE_AUTH_URL);
|
||||
}
|
||||
|
||||
if (_domainInfo.getUUID() == uuidFromPacketHeader(packet)) {
|
||||
if (hashForPacketAndConnectionUUID(packet, _domainInfo.getConnectionSecret()) == hashFromPacketHeader(packet)) {
|
||||
// this is a packet from the domain-server (PacketTypeDomainServerListRequest)
|
||||
// and the sender UUID matches the UUID we expect for the domain
|
||||
return true;
|
||||
} else {
|
||||
// this is a packet from the domain-server but there is a hash mismatch
|
||||
qDebug() << "Packet hash mismatch on" << checkType << "from domain-server at" << _domainInfo.getHostname();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Packet of type" << checkType << "received from unknown node with UUID"
|
||||
<< uuidFromPacketHeader(packet);
|
||||
}
|
||||
|
@ -246,7 +227,7 @@ qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) {
|
|||
|
||||
statsPacketStream << statsObject.toVariantMap();
|
||||
|
||||
return writeDatagram(statsPacket, _domainInfo.getSockAddr(), _domainInfo.getConnectionSecret());
|
||||
return writeDatagram(statsPacket, _domainInfo.getSockAddr(), QUuid());
|
||||
}
|
||||
|
||||
void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) {
|
||||
|
@ -290,10 +271,8 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
|
|||
processDomainServerList(packet);
|
||||
break;
|
||||
}
|
||||
case PacketTypeDomainServerAuthRequest: {
|
||||
// the domain-server has asked us to auth via a data-server
|
||||
processDomainServerAuthRequest(packet);
|
||||
|
||||
case PacketTypeDomainServerRequireDTLS: {
|
||||
_domainInfo.parseDTLSRequirementPacket(packet);
|
||||
break;
|
||||
}
|
||||
case PacketTypePing: {
|
||||
|
@ -590,61 +569,44 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
// send a STUN request to figure it out
|
||||
sendSTUNRequest();
|
||||
} else if (!_domainInfo.getIP().isNull()) {
|
||||
if (_domainInfo.getRootAuthenticationURL().isEmpty()
|
||||
|| !_sessionUUID.isNull()
|
||||
|| !_domainInfo.getRegistrationToken().isEmpty() ) {
|
||||
// construct the DS check in packet
|
||||
|
||||
PacketType domainPacketType = _sessionUUID.isNull() ? PacketTypeDomainConnectRequest : PacketTypeDomainListRequest;
|
||||
|
||||
QUuid packetUUID = (domainPacketType == PacketTypeDomainListRequest)
|
||||
? _sessionUUID : _domainInfo.getAssignmentUUID();
|
||||
|
||||
QByteArray domainServerPacket = byteArrayWithPopulatedHeader(domainPacketType, packetUUID);
|
||||
QDataStream packetStream(&domainServerPacket, QIODevice::Append);
|
||||
|
||||
if (domainPacketType == PacketTypeDomainConnectRequest) {
|
||||
// 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
|
||||
packetStream << _ownerType << _publicSockAddr
|
||||
<< HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())
|
||||
<< (quint8) _nodeTypesOfInterest.size();
|
||||
|
||||
// copy over the bytes for node types of interest, if required
|
||||
foreach (NodeType_t nodeTypeOfInterest, _nodeTypesOfInterest) {
|
||||
packetStream << nodeTypeOfInterest;
|
||||
}
|
||||
|
||||
writeDatagram(domainServerPacket, _domainInfo.getSockAddr(), _domainInfo.getConnectionSecret());
|
||||
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
|
||||
static unsigned int numDomainCheckins = 0;
|
||||
|
||||
// send a STUN request every Nth domain server check in so we update our public socket, if required
|
||||
if (numDomainCheckins++ % NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST == 0) {
|
||||
sendSTUNRequest();
|
||||
}
|
||||
|
||||
if (_numNoReplyDomainCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
|
||||
// so emit our signal that indicates that
|
||||
emit limitOfSilentDomainCheckInsReached();
|
||||
}
|
||||
|
||||
// increment the count of un-replied check-ins
|
||||
_numNoReplyDomainCheckIns++;
|
||||
} else if (AccountManager::getInstance().hasValidAccessToken()) {
|
||||
// we have an access token we can use for the authentication server the domain-server requested
|
||||
// so ask that server to provide us with information to connect to the domain-server
|
||||
requestAuthForDomainServer();
|
||||
// construct the DS check in packet
|
||||
|
||||
PacketType domainPacketType = _sessionUUID.isNull() ? PacketTypeDomainConnectRequest : PacketTypeDomainListRequest;
|
||||
|
||||
QUuid packetUUID = (domainPacketType == PacketTypeDomainListRequest)
|
||||
? _sessionUUID : _domainInfo.getAssignmentUUID();
|
||||
|
||||
QByteArray domainServerPacket = byteArrayWithPopulatedHeader(domainPacketType, packetUUID);
|
||||
QDataStream packetStream(&domainServerPacket, QIODevice::Append);
|
||||
|
||||
|
||||
// pack our data to send to the domain-server
|
||||
packetStream << _ownerType << _publicSockAddr
|
||||
<< HifiSockAddr(QHostAddress(getHostOrderLocalAddress()), _nodeSocket.localPort())
|
||||
<< (quint8) _nodeTypesOfInterest.size();
|
||||
|
||||
// copy over the bytes for node types of interest, if required
|
||||
foreach (NodeType_t nodeTypeOfInterest, _nodeTypesOfInterest) {
|
||||
packetStream << nodeTypeOfInterest;
|
||||
}
|
||||
|
||||
writeDatagram(domainServerPacket, _domainInfo.getSockAddr(), QUuid());
|
||||
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
|
||||
static unsigned int numDomainCheckins = 0;
|
||||
|
||||
// send a STUN request every Nth domain server check in so we update our public socket, if required
|
||||
if (numDomainCheckins++ % NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST == 0) {
|
||||
sendSTUNRequest();
|
||||
}
|
||||
|
||||
if (_numNoReplyDomainCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
|
||||
// so emit our signal that indicates that
|
||||
emit limitOfSilentDomainCheckInsReached();
|
||||
}
|
||||
|
||||
// increment the count of un-replied check-ins
|
||||
_numNoReplyDomainCheckIns++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,41 +669,6 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
|
|||
return readNodes;
|
||||
}
|
||||
|
||||
void NodeList::domainServerAuthReply(const QJsonObject& jsonObject) {
|
||||
_domainInfo.parseAuthInformationFromJsonObject(jsonObject);
|
||||
}
|
||||
|
||||
void NodeList::requestAuthForDomainServer() {
|
||||
JSONCallbackParameters callbackParams;
|
||||
callbackParams.jsonCallbackReceiver = this;
|
||||
callbackParams.jsonCallbackMethod = "domainServerAuthReply";
|
||||
|
||||
AccountManager::getInstance().authenticatedRequest("/api/v1/domains/"
|
||||
+ uuidStringWithoutCurlyBraces(_domainInfo.getUUID()) + "/auth.json",
|
||||
QNetworkAccessManager::GetOperation,
|
||||
callbackParams);
|
||||
}
|
||||
|
||||
void NodeList::processDomainServerAuthRequest(const QByteArray& packet) {
|
||||
QDataStream authPacketStream(packet);
|
||||
authPacketStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
|
||||
_domainInfo.setUUID(uuidFromPacketHeader(packet));
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
|
||||
// grab the hostname this domain-server wants us to authenticate with
|
||||
QUrl authenticationRootURL;
|
||||
authPacketStream >> authenticationRootURL;
|
||||
|
||||
accountManager.setAuthURL(authenticationRootURL);
|
||||
_domainInfo.setRootAuthenticationURL(authenticationRootURL);
|
||||
|
||||
if (AccountManager::getInstance().checkAndSignalForAccessToken()) {
|
||||
// request a domain-server auth
|
||||
requestAuthForDomainServer();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::sendAssignment(Assignment& assignment) {
|
||||
|
||||
PacketType assignmentPacketType = assignment.getCommand() == Assignment::CreateCommand
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace PingType {
|
|||
class NodeList : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static NodeList* createInstance(char ownerType, unsigned short int socketListenPort = 0);
|
||||
static NodeList* createInstance(char ownerType, unsigned short socketListenPort = 0, unsigned short dtlsPort = 0);
|
||||
static NodeList* getInstance();
|
||||
NodeType_t getOwnerType() const { return _ownerType; }
|
||||
void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; }
|
||||
|
@ -140,12 +140,10 @@ signals:
|
|||
void nodeAdded(SharedNodePointer);
|
||||
void nodeKilled(SharedNodePointer);
|
||||
void limitOfSilentDomainCheckInsReached();
|
||||
private slots:
|
||||
void domainServerAuthReply(const QJsonObject& jsonObject);
|
||||
private:
|
||||
static NodeList* _sharedInstance;
|
||||
|
||||
NodeList(char ownerType, unsigned short int socketListenPort);
|
||||
NodeList(char ownerType, unsigned short socketListenPort, unsigned short dtlsListenPort);
|
||||
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();
|
||||
|
|
|
@ -52,7 +52,7 @@ PacketVersion versionForPacketType(PacketType type) {
|
|||
return 1;
|
||||
case PacketTypeDomainList:
|
||||
case PacketTypeDomainListRequest:
|
||||
return 1;
|
||||
return 2;
|
||||
case PacketTypeCreateAssignment:
|
||||
case PacketTypeRequestAssignment:
|
||||
return 1;
|
||||
|
|
|
@ -57,9 +57,9 @@ enum PacketType {
|
|||
PacketTypeMetavoxelData,
|
||||
PacketTypeAvatarIdentity,
|
||||
PacketTypeAvatarBillboard,
|
||||
PacketTypeDomainConnectRequest,
|
||||
PacketTypeDomainServerAuthRequest,
|
||||
PacketTypeNodeJsonStats
|
||||
PacketTypeDomainConnectRequest, // RE-USABLE
|
||||
PacketTypeDomainServerRequireDTLS,
|
||||
PacketTypeNodeJsonStats,
|
||||
};
|
||||
|
||||
typedef char PacketVersion;
|
||||
|
|
Loading…
Reference in a new issue