Revert "Merge pull request #4332 from birarda/master"

This reverts commit 3230857b0d, reversing
changes made to 1b669af79d.
This commit is contained in:
Seth Alves 2015-02-24 17:09:05 -08:00
parent 3230857b0d
commit 89ebb45c03
18 changed files with 403 additions and 108 deletions

View file

@ -18,10 +18,10 @@
#include <AccountManager.h> #include <AccountManager.h>
#include <AddressManager.h> #include <AddressManager.h>
#include <Assignment.h> #include <Assignment.h>
#include <AvatarHashMap.h>
#include <HifiConfigVariantMap.h> #include <HifiConfigVariantMap.h>
#include <LogHandler.h> #include <LogHandler.h>
#include <LogUtils.h> #include <LogUtils.h>
#include <LimitedNodeList.h>
#include <NodeList.h> #include <NodeList.h>
#include <PacketHeaders.h> #include <PacketHeaders.h>
#include <SharedUtil.h> #include <SharedUtil.h>
@ -43,7 +43,8 @@ int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
AssignmentClient::AssignmentClient(int &argc, char **argv) : AssignmentClient::AssignmentClient(int &argc, char **argv) :
QCoreApplication(argc, argv), QCoreApplication(argc, argv),
_assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME), _assignmentServerHostname(DEFAULT_ASSIGNMENT_SERVER_HOSTNAME),
_localASPortSharedMem(NULL) _localASPortSharedMem(NULL),
_localACMPortSharedMem(NULL)
{ {
LogUtils::init(); LogUtils::init();
@ -56,7 +57,11 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
DependencyManager::registerInheritance<LimitedNodeList, NodeList>(); DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
auto addressManager = DependencyManager::set<AddressManager>(); auto addressManager = DependencyManager::set<AddressManager>();
auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned); auto nodeList = DependencyManager::set<NodeList>(NodeType::Unassigned);
auto avatarHashMap = DependencyManager::set<AvatarHashMap>();
// make up a uuid for this child so the parent can tell us apart. This id will be changed
// when the domain server hands over an assignment.
QUuid nodeUUID = QUuid::createUuid();
nodeList->setSessionUUID(nodeUUID);
// setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us // setup a shutdown event listener to handle SIGTERM or WM_CLOSE for us
#ifdef _WIN32 #ifdef _WIN32
@ -123,9 +128,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required // call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
qDebug() << "Waiting for assignment -" << _requestAssignment; qDebug() << "Waiting for assignment -" << _requestAssignment;
QTimer* timer = new QTimer(this); connect(&_requestTimer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest())); _requestTimer.start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
// connect our readPendingDatagrams method to the readyRead() signal of the socket // connect our readPendingDatagrams method to the readyRead() signal of the socket
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
@ -136,6 +140,45 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// Create Singleton objects on main thread // Create Singleton objects on main thread
NetworkAccessManager::getInstance(); NetworkAccessManager::getInstance();
// Hook up a timer to send this child's status to the Monitor once per second
setUpStatsToMonitor();
}
void AssignmentClient::stopAssignmentClient() {
qDebug() << "Exiting.";
_requestTimer.stop();
_statsTimerACM.stop();
quit();
}
void AssignmentClient::setUpStatsToMonitor() {
// Figure out the address to send out stats to
quint16 localMonitorServerPort = DEFAULT_ASSIGNMENT_CLIENT_MONITOR_PORT;
auto nodeList = DependencyManager::get<NodeList>();
nodeList->getLocalServerPortFromSharedMemory(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<NodeList>();
if (_currentAssignment) {
statsObject["assignment_type"] = _currentAssignment->getTypeName();
} else {
statsObject["assignment_type"] = "none";
}
nodeList->sendStats(statsObject, _assignmentClientMonitorSocket);
} }
void AssignmentClient::sendAssignmentRequest() { void AssignmentClient::sendAssignmentRequest() {
@ -145,23 +188,9 @@ void AssignmentClient::sendAssignmentRequest() {
if (_assignmentServerHostname == "localhost") { if (_assignmentServerHostname == "localhost") {
// we want to check again for the local domain-server port in case the DS has restarted // 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; quint16 localAssignmentServerPort;
memcpy(&localAssignmentServerPort, _localASPortSharedMem->data(), sizeof(localAssignmentServerPort)); if (nodeList->getLocalServerPortFromSharedMemory(DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY, _localASPortSharedMem,
localAssignmentServerPort)) {
_localASPortSharedMem->unlock();
if (localAssignmentServerPort != _assignmentServerSocket.getPort()) { if (localAssignmentServerPort != _assignmentServerSocket.getPort()) {
qDebug() << "Port for local assignment server read from shared memory is" qDebug() << "Port for local assignment server read from shared memory is"
<< localAssignmentServerPort; << localAssignmentServerPort;
@ -170,7 +199,9 @@ void AssignmentClient::sendAssignmentRequest() {
nodeList->setAssignmentServerSocket(_assignmentServerSocket); nodeList->setAssignmentServerSocket(_assignmentServerSocket);
} }
} }
else {
qDebug () << "- will attempt to connect to domain-server on" << _assignmentServerSocket.getPort();
}
} }
nodeList->sendAssignment(_requestAssignment); nodeList->sendAssignment(_requestAssignment);
@ -227,6 +258,14 @@ void AssignmentClient::readPendingDatagrams() {
} else { } else {
qDebug() << "Received an assignment that could not be unpacked. Re-requesting."; qDebug() << "Received an assignment that could not be unpacked. Re-requesting.";
} }
} else if (packetTypeForPacket(receivedPacket) == PacketTypeStopNode) {
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
qDebug() << "Network told me to exit.";
emit stopAssignmentClient();
} else {
qDebug() << "Got a stop packet from other than localhost.";
}
} else { } else {
// have the NodeList attempt to handle it // have the NodeList attempt to handle it
nodeList->processNodeData(senderSockAddr, receivedPacket); nodeList->processNodeData(senderSockAddr, receivedPacket);

View file

@ -29,13 +29,22 @@ private slots:
void readPendingDatagrams(); void readPendingDatagrams();
void assignmentCompleted(); void assignmentCompleted();
void handleAuthenticationRequest(); void handleAuthenticationRequest();
void sendStatsPacketToACM();
void stopAssignmentClient();
private: private:
void setUpStatsToMonitor();
Assignment _requestAssignment; Assignment _requestAssignment;
static SharedAssignmentPointer _currentAssignment; static SharedAssignmentPointer _currentAssignment;
QString _assignmentServerHostname; QString _assignmentServerHostname;
HifiSockAddr _assignmentServerSocket; 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 #endif // hifi_AssignmentClient_h

View file

@ -0,0 +1,66 @@
//
// 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 <QCommandLineParser>
#include <LogHandler.h>
#include <SharedUtil.h>
#include "Assignment.h"
#include "AssignmentClient.h"
#include "AssignmentClientMonitor.h"
#include "AssignmentClientApp.h"
AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) :
QCoreApplication(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);
if (!parser.parse(QCoreApplication::arguments())) {
qCritical() << parser.errorText() << endl;
parser.showHelp();
Q_UNREACHABLE();
}
if (parser.isSet(helpOption)) {
parser.showHelp();
Q_UNREACHABLE();
}
unsigned int numForks = 0;
if (parser.isSet(numChildsOption)) {
numForks = parser.value(numChildsOption).toInt();
}
if (numForks) {
AssignmentClientMonitor monitor(argc, argv, numForks);
monitor.exec();
} else {
AssignmentClient client(argc, argv);
client.exec();
}
}

