From 951c1b661cd71501c0ec83a121d394bd30801349 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Wed, 28 May 2025 13:58:02 +0200 Subject: [PATCH 01/13] Initial commit: added folder, qos, idl, readme --- examples/connext_secure/CMakeLists.txt | 1 + .../dynamic_permissions/README.md | 5 ++ .../dynamic_permissions/c++11/CMakeLists.txt | 41 +++++++++++ .../c++11/USER_QOS_PROFILES.xml | 68 +++++++++++++++++++ .../c++11/dynamic_permissions.idl | 14 ++++ 5 files changed, 129 insertions(+) create mode 100644 examples/connext_secure/dynamic_permissions/README.md create mode 100644 examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt create mode 100644 examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml create mode 100644 examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl diff --git a/examples/connext_secure/CMakeLists.txt b/examples/connext_secure/CMakeLists.txt index 4df2dc5a4..3ceb72855 100644 --- a/examples/connext_secure/CMakeLists.txt +++ b/examples/connext_secure/CMakeLists.txt @@ -24,6 +24,7 @@ if(NOT DEFINED CONNEXTDDS_CONNEXT_SECURE_EXAMPLES) set(CONNEXTDDS_CONNEXT_SECURE_EXAMPLES "cds" "certificate_revocation_list" + "dynamic_permissions" "lightweight" "whitelist" ) diff --git a/examples/connext_secure/dynamic_permissions/README.md b/examples/connext_secure/dynamic_permissions/README.md new file mode 100644 index 000000000..44a8cde22 --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/README.md @@ -0,0 +1,5 @@ +# Example Code: Dynamic Permissions + +## Concept + +Missing description. \ No newline at end of file diff --git a/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt b/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt new file mode 100644 index 000000000..47fa5e107 --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# (c) 2025 Copyright, Real-Time Innovations, Inc. All rights reserved. +# +# RTI grants Licensee a license to use, modify, compile, and create derivative +# works of the Software. Licensee has the right to distribute object form +# only for use with RTI products. The Software is provided "as is", with no +# warranty of any type, including any warranty for fitness for any purpose. +# RTI is under no obligation to maintain or support the Software. RTI shall +# not be liable for any incidental or consequential damages arising out of the +# use or inability to use the software. +# +cmake_minimum_required(VERSION 3.11) +project(rtiexamples-dynamic-permissions) +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/../../../../resources/cmake/Modules" +) +include(ConnextDdsConfigureCmakeUtils) +connextdds_configure_cmake_utils() + +find_package(RTIConnextDDS + "7.0.0" + REQUIRED + COMPONENTS + security_plugins +) + +if(NOT TARGET RTIConnextDDS::security_plugins) + message(WARNING "RTIConnextDDS::security_plugins component is missing. Skipping example") + return() +endif() + +# Include ConnextDdsAddExample.cmake from resources/cmake +include(ConnextDdsAddExample) + +connextdds_add_example( + IDL "dynamic_permissions" + LANG "C++11" +) + +include (ConnextDdsGenerateSecurityArtifacts) +connextdds_generate_security_artifacts() \ No newline at end of file diff --git a/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml b/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml new file mode 100644 index 000000000..23c2b7a8b --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml @@ -0,0 +1,68 @@ + + + + + + + + + + dds.sec.auth.identity_ca + file:security/ecdsa01/certs/ca_cert.pem + + + dds.sec.auth.identity_certificate + file:security/ecdsa01/certs/peer1_cert.pem + + + dds.sec.auth.private_key + file:security/ecdsa01/certs/peer1_key.pem + + + dds.sec.access.permissions_ca + file:security/ecdsa01/certs/ca_cert.pem + + + dds.sec.access.governance + file:security/ecdsa01/xml/signed/signed_Governance.p7s + + + dds.sec.access.permissions + file:security/ecdsa01/xml/signed/signed_Permissions1.p7s + + + + + + + + + + + dds.sec.auth.identity_certificate + file:security/ecdsa01/certs/peer2_cert.pem + + + dds.sec.auth.private_key + file:security/ecdsa01/certs/peer2_key.pem + + + dds.sec.access.permissions + file:security/ecdsa01/xml/signed/signed_Permissions2.p7s + + + + + + + diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl new file mode 100644 index 000000000..67b9242f1 --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl @@ -0,0 +1,14 @@ +/* + * (c) 2025 Copyright, Real-Time Innovations, Inc. All rights reserved. + * + * RTI grants Licensee a license to use, modify, compile, and create derivative + * works of the Software. Licensee has the right to distribute object form + * only for use with RTI products. The Software is provided "as is", with no + * warranty of any type, including any warranty for fitness for any purpose. + * RTI is under no obligation to maintain or support the Software. RTI shall + * not be liable for any incidental or consequential damages arising out of the + * use or inability to use the software. + */ +struct DynamicPermissions { + string<128> msg; +}; From a66d5f38ad9d0d7f1225ef179de09c0ca4083548 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Wed, 28 May 2025 15:55:51 +0200 Subject: [PATCH 02/13] basic secure application --- .../dynamic_permissions/README.md | 12 +- .../dynamic_permissions/c++11/application.h | 128 ++++++++++++++++ .../dynamic_permissions/c++11/application.hpp | 141 ++++++++++++++++++ .../c++11/dynamic_permissions_publisher.cxx | 94 ++++++++++++ .../c++11/dynamic_permissions_subscriber.cxx | 116 ++++++++++++++ .../ConnextDdsGenerateSecurityArtifacts.cmake | 1 + 6 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 examples/connext_secure/dynamic_permissions/c++11/application.h create mode 100644 examples/connext_secure/dynamic_permissions/c++11/application.hpp create mode 100644 examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx create mode 100644 examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx diff --git a/examples/connext_secure/dynamic_permissions/README.md b/examples/connext_secure/dynamic_permissions/README.md index 44a8cde22..8f014cf5b 100644 --- a/examples/connext_secure/dynamic_permissions/README.md +++ b/examples/connext_secure/dynamic_permissions/README.md @@ -2,4 +2,14 @@ ## Concept -Missing description. \ No newline at end of file +Missing description. + +## Building the Example + +```sh +cd c++11/ +mkdir build +cd build +cmake .. +cmake --build . +``` \ No newline at end of file diff --git a/examples/connext_secure/dynamic_permissions/c++11/application.h b/examples/connext_secure/dynamic_permissions/c++11/application.h new file mode 100644 index 000000000..22cb1de83 --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/application.h @@ -0,0 +1,128 @@ +/* +* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* RTI grants Licensee a license to use, modify, compile, and create derivative +* works of the software solely for use with RTI Connext DDS. Licensee may +* redistribute copies of the software provided that all such copies are subject +* to this license. The software is provided "as is", with no warranty of any +* type, including any warranty for fitness for any purpose. RTI is under no +* obligation to maintain or support the software. RTI shall not be liable for +* any incidental or consequential damages arising out of the use or inability +* to use the software. +*/ + +#ifndef APPLICATION_H +#define APPLICATION_H + +#include +#include +#include + +namespace application { + + // Catch control-C and tell application to shut down + bool shutdown_requested = false; + + inline void stop_handler(int) + { + shutdown_requested = true; + std::cout << "preparing to shut down..." << std::endl; + } + + inline void setup_signal_handlers() + { + signal(SIGINT, stop_handler); + signal(SIGTERM, stop_handler); + } + + enum ParseReturn { PARSE_RETURN_OK, PARSE_RETURN_FAILURE, PARSE_RETURN_EXIT }; + + struct ApplicationArguments { + ParseReturn parse_result; + unsigned int domain_id; + unsigned int sample_count; + NDDS_Config_LogVerbosity verbosity; + }; + + inline void set_verbosity( + ApplicationArguments& arguments, + int verbosity) + { + switch (verbosity) { + case 0: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_SILENT; + break; + case 1: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; + break; + case 2: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_WARNING; + break; + case 3: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL; + break; + default: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; + break; + } + } + + // Parses application arguments for example. Returns whether to exit. + inline void parse_arguments( + ApplicationArguments& arguments, + int argc, + char *argv[]) + { + int arg_processing = 1; + bool show_usage = false; + arguments.domain_id = 0; + arguments.sample_count = INT_MAX; + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; + arguments.parse_result = PARSE_RETURN_OK; + + while (arg_processing < argc) { + if ((argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-d") == 0 + || strcmp(argv[arg_processing], "--domain") == 0)) { + arguments.domain_id = atoi(argv[arg_processing + 1]); + arg_processing += 2; + } else if ((argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-s") == 0 + || strcmp(argv[arg_processing], "--sample-count") == 0)) { + arguments.sample_count = atoi(argv[arg_processing + 1]); + arg_processing += 2; + } else if ((argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-v") == 0 + || strcmp(argv[arg_processing], "--verbosity") == 0)) { + set_verbosity(arguments, atoi(argv[arg_processing + 1])); + arg_processing += 2; + } else if (strcmp(argv[arg_processing], "-h") == 0 + || strcmp(argv[arg_processing], "--help") == 0) { + std::cout << "Example application." << std::endl; + show_usage = true; + arguments.parse_result = PARSE_RETURN_EXIT; + break; + } else { + std::cout << "Bad parameter." << std::endl; + show_usage = true; + arguments.parse_result = PARSE_RETURN_FAILURE; + break; + } + } + if (show_usage) { + std::cout << "Usage:\n"\ + " -d, --domain Domain ID this application will\n" \ + " subscribe in. \n" + " Default: 0\n"\ + " -s, --sample_count Number of samples to receive before\n"\ + " cleanly shutting down. \n" + " Default: infinite\n" + " -v, --verbosity How much debugging output to show.\n"\ + " Range: 0-3 \n" + " Default: 1" + << std::endl; + } + } + +} // namespace application + +#endif // APPLICATION_H diff --git a/examples/connext_secure/dynamic_permissions/c++11/application.hpp b/examples/connext_secure/dynamic_permissions/c++11/application.hpp new file mode 100644 index 000000000..17683705b --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/application.hpp @@ -0,0 +1,141 @@ +/* +* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* RTI grants Licensee a license to use, modify, compile, and create derivative +* works of the software solely for use with RTI Connext DDS. Licensee may +* redistribute copies of the software provided that all such copies are subject +* to this license. The software is provided "as is", with no warranty of any +* type, including any warranty for fitness for any purpose. RTI is under no +* obligation to maintain or support the software. RTI shall not be liable for +* any incidental or consequential damages arising out of the use or inability +* to use the software. +*/ + +#ifndef APPLICATION_HPP +#define APPLICATION_HPP + +#include +#include +#include + +namespace application { + + // Catch control-C and tell application to shut down + bool shutdown_requested = false; + + inline void stop_handler(int) + { + shutdown_requested = true; + std::cout << "preparing to shut down..." << std::endl; + } + + inline void setup_signal_handlers() + { + signal(SIGINT, stop_handler); + signal(SIGTERM, stop_handler); + } + + enum class ParseReturn { + ok, + failure, + exit + }; + + struct ApplicationArguments { + ParseReturn parse_result; + unsigned int domain_id; + unsigned int sample_count; + rti::config::Verbosity verbosity; + + ApplicationArguments( + ParseReturn parse_result_param, + unsigned int domain_id_param, + unsigned int sample_count_param, + rti::config::Verbosity verbosity_param) + : parse_result(parse_result_param), + domain_id(domain_id_param), + sample_count(sample_count_param), + verbosity(verbosity_param) {} + }; + + inline void set_verbosity( + rti::config::Verbosity& verbosity, + int verbosity_value) + { + switch (verbosity_value) { + case 0: + verbosity = rti::config::Verbosity::SILENT; + break; + case 1: + verbosity = rti::config::Verbosity::EXCEPTION; + break; + case 2: + verbosity = rti::config::Verbosity::WARNING; + break; + case 3: + verbosity = rti::config::Verbosity::STATUS_ALL; + break; + default: + verbosity = rti::config::Verbosity::EXCEPTION; + break; + } + } + + // Parses application arguments for example. + inline ApplicationArguments parse_arguments(int argc, char *argv[]) + { + int arg_processing = 1; + bool show_usage = false; + ParseReturn parse_result = ParseReturn::ok; + unsigned int domain_id = 0; + unsigned int sample_count = (std::numeric_limits::max)(); + rti::config::Verbosity verbosity(rti::config::Verbosity::EXCEPTION); + + while (arg_processing < argc) { + if ((argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-d") == 0 + || strcmp(argv[arg_processing], "--domain") == 0)) { + domain_id = atoi(argv[arg_processing + 1]); + arg_processing += 2; + } else if ((argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-s") == 0 + || strcmp(argv[arg_processing], "--sample-count") == 0)) { + sample_count = atoi(argv[arg_processing + 1]); + arg_processing += 2; + } else if ((argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-v") == 0 + || strcmp(argv[arg_processing], "--verbosity") == 0)) { + set_verbosity(verbosity, atoi(argv[arg_processing + 1])); + arg_processing += 2; + } else if (strcmp(argv[arg_processing], "-h") == 0 + || strcmp(argv[arg_processing], "--help") == 0) { + std::cout << "Example application." << std::endl; + show_usage = true; + parse_result = ParseReturn::exit; + break; + } else { + std::cout << "Bad parameter." << std::endl; + show_usage = true; + parse_result = ParseReturn::failure; + break; + } + } + if (show_usage) { + std::cout << "Usage:\n"\ + " -d, --domain Domain ID this application will\n" \ + " subscribe in. \n" + " Default: 0\n"\ + " -s, --sample_count Number of samples to receive before\n"\ + " cleanly shutting down. \n" + " Default: infinite\n" + " -v, --verbosity How much debugging output to show.\n"\ + " Range: 0-3 \n" + " Default: 1" + << std::endl; + } + + return ApplicationArguments(parse_result, domain_id, sample_count, verbosity); + } + +} // namespace application + +#endif // APPLICATION_HPP diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx new file mode 100644 index 000000000..24bd8e1cd --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx @@ -0,0 +1,94 @@ +/* +* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* RTI grants Licensee a license to use, modify, compile, and create derivative +* works of the software solely for use with RTI Connext DDS. Licensee may +* redistribute copies of the software provided that all such copies are subject +* to this license. The software is provided "as is", with no warranty of any +* type, including any warranty for fitness for any purpose. RTI is under no +* obligation to maintain or support the software. RTI shall not be liable for +* any incidental or consequential damages arising out of the use or inability +* to use the software. +*/ + +#include + +#include +#include // for sleep() +#include // for logging +// alternatively, to include all the standard APIs: +// +// or to include both the standard APIs and extensions: +// +// +// For more information about the headers and namespaces, see: +// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSNamespaceModule.html +// For information on how to use extensions, see: +// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSCpp2Conventions.html + +#include "application.hpp" // for command line parsing and ctrl-c +#include "dynamic_permissions.hpp" + +void run_publisher_application(unsigned int domain_id, unsigned int sample_count) +{ + // DDS objects behave like shared pointers or value types + // (see https://community.rti.com/best-practices/use-modern-c-types-correctly) + + // Start communicating in a domain, usually one participant per application + dds::domain::DomainParticipant participant(domain_id); + + // Create a Topic with a name and a datatype + dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); + + // Create a Publisher + dds::pub::Publisher publisher(participant); + + // Create a DataWriter with default QoS + dds::pub::DataWriter< ::DynamicPermissions> writer(publisher, topic); + + ::DynamicPermissions data; + // Main loop, write data + for (unsigned int samples_written = 0; + !application::shutdown_requested && samples_written < sample_count; + samples_written++) { + // Modify the data to be written here + std::cout << "Writing ::DynamicPermissions, count " << samples_written << std::endl; + + writer.write(data); + + // Send once every second + rti::util::sleep(dds::core::Duration(1)); + } +} + +int main(int argc, char *argv[]) +{ + + using namespace application; + + // Parse arguments and handle control-C + auto arguments = parse_arguments(argc, argv); + if (arguments.parse_result == ParseReturn::exit) { + return EXIT_SUCCESS; + } else if (arguments.parse_result == ParseReturn::failure) { + return EXIT_FAILURE; + } + setup_signal_handlers(); + + // Sets Connext verbosity to help debugging + rti::config::Logger::instance().verbosity(arguments.verbosity); + + try { + run_publisher_application(arguments.domain_id, arguments.sample_count); + } catch (const std::exception& ex) { + // This will catch DDS exceptions + std::cerr << "Exception in run_publisher_application(): " << ex.what() + << std::endl; + return EXIT_FAILURE; + } + + // Releases the memory used by the participant factory. Optional at + // application exit + dds::domain::DomainParticipant::finalize_participant_factory(); + + return EXIT_SUCCESS; +} diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx new file mode 100644 index 000000000..59f63ea21 --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx @@ -0,0 +1,116 @@ +/* +* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* RTI grants Licensee a license to use, modify, compile, and create derivative +* works of the software solely for use with RTI Connext DDS. Licensee may +* redistribute copies of the software provided that all such copies are subject +* to this license. The software is provided "as is", with no warranty of any +* type, including any warranty for fitness for any purpose. RTI is under no +* obligation to maintain or support the software. RTI shall not be liable for +* any incidental or consequential damages arising out of the use or inability +* to use the software. +*/ + +#include +#include + +#include +#include +#include // for logging +// alternatively, to include all the standard APIs: +// +// or to include both the standard APIs and extensions: +// +// +// For more information about the headers and namespaces, see: +// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSNamespaceModule.html +// For information on how to use extensions, see: +// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSCpp2Conventions.html + +#include "dynamic_permissions.hpp" +#include "application.hpp" // for command line parsing and ctrl-c + +int process_data(dds::sub::DataReader< ::DynamicPermissions> reader) +{ + // Take all samples + int count = 0; + dds::sub::LoanedSamples< ::DynamicPermissions> samples = reader.take(); + for (auto sample : samples) { + if (sample.info().valid()) { + count++; + std::cout << sample.data() << std::endl; + } else { + std::cout << "Instance state changed to " + << sample.info().state().instance_state() << std::endl; + } + } + + return count; +} // The LoanedSamples destructor returns the loan + +void run_subscriber_application(unsigned int domain_id, unsigned int sample_count) +{ + // DDS objects behave like shared pointers or value types + // (see https://community.rti.com/best-practices/use-modern-c-types-correctly) + + // Start communicating in a domain, usually one participant per application + dds::domain::DomainParticipant participant(domain_id); + + // Create a Topic with a name and a datatype + dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); + + // Create a Subscriber and DataReader with default Qos + dds::sub::Subscriber subscriber(participant); + dds::sub::DataReader< ::DynamicPermissions> reader(subscriber, topic); + + // Create a ReadCondition for any data received on this reader and set a + // handler to process the data + unsigned int samples_read = 0; + dds::sub::cond::ReadCondition read_condition( + reader, + dds::sub::status::DataState::any(), + [reader, &samples_read]() { samples_read += process_data(reader); }); + + // WaitSet will be woken when the attached condition is triggered + dds::core::cond::WaitSet waitset; + waitset += read_condition; + + while (!application::shutdown_requested && samples_read < sample_count) { + std::cout << "::DynamicPermissions subscriber sleeping up to 1 sec..." << std::endl; + + // Run the handlers of the active conditions. Wait for up to 1 second. + waitset.dispatch(dds::core::Duration(1)); + } +} + +int main(int argc, char *argv[]) +{ + + using namespace application; + + // Parse arguments and handle control-C + auto arguments = parse_arguments(argc, argv); + if (arguments.parse_result == ParseReturn::exit) { + return EXIT_SUCCESS; + } else if (arguments.parse_result == ParseReturn::failure) { + return EXIT_FAILURE; + } + setup_signal_handlers(); + + // Sets Connext verbosity to help debugging + rti::config::Logger::instance().verbosity(arguments.verbosity); + + try { + run_subscriber_application(arguments.domain_id, arguments.sample_count); + } catch (const std::exception& ex) { + // This will catch DDS exceptions + std::cerr << "Exception in run_subscriber_application(): " << ex.what() + << std::endl; + return EXIT_FAILURE; + } + + // Releases the memory used by the participant factory. Optional at + // application exit + dds::domain::DomainParticipant::finalize_participant_factory(); + + return EXIT_SUCCESS; +} diff --git a/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake b/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake index 65fe6693b..cc1a5ac2e 100644 --- a/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake +++ b/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake @@ -149,6 +149,7 @@ function(connextdds_generate_security_artifacts) ECPARAM_NAME prime256v1 ECPARAM_OUTPUT_FILE "${openssl_temporary_dir}/ecdsaparam" CONFIG_FILE "${ca_config_file}" + CA_EXTENSION v3_ca WORKING_DIRECTORY "${openssl_working_dir}" ) From d38dbf6c15cb40949f13b6738450cc461877dabc Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Wed, 28 May 2025 16:34:15 +0200 Subject: [PATCH 03/13] update copyright notes --- .../c++11/dynamic_permissions_publisher.cxx | 14 +------------- .../c++11/dynamic_permissions_subscriber.cxx | 16 ++-------------- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx index 24bd8e1cd..9f723818e 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx @@ -1,5 +1,5 @@ /* -* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* (c) Copyright, Real-Time Innovations, 2025. All rights reserved. * RTI grants Licensee a license to use, modify, compile, and create derivative * works of the software solely for use with RTI Connext DDS. Licensee may * redistribute copies of the software provided that all such copies are subject @@ -15,24 +15,12 @@ #include #include // for sleep() #include // for logging -// alternatively, to include all the standard APIs: -// -// or to include both the standard APIs and extensions: -// -// -// For more information about the headers and namespaces, see: -// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSNamespaceModule.html -// For information on how to use extensions, see: -// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSCpp2Conventions.html #include "application.hpp" // for command line parsing and ctrl-c #include "dynamic_permissions.hpp" void run_publisher_application(unsigned int domain_id, unsigned int sample_count) { - // DDS objects behave like shared pointers or value types - // (see https://community.rti.com/best-practices/use-modern-c-types-correctly) - // Start communicating in a domain, usually one participant per application dds::domain::DomainParticipant participant(domain_id); diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx index 59f63ea21..00138148f 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx @@ -1,5 +1,5 @@ /* -* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* (c) Copyright, Real-Time Innovations, 2025. All rights reserved. * RTI grants Licensee a license to use, modify, compile, and create derivative * works of the software solely for use with RTI Connext DDS. Licensee may * redistribute copies of the software provided that all such copies are subject @@ -15,16 +15,7 @@ #include #include -#include // for logging -// alternatively, to include all the standard APIs: -// -// or to include both the standard APIs and extensions: -// -// -// For more information about the headers and namespaces, see: -// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSNamespaceModule.html -// For information on how to use extensions, see: -// https://community.rti.com/static/documentation/connext-dds/7.5.0/doc/api/connext_dds/api_cpp2/group__DDSCpp2Conventions.html +#include #include "dynamic_permissions.hpp" #include "application.hpp" // for command line parsing and ctrl-c @@ -49,9 +40,6 @@ int process_data(dds::sub::DataReader< ::DynamicPermissions> reader) void run_subscriber_application(unsigned int domain_id, unsigned int sample_count) { - // DDS objects behave like shared pointers or value types - // (see https://community.rti.com/best-practices/use-modern-c-types-correctly) - // Start communicating in a domain, usually one participant per application dds::domain::DomainParticipant participant(domain_id); From 64d2e46a8e20c11233ee0d919d18926836b6c396 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Wed, 28 May 2025 18:10:27 +0200 Subject: [PATCH 04/13] generate signed modified permissions document --- .../dynamic_permissions/c++11/CMakeLists.txt | 28 ++++++++++++++++++- .../c++11/USER_QOS_PROFILES.xml | 2 +- .../c++11/dynamic_permissions_publisher.cxx | 5 +++- .../c++11/dynamic_permissions_subscriber.cxx | 5 +++- .../c++11/modify_permissions.cmake | 19 +++++++++++++ 5 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake diff --git a/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt b/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt index 47fa5e107..d70e14f43 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt +++ b/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt @@ -38,4 +38,30 @@ connextdds_add_example( ) include (ConnextDdsGenerateSecurityArtifacts) -connextdds_generate_security_artifacts() \ No newline at end of file +connextdds_generate_security_artifacts() + +# Do a copy of the original subscriber's Permissions Document, but with the +# validity modified so that it expires in 1 minute. +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/Permissions2_expiring.xml" + COMMAND ${CMAKE_COMMAND} + -DINPUT_FILE="${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/Permissions2.xml" + -DOUTPUT_FILE="${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/Permissions2_expiring.xml" + -P ${CMAKE_SOURCE_DIR}/modify_permissions.cmake + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/Permissions2.xml" +) + +# Sign the modified Permissions Document +connextdds_openssl_smime_sign( + INPUT "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/Permissions2_expiring.xml" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/signed/signed_Permissions2_expiring.p7s" + SIGNER_CERTIFICATE "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/certs/ca_cert.pem" + PRIVATE_KEY_FILE "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/certs/ca_key.pem" +) + +# Create a Permissions Document that is about to expire +add_custom_target(createExpiringPermissions + ALL + DEPENDS + dynamic_permissions_securityArtifacts + "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/signed/signed_Permissions2_expiring.p7s") \ No newline at end of file diff --git a/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml b/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml index 23c2b7a8b..89d7fa65e 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml +++ b/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml @@ -58,7 +58,7 @@ dds.sec.access.permissions - file:security/ecdsa01/xml/signed/signed_Permissions2.p7s + file:security/ecdsa01/xml/signed/signed_Permissions2_expiring.p7s diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx index 9f723818e..c28031f59 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx @@ -22,7 +22,10 @@ void run_publisher_application(unsigned int domain_id, unsigned int sample_count) { // Start communicating in a domain, usually one participant per application - dds::domain::DomainParticipant participant(domain_id); + dds::domain::DomainParticipant participant( + domain_id, + dds::core::QosProvider::Default().participant_qos( + "dynamic_permissions_Library::dynamic_permissions_ProfileB")); // Create a Topic with a name and a datatype dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx index 00138148f..3e406f574 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx @@ -41,7 +41,10 @@ int process_data(dds::sub::DataReader< ::DynamicPermissions> reader) void run_subscriber_application(unsigned int domain_id, unsigned int sample_count) { // Start communicating in a domain, usually one participant per application - dds::domain::DomainParticipant participant(domain_id); + dds::domain::DomainParticipant participant( + domain_id, + dds::core::QosProvider::Default().participant_qos( + "dynamic_permissions_Library::dynamic_permissions_ProfileA")); // Create a Topic with a name and a datatype dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); diff --git a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake new file mode 100644 index 000000000..4a4c87a3c --- /dev/null +++ b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake @@ -0,0 +1,19 @@ +file(READ ${INPUT_FILE} CONTENTS) + +# Find the positions of the start and end tags +string(FIND "${CONTENTS}" "" START_INDEX) +string(FIND "${CONTENTS}" "" END_INDEX) + +if(START_INDEX EQUAL -1 OR END_INDEX EQUAL -1) + message(FATAL_ERROR "Tags not found in the input file") +endif() + +# Compute the new contents +string(LENGTH NOT_AFTER_LENGTH) +math(EXPR START_INDEX "${START_INDEX} + ${NOT_AFTER_LENGTH}") +string(SUBSTRING "${CONTENTS}" 0 ${START_INDEX} BEFORE_START) +string(SUBSTRING "${CONTENTS}" ${END_INDEX} -1 AFTER_END) + +# Replace with the current date + 1 minute +string(TIMESTAMP CURRENT_DATE "%Y-%m-%d %H:%M:%S") +file(WRITE ${OUTPUT_FILE} "${BEFORE_START}${CURRENT_DATE}\n${AFTER_END}") \ No newline at end of file From 3bcaddf7939cb02bd00fef8f61674a300dd79bf5 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Thu, 29 May 2025 12:37:03 +0200 Subject: [PATCH 05/13] permissions expire and communication stops --- .../c++11/USER_QOS_PROFILES.xml | 4 +-- .../c++11/dynamic_permissions_publisher.cxx | 2 +- .../c++11/dynamic_permissions_subscriber.cxx | 2 +- .../c++11/modify_permissions.cmake | 28 +++++++++++++++++-- .../ConnextDdsGenerateSecurityArtifacts.cmake | 5 +--- resources/security/xml/Governance.xml | 3 +- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml b/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml index 89d7fa65e..2b31c22dd 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml +++ b/examples/connext_secure/dynamic_permissions/c++11/USER_QOS_PROFILES.xml @@ -12,7 +12,7 @@ - + @@ -44,7 +44,7 @@ - + diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx index c28031f59..2410c6647 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx @@ -25,7 +25,7 @@ void run_publisher_application(unsigned int domain_id, unsigned int sample_count dds::domain::DomainParticipant participant( domain_id, dds::core::QosProvider::Default().participant_qos( - "dynamic_permissions_Library::dynamic_permissions_ProfileB")); + "dynamic_permissions_Library::publisher")); // Create a Topic with a name and a datatype dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx index 3e406f574..df01d0158 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx @@ -44,7 +44,7 @@ void run_subscriber_application(unsigned int domain_id, unsigned int sample_coun dds::domain::DomainParticipant participant( domain_id, dds::core::QosProvider::Default().participant_qos( - "dynamic_permissions_Library::dynamic_permissions_ProfileA")); + "dynamic_permissions_Library::subscriber")); // Create a Topic with a name and a datatype dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); diff --git a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake index 4a4c87a3c..81f7e7b5a 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake +++ b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake @@ -15,5 +15,29 @@ string(SUBSTRING "${CONTENTS}" 0 ${START_INDEX} BEFORE_START) string(SUBSTRING "${CONTENTS}" ${END_INDEX} -1 AFTER_END) # Replace with the current date + 1 minute -string(TIMESTAMP CURRENT_DATE "%Y-%m-%d %H:%M:%S") -file(WRITE ${OUTPUT_FILE} "${BEFORE_START}${CURRENT_DATE}\n${AFTER_END}") \ No newline at end of file +string(TIMESTAMP current_epoch "%s" UTC) +MATH(EXPR expiring_epoch "(${current_epoch} + 60)") + +# SOURCE_DATE_EPOCH allows the date and time to be set externally by an exported +# environment variable. If the SOURCE_DATE_EPOCH environment variable is set, +# the string(TIMESTAMP [...]) cmake command will return its value instead of the +# current time. +# Backup. +if (DEFINED ENV{SOURCE_DATE_EPOCH}) + set(_old_source_date_epoch ENV{SOURCE_DATE_EPOCH}) +endif() +# +# Set new value. +set(ENV{SOURCE_DATE_EPOCH} ${expiring_epoch}) +# +# Get the timestamp that we want. +string(TIMESTAMP expiring_date "%Y-%m-%dT%H:%M:%S" UTC) +# +# Revert old value. +if (DEFINED ${_old_source_date_epoch}) + set(ENV{SOURCE_DATE_EPOCH} ${_old_source_date_epoch}) +else() + unset(ENV{SOURCE_DATE_EPOCH}) +endif() + +file(WRITE ${OUTPUT_FILE} "${BEFORE_START}${expiring_date}${AFTER_END}") \ No newline at end of file diff --git a/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake b/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake index cc1a5ac2e..168178f27 100644 --- a/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake +++ b/resources/cmake/Modules/ConnextDdsGenerateSecurityArtifacts.cmake @@ -90,7 +90,7 @@ function(connextdds_generate_security_artifacts) ) set(xmls_name Governance Permissions1 Permissions2) foreach(xml ${xmls_name}) - list(APPEND artifacts_input_files "${xml}.xml") + list(APPEND artifacts_input_files "${openssl_working_dir}/xml/${xml}.xml") endforeach() add_custom_command( @@ -143,7 +143,6 @@ function(connextdds_generate_security_artifacts) OUTPUT_KEY_FILE "${ca_key_file}" OUTPUT_CERT_FILE "${ca_cert_file}" CRL_NUMBER_FILE "${openssl_temporary_dir}/crlNumber" - TEXT DIGEST SHA256 DAYS ${expiration_days} ECPARAM_NAME prime256v1 @@ -158,7 +157,6 @@ function(connextdds_generate_security_artifacts) OUTPUT_CERT_FILE "${peer1_cert_file}" OUTPUT_CERT_REQUEST_FILE "${openssl_temporary_dir}/peer1_req_cert.pem" OUTPUT_KEY_FILE "${peer1_key_file}" - TEXT ECPARAM_NAME "prime256v1" ECPARAM_OUTPUT_FILE "${openssl_temporary_dir}/ecdsaparam1" CONFIG_FILE "${peer1_config_file}" @@ -174,7 +172,6 @@ function(connextdds_generate_security_artifacts) OUTPUT_CERT_FILE "${peer2_cert_file}" OUTPUT_CERT_REQUEST_FILE "${openssl_temporary_dir}/peer2_req_cert.pem" OUTPUT_KEY_FILE "${peer2_key_file}" - TEXT ECPARAM_NAME "prime256v1" ECPARAM_OUTPUT_FILE "${openssl_temporary_dir}/ecdsaparam1" CONFIG_FILE "${peer2_config_file}" diff --git a/resources/security/xml/Governance.xml b/resources/security/xml/Governance.xml index 21e8ebf12..51a95ff37 100644 --- a/resources/security/xml/Governance.xml +++ b/resources/security/xml/Governance.xml @@ -1,6 +1,6 @@ + xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/7.5.0/dds_security_governance.xsd"> @@ -10,6 +10,7 @@ false true + true NONE NONE ENCRYPT From 8d82108469a9fea45af972c0bec2cb6e50e0ec86 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Thu, 29 May 2025 13:23:10 +0200 Subject: [PATCH 06/13] copilot suggestions, changed idl type, improved readme --- .../dynamic_permissions/README.md | 78 ++++++++++++++++++- .../c++11/dynamic_permissions.idl | 2 +- .../c++11/dynamic_permissions_publisher.cxx | 1 + .../c++11/modify_permissions.cmake | 4 +- 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/README.md b/examples/connext_secure/dynamic_permissions/README.md index 8f014cf5b..e676aa266 100644 --- a/examples/connext_secure/dynamic_permissions/README.md +++ b/examples/connext_secure/dynamic_permissions/README.md @@ -6,10 +6,82 @@ Missing description. ## Building the Example +Use the following commands to build the example and get the executables that +you can run: + ```sh cd c++11/ -mkdir build -cd build +mkdir build && cd build cmake .. cmake --build . -``` \ No newline at end of file +``` + +You can optionally pass the +``-DCONNEXTDDS_DIR=``, +``-DOPENSSL_ROOT_DIR=``, +``-DCONNEXTDDS_ARCH=``, +``-DCMAKE_BUILD_TYPE=``, and +``-DBUILD_SHARED_LIBS=`` variables to the cmake configuration step. + +After building the example, you will have a publisher Permissions Document that +expires in 1 minute. If you need to re-create it, please remove this file from +your build directory and re-run the ``createExpiringPermissions`` target. + +```sh +rm security/ecdsa01/xml/Permissions2_expiring.xml && \ + cmake --build . --target createExpiringPermissions +``` + +## Running the example + +Demo is based on a standard rtiddsgen publisher and subscriber example code. + +Run a publisher and a subscriber in separate terminal windows. + +```sh +./dynamic_permissions_publisher +``` + +``` +sh./dynamic_permissions_subscriber +``` + +Verify that they communicate and that the subscriber is receiving data. + +```sh +# Publisher +Writing ::DynamicPermissions, count 0 +Writing ::DynamicPermissions, count 1 +# [...] + +# Subscriber +::DynamicPermissions subscriber sleeping up to 1 sec... +[value: 0] +::DynamicPermissions subscriber sleeping up to 1 sec... +[value: 1] +::DynamicPermissions subscriber sleeping up to 1 sec... +# [...] +``` + +Once the Permissions Document of the publisher DomainParticipant expires, you +will see the following error messages: + +```sh +# Publisher +ERROR [0x831AB06E,0x43876C36,0xFD825600:0x000001C1|ADVANCE NOTIFY INVALID LOCAL PERMISSIONS|CHECK STATUS|LC:Security] RTI_Security_PermissionsGrant_isValidTime:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1748517658","n":"108000"},"h":"RTISP-10036","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"85264","k":"50331706","x":[{"DDS":[{"domain_id":"0"},{"guid":"831AB06E.43876C36.FD825600.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_PermissionsGrant_isValidTime"}]}],"m":"now is after not_after of permissions file"}} +ERROR [0x831AB06E,0x43876C36,0xFD825600:0x000001C1|ADVANCE NOTIFY INVALID LOCAL PERMISSIONS|CHECK STATUS|LC:Security] RTI_Security_AccessControl_validate_status:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1748517658","n":"192000"},"h":"RTISP-10036","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"85264","k":"50331706","x":[{"DDS":[{"domain_id":"0"},{"guid":"831AB06E.43876C36.FD825600.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_validate_status"}]}],"m":"permissions' validity period is invalid."}} +ERROR [0x831AB06E,0x43876C36,0xFD825600:0x000001C1|ADVANCE NOTIFY INVALID LOCAL PERMISSIONS|CHECK STATUS|LC:Security] PRESParticipant_onSecurityLocalCredentialValidateEvent:FAILED TO VALIDATE | Local permissions credentials. +ERROR [0x831AB06E,0x43876C36,0xFD825600:0x000001C1|ADVANCE NOTIFY INVALID LOCAL PERMISSIONS|LC:Security] PRESParticipant_onSecurityLocalCredentialEventListener:FAILED TO VALIDATE | Local credentials. + +# Subscriber +ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,MessageKind=DATA}|RECEIVE FROM 0x831AB06E,0x43876C36,0xFD825600:0x000201C3|:0x000001C1{Domain=0}|RECEIVE SAMPLE|PROCESS HANDSHAKE|GET SECURITY STATE|LC:Security] RTI_Security_PermissionsGrant_isValidTime:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1748517682","n":"984966998"},"h":"RTISP-10036","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"85248","k":"50331706","x":[{"DDS":[{"domain_id":"0"},{"guid":"DED844B7.87B9550F.B66DD964.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_PermissionsGrant_isValidTime"}]}],"m":"now is after not_after of permissions file"}} +ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,MessageKind=DATA}|RECEIVE FROM 0x831AB06E,0x43876C36,0xFD825600:0x000201C3|:0x000001C1{Domain=0}|RECEIVE SAMPLE|PROCESS HANDSHAKE|GET SECURITY STATE|LC:Security] RTI_Security_AccessControl_validatePermissionsDocument:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1748517682","n":"985028998"},"h":"RTISP-10036","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"85248","k":"50331706","x":[{"DDS":[{"domain_id":"0"},{"guid":"DED844B7.87B9550F.B66DD964.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_validatePermissionsDocument"}]}],"m":"grant has invalid time"}} +ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,MessageKind=DATA}|RECEIVE FROM 0x831AB06E,0x43876C36,0xFD825600:0x000201C3|:0x000001C1{Domain=0}|RECEIVE SAMPLE|PROCESS HANDSHAKE|GET SECURITY STATE|LC:Security] RTI_Security_AccessControl_validate_remote_permissions:{"DDS:Security:LogTopicV2":{"f":"10","s":"1","t":{"s":"1748517682","n":"985044998"},"h":"RTISP-10036","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"85248","k":"50331706","x":[{"DDS":[{"domain_id":"0"},{"guid":"DED844B7.87B9550F.B66DD964.000001C1"},{"plugin_class":"DDS:Access:Permissions"},{"plugin_method":"RTI_Security_AccessControl_validate_remote_permissions"}]}],"m":"failed to validate remote permissions"}} +ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,MessageKind=DATA}|RECEIVE FROM 0x831AB06E,0x43876C36,0xFD825600:0x000201C3|:0x000001C1{Domain=0}|RECEIVE SAMPLE|PROCESS HANDSHAKE|GET SECURITY STATE|LC:Security] DDS_DomainParticipantTrustPlugins_forwardGetAuthenticatedRemoteParticipantSecurityState:FAILED TO VALIDATE | Remote permissions. +ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,MessageKind=DATA}|RECEIVE FROM 0x831AB06E,0x43876C36,0xFD825600:0x000201C3|:0x000001C1{Domain=0}|RECEIVE SAMPLE|PROCESS HANDSHAKE|LC:Security] PRESParticipant_authorizeRemoteParticipant:{"DDS:Security:LogTopicV2":{"f":"10","s":"3","t":{"s":"1748517682","n":"985078998"},"h":"RTISP-10036","i":"0.0.0.0","a":"RTI Secure DDS Application","p":"85248","k":"50331706","x":[{"DDS":[{"domain_id":"0"},{"guid":"DED844B7.87B9550F.B66DD964.000001C1"},{"plugin_class":"RTI:Auth"},{"plugin_method":"PRESParticipant_authorizeRemoteParticipant"}]}],"m":"unauthorized remote participant 831ab06e.43876c36.fd825600 denied by local participant ded844b7.87b9550f.b66dd964"}} +ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,MessageKind=DATA}|RECEIVE FROM 0x831AB06E,0x43876C36,0xFD825600:0x000201C3|:0x000001C1{Domain=0}|RECEIVE SAMPLE|PROCESS HANDSHAKE|LC:Security] PRESParticipant_processHandshake:FAILED TO VALIDATE | Failed to authorize remote DP (GUID: 0x831AB06E,0x43876C36,0xFD825600:0x000001C1). +``` + +Communication will stop. + +# Renewing the Permissions Document \ No newline at end of file diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl index 67b9242f1..1b39e1cd6 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions.idl @@ -10,5 +10,5 @@ * use or inability to use the software. */ struct DynamicPermissions { - string<128> msg; + int32 value; }; diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx index 2410c6647..e5fbfa6dc 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx @@ -42,6 +42,7 @@ void run_publisher_application(unsigned int domain_id, unsigned int sample_count !application::shutdown_requested && samples_written < sample_count; samples_written++) { // Modify the data to be written here + data.value(static_cast(samples_written)); std::cout << "Writing ::DynamicPermissions, count " << samples_written << std::endl; writer.write(data); diff --git a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake index 81f7e7b5a..6619ea6ff 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake +++ b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake @@ -9,7 +9,7 @@ if(START_INDEX EQUAL -1 OR END_INDEX EQUAL -1) endif() # Compute the new contents -string(LENGTH NOT_AFTER_LENGTH) +string(LENGTH "" NOT_AFTER_LENGTH) math(EXPR START_INDEX "${START_INDEX} + ${NOT_AFTER_LENGTH}") string(SUBSTRING "${CONTENTS}" 0 ${START_INDEX} BEFORE_START) string(SUBSTRING "${CONTENTS}" ${END_INDEX} -1 AFTER_END) @@ -34,7 +34,7 @@ set(ENV{SOURCE_DATE_EPOCH} ${expiring_epoch}) string(TIMESTAMP expiring_date "%Y-%m-%dT%H:%M:%S" UTC) # # Revert old value. -if (DEFINED ${_old_source_date_epoch}) +if (DEFINED _old_source_date_epoch) set(ENV{SOURCE_DATE_EPOCH} ${_old_source_date_epoch}) else() unset(ENV{SOURCE_DATE_EPOCH}) From 2826694ebf4a58c7596058cf0203df47d6d93121 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Tue, 10 Jun 2025 12:25:52 +0200 Subject: [PATCH 07/13] permissions document renewal --- .../connext_secure/dynamic_permissions/README.md | 10 ++++++++-- .../c++11/dynamic_permissions_publisher.cxx | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/README.md b/examples/connext_secure/dynamic_permissions/README.md index e676aa266..934f5dc93 100644 --- a/examples/connext_secure/dynamic_permissions/README.md +++ b/examples/connext_secure/dynamic_permissions/README.md @@ -2,7 +2,9 @@ ## Concept -Missing description. +This example showcases how the Security Plugins enforce Permissions Document +expiration, and how the Permissions Document can be renewed to resume +communication. ## Building the Example @@ -84,4 +86,8 @@ ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,Messa Communication will stop. -# Renewing the Permissions Document \ No newline at end of file +# Renewing the Permissions Document + +This example updates the publisher DomainParticipant's Permissions Document +after 70 samples. At that point, communication with the subscriber will +resume. \ No newline at end of file diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx index e5fbfa6dc..411dfe522 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx @@ -49,6 +49,20 @@ void run_publisher_application(unsigned int domain_id, unsigned int sample_count // Send once every second rti::util::sleep(dds::core::Duration(1)); + + // The Permissions Document expires after 1 minute (~60 samples). + // Let's update it after 70 samples. At this point, the publisher and + // subscriber lost communication. This will be fixed by updating the + // Permissions Document. + if (samples_written == 70) { + std::cout << "Updating Permissions Document" << std::endl; + dds::domain::qos::DomainParticipantQos updated_qos = + participant.qos(); + updated_qos->property.set(rti::core::policy::Property::Entry( + "dds.sec.access.permissions", + "security/ecdsa01/xml/signed/signed_Permissions2.p7s")); + participant << updated_qos; + } } } From b326f5304b9a34be77cd29beef789550021e029c Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Tue, 10 Jun 2025 12:52:34 +0200 Subject: [PATCH 08/13] copilot suggestion --- .../dynamic_permissions/c++11/modify_permissions.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake index 6619ea6ff..0f6dce171 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake +++ b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake @@ -12,7 +12,10 @@ endif() string(LENGTH "" NOT_AFTER_LENGTH) math(EXPR START_INDEX "${START_INDEX} + ${NOT_AFTER_LENGTH}") string(SUBSTRING "${CONTENTS}" 0 ${START_INDEX} BEFORE_START) -string(SUBSTRING "${CONTENTS}" ${END_INDEX} -1 AFTER_END) + +string(LENGTH "${CONTENTS}" TOTAL_LENGTH) +math(EXPR TRAILING_LENGTH "${TOTAL_LENGTH} - ${END_INDEX}") +string(SUBSTRING "${CONTENTS}" ${END_INDEX} ${TRAILING_LENGTH} AFTER_END) # Replace with the current date + 1 minute string(TIMESTAMP current_epoch "%s" UTC) From da6a30f35efbcfbf222cac3e88b431ed0e394d74 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Tue, 17 Jun 2025 11:14:13 +0200 Subject: [PATCH 09/13] fix wrong copyright dates --- examples/connext_secure/dynamic_permissions/c++11/application.h | 2 +- .../connext_secure/dynamic_permissions/c++11/application.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/c++11/application.h b/examples/connext_secure/dynamic_permissions/c++11/application.h index 22cb1de83..8714b1228 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/application.h +++ b/examples/connext_secure/dynamic_permissions/c++11/application.h @@ -1,5 +1,5 @@ /* -* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* (c) Copyright, Real-Time Innovations, 2025. All rights reserved. * RTI grants Licensee a license to use, modify, compile, and create derivative * works of the software solely for use with RTI Connext DDS. Licensee may * redistribute copies of the software provided that all such copies are subject diff --git a/examples/connext_secure/dynamic_permissions/c++11/application.hpp b/examples/connext_secure/dynamic_permissions/c++11/application.hpp index 17683705b..3c8820e8b 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/application.hpp +++ b/examples/connext_secure/dynamic_permissions/c++11/application.hpp @@ -1,5 +1,5 @@ /* -* (c) Copyright, Real-Time Innovations, 2020. All rights reserved. +* (c) Copyright, Real-Time Innovations, 2025. All rights reserved. * RTI grants Licensee a license to use, modify, compile, and create derivative * works of the software solely for use with RTI Connext DDS. Licensee may * redistribute copies of the software provided that all such copies are subject From 0a945c1f12a08396658acb8c3e9d14edb598c684 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Wed, 25 Jun 2025 19:47:35 +0200 Subject: [PATCH 10/13] update schema version of the Governance The file doesn't exist yet, but it should exist once the release is out. Co-authored-by: krd-rti <162187247+krd-rti@users.noreply.github.com> --- resources/security/xml/Governance.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/security/xml/Governance.xml b/resources/security/xml/Governance.xml index 51a95ff37..c24796be4 100644 --- a/resources/security/xml/Governance.xml +++ b/resources/security/xml/Governance.xml @@ -1,6 +1,6 @@ + xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/7.6.0/dds_security_governance.xsd"> From 3e26ff9a637b39f12d9bf86aec9257692f8fee9f Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Tue, 1 Jul 2025 18:52:59 +0200 Subject: [PATCH 11/13] added new line at the end of files --- examples/connext_secure/dynamic_permissions/README.md | 2 +- .../connext_secure/dynamic_permissions/c++11/CMakeLists.txt | 2 +- .../dynamic_permissions/c++11/modify_permissions.cmake | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/README.md b/examples/connext_secure/dynamic_permissions/README.md index 934f5dc93..392b11268 100644 --- a/examples/connext_secure/dynamic_permissions/README.md +++ b/examples/connext_secure/dynamic_permissions/README.md @@ -90,4 +90,4 @@ Communication will stop. This example updates the publisher DomainParticipant's Permissions Document after 70 samples. At that point, communication with the subscriber will -resume. \ No newline at end of file +resume. diff --git a/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt b/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt index d70e14f43..c4fac74da 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt +++ b/examples/connext_secure/dynamic_permissions/c++11/CMakeLists.txt @@ -64,4 +64,4 @@ add_custom_target(createExpiringPermissions ALL DEPENDS dynamic_permissions_securityArtifacts - "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/signed/signed_Permissions2_expiring.p7s") \ No newline at end of file + "${CMAKE_CURRENT_BINARY_DIR}/security/ecdsa01/xml/signed/signed_Permissions2_expiring.p7s") diff --git a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake index 0f6dce171..ddd239f75 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake +++ b/examples/connext_secure/dynamic_permissions/c++11/modify_permissions.cmake @@ -43,4 +43,4 @@ else() unset(ENV{SOURCE_DATE_EPOCH}) endif() -file(WRITE ${OUTPUT_FILE} "${BEFORE_START}${expiring_date}${AFTER_END}") \ No newline at end of file +file(WRITE ${OUTPUT_FILE} "${BEFORE_START}${expiring_date}${AFTER_END}") From 24591af1797390c53e117a2fd38fde707656b365 Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Tue, 1 Jul 2025 19:00:30 +0200 Subject: [PATCH 12/13] readme errors from linter --- examples/connext_secure/dynamic_permissions/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/README.md b/examples/connext_secure/dynamic_permissions/README.md index 392b11268..4d9cc53d6 100644 --- a/examples/connext_secure/dynamic_permissions/README.md +++ b/examples/connext_secure/dynamic_permissions/README.md @@ -44,8 +44,8 @@ Run a publisher and a subscriber in separate terminal windows. ./dynamic_permissions_publisher ``` -``` -sh./dynamic_permissions_subscriber +```sh +./dynamic_permissions_subscriber ``` Verify that they communicate and that the subscriber is receiving data. @@ -86,7 +86,7 @@ ERROR [PARSE MESSAGE|0xDED844B7,0x87B9550F,0xB66DD964:0x000201C4{Entity=DR,Messa Communication will stop. -# Renewing the Permissions Document +## Renewing the Permissions Document This example updates the publisher DomainParticipant's Permissions Document after 70 samples. At that point, communication with the subscriber will From 0ec5d5445bd10a88d551c376cd3bb21f5522cc5b Mon Sep 17 00:00:00 2001 From: Luis Colmenero Date: Tue, 1 Jul 2025 19:26:27 +0200 Subject: [PATCH 13/13] c++ formatter changes according to linter --- .../dynamic_permissions/c++11/application.h | 204 +++++++++--------- .../c++11/dynamic_permissions_publisher.cxx | 44 ++-- .../c++11/dynamic_permissions_subscriber.cxx | 58 ++--- 3 files changed, 160 insertions(+), 146 deletions(-) diff --git a/examples/connext_secure/dynamic_permissions/c++11/application.h b/examples/connext_secure/dynamic_permissions/c++11/application.h index 8714b1228..b4353c51e 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/application.h +++ b/examples/connext_secure/dynamic_permissions/c++11/application.h @@ -1,14 +1,14 @@ /* -* (c) Copyright, Real-Time Innovations, 2025. All rights reserved. -* RTI grants Licensee a license to use, modify, compile, and create derivative -* works of the software solely for use with RTI Connext DDS. Licensee may -* redistribute copies of the software provided that all such copies are subject -* to this license. The software is provided "as is", with no warranty of any -* type, including any warranty for fitness for any purpose. RTI is under no -* obligation to maintain or support the software. RTI shall not be liable for -* any incidental or consequential damages arising out of the use or inability -* to use the software. -*/ + * (c) Copyright, Real-Time Innovations, 2025. All rights reserved. + * RTI grants Licensee a license to use, modify, compile, and create derivative + * works of the software solely for use with RTI Connext DDS. Licensee may + * redistribute copies of the software provided that all such copies are subject + * to this license. The software is provided "as is", with no warranty of any + * type, including any warranty for fitness for any purpose. RTI is under no + * obligation to maintain or support the software. RTI shall not be liable for + * any incidental or consequential damages arising out of the use or inability + * to use the software. + */ #ifndef APPLICATION_H #define APPLICATION_H @@ -19,109 +19,113 @@ namespace application { - // Catch control-C and tell application to shut down - bool shutdown_requested = false; +// Catch control-C and tell application to shut down +bool shutdown_requested = false; - inline void stop_handler(int) - { - shutdown_requested = true; - std::cout << "preparing to shut down..." << std::endl; - } +inline void stop_handler(int) +{ + shutdown_requested = true; + std::cout << "preparing to shut down..." << std::endl; +} - inline void setup_signal_handlers() - { - signal(SIGINT, stop_handler); - signal(SIGTERM, stop_handler); - } +inline void setup_signal_handlers() +{ + signal(SIGINT, stop_handler); + signal(SIGTERM, stop_handler); +} - enum ParseReturn { PARSE_RETURN_OK, PARSE_RETURN_FAILURE, PARSE_RETURN_EXIT }; +enum ParseReturn { PARSE_RETURN_OK, PARSE_RETURN_FAILURE, PARSE_RETURN_EXIT }; - struct ApplicationArguments { - ParseReturn parse_result; - unsigned int domain_id; - unsigned int sample_count; - NDDS_Config_LogVerbosity verbosity; - }; +struct ApplicationArguments { + ParseReturn parse_result; + unsigned int domain_id; + unsigned int sample_count; + NDDS_Config_LogVerbosity verbosity; +}; - inline void set_verbosity( - ApplicationArguments& arguments, - int verbosity) - { - switch (verbosity) { - case 0: - arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_SILENT; - break; - case 1: - arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; - break; - case 2: - arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_WARNING; - break; - case 3: - arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL; - break; - default: - arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; - break; - } +inline void set_verbosity(ApplicationArguments &arguments, int verbosity) +{ + switch (verbosity) { + case 0: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_SILENT; + break; + case 1: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; + break; + case 2: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_WARNING; + break; + case 3: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL; + break; + default: + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; + break; } +} - // Parses application arguments for example. Returns whether to exit. - inline void parse_arguments( - ApplicationArguments& arguments, +// Parses application arguments for example. Returns whether to exit. +inline void parse_arguments( + ApplicationArguments &arguments, int argc, char *argv[]) - { - int arg_processing = 1; - bool show_usage = false; - arguments.domain_id = 0; - arguments.sample_count = INT_MAX; - arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; - arguments.parse_result = PARSE_RETURN_OK; +{ + int arg_processing = 1; + bool show_usage = false; + arguments.domain_id = 0; + arguments.sample_count = INT_MAX; + arguments.verbosity = NDDS_CONFIG_LOG_VERBOSITY_ERROR; + arguments.parse_result = PARSE_RETURN_OK; - while (arg_processing < argc) { - if ((argc > arg_processing + 1) + while (arg_processing < argc) { + if ((argc > arg_processing + 1) && (strcmp(argv[arg_processing], "-d") == 0 - || strcmp(argv[arg_processing], "--domain") == 0)) { - arguments.domain_id = atoi(argv[arg_processing + 1]); - arg_processing += 2; - } else if ((argc > arg_processing + 1) - && (strcmp(argv[arg_processing], "-s") == 0 - || strcmp(argv[arg_processing], "--sample-count") == 0)) { - arguments.sample_count = atoi(argv[arg_processing + 1]); - arg_processing += 2; - } else if ((argc > arg_processing + 1) - && (strcmp(argv[arg_processing], "-v") == 0 - || strcmp(argv[arg_processing], "--verbosity") == 0)) { - set_verbosity(arguments, atoi(argv[arg_processing + 1])); - arg_processing += 2; - } else if (strcmp(argv[arg_processing], "-h") == 0 - || strcmp(argv[arg_processing], "--help") == 0) { - std::cout << "Example application." << std::endl; - show_usage = true; - arguments.parse_result = PARSE_RETURN_EXIT; - break; - } else { - std::cout << "Bad parameter." << std::endl; - show_usage = true; - arguments.parse_result = PARSE_RETURN_FAILURE; - break; - } - } - if (show_usage) { - std::cout << "Usage:\n"\ - " -d, --domain Domain ID this application will\n" \ - " subscribe in. \n" - " Default: 0\n"\ - " -s, --sample_count Number of samples to receive before\n"\ - " cleanly shutting down. \n" - " Default: infinite\n" - " -v, --verbosity How much debugging output to show.\n"\ - " Range: 0-3 \n" - " Default: 1" - << std::endl; + || strcmp(argv[arg_processing], "--domain") == 0)) { + arguments.domain_id = atoi(argv[arg_processing + 1]); + arg_processing += 2; + } else if ( + (argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-s") == 0 + || strcmp(argv[arg_processing], "--sample-count") == 0)) { + arguments.sample_count = atoi(argv[arg_processing + 1]); + arg_processing += 2; + } else if ( + (argc > arg_processing + 1) + && (strcmp(argv[arg_processing], "-v") == 0 + || strcmp(argv[arg_processing], "--verbosity") == 0)) { + set_verbosity(arguments, atoi(argv[arg_processing + 1])); + arg_processing += 2; + } else if ( + strcmp(argv[arg_processing], "-h") == 0 + || strcmp(argv[arg_processing], "--help") == 0) { + std::cout << "Example application." << std::endl; + show_usage = true; + arguments.parse_result = PARSE_RETURN_EXIT; + break; + } else { + std::cout << "Bad parameter." << std::endl; + show_usage = true; + arguments.parse_result = PARSE_RETURN_FAILURE; + break; } } + if (show_usage) { + std::cout << "Usage:\n" + " -d, --domain Domain ID this " + "application will\n" + " subscribe in. \n" + " Default: 0\n" + " -s, --sample_count Number of samples to " + "receive before\n" + " cleanly shutting down. \n" + " Default: infinite\n" + " -v, --verbosity How much debugging output " + "to show.\n" + " Range: 0-3 \n" + " Default: 1" + << std::endl; + } +} } // namespace application diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx index 411dfe522..aaf8b441e 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_publisher.cxx @@ -1,14 +1,14 @@ /* -* (c) Copyright, Real-Time Innovations, 2025. All rights reserved. -* RTI grants Licensee a license to use, modify, compile, and create derivative -* works of the software solely for use with RTI Connext DDS. Licensee may -* redistribute copies of the software provided that all such copies are subject -* to this license. The software is provided "as is", with no warranty of any -* type, including any warranty for fitness for any purpose. RTI is under no -* obligation to maintain or support the software. RTI shall not be liable for -* any incidental or consequential damages arising out of the use or inability -* to use the software. -*/ + * (c) Copyright, Real-Time Innovations, 2025. All rights reserved. + * RTI grants Licensee a license to use, modify, compile, and create derivative + * works of the software solely for use with RTI Connext DDS. Licensee may + * redistribute copies of the software provided that all such copies are subject + * to this license. The software is provided "as is", with no warranty of any + * type, including any warranty for fitness for any purpose. RTI is under no + * obligation to maintain or support the software. RTI shall not be liable for + * any incidental or consequential damages arising out of the use or inability + * to use the software. + */ #include @@ -19,31 +19,36 @@ #include "application.hpp" // for command line parsing and ctrl-c #include "dynamic_permissions.hpp" -void run_publisher_application(unsigned int domain_id, unsigned int sample_count) +void run_publisher_application( + unsigned int domain_id, + unsigned int sample_count) { // Start communicating in a domain, usually one participant per application dds::domain::DomainParticipant participant( domain_id, dds::core::QosProvider::Default().participant_qos( - "dynamic_permissions_Library::publisher")); + "dynamic_permissions_Library::publisher")); // Create a Topic with a name and a datatype - dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); + dds::topic::Topic<::DynamicPermissions> topic( + participant, + "Example DynamicPermissions"); // Create a Publisher dds::pub::Publisher publisher(participant); // Create a DataWriter with default QoS - dds::pub::DataWriter< ::DynamicPermissions> writer(publisher, topic); + dds::pub::DataWriter<::DynamicPermissions> writer(publisher, topic); ::DynamicPermissions data; // Main loop, write data for (unsigned int samples_written = 0; - !application::shutdown_requested && samples_written < sample_count; - samples_written++) { + !application::shutdown_requested && samples_written < sample_count; + samples_written++) { // Modify the data to be written here data.value(static_cast(samples_written)); - std::cout << "Writing ::DynamicPermissions, count " << samples_written << std::endl; + std::cout << "Writing ::DynamicPermissions, count " << samples_written + << std::endl; writer.write(data); @@ -68,7 +73,6 @@ void run_publisher_application(unsigned int domain_id, unsigned int sample_count int main(int argc, char *argv[]) { - using namespace application; // Parse arguments and handle control-C @@ -85,10 +89,10 @@ int main(int argc, char *argv[]) try { run_publisher_application(arguments.domain_id, arguments.sample_count); - } catch (const std::exception& ex) { + } catch (const std::exception &ex) { // This will catch DDS exceptions std::cerr << "Exception in run_publisher_application(): " << ex.what() - << std::endl; + << std::endl; return EXIT_FAILURE; } diff --git a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx index df01d0158..42edf4d60 100644 --- a/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx +++ b/examples/connext_secure/dynamic_permissions/c++11/dynamic_permissions_subscriber.cxx @@ -1,14 +1,14 @@ /* -* (c) Copyright, Real-Time Innovations, 2025. All rights reserved. -* RTI grants Licensee a license to use, modify, compile, and create derivative -* works of the software solely for use with RTI Connext DDS. Licensee may -* redistribute copies of the software provided that all such copies are subject -* to this license. The software is provided "as is", with no warranty of any -* type, including any warranty for fitness for any purpose. RTI is under no -* obligation to maintain or support the software. RTI shall not be liable for -* any incidental or consequential damages arising out of the use or inability -* to use the software. -*/ + * (c) Copyright, Real-Time Innovations, 2025. All rights reserved. + * RTI grants Licensee a license to use, modify, compile, and create derivative + * works of the software solely for use with RTI Connext DDS. Licensee may + * redistribute copies of the software provided that all such copies are subject + * to this license. The software is provided "as is", with no warranty of any + * type, including any warranty for fitness for any purpose. RTI is under no + * obligation to maintain or support the software. RTI shall not be liable for + * any incidental or consequential damages arising out of the use or inability + * to use the software. + */ #include #include @@ -20,53 +20,60 @@ #include "dynamic_permissions.hpp" #include "application.hpp" // for command line parsing and ctrl-c -int process_data(dds::sub::DataReader< ::DynamicPermissions> reader) +int process_data(dds::sub::DataReader<::DynamicPermissions> reader) { // Take all samples int count = 0; - dds::sub::LoanedSamples< ::DynamicPermissions> samples = reader.take(); + dds::sub::LoanedSamples<::DynamicPermissions> samples = reader.take(); for (auto sample : samples) { if (sample.info().valid()) { count++; std::cout << sample.data() << std::endl; } else { std::cout << "Instance state changed to " - << sample.info().state().instance_state() << std::endl; + << sample.info().state().instance_state() << std::endl; } } - return count; -} // The LoanedSamples destructor returns the loan + return count; +} // The LoanedSamples destructor returns the loan -void run_subscriber_application(unsigned int domain_id, unsigned int sample_count) +void run_subscriber_application( + unsigned int domain_id, + unsigned int sample_count) { // Start communicating in a domain, usually one participant per application dds::domain::DomainParticipant participant( domain_id, dds::core::QosProvider::Default().participant_qos( - "dynamic_permissions_Library::subscriber")); + "dynamic_permissions_Library::subscriber")); // Create a Topic with a name and a datatype - dds::topic::Topic< ::DynamicPermissions> topic(participant, "Example DynamicPermissions"); + dds::topic::Topic<::DynamicPermissions> topic( + participant, + "Example DynamicPermissions"); // Create a Subscriber and DataReader with default Qos dds::sub::Subscriber subscriber(participant); - dds::sub::DataReader< ::DynamicPermissions> reader(subscriber, topic); + dds::sub::DataReader<::DynamicPermissions> reader(subscriber, topic); // Create a ReadCondition for any data received on this reader and set a // handler to process the data unsigned int samples_read = 0; dds::sub::cond::ReadCondition read_condition( - reader, - dds::sub::status::DataState::any(), - [reader, &samples_read]() { samples_read += process_data(reader); }); + reader, + dds::sub::status::DataState::any(), + [reader, &samples_read]() { + samples_read += process_data(reader); + }); // WaitSet will be woken when the attached condition is triggered dds::core::cond::WaitSet waitset; waitset += read_condition; while (!application::shutdown_requested && samples_read < sample_count) { - std::cout << "::DynamicPermissions subscriber sleeping up to 1 sec..." << std::endl; + std::cout << "::DynamicPermissions subscriber sleeping up to 1 sec..." + << std::endl; // Run the handlers of the active conditions. Wait for up to 1 second. waitset.dispatch(dds::core::Duration(1)); @@ -75,7 +82,6 @@ void run_subscriber_application(unsigned int domain_id, unsigned int sample_coun int main(int argc, char *argv[]) { - using namespace application; // Parse arguments and handle control-C @@ -92,10 +98,10 @@ int main(int argc, char *argv[]) try { run_subscriber_application(arguments.domain_id, arguments.sample_count); - } catch (const std::exception& ex) { + } catch (const std::exception &ex) { // This will catch DDS exceptions std::cerr << "Exception in run_subscriber_application(): " << ex.what() - << std::endl; + << std::endl; return EXIT_FAILURE; }