Skip to content

Commit 62a9165

Browse files
authored
Discovery mode revisited (#374)
* Remove commented out code * Replace discovery_mode with sneakily stashing Host header in the web::uri
1 parent ba267fa commit 62a9165

10 files changed

+60
-78
lines changed

Development/nmos-cpp-node/config.json

-3
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,6 @@
235235
// proxy_port [registry, node]: forward proxy port
236236
//"proxy_port": 8080,
237237

238-
// discovery_mode [node]: whether the discovered host name (1) or resolved addresses (2) are used to construct request URLs for Registration APIs or System APIs
239-
//"discovery_mode": 1,
240-
241238
// href_mode [registry, node]: whether the host name (1), addresses (2) or both (3) are used to construct response headers, and host and URL fields in the data model
242239
//"href_mode": 1,
243240

Development/nmos/authorization_operation.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1200,7 +1200,7 @@ namespace nmos
12001200
const auto service = top_authorization_service(model.settings);
12011201

12021202
const auto auth_uri = service.second;
1203-
client.reset(new web::http::client::http_client(auth_uri, make_authorization_http_client_config(model.settings, load_ca_certificates, gate)));
1203+
client = nmos::details::make_http_client(auth_uri, make_authorization_http_client_config(model.settings, load_ca_certificates, gate));
12041204

12051205
auto token = cancellation_source.get_token();
12061206

Development/nmos/authorization_state.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace nmos
2828
, immediate(true)
2929
, received(false) {}
3030

31-
pubkeys_shared_state(web::http::client::http_client client, nmos::api_version version, web::uri issuer)//, bool one_shot = false)
31+
pubkeys_shared_state(web::http::client::http_client client, nmos::api_version version, web::uri issuer)
3232
: engine(seeder)
3333
, client(std::unique_ptr<web::http::client::http_client>(new web::http::client::http_client(client)))
3434
, version(std::move(version))

Development/nmos/client_utils.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,26 @@ namespace nmos
256256
return config;
257257
}
258258

259+
namespace details
260+
{
261+
// make a client for the specified base_uri and config, with Host header sneakily stashed in user info
262+
std::unique_ptr<web::http::client::http_client> make_http_client(const web::uri& base_uri, const web::http::client::http_client_config& client_config)
263+
{
264+
// unstash the Host header
265+
// cf. nmos::details::resolve_service
266+
const auto& host_name = base_uri.user_info();
267+
std::unique_ptr<web::http::client::http_client> client(new web::http::client::http_client(web::uri_builder(base_uri).set_user_info({}).to_uri(), client_config));
268+
if (!host_name.empty())
269+
{
270+
client->add_handler([host_name](web::http::http_request request, std::shared_ptr<web::http::http_pipeline_stage> next_stage) -> pplx::task<web::http::http_response>
271+
{
272+
request.headers().add(web::http::header_names::host, host_name);
273+
return next_stage->propagate(request);
274+
});
275+
}
276+
return client;
277+
}
278+
}
259279

260280
// make a request with logging
261281
pplx::task<web::http::http_response> api_request(web::http::client::http_client client, web::http::http_request request, slog::base_gate& gate, const pplx::cancellation_token& token)

Development/nmos/client_utils.h

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ namespace nmos
3131
web::websockets::client::websocket_client_config make_websocket_client_config(const nmos::settings& settings, load_ca_certificates_handler load_ca_certificates, nmos::experimental::get_authorization_bearer_token_handler get_authorization_bearer_token, slog::base_gate& gate);
3232
web::websockets::client::websocket_client_config make_websocket_client_config(const nmos::settings& settings, load_ca_certificates_handler load_ca_certificates, slog::base_gate& gate);
3333

34+
namespace details
35+
{
36+
// make a client for the specified base_uri and config, with Host header sneakily stashed in user info
37+
std::unique_ptr<web::http::client::http_client> make_http_client(const web::uri& base_uri_with_host_name_in_user_info, const web::http::client::http_client_config& client_config);
38+
}
39+
3440
// make an API request with logging
3541
pplx::task<web::http::http_response> api_request(web::http::client::http_client client, web::http::http_request request, slog::base_gate& gate, const pplx::cancellation_token& token = pplx::cancellation_token::none());
3642
pplx::task<web::http::http_response> api_request(web::http::client::http_client client, const web::http::method& mtd, slog::base_gate& gate, const pplx::cancellation_token& token = pplx::cancellation_token::none());

Development/nmos/mdns.cpp

