Skip to content

Commit

Permalink
Add method parameters constriants validation, and check method deprec…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
lo-simon committed Nov 18, 2023
1 parent 4420e1e commit bc5e0f5
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 293 deletions.
67 changes: 10 additions & 57 deletions Development/nmos-cpp-node/node_implementation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1006,81 +1006,34 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr
nmos::experimental::make_control_class_property(U("Example object sequence property"), { 3, 13 }, object_sequence, U("ExampleDataType"), false, false, true)
};

auto example_method_with_no_args = [](nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)
auto example_method_with_no_args = [](nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, const web::json::value& nc_method_descriptor, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)
{
// note, model mutex is already locked by the outter function, so access to control_protocol_resources is OK...

slog::log<slog::severities::more_info>(gate, SLOG_FLF) << "Executing the example method with no arguments";

return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::ok });
return nmos::make_control_protocol_message_response(handle, { nmos::fields::nc::is_deprecated(nc_method_descriptor) ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok });
};
auto example_method_with_simple_args = [enum_arg, string_arg, number_arg, boolean_arg, make_string_example_argument_constraints, make_number_example_argument_constraints](nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)
auto example_method_with_simple_args = [](nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)
{
// note, model mutex is already locked by the outter function, so access to control_protocol_resources is OK...

using web::json::value;
// and the method parameters constriants has already been validated by the outter function

slog::log<slog::severities::more_info>(gate, SLOG_FLF) << "Executing the example method with simple arguments: " << arguments.serialize();

// example to do method arguments constraints validation
if (!nmos::constraints_validation(arguments.at(enum_arg), value::null(), value::null(), { nmos::details::get_datatype_descriptor(value::string(U("ExampleEnum")), get_control_protocol_datatype), get_control_protocol_datatype }))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid enum_arg: " << arguments.at(enum_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}
if (!nmos::constraints_validation(arguments.at(string_arg), make_string_example_argument_constraints(), value::null(), {nmos::details::get_datatype_descriptor(value::string(U("NcString")), get_control_protocol_datatype), get_control_protocol_datatype}))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid string_arg: " << arguments.at(string_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}
if (!nmos::constraints_validation(arguments.at(number_arg), make_number_example_argument_constraints(), value::null(), { nmos::details::get_datatype_descriptor(value::string(U("NcUint64")), get_control_protocol_datatype), get_control_protocol_datatype }))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid number_arg: " << arguments.at(number_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}
if (!nmos::constraints_validation(arguments.at(boolean_arg), value::null(), value::null(), { nmos::details::get_datatype_descriptor(value::string(U("NcBoolean")), get_control_protocol_datatype), get_control_protocol_datatype }))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid boolean_arg: " << arguments.at(boolean_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}

return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::ok });
return nmos::make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok });
};
auto example_method_with_object_args = [obj_arg, enum_arg, string_arg, number_arg, boolean_arg, make_string_example_argument_constraints, make_number_example_argument_constraints](nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)
auto example_method_with_object_args = [](nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, nmos::get_control_protocol_class_handler get_control_protocol_class, nmos::get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)
{
// note, model mutex is already locked by the outter function, so access to control_protocol_resources is OK...
// and the method parameters constriants has already been validated by the outter function

using web::json::value;

slog::log<slog::severities::more_info>(gate, SLOG_FLF) << "Executing the example method with object argument: " << obj_arg(arguments).serialize();

// example to do method arguments constraints validation
const auto& obj_arg_ = obj_arg(arguments);
if (!nmos::constraints_validation(obj_arg_.at(enum_arg), value::null(), value::null(), { nmos::details::get_datatype_descriptor(value::string(U("ExampleEnum")), get_control_protocol_datatype), get_control_protocol_datatype }))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid enum_arg: " << obj_arg_.at(enum_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}
if (!nmos::constraints_validation(obj_arg_.at(string_arg), make_string_example_argument_constraints(), value::null(), { nmos::details::get_datatype_descriptor(value::string(U("NcString")), get_control_protocol_datatype), get_control_protocol_datatype }))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid string_arg: " << obj_arg_.at(string_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}
if (!nmos::constraints_validation(obj_arg_.at(number_arg), make_number_example_argument_constraints(), value::null(), { nmos::details::get_datatype_descriptor(value::string(U("NcUint64")), get_control_protocol_datatype), get_control_protocol_datatype }))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid number_arg: " << obj_arg_.at(number_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}
if (!nmos::constraints_validation(obj_arg_.at(boolean_arg), value::null(), value::null(), { nmos::details::get_datatype_descriptor(value::string(U("NcBoolean")), get_control_protocol_datatype), get_control_protocol_datatype }))
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "invalid boolean_arg: " << obj_arg_.at(boolean_arg).serialize();
return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::parameter_error });
}
slog::log<slog::severities::more_info>(gate, SLOG_FLF) << "Executing the example method with object argument: " << arguments.serialize();

