diff --git a/app/backend/nvcomputer.cpp b/app/backend/nvcomputer.cpp index 4217dd37..b52ee516 100644 --- a/app/backend/nvcomputer.cpp +++ b/app/backend/nvcomputer.cpp @@ -222,20 +222,27 @@ bool NvComputer::wake() const Q_ASSERT(wolPayload.count() == 102); } - const quint16 WOL_PORTS[] = { + // Ports used as-is + const quint16 STATIC_WOL_PORTS[] = { 9, // Standard WOL port (privileged port) - 47998, 47999, 48000, 48002, 48010, // Ports opened by GFE 47009, // Port opened by Moonlight Internet Hosting Tool for WoL (non-privileged port) }; + // Ports offset by the HTTP base port for hosts using alternate ports + const quint16 DYNAMIC_WOL_PORTS[] = { + 47998, 47999, 48000, 48002, 48010, // Ports opened by GFE + }; + // Add the addresses that we know this host to be // and broadcast addresses for this link just in // case the host has timed out in ARP entries. - QVector addressList; + QMap addressMap; + QSet basePortSet; for (const NvAddress& addr : uniqueAddresses()) { - addressList.append(addr.address()); + addressMap.insert(addr.address(), addr.port()); + basePortSet.insert(addr.port()); } - addressList.append("255.255.255.255"); + addressMap.insert("255.255.255.255", 0); // Try to broadcast on all available NICs for (const QNetworkInterface& nic : QNetworkInterface::allInterfaces()) { @@ -254,22 +261,22 @@ bool NvComputer::wake() const // Skip IPv6 which doesn't support broadcast if (!addr.broadcast().isNull()) { - addressList.append(addr.broadcast().toString()); + addressMap.insert(addr.broadcast().toString(), 0); } } if (!allNodesMulticast.scopeId().isEmpty()) { - addressList.append(allNodesMulticast.toString()); + addressMap.insert(allNodesMulticast.toString(), 0); } } // Try all unique address strings or host names bool success = false; - for (QString& addressString : addressList) { - QHostInfo hostInfo = QHostInfo::fromName(addressString); + for (auto i = addressMap.constBegin(); i != addressMap.constEnd(); i++) { + QHostInfo hostInfo = QHostInfo::fromName(i.key()); if (hostInfo.error() != QHostInfo::NoError) { - qWarning() << "Error resolving" << addressString << ":" << hostInfo.errorString(); + qWarning() << "Error resolving" << i.key() << ":" << hostInfo.errorString(); continue; } @@ -277,8 +284,8 @@ bool NvComputer::wake() const for (QHostAddress& address : hostInfo.addresses()) { QUdpSocket sock; - // Send to all ports - for (quint16 port : WOL_PORTS) { + // Send to all static ports + for (quint16 port : STATIC_WOL_PORTS) { if (sock.writeDatagram(wolPayload, address, port)) { qInfo().nospace().noquote() << "Sent WoL packet to " << name << " via " << address.toString() << ":" << port; success = true; @@ -287,6 +294,31 @@ bool NvComputer::wake() const qWarning() << "Send failed:" << sock.error(); } } + + QList basePorts; + if (i.value() != 0) { + // If we have a known base port for this address, use only that port + basePorts.append(i.value()); + } + else { + // If this is a broadcast address without a known HTTP port, try all of them + basePorts.append(basePortSet.values()); + } + + // Send to all dynamic ports using the HTTP port offset(s) for this address + for (quint16 basePort : basePorts) { + for (quint16 port : DYNAMIC_WOL_PORTS) { + port = (port - 47989) + basePort; + + if (sock.writeDatagram(wolPayload, address, port)) { + qInfo().nospace().noquote() << "Sent WoL packet to " << name << " via " << address.toString() << ":" << port; + success = true; + } + else { + qWarning() << "Send failed:" << sock.error(); + } + } + } } }