RAVENNAKIT
Loading...
Searching...
No Matches
dnssd_advertiser_example.cpp
Go to the documentation of this file.
5
6#include <iostream>
7#include <string>
8#include <vector>
9#include <boost/asio/post.hpp>
10#include <thread>
11
12namespace examples {
13
14static bool parse_txt_record(rav::dnssd::TxtRecord& txt_record, const std::string& string_value) {
15 if (string_value.empty())
16 return false;
17
18 const size_t pos = string_value.find('=');
19 if (pos != std::string::npos)
20 txt_record[string_value.substr(0, pos)] = string_value.substr(pos + 1);
21 else
22 txt_record[string_value.substr(0, pos)] = "";
23
24 return true;
25}
26
27} // namespace examples
28
29int main(int const argc, char* argv[]) {
32
33 std::vector<std::string> args;
34 for (int i = 1; i < argc; i++) {
35 args.emplace_back(argv[i]);
36 }
37
38 // Do we have at least the service type and port number?
39 if (args.size() < 2) {
40 std::cout << "Error: expected at least an argument which specifies the service type and an argument which "
41 "specifies the port number (example: _test._tcp 1234 key1=value1 key2=value2)"
42 << std::endl;
43 return -1;
44 }
45
46 // Parse port number
47 int port_number = 0;
48 try {
49 port_number = std::stoi(args[1]);
50 } catch (const std::exception& e) {
51 std::cout << "Invalid port number: " << e.what() << std::endl;
52 return -1;
53 }
54
55 // Parse remaining arguments as TxtRecord
56 rav::dnssd::TxtRecord txt_record;
57 for (auto it = args.begin() + 2; it != args.end(); ++it) {
58 examples::parse_txt_record(txt_record, *it);
59 }
60
61 boost::asio::io_context io_context;
62
63 const auto advertiser = rav::dnssd::Advertiser::create(io_context);
64
65 if (advertiser == nullptr) {
66 RAV_LOG_ERROR("Error: no dnssd advertiser implementation available for this platform");
67 return -1;
68 }
69
70 advertiser->on_error = [](const auto& error_message) {
71 RAV_LOG_ERROR("Advertiser error: {}", error_message);
72 };
73 advertiser->on_name_conflict = [](const auto* reg_type, const auto* name) {
74 RAV_LOG_CRITICAL("Name conflict: {} {}", reg_type, name);
75 };
76
77 const auto service_id =
78 advertiser->register_service(args[0], "Test service", nullptr, static_cast<uint16_t>(port_number), txt_record, true, true);
79
80 std::thread io_context_thread([&io_context] {
81 io_context.run();
82 });
83
84 RAV_LOG_INFO("Enter key=value to update the TXT record, or q to exit...");
85
86 std::string cmd;
87 while (true) {
88 std::getline(std::cin, cmd);
89 if (cmd == "q" || cmd == "Q") {
90 break;
91 }
92
93 if (cmd == "r" || cmd == "R") {
94 advertiser->unregister_service(service_id);
95 continue;
96 }
97 try {
98 if (examples::parse_txt_record(txt_record, cmd)) {
99 // Schedule the updates on the io_context thread because the advertiser is not thread-safe.
100 boost::asio::post(io_context, [=, &advertiser] {
101 advertiser->update_txt_record(service_id, txt_record);
102 RAV_LOG_INFO("Updated txt record");
103 });
104 }
105 } catch (const std::exception& e) {
106 RAV_LOG_ERROR("Failed to update txt record: {}", e.what());
107 }
108 }
109
110 io_context.stop();
111 io_context_thread.join();
112
113 std::cout << "Exit" << std::endl;
114
115 return 0;
116}
static std::unique_ptr< Advertiser > create(boost::asio::io_context &io_context)
Creates the most appropriate dnssd_advertiser implementation for the platform.
int main()
#define RAV_LOG_ERROR(...)
Definition log.hpp:106
#define RAV_LOG_CRITICAL(...)
Definition log.hpp:99
#define RAV_LOG_INFO(...)
Definition log.hpp:120
static bool parse_txt_record(rav::dnssd::TxtRecord &txt_record, const std::string &string_value)
std::map< std::string, std::string > TxtRecord
Simple typedef for representing a TXT record.
void set_log_level_from_env(const char *env_var="RAV_LOG_LEVEL")
Tries to find given environment variable and set the log level accordingly.
Definition log.hpp:216
void do_system_checks()
Definition system.hpp:33