View file

@ -0,0 +1,18 @@
//
// 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 <QApplication>
class AssignmentClientApp : public QCoreApplication {
Q_OBJECT
public:
AssignmentClientApp(int argc, char* argv[]);
};

View file

@ -0,0 +1,8 @@
#include "AssignmentClientChildData.h"
AssignmentClientChildData::AssignmentClientChildData(QString childType) :
_childType(childType)
{
}

View file

@ -0,0 +1,32 @@
//
// AssignmentClientChildData.h
// assignment-client/src
//
// Created by Seth Alves on 2/23/2015.
// 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
//
#ifndef hifi_AssignmentClientChildData_h
#define hifi_AssignmentClientChildData_h
#include <Assignment.h>
class AssignmentClientChildData : public NodeData {
public:
AssignmentClientChildData(QString childType);
QString getChildType() { return _childType; }
void setChildType(QString childType) { _childType = childType; }
// implement parseData to return 0 so we can be a subclass of NodeData
int parseData(const QByteArray& packet) { return 0; }
private:
QString _childType;
};
#endif // hifi_AssignmentClientChildData_h

View file

@ -13,14 +13,18 @@
#include <LogHandler.h> #include <LogHandler.h>
#include <ShutdownEventListener.h> #include <ShutdownEventListener.h>
#include <AddressManager.h>
#include "AssignmentClientMonitor.h" #include "AssignmentClientMonitor.h"
#include "AssignmentClientChildData.h"
#include "PacketHeaders.h"
#include "SharedUtil.h"
const char* NUM_FORKS_PARAMETER = "-n"; const char* NUM_FORKS_PARAMETER = "-n";
const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; 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) QCoreApplication(argc, argv)
{ {
// start the Logging class with the parent's target name // start the Logging class with the parent's target name
@ -42,10 +46,24 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num
_childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex);
_childArguments.removeAt(forksParameterIndex); _childArguments.removeAt(forksParameterIndex);
// create a NodeList so we can receive stats from children
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
auto addressManager = DependencyManager::set<AddressManager>();
auto nodeList = DependencyManager::set<LimitedNodeList>(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 // 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(); spawnChildClient();
} }
connect(&_checkSparesTimer, SIGNAL(timeout()), SLOT(checkSpares()));
_checkSparesTimer.start(NODE_SILENCE_THRESHOLD_MSECS * 3);
} }
AssignmentClientMonitor::~AssignmentClientMonitor() { AssignmentClientMonitor::~AssignmentClientMonitor() {
@ -53,46 +71,122 @@ AssignmentClientMonitor::~AssignmentClientMonitor() {
} }
void AssignmentClientMonitor::stopChildProcesses() { void AssignmentClientMonitor::stopChildProcesses() {
auto nodeList = DependencyManager::get<NodeList>();
QList<QPointer<QProcess> >::Iterator it = _childProcesses.begin(); nodeList->eachNode([&](const SharedNodePointer& node) {
while (it != _childProcesses.end()) { qDebug() << "asking child" << node->getUUID() << "to exit.";
if (!it->isNull()) { node->activateLocalSocket();
qDebug() << "Monitor is terminating child process" << it->data(); QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, *node->getActiveSocket());
// don't re-spawn this child when it goes down });
disconnect(it->data(), 0, this, 0);
it->data()->terminate();
it->data()->waitForFinished();
}
it = _childProcesses.erase(it);
}
} }
void AssignmentClientMonitor::spawnChildClient() { void AssignmentClientMonitor::spawnChildClient() {
QProcess *assignmentClient = new QProcess(this); QProcess *assignmentClient = new QProcess(this);
_childProcesses.append(QPointer<QProcess>(assignmentClient));
// make sure that the output from the child process appears in our output // make sure that the output from the child process appears in our output
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
assignmentClient->start(applicationFilePath(), _childArguments); assignmentClient->start(applicationFilePath(), _childArguments);
// link the child processes' finished slot to our childProcessFinished slot
connect(assignmentClient, SIGNAL(finished(int, QProcess::ExitStatus)), this,
SLOT(childProcessFinished(int, QProcess::ExitStatus)));
qDebug() << "Spawned a child client with PID" << assignmentClient->pid(); qDebug() << "Spawned a child client with PID" << assignmentClient->pid();
} }
void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) {
qDebug("Replacing dead child assignment client with a new one");
// remove the old process from our list of child processes
qDebug() << "need to remove" << QPointer<QProcess>(qobject_cast<QProcess*>(sender()));
_childProcesses.removeOne(QPointer<QProcess>(qobject_cast<QProcess*>(sender())));
void AssignmentClientMonitor::checkSpares() {
auto nodeList = DependencyManager::get<NodeList>();
QUuid aSpareId = "";
unsigned int spareCount = 0;
nodeList->removeSilentNodes();
nodeList->eachNode([&](const SharedNodePointer& node) {
AssignmentClientChildData *childData = static_cast<AssignmentClientChildData*>(node->getLinkedData());
if (childData->getChildType() == "none") {
spareCount ++;
aSpareId = node->getUUID();
}
});
if (spareCount != 1) {
qDebug() << "spare count is" << spareCount;
}
if (spareCount < 1) {
spawnChildClient(); spawnChildClient();
}
if (spareCount > 1) {
// kill aSpareId
qDebug() << "asking child" << aSpareId << "to exit.";
SharedNodePointer childNode = nodeList->nodeWithUUID(aSpareId);
childNode->activateLocalSocket();
QByteArray diePacket = byteArrayWithPopulatedHeader(PacketTypeStopNode);
nodeList->writeUnverifiedDatagram(diePacket, childNode);
}
} }
void AssignmentClientMonitor::readPendingDatagrams() {
auto nodeList = DependencyManager::get<NodeList>();
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);
SharedNodePointer matchingNode = nodeList->sendingNodeForPacket(receivedPacket);
if (!matchingNode) {
// The parent only expects to be talking with prorams running on this same machine.
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
if (!packetUUID.isNull()) {
matchingNode = DependencyManager::get<LimitedNodeList>()->addOrUpdateNode
(packetUUID, NodeType::Unassigned, senderSockAddr, senderSockAddr, false);
AssignmentClientChildData *childData = new AssignmentClientChildData("unknown");
matchingNode->setLinkedData(childData);
} else {
// tell unknown assignment-client child to exit.
qDebug() << "asking unknown 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));
// decode json
QVariantMap unpackedVariantMap;
packetStream >> unpackedVariantMap;
QJsonObject unpackedStatsJSON = QJsonObject::fromVariantMap(unpackedVariantMap);
// get child's assignment type out of the decoded json
QString childType = unpackedStatsJSON["assignment_type"].toString();
AssignmentClientChildData *childData =
static_cast<AssignmentClientChildData*>(matchingNode->getLinkedData());
childData->setChildType(childType);
// note when this child talked
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
}
} else {
// have the NodeList attempt to handle it
nodeList->processNodeData(senderSockAddr, receivedPacket);
}
}
}
}

