blob: ad2ff48473fab910259a4d3b5ce8aa297ce5cf59 [file] [log] [blame]
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "wpi/MulticastServiceAnnouncer.h"
#include <wpi/SmallString.h>
#include "dns_sd.h"
using namespace wpi;
struct MulticastServiceAnnouncer::Impl {
std::string serviceName;
std::string serviceType;
int port;
DNSServiceRef serviceRef{nullptr};
TXTRecordRef txtRecord;
Impl() { TXTRecordCreate(&txtRecord, 0, nullptr); }
~Impl() noexcept { TXTRecordDeallocate(&txtRecord); }
};
MulticastServiceAnnouncer::MulticastServiceAnnouncer(
std::string_view serviceName, std::string_view serviceType, int port,
wpi::span<const std::pair<std::string, std::string>> txt) {
pImpl = std::make_unique<Impl>();
pImpl->serviceName = serviceName;
pImpl->serviceType = serviceType;
pImpl->port = port;
for (auto&& i : txt) {
TXTRecordSetValue(&pImpl->txtRecord, i.first.c_str(), i.second.length(),
i.second.c_str());
}
}
MulticastServiceAnnouncer::MulticastServiceAnnouncer(
std::string_view serviceName, std::string_view serviceType, int port,
wpi::span<const std::pair<std::string_view, std::string_view>> txt) {
pImpl = std::make_unique<Impl>();
pImpl->serviceName = serviceName;
pImpl->serviceType = serviceType;
pImpl->port = port;
wpi::SmallString<64> key;
for (auto&& i : txt) {
key.clear();
key.append(i.first);
key.emplace_back('\0');
TXTRecordSetValue(&pImpl->txtRecord, key.data(), i.second.length(),
i.second.data());
}
}
MulticastServiceAnnouncer::~MulticastServiceAnnouncer() noexcept {
Stop();
}
bool MulticastServiceAnnouncer::HasImplementation() const {
return true;
}
void MulticastServiceAnnouncer::Start() {
if (pImpl->serviceRef) {
return;
}
uint16_t len = TXTRecordGetLength(&pImpl->txtRecord);
const void* ptr = TXTRecordGetBytesPtr(&pImpl->txtRecord);
(void)DNSServiceRegister(&pImpl->serviceRef, 0, 0, pImpl->serviceName.c_str(),
pImpl->serviceType.c_str(), "local", nullptr,
htons(pImpl->port), len, ptr, nullptr, nullptr);
}
void MulticastServiceAnnouncer::Stop() {
if (!pImpl->serviceRef) {
return;
}
DNSServiceRefDeallocate(pImpl->serviceRef);
pImpl->serviceRef = nullptr;
}