+22-62
Original file line numberDiff line numberDiff line change
@@ -495,44 +495,11 @@ namespace nmos
495495
update_service(advertiser, service, domain, settings, std::move(add_records));
496496
}
497497

498-
enum discovery_mode
499-
{
500-
discovery_mode_default = 0,
501-
discovery_mode_name = 1,
502-
discovery_mode_addresses = 2
503-
};
504-
505498
namespace details
506499
{
507500
typedef std::vector<resolved_service> resolved_services;
508501

509-
std::vector<utility::string_t> get_resolved_hosts(const mdns::resolve_result& resolved, const nmos::service_protocol& resolved_proto, discovery_mode mode)
510-
{
511-
std::vector<utility::string_t> results;
512-
513-
// by default, use the host name if secure communications are in use
514-
if (mode == discovery_mode_name || (mode == discovery_mode_default && is_service_protocol_secure(resolved_proto)))
515-
{
516-
auto host_name = utility::s2us(resolved.host_name);
517-
// remove a trailing '.' to turn an FQDN into a DNS name, for SSL certificate matching
518-
// hmm, this might be more appropriately done by tweaking the Host header in the client request?
519-
if (!host_name.empty() && U('.') == host_name.back()) host_name.pop_back();
520-
521-
results.push_back(host_name);
522-
}
523-
524-
if (mode == discovery_mode_addresses || (mode == discovery_mode_default && !is_service_protocol_secure(resolved_proto)))
525-
{
526-
for (const auto& ip_address : resolved.ip_addresses)
527-
{
528-
results.push_back(utility::s2us(ip_address));
529-
}
530-
}
531-
532-
return results;
533-
}
534-
535-
pplx::task<bool> resolve_service(std::shared_ptr<resolved_services> results, mdns::service_discovery& discovery, discovery_mode discovery_mode, 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, const std::chrono::steady_clock::time_point& timeout, const pplx::cancellation_token& token)
502+
pplx::task<bool> resolve_service(std::shared_ptr<resolved_services> results, 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, const std::chrono::steady_clock::time_point& timeout, const pplx::cancellation_token& token)
536503
{
537504
return discovery.browse([=, &discovery](const mdns::browse_result& resolving)
538505
{
@@ -588,12 +555,17 @@ namespace nmos
588555
.set_path(U("/x-nmos/") + utility::s2us(details::service_api(service)));
589556
}
590557

591-
auto resolved_hosts = get_resolved_hosts(resolved, resolved_proto, discovery_mode);
558+
auto host_name = utility::s2us(resolved.host_name);
559+
// remove a trailing '.' to turn an FQDN into a DNS name, for SSL certificate matching
560+
if (!host_name.empty() && U('.') == host_name.back()) host_name.pop_back();
592561

593-
for (const auto& host : resolved_hosts)
562+
for (const auto& ip_address : resolved.ip_addresses)
594563
{
564+
// sneakily stash the Host header in user info
565+
// cf. nmos::details::make_http_client
595566
results->push_back({ { *resolved_ver, resolved_pri }, resolved_uri
596-
.set_host(host)
567+
.set_user_info(host_name)
568+
.set_host(utility::s2us(ip_address))
597569
.to_uri()
598570
});
599571
}
@@ -618,7 +590,9 @@ namespace nmos
618590
}
619591
}
620592

621-
pplx::task<std::list<resolved_service>> resolve_service_(mdns::service_discovery& discovery, discovery_mode mode, 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)
593+
// helper function for resolving instances of the specified service (API)
594+
// with the highest version, highest priority instances at the front, and optionally services with the same priority ordered randomly
595+
pplx::task<std::list<resolved_service>> 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)
622596
{
623597
const auto absolute_timeout = std::chrono::steady_clock::now() + timeout;
624598

@@ -646,8 +620,8 @@ namespace nmos
646620
};
647621

648622
const std::vector<pplx::task<bool>> both_tasks{
649-
details::resolve_service(both_results[0], discovery, mode, nmos::service_types::register_, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, linked_token),
650-
details::resolve_service(both_results[1], discovery, mode, service, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, linked_token)
623+
details::resolve_service(both_results[0], discovery, nmos::service_types::register_, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, linked_token),
624+
details::resolve_service(both_results[1], discovery, service, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, linked_token)
651625
};
652626