return nmos::make_control_protocol_message_response(handle, { nmos::nc_method_status::ok });
return nmos::make_control_protocol_message_response(handle, { is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok });
};
// Example control class methods
std::vector<std::pair<web::json::value, nmos::experimental::method_handler>> example_control_methods =
std::vector<nmos::experimental::method> example_control_methods =
{
{ nmos::experimental::make_control_class_method(U("Example method with no arguments"), { 3, 1 }, U("MethodNoArgs"), U("NcMethodResult"), {}, false), example_method_with_no_args },
{ nmos::experimental::make_control_class_method(U("Example method with simple arguments"), { 3, 2 }, U("MethodSimpleArgs"), U("NcMethodResult"),
Expand Down
17 changes: 10 additions & 7 deletions Development/nmos/control_protocol_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,21 @@ namespace nmos
while (!class_id.empty())
{
const auto& control_class = get_control_protocol_class(class_id);
auto& methods = control_class.method_handlers;

auto method_found = methods.find(method_id);
auto& methods = control_class.methods;
auto method_found = std::find_if(methods.begin(), methods.end(), [&method_id](const experimental::method& method)
{
return method_id == details::parse_nc_method_id(nmos::fields::nc::id(method.first));
});
if (methods.end() != method_found)
{
return method_found->second;
return *method_found;
}

class_id.pop_back();
}

return experimental::method_handler(nullptr);
return experimental::method();
};
}

Expand All @@ -81,9 +84,9 @@ namespace nmos
// hmm, maybe updating connectionStatusMessage, payloadStatus, and payloadStatusMessage too

const auto propertry_changed_event = make_propertry_changed_event(nmos::fields::nc::oid(found->data),
{
{ nc_receiver_monitor_connection_status_property_id, nc_property_change_type::type::value_changed, val }
});
{
{ nc_receiver_monitor_connection_status_property_id, nc_property_change_type::type::value_changed, val }
});

modify_control_protocol_resource(resources, found->id, [&](nmos::resource& resource)
{
Expand Down
19 changes: 8 additions & 11 deletions Development/nmos/control_protocol_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,24 @@ namespace nmos

namespace experimental
{
// method handler defnition
typedef std::function<web::json::value(nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, get_control_protocol_class_handler get_control_protocol_class, get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)> method_handler;
// methods defnition
typedef std::map<nmos::nc_method_id, method_handler> methods; // method_id vs method handler
}
// method handler definition
typedef std::function<web::json::value(nmos::resources& resources, nmos::resources::iterator resource, int32_t handle, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_handler get_control_protocol_class, get_control_protocol_datatype_handler get_control_protocol_datatype, slog::base_gate& gate)> method_handler;

// callback to retrieve all the method handlers
// this callback should not throw exceptions
typedef std::function<std::map<nmos::nc_class_id, experimental::methods>()> get_control_protocol_methods_handler;
// method definition (NcMethodDescriptor vs method handler)
typedef std::pair<web::json::value, nmos::experimental::method_handler> method;
}

// callback to retrieve a specific method handler
// callback to retrieve a specific method
// this callback should not throw exceptions
typedef std::function<experimental::method_handler(const nc_class_id& class_id, const nc_method_id& method_id)> get_control_protocol_method_handler;
typedef std::function<experimental::method(const nc_class_id& class_id, const nc_method_id& method_id)> get_control_protocol_method_handler;

// construct callback to retrieve a specific control protocol class
get_control_protocol_class_handler make_get_control_protocol_class_handler(experimental::control_protocol_state& control_protocol_state);

// construct callback to retrieve a specific datatype
get_control_protocol_datatype_handler make_get_control_protocol_datatype_handler(experimental::control_protocol_state& control_protocol_state);

// construct callback to retrieve a specific method handler
// construct callback to retrieve a specific method
get_control_protocol_method_handler make_get_control_protocol_method_handler(experimental::control_protocol_state& control_protocol_state);

// a control_protocol_connection_activation_handler is a notification that the active parameters for the specified (IS-05) sender/connection_sender or receiver/connection_receiver have changed
Expand Down
Loading

0 comments on commit bc5e0f5

Please sign in to comment.