diff --git a/Development/nmos-cpp-node/config.json b/Development/nmos-cpp-node/config.json index 63625c42e..397da858f 100644 --- a/Development/nmos-cpp-node/config.json +++ b/Development/nmos-cpp-node/config.json @@ -137,6 +137,7 @@ //"channelmapping_port": 3215, // system_port [node]: used to construct request URLs for the System API (if not discovered via DNS-SD) //"system_port": 10641, + // control_protocol_ws_port [node]: used to construct request URLs for the Control Protocol websocket, or negative to disable the control protocol features //"control_protocol_ws_port": 3218, // listen_backlog [registry, node]: the maximum length of the queue of pending connections, or zero for the implementation default (the implementation may not honour this value) diff --git a/Development/nmos-cpp-node/main.cpp b/Development/nmos-cpp-node/main.cpp index 5b17eebb5..5dd65c38e 100644 --- a/Development/nmos-cpp-node/main.cpp +++ b/Development/nmos-cpp-node/main.cpp @@ -110,8 +110,11 @@ int main(int argc, char* argv[]) #endif nmos::experimental::control_protocol_state control_protocol_state; - node_implementation.on_get_control_classes(nmos::make_get_control_protocol_classes_handler(control_protocol_state, gate)); - node_implementation.on_get_control_datatypes(nmos::make_get_control_protocol_datatypes_handler(control_protocol_state, gate)); + if (0 <= nmos::fields::control_protocol_ws_port(node_model.settings)) + { + node_implementation.on_get_control_classes(nmos::make_get_control_protocol_classes_handler(control_protocol_state, gate)); + node_implementation.on_get_control_datatypes(nmos::make_get_control_protocol_datatypes_handler(control_protocol_state, gate)); + } // Set up the node server diff --git a/Development/nmos-cpp-node/node_implementation.cpp b/Development/nmos-cpp-node/node_implementation.cpp index d232d3bf3..2d4774f13 100644 --- a/Development/nmos-cpp-node/node_implementation.cpp +++ b/Development/nmos-cpp-node/node_implementation.cpp @@ -897,16 +897,19 @@ void node_implementation_init(nmos::node_model& model, const nmos::experimental: if (!insert_resource_after(delay_millis, model.channelmapping_resources, std::move(channelmapping_output), gate)) throw node_implementation_init_exception(); } - // example root block - auto root_block = nmos::make_root_block(); - // example device manager - auto device_manager = nmos::make_device_manager(2, root_block, model.settings); - if (!insert_resource_after(delay_millis, model.control_protocol_resources, std::move(device_manager), gate)) throw node_implementation_init_exception(); - // example class manager - auto class_manager = nmos::make_class_manager(3, root_block, control_protocol_state); - if (!insert_resource_after(delay_millis, model.control_protocol_resources, std::move(class_manager), gate)) throw node_implementation_init_exception(); - // insert root block to model - if (!insert_resource_after(delay_millis, model.control_protocol_resources, std::move(root_block), gate)) throw node_implementation_init_exception(); + if (0 <= nmos::fields::control_protocol_ws_port(model.settings)) + { + // example root block + auto root_block = nmos::make_root_block(); + // example device manager + auto device_manager = nmos::make_device_manager(2, root_block, model.settings); + if (!insert_resource_after(delay_millis, model.control_protocol_resources, std::move(device_manager), gate)) throw node_implementation_init_exception(); + // example class manager + auto class_manager = nmos::make_class_manager(3, root_block, control_protocol_state); + if (!insert_resource_after(delay_millis, model.control_protocol_resources, std::move(class_manager), gate)) throw node_implementation_init_exception(); + // insert root block to model + if (!insert_resource_after(delay_millis, model.control_protocol_resources, std::move(root_block), gate)) throw node_implementation_init_exception(); + } } void node_implementation_run(nmos::node_model& model, slog::base_gate& gate) diff --git a/Development/nmos/node_server.cpp b/Development/nmos/node_server.cpp index d163fdea8..cf4c15054 100644 --- a/Development/nmos/node_server.cpp +++ b/Development/nmos/node_server.cpp @@ -69,10 +69,14 @@ namespace nmos events_ws_api.first = nmos::make_events_ws_api(node_model, events_ws_api.second, gate); // can't share a port between the events ws and the control protocol ws + const auto& control_protocol_enabled = (0 <= nmos::fields::control_protocol_ws_port(node_model.settings)); const auto& control_protocol_ws_port = nmos::fields::control_protocol_ws_port(node_model.settings); - if (control_protocol_ws_port == events_ws_port) throw std::runtime_error("Same port used for events and control protocol websockets are not supported"); - auto& control_protocol_ws_api = node_server.ws_handlers[{ {}, control_protocol_ws_port }]; - control_protocol_ws_api.first = nmos::make_control_protocol_ws_api(node_model, control_protocol_ws_api.second, node_implementation.get_control_protocol_classes, node_implementation.get_control_protocol_datatypes, gate); + if (control_protocol_enabled) + { + if (control_protocol_ws_port == events_ws_port) throw std::runtime_error("Same port used for events and control protocol websockets are not supported"); + auto& control_protocol_ws_api = node_server.ws_handlers[{ {}, control_protocol_ws_port }]; + control_protocol_ws_api.first = nmos::make_control_protocol_ws_api(node_model, control_protocol_ws_api.second, node_implementation.get_control_protocol_classes, node_implementation.get_control_protocol_datatypes, gate); + } // Set up the listeners for each HTTP API port @@ -110,7 +114,7 @@ namespace nmos else { ++event_ws_pos; } } - if (!found_control_protocol_ws) + if (control_protocol_enabled && !found_control_protocol_ws) { if (ws_handler.first.second == control_protocol_ws_port) { found_control_protocol_ws = true; } else { ++control_protocol_ws_pos; } @@ -118,7 +122,6 @@ namespace nmos } auto& events_ws_listener = node_server.ws_listeners.at(event_ws_pos); - auto& control_protocol_ws_listener = node_server.ws_listeners.at(control_protocol_ws_pos); // Set up node operation (including the DNS-SD advertisements) @@ -133,8 +136,7 @@ namespace nmos [&] { nmos::send_events_ws_messages_thread(events_ws_listener, node_model, events_ws_api.second, gate); }, [&] { nmos::erase_expired_events_resources_thread(node_model, gate); }, [&, resolve_auto, set_transportfile, connection_activated] { nmos::connection_activation_thread(node_model, resolve_auto, set_transportfile, connection_activated, gate); }, - [&, channelmapping_activated] { nmos::channelmapping_activation_thread(node_model, channelmapping_activated, gate); }, - [&] { nmos::send_control_protocol_ws_messages_thread(control_protocol_ws_listener, node_model, control_protocol_ws_api.second, gate); } + [&, channelmapping_activated] { nmos::channelmapping_activation_thread(node_model, channelmapping_activated, gate); } }); auto system_changed = node_implementation.system_changed; @@ -143,6 +145,13 @@ namespace nmos node_server.thread_functions.push_back([&, load_ca_certificates, system_changed] { nmos::node_system_behaviour_thread(node_model, load_ca_certificates, system_changed, gate); }); } + if (control_protocol_enabled) + { + auto& control_protocol_ws_listener = node_server.ws_listeners.at(control_protocol_ws_pos); + auto& control_protocol_ws_api = node_server.ws_handlers.at({ {}, control_protocol_ws_port }); + node_server.thread_functions.push_back([&] { nmos::send_control_protocol_ws_messages_thread(control_protocol_ws_listener, node_model, control_protocol_ws_api.second, gate); }); + } + return node_server; } diff --git a/Development/nmos/settings.h b/Development/nmos/settings.h index e5e46ed0f..467c7c0e2 100644 --- a/Development/nmos/settings.h +++ b/Development/nmos/settings.h @@ -142,6 +142,7 @@ namespace nmos const web::json::field_as_integer_or channelmapping_port{ U("channelmapping_port"), 3215 }; // system_port [node]: used to construct request URLs for the System API (if not discovered via DNS-SD) const web::json::field_as_integer_or system_port{ U("system_port"), 10641 }; + // control_protocol_ws_port [node]: used to construct request URLs for the Control Protocol websocket, or negative to disable the control protocol features const web::json::field_as_integer_or control_protocol_ws_port{ U("control_protocol_ws_port"), 3218 }; // listen_backlog [registry, node]: the maximum length of the queue of pending connections, or zero for the implementation default (the implementation may not honour this value)