Offset the ports used for WOL if the host is using alternate ports

This commit is contained in:
Cameron Gutman 2022-11-13 11:39:28 -06:00
parent 6710d0561a
commit dd9de3fcb4

View file

@ -222,20 +222,27 @@ bool NvComputer::wake() const
Q_ASSERT(wolPayload.count() == 102); Q_ASSERT(wolPayload.count() == 102);
} }
const quint16 WOL_PORTS[] = { // Ports used as-is
const quint16 STATIC_WOL_PORTS[] = {
9, // Standard WOL port (privileged port) 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) 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 // Add the addresses that we know this host to be
// and broadcast addresses for this link just in // and broadcast addresses for this link just in
// case the host has timed out in ARP entries. // case the host has timed out in ARP entries.
QVector<QString> addressList; QMap<QString, quint16> addressMap;
QSet<quint16> basePortSet;
for (const NvAddress& addr : uniqueAddresses()) { 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 // Try to broadcast on all available NICs
for (const QNetworkInterface& nic : QNetworkInterface::allInterfaces()) { for (const QNetworkInterface& nic : QNetworkInterface::allInterfaces()) {
@ -254,22 +261,22 @@ bool NvComputer::wake() const
// Skip IPv6 which doesn't support broadcast // Skip IPv6 which doesn't support broadcast
if (!addr.broadcast().isNull()) { if (!addr.broadcast().isNull()) {
addressList.append(addr.broadcast().toString()); addressMap.insert(addr.broadcast().toString(), 0);
} }
} }
if (!allNodesMulticast.scopeId().isEmpty()) { if (!allNodesMulticast.scopeId().isEmpty()) {
addressList.append(allNodesMulticast.toString()); addressMap.insert(allNodesMulticast.toString(), 0);
} }
} }
// Try all unique address strings or host names // Try all unique address strings or host names
bool success = false; bool success = false;
for (QString& addressString : addressList) { for (auto i = addressMap.constBegin(); i != addressMap.constEnd(); i++) {
QHostInfo hostInfo = QHostInfo::fromName(addressString); QHostInfo hostInfo = QHostInfo::fromName(i.key());
if (hostInfo.error() != QHostInfo::NoError) { if (hostInfo.error() != QHostInfo::NoError) {
qWarning() << "Error resolving" << addressString << ":" << hostInfo.errorString(); qWarning() << "Error resolving" << i.key() << ":" << hostInfo.errorString();
continue; continue;
} }
@ -277,8 +284,8 @@ bool NvComputer::wake() const
for (QHostAddress& address : hostInfo.addresses()) { for (QHostAddress& address : hostInfo.addresses()) {
QUdpSocket sock; QUdpSocket sock;
// Send to all ports // Send to all static ports
for (quint16 port : WOL_PORTS) { for (quint16 port : STATIC_WOL_PORTS) {
if (sock.writeDatagram(wolPayload, address, port)) { if (sock.writeDatagram(wolPayload, address, port)) {
qInfo().nospace().noquote() << "Sent WoL packet to " << name << " via " << address.toString() << ":" << port; qInfo().nospace().noquote() << "Sent WoL packet to " << name << " via " << address.toString() << ":" << port;
success = true; success = true;
@ -287,6 +294,31 @@ bool NvComputer::wake() const
qWarning() << "Send failed:" << sock.error(); qWarning() << "Send failed:" << sock.error();
} }
} }
QList<quint16> 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();
}
}
}
} }
} }