diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 1d8908845f..b854e3c801 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -644,188 +644,187 @@ void AudioMixer::sendStatsPacket() { } void AudioMixer::run() { - + + qDebug() << "Waiting for connection to domain to request settings from domain-server."; + + // wait until we have the domain-server settings, otherwise we bail + DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); + connect(&domainHandler, &DomainHandler::settingsReceived, this, &AudioMixer::domainSettingsRequestComplete); + connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &AudioMixer::domainSettingsRequestFailed); + ThreadedAssignment::commonInit(AUDIO_MIXER_LOGGING_TARGET_NAME, NodeType::AudioMixer); +} +void AudioMixer::domainSettingsRequestComplete() { auto nodeList = DependencyManager::get(); - + nodeList->addNodeTypeToInterestSet(NodeType::Agent); - + nodeList->linkedDataCreateCallback = [](Node* node) { node->setLinkedData(new AudioMixerClientData()); }; - - // wait until we have the domain-server settings, otherwise we bail - DomainHandler& domainHandler = nodeList->getDomainHandler(); - - qDebug() << "Waiting for domain settings from domain-server."; - - // block until we get the settingsRequestComplete signal - QEventLoop loop; - connect(&domainHandler, &DomainHandler::settingsReceived, &loop, &QEventLoop::quit); - connect(&domainHandler, &DomainHandler::settingsReceiveFail, &loop, &QEventLoop::quit); - domainHandler.requestDomainSettings(); - loop.exec(); - if (domainHandler.getSettingsObject().isEmpty()) { - qDebug() << "Failed to retreive settings object from domain-server. Bailing on assignment."; - setFinished(true); - return; - } - + DomainHandler& domainHandler = nodeList->getDomainHandler(); const QJsonObject& settingsObject = domainHandler.getSettingsObject(); - + // check the settings object to see if we have anything we can parse out parseSettingsObject(settingsObject); + + // queue up a connection to start broadcasting mixes now that we're ready to go + QMetaObject::invokeMethod(this, "broadcastMixes", Qt::QueuedConnection); +} +void AudioMixer::broadcastMixes() { + auto nodeList = DependencyManager::get(); + int nextFrame = 0; QElapsedTimer timer; timer.start(); - + int usecToSleep = AudioConstants::NETWORK_FRAME_USECS; - + const int TRAILING_AVERAGE_FRAMES = 100; int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; - + while (!_isFinished) { const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f; - + const float RATIO_BACK_OFF = 0.02f; - + const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; - + if (usecToSleep < 0) { usecToSleep = 0; } - + _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) + (usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); - + float lastCutoffRatio = _performanceThrottlingRatio; bool hasRatioChanged = false; - + if (framesSinceCutoffEvent >= TRAILING_AVERAGE_FRAMES) { if (_trailingSleepRatio <= STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD) { // we're struggling - change our min required loudness to reduce some load _performanceThrottlingRatio = _performanceThrottlingRatio + (0.5f * (1.0f - _performanceThrottlingRatio)); - + qDebug() << "Mixer is struggling, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; hasRatioChanged = true; } else if (_trailingSleepRatio >= BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD && _performanceThrottlingRatio != 0) { // we've recovered and can back off the required loudness _performanceThrottlingRatio = _performanceThrottlingRatio - RATIO_BACK_OFF; - + if (_performanceThrottlingRatio < 0) { _performanceThrottlingRatio = 0; } - + qDebug() << "Mixer is recovering, sleeping" << _trailingSleepRatio * 100 << "% of frame time. Old cutoff was" << lastCutoffRatio << "and is now" << _performanceThrottlingRatio; hasRatioChanged = true; } - + if (hasRatioChanged) { // set out min audability threshold from the new ratio _minAudibilityThreshold = LOUDNESS_TO_DISTANCE_RATIO / (2.0f * (1.0f - _performanceThrottlingRatio)); qDebug() << "Minimum audability required to be mixed is now" << _minAudibilityThreshold; - + framesSinceCutoffEvent = 0; } } - + if (!hasRatioChanged) { ++framesSinceCutoffEvent; } - + quint64 now = usecTimestampNow(); if (now - _lastPerSecondCallbackTime > USECS_PER_SECOND) { perSecondActions(); _lastPerSecondCallbackTime = now; } - + nodeList->eachNode([&](const SharedNodePointer& node) { - + if (node->getLinkedData()) { AudioMixerClientData* nodeData = (AudioMixerClientData*)node->getLinkedData(); - + // this function will attempt to pop a frame from each audio stream. // a pointer to the popped data is stored as a member in InboundAudioStream. // That's how the popped audio data will be read for mixing (but only if the pop was successful) nodeData->checkBuffersBeforeFrameSend(); - + // if the stream should be muted, send mute packet if (nodeData->getAvatarAudioStream() && shouldMute(nodeData->getAvatarAudioStream()->getQuietestFrameLoudness())) { auto mutePacket = NLPacket::create(PacketType::NoisyMute, 0); nodeList->sendPacket(std::move(mutePacket), *node); } - + if (node->getType() == NodeType::Agent && node->getActiveSocket() && nodeData->getAvatarAudioStream()) { - + int streamsMixed = prepareMixForListeningNode(node.data()); - + std::unique_ptr mixPacket; - + if (streamsMixed > 0) { int mixPacketBytes = sizeof(quint16) + AudioConstants::NETWORK_FRAME_BYTES_STEREO; mixPacket = NLPacket::create(PacketType::MixedAudio, mixPacketBytes); - + // pack sequence number quint16 sequence = nodeData->getOutgoingSequenceNumber(); mixPacket->writePrimitive(sequence); - + // pack mixed audio samples mixPacket->write(reinterpret_cast(_mixSamples), AudioConstants::NETWORK_FRAME_BYTES_STEREO); } else { int silentPacketBytes = sizeof(quint16) + sizeof(quint16); mixPacket = NLPacket::create(PacketType::SilentAudioFrame, silentPacketBytes); - + // pack sequence number quint16 sequence = nodeData->getOutgoingSequenceNumber(); mixPacket->writePrimitive(sequence); - + // pack number of silent audio samples quint16 numSilentSamples = AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; mixPacket->writePrimitive(numSilentSamples); } - + // Send audio environment sendAudioEnvironmentPacket(node); - + // send mixed audio packet nodeList->sendPacket(std::move(mixPacket), *node); nodeData->incrementOutgoingMixedAudioSequenceNumber(); - + // send an audio stream stats packet if it's time if (_sendAudioStreamStats) { nodeData->sendAudioStreamStatsPackets(node); _sendAudioStreamStats = false; } - + ++_sumListeners; } } }); - + ++_numStatFrames; - + // since we're a while loop we need to help Qt's event processing QCoreApplication::processEvents(); - + if (_isFinished) { // at this point the audio-mixer is done // check if we have a deferred delete event to process (which we should once finished) QCoreApplication::sendPostedEvents(this, QEvent::DeferredDelete); break; } - + usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us - + if (usecToSleep > 0) { usleep(usecToSleep); } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 9e7a010f61..a09e67f4ba 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -40,10 +40,13 @@ public slots: static const InboundAudioStream::Settings& getStreamSettings() { return _streamSettings; } private slots: + void broadcastMixes(); void handleNodeAudioPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleMuteEnvironmentPacket(QSharedPointer packet, SharedNodePointer sendingNode); -private: +private: + void domainSettingsRequestComplete(); + /// adds one stream to the mix for a listening node int addStreamToMixForListeningNodeWithStream(AudioMixerClientData* listenerNodeData, const QUuid& streamUUID, diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 1e17467c3b..b52a4a7e45 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -71,7 +71,6 @@ const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; // 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present // if the avatar is not in view or in the keyhole. void AvatarMixer::broadcastAvatarData() { - int idleTime = QDateTime::currentMSecsSinceEpoch() - _lastFrameTimestamp; ++_numStatFrames; @@ -513,15 +512,15 @@ void AvatarMixer::sendStatsPacket() { } void AvatarMixer::run() { + qDebug() << "Waiting for connection to domain to request settings from domain-server."; + + // wait until we have the domain-server settings, otherwise we bail + DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); + connect(&domainHandler, &DomainHandler::settingsReceived, this, &AvatarMixer::domainSettingsRequestComplete); + connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &AvatarMixer::domainSettingsRequestFailed); + ThreadedAssignment::commonInit(AVATAR_MIXER_LOGGING_NAME, NodeType::AvatarMixer); - auto nodeList = DependencyManager::get(); - nodeList->addNodeTypeToInterestSet(NodeType::Agent); - - nodeList->linkedDataCreateCallback = [] (Node* node) { - node->setLinkedData(new AvatarMixerClientData()); - }; - // setup the timer that will be fired on the broadcast thread _broadcastTimer = new QTimer; _broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS); @@ -530,33 +529,24 @@ void AvatarMixer::run() { // connect appropriate signals and slots connect(_broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection); connect(&_broadcastThread, SIGNAL(started()), _broadcastTimer, SLOT(start())); +} - // wait until we have the domain-server settings, otherwise we bail - DomainHandler& domainHandler = nodeList->getDomainHandler(); - - qDebug() << "Waiting for domain settings from domain-server."; - - // block until we get the settingsRequestComplete signal - - QEventLoop loop; - connect(&domainHandler, &DomainHandler::settingsReceived, &loop, &QEventLoop::quit); - connect(&domainHandler, &DomainHandler::settingsReceiveFail, &loop, &QEventLoop::quit); - domainHandler.requestDomainSettings(); - loop.exec(); - - if (domainHandler.getSettingsObject().isEmpty()) { - qDebug() << "Failed to retreive settings object from domain-server. Bailing on assignment."; - setFinished(true); - return; - } - +void AvatarMixer::domainSettingsRequestComplete() { + auto nodeList = DependencyManager::get(); + nodeList->addNodeTypeToInterestSet(NodeType::Agent); + + nodeList->linkedDataCreateCallback = [] (Node* node) { + node->setLinkedData(new AvatarMixerClientData()); + }; + // parse the settings to pull out the values we need - parseDomainServerSettings(domainHandler.getSettingsObject()); - + parseDomainServerSettings(nodeList->getDomainHandler().getSettingsObject()); + // start the broadcastThread _broadcastThread.start(); } + void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) { const QString AVATAR_MIXER_SETTINGS_KEY = "avatar_mixer"; const QString NODE_SEND_BANDWIDTH_KEY = "max_node_send_bandwidth"; diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 67fdbf5285..6e87bd6a43 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -36,6 +36,7 @@ private slots: void handleAvatarIdentityPacket(QSharedPointer packet, SharedNodePointer senderNode); void handleAvatarBillboardPacket(QSharedPointer packet, SharedNodePointer senderNode); void handleKillAvatarPacket(QSharedPointer packet); + void domainSettingsRequestComplete(); private: void broadcastAvatarData(); diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 2fafaa6731..5126b5ab71 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -253,7 +253,7 @@ void EntityServer::pruneDeletedEntities() { } } -bool EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { +void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { bool wantEditLogging = false; readOptionBool(QString("wantEditLogging"), settingsSectionObject, wantEditLogging); qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging)); @@ -265,6 +265,4 @@ bool EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio EntityTreePointer tree = std::static_pointer_cast(_tree); tree->setWantEditLogging(wantEditLogging); tree->setWantTerseEditLogging(wantTerseEditLogging); - - return true; } diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index 065834cbc2..7ccf5eb0f1 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -41,7 +41,7 @@ public: virtual int sendSpecialPackets(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) override; virtual void entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) override; - virtual bool readAdditionalConfiguration(const QJsonObject& settingsSectionObject) override; + virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) override; public slots: void pruneDeletedEntities(); diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index b6a52358e5..fe75152d54 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -951,31 +951,14 @@ bool OctreeServer::readOptionString(const QString& optionName, const QJsonObject return optionAvailable; } -bool OctreeServer::readConfiguration() { +void OctreeServer::readConfiguration() { // if the assignment had a payload, read and parse that if (getPayload().size() > 0) { parsePayload(); } + + const QJsonObject& settingsObject = DependencyManager::get()->getDomainHandler().getSettingsObject(); - // wait until we have the domain-server settings, otherwise we bail - auto nodeList = DependencyManager::get(); - DomainHandler& domainHandler = nodeList->getDomainHandler(); - - qDebug() << "Waiting for domain settings from domain-server."; - - // block until we get the settingsRequestComplete signal - QEventLoop loop; - connect(&domainHandler, &DomainHandler::settingsReceived, &loop, &QEventLoop::quit); - connect(&domainHandler, &DomainHandler::settingsReceiveFail, &loop, &QEventLoop::quit); - domainHandler.requestDomainSettings(); - loop.exec(); - - if (domainHandler.getSettingsObject().isEmpty()) { - qDebug() << "Failed to retreive settings object from domain-server. Bailing on assignment."; - return false; - } - - const QJsonObject& settingsObject = domainHandler.getSettingsObject(); QString settingsKey = getMyDomainSettingsKey(); QJsonObject settingsSectionObject = settingsObject[settingsKey].toObject(); _settings = settingsSectionObject; // keep this for later @@ -1084,79 +1067,79 @@ bool OctreeServer::readConfiguration() { packetsPerSecondTotalMax, _packetsTotalPerInterval); - return readAdditionalConfiguration(settingsSectionObject); + readAdditionalConfiguration(settingsSectionObject); } void OctreeServer::run() { - - auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); - packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket"); - packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket"); - packetReceiver.registerListener(PacketType::JurisdictionRequest, this, "handleJurisdictionRequestPacket"); - _safeServerName = getMyServerName(); // Before we do anything else, create our tree... OctreeElement::resetPopulationStatistics(); _tree = createTree(); _tree->setIsServer(true); - - // make sure our NodeList knows what type we are - auto nodeList = DependencyManager::get(); - nodeList->setOwnerType(getMyNodeType()); + + qDebug() << "Waiting for connection to domain to request settings from domain-server."; + + // wait until we have the domain-server settings, otherwise we bail + DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); + connect(&domainHandler, &DomainHandler::settingsReceived, this, &OctreeServer::domainSettingsRequestComplete); + connect(&domainHandler, &DomainHandler::settingsReceiveFail, this, &OctreeServer::domainSettingsRequestFailed); // use common init to setup common timers and logging commonInit(getMyLoggingServerTargetName(), getMyNodeType()); +} + +void OctreeServer::domainSettingsRequestComplete() { + + auto nodeList = DependencyManager::get(); // we need to ask the DS about agents so we can ping/reply with them nodeList->addNodeTypeToInterestSet(NodeType::Agent); - - // read the configuration from either the payload or the domain server configuration - if (!readConfiguration()) { - qDebug() << "OctreeServer bailing on run since readConfiguration has failed."; - setFinished(true); - return; // bailing on run, because readConfiguration failed - } - + + auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); + packetReceiver.registerListener(getMyQueryMessageType(), this, "handleOctreeQueryPacket"); + packetReceiver.registerListener(PacketType::OctreeDataNack, this, "handleOctreeDataNackPacket"); + packetReceiver.registerListener(PacketType::JurisdictionRequest, this, "handleJurisdictionRequestPacket"); + + readConfiguration(); + beforeRun(); // after payload has been processed - + connect(nodeList.data(), SIGNAL(nodeAdded(SharedNodePointer)), SLOT(nodeAdded(SharedNodePointer))); connect(nodeList.data(), SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif - + nodeList->linkedDataCreateCallback = [] (Node* node) { OctreeQueryNode* newQueryNodeData = _instance->createOctreeQueryNode(); newQueryNodeData->init(); node->setLinkedData(newQueryNodeData); }; - + srand((unsigned)time(0)); - + // if we want Persistence, set up the local file and persist thread if (_wantPersist) { - + // now set up PersistThread _persistThread = new OctreePersistThread(_tree, _persistFilename, _persistInterval, _wantBackup, _settings, _debugTimestampNow, _persistAsFileType); _persistThread->initialize(true); } - - HifiSockAddr senderSockAddr; - + // set up our jurisdiction broadcaster... if (_jurisdiction) { _jurisdiction->setNodeType(getMyNodeType()); } _jurisdictionSender = new JurisdictionSender(_jurisdiction, getMyNodeType()); _jurisdictionSender->initialize(true); - + // set up our OctreeServerPacketProcessor _octreeInboundPacketProcessor = new OctreeInboundPacketProcessor(this); _octreeInboundPacketProcessor->initialize(true); - + // Convert now to tm struct for local timezone tm* localtm = localtime(&_started); const int MAX_TIME_LENGTH = 128; @@ -1168,6 +1151,7 @@ void OctreeServer::run() { if (gmtm) { strftime(utcBuffer, MAX_TIME_LENGTH, " [%m/%d/%Y %X UTC]", gmtm); } + qDebug() << "Now running... started at: " << localBuffer << utcBuffer; } diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 6d4eb89f66..00733579a7 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -129,6 +129,7 @@ public slots: void sendStatsPacket(); private slots: + void domainSettingsRequestComplete(); void handleOctreeQueryPacket(QSharedPointer packet, SharedNodePointer senderNode); void handleOctreeDataNackPacket(QSharedPointer packet, SharedNodePointer senderNode); void handleJurisdictionRequestPacket(QSharedPointer packet, SharedNodePointer senderNode); @@ -138,8 +139,8 @@ protected: bool readOptionBool(const QString& optionName, const QJsonObject& settingsSectionObject, bool& result); bool readOptionInt(const QString& optionName, const QJsonObject& settingsSectionObject, int& result); bool readOptionString(const QString& optionName, const QJsonObject& settingsSectionObject, QString& result); - bool readConfiguration(); - virtual bool readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { return true; }; + void readConfiguration(); + virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) { }; void parsePayload(); void initHTTPManager(int port); void resetSendingStats(); diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index f7d26f25c5..681f971ef5 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -38,12 +38,17 @@ DomainHandler::DomainHandler(QObject* parent) : _icePeer(this), _isConnected(false), _settingsObject(), - _failedSettingsRequests(0) + _settingsTimer(this) { _sockAddr.setObjectName("DomainServer"); // if we get a socket that make sure our NetworkPeer ping timer stops connect(this, &DomainHandler::completedSocketDiscovery, &_icePeer, &NetworkPeer::stopPingTimer); + + // setup a timeout for failure on settings requests + static const int DOMAIN_SETTINGS_TIMEOUT_MS = 5000; + _settingsTimer.setInterval(DOMAIN_SETTINGS_TIMEOUT_MS); + connect(&_settingsTimer, &QTimer::timeout, this, &DomainHandler::settingsReceiveFail); } void DomainHandler::disconnect() { @@ -80,13 +85,16 @@ void DomainHandler::sendDisconnectPacket() { void DomainHandler::clearSettings() { _settingsObject = QJsonObject(); - _failedSettingsRequests = 0; } void DomainHandler::softReset() { qCDebug(networking) << "Resetting current domain connection information."; disconnect(); + clearSettings(); + + // cancel the failure timeout for any pending requests for settings + QMetaObject::invokeMethod(&_settingsTimer, "stop", Qt::AutoConnection); } void DomainHandler::hardReset() { @@ -250,34 +258,35 @@ void DomainHandler::requestDomainSettings() { NodeType_t owningNodeType = DependencyManager::get()->getOwnerType(); if (owningNodeType == NodeType::Agent) { - // for now the agent nodes don't need any settings - this allows local assignment-clients - // to connect to a domain that is using automatic networking (since we don't have TCP hole punch yet) + // for now the agent nodes don't need any domain settings _settingsObject = QJsonObject(); emit settingsReceived(_settingsObject); } else { - if (_settingsObject.isEmpty()) { - qCDebug(networking) << "Requesting settings from domain server"; - - Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get()->getOwnerType()); - - auto packet = NLPacket::create(PacketType::DomainSettingsRequest, sizeof(assignmentType), true, false); - packet->writePrimitive(assignmentType); - - auto nodeList = DependencyManager::get(); - nodeList->sendPacket(std::move(packet), _sockAddr); - } + qCDebug(networking) << "Requesting settings from domain server"; + + Assignment::Type assignmentType = Assignment::typeForNodeType(DependencyManager::get()->getOwnerType()); + + auto packet = NLPacket::create(PacketType::DomainSettingsRequest, sizeof(assignmentType), true, false); + packet->writePrimitive(assignmentType); + + auto nodeList = DependencyManager::get(); + nodeList->sendPacket(std::move(packet), _sockAddr); + + _settingsTimer.start(); } } void DomainHandler::processSettingsPacketList(QSharedPointer packetList) { + // stop our settings timer since we successfully requested the settings we need + _settingsTimer.stop(); + auto data = packetList->getMessage(); _settingsObject = QJsonDocument::fromJson(data).object(); - - qCDebug(networking) << "Received domain settings: \n" << QString(data); - - // reset failed settings requests to 0, we got them - _failedSettingsRequests = 0; + + if (!_settingsObject.isEmpty()) { + qCDebug(networking) << "Received domain settings: \n" << _settingsObject; + } emit settingsReceived(_settingsObject); } diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 49bab6dc28..25d1c910cd 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -127,8 +127,8 @@ private: NetworkPeer _icePeer; bool _isConnected; QJsonObject _settingsObject; - int _failedSettingsRequests; QString _pendingPath; + QTimer _settingsTimer; }; #endif // hifi_DomainHandler_h diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 6855c2eec3..5433ed0ece 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -77,6 +77,9 @@ void ThreadedAssignment::commonInit(const QString& targetName, NodeType_t nodeTy connect(_domainServerTimer, SIGNAL(timeout()), this, SLOT(checkInWithDomainServerOrExit())); _domainServerTimer->start(DOMAIN_SERVER_CHECK_IN_MSECS); + // send a domain-server check in immediately + checkInWithDomainServerOrExit(); + // move the domain server time to the NL so check-ins fire from there _domainServerTimer->moveToThread(nodeList->thread()); @@ -130,3 +133,8 @@ void ThreadedAssignment::checkInWithDomainServerOrExit() { DependencyManager::get()->sendDomainServerCheckIn(); } } + +void ThreadedAssignment::domainSettingsRequestFailed() { + qDebug() << "Failed to retreive settings object from domain-server. Bailing on assignment."; + setFinished(true); +} diff --git a/libraries/networking/src/ThreadedAssignment.h b/libraries/networking/src/ThreadedAssignment.h index 9ff3b34add..33dca969df 100644 --- a/libraries/networking/src/ThreadedAssignment.h +++ b/libraries/networking/src/ThreadedAssignment.h @@ -40,7 +40,10 @@ protected: bool _isFinished; QTimer* _domainServerTimer = nullptr; QTimer* _statsTimer = nullptr; - + +protected slots: + void domainSettingsRequestFailed(); + private slots: void startSendingStats(); void stopSendingStats(); diff --git a/libraries/networking/src/udt/SendQueue.cpp b/libraries/networking/src/udt/SendQueue.cpp index fd11b0f41e..ba99efdcea 100644 --- a/libraries/networking/src/udt/SendQueue.cpp +++ b/libraries/networking/src/udt/SendQueue.cpp @@ -395,7 +395,7 @@ bool SendQueue::isInactive(bool sentAPacket) { #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "SendQueue to" << _destination << "reached" << NUM_TIMEOUTS_BEFORE_INACTIVE << "timeouts" - << "and 5s before receiving any ACK/NAK and is now inactive. Stopping."; + << "and 5s before receiving any ACK/NAK and is now inactive. Stopping."; #endif deactivate(); @@ -427,9 +427,9 @@ bool SendQueue::isInactive(bool sentAPacket) { if (cvStatus == std::cv_status::timeout) { #ifdef UDT_CONNECTION_DEBUG qCDebug(networking) << "SendQueue to" << _destination << "has been empty for" - << EMPTY_QUEUES_INACTIVE_TIMEOUT.count() - << "seconds and receiver has ACKed all packets." - << "The queue is now inactive and will be stopped."; + << EMPTY_QUEUES_INACTIVE_TIMEOUT.count() + << "seconds and receiver has ACKed all packets." + << "The queue is now inactive and will be stopped."; #endif // Deactivate queue