|
11 | 11 | #include <string.h> |
12 | 12 |
|
13 | 13 | #include "dds/ddsrt/heap.h" |
| 14 | +#include "dds/ddsrt/string.h" |
14 | 15 | #include "dds/ddsrt/dynlib.h" |
15 | 16 | #include "dds/ddsrt/mh3.h" |
16 | 17 | #include "dds/ddsrt/io.h" |
|
27 | 28 | 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); |
28 | 29 | static dds_return_t psmx_delete_endpoint (struct dds_psmx_endpoint *psmx_endpoint); |
29 | 30 |
|
| 31 | +void deep_cleanup_topic_array(char **topic_array); |
| 32 | + |
30 | 33 | dds_return_t dds_add_psmx_topic_to_list (struct dds_psmx_topic *psmx_topic, struct dds_psmx_topic_list_elem **list) |
31 | 34 | { |
32 | 35 | if (!psmx_topic) |
@@ -84,6 +87,14 @@ dds_return_t dds_remove_psmx_topic_from_list (struct dds_psmx_topic *psmx_topic, |
84 | 87 | return ret; |
85 | 88 | } |
86 | 89 |
|
| 90 | +// Free all members of a nullptr-terminated array of separately allocated char pointers |
| 91 | +void deep_cleanup_topic_array(char **topic_array) { |
| 92 | + for (char * topic = *topic_array; topic; topic++) { |
| 93 | + ddsrt_free((void*)topic); |
| 94 | + } |
| 95 | + ddsrt_free((void*)topic_array); |
| 96 | +} |
| 97 | + |
87 | 98 | dds_return_t dds_add_psmx_endpoint_to_list (struct dds_psmx_endpoint *psmx_endpoint, struct dds_psmx_endpoint_list_elem **list) |
88 | 99 | { |
89 | 100 | if (!psmx_endpoint) |
@@ -164,6 +175,12 @@ dds_return_t dds_psmx_cleanup_generic (struct dds_psmx *psmx) |
164 | 175 | dds_free ((void *) psmx->instance_name); |
165 | 176 | dds_free ((void *) psmx->locator); |
166 | 177 |
|
| 178 | + deep_cleanup_topic_array(psmx->only_for_topics); |
| 179 | + psmx->only_for_topics = NULL; |
| 180 | + |
| 181 | + deep_cleanup_topic_array(psmx->forbidden_topics); |
| 182 | + psmx->forbidden_topics = NULL; |
| 183 | + |
167 | 184 | while (ret == DDS_RETCODE_OK && psmx->psmx_topics) |
168 | 185 | ret = dds_remove_psmx_topic_from_list (psmx->psmx_topics->topic, &psmx->psmx_topics); |
169 | 186 |
|
@@ -313,11 +330,55 @@ static dds_return_t psmx_instance_load (const struct ddsi_domaingv *gv, const st |
313 | 330 | goto err_init; |
314 | 331 | } |
315 | 332 | psmx_instance->priority = config->priority.value; |
| 333 | + |
| 334 | + if (config->only_for_topics.size > 0 && config->forbidden_topics.size > 0) { |
| 335 | + ret = DDS_RETCODE_UNSUPPORTED; |
| 336 | + GVERROR ("Failed to initialize PSMX instance '%s': conflicting options only_for_topics and forbidden_topics were both present", |
| 337 | + config->name); |
| 338 | + goto err_init; |
| 339 | + } |
| 340 | + |
| 341 | + // Copy over the only_for_topics and forbidden_topics array, switching to nullptr-terminated array of separately-allocated strings |
| 342 | + psmx_instance->only_for_topics = psmx_instance->forbidden_topics = NULL; |
| 343 | + |
| 344 | + // Allocate +1 for the final nullptr terminator |
| 345 | + psmx_instance->only_for_topics = ddsrt_calloc_s(config->only_for_topics.size + 1, sizeof(char*)); |
| 346 | + psmx_instance->forbidden_topics = ddsrt_calloc_s(config->forbidden_topics.size + 1, sizeof(char*)); |
| 347 | + if (!psmx_instance->only_for_topics || !psmx_instance->forbidden_topics) { |
| 348 | + GVERROR ("Failed to initialize PSMX instance '%s': out of memory", |
| 349 | + config->name); |
| 350 | + goto err_topic_arrays_oom; |
| 351 | + } |
| 352 | + |
| 353 | + for (size_t i = 0 ; i < config->only_for_topics.size; i++) { |
| 354 | + psmx_instance->only_for_topics[i] = ddsrt_strdup(config->only_for_topics.topics[i]); |
| 355 | + if (psmx_instance->only_for_topics[i] == NULL) { |
| 356 | + GVERROR ("Failed to initialize PSMX instance '%s': out of memory", |
| 357 | + config->name); |
| 358 | + goto err_topic_arrays_oom; |
| 359 | + } |
| 360 | + } |
| 361 | + for (size_t i = 0 ; i < config->forbidden_topics.size; i++) { |
| 362 | + psmx_instance->forbidden_topics[i] = ddsrt_strdup(config->forbidden_topics.topics[i]); |
| 363 | + if (psmx_instance->forbidden_topics[i] == NULL) { |
| 364 | + GVERROR ("Failed to initialize PSMX instance '%s': out of memory", |
| 365 | + config->name); |
| 366 | + goto err_topic_arrays_oom; |
| 367 | + } |
| 368 | + } |
| 369 | + |
316 | 370 | *out = psmx_instance; |
317 | 371 | *lib_handle = handle; |
318 | 372 | ddsrt_free (configstr); |
319 | 373 | return DDS_RETCODE_OK; |
320 | 374 |
|
| 375 | +err_topic_arrays_oom: |
| 376 | + if (psmx_instance->only_for_topics) { |
| 377 | + deep_cleanup_topic_array(psmx_instance->only_for_topics); |
| 378 | + } |
| 379 | + if (psmx_instance->forbidden_topics) { |
| 380 | + deep_cleanup_topic_array(psmx_instance->forbidden_topics); |
| 381 | + } |
321 | 382 | err_init: |
322 | 383 | err_dlsym: |
323 | 384 | ddsrt_dlclose (handle); |
|
0 commit comments