/** * (c) Copyright, Real-Time Innovations, 2020. All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef RTI_CDS_CLOUD_DISCOVERY_SERVICE_PROPERTY_HPP_ #define RTI_CDS_CLOUD_DISCOVERY_SERVICE_PROPERTY_HPP_ /** * IMPORTANT: macros.hpp must be the first RTI header included in every header * file so that symbols are exported correctly on Windows */ #include #include #include "clouddiscoveryservice/clouddiscoveryservice_infrastructure.h" #include "clouddiscoveryservice/clouddiscoveryservice_service.h" namespace rti { namespace cds { /** \ingroup RTI_CDS_ServiceLibModule * * @brief Specifies the list of domain IDs to allow or deny. Overrides XML * configuration if specified. */ class DomainListProperty { public: DomainListProperty() : allow_domain_ids_(""), deny_domain_ids_("") { } DomainListProperty(std::string allow_domain_ids, std::string deny_domain_ids) { allow_domain_ids_ = allow_domain_ids; deny_domain_ids_ = deny_domain_ids; } /** * @brief The list of domain IDs where @product processes the incoming * participant announcements. * * @default Empty string. Use value from XML configuration. */ void allow_domain_ids(std::string allow_domain_ids) { allow_domain_ids_ = allow_domain_ids; } /** * @brief Getter (see setter with the same name) */ std::string& allow_domain_ids() { return allow_domain_ids_; } /** * @brief The list of domain IDs to deny or ignore. Overrides * \ref allow_domain_ids. * * @default Empty string. Use value from XML configuration. */ void deny_domain_ids(std::string deny_domain_ids) { deny_domain_ids_ = deny_domain_ids; } /** * @brief Getter (see setter with the same name) */ std::string& deny_domain_ids() { return deny_domain_ids_; } private: std::string allow_domain_ids_; std::string deny_domain_ids_; }; /** \ingroup RTI_CDS_ServiceLibModule * * @brief Specifies the alias name of the transport to be used by @product for * sending or receiving announcements. It also indicates the port where incoming * participant announcements are received. Overrides XML configuration if specified. * * Refer to \ref_url_cloud_discovery_service_users_manual_available_transports to * check the list of aliases for the preconfigured transports. */ class TransportUnicastProperty { public: TransportUnicastProperty(std::string alias, int receive_port) { alias_ = alias; receive_port_ = receive_port; } /** * @brief Transport alias name */ void alias(std::string alias) { alias_ = alias; } /** * @brief Getter (see setter with the same name) */ std::string& alias() { return alias_; } /** * @brief Receive port */ void receive_port(int receive_port) { receive_port_ = receive_port; } /** * @brief Getter (see setter with the same name) */ int receive_port() { return receive_port_; } private: std::string alias_; int receive_port_; }; class PropertyAdapter { public: typedef RTI_CDS_Property native_type; static void initialize(native_type& native_value) { static const native_type DEFAULT = RTI_CDS_Property_INITIALIZER; native_value = DEFAULT; // Replicating the defaults from the C Library API as specified in service.ifc native_value.service_verbosity = RTI_LOG_BIT_EXCEPTION; native_value.dds_verbosity = RTI_LOG_BIT_EXCEPTION; } static void finalize(native_type& native_value) { if (native_value.cfg_strings != NULL) { RTIOsapiHeap_freeArray(native_value.cfg_strings); native_value.cfg_strings = NULL; } RTI_CDS_Property_finalize(&native_value); } static void copy(native_type& destination, const native_type& source) { if (RTI_CDS_Property_copy(&destination, &source) == NULL) { throw dds::core::Error("Native RTI_CDS_Property_copy"); } } static bool equals(const native_type& first, const native_type& second) { RTIOsapiUtility_unusedParameter(first); RTIOsapiUtility_unusedParameter(second); throw dds::core::UnsupportedError("Unsupported operation: equals"); } static void add_transports_from_native( std::vector& transport_selection, const struct RTI_CDS_TransportSelectionProperty *transport_selection_native) { for (int i = 0; i < transport_selection_native->count; i++) { transport_selection.push_back(TransportUnicastProperty( transport_selection_native->transports[i].alias, transport_selection_native->transports[i].receive_port)); } } static void add_transports_to_native( struct RTI_CDS_TransportSelectionProperty *transport_selection_native, std::vector& transport_selection) { transport_selection_native->count = transport_selection.size(); for (unsigned int i = 0; i < transport_selection.size(); i++) { RTIOsapiUtility_strcpy( transport_selection_native->transports[i].alias, RTI_CDS_TRANSPORT_UNICAST_PROPERTY_ALIAS_LENGTH_MAX, transport_selection[i].alias().c_str()); transport_selection_native->transports[i].receive_port = transport_selection[i].receive_port(); } } static void add_domain_list_from_native( DomainListProperty& domain_ids, const struct RTI_CDS_DomainListProperty *domain_ids_native) { domain_ids.allow_domain_ids(domain_ids_native->allow_domain_ids); domain_ids.deny_domain_ids(domain_ids_native->deny_domain_ids); } static void add_domain_list_to_native( struct RTI_CDS_DomainListProperty *domain_ids_native, DomainListProperty& domain_ids) { DDS_String_replace( &domain_ids_native->allow_domain_ids, domain_ids.allow_domain_ids().c_str()); DDS_String_replace( &domain_ids_native->deny_domain_ids, domain_ids.deny_domain_ids().c_str()); } static void add_properties_from_native( std::map& properties, const RTI_RoutingServiceProperties *native_properties) { for (int i = 0; i < native_properties->count; i++) { properties[native_properties->properties[i].name] = (const char *) native_properties->properties[i].value; } } static void add_properties_to_native( RTI_RoutingServiceProperties *native_properties, const std::map& properties) { RTI_RoutingServiceProperties_finalize(native_properties); if (!RTI_RoutingServiceProperties_initialize(native_properties)) { throw dds::core::Error("failed to initialize native property"); } std::map::const_iterator it = properties.begin(); for (; it != properties.end(); ++it) { if (!RTI_RoutingServiceProperties_add( native_properties, it->first.c_str(), it->second.c_str())) { throw dds::core::Error("failed to add native property"); } } } }; class ServiceProperty; } namespace core { template<> struct native_type_traits { typedef rti::cds::PropertyAdapter adapter_type; typedef RTI_CDS_Property native_type; }; } namespace cds { /** \ingroup RTI_CDS_ServiceLibModule * * @brief Configuration properties for a @product object. * */ class ServiceProperty : public rti::core::NativeValueType { public: RTI_NATIVE_VALUE_TYPE_DEFINE_DEFAULT_MOVE_OPERATIONS(ServiceProperty) typedef rti::core::NativeValueType Base; /** * @brief Creates a property object with default settings. */ ServiceProperty(): Base() { } ServiceProperty(const struct RTI_CDS_Property &native_property) : Base(native_property) { } /** * @brief Getter (see setter with the same name) */ std::string cfg_file() const { return native().cfg_file == NULL ? "" : native().cfg_file; } /** * @brief Path to an @product configuration file * * @default Empty string. */ ServiceProperty& cfg_file(const std::string& filename) { DDS_String_replace( &native().cfg_file, filename.c_str()); return *this; } /** * @brief Getter (see setter with the same name) */ const std::vector& cfg_strings() const { return cfg_strings_; } /** * @brief XML configuration represented as strings * * An array of strings that altogether make up an * XML document to configure @product. This parameter is used * only if ServiceProperty::cfg_file is empty. * * The reason for using an array instead of one single string is to * get around the limited size of literal strings. * In general, if you create the XML string dynamically * the vector needs only one element. * * @default Empty. */ ServiceProperty& cfg_strings( const std::vector& the_cfg_strings) { cfg_strings_ = the_cfg_strings; if (cfg_strings_.size() > 0) { if (!RTIOsapiHeap_reallocateArray( (char ***) &native().cfg_strings, cfg_strings_.size(), char *)) { throw dds::core::OutOfResourcesError("cfg_strings native array"); } for (uint32_t i = 0; i < cfg_strings_.size(); i++) { native().cfg_strings[i] = cfg_strings_[i].c_str(); } } native().cfg_strings_count = static_cast(cfg_strings_.size()); return *this; } /** * @brief Getter (see setter with the same name) */ std::string service_name() const { return native().service_name == NULL ? "" : native().service_name; } /** * @brief The name of the @product configuration to run. * * This is the name used to find the <cloud_discovery_service> * XML tag in the configuration file; this is the default name that will * be used to refer to this execution in remote administration and * monitoring if application_name isn't specified. * * @default Empty string. */ ServiceProperty& service_name(const std::string& name) { DDS_String_replace(&native().service_name, name.c_str()); return *this; } /** * @brief Getter (see setter with the same name) */ std::string application_name() const { return native().application_name == NULL ? "" : native().application_name; } /** * @brief Assigns a name to the execution of the RTI Cloud Discovery Service. * * Remote commands and status information will refer to the RTI Cloud Discovery * Service using this name. * * \default service_name if this value is not set. */ ServiceProperty& application_name(const std::string& name) { DDS_String_replace(&native().application_name, name.c_str()); return *this; } /** * @brief Getter (see setter with the same name) */ bool enforce_xsd_validation() const { return (native().enforce_xsd_validation == DDS_BOOLEAN_TRUE) ? true : false; } /** * @brief Controls whether the service applies XSD validation to the loaded * configuration. * * @default true */ ServiceProperty& enforce_xsd_validation(const bool enforce_xsd_validation) { native().enforce_xsd_validation = enforce_xsd_validation; return *this; } /** * @brief Getter (see setter with the same name) */ bool skip_default_files() const { return (native().skip_default_files == DDS_BOOLEAN_TRUE) ? true : false; } /** * @brief Set it to true to avoid loading the * standard files usually loaded by @product. * * Only the configuration in ServiceProperty::cfg_file or * ServiceProperty::cfg_strings will be loaded. * * @default false */ ServiceProperty& skip_default_files(const bool& skip) { native().skip_default_files = skip ? DDS_BOOLEAN_TRUE : DDS_BOOLEAN_FALSE; return *this; } /** * @brief Getter (see setter with the same name) */ std::vector transport_selection() { PropertyAdapter::add_transports_from_native( transport_selection_, &native().transport_selection); return transport_selection_; } /** * @brief Specifies the transport and receive ports used to receive and * send discovery traffic. Specifically, a receive resource is uniquely * specified by a transport class-receive port pair. * Overrides XML configuration if specified. * * @default Unspecified. Use value from XML configuration. */ ServiceProperty& transport_selection( const std::vector& transport_selection) { transport_selection_ = transport_selection; PropertyAdapter::add_transports_to_native( &native().transport_selection, transport_selection_); return *this; } /** * @brief Getter (see setter with the same name) */ DomainListProperty domain_list() { PropertyAdapter::add_domain_list_from_native( domain_list_, &native().domain_list); return domain_list_; } /** * @brief Specifies the set of domain IDs the service will accept * announcements from. * * @default Unspecified. Use value from XML configuration. */ ServiceProperty& domain_list( const DomainListProperty& domain_list) { domain_list_ = domain_list; PropertyAdapter::add_domain_list_to_native( &native().domain_list, domain_list_); return *this; } /** * @brief Getter (see setter with the same name) */ bool enable_administration() const { return (native().enable_administration == DDS_BOOLEAN_TRUE) ? true : false; } /** * @brief Set this to true to enable remote administration * or false to disable it. * * @default false */ ServiceProperty& enable_administration(const bool enable) { native().enable_administration = enable ? DDS_BOOLEAN_TRUE : DDS_BOOLEAN_FALSE; return *this; } /** * @brief Getter (see setter with the same name) */ int administration_domain_id() const { return native().administration_domain_id; } /** * @brief If ServiceProperty::enable_administration is true, this is * the domain ID to use for remote administration. * * Takes precedence over the XML configuration. * If ServiceProperty::enable_administration is false, this value is not * used even if remote administration is enabled in the XML configuration. * * @default 0 */ ServiceProperty& administration_domain_id(const int domain_id) { native().administration_domain_id = domain_id; return *this; } /** * @brief Getter (see setter with the same name) */ bool enable_monitoring() const { return (native().enable_monitoring == DDS_BOOLEAN_TRUE) ? true : false; } /** * @brief Set this to true to enable monitoring or false to disable it. * * @default false */ ServiceProperty& enable_monitoring(const bool enable) { native().enable_monitoring = enable ? DDS_BOOLEAN_TRUE : DDS_BOOLEAN_FALSE; return *this; } /** * @brief Getter (see setter with the same name) */ int monitoring_domain_id() const { return native().monitoring_domain_id; } /** * @brief If ServiceProperty::enable_monitoring is true, this is * the domain ID to use for publishing monitoring topics. * * Takes precedence over the XML configuration. * If ServiceProperty::enable_monitoring is false, this value is not * used even if monitoring is enabled in the XML configuration. * * @default 0 */ ServiceProperty& monitoring_domain_id(const int domain_id) { native().monitoring_domain_id = domain_id; return *this; } /** * @brief Getter (see setter with the same name) */ std::string license_file_name() const { return native().license_file_name == NULL ? "" : native().license_file_name; } /** * @brief Path to an @product license file. * * If not empty, this file is checked for a valid license; otherwise, * default location will be used. This parameter is only used if your * installation requires a license file. * * @default empty string. */ ServiceProperty& license_file_name(const std::string& file_name) { DDS_String_replace( &native().license_file_name, file_name.c_str()); return *this; } /** * @brief Getter (see setter with the same name) */ std::map user_environment() const { std::map properties; PropertyAdapter::add_properties_from_native( properties, &native().user_environment); return properties; } /** * @brief Dictionary of user variables. * * The dictionary provides a parallel way to expand XML configuration * variables in the form $(my_var), when they are not defined in the * environment. * * @default empty */ ServiceProperty& user_environment( const std::map& user_environment) { PropertyAdapter::add_properties_to_native( &native().user_environment, user_environment); return *this; } private: std::vector cfg_strings_; std::vector transport_selection_; DomainListProperty domain_list_; }; }} #endif // RTI_CDS_CLOUD_DISCOVERY_SERVICE_PROPERTY_HPP_