Add support for dynamic HTTPS port

This commit is contained in:
Cameron Gutman 2021-07-03 00:00:27 -05:00
parent 043c55ae66
commit 48728efee0
6 changed files with 40 additions and 15 deletions

View File

@ -29,7 +29,7 @@ public:
private: private:
bool tryPollComputer(NvAddress address, bool& changed) bool tryPollComputer(NvAddress address, bool& changed)
{ {
NvHTTP http(address, m_Computer->serverCert); NvHTTP http(address, 0, m_Computer->serverCert);
QString serverInfo; QString serverInfo;
try { try {
@ -595,7 +595,7 @@ void ComputerManager::addNewHostManually(QString address)
QUrl url = QUrl::fromUserInput(address); QUrl url = QUrl::fromUserInput(address);
if (url.isValid() && !url.host().isEmpty()) { if (url.isValid() && !url.host().isEmpty()) {
// If there wasn't a port specified, use the default // 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 { else {
emit computerAddCompleted(false, false); emit computerAddCompleted(false, false);
@ -671,7 +671,7 @@ private:
void run() 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(); 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 // Fetch serverinfo again over HTTPS with the pinned cert
if (existingComputer != nullptr) { if (existingComputer != nullptr) {
Q_ASSERT(http.httpsPort() != 0);
serverInfo = fetchServerInfo(http); serverInfo = fetchServerInfo(http);
if (serverInfo.isEmpty()) { if (serverInfo.isEmpty()) {
return; return;

View File

@ -2,6 +2,9 @@
#include <QHostAddress> #include <QHostAddress>
#define DEFAULT_HTTP_PORT 47989
#define DEFAULT_HTTPS_PORT 47984
class NvAddress class NvAddress
{ {
public: public:

View File

@ -7,8 +7,6 @@
#include <QNetworkInterface> #include <QNetworkInterface>
#include <QNetworkProxy> #include <QNetworkProxy>
#define DEFAULT_HTTP_PORT 47989
#define SER_NAME "hostname" #define SER_NAME "hostname"
#define SER_UUID "uuid" #define SER_UUID "uuid"
#define SER_MAC "mac" #define SER_MAC "mac"
@ -62,6 +60,7 @@ NvComputer::NvComputer(QSettings& settings)
this->gpuModel = nullptr; this->gpuModel = nullptr;
this->isSupportedServerVersion = true; this->isSupportedServerVersion = true;
this->externalPort = this->remoteAddress.port(); this->externalPort = this->remoteAddress.port();
this->activeHttpsPort = 0;
} }
void NvComputer::setRemoteAddress(QHostAddress address) void NvComputer::setRemoteAddress(QHostAddress address)
@ -156,10 +155,15 @@ NvComputer::NvComputer(NvHTTP& http, QString serverInfo)
this->localAddress = NvAddress(); 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 // 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. // to support dynamic HTTP WAN ports without requiring the user to manually enter the port.
QString remotePortStr = NvHTTP::getXmlString(serverInfo, "ExternalPort"); 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; 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(remoteAddress);
ASSIGN_IF_CHANGED_AND_NONNULL(ipv6Address); ASSIGN_IF_CHANGED_AND_NONNULL(ipv6Address);
ASSIGN_IF_CHANGED_AND_NONNULL(manualAddress); ASSIGN_IF_CHANGED_AND_NONNULL(manualAddress);
ASSIGN_IF_CHANGED(activeHttpsPort);
ASSIGN_IF_CHANGED(externalPort);
ASSIGN_IF_CHANGED(pairState); ASSIGN_IF_CHANGED(pairState);
ASSIGN_IF_CHANGED(serverCodecModeSupport); ASSIGN_IF_CHANGED(serverCodecModeSupport);
ASSIGN_IF_CHANGED(currentGameId); ASSIGN_IF_CHANGED(currentGameId);

View File

@ -62,6 +62,7 @@ public:
ComputerState state; ComputerState state;
PairState pairState; PairState pairState;
NvAddress activeAddress; NvAddress activeAddress;
uint16_t activeHttpsPort;
int currentGameId; int currentGameId;
QString gfeVersion; QString gfeVersion;
QString appVersion; QString appVersion;

View File

@ -18,16 +18,14 @@
#define RESUME_TIMEOUT_MS 30000 #define RESUME_TIMEOUT_MS 30000
#define QUIT_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_ServerCert(serverCert)
{ {
m_BaseUrlHttp.setScheme("http"); m_BaseUrlHttp.setScheme("http");
m_BaseUrlHttps.setScheme("https"); m_BaseUrlHttps.setScheme("https");
setAddress(address); setAddress(address);
setHttpsPort(httpsPort);
// TODO: Use HttpsPort
setHttpsPort(47984);
// Never use a proxy server // Never use a proxy server
QNetworkProxy noProxy(QNetworkProxy::NoProxy); QNetworkProxy noProxy(QNetworkProxy::NoProxy);
@ -37,7 +35,7 @@ NvHTTP::NvHTTP(NvAddress address, QSslCertificate serverCert) :
} }
NvHTTP::NvHTTP(NvComputer* computer) : 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; QString serverInfo;
// Check if we have a pinned cert for this host yet // Check if we have a pinned cert and HTTPS port for this host yet
if (!m_ServerCert.isNull()) if (!m_ServerCert.isNull() && httpsPort() != 0)
{ {
try try
{ {
@ -163,13 +161,26 @@ NvHTTP::getServerInfo(NvLogLevel logLevel, bool fastFail)
} }
else else
{ {
// Only use HTTP prior to pairing // Only use HTTP prior to pairing or fetching HTTPS port
serverInfo = openConnectionToString(m_BaseUrlHttp, serverInfo = openConnectionToString(m_BaseUrlHttp,
"serverinfo", "serverinfo",
nullptr, nullptr,
fastFail ? FAST_FAIL_TIMEOUT_MS : REQUEST_TIMEOUT_MS, fastFail ? FAST_FAIL_TIMEOUT_MS : REQUEST_TIMEOUT_MS,
logLevel); logLevel);
verifyResponseStatus(serverInfo); 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; return serverInfo;
@ -477,6 +488,9 @@ NvHTTP::openConnection(QUrl baseUrl,
int timeoutMs, int timeoutMs,
NvLogLevel logLevel) NvLogLevel logLevel)
{ {
// Port must be set
Q_ASSERT(baseUrl.port(0) != 0);
// Build a URL for the request // Build a URL for the request
QUrl url(baseUrl); QUrl url(baseUrl);
url.setPath("/" + command); url.setPath("/" + command);

View File

@ -109,7 +109,7 @@ public:
NVLL_VERBOSE NVLL_VERBOSE
}; };
explicit NvHTTP(NvAddress address, QSslCertificate serverCert); explicit NvHTTP(NvAddress address, uint16_t httpsPort, QSslCertificate serverCert);
explicit NvHTTP(NvComputer* computer); explicit NvHTTP(NvComputer* computer);