From e2830abe549dd55d94a5746f3c7ed2158301b743 Mon Sep 17 00:00:00 2001 From: Simon Lo Date: Wed, 5 Jun 2024 12:38:59 +0100 Subject: [PATCH] Optimize is12 method handlers (#393) * Enhance control_protocol_state to support user callback on control class method handler * Update control_protocol_state use in control protocol test * Rename method_handler to control_protocol_method_handler with @jonathan-r-thorpe suggestion. --- Development/nmos-cpp-node/main.cpp | 2 +- .../nmos-cpp-node/node_implementation.cpp | 14 +- Development/nmos/control_protocol_handlers.h | 18 +- Development/nmos/control_protocol_methods.cpp | 188 +++++++++--------- Development/nmos/control_protocol_methods.h | 26 +-- .../nmos/control_protocol_resource.cpp | 32 +-- Development/nmos/control_protocol_resource.h | 14 +- Development/nmos/control_protocol_state.cpp | 141 ++++++++++--- Development/nmos/control_protocol_state.h | 4 +- Development/nmos/control_protocol_ws_api.cpp | 31 ++- .../nmos/test/control_protocol_test.cpp | 4 +- 11 files changed, 266 insertions(+), 208 deletions(-) diff --git a/Development/nmos-cpp-node/main.cpp b/Development/nmos-cpp-node/main.cpp index 857fac13..e4b420fa 100644 --- a/Development/nmos-cpp-node/main.cpp +++ b/Development/nmos-cpp-node/main.cpp @@ -138,7 +138,7 @@ int main(int argc, char* argv[]) .on_request_authorization_code(nmos::experimental::make_request_authorization_code_handler(gate)); // may be omitted, only required for OAuth client which is using the Authorization Code Flow to obtain the access token } - nmos::experimental::control_protocol_state control_protocol_state; + nmos::experimental::control_protocol_state control_protocol_state(node_implementation.control_protocol_property_changed); if (0 <= nmos::fields::control_protocol_ws_port(node_model.settings)) { node_implementation diff --git a/Development/nmos-cpp-node/node_implementation.cpp b/Development/nmos-cpp-node/node_implementation.cpp index 1e89fb8e..f12cca15 100644 --- a/Development/nmos-cpp-node/node_implementation.cpp +++ b/Development/nmos-cpp-node/node_implementation.cpp @@ -1008,31 +1008,31 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr nmos::experimental::make_control_class_property_descriptor(U("Example object sequence property"), { 3, 14 }, object_sequence, U("ExampleDataType"), false, false, true) }; - auto example_method_with_no_args = [](nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + auto example_method_with_no_args = [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... slog::log(gate, SLOG_FLF) << "Executing the example method with no arguments"; - return nmos::make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); + return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); }; - auto example_method_with_simple_args = [](nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + auto example_method_with_simple_args = [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... // and the method parameters constriants has already been validated by the outer function slog::log(gate, SLOG_FLF) << "Executing the example method with simple arguments: " << arguments.serialize(); - return nmos::make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); + return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); }; - auto example_method_with_object_args = [](nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + auto example_method_with_object_args = [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... // and the method parameters constriants has already been validated by the outer function slog::log(gate, SLOG_FLF) << "Executing the example method with object argument: " << arguments.serialize(); - return nmos::make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); + return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); }; // Example control class method descriptors std::vector example_control_method_descriptors = @@ -1113,7 +1113,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr // helper function to create Example control instance auto make_example_control = [&](nmos::nc_oid oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const value& touchpoints, const value& runtime_property_constraints, // level 2: runtime constraints. See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use of make_nc_property_constraints_string and make_nc_property_constraints_number to create runtime constraints + // use of make_nc_property_constraints_string and make_nc_property_constraints_number to create runtime constraints example_enum enum_property_, const utility::string_t& string_property_, uint64_t number_property_, diff --git a/Development/nmos/control_protocol_handlers.h b/Development/nmos/control_protocol_handlers.h index 89c6dd03..0dcd8478 100644 --- a/Development/nmos/control_protocol_handlers.h +++ b/Development/nmos/control_protocol_handlers.h @@ -38,23 +38,15 @@ namespace nmos namespace experimental { - // standard method handler definition - typedef std::function standard_method_handler; - - // non-standard method handler definition - typedef std::function non_standard_method_handler; + // control method handler definition + typedef std::function control_protocol_method_handler; // method definition (NcMethodDescriptor vs method handler) - typedef std::tuple method; - - inline method make_control_class_standard_method(const web::json::value& nc_method_descriptor, standard_method_handler method_handler) - { - return std::make_tuple(nc_method_descriptor, method_handler, nullptr); - } + typedef std::pair method; - inline method make_control_class_non_standard_method(const web::json::value& nc_method_descriptor, non_standard_method_handler method_handler) + inline method make_control_class_method(const web::json::value& nc_method_descriptor, control_protocol_method_handler method_handler) { - return std::make_tuple(nc_method_descriptor, nullptr, method_handler); + return std::make_pair(nc_method_descriptor, method_handler); } } diff --git a/Development/nmos/control_protocol_methods.cpp b/Development/nmos/control_protocol_methods.cpp index 8bdd673c..d9d78129 100644 --- a/Development/nmos/control_protocol_methods.cpp +++ b/Development/nmos/control_protocol_methods.cpp @@ -12,7 +12,7 @@ namespace nmos { // NcObject methods implementation // Get property value - web::json::value get(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value get(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -24,17 +24,17 @@ namespace nmos const auto& property = find_property_descriptor(details::parse_nc_property_id(property_id), details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); if (!property.is_null()) { - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, resource.data.at(nmos::fields::nc::name(property))); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, resource.data.at(nmos::fields::nc::name(property))); } // unknown property utility::stringstream_t ss; ss << U("unknown property: ") << property_id.serialize() << U(" to do Get"); - return make_control_protocol_error_response(handle, { nc_method_status::property_not_implemented }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); } // Set property value - web::json::value set(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) + web::json::value set(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -50,14 +50,14 @@ namespace nmos { if (nmos::fields::nc::is_read_only(property)) { - return make_control_protocol_message_response(handle, { nc_method_status::read_only }); + return details::make_nc_method_result({ nc_method_status::read_only }); } if ((val.is_null() && !nmos::fields::nc::is_nullable(property)) || (!val.is_array() && nmos::fields::nc::is_sequence(property)) || (val.is_array() && !nmos::fields::nc::is_sequence(property))) { - return make_control_protocol_message_response(handle, { nc_method_status::parameter_error }); + return details::make_nc_method_result({ nc_method_status::parameter_error }); } try @@ -78,24 +78,24 @@ namespace nmos }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { property_id_, nc_property_change_type::type::value_changed, val } })); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); } catch (const nmos::control_protocol_exception& e) { slog::log(gate, SLOG_FLF) << "Set property: " << property_id.serialize() << " value: " << val.serialize() << " error: " << e.what(); - return make_control_protocol_message_response(handle, { nc_method_status::parameter_error }); + return details::make_nc_method_result({ nc_method_status::parameter_error }); } } // unknown property utility::stringstream_t ss; ss << U("unknown property: ") << property_id.serialize() << " to do Set"; - return make_control_protocol_error_response(handle, { nc_method_status::property_not_implemented }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); } // Get sequence item - web::json::value get_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value get_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -115,28 +115,28 @@ namespace nmos // property is not a sequence utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do GetSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::invalid_request }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); } if (data.as_array().size() > (size_t)index) { - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, data.at(index)); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, data.at(index)); } // out of bound utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do GetSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::index_out_of_bounds }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::index_out_of_bounds }, ss.str()); } // unknown property utility::stringstream_t ss; ss << U("unknown property: ") << property_id.serialize() << U(" to do GetSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::property_not_implemented }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); } // Set sequence item - web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) + web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -153,7 +153,7 @@ namespace nmos { if (nmos::fields::nc::is_read_only(property)) { - return make_control_protocol_message_response(handle, { nc_method_status::read_only }); + return details::make_nc_method_result({ nc_method_status::read_only }); } auto& data = resource.data.at(nmos::fields::nc::name(property)); @@ -163,7 +163,7 @@ namespace nmos // property is not a sequence utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do SetSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::invalid_request }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); } if (data.as_array().size() > (size_t)index) @@ -186,30 +186,30 @@ namespace nmos }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { property_id_, nc_property_change_type::type::sequence_item_changed, val, nc_id(index) } })); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); } catch (const nmos::control_protocol_exception& e) { slog::log(gate, SLOG_FLF) << "Set sequence item: " << property_id.serialize() << " index: " << index << " value: " << val.serialize() << " error: " << e.what(); - return make_control_protocol_message_response(handle, { nc_method_status::parameter_error }); + return details::make_nc_method_result({ nc_method_status::parameter_error }); } } // out of bound utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do SetSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::index_out_of_bounds }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::index_out_of_bounds }, ss.str()); } // unknown property utility::stringstream_t ss; ss << U("unknown property: ") << property_id.serialize() << U(" to do SetSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::property_not_implemented }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); } // Add item to sequence - web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) + web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -227,7 +227,7 @@ namespace nmos { if (nmos::fields::nc::is_read_only(property)) { - return make_control_protocol_message_response(handle, { nc_method_status::read_only }); + return details::make_nc_method_result({ nc_method_status::read_only }); } if (!nmos::fields::nc::is_sequence(property)) @@ -235,7 +235,7 @@ namespace nmos // property is not a sequence utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do AddSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::invalid_request }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); } auto& data = resource.data.at(nmos::fields::nc::name(property)); @@ -262,24 +262,24 @@ namespace nmos }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { property_id_, nc_property_change_type::type::sequence_item_added, val, sequence_item_index } })); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, sequence_item_index); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, sequence_item_index); } catch (const nmos::control_protocol_exception& e) { slog::log(gate, SLOG_FLF) << "Add sequence item: " << property_id.serialize() << " value: " << val.serialize() << " error: " << e.what(); - return make_control_protocol_message_response(handle, { nc_method_status::parameter_error }); + return details::make_nc_method_result({ nc_method_status::parameter_error }); } } // unknown property utility::stringstream_t ss; ss << U("unknown property: ") << property_id.serialize() << U(" to do AddSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::property_not_implemented }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); } // Delete sequence item - web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -299,7 +299,7 @@ namespace nmos // property is not a sequence utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do RemoveSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::invalid_request }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); } if (data.as_array().size() > (size_t)index) @@ -311,23 +311,23 @@ namespace nmos }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { details::parse_nc_property_id(property_id), nc_property_change_type::type::sequence_item_removed, nc_id(index) } })); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); } // out of bound utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do RemoveSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::index_out_of_bounds }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::index_out_of_bounds }, ss.str()); } // unknown property utility::stringstream_t ss; ss << U("unknown property: ") << property_id.serialize() << U(" to do RemoveSequenceItem"); - return make_control_protocol_error_response(handle, { nc_method_status::property_not_implemented }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); } // Get sequence length - web::json::value get_sequence_length(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value get_sequence_length(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -346,7 +346,7 @@ namespace nmos // property is not a sequence utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do GetSequenceLength"); - return make_control_protocol_error_response(handle, { nc_method_status::invalid_request }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); } const auto& data = resource.data.at(nmos::fields::nc::name(property)); @@ -357,7 +357,7 @@ namespace nmos if (data.is_null()) { // null - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, value::null()); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, value::null()); } } else @@ -368,21 +368,21 @@ namespace nmos // null utility::stringstream_t ss; ss << U("property: ") << property_id.serialize() << " is a null sequence to do GetSequenceLength"; - return make_control_protocol_error_response(handle, { nc_method_status::invalid_request }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); } } - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, uint32_t(data.as_array().size())); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, value(uint32_t(data.as_array().size()))); } // unknown property utility::stringstream_t ss; ss << U("unknown property: ") << property_id.serialize() << " to do GetSequenceLength"; - return make_control_protocol_error_response(handle, { nc_method_status::property_not_implemented }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); } // NcBlock methods implementation // Gets descriptors of members of the block - web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -395,11 +395,11 @@ namespace nmos auto descriptors = value::array(); nmos::get_member_descriptors(resources, resource, recurse, descriptors.as_array()); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); } // Finds member(s) by path - web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource_, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource_, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -413,7 +413,7 @@ namespace nmos if (0 == path.size()) { // empty path - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("empty path to do FindMembersByPath")); + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty path to do FindMembersByPath")); } auto descriptors = value::array(); @@ -444,22 +444,22 @@ namespace nmos // no role utility::stringstream_t ss; ss << U("role: ") << role.as_string() << U(" not found to do FindMembersByPath"); - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, ss.str()); + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); } } else { // no members - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("no members to do FindMembersByPath")); + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("no members to do FindMembersByPath")); } } web::json::push_back(descriptors, descriptor); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); } // Finds members with given role name or fragment - web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -475,17 +475,17 @@ namespace nmos if (role.empty()) { // empty role - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("empty role to do FindMembersByRole")); + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty role to do FindMembersByRole")); } auto descriptors = value::array(); nmos::find_members_by_role(resources, resource, role, match_whole_string, case_sensitive, recurse, descriptors.as_array()); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); } // Finds members with given class id - web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -500,7 +500,7 @@ namespace nmos if (class_id.empty()) { // empty class_id - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("empty classId to do FindMembersByClassId")); + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty classId to do FindMembersByClassId")); } // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -508,12 +508,12 @@ namespace nmos auto descriptors = value::array(); nmos::find_members_by_class_id(resources, resource, class_id, include_derived, recurse, descriptors.as_array()); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); } // NcClassManager methods implementation // Get a single class descriptor - web::json::value get_control_class(nmos::resources&, const nmos::resource&, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate) + web::json::value get_control_class(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { using web::json::value; @@ -525,7 +525,7 @@ namespace nmos if (class_id.empty()) { // empty class_id - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("empty classId to do GetControlClass")); + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty classId to do GetControlClass")); } // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... @@ -561,68 +561,68 @@ namespace nmos ? details::make_nc_class_descriptor(description, class_id, name, property_descriptors, method_descriptors, event_descriptors) : details::make_nc_class_descriptor(description, class_id, name, fixed_role.as_string(), property_descriptors, method_descriptors, event_descriptors); - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptor); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptor); } - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("classId not found")); + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("classId not found")); } // Get a single datatype descriptor - web::json::value get_datatype(nmos::resources&, const nmos::resource&, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + web::json::value get_datatype(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - const auto& name = nmos::fields::nc::name(arguments); // name of datatype - const auto& include_inherited = nmos::fields::nc::include_inherited(arguments); // If set the descriptor would contain all inherited elements + const auto& name = nmos::fields::nc::name(arguments); // name of datatype + const auto& include_inherited = nmos::fields::nc::include_inherited(arguments); // If set the descriptor would contain all inherited elements - slog::log(gate, SLOG_FLF) << "Get a single datatype descriptor: " << "name: " << name; + slog::log(gate, SLOG_FLF) << "Get a single datatype descriptor: " << "name: " << name; - if (name.empty()) - { - // empty name - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("empty name to do GetDatatype")); - } + if (name.empty()) + { + // empty name + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty name to do GetDatatype")); + } - const auto& datatype = get_control_protocol_datatype_descriptor(name); - if (datatype.descriptor.size()) - { - auto descriptor = datatype.descriptor; + const auto& datatype = get_control_protocol_datatype_descriptor(name); + if (datatype.descriptor.size()) + { + auto descriptor = datatype.descriptor; - if (include_inherited) + if (include_inherited) + { + const auto& type = nmos::fields::nc::type(descriptor); + if (nc_datatype_type::Struct == type) { - const auto& type = nmos::fields::nc::type(descriptor); - if (nc_datatype_type::Struct == type) - { - auto descriptor_ = descriptor; + auto descriptor_ = descriptor; - for (;;) + for (;;) + { + const auto& parent_type = descriptor_.at(nmos::fields::nc::parent_type); + if (!parent_type.is_null()) { - const auto& parent_type = descriptor_.at(nmos::fields::nc::parent_type); - if (!parent_type.is_null()) + const auto& parent_datatype = get_control_protocol_datatype_descriptor(parent_type.as_string()); + if (parent_datatype.descriptor.size()) { - const auto& parent_datatype = get_control_protocol_datatype_descriptor(parent_type.as_string()); - if (parent_datatype.descriptor.size()) - { - descriptor_ = parent_datatype.descriptor; + descriptor_ = parent_datatype.descriptor; - const auto& fields = nmos::fields::nc::fields(descriptor_); - for (const auto& field : fields) - { - web::json::push_back(descriptor.at(nmos::fields::nc::fields), field); - } + const auto& fields = nmos::fields::nc::fields(descriptor_); + for (const auto& field : fields) + { + web::json::push_back(descriptor.at(nmos::fields::nc::fields), field); } } - else - { - break; - } + } + else + { + break; } } } - - return make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptor); } - return make_control_protocol_error_response(handle, { nc_method_status::parameter_error }, U("name not found")); + return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptor); } + + return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("name not found")); + } } diff --git a/Development/nmos/control_protocol_methods.h b/Development/nmos/control_protocol_methods.h index fe44d77c..957f9362 100644 --- a/Development/nmos/control_protocol_methods.h +++ b/Development/nmos/control_protocol_methods.h @@ -13,35 +13,35 @@ namespace nmos { // NcObject methods implementation // Get property value - web::json::value get(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value get(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); // Set property value - web::json::value set(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + web::json::value set(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); // Get sequence item - web::json::value get_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value get_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); // Set sequence item - web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); // Add item to sequence - web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); // Delete sequence item - web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); // Get sequence length - web::json::value get_sequence_length(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value get_sequence_length(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); // NcBlock methods implementation // Get descriptors of members of the block - web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); // Finds member(s) by path - web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); // Finds members with given role name or fragment - web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); // Finds members with given class id - web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); // NcClassManager methods implementation // Get a single class descriptor - web::json::value get_control_class(nmos::resources&, const nmos::resource&, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value get_control_class(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); // Get a single datatype descriptor - web::json::value get_datatype(nmos::resources&, const nmos::resource&, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype, control_protocol_property_changed_handler, slog::base_gate& gate); + web::json::value get_datatype(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype, slog::base_gate& gate); } #endif diff --git a/Development/nmos/control_protocol_resource.cpp b/Development/nmos/control_protocol_resource.cpp index 890e1363..83ccaad0 100644 --- a/Development/nmos/control_protocol_resource.cpp +++ b/Development/nmos/control_protocol_resource.cpp @@ -831,42 +831,18 @@ namespace nmos } } - // message response + // command message response // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#command-response-message-type - web::json::value make_control_protocol_error_response(int32_t handle, const nc_method_result& method_result, const utility::string_t& error_message) + web::json::value make_control_protocol_response(int32_t handle, const web::json::value& method_result) { using web::json::value_of; return value_of({ { nmos::fields::nc::handle, handle }, - { nmos::fields::nc::result, details::make_nc_method_result_error(method_result, error_message) } + { nmos::fields::nc::result, method_result } }); } - web::json::value make_control_protocol_message_response(int32_t handle, const nc_method_result& method_result) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::handle, handle }, - { nmos::fields::nc::result, details::make_nc_method_result(method_result) } - }); - } - web::json::value make_control_protocol_message_response(int32_t handle, const nc_method_result& method_result, const web::json::value& value) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::handle, handle }, - { nmos::fields::nc::result, details::make_nc_method_result(method_result, value) } - }); - } - web::json::value make_control_protocol_message_response(int32_t handle, const nc_method_result& method_result, uint32_t value_) - { - using web::json::value; - - return make_control_protocol_message_response(handle, method_result, value(value_)); - } - web::json::value make_control_protocol_message_response(const web::json::value& responses) + web::json::value make_control_protocol_command_response(const web::json::value& responses) { using web::json::value_of; diff --git a/Development/nmos/control_protocol_resource.h b/Development/nmos/control_protocol_resource.h index a0354226..5f341949 100644 --- a/Development/nmos/control_protocol_resource.h +++ b/Development/nmos/control_protocol_resource.h @@ -40,6 +40,11 @@ namespace nmos namespace details { + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethodresult + web::json::value make_nc_method_result(const nc_method_result& method_result); + web::json::value make_nc_method_result_error(const nc_method_result& method_result, const utility::string_t& error_message); + web::json::value make_nc_method_result(const nc_method_result& method_result, const web::json::value& value); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncelementid web::json::value make_nc_element_id(const nc_element_id& element_id); nc_element_id parse_nc_element_id(const web::json::value& element_id); @@ -188,13 +193,10 @@ namespace nmos web::json::value make_nc_class_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, const nmos::experimental::control_protocol_state& control_protocol_state); } - // message response + // command message response // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#command-response-message-type - web::json::value make_control_protocol_error_response(int32_t handle, const nc_method_result& method_result, const utility::string_t& error_message); - web::json::value make_control_protocol_message_response(int32_t handle, const nc_method_result& method_result); - web::json::value make_control_protocol_message_response(int32_t handle, const nc_method_result& method_result, const web::json::value& value); // value can be sequence, NcClassDescriptor, NcDatatypeDescriptor - web::json::value make_control_protocol_message_response(int32_t handle, const nc_method_result& method_result, uint32_t value); - web::json::value make_control_protocol_message_response(const web::json::value& responses); + web::json::value make_control_protocol_response(int32_t handle, const web::json::value& method_result); + web::json::value make_control_protocol_command_response(const web::json::value& responses); // subscription response // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#subscription-response-message-type diff --git a/Development/nmos/control_protocol_state.cpp b/Development/nmos/control_protocol_state.cpp index b611c2ed..dd4b1911 100644 --- a/Development/nmos/control_protocol_state.cpp +++ b/Development/nmos/control_protocol_state.cpp @@ -73,15 +73,10 @@ namespace nmos return nmos::details::make_nc_method_descriptor(description, id, name, result_datatype, parameters, is_deprecated); } } - // create standard control class method descriptor - method make_control_class_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const std::vector& parameters, bool is_deprecated, standard_method_handler method_handler) + // create control class method descriptor + method make_control_class_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const std::vector& parameters, bool is_deprecated, control_protocol_method_handler method_handler) { - return make_control_class_standard_method(details::make_control_class_method_descriptor(description, id, name, result_datatype, parameters, is_deprecated), method_handler); - } - // create non-standard control class method descriptor - method make_control_class_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const std::vector& parameters, bool is_deprecated, non_standard_method_handler method_handler) - { - return make_control_class_non_standard_method(details::make_control_class_method_descriptor(description, id, name, result_datatype, parameters, is_deprecated), method_handler); + return make_control_class_method(details::make_control_class_method_descriptor(description, id, name, result_datatype, parameters, is_deprecated), method_handler); } // create control class event descriptor @@ -90,7 +85,102 @@ namespace nmos return nmos::details::make_nc_event_descriptor(description, id, name, event_datatype, is_deprecated); } - control_protocol_state::control_protocol_state() + namespace details + { + nmos::experimental::control_protocol_method_handler make_nc_get_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return get(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_set_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed) + { + return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return set(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_get_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return get_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_set_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed) + { + return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return set_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_add_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed) + { + return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return add_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_remove_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return remove_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_get_sequence_length_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return get_sequence_length(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_get_member_descriptors_handler() + { + return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return get_member_descriptors(resources, resource, arguments, is_deprecated, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_find_members_by_path_handler() + { + return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return find_members_by_path(resources, resource, arguments, is_deprecated, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_find_members_by_role_handler() + { + return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return find_members_by_role(resources, resource, arguments, is_deprecated, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_find_members_by_class_id_handler() + { + return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return find_members_by_class_id(resources, resource, arguments, is_deprecated, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_get_control_class_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return get_control_class(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_get_datatype_handler(get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) + { + return [get_control_protocol_datatype_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + return get_datatype(resources, resource, arguments, is_deprecated, get_control_protocol_datatype_descriptor, gate); + }; + } + } + + control_protocol_state::control_protocol_state(control_protocol_property_changed_handler property_changed) { using web::json::value; @@ -103,7 +193,7 @@ namespace nmos return std::vector{}; }; - auto to_methods_vector = [](const web::json::value& nc_method_descriptors, const std::map& method_handlers) + auto to_methods_vector = [](const web::json::value& nc_method_descriptors, const std::map& method_handlers) { // NcMethodDescriptor method handler array std::vector methods; @@ -112,12 +202,15 @@ namespace nmos { for (const auto& nc_method_descriptor : nc_method_descriptors.as_array()) { - methods.push_back(make_control_class_standard_method(nc_method_descriptor, method_handlers.at(nmos::details::parse_nc_method_id(nmos::fields::nc::id(nc_method_descriptor))))); + methods.push_back(make_control_class_method(nc_method_descriptor, method_handlers.at(nmos::details::parse_nc_method_id(nmos::fields::nc::id(nc_method_descriptor))))); } } return methods; }; + auto get_control_protocol_class_descriptor = make_get_control_protocol_class_descriptor_handler(*this); + auto get_control_protocol_datatype_descriptor = make_get_control_protocol_datatype_descriptor_handler(*this); + // setup the standard control classes control_class_descriptors = { @@ -132,13 +225,13 @@ namespace nmos to_methods_vector(make_nc_object_methods(), { // link NcObject method_ids with method functions - { nc_object_get_method_id, get }, - { nc_object_set_method_id, set }, - { nc_object_get_sequence_item_method_id, get_sequence_item }, - { nc_object_set_sequence_item_method_id, set_sequence_item }, - { nc_object_add_sequence_item_method_id, add_sequence_item }, - { nc_object_remove_sequence_item_method_id, remove_sequence_item }, - { nc_object_get_sequence_length_method_id, get_sequence_length } + { nc_object_get_method_id, details::make_nc_get_handler(get_control_protocol_class_descriptor) }, + { nc_object_set_method_id, details::make_nc_set_handler(get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed) }, + { nc_object_get_sequence_item_method_id, details::make_nc_get_sequence_item_handler(get_control_protocol_class_descriptor) }, + { nc_object_set_sequence_item_method_id, details::make_nc_set_sequence_item_handler(get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed) }, + { nc_object_add_sequence_item_method_id, details::make_nc_add_sequence_item_handler(get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed) }, + { nc_object_remove_sequence_item_method_id, details::make_nc_remove_sequence_item_handler(get_control_protocol_class_descriptor) }, + { nc_object_get_sequence_length_method_id, details::make_nc_get_sequence_length_handler(get_control_protocol_class_descriptor) } }), // NcObject events to_vector(make_nc_object_events())) }, @@ -150,10 +243,10 @@ namespace nmos to_methods_vector(make_nc_block_methods(), { // link NcBlock method_ids with method functions - { nc_block_get_member_descriptors_method_id, get_member_descriptors }, - { nc_block_find_members_by_path_method_id, find_members_by_path }, - { nc_block_find_members_by_role_method_id, find_members_by_role }, - { nc_block_find_members_by_class_id_method_id, find_members_by_class_id } + { nc_block_get_member_descriptors_method_id, details::make_nc_get_member_descriptors_handler() }, + { nc_block_find_members_by_path_method_id, details::make_nc_find_members_by_path_handler() }, + { nc_block_find_members_by_role_method_id, details::make_nc_find_members_by_role_handler() }, + { nc_block_find_members_by_class_id_method_id, details::make_nc_find_members_by_class_id_handler() } }), // NcBlock events to_vector(make_nc_block_events())) }, @@ -189,8 +282,8 @@ namespace nmos to_methods_vector(make_nc_class_manager_methods(), { // link NcClassManager method_ids with method functions - { nc_class_manager_get_control_class_method_id, get_control_class }, - { nc_class_manager_get_datatype_method_id, get_datatype } + { nc_class_manager_get_control_class_method_id, details::make_nc_get_control_class_handler(get_control_protocol_class_descriptor) }, + { nc_class_manager_get_datatype_method_id, details::make_nc_get_datatype_handler(get_control_protocol_datatype_descriptor) } }), // NcClassManager events to_vector(make_nc_class_manager_events())) }, diff --git a/Development/nmos/control_protocol_state.h b/Development/nmos/control_protocol_state.h index 121a75ae..b49d4e50 100644 --- a/Development/nmos/control_protocol_state.h +++ b/Development/nmos/control_protocol_state.h @@ -58,7 +58,7 @@ namespace nmos nmos::read_lock read_lock() const { return nmos::read_lock{ mutex }; } nmos::write_lock write_lock() const { return nmos::write_lock{ mutex }; } - control_protocol_state(); + control_protocol_state(control_protocol_property_changed_handler property_changed); // insert control class descriptor, false if class descriptor already inserted bool insert(const experimental::control_class_descriptor& control_class_descriptor); @@ -88,7 +88,7 @@ namespace nmos bool is_nullable = false, bool is_sequence = false, const web::json::value& constraints = web::json::value::null()); // create control class method descriptor method make_control_class_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, - const std::vector& parameters, bool is_deprecated, non_standard_method_handler method_handler); + const std::vector& parameters, bool is_deprecated, control_protocol_method_handler method_handler); // create control class event descriptor web::json::value make_control_class_event_descriptor(const utility::string_t& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, diff --git a/Development/nmos/control_protocol_ws_api.cpp b/Development/nmos/control_protocol_ws_api.cpp index 30f15ab6..b777064b 100644 --- a/Development/nmos/control_protocol_ws_api.cpp +++ b/Development/nmos/control_protocol_ws_api.cpp @@ -251,7 +251,7 @@ namespace nmos // get arguments const auto& arguments = nmos::fields::nc::arguments(cmd); - value response; + value nc_method_result; auto resource = nmos::find_resource(resources, utility::s2us(std::to_string(oid))); if (resources.end() != resource) @@ -261,31 +261,24 @@ namespace nmos // find the relevent method handler to execute // method tuple definition described in control_protocol_handlers.h auto method = get_control_protocol_method_descriptor(class_id, method_id); - auto& nc_method_descriptor = std::get<0>(method); - auto& standard_method = std::get<1>(method); - auto& non_standard_method = std::get<2>(method); - if (standard_method || non_standard_method) + auto& nc_method_descriptor = method.first; + auto& control_method_handler = method.second; + if (control_method_handler) { try { // do method arguments constraints validation method_parameters_contraints_validation(arguments, nc_method_descriptor, get_control_protocol_datatype_descriptor); - // execute the relevant method handler, then accumulating up their response to reponses - if (standard_method) - { - response = standard_method(resources, *resource, handle, arguments, nmos::fields::nc::is_deprecated(nc_method_descriptor), get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); - } - else // non_standard_method - { - response = non_standard_method(resources, *resource, handle, arguments, nmos::fields::nc::is_deprecated(nc_method_descriptor), gate); - } + // execute the relevant control method handler, then accumulating up their response to reponses + // wrap the NcMethodResuls here + nc_method_result = control_method_handler(resources, *resource, arguments, nmos::fields::nc::is_deprecated(nc_method_descriptor), gate); } catch (const nmos::control_protocol_exception& e) { // invalid arguments slog::log(gate, SLOG_FLF) << "invalid argument: " << arguments.serialize() << " error: " << e.what(); - response = make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error }); + nc_method_result = details::make_nc_method_result({ nmos::nc_method_status::parameter_error }); } } else @@ -294,7 +287,7 @@ namespace nmos utility::stringstream_t ss; ss << U("unsupported method_id: ") << nmos::fields::nc::method_id(cmd).serialize() << U(" for control class class_id: ") << resource->data.at(nmos::fields::nc::class_id).serialize(); - response = make_control_protocol_error_response(handle, { nc_method_status::method_not_implemented }, ss.str()); + nc_method_result = details::make_nc_method_result_error({ nc_method_status::method_not_implemented }, ss.str()); } } else @@ -302,16 +295,18 @@ namespace nmos // resource not found for the given oid utility::stringstream_t ss; ss << U("unknown oid: ") << oid; - response = make_control_protocol_error_response(handle, { nc_method_status::bad_oid }, ss.str()); + nc_method_result = details::make_nc_method_result_error({ nc_method_status::bad_oid }, ss.str()); } // accumulating up response + auto response = make_control_protocol_response(handle, nc_method_result); + web::json::push_back(responses, response); } // add command_response to the grain ready to transfer to the client in nmos::send_control_protocol_ws_messages_thread resources.modify(grain, [&](nmos::resource& grain) { - web::json::push_back(nmos::fields::message_grain_data(grain.data), make_control_protocol_message_response(responses)); + web::json::push_back(nmos::fields::message_grain_data(grain.data), make_control_protocol_command_response(responses)); grain.updated = strictly_increasing_update(resources); }); diff --git a/Development/nmos/test/control_protocol_test.cpp b/Development/nmos/test/control_protocol_test.cpp index 25364f65..7150accd 100644 --- a/Development/nmos/test/control_protocol_test.cpp +++ b/Development/nmos/test/control_protocol_test.cpp @@ -676,7 +676,7 @@ BST_TEST_CASE(testFindProperty) const auto invalid_property_id = nmos::nc_property_id(1000, 1000); const auto invalid_class_id = nmos::nc_class_id({ 1000, 1000 }); - nmos::experimental::control_protocol_state control_protocol_state; + nmos::experimental::control_protocol_state control_protocol_state(nullptr); auto get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); { @@ -773,7 +773,7 @@ BST_TEST_CASE(testConstraints) const auto struct_datatype = nmos::details::make_nc_datatype_descriptor_struct(U("struct datatype"), U("structDatatype"), fields, value::null()); // no datatype constraints for struct datatype // setup datatypes in control_protocol_state - nmos::experimental::control_protocol_state control_protocol_state; + nmos::experimental::control_protocol_state control_protocol_state(nullptr); control_protocol_state.insert(nmos::experimental::datatype_descriptor{ no_constraints_int16_datatype }); control_protocol_state.insert(nmos::experimental::datatype_descriptor{ no_constraints_int32_datatype }); control_protocol_state.insert(nmos::experimental::datatype_descriptor{ no_constraints_int64_datatype });