mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 03:24:00 +02:00
update temporary domains to use api_key
This commit is contained in:
parent
eebf8e91c6
commit
a6115cba6e
2 changed files with 105 additions and 54 deletions
|
@ -76,6 +76,8 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
setApplicationVersion(BuildInfo::VERSION);
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
|
||||
qDebug() << "Setting up domain-server";
|
||||
|
||||
// make sure we have a fresh AccountManager instance
|
||||
// (need this since domain-server can restart itself and maintain static variables)
|
||||
DependencyManager::set<AccountManager>();
|
||||
|
@ -109,20 +111,26 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Setting up domain-server";
|
||||
setupNodeListAndAssignments();
|
||||
setupAutomaticNetworking();
|
||||
_gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request
|
||||
|
||||
_metadata = new DomainMetadata(this);
|
||||
|
||||
// check for the temporary name parameter
|
||||
const QString GET_TEMPORARY_NAME_SWITCH = "--get-temp-name";
|
||||
if (args.contains(GET_TEMPORARY_NAME_SWITCH)) {
|
||||
getTemporaryName();
|
||||
}
|
||||
|
||||
qDebug() << "domain-server" << nullptr << "is running";
|
||||
setupNodeListAndAssignments();
|
||||
setupAutomaticNetworking();
|
||||
if (!getID().isNull()) {
|
||||
setupHeartbeatToMetaverse();
|
||||
// send the first heartbeat immediately
|
||||
sendHeartbeatToMetaverse();
|
||||
}
|
||||
|
||||
_gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request
|
||||
|
||||
_metadata = new DomainMetadata(this);
|
||||
|
||||
|
||||
qDebug() << "domain-server is running";
|
||||
}
|
||||
|
||||
DomainServer::~DomainServer() {
|
||||
|
@ -150,6 +158,10 @@ void DomainServer::restart() {
|
|||
exit(DomainServer::EXIT_CODE_REBOOT);
|
||||
}
|
||||
|
||||
const QUuid& DomainServer::getID() {
|
||||
return DependencyManager::get<LimitedNodeList>()->getSessionUUID();
|
||||
}
|
||||
|
||||
bool DomainServer::optionallyReadX509KeyAndCertificate() {
|
||||
const QString X509_CERTIFICATE_OPTION = "cert";
|
||||
const QString X509_PRIVATE_KEY_OPTION = "key";
|
||||
|
@ -264,11 +276,13 @@ void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) {
|
|||
static const QString DOMAIN_KEY = "domain";
|
||||
static const QString ID_KEY = "id";
|
||||
static const QString NAME_KEY = "name";
|
||||
static const QString KEY_KEY = "api_key";
|
||||
|
||||
auto domainObject = jsonObject[DATA_KEY].toObject()[DOMAIN_KEY].toObject();
|
||||
if (!domainObject.isEmpty()) {
|
||||
auto id = domainObject[ID_KEY].toString();
|
||||
auto name = domainObject[NAME_KEY].toString();
|
||||
auto key = domainObject[KEY_KEY].toString();
|
||||
|
||||
qInfo() << "Received new temporary domain name" << name;
|
||||
qDebug() << "The temporary domain ID is" << id;
|
||||
|
@ -284,9 +298,13 @@ void DomainServer::handleTempDomainSuccess(QNetworkReply& requestReply) {
|
|||
// change our domain ID immediately
|
||||
DependencyManager::get<LimitedNodeList>()->setSessionUUID(QUuid { id });
|
||||
|
||||
// change our automatic networking settings so that we're communicating with the ICE server
|
||||
setupICEHeartbeatForFullNetworking();
|
||||
// store the new token to the account info
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
accountManager->setTemporaryDomain(id, key);
|
||||
|
||||
// update our heartbeats to use the correct id
|
||||
setupICEHeartbeatForFullNetworking();
|
||||
setupHeartbeatToMetaverse();
|
||||
} else {
|
||||
qWarning() << "There were problems parsing the API response containing a temporary domain name. Please try again"
|
||||
<< "via domain-server relaunch or from the domain-server settings.";
|
||||
|
@ -325,7 +343,7 @@ bool DomainServer::packetVersionMatch(const udt::Packet& packet) {
|
|||
}
|
||||
|
||||
|
||||
void DomainServer::setupNodeListAndAssignments(const QUuid& sessionUUID) {
|
||||
void DomainServer::setupNodeListAndAssignments() {
|
||||
const QString CUSTOM_LOCAL_PORT_OPTION = "metaverse.local_port";
|
||||
|
||||
QVariant localPortValue = _settingsManager.valueOrDefaultValueForKeyPath(CUSTOM_LOCAL_PORT_OPTION);
|
||||
|
@ -450,29 +468,20 @@ bool DomainServer::resetAccountManagerAccessToken() {
|
|||
}
|
||||
|
||||
void DomainServer::setupAutomaticNetworking() {
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
|
||||
qDebug() << "Updating automatic networking setting in domain-server to" << _automaticNetworkingSetting;
|
||||
_automaticNetworkingSetting =
|
||||
_settingsManager.valueOrDefaultValueForKeyPath(METAVERSE_AUTOMATIC_NETWORKING_KEY_PATH).toString();
|
||||
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
const QUuid& domainID = getID();
|
||||
|
||||
if (_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) {
|
||||
setupICEHeartbeatForFullNetworking();
|
||||
}
|
||||
|
||||
_hasAccessToken = resetAccountManagerAccessToken();
|
||||
|
||||
if (!_hasAccessToken) {
|
||||
qDebug() << "Will not send heartbeat to Metaverse API without an access token.";
|
||||
qDebug() << "If this is not a temporary domain add an access token to your config file or via the web interface.";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (_automaticNetworkingSetting == IP_ONLY_AUTOMATIC_NETWORKING_VALUE ||
|
||||
_automaticNetworkingSetting == FULL_AUTOMATIC_NETWORKING_VALUE) {
|
||||
|
||||
const QUuid& domainID = nodeList->getSessionUUID();
|
||||
|
||||
if (!domainID.isNull()) {
|
||||
qDebug() << "domain-server" << _automaticNetworkingSetting << "automatic networking enabled for ID"
|
||||
<< uuidStringWithoutCurlyBraces(domainID) << "via" << _oauthProviderURL.toString();
|
||||
|
@ -484,9 +493,6 @@ void DomainServer::setupAutomaticNetworking() {
|
|||
|
||||
// have the LNL enable public socket updating via STUN
|
||||
nodeList->startSTUNPublicSocketUpdate();
|
||||
} else {
|
||||
// send our heartbeat to data server so it knows what our network settings are
|
||||
sendHeartbeatToMetaverse();
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Cannot enable domain-server automatic networking without a domain ID."
|
||||
|
@ -494,18 +500,20 @@ void DomainServer::setupAutomaticNetworking() {
|
|||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
sendHeartbeatToMetaverse();
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Updating automatic networking setting in domain-server to" << _automaticNetworkingSetting;
|
||||
|
||||
// no matter the auto networking settings we should heartbeat to the data-server every 15s
|
||||
void DomainServer::setupHeartbeatToMetaverse() {
|
||||
// heartbeat to the data-server every 15s
|
||||
const int DOMAIN_SERVER_DATA_WEB_HEARTBEAT_MSECS = 15 * 1000;
|
||||
|
||||
QTimer* dataHeartbeatTimer = new QTimer(this);
|
||||
connect(dataHeartbeatTimer, SIGNAL(timeout()), this, SLOT(sendHeartbeatToMetaverse()));
|
||||
dataHeartbeatTimer->start(DOMAIN_SERVER_DATA_WEB_HEARTBEAT_MSECS);
|
||||
if (!_metaverseHeartbeatTimer) {
|
||||
// setup a timer to heartbeat with the metaverse-server
|
||||
_metaverseHeartbeatTimer = new QTimer { this };
|
||||
connect(_metaverseHeartbeatTimer, SIGNAL(timeout()), this, SLOT(sendHeartbeatToMetaverse()));
|
||||
// do not send a heartbeat immediately - this avoids flooding if the heartbeat fails with a 401
|
||||
_metaverseHeartbeatTimer->start(DOMAIN_SERVER_DATA_WEB_HEARTBEAT_MSECS);
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::setupICEHeartbeatForFullNetworking() {
|
||||
|
@ -524,22 +532,21 @@ void DomainServer::setupICEHeartbeatForFullNetworking() {
|
|||
limitedNodeList->startSTUNPublicSocketUpdate();
|
||||
|
||||
// to send ICE heartbeats we'd better have a private key locally with an uploaded public key
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto domainID = accountManager->getAccountInfo().getDomainID();
|
||||
|
||||
// if we have an access token and we don't have a private key or the current domain ID has changed
|
||||
// we should generate a new keypair
|
||||
if (!accountManager->getAccountInfo().hasPrivateKey() || domainID != limitedNodeList->getSessionUUID()) {
|
||||
accountManager->generateNewDomainKeypair(limitedNodeList->getSessionUUID());
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
if (!accountManager->getAccountInfo().hasPrivateKey() || accountManager->getAccountInfo().getDomainID() != getID()) {
|
||||
accountManager->generateNewDomainKeypair(getID());
|
||||
}
|
||||
|
||||
// hookup to the signal from account manager that tells us when keypair is available
|
||||
connect(accountManager.data(), &AccountManager::newKeypair, this, &DomainServer::handleKeypairChange);
|
||||
|
||||
if (!_iceHeartbeatTimer) {
|
||||
// setup a timer to heartbeat with the ice-server every so often
|
||||
// setup a timer to heartbeat with the ice-server
|
||||
_iceHeartbeatTimer = new QTimer { this };
|
||||
connect(_iceHeartbeatTimer, &QTimer::timeout, this, &DomainServer::sendHeartbeatToIceServer);
|
||||
sendHeartbeatToIceServer();
|
||||
_iceHeartbeatTimer->start(ICE_HEARBEAT_INTERVAL_MSECS);
|
||||
}
|
||||
}
|
||||
|
@ -1067,9 +1074,6 @@ void DomainServer::performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr)
|
|||
}
|
||||
|
||||
void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
const QUuid& domainID = nodeList->getSessionUUID();
|
||||
|
||||
// Setup the domain object to send to the data server
|
||||
QJsonObject domainObject;
|
||||
|
||||
|
@ -1088,6 +1092,13 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
|
|||
NodePermissions anonymousPermissions = _settingsManager.getPermissionsForName(NodePermissions::standardNameAnonymous);
|
||||
domainObject[RESTRICTED_ACCESS_FLAG] = !anonymousPermissions.canConnectToDomain;
|
||||
|
||||
const auto& temporaryDomainKey = DependencyManager::get<AccountManager>()->getTemporaryDomainKey(getID());
|
||||
if (!temporaryDomainKey.isEmpty()) {
|
||||
// add the temporary domain token
|
||||
const QString KEY_KEY = "api_key";
|
||||
domainObject[KEY_KEY] = temporaryDomainKey;
|
||||
}
|
||||
|
||||
if (_metadata) {
|
||||
// Add the metadata to the heartbeat
|
||||
static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat";
|
||||
|
@ -1097,18 +1108,47 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) {
|
|||
QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact)));
|
||||
|
||||
static const QString DOMAIN_UPDATE = "/api/v1/domains/%1";
|
||||
DependencyManager::get<AccountManager>()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)),
|
||||
AccountManagerAuth::Required,
|
||||
DependencyManager::get<AccountManager>()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(getID())),
|
||||
AccountManagerAuth::Optional,
|
||||
QNetworkAccessManager::PutOperation,
|
||||
JSONCallbackParameters(),
|
||||
JSONCallbackParameters(nullptr, QString(), this, "handleMetaverseHeartbeatError"),
|
||||
domainUpdateJSON.toUtf8());
|
||||
}
|
||||
|
||||
void DomainServer::handleMetaverseHeartbeatError(QNetworkReply& requestReply) {
|
||||
if (!_metaverseHeartbeatTimer) {
|
||||
// avoid rehandling errors from the same issue
|
||||
return;
|
||||
}
|
||||
|
||||
// if we have a temporary domain with a bad token, we will get a 401
|
||||
if (requestReply.error() == QNetworkReply::NetworkError::AuthenticationRequiredError) {
|
||||
static const QString DATA_KEY = "data";
|
||||
static const QString TOKEN_KEY = "api_key";
|
||||
|
||||
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object();
|
||||
auto tokenFailure = jsonObject[DATA_KEY].toObject()[TOKEN_KEY];
|
||||
|
||||
if (!tokenFailure.isNull()) {
|
||||
qWarning() << "Temporary domain name lacks a valid API key, and is being reset.";
|
||||
|
||||
// halt heartbeats until we have a token
|
||||
_metaverseHeartbeatTimer->deleteLater();
|
||||
_metaverseHeartbeatTimer = nullptr;
|
||||
|
||||
// give up eventually to avoid flooding traffic
|
||||
static const int MAX_ATTEMPTS = 5;
|
||||
static int attempt = 0;
|
||||
if (++attempt < MAX_ATTEMPTS) {
|
||||
// get a new temporary name and token
|
||||
getTemporaryName(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
||||
if (!_iceServerSocket.isNull()) {
|
||||
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||
const QUuid& domainID = nodeList->getSessionUUID();
|
||||
|
||||
const QString ICE_SERVER_ADDRESS = "ice_server_address";
|
||||
|
||||
QJsonObject domainObject;
|
||||
|
@ -1116,6 +1156,13 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
|||
// we're using full automatic networking and we have a current ice-server socket, use that now
|
||||
domainObject[ICE_SERVER_ADDRESS] = _iceServerSocket.getAddress().toString();
|
||||
|
||||
const auto& temporaryDomainKey = DependencyManager::get<AccountManager>()->getTemporaryDomainKey(getID());
|
||||
if (!temporaryDomainKey.isEmpty()) {
|
||||
// add the temporary domain token
|
||||
const QString KEY_KEY = "api_key";
|
||||
domainObject[KEY_KEY] = temporaryDomainKey;
|
||||
}
|
||||
|
||||
QString domainUpdateJSON = QString("{\"domain\": %1 }").arg(QString(QJsonDocument(domainObject).toJson()));
|
||||
|
||||
// make sure we hear about failure so we can retry
|
||||
|
@ -1127,7 +1174,7 @@ void DomainServer::sendICEServerAddressToMetaverseAPI() {
|
|||
|
||||
static const QString DOMAIN_ICE_ADDRESS_UPDATE = "/api/v1/domains/%1/ice_server_address";
|
||||
|
||||
DependencyManager::get<AccountManager>()->sendRequest(DOMAIN_ICE_ADDRESS_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)),
|
||||
DependencyManager::get<AccountManager>()->sendRequest(DOMAIN_ICE_ADDRESS_UPDATE.arg(uuidStringWithoutCurlyBraces(getID())),
|
||||
AccountManagerAuth::Optional,
|
||||
QNetworkAccessManager::PutOperation,
|
||||
callbackParameters,
|
||||
|
|
|
@ -80,6 +80,8 @@ private slots:
|
|||
void handleTempDomainSuccess(QNetworkReply& requestReply);
|
||||
void handleTempDomainError(QNetworkReply& requestReply);
|
||||
|
||||
void handleMetaverseHeartbeatError(QNetworkReply& requestReply);
|
||||
|
||||
void queuedQuit(QString quitMessage, int exitCode);
|
||||
|
||||
void handleKeypairChange();
|
||||
|
@ -96,7 +98,9 @@ signals:
|
|||
void userDisconnected();
|
||||
|
||||
private:
|
||||
void setupNodeListAndAssignments(const QUuid& sessionUUID = QUuid::createUuid());
|
||||
const QUuid& getID();
|
||||
|
||||
void setupNodeListAndAssignments();
|
||||
bool optionallySetupOAuth();
|
||||
bool optionallyReadX509KeyAndCertificate();
|
||||
|
||||
|
@ -108,6 +112,7 @@ private:
|
|||
|
||||
void setupAutomaticNetworking();
|
||||
void setupICEHeartbeatForFullNetworking();
|
||||
void setupHeartbeatToMetaverse();
|
||||
void sendHeartbeatToMetaverse(const QString& networkAddress);
|
||||
|
||||
void randomizeICEServerAddress(bool shouldTriggerHostLookup);
|
||||
|
@ -178,6 +183,7 @@ private:
|
|||
// These will be parented to this, they are not dangling
|
||||
DomainMetadata* _metadata { nullptr };
|
||||
QTimer* _iceHeartbeatTimer { nullptr };
|
||||
QTimer* _metaverseHeartbeatTimer { nullptr };
|
||||
|
||||
QList<QHostAddress> _iceServerAddresses;
|
||||
QSet<QHostAddress> _failedIceServerAddresses;
|
||||
|
@ -186,8 +192,6 @@ private:
|
|||
int _numHeartbeatDenials { 0 };
|
||||
bool _connectedToICEServer { false };
|
||||
|
||||
bool _hasAccessToken { false };
|
||||
|
||||
friend class DomainGatekeeper;
|
||||
friend class DomainMetadata;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue