blob: ad2ff48473fab910259a4d3b5ce8aa297ce5cf59 [file] [log] [blame]
Austin Schuh75263e32022-02-22 18:05:32 -08001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include "wpi/MulticastServiceAnnouncer.h"
6
7#include <wpi/SmallString.h>
8
9#include "dns_sd.h"
10
11using namespace wpi;
12
13struct MulticastServiceAnnouncer::Impl {
14 std::string serviceName;
15 std::string serviceType;
16 int port;
17 DNSServiceRef serviceRef{nullptr};
18 TXTRecordRef txtRecord;
19
20 Impl() { TXTRecordCreate(&txtRecord, 0, nullptr); }
21
22 ~Impl() noexcept { TXTRecordDeallocate(&txtRecord); }
23};
24
25MulticastServiceAnnouncer::MulticastServiceAnnouncer(
26 std::string_view serviceName, std::string_view serviceType, int port,
27 wpi::span<const std::pair<std::string, std::string>> txt) {
28 pImpl = std::make_unique<Impl>();
29 pImpl->serviceName = serviceName;
30 pImpl->serviceType = serviceType;
31 pImpl->port = port;
32
33 for (auto&& i : txt) {
34 TXTRecordSetValue(&pImpl->txtRecord, i.first.c_str(), i.second.length(),
35 i.second.c_str());
36 }
37}
38
39MulticastServiceAnnouncer::MulticastServiceAnnouncer(
40 std::string_view serviceName, std::string_view serviceType, int port,
41 wpi::span<const std::pair<std::string_view, std::string_view>> txt) {
42 pImpl = std::make_unique<Impl>();
43 pImpl->serviceName = serviceName;
44 pImpl->serviceType = serviceType;
45 pImpl->port = port;
46
47 wpi::SmallString<64> key;
48
49 for (auto&& i : txt) {
50 key.clear();
51 key.append(i.first);
52 key.emplace_back('\0');
53
54 TXTRecordSetValue(&pImpl->txtRecord, key.data(), i.second.length(),
55 i.second.data());
56 }
57}
58
59MulticastServiceAnnouncer::~MulticastServiceAnnouncer() noexcept {
60 Stop();
61}
62
63bool MulticastServiceAnnouncer::HasImplementation() const {
64 return true;
65}
66
67void MulticastServiceAnnouncer::Start() {
68 if (pImpl->serviceRef) {
69 return;
70 }
71
72 uint16_t len = TXTRecordGetLength(&pImpl->txtRecord);
73 const void* ptr = TXTRecordGetBytesPtr(&pImpl->txtRecord);
74
75 (void)DNSServiceRegister(&pImpl->serviceRef, 0, 0, pImpl->serviceName.c_str(),
76 pImpl->serviceType.c_str(), "local", nullptr,
77 htons(pImpl->port), len, ptr, nullptr, nullptr);
78}
79
80void MulticastServiceAnnouncer::Stop() {
81 if (!pImpl->serviceRef) {
82 return;
83 }
84 DNSServiceRefDeallocate(pImpl->serviceRef);
85 pImpl->serviceRef = nullptr;
86}