diff --git a/app/backend/nvhttp.cpp b/app/backend/nvhttp.cpp index c95f46bb..d1d3acba 100644 --- a/app/backend/nvhttp.cpp +++ b/app/backend/nvhttp.cpp @@ -13,6 +13,9 @@ #include #define REQUEST_TIMEOUT_MS 5000 +#define LAUNCH_TIMEOUT_MS 120000 +#define RESUME_TIMEOUT_MS 30000 +#define QUIT_TIMEOUT_MS 30000 NvHTTP::NvHTTP(QString address, QSslCertificate serverCert) : m_Address(address), @@ -89,7 +92,7 @@ NvHTTP::getServerInfo(NvLogLevel logLevel) serverInfo = openConnectionToString(m_BaseUrlHttps, "serverinfo", nullptr, - true, + REQUEST_TIMEOUT_MS, logLevel); // Throws if the request failed verifyResponseStatus(serverInfo); @@ -102,7 +105,7 @@ NvHTTP::getServerInfo(NvLogLevel logLevel) serverInfo = openConnectionToString(m_BaseUrlHttp, "serverinfo", nullptr, - true, + REQUEST_TIMEOUT_MS, logLevel); verifyResponseStatus(serverInfo); } @@ -119,7 +122,7 @@ NvHTTP::getServerInfo(NvLogLevel logLevel) serverInfo = openConnectionToString(m_BaseUrlHttp, "serverinfo", nullptr, - true, + REQUEST_TIMEOUT_MS, logLevel); verifyResponseStatus(serverInfo); } @@ -180,7 +183,7 @@ NvHTTP::launchApp(int appId, "&surroundAudioInfo="+getSurroundAudioInfoString(streamConfig->audioConfiguration)+ "&remoteControllersBitmap="+QString::number(gamepadMask)+ "&gcmap="+QString::number(gamepadMask), - false); + LAUNCH_TIMEOUT_MS); // Throws if the request failed verifyResponseStatus(response); @@ -200,7 +203,7 @@ NvHTTP::resumeApp(PSTREAM_CONFIGURATION streamConfig) "rikey="+QString(QByteArray(streamConfig->remoteInputAesKey, sizeof(streamConfig->remoteInputAesKey)).toHex())+ "&rikeyid="+QString::number(riKeyId)+ "&surroundAudioInfo="+getSurroundAudioInfoString(streamConfig->audioConfiguration), - false); + RESUME_TIMEOUT_MS); // Throws if the request failed verifyResponseStatus(response); @@ -213,7 +216,7 @@ NvHTTP::quitApp() openConnectionToString(m_BaseUrlHttps, "cancel", nullptr, - false); + QUIT_TIMEOUT_MS); // Throws if the request failed verifyResponseStatus(response); @@ -260,7 +263,7 @@ NvHTTP::getAppList() QString appxml = openConnectionToString(m_BaseUrlHttps, "applist", nullptr, - true, + REQUEST_TIMEOUT_MS, NvLogLevel::ERROR); verifyResponseStatus(appxml); @@ -328,7 +331,7 @@ NvHTTP::getBoxArt(int appId) "appasset", "appid="+QString::number(appId)+ "&AssetType=2&AssetIdx=0", - true, + REQUEST_TIMEOUT_MS, NvLogLevel::VERBOSE); QImage image = QImageReader(reply).read(); delete reply; @@ -375,10 +378,10 @@ QString NvHTTP::openConnectionToString(QUrl baseUrl, QString command, QString arguments, - bool enableTimeout, + int timeoutMs, NvLogLevel logLevel) { - QNetworkReply* reply = openConnection(baseUrl, command, arguments, enableTimeout, logLevel); + QNetworkReply* reply = openConnection(baseUrl, command, arguments, timeoutMs, logLevel); QString ret; QTextStream stream(reply); @@ -393,7 +396,7 @@ QNetworkReply* NvHTTP::openConnection(QUrl baseUrl, QString command, QString arguments, - bool enableTimeout, + int timeoutMs, NvLogLevel logLevel) { // Build a URL for the request @@ -434,9 +437,8 @@ NvHTTP::openConnection(QUrl baseUrl, // Run the request with a timeout if requested QEventLoop loop; QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); - if (enableTimeout) - { - QTimer::singleShot(REQUEST_TIMEOUT_MS, &loop, SLOT(quit())); + if (timeoutMs) { + QTimer::singleShot(timeoutMs, &loop, SLOT(quit())); } if (logLevel >= NvLogLevel::VERBOSE) { qInfo() << "Executing request:" << url.toString(); @@ -470,6 +472,11 @@ NvHTTP::openConnection(QUrl baseUrl, delete reply; throw exception; } + else if (reply->error() == QNetworkReply::OperationCanceledError) { + QtNetworkReplyException exception(QNetworkReply::TimeoutError, "Request timed out"); + delete reply; + throw exception; + } else { QtNetworkReplyException exception(reply->error(), reply->errorString()); delete reply; diff --git a/app/backend/nvhttp.h b/app/backend/nvhttp.h index 014d87cf..3586400f 100644 --- a/app/backend/nvhttp.h +++ b/app/backend/nvhttp.h @@ -149,7 +149,7 @@ public: openConnectionToString(QUrl baseUrl, QString command, QString arguments, - bool enableTimeout, + int timeoutMs, NvLogLevel logLevel = NvLogLevel::VERBOSE); void setServerCert(QSslCertificate serverCert); @@ -188,7 +188,7 @@ private: openConnection(QUrl baseUrl, QString command, QString arguments, - bool enableTimeout, + int timeoutMs, NvLogLevel logLevel); QString m_Address; diff --git a/app/backend/nvpairingmanager.cpp b/app/backend/nvpairingmanager.cpp index 9e3e4455..a1a3dcdb 100644 --- a/app/backend/nvpairingmanager.cpp +++ b/app/backend/nvpairingmanager.cpp @@ -8,6 +8,8 @@ #include #include +#define REQUEST_TIMEOUT_MS 5000 + NvPairingManager::NvPairingManager(QString address) : m_Http(address, QSslCertificate()) { @@ -192,7 +194,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC "pair", "devicename=roth&updateState=1&phrase=getservercert&salt=" + salt.toHex() + "&clientcert=" + IdentityManager::get()->getCertificate().toHex(), - false); + 0); NvHTTP::verifyResponseStatus(getCert); if (NvHTTP::getXmlString(getCert, "paired") != "1") { @@ -204,7 +206,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC if (serverCertStr == nullptr) { qCritical() << "Server likely already pairing"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::ALREADY_IN_PROGRESS; } @@ -213,7 +215,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC Q_ASSERT(!serverCert.isNull()); qCritical() << "Failed to parse plaincert"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::FAILED; } @@ -226,12 +228,12 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC "pair", "devicename=roth&updateState=1&clientchallenge=" + encryptedChallenge.toHex(), - true); + REQUEST_TIMEOUT_MS); NvHTTP::verifyResponseStatus(challengeXml); if (NvHTTP::getXmlString(challengeXml, "paired") != "1") { qCritical() << "Failed pairing at stage #2"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::FAILED; } @@ -259,12 +261,12 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC "pair", "devicename=roth&updateState=1&serverchallengeresp=" + encryptedChallengeResponseHash.toHex(), - true); + REQUEST_TIMEOUT_MS); NvHTTP::verifyResponseStatus(respXml); if (NvHTTP::getXmlString(respXml, "paired") != "1") { qCritical() << "Failed pairing at stage #3"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::FAILED; } @@ -277,7 +279,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC serverCertStr)) { qCritical() << "MITM detected"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::FAILED; } @@ -288,7 +290,7 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC if (QCryptographicHash::hash(expectedResponseData, hashAlgo) != serverResponse) { qCritical() << "Incorrect PIN"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::PIN_WRONG; } @@ -300,24 +302,24 @@ NvPairingManager::pair(QString appVersion, QString pin, QSslCertificate& serverC "pair", "devicename=roth&updateState=1&clientpairingsecret=" + clientPairingSecret.toHex(), - true); + REQUEST_TIMEOUT_MS); NvHTTP::verifyResponseStatus(secretRespXml); if (NvHTTP::getXmlString(secretRespXml, "paired") != "1") { qCritical() << "Failed pairing at stage #4"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::FAILED; } QString pairChallengeXml = m_Http.openConnectionToString(m_Http.m_BaseUrlHttps, "pair", "devicename=roth&updateState=1&phrase=pairchallenge", - true); + REQUEST_TIMEOUT_MS); NvHTTP::verifyResponseStatus(pairChallengeXml); if (NvHTTP::getXmlString(pairChallengeXml, "paired") != "1") { qCritical() << "Failed pairing at stage #5"; - m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, true); + m_Http.openConnectionToString(m_Http.m_BaseUrlHttp, "unpair", nullptr, REQUEST_TIMEOUT_MS); return PairState::FAILED; }