ref:50eb6e478f01e19c84237062fcd9f1071e952574

feat(linux): advertise sunshine_name over mDNS so per-VM instances don't collide

The Avahi service instance name came from the host name, so two Sunshine instances on one host (one per VM) both registered "<host>" and the second was renamed to "<host> #2". The name now follows sunshine_name, which defaults to the host name, so a single instance advertises what it did before. Refs #6 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SHA: 50eb6e478f01e19c84237062fcd9f1071e952574
Author: Cole Christensen <cole.christensen@gmail.com>
Date: 2026-09-13 01:00
Parents: cbc1a54
4 files changed +34 -1
Type
src/network.cpp +6 −0
@@ -10,6 +10,7 @@
#include "config.h"
#include "logging.h"
#include "network.h"
#include "platform/common.h"
#include "utility.h"
using namespace std::literals;
@@ -259,5 +260,10 @@
}
return !instancename.empty() ? instancename : "Sunshine";
}
std::string mdns_service_name() {
const auto &name = config::nvhttp.sunshine_name;
return mdns_instance_name(!name.empty() ? name : platf::get_host_name());
}
} // namespace net
src/network.h +9 −0
@@ -155,4 +155,13 @@
* @return Hostname-based instance name or "Sunshine" if hostname is invalid.
*/
std::string mdns_instance_name(const std::string_view &hostname);
/**
* @brief Returns the mDNS service instance name this Sunshine advertises.
* @details Uses `sunshine_name`, so several Sunshine instances on one host (for example one per
* VM) are listed separately instead of colliding on the host name. Falls back to the host name
* when `sunshine_name` is empty.
* @return Instance name derived from `sunshine_name` or the host name.
*/
std::string mdns_service_name();
} // namespace net
src/platform/linux/publish.cpp +1 −1
@@ -571,7 +571,7 @@
return nullptr;
}
auto instance_name = net::mdns_instance_name(platf::get_host_name());
auto instance_name = net::mdns_service_name();
name.reset(avahi::strdup(instance_name.c_str()));
client.reset(
tests/unit/test_network.cpp +18 −0
@@ -7,6 +7,8 @@
#include "../tests_common.h"
// local includes
#include <src/config.h>
#include <src/network.h>
#include <src/platform/common.h>
struct MdnsInstanceNameTest: BaseTest, testing::WithParamInterface<std::tuple<std::string, std::string>> {};
@@ -29,6 +31,22 @@
std::make_tuple(std::string(128, 'a'), std::string(63, 'a'))
)
);
// @tag requirements: [REQ-DEP-001]
TEST(MdnsServiceNameTest, FollowsSunshineNameSoInstancesOnOneHostDiffer) {
const auto saved = config::nvhttp.sunshine_name;
config::nvhttp.sunshine_name = "sq-vm-1";
EXPECT_EQ(net::mdns_service_name(), "sq-vm-1");
config::nvhttp.sunshine_name = "win11 vm.example";
EXPECT_EQ(net::mdns_service_name(), "win11-vm");
// without a name, the host name is advertised as before
config::nvhttp.sunshine_name = "";
EXPECT_EQ(net::mdns_service_name(), net::mdns_instance_name(platf::get_host_name()));
config::nvhttp.sunshine_name = saved;
}
/**
* @brief Test fixture for bind_address tests with setup/teardown