View file

@ -15,25 +15,30 @@
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/qpointer.h> #include <QtCore/qpointer.h>
#include <QtCore/QProcess> #include <QtCore/QProcess>
#include <QtCore/QDateTime>
#include <Assignment.h> #include <Assignment.h>
#include "AssignmentClientChildData.h"
extern const char* NUM_FORKS_PARAMETER; extern const char* NUM_FORKS_PARAMETER;
class AssignmentClientMonitor : public QCoreApplication { class AssignmentClientMonitor : public QCoreApplication {
Q_OBJECT Q_OBJECT
public: public:
AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks); AssignmentClientMonitor(int &argc, char **argv, const unsigned int numAssignmentClientForks);
~AssignmentClientMonitor(); ~AssignmentClientMonitor();
void stopChildProcesses(); void stopChildProcesses();
private slots: private slots:
void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); void readPendingDatagrams();
void checkSpares();
private: private:
void spawnChildClient(); void spawnChildClient();
QList<QPointer<QProcess> > _childProcesses;
QStringList _childArguments; QStringList _childArguments;
QTimer _checkSparesTimer; // every few seconds see if it need fewer or more spare children
}; };
#endif // hifi_AssignmentClientMonitor_h #endif // hifi_AssignmentClientMonitor_h

View file

