diff --git a/app/backend/computermanager.cpp b/app/backend/computermanager.cpp index 6dd0bf36..3372ccbb 100644 --- a/app/backend/computermanager.cpp +++ b/app/backend/computermanager.cpp @@ -29,7 +29,7 @@ public: private: bool tryPollComputer(NvAddress address, bool& changed) { - NvHTTP http(address, m_Computer->serverCert); + NvHTTP http(address, 0, m_Computer->serverCert); QString serverInfo; try { @@ -595,7 +595,7 @@ void ComputerManager::addNewHostManually(QString address) QUrl url = QUrl::fromUserInput(address); if (url.isValid() && !url.host().isEmpty()) { // If there wasn't a port specified, use the default - addNewHost(NvAddress(url.host(), url.port(47989)), false); + addNewHost(NvAddress(url.host(), url.port(DEFAULT_HTTP_PORT)), false); } else { emit computerAddCompleted(false, false); @@ -671,7 +671,7 @@ private: void run() { - NvHTTP http(m_Address, QSslCertificate()); + NvHTTP http(m_Address, 0, QSslCertificate()); qInfo() << "Processing new PC at" << m_Address.toString() << "from" << (m_Mdns ? "mDNS" : "user") << "with IPv6 address" << m_MdnsIpv6Address.toString(); @@ -701,6 +701,7 @@ private: // Fetch serverinfo again over HTTPS with the pinned cert if (existingComputer != nullptr) { + Q_ASSERT(http.httpsPort() != 0); serverInfo = fetchServerInfo(http); if (serverInfo.isEmpty()) { return; diff --git a/app/backend/nvaddress.h b/app/backend/nvaddress.h index d20c7d2e..69eca066 100644 --- a/app/backend/nvaddress.h +++ b/app/backend/nvaddress.h @@ -2,6 +2,9 @@ #include +#define DEFAULT_HTTP_PORT 47989 +#define DEFAULT_HTTPS_PORT 47984 + class NvAddress { public: diff --git a/app/backend/nvcomputer.cpp b/app/backend/nvcomputer.cpp index 94efaeda..802624f2 100644 --- a/app/backend/nvcomputer.cpp +++ b/app/backend/nvcomputer.cpp @@ -7,8 +7,6 @@ #include #include -#define DEFAULT_HTTP_PORT 47989 - #define SER_NAME "hostname" #define SER_UUID "uuid" #define SER_MAC "mac" @@ -62,6 +60,7 @@ NvComputer::NvComputer(QSettings& settings) this->gpuModel = nullptr; this->isSupportedServerVersion = true; this->externalPort = this->remoteAddress.port(); + this->activeHttpsPort = 0; } void NvComputer::setRemoteAddress(QHostAddress address) @@ -156,10 +155,15 @@ NvComputer::NvComputer(NvHTTP& http, QString serverInfo) this->localAddress = NvAddress(); } + QString httpsPort = NvHTTP::getXmlString(serverInfo, "HttpsPort"); + if (httpsPort.isEmpty() || (this->activeHttpsPort = httpsPort.toUShort()) == 0) { + this->activeHttpsPort = DEFAULT_HTTPS_PORT; + } + // This is an extension which is not present in GFE. It is present for Sunshine to be able // to support dynamic HTTP WAN ports without requiring the user to manually enter the port. QString remotePortStr = NvHTTP::getXmlString(serverInfo, "ExternalPort"); - if (remotePortStr.isEmpty() || (this->externalPort = this->remoteAddress.port()) == 0) { + if (remotePortStr.isEmpty() || (this->externalPort = remotePortStr.toUShort()) == 0) { this->externalPort = DEFAULT_HTTP_PORT; } @@ -442,6 +446,8 @@ bool NvComputer::update(NvComputer& that) ASSIGN_IF_CHANGED_AND_NONNULL(remoteAddress); ASSIGN_IF_CHANGED_AND_NONNULL(ipv6Address); ASSIGN_IF_CHANGED_AND_NONNULL(manualAddress); + ASSIGN_IF_CHANGED(activeHttpsPort); + ASSIGN_IF_CHANGED(externalPort); ASSIGN_IF_CHANGED(pairState); ASSIGN_IF_CHANGED(serverCodecModeSupport); ASSIGN_IF_CHANGED(currentGameId); diff --git a/app/backend/nvcomputer.h b/app/backend/nvcomputer.h index 8f4e1b02..1942c427 100644 --- a/app/backend/nvcomputer.h +++ b/app/backend/nvcomputer.h @@ -62,6 +62,7 @@ public: ComputerState state; PairState pairState; NvAddress activeAddress; + uint16_t activeHttpsPort; int currentGameId; QString gfeVersion; QString appVersion; diff --git a/app/backend/nvhttp.cpp b/app/backend/nvhttp.cpp index b578e8b0..4f96b585 100644 --- a/app/backend/nvhttp.cpp +++ b/app/backend/nvhttp.cpp @@ -18,16 +18,14 @@ #define RESUME_TIMEOUT_MS 30000 #define QUIT_TIMEOUT_MS 30000 -NvHTTP::NvHTTP(NvAddress address, QSslCertificate serverCert) : +NvHTTP::NvHTTP(NvAddress address, uint16_t httpsPort, QSslCertificate serverCert) : m_ServerCert(serverCert) { m_BaseUrlHttp.setScheme("http"); m_BaseUrlHttps.setScheme("https"); setAddress(address); - - // TODO: Use HttpsPort - setHttpsPort(47984); + setHttpsPort(httpsPort); // Never use a proxy server QNetworkProxy noProxy(QNetworkProxy::NoProxy); @@ -37,7 +35,7 @@ NvHTTP::NvHTTP(NvAddress address, QSslCertificate serverCert) : } NvHTTP::NvHTTP(NvComputer* computer) : - NvHTTP(computer->activeAddress, computer->serverCert) + NvHTTP(computer->activeAddress, computer->activeHttpsPort, computer->serverCert) { } @@ -127,8 +125,8 @@ NvHTTP::getServerInfo(NvLogLevel logLevel, bool fastFail) { QString serverInfo; - // Check if we have a pinned cert for this host yet - if (!m_ServerCert.isNull()) + // Check if we have a pinned cert and HTTPS port for this host yet + if (!m_ServerCert.isNull() && httpsPort() != 0) { try { @@ -163,13 +161,26 @@ NvHTTP::getServerInfo(NvLogLevel logLevel, bool fastFail) } else { - // Only use HTTP prior to pairing + // Only use HTTP prior to pairing or fetching HTTPS port serverInfo = openConnectionToString(m_BaseUrlHttp, "serverinfo", nullptr, fastFail ? FAST_FAIL_TIMEOUT_MS : REQUEST_TIMEOUT_MS, logLevel); verifyResponseStatus(serverInfo); + + // Populate the HTTPS port + uint16_t httpsPort = getXmlString(serverInfo, "HttpsPort").toUShort(); + if (httpsPort == 0) { + httpsPort = DEFAULT_HTTPS_PORT; + } + setHttpsPort(httpsPort); + + // If we just needed to determine the HTTPS port, we'll try again over + // HTTPS now that we have the port number + if (!m_ServerCert.isNull()) { + return getServerInfo(logLevel, fastFail); + } } return serverInfo; @@ -477,6 +488,9 @@ NvHTTP::openConnection(QUrl baseUrl, int timeoutMs, NvLogLevel logLevel) { + // Port must be set + Q_ASSERT(baseUrl.port(0) != 0); + // Build a URL for the request QUrl url(baseUrl); url.setPath("/" + command); diff --git a/app/backend/nvhttp.h b/app/backend/nvhttp.h index a08657a9..01715f41 100644 --- a/app/backend/nvhttp.h +++ b/app/backend/nvhttp.h @@ -109,7 +109,7 @@ public: NVLL_VERBOSE }; - explicit NvHTTP(NvAddress address, QSslCertificate serverCert); + explicit NvHTTP(NvAddress address, uint16_t httpsPort, QSslCertificate serverCert); explicit NvHTTP(NvComputer* computer);