forked from sony/nmos-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mdns.h
178 lines (137 loc) · 10.3 KB
/
mdns.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#ifndef NMOS_MDNS_H
#define NMOS_MDNS_H
#include <list>
#include "cpprest/base_uri.h"
#include "mdns/core.h" // for mdns::structured_txt_records
#include "nmos/is04_versions.h"
#include "nmos/settings.h" // just a forward declaration of nmos::settings required for nmos::experimental functions
namespace mdns
{
class service_advertiser;
class service_discovery;
}
namespace nmos
{
// "APIs MUST produce an mDNS advertisement [...] accompanied by DNS TXT records"
// See https://specs.amwa.tv/is-04/releases/v1.2.0/APIs/RegistrationAPI.html#dns_sd_advertisement etc.
typedef std::string service_type;
namespace service_types
{
// IS-04 Node API
const service_type node{ "_nmos-node._tcp" };
// IS-04 Query API
const service_type query{ "_nmos-query._tcp" };
// IS-04 Registration API
// "RFC6763 Section 7.2 specifies that the maximum service name length for an mDNS advertisement
// is 16 characters when including the leading underscore, but "_nmos-registration" is 18 characters."
// See https://specs.amwa.tv/is-04/releases/v1.2.1/APIs/RegistrationAPI.html#dns_sd_advertisement
// This was addressed in v1.3, by specifying a shorter service type, "_nmos-register._tcp".
// See https://specs.amwa.tv/is-04/releases/v1.3.0/docs/3.1._Discovery_-_Registered_Operation.html#dns-sd-advertisement
const service_type registration{ "_nmos-registration._tcp" };
// IS-09 System API (originally specified in JT-NM TR-1001-1:2018 Annex A)
const service_type system{ "_nmos-system._tcp" };
// IS-10 Authorization API
const service_type authorization{ "_nmos-auth._tcp" };
// MQTT Broker
// See https://specs.amwa.tv/is-07/releases/v1.0.1/docs/5.1._Transport_-_MQTT.html#7-broker-discovery
const service_type mqtt{ "_nmos-mqtt._tcp" };
}
// "The DNS-SD advertisement MUST be accompanied by a TXT record of name 'api_proto' with a value
// of either 'http' or 'https' dependent on the protocol in use by the [...] server."
// (However, v1.0 did not include this record, so when it is omitted, "http" should be assumed.)
typedef std::string service_protocol;
namespace service_protocols
{
// Values for the 'api_proto' TXT record for e.g. IS-04 Registration API, IS-04 Query API, IS-09 System API and IS-10 Authorization API
// See https://specs.amwa.tv/is-04/releases/v1.3.1/docs/3.1._Discovery_-_Registered_Operation.html#dns-sd-txt-records
// and https://specs.amwa.tv/is-09/releases/v1.0.0/docs/3.1._Discovery_-_Operation.html#dns-sd-txt-records
// and https://specs.amwa.tv/is-10/releases/v1.0.0/docs/3.0._Discovery.html#dns-sd-txt-records
const service_protocol http{ "http" };
const service_protocol https{ "https" };
// Values for the 'api_proto' TXT record for MQTT broker advertisements
// See https://specs.amwa.tv/is-07/releases/v1.0.1/docs/5.1._Transport_-_MQTT.html#7-broker-discovery
const service_protocol mqtt{ "mqtt" };
const service_protocol secure_mqtt{ "secure-mqtt" };
const std::set<service_protocol> all{ nmos::service_protocols::http, nmos::service_protocols::https };
}
// returns true if the specified service protocol is secure
bool is_service_protocol_secure(const service_protocol& api_proto);
// returns e.g. "http" or "https" depending on settings
service_protocol get_service_protocol(const nmos::service_type& service, const nmos::settings& settings);
// find and parse the 'api_proto' TXT record (or return the default)
service_protocol parse_api_proto_record(const mdns::structured_txt_records& records);
// "The DNS-SD advertisement MUST be accompanied by a TXT record of name 'api_ver'.
// The value of this TXT record is a comma separated list of API versions supported by the server.
// There should be no whitespace between commas, and versions should be listed in ascending order."
// (However, v1.0 did not include this record, so when it is omitted, "v1.0" should be assumed.)
namespace is04_versions
{
const std::set<api_version> unspecified{ nmos::is04_versions::v1_0 };
}
// find and parse the 'api_ver' TXT record (or return the default)
std::set<api_version> parse_api_ver_record(const mdns::structured_txt_records& records);
// "The DNS-SD advertisement MUST be accompanied by a TXT record of name 'api_auth'
// with a value of either 'true' or 'false' dependent on whether authorization is required
// in order to interact with the API or not."
// (This record is added in v1.3, so when it is omitted, "false" should be assumed.)
// returns true or false depending on settings
bool get_service_authorization(const nmos::service_type& service, const nmos::settings& settings);
// find and parse the 'api_auth' TXT record (or return the default)
bool parse_api_auth_record(const mdns::structured_txt_records& records);
// "The DNS-SD advertisement MUST include a TXT record with key 'pri' and an integer value.
// Values 0 to 99 correspond to an active NMOS Registration API (zero being the highest priority).
// Values 100+ are reserved for development work to avoid colliding with a live system."
typedef int service_priority;
namespace service_priorities
{
const service_priority highest_active_priority = 0;
const service_priority lowest_active_priority = 99;
const service_priority highest_development_priority = 100;
const service_priority no_priority = (std::numeric_limits<int>::max)();
}
// find and parse the 'pri' TXT record
service_priority parse_pri_record(const mdns::structured_txt_records& records);
// make the required TXT records from the specified values (or sensible default values)
mdns::structured_txt_records make_txt_records(const nmos::service_type& service, service_priority pri = service_priorities::highest_development_priority, const std::set<api_version>& api_ver = is04_versions::all, const service_protocol& api_proto = service_protocols::http, bool api_auth = false);
// "The value of each of the ['ver_' TXT records] should be an unsigned 8-bit integer initialised
// to '0'. This integer MUST be incremented and mDNS TXT record updated whenever a change is made
// to the corresponding HTTP API resource on the Node. The integer must wrap back to a value of
// '0' after reaching a maximum value of '255' (MAX_UINT8_T)."
typedef unsigned char api_resource_version;
struct api_resource_versions
{
api_resource_version self = 0;
api_resource_version devices = 0;
api_resource_version sources = 0;
api_resource_version flows = 0;
api_resource_version senders = 0;
api_resource_version receivers = 0;
};
// find and parse the Node 'ver_' TXT records
api_resource_versions parse_ver_records(const mdns::structured_txt_records& records);
// make the Node 'ver_' TXT records from the specified values
mdns::structured_txt_records make_ver_records(const api_resource_versions& ver);
namespace experimental
{
// helper function for registering addresses when the host name is explicitly configured
void register_addresses(mdns::service_advertiser& advertiser, const nmos::settings& settings);
// helper function for registering the specified service (API)
void register_service(mdns::service_advertiser& advertiser, const nmos::service_type& service, const nmos::settings& settings);
// helper function for updating the specified service (API) TXT records
void update_service(mdns::service_advertiser& advertiser, const nmos::service_type& service, const nmos::settings& settings, mdns::structured_txt_records add_records = {});
// helper function for resolving instances of the specified service (API)
// with the highest version, highest priority instances at the front, and (by default) services with the same priority ordered randomly
pplx::task<std::list<web::uri>> resolve_service(mdns::service_discovery& discovery, const nmos::service_type& service, const std::string& browse_domain, const std::set<nmos::api_version>& api_ver, const std::pair<nmos::service_priority, nmos::service_priority>& priorities, const std::set<nmos::service_protocol>& api_proto, const std::set<bool>& api_auth, bool randomize, const std::chrono::steady_clock::duration& timeout, const pplx::cancellation_token& token = pplx::cancellation_token::none());
// helper function for resolving instances of the specified service (API) based on the specified options or defaults
// with the highest version, highest priority instances at the front, and (by default) services with the same priority ordered randomly
template <typename Rep = std::chrono::seconds::rep, typename Period = std::chrono::seconds::period>
inline pplx::task<std::list<web::uri>> resolve_service(mdns::service_discovery& discovery, const nmos::service_type& service, const std::string& browse_domain = {}, const std::set<nmos::api_version>& api_ver = nmos::is04_versions::all, const std::pair<nmos::service_priority, nmos::service_priority>& priorities = { service_priorities::highest_active_priority, service_priorities::no_priority }, const std::set<nmos::service_protocol>& api_proto = nmos::service_protocols::all, const std::set<bool>& api_auth = { false, true }, bool randomize = true, const std::chrono::duration<Rep, Period>& timeout = std::chrono::seconds(mdns::default_timeout_seconds), const pplx::cancellation_token& token = pplx::cancellation_token::none())
{
return resolve_service(discovery, service, browse_domain, api_ver, api_proto, api_auth, randomize, std::chrono::duration_cast<std::chrono::steady_clock::duration>(timeout), token);
}
// helper function for resolving instances of the specified service (API) based on the specified settings
// with the highest version, highest priority instances at the front, and services with the same priority ordered randomly
pplx::task<std::list<web::uri>> resolve_service(mdns::service_discovery& discovery, const nmos::service_type& service, const nmos::settings& settings, const pplx::cancellation_token& token = pplx::cancellation_token::none());
}
}
#endif