diff --git a/src/core/ddsc/src/dds_matched.c b/src/core/ddsc/src/dds_matched.c index fe3adf453c..58679b71f3 100644 --- a/src/core/ddsc/src/dds_matched.c +++ b/src/core/ddsc/src/dds_matched.c @@ -76,6 +76,8 @@ static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const ddsi_guid_ return ep; } +static const struct ddsi_entity_common null_entity_common; + dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t writer, dds_instance_handle_t ih) { dds_writer *wr; @@ -83,15 +85,19 @@ dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t wri return NULL; dds_builtintopic_endpoint_t *ret = NULL; - struct ddsi_entity_common *rdc; - struct dds_qos *rdqos; - struct ddsi_entity_common *ppc; + const struct ddsi_entity_common *rdc; + const struct dds_qos *rdqos; + const struct ddsi_entity_common *ppc; // thread must be "awake" while pointers to DDSI entities are being used struct ddsi_domaingv * const gv = &wr->m_entity.m_domain->gv; ddsi_thread_state_awake (ddsi_lookup_thread_state (), gv); if (ddsi_writer_find_matched_reader (wr->m_wr, ih, &rdc, &rdqos, &ppc)) + { + if (ppc == NULL) + ppc = &null_entity_common; ret = make_builtintopic_endpoint (&rdc->guid, &ppc->guid, ppc->iid, rdqos); + } ddsi_thread_state_asleep (ddsi_lookup_thread_state ()); dds_writer_unlock (wr); @@ -105,15 +111,19 @@ dds_builtintopic_endpoint_t *dds_get_matched_publication_data (dds_entity_t read return NULL; dds_builtintopic_endpoint_t *ret = NULL; - struct ddsi_entity_common *wrc; - struct dds_qos *wrqos; - struct ddsi_entity_common *ppc; + const struct ddsi_entity_common *wrc; + const struct dds_qos *wrqos; + const struct ddsi_entity_common *ppc; // thread must be "awake" while pointers to DDSI entities are being used struct ddsi_domaingv * const gv = &rd->m_entity.m_domain->gv; ddsi_thread_state_awake (ddsi_lookup_thread_state (), gv); if (ddsi_reader_find_matched_writer (rd->m_rd, ih, &wrc, &wrqos, &ppc)) + { + if (ppc == NULL) + ppc = &null_entity_common; ret = make_builtintopic_endpoint (&wrc->guid, &ppc->guid, ppc->iid, wrqos); + } ddsi_thread_state_asleep (ddsi_lookup_thread_state ()); dds_reader_unlock (rd); diff --git a/src/core/ddsc/tests/builtin_topics.c b/src/core/ddsc/tests/builtin_topics.c index 47b35c0b52..7f2e891a80 100644 --- a/src/core/ddsc/tests/builtin_topics.c +++ b/src/core/ddsc/tests/builtin_topics.c @@ -558,3 +558,41 @@ CU_Test(ddsc_builtin_topics, get_qos) check_default_qos_of_builtin_entity (tps[i].h, CDQOBE_TOPIC); } } + +CU_Test(ddsc_builtin_topics, get_matched_publication) +{ + static const dds_entity_t tps[] = { + DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, +#ifdef DDS_HAS_TOPIC_DISCOVERY + DDS_BUILTIN_TOPIC_DCPSTOPIC, +#endif + DDS_BUILTIN_TOPIC_DCPSPUBLICATION, + DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION + }; + static const dds_guid_t zguid; + // pseudo handles always exist and it actually works even in the absence of a domain + // not sure whether that's a feature or a bug ... + const dds_entity_t dp = dds_create_participant (0, NULL, NULL); + CU_ASSERT_FATAL (dp > 0); + dds_return_t rc; + for (size_t i = 0; i < sizeof (tps) / sizeof (tps[0]); i++) + { + const dds_entity_t rd = dds_create_reader (dp, tps[i], NULL, NULL); + CU_ASSERT_FATAL (rd > 0); + dds_instance_handle_t wrih; + // Application may not create writers, one local orphan writer, no remote writers + // Function returns actual number of matches, even if greater than the size of the + // output array. + rc = dds_get_matched_publications (rd, &wrih, 1); + CU_ASSERT_FATAL (rc == 1); + dds_builtintopic_endpoint_t *ep = dds_get_matched_publication_data (rd, wrih); + CU_ASSERT_FATAL (ep != NULL); + CU_ASSERT_FATAL (memcmp (&ep->participant_key, &zguid, sizeof (ep->participant_key)) == 0); + CU_ASSERT_FATAL (ep->participant_instance_handle == 0); + dds_builtintopic_free_endpoint (ep); + rc = dds_delete (rd); + CU_ASSERT_FATAL (rc == 0); + } + rc = dds_delete (dp); + CU_ASSERT_FATAL (rc == 0); +} diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_endpoint_match.h b/src/core/ddsi/include/dds/ddsi/ddsi_endpoint_match.h index 1e576ad6c0..a3d7e1e7c6 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_endpoint_match.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_endpoint_match.h @@ -32,11 +32,33 @@ dds_return_t ddsi_writer_get_matched_subscriptions (struct ddsi_writer *wr, uint /** @component endpoint_matching */ dds_return_t ddsi_reader_get_matched_publications (struct ddsi_reader *rd, uint64_t *wrs, size_t nwrs); -/** @component endpoint_matching */ -bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, struct ddsi_entity_common **rdc, struct dds_qos **rdqos, struct ddsi_entity_common **ppc); +/** @brief Lookup the instance handle of a matching reader and return it, it's qos and participant + * @component endpoint_matching + * + * @note Thread state must be "awake", returned pointers are aliases; lifetime ends on leaving the "awake" state; contents may not be modified. + * + * @param[in] wr writer for which to lookup ih in the setting of matching readers + * @param[in] ih instance handle of a reader + * @param[out] rdc pointer to the common entity data of the reader + * @param[out] rdqos pointer to the QoS of the reader + * @param[out] ppc participant, may be null for an orphan reader + * @return true iff ih corresponds to a matched reader, output parameters are undefined if not + */ +bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, const struct ddsi_entity_common **rdc, const struct dds_qos **rdqos, const struct ddsi_entity_common **ppc); -/** @component endpoint_matching */ -bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, struct ddsi_entity_common **wrc, struct dds_qos **wrqos, struct ddsi_entity_common **ppc); +/** @brief Lookup the instance handle of a matching writer and return it, it's qos and participant + * @component endpoint_matching + * + * @note Thread state must be "awake", returned pointers are aliases; lifetime ends on leaving the "awake" state; contents may not be modified. + * + * @param[in] rd reader for which to lookup ih in the setting of matching writers + * @param[in] ih instance handle of a writer + * @param[out] wrc pointer to the common entity data of the writer + * @param[out] wrqos pointer to the QoS of the writer + * @param[out] ppc participant, may be null for an orphan writer + * @return true iff ih corresponds to a matched writer, output parameters are undefined if not + */ +bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, const struct ddsi_entity_common **wrc, const struct dds_qos **wrqos, const struct ddsi_entity_common **ppc); #if defined (__cplusplus) } diff --git a/src/core/ddsi/src/ddsi_endpoint_match.c b/src/core/ddsi/src/ddsi_endpoint_match.c index 567fc0d5c0..4d20694997 100644 --- a/src/core/ddsi/src/ddsi_endpoint_match.c +++ b/src/core/ddsi/src/ddsi_endpoint_match.c @@ -1864,7 +1864,7 @@ dds_return_t ddsi_reader_get_matched_publications (struct ddsi_reader *rd, uint6 return (dds_return_t) nwrs_act; } -bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, struct ddsi_entity_common **rdc, struct dds_qos **rdqos, struct ddsi_entity_common **ppc) +bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, const struct ddsi_entity_common **rdc, const struct dds_qos **rdqos, const struct ddsi_entity_common **ppc) { /* FIXME: this ought not be so inefficient */ struct ddsi_domaingv *gv = wr->e.gv; @@ -1895,14 +1895,15 @@ bool ddsi_writer_find_matched_reader (struct ddsi_writer *wr, uint64_t ih, struc found = true; *rdc = &rd->e; *rdqos = rd->xqos; - *ppc = &rd->c.pp->e; + // The day orphan readers are introduced in addition to orphan writers, rd->c.pp may be a null pointer + *ppc = rd->c.pp ? &rd->c.pp->e : NULL; } } ddsrt_mutex_unlock (&wr->e.lock); return found; } -bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, struct ddsi_entity_common **wrc, struct dds_qos **wrqos, struct ddsi_entity_common **ppc) +bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, const struct ddsi_entity_common **wrc, const struct dds_qos **wrqos, const struct ddsi_entity_common **ppc) { /* FIXME: this ought not be so inefficient */ struct ddsi_domaingv *gv = rd->e.gv; @@ -1933,7 +1934,8 @@ bool ddsi_reader_find_matched_writer (struct ddsi_reader *rd, uint64_t ih, struc found = true; *wrc = &wr->e; *wrqos = wr->xqos; - *ppc = &wr->c.pp->e; + // Orphan writers have no participant + *ppc = wr->c.pp ? &wr->c.pp->e : NULL; } } ddsrt_mutex_unlock (&rd->e.lock);