diff --git a/docs/manual/config/config_file_reference.rst b/docs/manual/config/config_file_reference.rst
index a9c4280258..388da0bd4a 100644
--- a/docs/manual/config/config_file_reference.rst
+++ b/docs/manual/config/config_file_reference.rst
@@ -609,7 +609,7 @@ The default value is: ``default``
//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Attributes: :ref:`config/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@config]>`, :ref:`library/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@library]>`, :ref:`name/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@name]>`, :ref:`priority/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@priority]>`
+Attributes: :ref:`config/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@config]>`, :ref:`forbiddenTopics/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@forbiddenTopics]>`, :ref:`library/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@library]>`, :ref:`name/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@name]>`, :ref:`onlyForTopics/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@onlyForTopics]>`, :ref:`priority/CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@priority]>`
This element defines a PSMX.
@@ -626,6 +626,18 @@ This attribute specifies any configuration data for the PSMX instance.This has n
The default value is: ````
+.. _`//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@forbiddenTopics]`:
+
+//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@forbiddenTopics]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Text
+
+A comma-separated list of topics that should never use this psmx.Mutually exclusive with onlyForTopics.
+
+The default value is: ````
+
+
.. _`//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@library]`:
//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@library]
@@ -650,6 +662,18 @@ This attribute specifies the name of the interface.
The default value is: ````
+.. _`//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@onlyForTopics]`:
+
+//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@onlyForTopics]
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Text
+
+A comma-separated list of all the topics that should use this PSMX.This option can be used to restrict the PSMX to a selected list of topics.Mutually exclusive with forbiddenTopics.
+
+The default value is: ````
+
+
.. _`//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@priority]`:
//CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@priority]
@@ -2642,14 +2666,14 @@ The categorisation of tracing output is incomplete and hence most of the verbosi
The default value is: ``none``
..
- generated from ddsi_config.h[570f67bd3080674a4bad53d9580a8bb7ad1e6e4d]
+ generated from ddsi_config.h[a6553d01e0d7a9c01fda217e68613a8ae1875883]
generated from ddsi__cfgunits.h[bd22f0c0ed210501d0ecd3b07c992eca549ef5aa]
- generated from ddsi__cfgelems.h[d4d0b8c7cf61f0a1cfa4b62e02458cf7b8962536]
- generated from ddsi_config.c[efeae198a5e12ca8977a655216470564b5c44b64]
- generated from _confgen.h[e32eabfc35e9f3a7dcb63b19ed148c0d17c6e5fc]
+ generated from ddsi__cfgelems.h[8c3942cd63352722dacc9df4db7cddae90a2cc13]
+ generated from ddsi_config.c[9a5b3e0862f49dc8bcd57b48b20efa1fc7702f42]
+ generated from _confgen.h[b3b98385ecc752860a55e126b3893423730f53ab]
generated from _confgen.c[237308acd53897a34e8c643e16e05a61d73ffd65]
generated from generate_rnc.c[b50e4b7ab1d04b2bc1d361a0811247c337b74934]
generated from generate_md.c[789b92e422631684352909cfb8bf43f6ceb16a01]
generated from generate_rst.c[3c4b523fbb57c8e4a7e247379d06a8021ccc21c4]
generated from generate_xsd.c[6b6818d7f17a35d56c376c04ec1410427f34c0f0]
- generated from generate_defconfig.c[63ca9d8ae2f1ce2e761c9d4c0510a45eb062d830]
+ generated from generate_defconfig.c[0ef1411470804c3db386c20c8752b161eb8418ae]
diff --git a/docs/manual/options.md b/docs/manual/options.md
index 3227bcdbe2..acde5f3720 100644
--- a/docs/manual/options.md
+++ b/docs/manual/options.md
@@ -402,7 +402,7 @@ The default value is: `default`
##### //CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange
-Attributes: [config](#cycloneddsdomaingeneralinterfacespubsubmessageexchangeconfig), [library](#cycloneddsdomaingeneralinterfacespubsubmessageexchangelibrary), [name](#cycloneddsdomaingeneralinterfacespubsubmessageexchangename), [priority](#cycloneddsdomaingeneralinterfacespubsubmessageexchangepriority)
+Attributes: [config](#cycloneddsdomaingeneralinterfacespubsubmessageexchangeconfig), [forbiddenTopics](#cycloneddsdomaingeneralinterfacespubsubmessageexchangeforbiddentopics), [library](#cycloneddsdomaingeneralinterfacespubsubmessageexchangelibrary), [name](#cycloneddsdomaingeneralinterfacespubsubmessageexchangename), [onlyForTopics](#cycloneddsdomaingeneralinterfacespubsubmessageexchangeonlyfortopics), [priority](#cycloneddsdomaingeneralinterfacespubsubmessageexchangepriority)
This element defines a PSMX.
@@ -415,6 +415,14 @@ This attribute specifies any configuration data for the PSMX instance.This has n
The default value is: ``
+##### //CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@forbiddenTopics]
+Text
+
+A comma-separated list of topics that should never use this psmx.Mutually exclusive with onlyForTopics.
+
+The default value is: ``
+
+
##### //CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@library]
Text
@@ -431,6 +439,14 @@ This attribute specifies the name of the interface.
The default value is: ``
+##### //CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@onlyForTopics]
+Text
+
+A comma-separated list of all the topics that should use this PSMX.This option can be used to restrict the PSMX to a selected list of topics.Mutually exclusive with forbiddenTopics.
+
+The default value is: ``
+
+
##### //CycloneDDS/Domain/General/Interfaces/PubSubMessageExchange[@priority]
Text
@@ -1846,14 +1862,14 @@ While none prevents any message from being written to a DDSI2 log file.
The categorisation of tracing output is incomplete and hence most of the verbosity levels and categories are not of much use in the current release. This is an ongoing process and here we describe the target situation rather than the current situation. Currently, the most useful verbosity levels are config, fine and finest.
The default value is: `none`
-
+
-
-
-
+
+
+
-
+
diff --git a/etc/cyclonedds.rnc b/etc/cyclonedds.rnc
index 02ded851fa..521635f7f8 100644
--- a/etc/cyclonedds.rnc
+++ b/etc/cyclonedds.rnc
@@ -296,6 +296,12 @@ CycloneDDS configuration""" ] ]
text
}?
& [ a:documentation [ xml:lang="en" """
+A comma-separated list of topics that should never use this psmx.Mutually exclusive with onlyForTopics.
+The default value is: <empty>
""" ] ]
+ attribute forbiddenTopics {
+ text
+ }?
+ & [ a:documentation [ xml:lang="en" """
This attribute specifies the filename of the interface library.
The default value is: <empty>
""" ] ]
attribute library {
@@ -308,6 +314,12 @@ CycloneDDS configuration""" ] ]
text
}?
& [ a:documentation [ xml:lang="en" """
+A comma-separated list of all the topics that should use this PSMX.This option can be used to restrict the PSMX to a selected list of topics.Mutually exclusive with forbiddenTopics.
+The default value is: <empty>
""" ] ]
+ attribute onlyForTopics {
+ text
+ }?
+ & [ a:documentation [ xml:lang="en" """
This attribute specifies the interface priority (decimal integer or default). The default value for a PSMX is 0.
The default value is: default
""" ] ]
attribute priority {
@@ -1283,14 +1295,14 @@ MIIEpAIBAAKCAQEA3HIh...AOBaaqSV37XBUJg==
duration_inf = xsd:token { pattern = "inf|0|(\d+(\.\d*)?([Ee][\-+]?\d+)?|\.\d+([Ee][\-+]?\d+)?) *([num]?s|min|hr|day)" }
memsize = xsd:token { pattern = "0|(\d+(\.\d*)?([Ee][\-+]?\d+)?|\.\d+([Ee][\-+]?\d+)?) *([kMG]i?)?B" }
}
-# generated from ddsi_config.h[570f67bd3080674a4bad53d9580a8bb7ad1e6e4d]
+# generated from ddsi_config.h[a6553d01e0d7a9c01fda217e68613a8ae1875883]
# generated from ddsi__cfgunits.h[bd22f0c0ed210501d0ecd3b07c992eca549ef5aa]
-# generated from ddsi__cfgelems.h[d4d0b8c7cf61f0a1cfa4b62e02458cf7b8962536]
-# generated from ddsi_config.c[efeae198a5e12ca8977a655216470564b5c44b64]
-# generated from _confgen.h[e32eabfc35e9f3a7dcb63b19ed148c0d17c6e5fc]
+# generated from ddsi__cfgelems.h[8c3942cd63352722dacc9df4db7cddae90a2cc13]
+# generated from ddsi_config.c[9a5b3e0862f49dc8bcd57b48b20efa1fc7702f42]
+# generated from _confgen.h[b3b98385ecc752860a55e126b3893423730f53ab]
# generated from _confgen.c[237308acd53897a34e8c643e16e05a61d73ffd65]
# generated from generate_rnc.c[b50e4b7ab1d04b2bc1d361a0811247c337b74934]
# generated from generate_md.c[789b92e422631684352909cfb8bf43f6ceb16a01]
# generated from generate_rst.c[3c4b523fbb57c8e4a7e247379d06a8021ccc21c4]
# generated from generate_xsd.c[6b6818d7f17a35d56c376c04ec1410427f34c0f0]
-# generated from generate_defconfig.c[63ca9d8ae2f1ce2e761c9d4c0510a45eb062d830]
+# generated from generate_defconfig.c[0ef1411470804c3db386c20c8752b161eb8418ae]
diff --git a/etc/cyclonedds.xsd b/etc/cyclonedds.xsd
index 4ab6d375b9..ad112f0ead 100644
--- a/etc/cyclonedds.xsd
+++ b/etc/cyclonedds.xsd
@@ -479,6 +479,13 @@ CycloneDDS configuration
<p>This attribute specifies any configuration data for the PSMX instance.This has no meaning in CycloneDDS itself, and its parsing is deferred to thePSMX implementation.</p>
+<p>The default value is: <code><empty></code></p>
+
+
+
+
+
+<p>A comma-separated list of topics that should never use this psmx.Mutually exclusive with onlyForTopics.</p>
<p>The default value is: <code><empty></code></p>
@@ -493,6 +500,13 @@ CycloneDDS configuration
<p>This attribute specifies the name of the interface. </p>
+<p>The default value is: <code><empty></code></p>
+
+
+
+
+
+<p>A comma-separated list of all the topics that should use this PSMX.This option can be used to restrict the PSMX to a selected list of topics.Mutually exclusive with forbiddenTopics.</p>
<p>The default value is: <code><empty></code></p>
@@ -1939,14 +1953,14 @@ MIIEpAIBAAKCAQEA3HIh...AOBaaqSV37XBUJg==<br>
-
+
-
-
-
+
+
+
-
+
diff --git a/src/core/ddsc/include/dds/ddsc/dds_psmx.h b/src/core/ddsc/include/dds/ddsc/dds_psmx.h
index 2ccf4e87d9..18ecd1dc85 100644
--- a/src/core/ddsc/include/dds/ddsc/dds_psmx.h
+++ b/src/core/ddsc/include/dds/ddsc/dds_psmx.h
@@ -260,6 +260,8 @@ typedef struct dds_psmx {
dds_psmx_ops_t ops; //!< associated functions
const char *instance_name; //!< name of this PSMX instance
int32_t priority; //!< priority of choosing this interface
+ char ** only_for_topics; //!< See ddsi_config_psmx. Format is nullptr-terminated array of separately allocated char*
+ char ** forbidden_topics; //!< See ddsi_config_psmx. Format is nullptr-terminated array of separately allocated char*
const struct ddsi_locator *locator; //!< the locator for this PSMX instance
dds_psmx_instance_id_t instance_id; //!< the identifier of this PSMX instance
struct dds_psmx_topic_list_elem *psmx_topics; //!< associated topics
diff --git a/src/core/ddsc/src/dds_psmx.c b/src/core/ddsc/src/dds_psmx.c
index d3634d19f4..e96f010a91 100644
--- a/src/core/ddsc/src/dds_psmx.c
+++ b/src/core/ddsc/src/dds_psmx.c
@@ -11,6 +11,7 @@
#include
#include "dds/ddsrt/heap.h"
+#include "dds/ddsrt/string.h"
#include "dds/ddsrt/dynlib.h"
#include "dds/ddsrt/mh3.h"
#include "dds/ddsi/ddsi_locator.h"
@@ -26,6 +27,8 @@
static struct dds_psmx_endpoint * psmx_create_endpoint (struct dds_psmx_topic *psmx_topic, const struct dds_qos *qos, dds_psmx_endpoint_type_t endpoint_type);
static dds_return_t psmx_delete_endpoint (struct dds_psmx_endpoint *psmx_endpoint);
+void deep_cleanup_topic_array(char **topic_array);
+
dds_return_t dds_add_psmx_topic_to_list (struct dds_psmx_topic *psmx_topic, struct dds_psmx_topic_list_elem **list)
{
if (!psmx_topic)
@@ -83,6 +86,14 @@ dds_return_t dds_remove_psmx_topic_from_list (struct dds_psmx_topic *psmx_topic,
return ret;
}
+// Free all members of a nullptr-terminated array of separately allocated char pointers
+void deep_cleanup_topic_array(char **topic_array) {
+ for (char * topic = *topic_array; topic; topic++) {
+ ddsrt_free((void*)topic);
+ }
+ ddsrt_free((void*)topic_array);
+}
+
dds_return_t dds_add_psmx_endpoint_to_list (struct dds_psmx_endpoint *psmx_endpoint, struct dds_psmx_endpoint_list_elem **list)
{
if (!psmx_endpoint)
@@ -163,6 +174,12 @@ dds_return_t dds_psmx_cleanup_generic (struct dds_psmx *psmx)
dds_free ((void *) psmx->instance_name);
dds_free ((void *) psmx->locator);
+ deep_cleanup_topic_array(psmx->only_for_topics);
+ psmx->only_for_topics = NULL;
+
+ deep_cleanup_topic_array(psmx->forbidden_topics);
+ psmx->forbidden_topics = NULL;
+
while (ret == DDS_RETCODE_OK && psmx->psmx_topics)
ret = dds_remove_psmx_topic_from_list (psmx->psmx_topics->topic, &psmx->psmx_topics);
@@ -249,10 +266,54 @@ static dds_return_t psmx_instance_load (const struct ddsi_domaingv *gv, struct d
goto err_init;
}
psmx_instance->priority = config->priority.value;
+
+ if (config->only_for_topics.size > 0 && config->forbidden_topics.size > 0) {
+ ret = DDS_RETCODE_UNSUPPORTED;
+ GVERROR ("Failed to initialize PSMX instance '%s': conflicting options only_for_topics and forbidden_topics were both present",
+ config->name);
+ goto err_init;
+ }
+
+ // Copy over the only_for_topics and forbidden_topics array, switching to nullptr-terminated array of separately-allocated strings
+ psmx_instance->only_for_topics = psmx_instance->forbidden_topics = NULL;
+
+ // Allocate +1 for the final nullptr terminator
+ psmx_instance->only_for_topics = ddsrt_calloc_s(config->only_for_topics.size + 1, sizeof(char*));
+ psmx_instance->forbidden_topics = ddsrt_calloc_s(config->forbidden_topics.size + 1, sizeof(char*));
+ if (!psmx_instance->only_for_topics || !psmx_instance->forbidden_topics) {
+ GVERROR ("Failed to initialize PSMX instance '%s': out of memory",
+ config->name);
+ goto err_topic_arrays_oom;
+ }
+
+ for (size_t i = 0 ; i < config->only_for_topics.size; i++) {
+ psmx_instance->only_for_topics[i] = ddsrt_strdup(config->only_for_topics.topics[i]);
+ if (psmx_instance->only_for_topics[i] == NULL) {
+ GVERROR ("Failed to initialize PSMX instance '%s': out of memory",
+ config->name);
+ goto err_topic_arrays_oom;
+ }
+ }
+ for (size_t i = 0 ; i < config->forbidden_topics.size; i++) {
+ psmx_instance->forbidden_topics[i] = ddsrt_strdup(config->forbidden_topics.topics[i]);
+ if (psmx_instance->forbidden_topics[i] == NULL) {
+ GVERROR ("Failed to initialize PSMX instance '%s': out of memory",
+ config->name);
+ goto err_topic_arrays_oom;
+ }
+ }
+
*out = psmx_instance;
*lib_handle = handle;
return DDS_RETCODE_OK;
+err_topic_arrays_oom:
+ if (psmx_instance->only_for_topics) {
+ deep_cleanup_topic_array(psmx_instance->only_for_topics);
+ }
+ if (psmx_instance->forbidden_topics) {
+ deep_cleanup_topic_array(psmx_instance->forbidden_topics);
+ }
err_init:
err_dlsym:
ddsrt_dlclose (handle);
diff --git a/src/core/ddsc/src/dds_topic.c b/src/core/ddsc/src/dds_topic.c
index 3165b62f06..49eb3b8ef6 100644
--- a/src/core/ddsc/src/dds_topic.c
+++ b/src/core/ddsc/src/dds_topic.c
@@ -583,6 +583,30 @@ dds_entity_t dds_create_topic_impl (
struct dds_psmx *psmx = dom->psmx_instances.instances[i];
if (!psmx->ops.type_qos_supported (psmx, DDS_PSMX_ENDPOINT_TYPE_UNSET, sertype_registered->data_type_props, new_qos))
continue;
+
+ // Check if the topic is in the forbiddenTopics or NOT in the onlyForTopics list, depending
+ // on which one is used.
+ // First off, topics not mentioned are allowed iff only_for_topics is unused
+ bool allowed_by_config = !psmx->only_for_topics[0];
+ // Then any topic in only_for_topics is allowed
+ for (char **topic = psmx->only_for_topics; *topic; topic++) {
+ if (strcmp(ktp->name, *topic) == 0) {
+ allowed_by_config = true;
+ break;
+ }
+ }
+ // And any topic in forbidden_topics is forbidden
+ for (char **topic = psmx->forbidden_topics; *topic; topic++) {
+ if (strcmp(ktp->name, *topic) == 0) {
+ allowed_by_config = false;
+ break;
+ }
+ }
+
+ if (!allowed_by_config) {
+ continue;
+ }
+
struct dds_psmx_topic *psmx_topic = psmx->ops.create_topic (psmx, ktp->name, sertype_registered->type_name, sertype_registered->data_type_props);
if (psmx_topic == NULL)
{
diff --git a/src/core/ddsi/defconfig.c b/src/core/ddsi/defconfig.c
index 814d0d5ef5..0ed931e84d 100644
--- a/src/core/ddsi/defconfig.c
+++ b/src/core/ddsi/defconfig.c
@@ -99,14 +99,14 @@ void ddsi_config_init_default (struct ddsi_config *cfg)
cfg->ssl_min_version.minor = 3;
#endif /* DDS_HAS_SSL */
}
-/* generated from ddsi_config.h[570f67bd3080674a4bad53d9580a8bb7ad1e6e4d] */
+/* generated from ddsi_config.h[a6553d01e0d7a9c01fda217e68613a8ae1875883] */
/* generated from ddsi__cfgunits.h[bd22f0c0ed210501d0ecd3b07c992eca549ef5aa] */
-/* generated from ddsi__cfgelems.h[d4d0b8c7cf61f0a1cfa4b62e02458cf7b8962536] */
-/* generated from ddsi_config.c[efeae198a5e12ca8977a655216470564b5c44b64] */
-/* generated from _confgen.h[e32eabfc35e9f3a7dcb63b19ed148c0d17c6e5fc] */
+/* generated from ddsi__cfgelems.h[8c3942cd63352722dacc9df4db7cddae90a2cc13] */
+/* generated from ddsi_config.c[9a5b3e0862f49dc8bcd57b48b20efa1fc7702f42] */
+/* generated from _confgen.h[b3b98385ecc752860a55e126b3893423730f53ab] */
/* generated from _confgen.c[237308acd53897a34e8c643e16e05a61d73ffd65] */
/* generated from generate_rnc.c[b50e4b7ab1d04b2bc1d361a0811247c337b74934] */
/* generated from generate_md.c[789b92e422631684352909cfb8bf43f6ceb16a01] */
/* generated from generate_rst.c[3c4b523fbb57c8e4a7e247379d06a8021ccc21c4] */
/* generated from generate_xsd.c[6b6818d7f17a35d56c376c04ec1410427f34c0f0] */
-/* generated from generate_defconfig.c[63ca9d8ae2f1ce2e761c9d4c0510a45eb062d830] */
+/* generated from generate_defconfig.c[0ef1411470804c3db386c20c8752b161eb8418ae] */
diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_config.h b/src/core/ddsi/include/dds/ddsi/ddsi_config.h
index f3be421a94..f7afeb2de3 100644
--- a/src/core/ddsi/include/dds/ddsi/ddsi_config.h
+++ b/src/core/ddsi/include/dds/ddsi/ddsi_config.h
@@ -235,11 +235,22 @@ enum ddsi_config_entity_naming_mode {
DDSI_ENTITY_NAMING_DEFAULT_FANCY
};
+// The array is stored as size + pointer to pointer array.
+// If size is zero, the pointer is NULL rather than a pointer to an empty array.
+// The pointed-to strings are allocated right after the array, so
+// a simple `free(topics)` frees everything
+struct ddsi_config_topic_array {
+ size_t size;
+ char **topics;
+};
+
struct ddsi_config_psmx {
char *name;
char *library;
char *config;
struct ddsi_config_maybe_int32 priority;
+ struct ddsi_config_topic_array forbidden_topics;
+ struct ddsi_config_topic_array only_for_topics;
};
struct ddsi_config_psmx_listelem {
diff --git a/src/core/ddsi/src/ddsi__cfgelems.h b/src/core/ddsi/src/ddsi__cfgelems.h
index a0ccf089fa..760bb5bb1f 100644
--- a/src/core/ddsi/src/ddsi__cfgelems.h
+++ b/src/core/ddsi/src/ddsi__cfgelems.h
@@ -103,6 +103,21 @@ static struct cfgelem psmx_attributes[] = {
"This has no meaning in CycloneDDS itself, and its parsing is deferred to the"
"PSMX implementation.
"
)),
+ STRING("forbiddenTopics", NULL, 1, "",
+ MEMBEROF(ddsi_config_psmx_listelem, cfg.forbidden_topics),
+ FUNCTIONS(if_topic_array, uf_topic_array, ff_topic_array, pf_topic_array),
+ DESCRIPTION(
+ "A comma-separated list of topics that should never use this psmx."
+ "Mutually exclusive with onlyForTopics.
"
+ )),
+ STRING("onlyForTopics", NULL, 1, "",
+ MEMBEROF(ddsi_config_psmx_listelem, cfg.only_for_topics),
+ FUNCTIONS(if_topic_array, uf_topic_array, ff_topic_array, pf_topic_array),
+ DESCRIPTION(
+ "A comma-separated list of all the topics that should use this PSMX."
+ "This option can be used to restrict the PSMX to a selected list of topics."
+ "Mutually exclusive with forbiddenTopics.
"
+ )),
END_MARKER
};
diff --git a/src/core/ddsi/src/ddsi_config.c b/src/core/ddsi/src/ddsi_config.c
index 52c9d624b9..fbf4a2c983 100644
--- a/src/core/ddsi/src/ddsi_config.c
+++ b/src/core/ddsi/src/ddsi_config.c
@@ -52,6 +52,11 @@ typedef enum update_result (*update_fun_t) (struct ddsi_cfgst *cfgst, void *pare
typedef void (*free_fun_t) (struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem);
typedef void (*print_fun_t) (struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, uint32_t sources);
+// Split the given string at commas. Returns a freshly allocated char* array pointing to the
+// split words and returns the number of words found in *nwords. The pointed-to strings are
+// contained in the returned allocation, so a single `free` on the return value frees everything
+static char **split_at_comma (const char *str, size_t *nwords);
+
struct unit {
const char *name;
int64_t multiplier;
@@ -192,6 +197,7 @@ DU(deaf_mute);
DUPF(min_tls_version);
#endif
DUPF(shm_loglevel);
+DUPF(topic_array);
#undef DUPF
#undef DU
#undef PF
@@ -199,6 +205,7 @@ DUPF(shm_loglevel);
#define DF(fname) static void fname (struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
DF(ff_free);
DF(ff_networkAddresses);
+DF(ff_topic_array);
#undef DF
#define DI(fname) static int fname (struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem)
@@ -214,6 +221,7 @@ DI(if_thread_properties);
#ifdef DDS_HAS_SECURITY
DI(if_omg_security);
#endif
+DI(if_topic_array);
#undef DI
/* drop extra information, i.e. DESCRIPTION, RANGE, UNIT and VALUES */
@@ -680,9 +688,7 @@ static int if_psmx(struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const
struct ddsi_config_psmx_listelem *new = if_common (cfgst, parent, cfgelem, sizeof(*new));
if (new == NULL)
return -1;
- new->cfg.name = NULL;
- new->cfg.library = NULL;
- new->cfg.config = NULL;
+ memset(&new->cfg, 0, sizeof(new->cfg));
return 0;
}
@@ -1279,6 +1285,42 @@ static void ff_networkAddresses (struct ddsi_cfgst *cfgst, void *parent, struct
ddsrt_free (*elem);
}
+static int if_topic_array(struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) {
+ struct ddsi_config_topic_array * elem = cfg_address (cfgst, parent, cfgelem);
+ elem->size = 0;
+ elem->topics = NULL;
+ return 0;
+}
+
+static enum update_result uf_topic_array (struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem, UNUSED_ARG(int first), const char *value) {
+ struct ddsi_config_topic_array * elem = cfg_address (cfgst, parent, cfgelem);
+ free(elem->topics);
+ if (*value == '\0') {
+ elem->size = 0;
+ elem->topics = NULL;
+ } else {
+ elem->topics = split_at_comma(value, &elem->size);
+ }
+ return URES_SUCCESS;
+}
+
+static void ff_topic_array (struct ddsi_cfgst *cfgst, void *parent, struct cfgelem const * const cfgelem) {
+ struct ddsi_config_topic_array * elem = cfg_address (cfgst, parent, cfgelem);
+ free(elem->topics);
+}
+
+static void pf_topic_array (struct ddsi_cfgst *cfgst, UNUSED_ARG (void *parent), UNUSED_ARG (struct cfgelem const * const cfgelem), uint32_t sources) {
+ struct ddsi_config_topic_array * elem = cfg_address (cfgst, parent, cfgelem);
+ if (elem->size == 0) {
+ // Just passing "" produces a "zero-length format string" warning
+ cfg_logelem (cfgst, sources, "%s", "");
+ } else {
+ for (size_t i = 0; i < elem->size; ++i) {
+ cfg_logelem (cfgst, sources, "%s", elem->topics[i]);
+ }
+ }
+}
+
#ifdef DDS_HAS_SSM
static const char *allow_multicast_names[] = { "false", "spdp", "asm", "ssm", "true", NULL };
static const uint32_t allow_multicast_codes[] = { DDSI_AMC_FALSE, DDSI_AMC_SPDP, DDSI_AMC_ASM, DDSI_AMC_SSM, DDSI_AMC_TRUE };
diff --git a/src/tools/_confgen/_confgen.h b/src/tools/_confgen/_confgen.h
index cd64e8ae90..b404bacca1 100644
--- a/src/tools/_confgen/_confgen.h
+++ b/src/tools/_confgen/_confgen.h
@@ -53,6 +53,7 @@ void gendef_pf_transport_selector (FILE *fp, void *parent, struct cfgelem const
void gendef_pf_many_sockets_mode (FILE *fp, void *parent, struct cfgelem const * const cfgelem);
void gendef_pf_standards_conformance (FILE *fp, void *parent, struct cfgelem const * const cfgelem);
void gendef_pf_shm_loglevel (FILE *fp, void *parent, struct cfgelem const * const cfgelem);
+void gendef_pf_topic_array (FILE *fp, void *parent, struct cfgelem const * const cfgelem);
struct cfgunit {
const char *name;
diff --git a/src/tools/_confgen/generate_defconfig.c b/src/tools/_confgen/generate_defconfig.c
index 1122998307..e96eca7c94 100644
--- a/src/tools/_confgen/generate_defconfig.c
+++ b/src/tools/_confgen/generate_defconfig.c
@@ -193,6 +193,18 @@ void gendef_pf_standards_conformance (FILE *out, void *parent, struct cfgelem co
void gendef_pf_shm_loglevel (FILE *out, void *parent, struct cfgelem const * const cfgelem) {
gendef_pf_int (out, parent, cfgelem);
}
+void gendef_pf_topic_array (FILE *out, void *parent, struct cfgelem const * const cfgelem) {
+ struct ddsi_config_topic_array * elem = cfg_address (parent, cfgelem);
+ if (elem->size == 0) {
+ // The default zero-initialization does the right thing, nothing to do here
+ } else {
+ // Creating an initializer out of a dds_config_topic_array is a bit involved (we'd need to
+ // glue the topics back together with commas and also set up the allocation just like split_at_comma
+ // does it). At the same time, it's probably not useful. So restrict the gendef to empty arrays for now
+ // and implement this once it's actually needed.
+ fprintf(out, "#error \"Non-empty topic arrays not supported in default config\"\n");
+ }
+}
static void gen_defaults (FILE *out, void *parent, struct cfgelem const * const cfgelem)
{