Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Development/nmos-cpp-node/node_implementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr
auto connection_sender = nmos::make_connection_events_websocket_sender(sender_id, device_id, source_id, model.settings);
connection_sender.data[nmos::fields::endpoint_active][nmos::fields::master_enable] = connection_sender.data[nmos::fields::endpoint_staged][nmos::fields::master_enable] = value::boolean(true);
resolve_auto(sender, connection_sender, connection_sender.data[nmos::fields::endpoint_active][nmos::fields::transport_params]);
nmos::set_resource_subscription(sender, nmos::fields::master_enable(connection_sender.data[nmos::fields::endpoint_active]), {}, nmos::tai_now());
nmos::set_resource_subscription(model.node_resources, sender, nmos::fields::master_enable(connection_sender.data[nmos::fields::endpoint_active]), {}, nmos::tai_now());

if (!insert_resource_after(delay_millis, model.node_resources, std::move(source), gate)) throw node_implementation_init_exception();
if (!insert_resource_after(delay_millis, model.node_resources, std::move(flow), gate)) throw node_implementation_init_exception();
Expand Down
4 changes: 2 additions & 2 deletions Development/nmos/activation_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,12 +226,12 @@ namespace nmos
}
}

modify_resource(resources, id_type.first, [&response_activation](nmos::resource& resource)
modify_resource(resources, id_type.first, [&resources, &response_activation](nmos::resource& resource)
{
auto& staged = nmos::fields::endpoint_staged(resource.data);
auto& staged_activation = staged[nmos::fields::activation];

resource.data[nmos::fields::version] = web::json::value::string(nmos::make_version());
resource.data[nmos::fields::version] = value::string(nmos::make_version(nmos::strictly_increasing_update(resources)));

// "For immediate activations, [the `mode` field] will be null in response to any subsequent GET requests."
staged_activation[nmos::fields::mode] = value::null();
Expand Down
20 changes: 11 additions & 9 deletions Development/nmos/api_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,8 +503,13 @@ namespace nmos
nmos::api_gate gate(gate_, req, parameters);

const auto received_time = req.headers().find(details::received_time);

const auto processing_dur = req.headers().end() != received_time
? bst::chrono::duration_cast<bst::chrono::microseconds>(nmos::tai_clock::now() - nmos::time_point_from_tai(nmos::parse_version(received_time->second))).count() / 1000.0
? bst::chrono::duration_cast<bst::chrono::microseconds>(
// processing_dur = now - received time
( tai_clock::time_point(tai_clock::duration(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count()))
- nmos::time_point_from_tai(nmos::parse_version(received_time->second)))
).count() / 1000.0
: 0.0;

// experimental extension, to add Server-Timing response header
Expand Down Expand Up @@ -707,15 +712,12 @@ namespace nmos
add_api_finally_handler(api_, hsts, gate);
auto api = [api_, &gate](web::http::http_request req) mutable
{
// hmm, in Windows, the boost version of the time_point::now sometimes returns the same value after a small time increment.
// This issue does not seem to happen in the std::chrono implementation.
#if defined(_WIN32) && defined (BST_THREAD_BOOST)
// calculate received_time using std::chrono
const auto now = tai_clock::time_point(tai_clock::duration(std::chrono::system_clock::now().time_since_epoch().count() + tai_clock::tai_offset().count()));
// hmm, in Windows, the boost version of time_point::now (system_clock::now) sometimes returns the same value after a small time increment.
// I guess the same could happen with the Boost version of steady_clock::now, since this issue does not seem to occur in the std::chrono implementation.
// So let's use std::chrono for both Windows and Linux.
const auto now = tai_clock::time_point(tai_clock::duration(std::chrono::steady_clock::now().time_since_epoch().count()));
req.headers().add(details::received_time, nmos::make_version(tai_from_time_point(now)));
#else
req.headers().add(details::received_time, nmos::make_version());
#endif

slog::log<slog::severities::too_much_info>(gate, SLOG_FLF)
<< stash_remote_address(req.remote_address())
<< stash_http_method(req.method())
Expand Down
8 changes: 4 additions & 4 deletions Development/nmos/channelmapping_activation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ namespace nmos

if (!source_id_or_null.is_null())
{
nmos::modify_resource(model.node_resources, source_id_or_null.as_string(), [&activation_time](nmos::resource& source)
nmos::modify_resource(model.node_resources, source_id_or_null.as_string(), [&resources = model.node_resources, &activation_time](nmos::resource& source)
{
nmos::set_resource_version(source, activation_time);
nmos::set_resource_version(resources, source, activation_time);
});
}

Expand Down Expand Up @@ -188,9 +188,9 @@ namespace nmos

for (auto device = devices.first; devices.second != device; ++device)
{
nmos::modify_resource(model.node_resources, device->id, [&activation_time](nmos::resource& source)
nmos::modify_resource(model.node_resources, device->id, [&resources = model.node_resources, &activation_time](nmos::resource& source)
{
nmos::set_resource_version(source, activation_time);
nmos::set_resource_version(resources, source, activation_time);
});
}
}
Expand Down
5 changes: 2 additions & 3 deletions Development/nmos/channelmapping_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,14 +558,13 @@ namespace nmos

// Update the IS-04 source or device after the active map is changed in any way
// (This function should be called after nmos::set_channelmapping_output_active.)
void set_resource_version(nmos::resource& node_resource, const nmos::tai& activation_time)
void set_resource_version(const nmos::resources& node_resources, nmos::resource& node_resource, const nmos::tai& activation_time)
{
using web::json::value;

auto& resource = node_resource;
const auto at = value::string(nmos::make_version(activation_time));

resource.data[nmos::fields::version] = at;
resource.data[nmos::fields::version] = value::string(nmos::make_version(nmos::strictly_increasing_update(node_resources, activation_time)));
}

web::http::experimental::listener::api_router make_unmounted_channelmapping_api(nmos::node_model& model, details::channelmapping_output_map_validator validate_merged, slog::base_gate& gate_)
Expand Down
2 changes: 1 addition & 1 deletion Development/nmos/channelmapping_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ namespace nmos

// Update the IS-04 source or device after the active map is changed in any way
// (This function should be called after nmos::set_channelmapping_output_active.)
void set_resource_version(nmos::resource& node_resource, const nmos::tai& activation_time);
void set_resource_version(const nmos::resources& node_resources, nmos::resource& node_resource, const nmos::tai& activation_time);

// Channel Mapping API implementation details
namespace details
Expand Down
6 changes: 3 additions & 3 deletions Development/nmos/connection_activation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ namespace nmos
{
// Update the IS-05 resource's /active endpoint

nmos::set_connection_resource_active(connection_resource, [&](web::json::value& endpoint_active)
nmos::set_connection_resource_active(model.connection_resources, connection_resource, [&](web::json::value& endpoint_active)
{
// the resolve_auto callback may throw exceptions, which will prevent activation in order that
// "if there is an error condition that means `auto` cannot be resolved, the active transport parameters
Expand All @@ -169,9 +169,9 @@ namespace nmos

// Update the IS-04 resource's subscription

nmos::modify_resource(model.node_resources, id_type.first, [&activation_time, &active, &connected_id](nmos::resource& resource)
nmos::modify_resource(model.node_resources, id_type.first, [&resources = model.node_resources, &activation_time, &active, &connected_id](nmos::resource& resource)
{
nmos::set_resource_subscription(resource, active, connected_id, activation_time);
nmos::set_resource_subscription(resources, resource, active, connected_id, activation_time);
});

// Synchronous notification that the active parameters for the specified (IS-04/IS-05) sender/connection_sender or receiver/connection_receiver have changed
Expand Down
13 changes: 6 additions & 7 deletions Development/nmos/connection_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,9 +555,9 @@ namespace nmos

// Finally, update the staged endpoint

modify_resource(resources, id_type.first, [&merged](nmos::resource& resource)
modify_resource(resources, id_type.first, [&resources, &merged](nmos::resource& resource)
{
resource.data[nmos::fields::version] = web::json::value::string(nmos::make_version());
resource.data[nmos::fields::version] = value::string(nmos::make_version(nmos::strictly_increasing_update(resources)));

nmos::fields::endpoint_staged(resource.data) = merged;
// In the case of an immediate activation, this is not yet a valid response
Expand Down Expand Up @@ -709,15 +709,15 @@ namespace nmos
}

// Activate an IS-05 sender or receiver by transitioning the 'staged' settings into the 'active' resource
void set_connection_resource_active(nmos::resource& connection_resource, std::function<void(web::json::value& endpoint_active)> resolve_auto, const nmos::tai& activation_time)
void set_connection_resource_active(const nmos::resources& connection_resources, nmos::resource& connection_resource, std::function<void(web::json::value& endpoint_active)> resolve_auto, const nmos::tai& activation_time)
{
using web::json::value;
using web::json::value_of;

auto& resource = connection_resource;
const auto at = value::string(nmos::make_version(activation_time));

resource.data[nmos::fields::version] = at;
resource.data[nmos::fields::version] = value::string(nmos::make_version(nmos::strictly_increasing_update(connection_resources, activation_time)));

auto& staged = nmos::fields::endpoint_staged(resource.data);
auto& staged_activation = staged[nmos::fields::activation];
Expand Down Expand Up @@ -776,13 +776,12 @@ namespace nmos

// Update the IS-04 sender or receiver after the active connection is changed in any way
// (This function should be called after nmos::set_connection_resource_active.)
void set_resource_subscription(nmos::resource& node_resource, bool active, const nmos::id& connected_id, const nmos::tai& activation_time)
void set_resource_subscription(const nmos::resources& node_resources, nmos::resource& node_resource, bool active, const nmos::id& connected_id, const nmos::tai& activation_time)
{
using web::json::value;
using web::json::value_of;

auto& resource = node_resource;
const auto at = value::string(nmos::make_version(activation_time));

// "The 'receiver_id' key MUST be set to `null` in all cases except where a unicast push-based Sender is configured to transmit to an NMOS Receiver, and the 'active' key is set to 'true'."
// "The 'sender_id' key MUST be set to `null` in all cases except where the Receiver is currently configured to receive from an NMOS Sender, and the 'active' key is set to 'true'.
Expand All @@ -792,7 +791,7 @@ namespace nmos
// "When the 'active' parameters of a Sender or Receiver are modified, or when a re-activation of the same parameters
// is performed, the 'version' attribute of the relevant IS-04 Sender or Receiver must be incremented."
// See https://specs.amwa.tv/is-05/releases/v1.0.0/docs/3.1._Interoperability_-_NMOS_IS-04.html#version-increments
resource.data[nmos::fields::version] = at;
resource.data[nmos::fields::version] = value::string(nmos::make_version(nmos::strictly_increasing_update(node_resources, activation_time)));

// Senders indicate the connected receiver_id, receivers indicate the connected sender_id
// (depending on the API version)
Expand Down
5 changes: 3 additions & 2 deletions Development/nmos/connection_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "cpprest/api_router.h"
#include "nmos/id.h"
#include "nmos/resources.h"

namespace slog
{
Expand Down Expand Up @@ -57,15 +58,15 @@ namespace nmos
// Functions for interaction between the Connection API implementation and the connection activation thread

// Activate an IS-05 sender or receiver by transitioning the 'staged' settings into the 'active' resource
void set_connection_resource_active(nmos::resource& connection_resource, std::function<void(web::json::value& endpoint_active)> resolve_auto, const nmos::tai& activation_time);
void set_connection_resource_active(const nmos::resources& connection_resources, nmos::resource& connection_resource, std::function<void(web::json::value& endpoint_active)> resolve_auto, const nmos::tai& activation_time);

// Clear any pending activation of an IS-05 sender or receiver
// (This function should not be called after nmos::set_connection_resource_active.)
void set_connection_resource_not_pending(nmos::resource& connection_resource);

// Update the IS-04 sender or receiver after the active connection is changed in any way
// (This function should be called after nmos::set_connection_resource_active.)
void set_resource_subscription(nmos::resource& node_resource, bool active, const nmos::id& connected_id, const nmos::tai& activation_time);
void set_resource_subscription(const nmos::resources& node_resources, nmos::resource& node_resource, bool active, const nmos::id& connected_id, const nmos::tai& activation_time);

// Helper functions for the Connection API callbacks

Expand Down
8 changes: 4 additions & 4 deletions Development/nmos/connection_events_activation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ namespace nmos
{
using web::json::value;

const auto at = web::json::value::string(nmos::make_version(activation_time));
const auto at = value::string(nmos::make_version(activation_time));

connection_resource.data[nmos::fields::version] = at;
connection_resource.data[nmos::fields::version] = value::string(nmos::make_version(nmos::strictly_increasing_update(model.connection_resources, activation_time)));

auto& endpoint_active = nmos::fields::endpoint_active(connection_resource.data);
auto& active_activation = endpoint_active[nmos::fields::activation];
Expand All @@ -185,9 +185,9 @@ namespace nmos

// Update the IS-04 resource's subscription

nmos::modify_resource(model.node_resources, id_type.first, [&activation_time](nmos::resource& resource)
nmos::modify_resource(model.node_resources, id_type.first, [&resources = model.node_resources, &activation_time](nmos::resource& resource)
{
nmos::set_resource_subscription(resource, false, {}, activation_time);
nmos::set_resource_subscription(resources, resource, false, {}, activation_time);
});
}
};
Expand Down
5 changes: 3 additions & 2 deletions Development/nmos/lldp_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace nmos
const auto& interface_name = interface->second.name;

using web::json::value_of;
using web::json::value;

auto lock = model.write_lock();
auto& resources = model.node_resources;
Expand Down Expand Up @@ -55,9 +56,9 @@ namespace nmos
{
slog::log<slog::severities::more_info>(gate, SLOG_FLF) << "LLDP received - updating attached network device info for network interface " << interface->second.name;

nmos::modify_resource(resources, resource->id, [&interface_name, &attached_network_device](nmos::resource& resource)
nmos::modify_resource(resources, resource->id, [&resources, &interface_name, &attached_network_device](nmos::resource& resource)
{
resource.data[nmos::fields::version] = web::json::value::string(nmos::make_version());
resource.data[nmos::fields::version] = value::string(nmos::make_version(nmos::strictly_increasing_update(resources)));

auto& json_interfaces = nmos::fields::interfaces(resource.data);

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ The implementation is designed to be extended. Development is ongoing, following

Recent activity on the project (newest first):

- Added Network Time Protocol (NTP) support
- Added support for IS-14 NMOS Device Configuration
- Added support for BCP-008-01 Receiver Status Monitoring
- Added support for BCP-008-02 Sender Status Monitoring
Expand Down
Loading