653627
// when either task is completed, cancel and wait for the other to be completed
@@ -675,12 +649,12 @@ namespace nmos
675649
}
676650
else
677651
{
678-
resolve_task = details::resolve_service(results, discovery, mode, nmos::service_types::register_, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, token);
652+
resolve_task = details::resolve_service(results, discovery, nmos::service_types::register_, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, token);
679653
}
680654
}
681655
else
682656
{
683-
resolve_task = details::resolve_service(results, discovery, mode, service, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, token);
657+
resolve_task = details::resolve_service(results, discovery, service, browse_domain, api_ver, priorities, api_proto, api_auth, absolute_timeout, token);
684658
}
685659

686660
return resolve_task.then([results, randomize](bool)
@@ -722,9 +696,11 @@ namespace nmos
722696
});
723697
}
724698

725-
pplx::task<std::list<web::uri>> resolve_service(mdns::service_discovery& discovery, discovery_mode mode, 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)
699+
// helper function for resolving instances of the specified service (API)
700+
// with the highest version, highest priority instances at the front, and optionally services with the same priority ordered randomly
701+
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)
726702
{
727-
return resolve_service_(discovery, mode, service, browse_domain, api_ver, priorities, api_proto, api_auth, randomize, timeout, token).then([](std::list<resolved_service> resolved_services)
703+
return resolve_service_(discovery, service, browse_domain, api_ver, priorities, api_proto, api_auth, randomize, timeout, token).then([](std::list<resolved_service> resolved_services)
728704
{
729705
// add the version to each uri
730706
return boost::copy_range<std::list<web::uri>>(resolved_services | boost::adaptors::transformed([](const resolved_service& s)
@@ -734,18 +710,10 @@ namespace nmos
734710
});
735711
}
736712

737-
// helper function for resolving instances of the specified service (API)
738-
// with the highest version, highest priority instances at the front, and (by default) services with the same priority ordered randomly
739-
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)
740-
{
741-
return resolve_service(discovery, discovery_mode_default, service, browse_domain, api_ver, priorities, api_proto, api_auth, randomize, timeout, token);
742-
}
743-
744713
// helper function for resolving instances of the specified service (API) based on the specified settings
745714
// with the highest version, highest priority instances at the front, and services with the same priority ordered randomly
746715
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)
747716
{
748-
const auto mode = discovery_mode(nmos::experimental::fields::discovery_mode(settings));
749717
const auto browse_domain = utility::us2s(nmos::get_domain(settings));
750718
const auto versions = details::service_versions(service, settings);
751719
const auto priorities = details::service_priorities(service, settings);
@@ -756,21 +724,13 @@ namespace nmos
756724
// when no cancellation token is specified
757725
const auto timeout = token.is_cancelable() ? nmos::fields::discovery_backoff_max(settings) : 1;
758726

759-
return resolve_service(discovery, mode, service, browse_domain, versions, priorities, protocols, authorization, true, std::chrono::seconds(timeout), token);
760-
}
761-
762-
// helper function for resolving instances of the specified service (API)
763-
// with the highest version, highest priority instances at the front, and (by default) services with the same priority ordered randomly
764-
pplx::task<std::list<resolved_service>> 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)
765-
{
766-
return resolve_service_(discovery, discovery_mode_default, service, browse_domain, api_ver, priorities, api_proto, api_auth, randomize, timeout, token);
727+
return resolve_service(discovery, service, browse_domain, versions, priorities, protocols, authorization, true, std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::seconds(timeout)), token);
767728
}
768729

769730
// helper function for resolving instances of the specified service (API) based on the specified settings
770731
// with the highest version, highest priority instances at the front, and services with the same priority ordered randomly
771732
pplx::task<std::list<resolved_service>> resolve_service_(mdns::service_discovery& discovery, const nmos::service_type& service, const nmos::settings& settings, const pplx::cancellation_token& token)
772733
{
773-
const auto mode = discovery_mode(nmos::experimental::fields::discovery_mode(settings));
774734
const auto browse_domain = utility::us2s(nmos::get_domain(settings));
775735
const auto versions = details::service_versions(service, settings);
776736
const auto priorities = details::service_priorities(service, settings);
@@ -781,7 +741,7 @@ namespace nmos
781741
// when no cancellation token is specified
782742
const auto timeout = token.is_cancelable() ? nmos::fields::discovery_backoff_max(settings) : 1;
783743

784-
return resolve_service_(discovery, mode, service, browse_domain, versions, priorities, protocols, authorization, true, std::chrono::seconds(timeout), token);
744+
return resolve_service_(discovery, service, browse_domain, versions, priorities, protocols, authorization, true, std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::seconds(timeout)), token);
785745
}
786746
}
787747
}

0 commit comments

Comments
 (0)