Skip to content

Commit

Permalink
fix(mdns): don't hardcode mDNS instance name
Browse files Browse the repository at this point in the history
  • Loading branch information
cgutman committed Aug 25, 2024
1 parent c9f853d commit ca5036c
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 4 deletions.
28 changes: 28 additions & 0 deletions src/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,32 @@ namespace net {

return mapped_port;
}

/**
* @brief Returns a string for use as the instance name for mDNS.
* @return Hostname-based instance name or "Sunshine" if hostname is invalid.
*/
std::string
mdns_instance_name() {
std::string hostname = boost::asio::ip::host_name();

// Truncate to 63 characters per RFC 6763 section 7.2.
if (hostname.size() > 63) {
hostname.resize(63);
}

for (auto i = 0; i < hostname.size(); i++) {
// Replace any spaces with dashes
if (hostname[i] == ' ') {
hostname[i] = '-';

Check warning on line 226 in src/network.cpp

View check run for this annotation

Codecov / codecov/patch

src/network.cpp#L226

Added line #L226 was not covered by tests
}
else if (!std::isalnum(hostname[i]) && hostname[i] != '-') {
// Stop at the first invalid character
hostname.resize(i);
break;
}
}

return !hostname.empty() ? hostname : "Sunshine";
}
} // namespace net
7 changes: 7 additions & 0 deletions src/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,11 @@ namespace net {
*/
int
encryption_mode_for_address(boost::asio::ip::address address);

/**
* @brief Returns a string for use as the instance name for mDNS.
* @return Hostname-based instance name or "Sunshine" if hostname is invalid.
*/
std::string
mdns_instance_name();
} // namespace net
3 changes: 2 additions & 1 deletion src/platform/linux/publish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,8 @@ namespace platf::publish {
return nullptr;
}

name.reset(avahi::strdup(SERVICE_NAME));
auto instance_name = net::mdns_instance_name();

Check warning on line 429 in src/platform/linux/publish.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/linux/publish.cpp#L429

Added line #L429 was not covered by tests
name.reset(avahi::strdup(instance_name.c_str()));

client.reset(
avahi::client_new(avahi::simple_poll_get(poll.get()), avahi::ClientFlags(0), client_callback, nullptr, &avhi_error));
Expand Down
3 changes: 2 additions & 1 deletion src/platform/macos/publish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ namespace platf::publish {
&serviceRef,
0, // flags
0, // interfaceIndex
SERVICE_NAME, SERVICE_TYPE,
nullptr, // name
SERVICE_TYPE,
nullptr, // domain
nullptr, // host
htons(net::map_port(nvhttp::PORT_HTTP)),
Expand Down
3 changes: 1 addition & 2 deletions src/platform/windows/publish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ constexpr auto DNS_QUERY_RESULTS_VERSION1 = 0x1;

#define SERVICE_DOMAIN "local"

constexpr auto SERVICE_INSTANCE_NAME = SV(SERVICE_NAME "." SERVICE_TYPE "." SERVICE_DOMAIN);
constexpr auto SERVICE_TYPE_DOMAIN = SV(SERVICE_TYPE "." SERVICE_DOMAIN);

#ifndef __MINGW32__
Expand Down Expand Up @@ -107,8 +106,8 @@ namespace platf::publish {
service(bool enable, PDNS_SERVICE_INSTANCE &existing_instance) {
auto alarm = safe::make_alarm<PDNS_SERVICE_INSTANCE>();

std::wstring name { SERVICE_INSTANCE_NAME.data(), SERVICE_INSTANCE_NAME.size() };
std::wstring domain { SERVICE_TYPE_DOMAIN.data(), SERVICE_TYPE_DOMAIN.size() };
std::wstring name = from_utf8(net::mdns_instance_name() + '.') + domain;

auto host = from_utf8(boost::asio::ip::host_name() + ".local");

Expand Down
23 changes: 23 additions & 0 deletions tests/unit/test_network.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @file tests/unit/test_network.cpp
* @brief Test src/network.*
*/
#include <src/network.h>

#include "../tests_common.h"

TEST(MdnsInstanceNameTests, ValidLength) {
auto name = net::mdns_instance_name();

// The instance name must be 63 characters or less
EXPECT_LT(name.size(), 64);
}

TEST(MdnsInstanceNameTests, ValidCharacters) {
auto name = net::mdns_instance_name();

// The string must not contain invalid hostname characters
for (const char& c : name) {
EXPECT_TRUE(std::isalnum(c) || c == '-');
}
}

0 comments on commit ca5036c

Please sign in to comment.