diff --git a/app/backend/computermanager.cpp b/app/backend/computermanager.cpp index 58c0c500..535a86f5 100644 --- a/app/backend/computermanager.cpp +++ b/app/backend/computermanager.cpp @@ -878,7 +878,7 @@ private: // If this wasn't added via mDNS but it is a RFC 1918 IPv4 address and not a VPN, // go ahead and do the STUN request now to populate an external address. - if (!m_Mdns && addressIsSiteLocalV4 && !newComputer->isReachableOverVpn()) { + if (!m_Mdns && addressIsSiteLocalV4 && newComputer->getActiveAddressReachability() != NvComputer::RI_VPN) { quint32 addr; int err = LiFindExternalAddressIP4("stun.moonlight-stream.org", 3478, &addr); if (err == 0) { diff --git a/app/backend/nvcomputer.cpp b/app/backend/nvcomputer.cpp index 0b80e657..1ad659f4 100644 --- a/app/backend/nvcomputer.cpp +++ b/app/backend/nvcomputer.cpp @@ -293,7 +293,7 @@ bool NvComputer::wake() const return success; } -bool NvComputer::isReachableOverVpn() const +NvComputer::ReachabilityType NvComputer::getActiveAddressReachability() const { NvAddress copyOfActiveAddress; @@ -301,7 +301,7 @@ bool NvComputer::isReachableOverVpn() const QReadLocker readLocker(&lock); if (activeAddress.isNull()) { - return false; + return ReachabilityType::RI_UNKNOWN; } // Grab a copy of the active address to avoid having to hold @@ -332,48 +332,55 @@ bool NvComputer::isReachableOverVpn() const if (nic.type() == QNetworkInterface::Virtual || nic.type() == QNetworkInterface::Ppp) { // Treat PPP and virtual interfaces as likely VPNs - return true; + return ReachabilityType::RI_VPN; } if (nic.maximumTransmissionUnit() != 0 && nic.maximumTransmissionUnit() < 1500) { // Treat MTUs under 1500 as likely VPNs - return true; + return ReachabilityType::RI_VPN; } #endif if (nic.flags() & QNetworkInterface::IsPointToPoint) { // Treat point-to-point links as likely VPNs. // This check detects OpenVPN on Unix-like OSes. - return true; + return ReachabilityType::RI_VPN; } if (nic.hardwareAddress().startsWith("00:FF", Qt::CaseInsensitive)) { // OpenVPN TAP interfaces have a MAC address starting with 00:FF on Windows - return true; + return ReachabilityType::RI_VPN; } if (nic.humanReadableName().startsWith("ZeroTier")) { // ZeroTier interfaces always start with "ZeroTier" - return true; + return ReachabilityType::RI_VPN; } if (nic.humanReadableName().contains("VPN")) { - // This one is just a final heuristic if all else fails - return true; + // This one is just a final VPN heuristic if all else fails + return ReachabilityType::RI_VPN; } - // Didn't meet any of our VPN heuristics - return false; + // Didn't meet any of our VPN heuristics. Let's see if it's on-link. + Q_ASSERT(addr.prefixLength() >= 0); + if (addr.prefixLength() >= 0 && s.localAddress().isInSubnet(addr.ip(), addr.prefixLength())) { + return ReachabilityType::RI_LAN; + } + + // Default to unknown if nothing else matched + return ReachabilityType::RI_UNKNOWN; } } } qWarning() << "No match found for address:" << s.localAddress(); - return false; + return ReachabilityType::RI_UNKNOWN; } else { // If we fail to connect, just pretend that it's not a VPN - return false; + qWarning() << "Unable to check for reachability within 3 seconds"; + return ReachabilityType::RI_UNKNOWN; } } diff --git a/app/backend/nvcomputer.h b/app/backend/nvcomputer.h index bab7fe5c..9c959f54 100644 --- a/app/backend/nvcomputer.h +++ b/app/backend/nvcomputer.h @@ -35,8 +35,15 @@ public: bool wake() const; - bool - isReachableOverVpn() const; + enum ReachabilityType + { + RI_UNKNOWN, + RI_LAN, + RI_VPN, + }; + + ReachabilityType + getActiveAddressReachability() const; QVector uniqueAddresses() const; diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index d204a474..db7f92f2 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -1227,17 +1227,27 @@ bool Session::startConnectionAsync() m_Preferences->packetSize); } else { - // isReachableOverVpn() does network I/O, so we only attempt to check - // VPN reachability if we've already contacted the PC successfully - if (m_Computer->isReachableOverVpn()) { - // It looks like our route to this PC is over a VPN. + // Use 1392 byte video packets by default + m_StreamConfig.packetSize = 1392; + + // getActiveAddressReachability() does network I/O, so we only attempt to check + // reachability if we've already contacted the PC successfully. + switch (m_Computer->getActiveAddressReachability()) { + case NvComputer::RI_LAN: + // This address is on-link, so treat it as a local address + // even if it's not in RFC 1918 space or it's an IPv6 address. + m_StreamConfig.streamingRemotely = STREAM_CFG_LOCAL; + break; + case NvComputer::RI_VPN: + // It looks like our route to this PC is over a VPN, so cap at 1024 bytes. // Treat it as remote even if the target address is in RFC 1918 address space. m_StreamConfig.streamingRemotely = STREAM_CFG_REMOTE; m_StreamConfig.packetSize = 1024; - } - else { + break; + default: + // If we don't have reachability info, let moonlight-common-c decide. m_StreamConfig.streamingRemotely = STREAM_CFG_AUTO; - m_StreamConfig.packetSize = 1392; + break; } }