@ -9,34 +9,10 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <LogHandler.h>
#include <SharedUtil.h>
#include "Assignment.h" #include "AssignmentClientApp.h"
#include "AssignmentClient.h"
#include "AssignmentClientMonitor.h"
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#ifndef WIN32 AssignmentClientApp app(argc, argv);
setvbuf(stdout, NULL, _IOLBF, 0); return 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();
}
} }

View file

@ -246,19 +246,7 @@ void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
auto nodeList = DependencyManager::set<LimitedNodeList>(domainServerPort, domainServerDTLSPort); auto nodeList = DependencyManager::set<LimitedNodeList>(domainServerPort, domainServerDTLSPort);
// no matter the local port, save it to shared mem so that local assignment clients can ask what it is // 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); nodeList->putLocalPortIntoSharedMemory(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.";
}
// set our LimitedNodeList UUID to match the UUID from our config // 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 // nodes will currently use this to add resources to data-web that relate to our domain

View file

@ -76,7 +76,7 @@ const QString AddressManager::currentPath(bool withOrientation) const {
pathString += "/" + orientationString; pathString += "/" + orientationString;
} else { } else {
qDebug() << "Cannot add orientation to path without a getter for position." qDebug() << "Cannot add orientation to path without a getter for position."
<< "Call AdressManager::setOrientationGetter to pass a function that will return a glm::quat"; << "Call AddressManager::setOrientationGetter to pass a function that will return a glm::quat";
} }
} }
@ -84,7 +84,7 @@ const QString AddressManager::currentPath(bool withOrientation) const {
return pathString; return pathString;
} else { } else {
qDebug() << "Cannot create address path without a getter for position." qDebug() << "Cannot create address path without a getter for position."
<< "Call AdressManager::setPositionGetter to pass a function that will return a const glm::vec3&"; << "Call AddressManager::setPositionGetter to pass a function that will return a const glm::vec3&";
return QString(); return QString();
} }
} }

