mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 07:27:04 +02:00
Initial path to fixing screenshare auth race condition
This commit is contained in:
parent
f01a39adf5
commit
c96c684400
6 changed files with 86 additions and 12 deletions
|
@ -3634,10 +3634,10 @@ void DomainServer::processAvatarZonePresencePacket(QSharedPointer<ReceivedMessag
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static const int SCREENSHARE_EXPIRATION_SECONDS = 24 * 60 * 60;
|
static const int SCREENSHARE_EXPIRATION_SECONDS = 24 * 60 * 60;
|
||||||
screensharePresence(zone.isNull() ? "" : zone.toString(), verifiedUsername, SCREENSHARE_EXPIRATION_SECONDS);
|
screensharePresence(zone.isNull() ? "" : zone.toString(), verifiedUsername, avatar, SCREENSHARE_EXPIRATION_SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::screensharePresence(QString roomname, QString username, int expirationSeconds) {
|
void DomainServer::screensharePresence(QString roomname, QString username, QUuid avatarID, int expirationSeconds) {
|
||||||
if (!DependencyManager::get<AccountManager>()->hasValidAccessToken()) {
|
if (!DependencyManager::get<AccountManager>()->hasValidAccessToken()) {
|
||||||
static std::once_flag presenceAuthorityWarning;
|
static std::once_flag presenceAuthorityWarning;
|
||||||
std::call_once(presenceAuthorityWarning, [] {
|
std::call_once(presenceAuthorityWarning, [] {
|
||||||
|
@ -3649,6 +3649,10 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e
|
||||||
callbackParams.callbackReceiver = this;
|
callbackParams.callbackReceiver = this;
|
||||||
callbackParams.jsonCallbackMethod = "handleSuccessfulScreensharePresence";
|
callbackParams.jsonCallbackMethod = "handleSuccessfulScreensharePresence";
|
||||||
callbackParams.errorCallbackMethod = "handleFailedScreensharePresence";
|
callbackParams.errorCallbackMethod = "handleFailedScreensharePresence";
|
||||||
|
QJsonObject callbackData;
|
||||||
|
callbackData.insert("roomname", roomname);
|
||||||
|
callbackData.insert("avatarID", avatarID.toString());
|
||||||
|
callbackParams.callbackData = callbackData;
|
||||||
const QString PATH = "api/v1/domains/%1/screenshare";
|
const QString PATH = "api/v1/domains/%1/screenshare";
|
||||||
QString domain_id = uuidStringWithoutCurlyBraces(getID());
|
QString domain_id = uuidStringWithoutCurlyBraces(getID());
|
||||||
QJsonObject json, screenshare;
|
QJsonObject json, screenshare;
|
||||||
|
@ -3666,11 +3670,17 @@ void DomainServer::screensharePresence(QString roomname, QString username, int e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply) {
|
void DomainServer::handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData) {
|
||||||
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
|
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
|
||||||
if (jsonObject["status"].toString() != "success") {
|
if (jsonObject["status"].toString() != "success") {
|
||||||
qCWarning(domain_server) << "screensharePresence api call failed:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
|
qCWarning(domain_server) << "screensharePresence api call failed:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto nodeList = DependencyManager::get<LimitedNodeList>();
|
||||||
|
auto packet = NLPacket::create(PacketType::AvatarZonePresence, NUM_BYTES_RFC4122_UUID, true);
|
||||||
|
packet->write(QUuid(callbackData["roomname"].toString()).toRfc4122());
|
||||||
|
nodeList->sendPacket(std::move(packet), *(nodeList->nodeWithUUID(QUuid(callbackData["avatarID"].toString()))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainServer::handleFailedScreensharePresence(QNetworkReply* requestReply) {
|
void DomainServer::handleFailedScreensharePresence(QNetworkReply* requestReply) {
|
||||||
|
|
|
@ -78,7 +78,7 @@ public:
|
||||||
|
|
||||||
bool isAssetServerEnabled();
|
bool isAssetServerEnabled();
|
||||||
|
|
||||||
void screensharePresence(QString roomname, QString username, int expiration_seconds = 0);
|
void screensharePresence(QString roomname, QString username, QUuid avatarID, int expiration_seconds = 0);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// Called by NodeList to inform us a node has been added
|
/// Called by NodeList to inform us a node has been added
|
||||||
|
@ -132,7 +132,7 @@ private slots:
|
||||||
void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply);
|
void handleSuccessfulICEServerAddressUpdate(QNetworkReply* requestReply);
|
||||||
void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply);
|
void handleFailedICEServerAddressUpdate(QNetworkReply* requestReply);
|
||||||
|
|
||||||
void handleSuccessfulScreensharePresence(QNetworkReply* requestReply);
|
void handleSuccessfulScreensharePresence(QNetworkReply* requestReply, QJsonObject callbackData);
|
||||||
void handleFailedScreensharePresence(QNetworkReply* requestReply);
|
void handleFailedScreensharePresence(QNetworkReply* requestReply);
|
||||||
|
|
||||||
void updateReplicatedNodes();
|
void updateReplicatedNodes();
|
||||||
|
|
|
@ -37,14 +37,41 @@ ScreenshareScriptingInterface::ScreenshareScriptingInterface() {
|
||||||
_requestScreenshareInfoRetryTimer->setSingleShot(true);
|
_requestScreenshareInfoRetryTimer->setSingleShot(true);
|
||||||
_requestScreenshareInfoRetryTimer->setInterval(SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS);
|
_requestScreenshareInfoRetryTimer->setInterval(SCREENSHARE_INFO_REQUEST_RETRY_TIMEOUT_MS);
|
||||||
connect(_requestScreenshareInfoRetryTimer, &QTimer::timeout, this, &ScreenshareScriptingInterface::requestScreenshareInfo);
|
connect(_requestScreenshareInfoRetryTimer, &QTimer::timeout, this, &ScreenshareScriptingInterface::requestScreenshareInfo);
|
||||||
|
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
PacketReceiver& packetReceiver = nodeList->getPacketReceiver();
|
||||||
|
packetReceiver.registerListener(PacketType::AvatarZonePresence, this, "processAvatarZonePresencePacketOnClient");
|
||||||
};
|
};
|
||||||
|
|
||||||
ScreenshareScriptingInterface::~ScreenshareScriptingInterface() {
|
ScreenshareScriptingInterface::~ScreenshareScriptingInterface() {
|
||||||
stopScreenshare();
|
stopScreenshare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenshareScriptingInterface::processAvatarZonePresencePacketOnClient(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||||
|
QUuid zone = QUuid::fromRfc4122(message->readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||||
|
|
||||||
|
if (zone.isNull()) {
|
||||||
|
qWarning() << "Ignoring avatar zone presence packet that doesn't specify a zone.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastAuthorizedZoneID = zone;
|
||||||
|
|
||||||
|
if (_waitingForAuthorization) {
|
||||||
|
requestScreenshareInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const int MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES = 5;
|
static const int MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES = 5;
|
||||||
void ScreenshareScriptingInterface::requestScreenshareInfo() {
|
void ScreenshareScriptingInterface::requestScreenshareInfo() {
|
||||||
|
if (_screenshareZoneID != _lastAuthorizedZoneID) {
|
||||||
|
qDebug() << "Client not yet authorized to screenshare. Waiting for authorization message from domain server...";
|
||||||
|
_waitingForAuthorization = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_waitingForAuthorization = false;
|
||||||
|
|
||||||
_requestScreenshareInfoRetries++;
|
_requestScreenshareInfoRetries++;
|
||||||
|
|
||||||
if (_requestScreenshareInfoRetries >= MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES) {
|
if (_requestScreenshareInfoRetries >= MAX_NUM_SCREENSHARE_INFO_REQUEST_RETRIES) {
|
||||||
|
@ -174,6 +201,7 @@ void ScreenshareScriptingInterface::stopScreenshare() {
|
||||||
_projectAPIKey = "";
|
_projectAPIKey = "";
|
||||||
_sessionID = "";
|
_sessionID = "";
|
||||||
_isPresenter = false;
|
_isPresenter = false;
|
||||||
|
_waitingForAuthorization = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when the Metaverse returns the information necessary to start/view a screen share.
|
// Called when the Metaverse returns the information necessary to start/view a screen share.
|
||||||
|
|
|
@ -41,6 +41,8 @@ private slots:
|
||||||
void handleFailedScreenshareInfoGet(QNetworkReply* reply);
|
void handleFailedScreenshareInfoGet(QNetworkReply* reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void processAvatarZonePresencePacketOnClient(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||||
|
|
||||||
#if DEV_BUILD
|
#if DEV_BUILD
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
const QString SCREENSHARE_EXE_PATH{ PathUtils::projectRootPath() + "/screenshare/hifi-screenshare-win32-x64/hifi-screenshare.exe" };
|
const QString SCREENSHARE_EXE_PATH{ PathUtils::projectRootPath() + "/screenshare/hifi-screenshare-win32-x64/hifi-screenshare.exe" };
|
||||||
|
@ -82,6 +84,9 @@ private:
|
||||||
QUuid _screenshareZoneID;
|
QUuid _screenshareZoneID;
|
||||||
QUuid _smartboardEntityID;
|
QUuid _smartboardEntityID;
|
||||||
bool _isPresenter{ false };
|
bool _isPresenter{ false };
|
||||||
|
|
||||||
|
QUuid _lastAuthorizedZoneID;
|
||||||
|
bool _waitingForAuthorization{ false };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ScreenshareScriptingInterface_h
|
#endif // hifi_ScreenshareScriptingInterface_h
|
||||||
|
|
|
@ -61,6 +61,18 @@ JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSONCallbackParameters::JSONCallbackParameters(QObject* callbackReceiver,
|
||||||
|
const QString& jsonCallbackMethod,
|
||||||
|
const QString& errorCallbackMethod,
|
||||||
|
const QJsonObject& callbackData) :
|
||||||
|
callbackReceiver(callbackReceiver),
|
||||||
|
jsonCallbackMethod(jsonCallbackMethod),
|
||||||
|
errorCallbackMethod(errorCallbackMethod),
|
||||||
|
callbackData(callbackData)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply* requestReply) {
|
QJsonObject AccountManager::dataObjectFromResponse(QNetworkReply* requestReply) {
|
||||||
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
|
QJsonObject jsonObject = QJsonDocument::fromJson(requestReply->readAll()).object();
|
||||||
|
|
||||||
|
@ -348,9 +360,17 @@ void AccountManager::sendRequest(const QString& path,
|
||||||
[callbackParams, networkReply] {
|
[callbackParams, networkReply] {
|
||||||
if (networkReply->error() == QNetworkReply::NoError) {
|
if (networkReply->error() == QNetworkReply::NoError) {
|
||||||
if (!callbackParams.jsonCallbackMethod.isEmpty()) {
|
if (!callbackParams.jsonCallbackMethod.isEmpty()) {
|
||||||
bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
bool invoked = false;
|
||||||
qPrintable(callbackParams.jsonCallbackMethod),
|
if (callbackParams.callbackData.isEmpty()) {
|
||||||
Q_ARG(QNetworkReply*, networkReply));
|
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||||
|
qPrintable(callbackParams.jsonCallbackMethod),
|
||||||
|
Q_ARG(QNetworkReply*, networkReply));
|
||||||
|
} else {
|
||||||
|
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||||
|
qPrintable(callbackParams.jsonCallbackMethod),
|
||||||
|
Q_ARG(QNetworkReply*, networkReply),
|
||||||
|
Q_ARG(QJsonObject, callbackParams.callbackData));
|
||||||
|
}
|
||||||
|
|
||||||
if (!invoked) {
|
if (!invoked) {
|
||||||
QString error = "Could not invoke " + callbackParams.jsonCallbackMethod + " with QNetworkReply* "
|
QString error = "Could not invoke " + callbackParams.jsonCallbackMethod + " with QNetworkReply* "
|
||||||
|
@ -366,9 +386,18 @@ void AccountManager::sendRequest(const QString& path,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!callbackParams.errorCallbackMethod.isEmpty()) {
|
if (!callbackParams.errorCallbackMethod.isEmpty()) {
|
||||||
bool invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
bool invoked = false;
|
||||||
qPrintable(callbackParams.errorCallbackMethod),
|
if (callbackParams.callbackData.isEmpty()) {
|
||||||
Q_ARG(QNetworkReply*, networkReply));
|
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||||
|
qPrintable(callbackParams.errorCallbackMethod),
|
||||||
|
Q_ARG(QNetworkReply*, networkReply));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
invoked = QMetaObject::invokeMethod(callbackParams.callbackReceiver,
|
||||||
|
qPrintable(callbackParams.errorCallbackMethod),
|
||||||
|
Q_ARG(QNetworkReply*, networkReply),
|
||||||
|
Q_ARG(QJsonObject, callbackParams.callbackData));
|
||||||
|
}
|
||||||
|
|
||||||
if (!invoked) {
|
if (!invoked) {
|
||||||
QString error = "Could not invoke " + callbackParams.errorCallbackMethod + " with QNetworkReply* "
|
QString error = "Could not invoke " + callbackParams.errorCallbackMethod + " with QNetworkReply* "
|
||||||
|
|
|
@ -31,13 +31,15 @@ class JSONCallbackParameters {
|
||||||
public:
|
public:
|
||||||
JSONCallbackParameters(QObject* callbackReceiver = nullptr,
|
JSONCallbackParameters(QObject* callbackReceiver = nullptr,
|
||||||
const QString& jsonCallbackMethod = QString(),
|
const QString& jsonCallbackMethod = QString(),
|
||||||
const QString& errorCallbackMethod = QString());
|
const QString& errorCallbackMethod = QString(),
|
||||||
|
const QJsonObject& callbackData = QJsonObject());
|
||||||
|
|
||||||
bool isEmpty() const { return !callbackReceiver; }
|
bool isEmpty() const { return !callbackReceiver; }
|
||||||
|
|
||||||
QObject* callbackReceiver;
|
QObject* callbackReceiver;
|
||||||
QString jsonCallbackMethod;
|
QString jsonCallbackMethod;
|
||||||
QString errorCallbackMethod;
|
QString errorCallbackMethod;
|
||||||
|
QJsonObject callbackData;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace AccountManagerAuth {
|
namespace AccountManagerAuth {
|
||||||
|
|
Loading…
Reference in a new issue