From 4b3183d820b5cf9eddcffda9724f0a3c7cba42d3 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 19 Feb 2015 17:44:06 -0800 Subject: [PATCH] AssignmentClients accept an id on the command-line. AssignmentClientMonitor now has a NodeList. It stores its local port in shared memory, like the DomainServer does. As it spawns children, it addes Nodes to the NodeList for each one. The children send status updates to the Monitor. The Monitor will notice if there are no spares and fork another child. --- assignment-client/src/AssignmentClient.cpp | 77 +++++++--- assignment-client/src/AssignmentClient.h | 12 +- assignment-client/src/AssignmentClientApp.cpp | 84 ++++++++++ assignment-client/src/AssignmentClientApp.h | 19 +++ .../src/AssignmentClientMonitor.cpp | 143 +++++++++++++++++- .../src/AssignmentClientMonitor.h | 21 ++- assignment-client/src/main.cpp | 30 +--- domain-server/src/DomainServer.cpp | 16 +- libraries/networking/src/LimitedNodeList.cpp | 38 +++++ libraries/networking/src/LimitedNodeList.h | 10 ++ libraries/networking/src/NodeList.cpp | 8 +- libraries/networking/src/NodeList.h | 1 + libraries/networking/src/PacketHeaders.cpp | 3 + libraries/networking/src/PacketHeaders.h | 4 +- 14 files changed, 389 insertions(+), 77 deletions(-) create mode 100644 assignment-client/src/AssignmentClientApp.cpp create mode 100644 assignment-client/src/AssignmentClientApp.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index bf67d4d597..9098a258e7 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -40,10 +41,11 @@ SharedAssignmentPointer AssignmentClient::_currentAssignment; int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); -AssignmentClient::AssignmentClient(int &argc, char **argv) : +AssignmentClient::AssignmentClient(int &argc, char **argv, QUuid nodeUUID) : QCoreApplication(argc, argv), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), - _localASPortSharedMem(NULL) + _localASPortSharedMem(NULL), + _localACMPortSharedMem(NULL) { LogUtils::init(); @@ -57,6 +59,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : auto addressManager = DependencyManager::set(); auto nodeList = DependencyManager::set(NodeType::Unassigned); auto avatarHashMap = DependencyManager::set(); + + nodeList->setSessionUUID(nodeUUID); // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us #ifdef _WIN32 @@ -123,9 +127,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required qDebug() << "Waiting for assignment -" << _requestAssignment; - QTimer* timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); - timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); + connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); + _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS); // connect our readPendingDatagrams method to the readyRead() signal of the socket connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); @@ -136,6 +139,36 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) : // Create Singleton objects on main thread NetworkAccessManager::getInstance(); + + setUpStatsToMonitor(); +} + + +void AssignmentClient::setUpStatsToMonitor() { + // Figure out the address to send out stats to + quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT; + auto nodeList = DependencyManager::get(); + + nodeList->getLocalPortFromSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, + _localACMPortSharedMem, localMonitorServerPort); + _assignmentClientMonitorSocket = HifiSockAddr(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME, localMonitorServerPort, true); + + // send a stats packet every 1 seconds + connect(&_statsTimerACM, &QTimer::timeout, this, &AssignmentClient::sendStatsPacketToACM); + _statsTimerACM.start(1000); +} + +void AssignmentClient::sendStatsPacketToACM() { + // tell the assignment client monitor what this assignment client is doing (if anything) + QJsonObject statsObject; + auto nodeList = DependencyManager::get(); + + if (_currentAssignment) { + statsObject["assignment_type"] = _currentAssignment->getTypeName(); + } else { + statsObject["assignment_type"] = "none"; + } + nodeList->sendStats(statsObject, _assignmentClientMonitorSocket); } void AssignmentClient::sendAssignmentRequest() { @@ -145,34 +178,22 @@ void AssignmentClient::sendAssignmentRequest() { if (_assignmentServerHostname == "localhost") { // we want to check again for the local domain-server port in case the DS has restarted - if (!_localASPortSharedMem) { - _localASPortSharedMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - - if (!_localASPortSharedMem->attach(QSharedMemory::ReadOnly)) { - qWarning() << "Could not attach to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY - << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); - } - } - - if (_localASPortSharedMem->isAttached()) { - _localASPortSharedMem->lock(); - - quint16 localAssignmentServerPort; - memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); - - _localASPortSharedMem->unlock(); - + quint16 localAssignmentServerPort; + if (nodeList->getLocalPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem, + localAssignmentServerPort)) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { qDebug() << "Port for local assignment server read from shared memory is" - << localAssignmentServerPort; + << localAssignmentServerPort; _assignmentServerSocket.setPort(localAssignmentServerPort); nodeList->setAssignmentServerSocket(_assignmentServerSocket); } } - + else { + qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort(); + } } - + nodeList->sendAssignment(_requestAssignment); } } @@ -227,10 +248,16 @@ void AssignmentClient::readPendingDatagrams() { } else { qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; } + } else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) { + qDebug() << "Network told me to exit"; + quit(); } else { + qDebug() << "punt"; // have the NodeList attempt to handle it nodeList->processNodeData(senderSockAddr, receivedPacket); } + } else { + qDebug() << "packetVersionAndHashMatch said no"; } } } diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 053458f136..7f0f16e6d6 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -21,7 +21,7 @@ class QSharedMemory; class AssignmentClient : public QCoreApplication { Q_OBJECT public: - AssignmentClient(int &argc, char **argv); + AssignmentClient(int &argc, char **argv, QUuid nodeUUID); static const SharedAssignmentPointer& getCurrentAssignment() { return _currentAssignment; } private slots: @@ -29,13 +29,21 @@ private slots: void readPendingDatagrams(); void assignmentCompleted(); void handleAuthenticationRequest(); + void sendStatsPacketToACM(); private: + void setUpStatsToMonitor(); Assignment _requestAssignment; static SharedAssignmentPointer _currentAssignment; QString _assignmentServerHostname; HifiSockAddr _assignmentServerSocket; - QSharedMemory* _localASPortSharedMem; + QSharedMemory* _localASPortSharedMem; // memory shared with domain server + QSharedMemory* _localACMPortSharedMem; // memory shared with assignment client monitor + QTimer _requestTimer; // timer for requesting and assignment + QTimer _statsTimerACM; // timer for sending stats to assignment client monitor + + protected: + HifiSockAddr _assignmentClientMonitorSocket; }; #endif // hifi_AssignmentClient_h diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp new file mode 100644 index 0000000000..4541732e2c --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -0,0 +1,84 @@ +// +// AssignmentClientapp.cpp +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include + +#include "Assignment.h" +#include "AssignmentClient.h" +#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" + + +AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : + QApplication(argc, argv) +{ +# ifndef WIN32 + setvbuf(stdout, NULL, _IOLBF, 0); +# endif + + // use the verbose message handler in Logging + qInstallMessageHandler(LogHandler::verboseMessageHandler); + + // parse command-line + QCommandLineParser parser; + parser.setApplicationDescription("High Fidelity Assignment Client"); + parser.addHelpOption(); + + const QCommandLineOption helpOption = parser.addHelpOption(); + + const QCommandLineOption numChildsOption("n", "number of children to fork", "child-count"); + parser.addOption(numChildsOption); + + const QCommandLineOption idOption("i", "assignment client id", "uuid"); + parser.addOption(idOption); + + if (!parser.parse(QCoreApplication::arguments())) { + qCritical() << parser.errorText() << endl; + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(helpOption)) { + parser.showHelp(); + Q_UNREACHABLE(); + } + + if (parser.isSet(numChildsOption) && parser.isSet(idOption)) { + qCritical() << "using both -i and -n doesn't make sense."; + parser.showHelp(); + Q_UNREACHABLE(); + } + + unsigned int numForks = 0; + if (parser.isSet(numChildsOption)) { + numForks = parser.value(numChildsOption).toInt(); + } + + QUuid nodeUUID = QUuid::createUuid(); + if (parser.isSet(idOption)) { + nodeUUID = QUuid(parser.value(idOption)); + } + + if (numForks) { + AssignmentClientMonitor monitor(argc, argv, numForks); + monitor.exec(); + } else { + AssignmentClient client(argc, argv, nodeUUID); + client.exec(); + } +} + + +AssignmentClientApp::~AssignmentClientApp() { +} diff --git a/assignment-client/src/AssignmentClientApp.h b/assignment-client/src/AssignmentClientApp.h new file mode 100644 index 0000000000..6c91fa06a3 --- /dev/null +++ b/assignment-client/src/AssignmentClientApp.h @@ -0,0 +1,19 @@ +// +// AssignmentClientapp.h +// assignment-client/src +// +// Created by Seth Alves on 2/19/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +class AssignmentClientApp : public QApplication { + Q_OBJECT +public: + AssignmentClientApp(int argc, char* argv[]); + ~AssignmentClientApp(); +}; diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 45e1f56d53..831d50c134 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -14,13 +14,18 @@ #include #include + +#include // XXX need this? + + #include "AssignmentClientMonitor.h" +#include "PacketHeaders.h" const char* NUM_FORKS_PARAMETER = "-n"; const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; -AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) : +AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks) : QCoreApplication(argc, argv) { // start the Logging class with the parent's target name @@ -41,17 +46,38 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num // this removes both the "-n" parameter and the number of forks passed _childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex); + + + // create a NodeList so we can receive stats from children + DependencyManager::registerInheritance(); + auto addressManager = DependencyManager::set(); + // auto nodeList = DependencyManager::set(NodeType::Unassigned); + auto nodeList = DependencyManager::set(DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT, + DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT); + + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClientMonitor::readPendingDatagrams); + + nodeList->putLocalPortIntoSharedMemory(ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY, this); // use QProcess to fork off a process for each of the child assignment clients - for (int i = 0; i < numAssignmentClientForks; i++) { + for (unsigned int i = 0; i < numAssignmentClientForks; i++) { spawnChildClient(); } + + connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares())); + _checkSparesTimer.start(5000); } AssignmentClientMonitor::~AssignmentClientMonitor() { stopChildProcesses(); + + foreach (AssignmentClientChildData* childStatus, _childStatus) { + delete childStatus; + } } + + void AssignmentClientMonitor::stopChildProcesses() { QList >::Iterator it = _childProcesses.begin(); @@ -74,11 +100,18 @@ void AssignmentClientMonitor::spawnChildClient() { QProcess *assignmentClient = new QProcess(this); _childProcesses.append(QPointer(assignmentClient)); + + QUuid childUUID = QUuid::createUuid(); + + // create a Node for this child. this is done so we can idenitfy packets from unknown children + DependencyManager::get()->addOrUpdateNode + (childUUID, NodeType::Unassigned, HifiSockAddr("localhost", 0), HifiSockAddr("localhost", 0), false); // make sure that the output from the child process appears in our output assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); - - assignmentClient->start(applicationFilePath(), _childArguments); + + QStringList idArgs = QStringList() << "-i" << childUUID.toString(); + assignmentClient->start(applicationFilePath(), _childArguments + idArgs); // link the child processes' finished slot to our childProcessFinished slot connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this, @@ -96,3 +129,105 @@ void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitS spawnChildClient(); } + + + +void AssignmentClientMonitor::checkSpares() { + qDebug() << "check spares:"; + + QString aSpareId = ""; + unsigned int spareCount = 0; + + QHash::const_iterator i = _childStatus.constBegin(); + while (i != _childStatus.constEnd()) { + qDebug() << " " << i.key() << i.value()->getChildType(); + if (i.value()->getChildType() == "none") { + spareCount ++; + aSpareId = i.key(); + } + ++i; + } + + qDebug() << "spare count is" << spareCount; + + if (spareCount < 1) { + qDebug() << "FORK"; + spawnChildClient(); + } + + if (spareCount > 1) { + qDebug() << "KILL"; + } +} + + + + +void AssignmentClientMonitor::readPendingDatagrams() { + auto nodeList = DependencyManager::get(); + + QByteArray receivedPacket; + HifiSockAddr senderSockAddr; + + while (nodeList->getNodeSocket().hasPendingDatagrams()) { + receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize()); + nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(), + senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer()); + + if (nodeList->packetVersionAndHashMatch(receivedPacket)) { + if (packetTypeForPacket(receivedPacket) == PacketTypeNodeJsonStats) { + + QUuid packetUUID = uuidFromPacketHeader(receivedPacket); + // qDebug() << "packetUUID = " << packetUUID; + + SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket); + if (!matchingNode) { + qDebug() << "got packet from unknown child, id =" << packetUUID.toString(); + // tell unknown assignment-client child to exit. + QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode); + nodeList->writeUnverifiedDatagram(diePacket, senderSockAddr); + } + + if (matchingNode) { + // update our records about how to reach this child + matchingNode->setLocalSocket(senderSockAddr); + + // push past the packet header + QDataStream packetStream(receivedPacket); + packetStream.skipRawData(numBytesForPacketHeader(receivedPacket)); + + QVariantMap unpackedVariantMap; + + packetStream >> unpackedVariantMap; + + QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap); + + // qDebug() << "ACM got stats packet, id =" << packetUUID.toString() + // << "type =" << unpackedStatsJSON["assignment_type"]; + + QString key(QString(packetUUID.toString())); + if (_childStatus.contains(key)) { + delete _childStatus[ key ]; + } + + QString childType = unpackedStatsJSON["assignment_type"].toString(); + auto childStatus = new AssignmentClientChildData(childType); + _childStatus[ key ] = childStatus; + + } + } else { + // have the NodeList attempt to handle it + nodeList->processNodeData(senderSockAddr, receivedPacket); + } + } + } +} + + +AssignmentClientChildData::AssignmentClientChildData(QString childType) { + _childType = childType; +} + + +AssignmentClientChildData::~AssignmentClientChildData() { +} diff --git a/assignment-client/src/AssignmentClientMonitor.h b/assignment-client/src/AssignmentClientMonitor.h index 9a7bca9cb3..75d2296533 100644 --- a/assignment-client/src/AssignmentClientMonitor.h +++ b/assignment-client/src/AssignmentClientMonitor.h @@ -20,20 +20,39 @@ extern const char* NUM_FORKS_PARAMETER; +class AssignmentClientChildData { + public: + AssignmentClientChildData(QString childType); + ~AssignmentClientChildData(); + + QString getChildType() { return _childType; } + + private: + QString _childType; + // ... timestamp +}; + + class AssignmentClientMonitor : public QCoreApplication { Q_OBJECT public: - AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); + AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks); ~AssignmentClientMonitor(); void stopChildProcesses(); private slots: void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void readPendingDatagrams(); + void checkSpares(); + private: void spawnChildClient(); QList > _childProcesses; QStringList _childArguments; + QHash _childStatus; + + QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children }; #endif // hifi_AssignmentClientMonitor_h diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 3bf6990a74..81a12526bf 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -9,34 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include "Assignment.h" -#include "AssignmentClient.h" -#include "AssignmentClientMonitor.h" +#include "AssignmentClientApp.h" int main(int argc, char* argv[]) { -#ifndef WIN32 - setvbuf(stdout, NULL, _IOLBF, 0); -#endif - - // use the verbose message handler in Logging - qInstallMessageHandler(LogHandler::verboseMessageHandler); - - const char* numForksString = getCmdOption(argc, (const char**)argv, NUM_FORKS_PARAMETER); - - int numForks = 0; - - if (numForksString) { - numForks = atoi(numForksString); - } - - if (numForks) { - AssignmentClientMonitor monitor(argc, argv, numForks); - return monitor.exec(); - } else { - AssignmentClient client(argc, argv); - return client.exec(); - } + AssignmentClientApp app(argc, argv); + return 0; } diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index f84722a438..30d6dd4348 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -244,21 +244,9 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) { populateStaticScriptedAssignmentsFromSettings(); auto nodeList = DependencyManager::set(domainServerPort, domainServerDTLSPort); - + // no matter the local port, save it to shared mem so that local assignment clients can ask what it is - QSharedMemory* sharedPortMem = new QSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); - quint16 localPort = nodeList->getNodeSocket().localPort(); - - // attempt to create the shared memory segment - if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { - sharedPortMem->lock(); - memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); - sharedPortMem->unlock(); - - qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY; - } else { - qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; - } + nodeList->putLocalPortIntoSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, this); // set our LimitedNodeList UUID to match the UUID from our config // nodes will currently use this to add resources to data-web that relate to our domain diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index c8c454ff14..075fd5a44b 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -669,3 +669,41 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); } + +void LimitedNodeList::putLocalPortIntoSharedMemory(const QString key, QObject* parent) { + // save our local port to shared memory so that assignment client children know how to talk to this parent + QSharedMemory* sharedPortMem = new QSharedMemory(key, parent); + quint16 localPort = getNodeSocket().localPort(); + + // attempt to create the shared memory segment + if (sharedPortMem->create(sizeof(localPort)) || sharedPortMem->attach()) { + sharedPortMem->lock(); + memcpy(sharedPortMem->data(), &localPort, sizeof(localPort)); + sharedPortMem->unlock(); + + qDebug() << "Wrote local listening port" << localPort << "to shared memory at key" << key; + } else { + qWarning() << "Failed to create and attach to shared memory to share local port with assignment-client children."; + } +} + + +bool LimitedNodeList::getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, + quint16& localPort) { + if (!sharedMem) { + sharedMem = new QSharedMemory(key, this); + + if (!sharedMem->attach(QSharedMemory::ReadOnly)) { + qWarning() << "Could not attach to shared memory at key" << key; + } + } + + if (sharedMem->isAttached()) { + sharedMem->lock(); + memcpy(&localPort, sharedMem->data(), sizeof(localPort)); + sharedMem->unlock(); + return true; + } + + return false; +} diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 72aefdb2b3..e7ccbe7746 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include @@ -49,6 +51,11 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; const unsigned short STUN_SERVER_PORT = 3478; const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; +const QString ASSIGNMENT_CLIENT_MONITOR_LOCAL_PORT_SMEM_KEY = "assignment-client-monitor.local-port"; + +const char DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME[] = "localhost"; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT = 40104; +const unsigned short DEFAULT_ASSIGNMENT_CLIENT_MONITOR_DTLS_PORT = 40105; class HifiSockAddr; @@ -168,6 +175,9 @@ public: return SharedNodePointer(); } + + void putLocalPortIntoSharedMemory(const QString key, QObject* parent); + bool getLocalPortFromSharedMemory(const QString key, QSharedMemory* &sharedMem, quint16& localPort); public slots: void reset(); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index f70c2d9b3c..e63f230f6e 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -62,13 +62,17 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); } -qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { +qint64 NodeList::sendStats(const QJsonObject& statsObject, HifiSockAddr destination) { QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats); QDataStream statsPacketStream(&statsPacket, QIODevice::Append); statsPacketStream << statsObject.toVariantMap(); - return writeUnverifiedDatagram(statsPacket, _domainHandler.getSockAddr()); + return writeUnverifiedDatagram(statsPacket, destination); +} + +qint64 NodeList::sendStatsToDomainServer(const QJsonObject& statsObject) { + return sendStats(statsObject, _domainHandler.getSockAddr()); } void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) { diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index 907fccfcac..1c6de4bb6c 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -47,6 +47,7 @@ public: NodeType_t getOwnerType() const { return _ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } + qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination); qint64 sendStatsToDomainServer(const QJsonObject& statsObject); int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index 2eee540fff..db97e216ee 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -70,6 +70,8 @@ PacketVersion versionForPacketType(PacketType type) { return 2; case PacketTypeOctreeStats: return 1; + case PacketTypeStopNode: + return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; @@ -124,6 +126,7 @@ QString nameForPacketType(PacketType type) { PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); + PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index e593955b51..32f33c01d9 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -67,7 +67,7 @@ enum PacketType { PacketTypeEntityErase, PacketTypeEntityAddResponse, PacketTypeOctreeDataNack, // 45 - UNUSED_10, + PacketTypeStopNode, PacketTypeAudioEnvironment, PacketTypeEntityEditNack, PacketTypeSignedTransactionPayment, @@ -86,7 +86,7 @@ const QSet NON_VERIFIED_PACKETS = QSet() << PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse - << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; + << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode; const int NUM_BYTES_MD5_HASH = 16; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;