View file

@ -669,3 +669,41 @@ void LimitedNodeList::sendHeartbeatToIceServer(const HifiSockAddr& iceServerSock
writeUnverifiedDatagram(iceRequestByteArray, iceServerSockAddr); 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::getLocalServerPortFromSharedMemory(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;
}

View file

@ -26,6 +26,7 @@
#include <qsharedpointer.h> #include <qsharedpointer.h>
#include <QtNetwork/qudpsocket.h> #include <QtNetwork/qudpsocket.h>
#include <QtNetwork/qhostaddress.h> #include <QtNetwork/qhostaddress.h>
#include <QSharedMemory>
#include <tbb/concurrent_unordered_map.h> #include <tbb/concurrent_unordered_map.h>
@ -49,6 +50,11 @@ const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io";
const unsigned short STUN_SERVER_PORT = 3478; const unsigned short STUN_SERVER_PORT = 3478;
const QString DOMAIN_SERVER_LOCAL_PORT_SMEM_KEY = "domain-server.local-port"; 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; class HifiSockAddr;
@ -169,6 +175,9 @@ public:
return SharedNodePointer(); return SharedNodePointer();
} }
void putLocalPortIntoSharedMemory(const QString key, QObject* parent);
bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort);
public slots: public slots:
void reset(); void reset();
void eraseAllNodes(); void eraseAllNodes();

View file

