From 6c08e2a4075082fb5aa3683a000a8da8d615eed6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 31 Mar 2014 15:06:58 -0700 Subject: [PATCH] add option for domain-server to enforce DTLS --- cmake/modules/FindGnuTLS.cmake | 2 +- domain-server/src/DomainServer.cpp | 161 +++++++++++++---------- domain-server/src/DomainServer.h | 3 +- interface/CMakeLists.txt | 4 +- libraries/shared/CMakeLists.txt | 4 +- libraries/shared/src/DomainInfo.cpp | 44 +++---- libraries/shared/src/DomainInfo.h | 20 +-- libraries/shared/src/NodeList.cpp | 175 +++++++------------------ libraries/shared/src/NodeList.h | 6 +- libraries/shared/src/PacketHeaders.cpp | 2 +- libraries/shared/src/PacketHeaders.h | 6 +- 11 files changed, 180 insertions(+), 247 deletions(-) diff --git a/cmake/modules/FindGnuTLS.cmake b/cmake/modules/FindGnuTLS.cmake index d09ba38fb7..f56a0db7d2 100644 --- a/cmake/modules/FindGnuTLS.cmake +++ b/cmake/modules/FindGnuTLS.cmake @@ -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 diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index df0935ba54..7584b00c8d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -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 parsedTypes(QSet() << 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(&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(matchingNode->getLinkedData())->parseJSONStatsPacket(receivedPacket); - } + } + + if (noisyMessage) { + lastNoisyMessage = timeNow; + } + } else if (requestType == PacketTypeNodeJsonStats) { + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); + if (matchingNode) { + reinterpret_cast(matchingNode->getLinkedData())->parseJSONStatsPacket(receivedPacket); } } } } -void DomainServer::readAvailableDTLSDatagrams() { - -} - QJsonObject DomainServer::jsonForSocket(const HifiSockAddr& socket) { QJsonObject socketJSON; diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index ba2b47a2e7..7ee6d7374e 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -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, diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index f991212a6e..18210668f6 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -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) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 3af7272cc1..6b4dafd8d4 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -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}") \ No newline at end of file diff --git a/libraries/shared/src/DomainInfo.cpp b/libraries/shared/src/DomainInfo.cpp index bed638bf59..648f658619 100644 --- a/libraries/shared/src/DomainInfo.cpp +++ b/libraries/shared/src/DomainInfo.cpp @@ -8,7 +8,7 @@ #include -#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."; +} \ No newline at end of file diff --git a/libraries/shared/src/DomainInfo.h b/libraries/shared/src/DomainInfo.h index da65525f9d..63c7dcbf6d 100644 --- a/libraries/shared/src/DomainInfo.h +++ b/libraries/shared/src/DomainInfo.h @@ -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; }; diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index b053db356e..bb4ff84865 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -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(); @@ -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 NON_VERIFIED_PACKETS = QSet() - << 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 diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 24281e3aa3..4f9b839779 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -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(); diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index c7518708ce..0035f053fb 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -52,7 +52,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeDomainList: case PacketTypeDomainListRequest: - return 1; + return 2; case PacketTypeCreateAssignment: case PacketTypeRequestAssignment: return 1; diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index a9bc5d3763..483fdb8a4d 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -57,9 +57,9 @@ enum PacketType { PacketTypeMetavoxelData, PacketTypeAvatarIdentity, PacketTypeAvatarBillboard, - PacketTypeDomainConnectRequest, - PacketTypeDomainServerAuthRequest, - PacketTypeNodeJsonStats + PacketTypeDomainConnectRequest, // RE-USABLE + PacketTypeDomainServerRequireDTLS, + PacketTypeNodeJsonStats, }; typedef char PacketVersion;