// // DomainServer.h // domain-server/src // // Created by Stephen Birarda on 9/26/13. // Copyright 2013 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_DomainServer_h #define hifi_DomainServer_h #include #include #include #include #include #include #include #include #include #include #include #include #include #include "AssetsBackupHandler.h" #include "DomainGatekeeper.h" #include "DomainMetadata.h" #include "DomainServerSettingsManager.h" #include "DomainServerWebSessionData.h" #include "WalletTransaction.h" #include "DomainContentBackupManager.h" #include "PendingAssignedNodeData.h" #include Q_DECLARE_LOGGING_CATEGORY(domain_server) typedef QSharedPointer SharedAssignmentPointer; typedef QMultiHash TransactionHash; using Subnet = QPair; using SubnetList = std::vector; const int INVALID_ICE_LOOKUP_ID = -1; enum ReplicationServerDirection { Upstream, Downstream }; class DomainServer : public QCoreApplication, public HTTPSRequestHandler { Q_OBJECT public: DomainServer(int argc, char* argv[]); ~DomainServer(); static void parseCommandLine(int argc, char* argv[]); enum DomainType { NonMetaverse, MetaverseDomain, MetaverseTemporaryDomain }; static int const EXIT_CODE_REBOOT; bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false) override; bool handleHTTPSRequest(HTTPSConnection* connection, const QUrl& url, bool skipSubHandler = false) override; static const QString REPLACEMENT_FILE_EXTENSION; bool isAssetServerEnabled(); public slots: /// Called by NodeList to inform us a node has been added void nodeAdded(SharedNodePointer node); /// Called by NodeList to inform us a node has been killed void nodeKilled(SharedNodePointer node); void transactionJSONCallback(const QJsonObject& data); void restart(); private slots: void processRequestAssignmentPacket(QSharedPointer packet); void processListRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); void processNodeJSONStatsPacket(QSharedPointer packetList, SharedNodePointer sendingNode); void processPathQueryPacket(QSharedPointer packet); void processNodeDisconnectRequestPacket(QSharedPointer message); void processICEServerHeartbeatDenialPacket(QSharedPointer message); void processICEServerHeartbeatACK(QSharedPointer message); void handleDomainContentReplacementFromURLRequest(QSharedPointer message); void handleOctreeFileReplacementRequest(QSharedPointer message); void handleOctreeFileReplacement(QByteArray octreeFile); void processOctreeDataRequestMessage(QSharedPointer message); void processOctreeDataPersistMessage(QSharedPointer message); void setupPendingAssignmentCredits(); void sendPendingTransactionsToServer(); void performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr); void sendHeartbeatToMetaverse() { sendHeartbeatToMetaverse(QString()); } void sendHeartbeatToIceServer(); void handleConnectedNode(SharedNodePointer newNode); void handleTempDomainSuccess(QNetworkReply* requestReply); void handleTempDomainError(QNetworkReply* requestReply); void handleMetaverseHeartbeatError(QNetworkReply* requestReply); void queuedQuit(QString quitMessage, int exitCode); void handleKeypairChange(); void updateICEServerAddresses(); void handleICEHostInfo(const QHostInfo& hostInfo); void sendICEServerAddressToMetaverseAPI(); void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply); void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply); void updateReplicatedNodes(); void updateDownstreamNodes(); void updateUpstreamNodes(); void tokenGrantFinished(); void profileRequestFinished(); signals: void iceServerChanged(); void userConnected(); void userDisconnected(); private: QUuid getID(); QString getContentBackupDir(); QString getEntitiesDirPath(); QString getEntitiesFilePath(); QString getEntitiesReplacementFilePath(); void maybeHandleReplacementEntityFile(); void setupNodeListAndAssignments(); bool optionallySetupOAuth(); bool optionallyReadX509KeyAndCertificate(); void getTemporaryName(bool force = false); static bool isPacketVerified(const udt::Packet& packet); bool resetAccountManagerAccessToken(); void setupAutomaticNetworking(); void setupICEHeartbeatForFullNetworking(); void setupHeartbeatToMetaverse(); void sendHeartbeatToMetaverse(const QString& networkAddress); void randomizeICEServerAddress(bool shouldTriggerHostLookup); unsigned int countConnectedUsers(); void handleKillNode(SharedNodePointer nodeToKill); void broadcastNodeDisconnect(const SharedNodePointer& disconnnectedNode); void sendDomainListToNode(const SharedNodePointer& node, const HifiSockAddr& senderSockAddr); bool isInInterestSet(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB); QUuid connectionSecretForNodes(const SharedNodePointer& nodeA, const SharedNodePointer& nodeB); void broadcastNewNode(const SharedNodePointer& node); void parseAssignmentConfigs(QSet& excludedTypes); void addStaticAssignmentToAssignmentHash(Assignment* newAssignment); void createStaticAssignmentsForType(Assignment::Type type, const QVariantList& configList); void populateDefaultStaticAssignmentsExcludingTypes(const QSet& excludedTypes); void populateStaticScriptedAssignmentsFromSettings(); SharedAssignmentPointer dequeueMatchingAssignment(const QUuid& checkInUUID, NodeType_t nodeType); SharedAssignmentPointer deployableAssignmentForRequest(const Assignment& requestAssignment); void refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment); void addStaticAssignmentsToQueue(); QUrl oauthRedirectURL(); QUrl oauthAuthorizationURL(const QUuid& stateUUID = QUuid::createUuid()); bool isAuthenticatedRequest(HTTPConnection* connection, const QUrl& url); QNetworkReply* profileRequestGivenTokenReply(QNetworkReply* tokenReply); Headers setupCookieHeadersFromProfileReply(QNetworkReply* profileReply); QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); bool shouldReplicateNode(const Node& node); void setupGroupCacheRefresh(); QString pathForRedirect(QString path = QString()) const; void updateReplicationNodes(ReplicationServerDirection direction); HTTPSConnection* connectionFromReplyWithState(QNetworkReply* reply); bool processPendingContent(HTTPConnection* connection, QString itemName, QString filename, QByteArray dataChunk); bool forwardMetaverseAPIRequest(HTTPConnection* connection, const QString& metaversePath, const QString& requestSubobject, std::initializer_list requiredData = { }, std::initializer_list optionalData = { }, bool requireAccessToken = true); SubnetList _acSubnetWhitelist; std::vector _replicatedUsernames; DomainGatekeeper _gatekeeper; HTTPManager _httpManager; std::unique_ptr _httpsManager; QHash _allAssignments; QQueue _unfulfilledAssignments; TransactionHash _pendingAssignmentCredits; bool _isUsingDTLS { false }; QUrl _oauthProviderURL; QString _oauthClientID; QString _oauthClientSecret; QString _hostname; std::unordered_map _ephemeralACScripts; QSet _webAuthenticationStateSet; QHash _cookieSessionHash; QString _automaticNetworkingSetting; DomainServerSettingsManager _settingsManager; HifiSockAddr _iceServerSocket; std::unique_ptr _iceServerHeartbeatPacket; // These will be parented to this, they are not dangling DomainMetadata* _metadata { nullptr }; QTimer* _iceHeartbeatTimer { nullptr }; QTimer* _metaverseHeartbeatTimer { nullptr }; QTimer* _metaverseGroupCacheTimer { nullptr }; QList _iceServerAddresses; QSet _failedIceServerAddresses; int _iceAddressLookupID { INVALID_ICE_LOOKUP_ID }; int _noReplyICEHeartbeats { 0 }; int _numHeartbeatDenials { 0 }; bool _connectedToICEServer { false }; DomainType _type { DomainType::NonMetaverse }; friend class DomainGatekeeper; friend class DomainMetadata; static QString _iceServerAddr; static int _iceServerPort; static bool _overrideDomainID; // should we override the domain-id from settings? static QUuid _overridingDomainID; // what should we override it with? static bool _getTempName; static QString _userConfigFilename; static int _parentPID; bool _sendICEServerAddressToMetaverseAPIInProgress { false }; bool _sendICEServerAddressToMetaverseAPIRedo { false }; std::unique_ptr _contentManager { nullptr }; QHash> _pendingOAuthConnections; std::unordered_map _pendingUploadedContents; std::unordered_map> _pendingContentFiles; QThread _assetClientThread; }; #endif // hifi_DomainServer_h