@ -149,7 +149,12 @@ QDataStream& operator>>(QDataStream& in, Node& node) {
} }
QDebug operator<<(QDebug debug, const Node &node) { QDebug operator<<(QDebug debug, const Node &node) {
debug.nospace() << NodeType::getNodeTypeName(node.getType()) << " (" << node.getType() << ")"; debug.nospace() << NodeType::getNodeTypeName(node.getType());
if (node.getType() == NodeType::Unassigned) {
debug.nospace() << " (1)";
} else {
debug.nospace() << " (" << node.getType() << ")";
}
debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " "; debug << " " << node.getUUID().toString().toLocal8Bit().constData() << " ";
debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket(); debug.nospace() << node.getPublicSocket() << "/" << node.getLocalSocket();
return debug.nospace(); return debug.nospace();

View file

@ -62,13 +62,17 @@ NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); 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); QByteArray statsPacket = byteArrayWithPopulatedHeader(PacketTypeNodeJsonStats);
QDataStream statsPacketStream(&statsPacket, QIODevice::Append); QDataStream statsPacketStream(&statsPacket, QIODevice::Append);
statsPacketStream << statsObject.toVariantMap(); 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) { void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode) {

View file

@ -47,6 +47,7 @@ public:
NodeType_t getOwnerType() const { return _ownerType; } NodeType_t getOwnerType() const { return _ownerType; }
void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; } void setOwnerType(NodeType_t ownerType) { _ownerType = ownerType; }
qint64 sendStats(const QJsonObject& statsObject, HifiSockAddr destination);
qint64 sendStatsToDomainServer(const QJsonObject& statsObject); qint64 sendStatsToDomainServer(const QJsonObject& statsObject);
int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; } int getNumNoReplyDomainCheckIns() const { return _numNoReplyDomainCheckIns; }

View file

@ -70,6 +70,8 @@ PacketVersion versionForPacketType(PacketType type) {
return 2; return 2;
case PacketTypeOctreeStats: case PacketTypeOctreeStats:
return 1; return 1;
case PacketTypeStopNode:
return 1;
case PacketTypeEntityAddOrEdit: case PacketTypeEntityAddOrEdit:
case PacketTypeEntityData: case PacketTypeEntityData:
return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE; return VERSION_MODEL_ENTITIES_SUPPORT_SHAPE_TYPE;
@ -124,6 +126,7 @@ QString nameForPacketType(PacketType type) {
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityErase);
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityAddResponse);
PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeOctreeDataNack);
PACKET_TYPE_NAME_LOOKUP(PacketTypeStopNode);
PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment); PACKET_TYPE_NAME_LOOKUP(PacketTypeAudioEnvironment);
PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack); PACKET_TYPE_NAME_LOOKUP(PacketTypeEntityEditNack);
PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment); PACKET_TYPE_NAME_LOOKUP(PacketTypeSignedTransactionPayment);

View file

@ -67,7 +67,7 @@ enum PacketType {
PacketTypeEntityErase, PacketTypeEntityErase,
PacketTypeEntityAddResponse, PacketTypeEntityAddResponse,
PacketTypeOctreeDataNack, // 45 PacketTypeOctreeDataNack, // 45
UNUSED_10, PacketTypeStopNode,
PacketTypeAudioEnvironment, PacketTypeAudioEnvironment,
PacketTypeEntityEditNack, PacketTypeEntityEditNack,
PacketTypeSignedTransactionPayment, PacketTypeSignedTransactionPayment,
@ -86,7 +86,7 @@ const QSet<PacketType> NON_VERIFIED_PACKETS = QSet<PacketType>()
<< PacketTypeNodeJsonStats << PacketTypeEntityQuery << PacketTypeNodeJsonStats << PacketTypeEntityQuery
<< PacketTypeOctreeDataNack << PacketTypeEntityEditNack << PacketTypeOctreeDataNack << PacketTypeEntityEditNack
<< PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse << PacketTypeIceServerHeartbeat << PacketTypeIceServerHeartbeatResponse
<< PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply; << PacketTypeUnverifiedPing << PacketTypeUnverifiedPingReply << PacketTypeStopNode;
const int NUM_BYTES_MD5_HASH = 16; const int NUM_BYTES_MD5_HASH = 16;
const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID; const int NUM_STATIC_HEADER_BYTES = sizeof(PacketVersion) + NUM_BYTES_RFC4122_UUID;