2018-07-09 13:22:25 +02:00
|
|
|
// Copyright 2018 ADLINK Technology Limited.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
/* TODO:
|
|
|
|
|
|
|
|
- topic names (should use the same as other RMW layers)
|
|
|
|
|
|
|
|
- type names (make a copy of the generic type descriptor, modify the name and pass that)
|
|
|
|
|
2018-07-19 16:37:12 +02:00
|
|
|
- need to handle endianness differences in deserialization
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-13 08:52:21 +02:00
|
|
|
- topic creation: shouldn't leak topics
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
- introspection stuff not done yet
|
2018-07-09 13:22:25 +02:00
|
|
|
|
|
|
|
- check / make sure a node remains valid while one of its subscriptions exists
|
|
|
|
|
|
|
|
- service/client simply use the instance handle of its publisher as its GUID -- yikes! but it is
|
|
|
|
actually only kinda wrong because the instance handles allocated by different instance of cdds
|
|
|
|
are actually taken from uncorrelated (close to uncorrelated anyway) permutations of 64-bit
|
|
|
|
unsigned integers
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
- ... and probably many more things ...
|
2018-07-10 08:14:20 +02:00
|
|
|
*/
|
2018-07-09 13:22:25 +02:00
|
|
|
|
|
|
|
#include <mutex>
|
|
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
#include "rcutils/logging_macros.h"
|
|
|
|
|
|
|
|
#include "rmw/allocators.h"
|
|
|
|
#include "rmw/convert_rcutils_ret_to_rmw_ret.h"
|
|
|
|
#include "rmw/error_handling.h"
|
|
|
|
#include "rmw/names_and_types.h"
|
|
|
|
#include "rmw/rmw.h"
|
|
|
|
#include "rmw/sanity_checks.h"
|
|
|
|
|
|
|
|
#include "rmw/impl/cpp/macros.hpp"
|
|
|
|
|
|
|
|
#include "rmw_cyclonedds_cpp/MessageTypeSupport.hpp"
|
|
|
|
#include "rmw_cyclonedds_cpp/ServiceTypeSupport.hpp"
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
#include "namespace_prefix.hpp"
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
#include "dds/dds.h"
|
|
|
|
#include "dds/ddsi/ddsi_sertopic.h"
|
2018-07-19 16:37:12 +02:00
|
|
|
#include "rmw_cyclonedds_cpp/serdes.hpp"
|
2019-04-29 09:33:13 +02:00
|
|
|
#include "rmw_cyclonedds_cpp/serdata.hpp"
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
#define RET_ERR_X(msg, code) do { RMW_SET_ERROR_MSG (msg); code; } while (0)
|
|
|
|
#define RET_NULL_X(var, code) do { if (!var) RET_ERR_X (#var " is null", code); } while (0)
|
|
|
|
#define RET_ALLOC_X(var, code) do { if (!var) RET_ERR_X ("failed to allocate " #var, code); } while (0)
|
2018-07-09 13:22:25 +02:00
|
|
|
#define RET_WRONG_IMPLID_X(var, code) do { \
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_NULL_X (var, code); \
|
2019-05-03 17:12:51 +08:00
|
|
|
if ((var)->implementation_identifier != eclipse_cyclonedds_identifier) { \
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_ERR_X (#var " not from this implementation", code); \
|
2018-07-09 13:22:25 +02:00
|
|
|
} \
|
2019-04-29 09:33:13 +02:00
|
|
|
} while (0)
|
2018-07-09 13:22:25 +02:00
|
|
|
#define RET_NULL_OR_EMPTYSTR_X(var, code) do { \
|
2019-04-29 09:33:13 +02:00
|
|
|
if (!var || strlen (var) == 0) { \
|
|
|
|
RET_ERR_X (#var " is null or empty string", code); \
|
2018-07-10 08:14:20 +02:00
|
|
|
} \
|
2019-04-29 09:33:13 +02:00
|
|
|
} while (0)
|
|
|
|
#define RET_ERR(msg) RET_ERR_X (msg, return RMW_RET_ERROR)
|
|
|
|
#define RET_NULL(var) RET_NULL_X (var, return RMW_RET_ERROR)
|
|
|
|
#define RET_ALLOC(var) RET_ALLOC_X (var, return RMW_RET_ERROR)
|
|
|
|
#define RET_WRONG_IMPLID(var) RET_WRONG_IMPLID_X (var, return RMW_RET_ERROR)
|
|
|
|
#define RET_NULL_OR_EMPTYSTR(var) RET_NULL_OR_EMPTYSTR_X (var, return RMW_RET_ERROR)
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
const char *const eclipse_cyclonedds_identifier = "rmw_cyclonedds_cpp";
|
|
|
|
const char * const eclipse_cyclonedds_serialization_format = "cdr";
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-13 08:52:21 +02:00
|
|
|
/* instance handles are unsigned 64-bit integers carefully constructed to be as close to uniformly
|
|
|
|
distributed as possible for no other reason than making them near-perfect hash keys, hence we can
|
|
|
|
improve over the default hash function */
|
2018-07-09 13:22:25 +02:00
|
|
|
struct dds_instance_handle_hash {
|
|
|
|
public:
|
2019-04-29 09:33:13 +02:00
|
|
|
std::size_t operator () (dds_instance_handle_t const& x) const noexcept {
|
|
|
|
return static_cast<std::size_t> (x);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CddsNode {
|
|
|
|
rmw_guard_condition_t *graph_guard_condition;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CddsPublisher {
|
|
|
|
dds_entity_t pubh;
|
|
|
|
dds_instance_handle_t pubiid;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CddsSubscription {
|
|
|
|
dds_entity_t subh;
|
2018-07-13 08:52:21 +02:00
|
|
|
dds_entity_t rdcondh;
|
2018-07-09 13:22:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CddsCS {
|
|
|
|
CddsPublisher *pub;
|
|
|
|
CddsSubscription *sub;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CddsClient {
|
|
|
|
CddsCS client;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CddsService {
|
|
|
|
CddsCS service;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CddsGuardCondition {
|
2018-07-13 08:52:21 +02:00
|
|
|
dds_entity_t gcondh;
|
2018-07-09 13:22:25 +02:00
|
|
|
};
|
|
|
|
|
2018-07-19 16:35:46 +02:00
|
|
|
struct CddsWaitset {
|
|
|
|
dds_entity_t waitseth;
|
|
|
|
|
|
|
|
std::vector<dds_attach_t> trigs;
|
|
|
|
|
|
|
|
std::mutex lock;
|
|
|
|
bool inuse;
|
|
|
|
std::vector<CddsSubscription *> subs;
|
|
|
|
std::vector<CddsGuardCondition *> gcs;
|
|
|
|
std::vector<CddsClient *> cls;
|
|
|
|
std::vector<CddsService *> srvs;
|
|
|
|
};
|
|
|
|
|
2018-07-13 08:52:21 +02:00
|
|
|
struct Cdds {
|
|
|
|
std::mutex lock;
|
|
|
|
uint32_t refcount;
|
|
|
|
dds_entity_t ppant;
|
2018-07-19 16:35:46 +02:00
|
|
|
std::unordered_set<CddsWaitset *> waitsets;
|
2019-04-29 09:33:13 +02:00
|
|
|
Cdds () : refcount (0), ppant (0) {}
|
2018-07-13 08:52:21 +02:00
|
|
|
};
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-13 08:52:21 +02:00
|
|
|
static Cdds gcdds;
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static void clean_waitset_caches ();
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
#pragma GCC visibility push (default)
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" const char *rmw_get_implementation_identifier ()
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-05-03 17:12:51 +08:00
|
|
|
return eclipse_cyclonedds_identifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" const char *rmw_get_serialization_format()
|
|
|
|
{
|
|
|
|
return eclipse_cyclonedds_serialization_format;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_init_options_init (rmw_init_options_t *init_options, rcutils_allocator_t allocator)
|
|
|
|
{
|
|
|
|
RMW_CHECK_ARGUMENT_FOR_NULL (init_options, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RCUTILS_CHECK_ALLOCATOR (&allocator, return RMW_RET_INVALID_ARGUMENT);
|
|
|
|
if (NULL != init_options->implementation_identifier) {
|
|
|
|
RMW_SET_ERROR_MSG ("expected zero-initialized init_options");
|
|
|
|
return RMW_RET_INVALID_ARGUMENT;
|
|
|
|
}
|
|
|
|
init_options->instance_id = 0;
|
|
|
|
init_options->implementation_identifier = eclipse_cyclonedds_identifier;
|
|
|
|
init_options->allocator = allocator;
|
|
|
|
init_options->impl = nullptr;
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_init_options_copy (const rmw_init_options_t *src, rmw_init_options_t *dst)
|
|
|
|
{
|
|
|
|
RMW_CHECK_ARGUMENT_FOR_NULL (src, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RMW_CHECK_ARGUMENT_FOR_NULL (dst, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RMW_CHECK_TYPE_IDENTIFIERS_MATCH (
|
|
|
|
src,
|
|
|
|
src->implementation_identifier,
|
|
|
|
eclipse_cyclonedds_identifier,
|
|
|
|
return RMW_RET_INCORRECT_RMW_IMPLEMENTATION);
|
|
|
|
if (NULL != dst->implementation_identifier) {
|
|
|
|
RMW_SET_ERROR_MSG ("expected zero-initialized dst");
|
|
|
|
return RMW_RET_INVALID_ARGUMENT;
|
|
|
|
}
|
|
|
|
*dst = *src;
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_init_options_fini (rmw_init_options_t *init_options)
|
|
|
|
{
|
|
|
|
RMW_CHECK_ARGUMENT_FOR_NULL (init_options, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RCUTILS_CHECK_ALLOCATOR (&init_options->allocator, return RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RMW_CHECK_TYPE_IDENTIFIERS_MATCH (
|
|
|
|
init_options,
|
|
|
|
init_options->implementation_identifier,
|
|
|
|
eclipse_cyclonedds_identifier,
|
|
|
|
return RMW_RET_INCORRECT_RMW_IMPLEMENTATION);
|
|
|
|
*init_options = rmw_get_zero_initialized_init_options ();
|
|
|
|
return RMW_RET_OK;
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_init (const rmw_init_options_t *options __attribute__ ((unused)), rmw_context_t *context __attribute__ ((unused)))
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-05-03 17:12:51 +08:00
|
|
|
RCUTILS_CHECK_ARGUMENT_FOR_NULL (options, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RCUTILS_CHECK_ARGUMENT_FOR_NULL (context, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RMW_CHECK_TYPE_IDENTIFIERS_MATCH (
|
|
|
|
options,
|
|
|
|
options->implementation_identifier,
|
|
|
|
eclipse_cyclonedds_identifier,
|
|
|
|
return RMW_RET_INCORRECT_RMW_IMPLEMENTATION);
|
|
|
|
context->instance_id = options->instance_id;
|
|
|
|
context->implementation_identifier = eclipse_cyclonedds_identifier;
|
|
|
|
context->impl = nullptr;
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_shutdown (rmw_context_t *context)
|
|
|
|
{
|
|
|
|
RCUTILS_CHECK_ARGUMENT_FOR_NULL (context, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
RMW_CHECK_TYPE_IDENTIFIERS_MATCH (
|
|
|
|
context,
|
|
|
|
context->implementation_identifier,
|
|
|
|
eclipse_cyclonedds_identifier,
|
|
|
|
return RMW_RET_INCORRECT_RMW_IMPLEMENTATION);
|
|
|
|
// context impl is explicitly supposed to be nullptr for now, see rmw_init's code
|
|
|
|
// RCUTILS_CHECK_ARGUMENT_FOR_NULL (context->impl, RMW_RET_INVALID_ARGUMENT);
|
|
|
|
*context = rmw_get_zero_initialized_context ();
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static dds_entity_t ref_ppant ()
|
2018-07-13 08:52:21 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (gcdds.lock);
|
2018-07-13 08:52:21 +02:00
|
|
|
if (gcdds.refcount == 0) {
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((gcdds.ppant = dds_create_participant (DDS_DOMAIN_DEFAULT, nullptr, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create participant");
|
2018-07-13 08:52:21 +02:00
|
|
|
return gcdds.ppant;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gcdds.refcount++;
|
|
|
|
return gcdds.ppant;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static void unref_ppant ()
|
2018-07-13 08:52:21 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (gcdds.lock);
|
2018-07-13 08:52:21 +02:00
|
|
|
if (--gcdds.refcount == 0) {
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete (gcdds.ppant);
|
2018-07-13 08:52:21 +02:00
|
|
|
gcdds.ppant = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////// NODES ///////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_node_t *rmw_create_node (rmw_context_t *context __attribute__ ((unused)), const char *name, const char *namespace_, size_t domain_id, const rmw_node_security_options_t *security_options)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_NULL_X (name, return nullptr);
|
|
|
|
RET_NULL_X (namespace_, return nullptr);
|
|
|
|
(void) domain_id;
|
|
|
|
(void) security_options;
|
2018-07-10 08:14:20 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_entity_t pp = ref_ppant ();
|
2018-07-13 08:52:21 +02:00
|
|
|
if (pp < 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
auto *node_impl = new CddsNode ();
|
2018-07-10 08:14:20 +02:00
|
|
|
rmw_node_t *node_handle = nullptr;
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_ALLOC_X (node_impl, goto fail_node_impl);
|
2018-07-10 08:14:20 +02:00
|
|
|
rmw_guard_condition_t *graph_guard_condition;
|
2019-04-29 09:33:13 +02:00
|
|
|
if (!(graph_guard_condition = rmw_create_guard_condition (context))) {
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_ggc;
|
|
|
|
}
|
|
|
|
node_impl->graph_guard_condition = graph_guard_condition;
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
node_handle = rmw_node_allocate ();
|
|
|
|
RET_ALLOC_X (node_handle, goto fail_node_handle);
|
2019-05-03 17:12:51 +08:00
|
|
|
node_handle->implementation_identifier = eclipse_cyclonedds_identifier;
|
2018-07-10 08:14:20 +02:00
|
|
|
node_handle->data = node_impl;
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
node_handle->name = static_cast<const char *> (rmw_allocate (sizeof (char) * strlen (name) + 1));
|
|
|
|
RET_ALLOC_X (node_handle->name, goto fail_node_handle_name);
|
|
|
|
memcpy (const_cast<char *> (node_handle->name), name, strlen (name) + 1);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
node_handle->namespace_ = static_cast<const char *> (rmw_allocate (sizeof (char) * strlen (namespace_) + 1));
|
|
|
|
RET_ALLOC_X (node_handle->namespace_, goto fail_node_handle_namespace);
|
|
|
|
memcpy (const_cast<char *> (node_handle->namespace_), namespace_, strlen (namespace_) + 1);
|
2018-07-10 08:14:20 +02:00
|
|
|
return node_handle;
|
2018-07-09 13:22:25 +02:00
|
|
|
|
|
|
|
#if 0
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_add_node:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_free (const_cast<char *> (node_handle->namespace_));
|
2018-07-09 13:22:25 +02:00
|
|
|
#endif
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_node_handle_namespace:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_free (const_cast<char *> (node_handle->name));
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_node_handle_name:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_node_free (node_handle);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_node_handle:
|
2019-04-29 09:33:13 +02:00
|
|
|
if (RMW_RET_OK != rmw_destroy_guard_condition (graph_guard_condition)) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED ("rmw_cyclonedds_cpp", "failed to destroy guard condition during error handling");
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_ggc:
|
|
|
|
delete node_impl;
|
|
|
|
fail_node_impl:
|
2019-04-29 09:33:13 +02:00
|
|
|
unref_ppant ();
|
2018-07-10 08:14:20 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_destroy_node (rmw_node_t *node)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
|
|
|
rmw_ret_t result_ret = RMW_RET_OK;
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
auto node_impl = static_cast<CddsNode *> (node->data);
|
|
|
|
RET_NULL (node_impl);
|
|
|
|
rmw_free (const_cast<char *> (node->name));
|
|
|
|
rmw_free (const_cast<char *> (node->namespace_));
|
|
|
|
rmw_node_free (node);
|
|
|
|
if (RMW_RET_OK != rmw_destroy_guard_condition (node_impl->graph_guard_condition)) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to destroy graph guard condition");
|
2018-07-10 08:14:20 +02:00
|
|
|
result_ret = RMW_RET_ERROR;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
delete node_impl;
|
2019-04-29 09:33:13 +02:00
|
|
|
unref_ppant ();
|
2018-07-10 08:14:20 +02:00
|
|
|
return result_ret;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" const rmw_guard_condition_t *rmw_node_get_graph_guard_condition (const rmw_node_t *node)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID_X (node, return nullptr);
|
|
|
|
auto node_impl = static_cast<CddsNode *> (node->data);
|
|
|
|
RET_NULL_X (node_impl, return nullptr);
|
2018-07-10 08:14:20 +02:00
|
|
|
return node_impl->graph_guard_condition;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////// (DE)SERIALIZATION ///////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_serialize (const void *ros_message, const rosidl_message_type_support_t *type_support, rmw_serialized_message_t *serialized_message)
|
|
|
|
{
|
|
|
|
(void) ros_message; (void) type_support; (void) serialized_message;
|
|
|
|
RMW_SET_ERROR_MSG ("rmw_serialize not implemented");
|
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_deserialize (const rmw_serialized_message_t *serialized_message, const rosidl_message_type_support_t *type_support, void *ros_message)
|
|
|
|
{
|
|
|
|
(void) ros_message; (void) type_support; (void) serialized_message;
|
|
|
|
RMW_SET_ERROR_MSG ("rmw_deserialize not implemented");
|
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////// PUBLICATIONS ///////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_publish (const rmw_publisher_t *publisher, const void *ros_message)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (publisher);
|
|
|
|
RET_NULL (ros_message);
|
|
|
|
auto pub = static_cast<CddsPublisher *> (publisher->data);
|
|
|
|
assert (pub);
|
|
|
|
if (dds_write (pub->pubh, ros_message) >= 0) {
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
} else {
|
|
|
|
/* FIXME: what is the expected behavior when it times out? */
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("cannot publish data");
|
2018-07-10 08:14:20 +02:00
|
|
|
//return RMW_RET_ERROR;
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-19 16:37:12 +02:00
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
extern "C" rmw_ret_t rmw_publish_serialized_message (const rmw_publisher_t *publisher, const rmw_serialized_message_t *serialized_message)
|
|
|
|
{
|
|
|
|
(void) publisher; (void) serialized_message;
|
|
|
|
RMW_SET_ERROR_MSG ("rmw_publish_serialized_message not implemented");
|
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static const rosidl_message_type_support_t *get_typesupport (const rosidl_message_type_support_t *type_supports)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
|
|
|
const rosidl_message_type_support_t *ts;
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((ts = get_message_typesupport_handle (type_supports, rosidl_typesupport_introspection_c__identifier)) != nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
return ts;
|
2019-04-29 09:33:13 +02:00
|
|
|
} else if ((ts = get_message_typesupport_handle (type_supports, rosidl_typesupport_introspection_cpp::typesupport_identifier)) != nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
return ts;
|
|
|
|
} else {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("type support not from this implementation");
|
2018-07-10 08:14:20 +02:00
|
|
|
return nullptr;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static std::string make_fqtopic (const char *prefix, const char *topic_name, const char *suffix, bool avoid_ros_namespace_conventions)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
|
|
|
if (avoid_ros_namespace_conventions) {
|
2019-04-29 09:33:13 +02:00
|
|
|
return std::string (topic_name) + "__" + std::string (suffix);
|
2018-07-10 08:14:20 +02:00
|
|
|
} else {
|
2019-04-29 09:33:13 +02:00
|
|
|
return std::string (prefix) + "/" + make_fqtopic (prefix, topic_name, suffix, true);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static std::string make_fqtopic (const char *prefix, const char *topic_name, const char *suffix, const rmw_qos_profile_t *qos_policies)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
return make_fqtopic (prefix, topic_name, suffix, qos_policies->avoid_ros_namespace_conventions);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static dds_qos_t *create_readwrite_qos (const rmw_qos_profile_t *qos_policies, bool ignore_local_publications)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qos_t *qos = dds_create_qos ();
|
2018-07-10 08:14:20 +02:00
|
|
|
switch (qos_policies->history) {
|
|
|
|
case RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT:
|
|
|
|
case RMW_QOS_POLICY_HISTORY_KEEP_LAST:
|
|
|
|
if (qos_policies->depth > INT32_MAX) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("unsupported history depth");
|
|
|
|
dds_delete_qos (qos);
|
2018-07-10 08:14:20 +02:00
|
|
|
return nullptr;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qset_history (qos, DDS_HISTORY_KEEP_LAST, static_cast<uint32_t> (qos_policies->depth));
|
2018-07-10 08:14:20 +02:00
|
|
|
break;
|
|
|
|
case RMW_QOS_POLICY_HISTORY_KEEP_ALL:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED);
|
2018-07-10 08:14:20 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (qos_policies->reliability) {
|
|
|
|
case RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT:
|
|
|
|
case RMW_QOS_POLICY_RELIABILITY_RELIABLE:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (1));
|
2018-07-10 08:14:20 +02:00
|
|
|
break;
|
|
|
|
case RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qset_reliability (qos, DDS_RELIABILITY_BEST_EFFORT, 0);
|
2018-07-10 08:14:20 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (qos_policies->durability) {
|
|
|
|
case RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT:
|
|
|
|
case RMW_QOS_POLICY_DURABILITY_VOLATILE:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qset_durability (qos, DDS_DURABILITY_VOLATILE);
|
2018-07-10 08:14:20 +02:00
|
|
|
break;
|
|
|
|
case RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qset_durability (qos, DDS_DURABILITY_TRANSIENT_LOCAL);
|
2018-07-10 08:14:20 +02:00
|
|
|
break;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if (ignore_local_publications) {
|
|
|
|
dds_qset_ignorelocal (qos, DDS_IGNORELOCAL_PARTICIPANT);
|
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
return qos;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static CddsPublisher *create_cdds_publisher (const rmw_node_t *node, const rosidl_message_type_support_t *type_supports, const char *topic_name, const rmw_qos_profile_t *qos_policies)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID_X (node, return nullptr);
|
|
|
|
RET_NULL_OR_EMPTYSTR_X (topic_name, return nullptr);
|
|
|
|
RET_NULL_X (qos_policies, return nullptr);
|
|
|
|
auto node_impl = static_cast<CddsNode *> (node->data);
|
|
|
|
RET_NULL_X (node_impl, return nullptr);
|
|
|
|
const rosidl_message_type_support_t *type_support = get_typesupport (type_supports);
|
|
|
|
RET_NULL_X (type_support, return nullptr);
|
|
|
|
CddsPublisher *pub = new CddsPublisher ();
|
2018-07-10 08:14:20 +02:00
|
|
|
dds_entity_t topic;
|
|
|
|
dds_qos_t *qos;
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
std::string fqtopic_name = make_fqtopic (ros_topic_prefix, topic_name, "", qos_policies);
|
2018-07-10 08:14:20 +02:00
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
auto sertopic = create_sertopic (fqtopic_name.c_str (), type_support->typesupport_identifier, create_message_type_support (type_support->data, type_support->typesupport_identifier), false);
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((topic = dds_create_topic_arbitrary (gcdds.ppant, sertopic, fqtopic_name.c_str (), nullptr, nullptr, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create topic");
|
|
|
|
goto fail_topic;
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((qos = create_readwrite_qos (qos_policies, false)) == nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_qos;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((pub->pubh = dds_create_writer (gcdds.ppant, topic, qos, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create writer");
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_writer;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_get_instance_handle (pub->pubh, &pub->pubiid) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to get instance handle for writer");
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_instance_handle;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete_qos (qos);
|
2018-07-10 08:14:20 +02:00
|
|
|
/* FIXME: leak the topic for now */
|
|
|
|
return pub;
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_instance_handle:
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_delete (pub->pubh) < 0) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED ("rmw_cyclonedds_cpp", "failed to destroy writer during error handling");
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_writer:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete_qos (qos);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_qos:
|
|
|
|
/* not deleting topic -- have to sort out proper topic handling & that requires fixing a few
|
|
|
|
things in cyclone as well */
|
|
|
|
fail_topic:
|
|
|
|
delete pub;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_publisher_t *rmw_create_publisher (const rmw_node_t *node, const rosidl_message_type_support_t *type_supports, const char *topic_name, const rmw_qos_profile_t *qos_policies)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
|
|
|
CddsPublisher *pub;
|
|
|
|
rmw_publisher_t *rmw_publisher;
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((pub = create_cdds_publisher (node, type_supports, topic_name, qos_policies)) == nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_common_init;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_publisher = rmw_publisher_allocate ();
|
|
|
|
RET_ALLOC_X (rmw_publisher, goto fail_publisher);
|
2019-05-03 17:12:51 +08:00
|
|
|
rmw_publisher->implementation_identifier = eclipse_cyclonedds_identifier;
|
2018-07-10 08:14:20 +02:00
|
|
|
rmw_publisher->data = pub;
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_publisher->topic_name = reinterpret_cast<char *> (rmw_allocate (strlen (topic_name) + 1));
|
|
|
|
RET_ALLOC_X (rmw_publisher->topic_name, goto fail_topic_name);
|
|
|
|
memcpy (const_cast<char *> (rmw_publisher->topic_name), topic_name, strlen (topic_name) + 1);
|
2018-07-10 08:14:20 +02:00
|
|
|
return rmw_publisher;
|
|
|
|
fail_topic_name:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_publisher_free (rmw_publisher);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_publisher:
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_delete (pub->pubh) < 0) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED ("rmw_cyclonedds_cpp", "failed to delete writer during error handling");
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
delete pub;
|
|
|
|
fail_common_init:
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_get_gid_for_publisher (const rmw_publisher_t *publisher, rmw_gid_t *gid)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (publisher);
|
|
|
|
RET_NULL (gid);
|
|
|
|
auto pub = static_cast<const CddsPublisher *> (publisher->data);
|
|
|
|
RET_NULL (pub);
|
2019-05-03 17:12:51 +08:00
|
|
|
gid->implementation_identifier = eclipse_cyclonedds_identifier;
|
2019-04-29 09:33:13 +02:00
|
|
|
memset (gid->data, 0, sizeof (gid->data));
|
|
|
|
assert (sizeof (pub->pubiid) <= sizeof (gid->data));
|
|
|
|
memcpy (gid->data, &pub->pubiid, sizeof (pub->pubiid));
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_compare_gids_equal (const rmw_gid_t *gid1, const rmw_gid_t *gid2, bool *result)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (gid1);
|
|
|
|
RET_WRONG_IMPLID (gid2);
|
|
|
|
RET_NULL (result);
|
2018-07-10 08:14:20 +02:00
|
|
|
/* alignment is potentially lost because of the translation to an array of bytes, so use
|
|
|
|
memcmp instead of a simple integer comparison */
|
2019-04-29 09:33:13 +02:00
|
|
|
*result = memcmp (gid1->data, gid2->data, sizeof (gid1->data)) == 0;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
extern "C" rmw_ret_t rmw_publisher_count_matched_subscriptions (const rmw_publisher_t *publisher, size_t *subscription_count)
|
|
|
|
{
|
|
|
|
(void) publisher;
|
|
|
|
*subscription_count = 0;
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_destroy_publisher (rmw_node_t *node, rmw_publisher_t *publisher)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
RET_WRONG_IMPLID (publisher);
|
|
|
|
auto pub = static_cast<CddsPublisher *> (publisher->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (pub != nullptr) {
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_delete (pub->pubh) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to delete writer");
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
delete pub;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_free (const_cast<char *> (publisher->topic_name));
|
2018-07-10 08:14:20 +02:00
|
|
|
publisher->topic_name = nullptr;
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_publisher_free (publisher);
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////// SUBSCRIPTIONS ///////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static CddsSubscription *create_cdds_subscription (const rmw_node_t *node, const rosidl_message_type_support_t *type_supports, const char *topic_name, const rmw_qos_profile_t *qos_policies, bool ignore_local_publications)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID_X (node, return nullptr);
|
|
|
|
RET_NULL_OR_EMPTYSTR_X (topic_name, return nullptr);
|
|
|
|
RET_NULL_X (qos_policies, return nullptr);
|
|
|
|
auto node_impl = static_cast<CddsNode *> (node->data);
|
|
|
|
RET_NULL_X (node_impl, return nullptr);
|
|
|
|
const rosidl_message_type_support_t *type_support = get_typesupport (type_supports);
|
|
|
|
RET_NULL_X (type_support, return nullptr);
|
|
|
|
CddsSubscription *sub = new CddsSubscription ();
|
2018-07-10 08:14:20 +02:00
|
|
|
dds_entity_t topic;
|
|
|
|
dds_qos_t *qos;
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
std::string fqtopic_name = make_fqtopic (ros_topic_prefix, topic_name, "", qos_policies);
|
2018-07-10 08:14:20 +02:00
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
auto sertopic = create_sertopic (fqtopic_name.c_str (), type_support->typesupport_identifier, create_message_type_support (type_support->data, type_support->typesupport_identifier), false);
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((topic = dds_create_topic_arbitrary (gcdds.ppant, sertopic, fqtopic_name.c_str (), nullptr, nullptr, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create topic");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_topic;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((qos = create_readwrite_qos (qos_policies, ignore_local_publications)) == nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_qos;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((sub->subh = dds_create_reader (gcdds.ppant, topic, qos, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create reader");
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_reader;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((sub->rdcondh = dds_create_readcondition (sub->subh, DDS_ANY_STATE)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create readcondition");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_readcond;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete_qos (qos);
|
2018-07-10 08:14:20 +02:00
|
|
|
return sub;
|
2018-07-13 08:52:21 +02:00
|
|
|
fail_readcond:
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_delete (sub->subh) < 0) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED ("rmw_cyclonedds_cpp", "failed to delete reader during error handling");
|
2018-07-13 08:52:21 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_reader:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete_qos (qos);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_qos:
|
|
|
|
/* FIXME: leak topic */
|
|
|
|
fail_topic:
|
|
|
|
delete sub;
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_subscription_t *rmw_create_subscription (const rmw_node_t *node, const rosidl_message_type_support_t *type_supports, const char *topic_name, const rmw_qos_profile_t *qos_policies, bool ignore_local_publications)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
|
|
|
CddsSubscription *sub;
|
|
|
|
rmw_subscription_t *rmw_subscription;
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((sub = create_cdds_subscription (node, type_supports, topic_name, qos_policies, ignore_local_publications)) == nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_common_init;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_subscription = rmw_subscription_allocate ();
|
|
|
|
RET_ALLOC_X (rmw_subscription, goto fail_subscription);
|
2019-05-03 17:12:51 +08:00
|
|
|
rmw_subscription->implementation_identifier = eclipse_cyclonedds_identifier;
|
2018-07-10 08:14:20 +02:00
|
|
|
rmw_subscription->data = sub;
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_subscription->topic_name = reinterpret_cast<const char *> (rmw_allocate (strlen (topic_name) + 1));
|
|
|
|
RET_ALLOC_X (rmw_subscription->topic_name, goto fail_topic_name);
|
|
|
|
memcpy (const_cast<char *> (rmw_subscription->topic_name), topic_name, strlen (topic_name) + 1);
|
2018-07-10 08:14:20 +02:00
|
|
|
return rmw_subscription;
|
|
|
|
fail_topic_name:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_subscription_free (rmw_subscription);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_subscription:
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_delete (sub->rdcondh) < 0) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED ("rmw_cyclonedds_cpp", "failed to delete readcondition during error handling");
|
2018-07-13 08:52:21 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_delete (sub->subh) < 0) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED ("rmw_cyclonedds_cpp", "failed to delete reader during error handling");
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
delete sub;
|
|
|
|
fail_common_init:
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
extern "C" rmw_ret_t rmw_subscription_count_matched_publishers (const rmw_subscription_t *subscription, size_t *publisher_count)
|
|
|
|
{
|
|
|
|
(void) subscription;
|
|
|
|
*publisher_count = 0;
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_destroy_subscription (rmw_node_t *node, rmw_subscription_t *subscription)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
RET_WRONG_IMPLID (subscription);
|
|
|
|
auto sub = static_cast<CddsSubscription *> (subscription->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (sub != nullptr) {
|
2019-04-29 09:33:13 +02:00
|
|
|
clean_waitset_caches ();
|
|
|
|
if (dds_delete (sub->rdcondh) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to delete readcondition");
|
2018-07-13 08:52:21 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_delete (sub->subh) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to delete reader");
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
delete sub;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_free (const_cast<char *> (subscription->topic_name));
|
2018-07-10 08:14:20 +02:00
|
|
|
subscription->topic_name = nullptr;
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_subscription_free (subscription);
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static rmw_ret_t rmw_take_int (const rmw_subscription_t *subscription, void *ros_message, bool *taken, rmw_message_info_t *message_info)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_NULL (taken);
|
|
|
|
RET_NULL (ros_message);
|
|
|
|
RET_WRONG_IMPLID (subscription);
|
|
|
|
CddsSubscription *sub = static_cast<CddsSubscription *> (subscription->data);
|
|
|
|
RET_NULL (sub);
|
2018-07-10 08:14:20 +02:00
|
|
|
dds_sample_info_t info;
|
2019-04-29 09:33:13 +02:00
|
|
|
while (dds_take (sub->subh, &ros_message, &info, 1, 1) == 1) {
|
|
|
|
if (info.valid_data) {
|
2018-07-10 08:14:20 +02:00
|
|
|
if (message_info) {
|
2019-05-03 17:12:51 +08:00
|
|
|
message_info->publisher_gid.implementation_identifier = eclipse_cyclonedds_identifier;
|
2019-04-29 09:33:13 +02:00
|
|
|
memset (message_info->publisher_gid.data, 0, sizeof (message_info->publisher_gid.data));
|
|
|
|
assert (sizeof (info.publication_handle) <= sizeof (message_info->publisher_gid.data));
|
|
|
|
memcpy (message_info->publisher_gid.data, &info.publication_handle, sizeof (info.publication_handle));
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
*taken = true;
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
*taken = false;
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_take (const rmw_subscription_t *subscription, void *ros_message, bool *taken)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
return rmw_take_int (subscription, ros_message, taken, nullptr);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_take_with_info (const rmw_subscription_t *subscription, void *ros_message, bool *taken, rmw_message_info_t *message_info)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
return rmw_take_int (subscription, ros_message, taken, message_info);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-05-03 17:12:51 +08:00
|
|
|
extern "C" rmw_ret_t rmw_take_serialized_message (const rmw_subscription_t *subscription, rmw_serialized_message_t *serialized_message, bool *taken)
|
|
|
|
{
|
|
|
|
(void) subscription; (void) serialized_message; (void) taken;
|
|
|
|
RMW_SET_ERROR_MSG ("rmw_take_serialized_message not implemented");
|
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_take_serialized_message_with_info (const rmw_subscription_t *subscription, rmw_serialized_message_t *serialized_message, bool *taken, rmw_message_info_t *message_info)
|
|
|
|
{
|
|
|
|
(void) subscription; (void) serialized_message; (void) taken; (void) message_info;
|
|
|
|
RMW_SET_ERROR_MSG ("rmw_take_serialized_message_with_info not implemented");
|
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////// GUARDS AND WAITSETS ///////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_guard_condition_t *rmw_create_guard_condition (rmw_context_t *context __attribute__ ((unused)))
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2018-07-13 08:52:21 +02:00
|
|
|
rmw_guard_condition_t *guard_condition_handle;
|
2019-04-29 09:33:13 +02:00
|
|
|
auto *gcond_impl = new CddsGuardCondition ();
|
|
|
|
if (ref_ppant () < 0) {
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_ppant;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((gcond_impl->gcondh = dds_create_guardcondition (gcdds.ppant)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create guardcondition");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_guardcond;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-13 08:52:21 +02:00
|
|
|
guard_condition_handle = new rmw_guard_condition_t;
|
2019-05-03 17:12:51 +08:00
|
|
|
guard_condition_handle->implementation_identifier = eclipse_cyclonedds_identifier;
|
2018-07-13 08:52:21 +02:00
|
|
|
guard_condition_handle->data = gcond_impl;
|
2018-07-10 08:14:20 +02:00
|
|
|
return guard_condition_handle;
|
2018-07-13 08:52:21 +02:00
|
|
|
|
|
|
|
fail_guardcond:
|
2019-04-29 09:33:13 +02:00
|
|
|
unref_ppant ();
|
2018-07-13 08:52:21 +02:00
|
|
|
fail_ppant:
|
2019-04-29 09:33:13 +02:00
|
|
|
delete (gcond_impl);
|
2018-07-13 08:52:21 +02:00
|
|
|
return nullptr;
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_destroy_guard_condition (rmw_guard_condition_t *guard_condition_handle)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_NULL (guard_condition_handle);
|
|
|
|
auto *gcond_impl = static_cast<CddsGuardCondition *> (guard_condition_handle->data);
|
|
|
|
clean_waitset_caches ();
|
|
|
|
dds_delete (gcond_impl->gcondh);
|
|
|
|
unref_ppant ();
|
2018-07-13 08:52:21 +02:00
|
|
|
delete gcond_impl;
|
|
|
|
delete guard_condition_handle;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_trigger_guard_condition (const rmw_guard_condition_t *guard_condition_handle)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (guard_condition_handle);
|
|
|
|
auto *gcond_impl = static_cast<CddsGuardCondition *> (guard_condition_handle->data);
|
|
|
|
dds_set_guardcondition (gcond_impl->gcondh, true);
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_wait_set_t *rmw_create_wait_set (size_t max_conditions)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
(void) max_conditions;
|
|
|
|
rmw_wait_set_t *wait_set = rmw_wait_set_allocate ();
|
2018-07-10 08:14:20 +02:00
|
|
|
CddsWaitset *ws = nullptr;
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_ALLOC_X (wait_set, goto fail_alloc_wait_set);
|
2019-05-03 17:12:51 +08:00
|
|
|
wait_set->implementation_identifier = eclipse_cyclonedds_identifier;
|
2019-04-29 09:33:13 +02:00
|
|
|
wait_set->data = rmw_allocate (sizeof (CddsWaitset));
|
|
|
|
RET_ALLOC_X (wait_set->data, goto fail_alloc_wait_set_data);
|
2018-07-10 08:14:20 +02:00
|
|
|
// This should default-construct the fields of CddsWaitset
|
2019-04-29 09:33:13 +02:00
|
|
|
ws = static_cast<CddsWaitset *> (wait_set->data);
|
|
|
|
RMW_TRY_PLACEMENT_NEW (ws, ws, goto fail_placement_new, CddsWaitset, );
|
2018-07-13 08:52:21 +02:00
|
|
|
if (!ws) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("failed to construct wait set info struct");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_ws;
|
|
|
|
}
|
2018-07-19 16:35:46 +02:00
|
|
|
ws->inuse = false;
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((ws->waitseth = dds_create_waitset (gcdds.ppant)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create waitset");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_waitset;
|
|
|
|
}
|
2018-07-19 16:35:46 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (gcdds.lock);
|
|
|
|
gcdds.waitsets.insert (ws);
|
2018-07-19 16:35:46 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
return wait_set;
|
2018-07-13 08:52:21 +02:00
|
|
|
|
|
|
|
fail_waitset:
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_ws:
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_TRY_DESTRUCTOR_FROM_WITHIN_FAILURE (ws->~CddsWaitset (), ws);
|
2018-07-13 08:52:21 +02:00
|
|
|
fail_placement_new:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_free (wait_set->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_alloc_wait_set_data:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_wait_set_free (wait_set);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_alloc_wait_set:
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_destroy_wait_set (rmw_wait_set_t *wait_set)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (wait_set);
|
2018-07-10 08:14:20 +02:00
|
|
|
auto result = RMW_RET_OK;
|
2019-04-29 09:33:13 +02:00
|
|
|
auto ws = static_cast<CddsWaitset *> (wait_set->data);
|
|
|
|
RET_NULL (ws);
|
|
|
|
dds_delete (ws->waitseth);
|
2018-07-19 16:35:46 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (gcdds.lock);
|
|
|
|
gcdds.waitsets.erase (ws);
|
2018-07-19 16:35:46 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_TRY_DESTRUCTOR (ws->~CddsWaitset (), ws, result = RMW_RET_ERROR);
|
|
|
|
rmw_free (wait_set->data);
|
|
|
|
rmw_wait_set_free (wait_set);
|
2018-07-10 08:14:20 +02:00
|
|
|
return result;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-19 16:35:46 +02:00
|
|
|
template<typename T>
|
2019-04-29 09:33:13 +02:00
|
|
|
static bool require_reattach (const std::vector<T *>& cached, size_t count, void **ary)
|
2018-07-19 16:35:46 +02:00
|
|
|
{
|
|
|
|
if (ary == nullptr || count == 0) {
|
2019-04-29 09:33:13 +02:00
|
|
|
return (cached.size () != 0);
|
|
|
|
} else if (count != cached.size ()) {
|
2018-07-19 16:35:46 +02:00
|
|
|
return true;
|
|
|
|
} else {
|
2019-04-29 09:33:13 +02:00
|
|
|
return (memcmp (static_cast<const void *> (cached.data ()), static_cast<void *> (ary), count * sizeof (void *)) != 0);
|
2018-07-19 16:35:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static void waitset_detach (CddsWaitset *ws)
|
2018-07-19 16:35:46 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
for (auto&& x : ws->subs) dds_waitset_detach (ws->waitseth, x->rdcondh);
|
|
|
|
for (auto&& x : ws->gcs) dds_waitset_detach (ws->waitseth, x->gcondh);
|
|
|
|
for (auto&& x : ws->srvs) dds_waitset_detach (ws->waitseth, x->service.sub->rdcondh);
|
|
|
|
for (auto&& x : ws->cls) dds_waitset_detach (ws->waitseth, x->client.sub->rdcondh);
|
|
|
|
ws->subs.resize (0);
|
|
|
|
ws->gcs.resize (0);
|
|
|
|
ws->srvs.resize (0);
|
|
|
|
ws->cls.resize (0);
|
2018-07-19 16:35:46 +02:00
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static void clean_waitset_caches ()
|
2018-07-19 16:35:46 +02:00
|
|
|
{
|
|
|
|
/* Called whenever a subscriber, guard condition, service or client is deleted (as these may
|
|
|
|
have been cached in a waitset), and drops all cached entities from all waitsets (just to keep
|
|
|
|
life simple). I'm assuming one is not allowed to delete an entity while it is still being
|
|
|
|
used ... */
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (gcdds.lock);
|
2018-07-19 16:35:46 +02:00
|
|
|
for (auto&& ws : gcdds.waitsets) {
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (ws->lock);
|
2018-07-19 16:35:46 +02:00
|
|
|
if (!ws->inuse) {
|
2019-04-29 09:33:13 +02:00
|
|
|
waitset_detach (ws);
|
2018-07-19 16:35:46 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_wait (rmw_subscriptions_t *subs, rmw_guard_conditions_t *gcs, rmw_services_t *srvs, rmw_clients_t *cls, rmw_wait_set_t *wait_set, const rmw_time_t *wait_timeout)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_NULL (wait_set);
|
|
|
|
CddsWaitset *ws = static_cast<CddsWaitset *> (wait_set->data);
|
|
|
|
RET_NULL (ws);
|
2018-07-19 16:35:46 +02:00
|
|
|
|
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (ws->lock);
|
2018-07-19 16:35:46 +02:00
|
|
|
if (ws->inuse) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("concurrent calls to rmw_wait on a single waitset is not supported");
|
2018-07-19 16:35:46 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
ws->inuse = true;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
if (require_reattach (ws->subs, subs ? subs->subscriber_count : 0, subs ? subs->subscribers : nullptr) ||
|
|
|
|
require_reattach (ws->gcs, gcs ? gcs->guard_condition_count : 0, gcs ? gcs->guard_conditions : nullptr) ||
|
|
|
|
require_reattach (ws->srvs, srvs ? srvs->service_count : 0, srvs ? srvs->services : nullptr) ||
|
|
|
|
require_reattach (ws->cls, cls ? cls->client_count : 0, cls ? cls->clients : nullptr)) {
|
2018-07-19 16:35:46 +02:00
|
|
|
size_t nelems = 0;
|
2019-04-29 09:33:13 +02:00
|
|
|
waitset_detach (ws);
|
2018-07-19 16:35:46 +02:00
|
|
|
#define ATTACH(type, var, name, cond) do { \
|
2019-04-29 09:33:13 +02:00
|
|
|
ws->var.resize (0); \
|
2018-07-19 16:35:46 +02:00
|
|
|
if (var) { \
|
2019-04-29 09:33:13 +02:00
|
|
|
ws->var.reserve (var->name##_count); \
|
2018-07-19 16:35:46 +02:00
|
|
|
for (size_t i = 0; i < var->name##_count; i++) { \
|
2019-04-29 09:33:13 +02:00
|
|
|
auto x = static_cast<type *> (var->name##s[i]); \
|
|
|
|
ws->var.push_back (x); \
|
|
|
|
dds_waitset_attach (ws->waitseth, x->cond, nelems); \
|
2018-07-19 16:35:46 +02:00
|
|
|
nelems++; \
|
|
|
|
} \
|
2018-07-13 08:52:21 +02:00
|
|
|
} \
|
2018-07-19 16:35:46 +02:00
|
|
|
} while (0)
|
2019-04-29 09:33:13 +02:00
|
|
|
ATTACH (CddsSubscription, subs, subscriber, rdcondh);
|
|
|
|
ATTACH (CddsGuardCondition, gcs, guard_condition, gcondh);
|
|
|
|
ATTACH (CddsService, srvs, service, service.sub->rdcondh);
|
|
|
|
ATTACH (CddsClient, cls, client, client.sub->rdcondh);
|
2018-07-13 08:52:21 +02:00
|
|
|
#undef ATTACH
|
2019-04-29 09:33:13 +02:00
|
|
|
ws->trigs.reserve (nelems + 1);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-19 16:35:46 +02:00
|
|
|
|
|
|
|
const dds_duration_t timeout =
|
2019-04-29 09:33:13 +02:00
|
|
|
(wait_timeout == NULL) ? DDS_NEVER : (dds_duration_t) wait_timeout->sec * 1000000000 + wait_timeout->nsec;
|
|
|
|
const dds_return_t ntrig = dds_waitset_wait (ws->waitseth, ws->trigs.data (), ws->trigs.capacity (), timeout);
|
|
|
|
ws->trigs.resize (ntrig);
|
|
|
|
std::sort (ws->trigs.begin (), ws->trigs.end ());
|
|
|
|
ws->trigs.push_back ((dds_attach_t) -1);
|
2018-07-19 16:35:46 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
long trig_idx = 0;
|
|
|
|
bool dummy;
|
|
|
|
size_t nelems = 0;
|
|
|
|
#define DETACH(type, var, name, cond, on_triggered) do { \
|
|
|
|
if (var) { \
|
|
|
|
for (size_t i = 0; i < var->name##_count; i++) { \
|
2019-04-29 09:33:13 +02:00
|
|
|
auto x = static_cast<type *> (var->name##s[i]); \
|
|
|
|
/*dds_waitset_detach (ws->waitseth, x->cond);*/ \
|
|
|
|
if (ws->trigs[trig_idx] == (long) nelems) { \
|
2018-07-19 16:35:46 +02:00
|
|
|
on_triggered; \
|
|
|
|
trig_idx++; \
|
|
|
|
} else { \
|
|
|
|
var->name##s[i] = nullptr; \
|
|
|
|
} \
|
|
|
|
nelems++; \
|
2018-07-13 08:52:21 +02:00
|
|
|
} \
|
|
|
|
} \
|
2018-07-19 16:35:46 +02:00
|
|
|
} while (0)
|
2019-04-29 09:33:13 +02:00
|
|
|
DETACH (CddsSubscription, subs, subscriber, rdcondh, (void) x);
|
|
|
|
DETACH (CddsGuardCondition, gcs, guard_condition, gcondh, dds_take_guardcondition (x->gcondh, &dummy));
|
|
|
|
DETACH (CddsService, srvs, service, service.sub->rdcondh, (void) x);
|
|
|
|
DETACH (CddsClient, cls, client, client.sub->rdcondh, (void) x);
|
2018-07-13 08:52:21 +02:00
|
|
|
#undef DETACH
|
2018-07-19 16:35:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
std::lock_guard<std::mutex> lock (ws->lock);
|
2018-07-19 16:35:46 +02:00
|
|
|
ws->inuse = false;
|
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
return (ws->trigs.size () == 0) ? RMW_RET_TIMEOUT : RMW_RET_OK;
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////// CLIENTS AND SERVERS ///////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static rmw_ret_t rmw_take_response_request (CddsCS *cs, rmw_request_id_t *request_header, void *ros_data, bool *taken, dds_instance_handle_t srcfilter)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_NULL (taken);
|
|
|
|
RET_NULL (ros_data);
|
|
|
|
RET_NULL (request_header);
|
|
|
|
cdds_request_wrapper_t wrap;
|
2018-07-10 08:14:20 +02:00
|
|
|
dds_sample_info_t info;
|
2019-04-29 09:33:13 +02:00
|
|
|
wrap.data = ros_data;
|
|
|
|
void *wrap_ptr = static_cast<void *> (&wrap);
|
|
|
|
while (dds_take (cs->sub->subh, &wrap_ptr, &info, 1, 1) == 1) {
|
2018-07-10 08:14:20 +02:00
|
|
|
if (info.valid_data) {
|
2019-04-29 09:33:13 +02:00
|
|
|
memset (request_header, 0, sizeof (wrap.header));
|
|
|
|
assert (sizeof (wrap.header.guid) < sizeof (wrap.header.guid));
|
|
|
|
memcpy (request_header->writer_guid, &wrap.header.guid, sizeof (wrap.header.guid));
|
|
|
|
request_header->sequence_number = wrap.header.seq;
|
|
|
|
if (srcfilter == 0 || srcfilter == wrap.header.guid) {
|
2018-07-10 08:14:20 +02:00
|
|
|
*taken = true;
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
*taken = false;
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_take_response (const rmw_client_t *client, rmw_request_id_t *request_header, void *ros_response, bool *taken)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (client);
|
|
|
|
auto info = static_cast<CddsClient *> (client->data);
|
|
|
|
return rmw_take_response_request (&info->client, request_header, ros_response, taken, info->client.pub->pubiid);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_take_request (const rmw_service_t *service, rmw_request_id_t *request_header, void *ros_request, bool *taken)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (service);
|
|
|
|
auto info = static_cast<CddsService *> (service->data);
|
|
|
|
return rmw_take_response_request (&info->service, request_header, ros_request, taken, 0);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static rmw_ret_t rmw_send_response_request (CddsCS *cs, const cdds_request_header_t& header, const void *ros_data)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
const cdds_request_wrapper_t wrap = { header, const_cast<void *> (ros_data) };
|
|
|
|
if (dds_write (cs->pub->pubh, static_cast<const void *> (&wrap)) >= 0) {
|
|
|
|
return RMW_RET_OK;
|
2018-07-10 08:14:20 +02:00
|
|
|
} else {
|
2019-04-29 09:33:13 +02:00
|
|
|
/* FIXME: what is the expected behavior when it times out? */
|
|
|
|
RMW_SET_ERROR_MSG ("cannot publish data");
|
|
|
|
//return RMW_RET_ERROR;
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_send_response (const rmw_service_t *service, rmw_request_id_t *request_header, void *ros_response)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (service);
|
|
|
|
RET_NULL (request_header);
|
|
|
|
RET_NULL (ros_response);
|
|
|
|
CddsService *info = static_cast<CddsService *> (service->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
cdds_request_header_t header;
|
2019-04-29 09:33:13 +02:00
|
|
|
memcpy (&header.guid, request_header->writer_guid, sizeof (header.guid));
|
2018-07-10 08:14:20 +02:00
|
|
|
header.seq = request_header->sequence_number;
|
2019-04-29 09:33:13 +02:00
|
|
|
return rmw_send_response_request (&info->service, header, ros_response);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_send_request (const rmw_client_t *client, const void *ros_request, int64_t *sequence_id)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
|
|
|
static std::atomic_uint next_request_id;
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (client);
|
|
|
|
RET_NULL (ros_request);
|
|
|
|
RET_NULL (sequence_id);
|
|
|
|
auto info = static_cast<CddsClient *> (client->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
cdds_request_header_t header;
|
|
|
|
header.guid = info->client.pub->pubiid;
|
|
|
|
header.seq = *sequence_id = next_request_id++;
|
2019-04-29 09:33:13 +02:00
|
|
|
return rmw_send_response_request (&info->client, header, ros_request);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static const rosidl_service_type_support_t *get_service_typesupport (const rosidl_service_type_support_t *type_supports)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
|
|
|
const rosidl_service_type_support_t *ts;
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((ts = get_service_typesupport_handle (type_supports, rosidl_typesupport_introspection_c__identifier)) != nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
return ts;
|
2019-04-29 09:33:13 +02:00
|
|
|
} else if ((ts = get_service_typesupport_handle (type_supports, rosidl_typesupport_introspection_cpp::typesupport_identifier)) != nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
return ts;
|
|
|
|
} else {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("service type support not from this implementation");
|
2018-07-10 08:14:20 +02:00
|
|
|
return nullptr;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static rmw_ret_t rmw_init_cs (CddsCS *cs, const rmw_node_t *node, const rosidl_service_type_support_t *type_supports, const char *service_name, const rmw_qos_profile_t *qos_policies, bool is_service)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
RET_NULL_OR_EMPTYSTR (service_name);
|
|
|
|
RET_NULL (qos_policies);
|
|
|
|
auto node_impl = static_cast<CddsNode *> (node->data);
|
|
|
|
RET_NULL (node_impl);
|
|
|
|
const rosidl_service_type_support_t *type_support = get_service_typesupport (type_supports);
|
|
|
|
RET_NULL (type_support);
|
|
|
|
|
|
|
|
auto pub = new CddsPublisher ();
|
|
|
|
auto sub = new CddsSubscription ();
|
2018-07-10 08:14:20 +02:00
|
|
|
std::string subtopic_name, pubtopic_name;
|
2019-04-29 09:33:13 +02:00
|
|
|
void *pub_type_support, *sub_type_support;
|
2018-07-10 08:14:20 +02:00
|
|
|
if (is_service) {
|
2019-04-29 09:33:13 +02:00
|
|
|
sub_type_support = create_request_type_support (type_support->data, type_support->typesupport_identifier);
|
|
|
|
pub_type_support = create_response_type_support (type_support->data, type_support->typesupport_identifier);
|
|
|
|
subtopic_name = make_fqtopic (ros_service_requester_prefix, service_name, "_request", qos_policies);
|
|
|
|
pubtopic_name = make_fqtopic (ros_service_response_prefix, service_name, "_reply", qos_policies);
|
2018-07-10 08:14:20 +02:00
|
|
|
} else {
|
2019-04-29 09:33:13 +02:00
|
|
|
pub_type_support = create_request_type_support (type_support->data, type_support->typesupport_identifier);
|
|
|
|
sub_type_support = create_response_type_support (type_support->data, type_support->typesupport_identifier);
|
|
|
|
pubtopic_name = make_fqtopic (ros_service_requester_prefix, service_name, "_request", qos_policies);
|
|
|
|
subtopic_name = make_fqtopic (ros_service_response_prefix, service_name, "_reply", qos_policies);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
RCUTILS_LOG_DEBUG_NAMED ("rmw_cyclonedds_cpp", "************ %s Details *********", is_service ? "Service" : "Client");
|
|
|
|
RCUTILS_LOG_DEBUG_NAMED ("rmw_cyclonedds_cpp", "Sub Topic %s", subtopic_name.c_str ());
|
|
|
|
RCUTILS_LOG_DEBUG_NAMED ("rmw_cyclonedds_cpp", "Pub Topic %s", pubtopic_name.c_str ());
|
|
|
|
RCUTILS_LOG_DEBUG_NAMED ("rmw_cyclonedds_cpp", "***********");
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_entity_t pubtopic, subtopic;
|
|
|
|
|
|
|
|
auto pub_st = create_sertopic (pubtopic_name.c_str (), type_support->typesupport_identifier, pub_type_support, true);
|
|
|
|
auto sub_st = create_sertopic (subtopic_name.c_str (), type_support->typesupport_identifier, sub_type_support, true);
|
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
dds_qos_t *qos;
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((pubtopic = dds_create_topic_arbitrary (gcdds.ppant, pub_st, pubtopic_name.c_str (), nullptr, nullptr, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create topic");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_pubtopic;
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((subtopic = dds_create_topic_arbitrary (gcdds.ppant, sub_st, subtopic_name.c_str (), nullptr, nullptr, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create topic");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_subtopic;
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((qos = dds_create_qos ()) == nullptr) {
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_qos;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_qset_reliability (qos, DDS_RELIABILITY_RELIABLE, DDS_SECS (1));
|
|
|
|
dds_qset_history (qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED);
|
|
|
|
if ((pub->pubh = dds_create_writer (gcdds.ppant, pubtopic, qos, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create writer");
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_writer;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((sub->subh = dds_create_reader (gcdds.ppant, subtopic, qos, nullptr)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create reader");
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_reader;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if ((sub->rdcondh = dds_create_readcondition (sub->subh, DDS_ANY_STATE)) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to create readcondition");
|
2018-07-13 08:52:21 +02:00
|
|
|
goto fail_readcond;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
if (dds_get_instance_handle (pub->pubh, &pub->pubiid) < 0) {
|
|
|
|
RMW_SET_ERROR_MSG ("failed to get instance handle for writer");
|
2018-07-10 08:14:20 +02:00
|
|
|
goto fail_instance_handle;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete_qos (qos);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
cs->pub = pub;
|
|
|
|
cs->sub = sub;
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_instance_handle:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete (sub->rdcondh);
|
2018-07-13 08:52:21 +02:00
|
|
|
fail_readcond:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete (sub->subh);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_reader:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete (pub->pubh);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_writer:
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete_qos (qos);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_qos:
|
|
|
|
/* leak subtopic */
|
|
|
|
fail_subtopic:
|
|
|
|
/* leak pubtopic */
|
|
|
|
fail_pubtopic:
|
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
static void rmw_fini_cs (CddsCS *cs)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
dds_delete (cs->sub->rdcondh);
|
|
|
|
dds_delete (cs->sub->subh);
|
|
|
|
dds_delete (cs->pub->pubh);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_client_t *rmw_create_client (const rmw_node_t *node, const rosidl_service_type_support_t *type_supports, const char *service_name, const rmw_qos_profile_t *qos_policies)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
CddsClient *info = new CddsClient ();
|
|
|
|
if (rmw_init_cs (&info->client, node, type_supports, service_name, qos_policies, false) != RMW_RET_OK) {
|
|
|
|
delete (info);
|
2018-07-09 13:22:25 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_client_t *rmw_client = rmw_client_allocate ();
|
|
|
|
RET_NULL_X (rmw_client, goto fail_client);
|
2019-05-03 17:12:51 +08:00
|
|
|
rmw_client->implementation_identifier = eclipse_cyclonedds_identifier;
|
2018-07-10 08:14:20 +02:00
|
|
|
rmw_client->data = info;
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_client->service_name = reinterpret_cast<const char *> (rmw_allocate (strlen (service_name) + 1));
|
|
|
|
RET_NULL_X (rmw_client->service_name, goto fail_service_name);
|
|
|
|
memcpy (const_cast<char *> (rmw_client->service_name), service_name, strlen (service_name) + 1);
|
2018-07-10 08:14:20 +02:00
|
|
|
return rmw_client;
|
|
|
|
fail_service_name:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_client_free (rmw_client);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_client:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_fini_cs (&info->client);
|
2018-07-10 08:14:20 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_destroy_client (rmw_node_t *node, rmw_client_t *client)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
RET_WRONG_IMPLID (client);
|
|
|
|
auto info = static_cast<CddsClient *> (client->data);
|
|
|
|
clean_waitset_caches ();
|
|
|
|
rmw_fini_cs (&info->client);
|
|
|
|
rmw_free (const_cast<char *> (client->service_name));
|
|
|
|
rmw_client_free (client);
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_service_t *rmw_create_service (const rmw_node_t *node, const rosidl_service_type_support_t *type_supports, const char *service_name, const rmw_qos_profile_t *qos_policies)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
CddsService *info = new CddsService ();
|
|
|
|
if (rmw_init_cs (&info->service, node, type_supports, service_name, qos_policies, true) != RMW_RET_OK) {
|
|
|
|
delete (info);
|
2018-07-09 13:22:25 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_service_t *rmw_service = rmw_service_allocate ();
|
|
|
|
RET_NULL_X (rmw_service, goto fail_service);
|
2019-05-03 17:12:51 +08:00
|
|
|
rmw_service->implementation_identifier = eclipse_cyclonedds_identifier;
|
2018-07-10 08:14:20 +02:00
|
|
|
rmw_service->data = info;
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_service->service_name = reinterpret_cast<const char *> (rmw_allocate (strlen (service_name) + 1));
|
|
|
|
RET_NULL_X (rmw_service->service_name, goto fail_service_name);
|
|
|
|
memcpy (const_cast<char *> (rmw_service->service_name), service_name, strlen (service_name) + 1);
|
2018-07-10 08:14:20 +02:00
|
|
|
return rmw_service;
|
|
|
|
fail_service_name:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_service_free (rmw_service);
|
2018-07-10 08:14:20 +02:00
|
|
|
fail_service:
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_fini_cs (&info->service);
|
2018-07-10 08:14:20 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_destroy_service (rmw_node_t *node, rmw_service_t *service)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
RET_WRONG_IMPLID (service);
|
|
|
|
auto info = static_cast<CddsService *> (service->data);
|
|
|
|
clean_waitset_caches ();
|
|
|
|
rmw_fini_cs (&info->service);
|
|
|
|
rmw_free (const_cast<char *> (service->service_name));
|
|
|
|
rmw_service_free (service);
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////// INTROSPECTION ///////////
|
|
|
|
/////////// ///////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_get_node_names (const rmw_node_t *node, rcutils_string_array_t *node_names, rcutils_string_array_t *node_namespaces)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2018-07-09 13:22:25 +02:00
|
|
|
#if 0 // NIY
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
if (rmw_check_zero_rmw_string_array (node_names) != RMW_RET_OK) {
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
auto impl = static_cast<CddsNode *> (node->data);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
// FIXME: sorry, can't do it with current Zenoh
|
|
|
|
auto participant_names = std::vector<std::string>{};
|
2019-04-29 09:33:13 +02:00
|
|
|
rcutils_allocator_t allocator = rcutils_get_default_allocator ();
|
2018-07-10 08:14:20 +02:00
|
|
|
rcutils_ret_t rcutils_ret =
|
2019-04-29 09:33:13 +02:00
|
|
|
rcutils_string_array_init (node_names, participant_names.size (), &allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (rcutils_ret != RCUTILS_RET_OK) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG (rcutils_get_error_string_safe ())
|
|
|
|
return rmw_convert_rcutils_ret_to_rmw_ret (rcutils_ret);
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
for (size_t i = 0; i < participant_names.size (); ++i) {
|
|
|
|
node_names->data[i] = rcutils_strdup (participant_names[i].c_str (), allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!node_names->data[i]) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("failed to allocate memory for node name")
|
|
|
|
rcutils_ret = rcutils_string_array_fini (node_names);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (rcutils_ret != RCUTILS_RET_OK) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RCUTILS_LOG_ERROR_NAMED (
|
2018-07-10 08:14:20 +02:00
|
|
|
"rmw_cyclonedds_cpp",
|
2019-04-29 09:33:13 +02:00
|
|
|
"failed to cleanup during error handling: %s", rcutils_get_error_string_safe ());
|
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_BAD_ALLOC;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
#else
|
2019-04-29 09:33:13 +02:00
|
|
|
(void) node; (void) node_names; (void) node_namespaces;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_TIMEOUT;
|
2018-07-09 13:22:25 +02:00
|
|
|
#endif
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_get_topic_names_and_types (const rmw_node_t *node, rcutils_allocator_t *allocator, bool no_demangle, rmw_names_and_types_t *topic_names_and_types)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2018-07-09 13:22:25 +02:00
|
|
|
#if 0 // NIY
|
2019-04-29 09:33:13 +02:00
|
|
|
RET_NULL (allocator);
|
|
|
|
RET_WRONG_IMPLID (node);
|
|
|
|
rmw_ret_t ret = rmw_names_and_types_check_zero (topic_names_and_types);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (ret != RMW_RET_OK) {
|
|
|
|
return ret;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
auto impl = static_cast<CustomParticipantInfo *> (node->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
|
|
|
|
// Access the slave Listeners, which are the ones that have the topicnamesandtypes member
|
|
|
|
// Get info from publisher and subscriber
|
|
|
|
// Combined results from the two lists
|
|
|
|
std::map<std::string, std::set<std::string>> topics;
|
|
|
|
{
|
|
|
|
ReaderInfo * slave_target = impl->secondarySubListener;
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.lock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
for (auto it : slave_target->topicNtypes) {
|
2019-04-29 09:33:13 +02:00
|
|
|
if (!no_demangle && _get_ros_prefix_if_exists (it.first) != ros_topic_prefix) {
|
2018-07-10 08:14:20 +02:00
|
|
|
// if we are demangling and this is not prefixed with rt/, skip it
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (auto & itt : it.second) {
|
2019-04-29 09:33:13 +02:00
|
|
|
topics[it.first].insert (itt);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.unlock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
{
|
|
|
|
WriterInfo * slave_target = impl->secondaryPubListener;
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.lock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
for (auto it : slave_target->topicNtypes) {
|
2019-04-29 09:33:13 +02:00
|
|
|
if (!no_demangle && _get_ros_prefix_if_exists (it.first) != ros_topic_prefix) {
|
2018-07-10 08:14:20 +02:00
|
|
|
// if we are demangling and this is not prefixed with rt/, skip it
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (auto & itt : it.second) {
|
2019-04-29 09:33:13 +02:00
|
|
|
topics[it.first].insert (itt);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.unlock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
// Copy data to results handle
|
2019-04-29 09:33:13 +02:00
|
|
|
if (topics.size () > 0) {
|
2018-07-10 08:14:20 +02:00
|
|
|
// Setup string array to store names
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_ret_t rmw_ret = rmw_names_and_types_init (topic_names_and_types, topics.size (), allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (rmw_ret != RMW_RET_OK) {
|
|
|
|
return rmw_ret;
|
|
|
|
}
|
|
|
|
// Setup cleanup function, in case of failure below
|
|
|
|
auto fail_cleanup = [&topic_names_and_types]() {
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_ret_t rmw_ret = rmw_names_and_types_fini (topic_names_and_types);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (rmw_ret != RMW_RET_OK) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RCUTILS_LOG_ERROR_NAMED (
|
2018-07-10 08:14:20 +02:00
|
|
|
"rmw_cyclonedds_cpp",
|
2019-04-29 09:33:13 +02:00
|
|
|
"error during report of error: %s", rmw_get_error_string_safe ());
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
};
|
2018-07-10 08:14:20 +02:00
|
|
|
// Setup demangling functions based on no_demangle option
|
|
|
|
auto demangle_topic = _demangle_if_ros_topic;
|
|
|
|
auto demangle_type = _demangle_if_ros_type;
|
|
|
|
if (no_demangle) {
|
|
|
|
auto noop = [](const std::string & in) {
|
|
|
|
return in;
|
|
|
|
};
|
|
|
|
demangle_topic = noop;
|
|
|
|
demangle_type = noop;
|
|
|
|
}
|
|
|
|
// For each topic, store the name, initialize the string array for types, and store all types
|
|
|
|
size_t index = 0;
|
|
|
|
for (const auto & topic_n_types : topics) {
|
|
|
|
// Duplicate and store the topic_name
|
2019-04-29 09:33:13 +02:00
|
|
|
char * topic_name = rcutils_strdup (demangle_topic (topic_n_types.first).c_str (), *allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!topic_name) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG_ALLOC ("failed to allocate memory for topic name", *allocator);
|
|
|
|
fail_cleanup ();
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_BAD_ALLOC;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
topic_names_and_types->names.data[index] = topic_name;
|
|
|
|
// Setup storage for types
|
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
rcutils_ret_t rcutils_ret = rcutils_string_array_init (
|
2018-07-10 08:14:20 +02:00
|
|
|
&topic_names_and_types->types[index],
|
2019-04-29 09:33:13 +02:00
|
|
|
topic_n_types.second.size (),
|
2018-07-10 08:14:20 +02:00
|
|
|
allocator);
|
|
|
|
if (rcutils_ret != RCUTILS_RET_OK) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG (rcutils_get_error_string_safe ())
|
|
|
|
fail_cleanup ();
|
|
|
|
return rmw_convert_rcutils_ret_to_rmw_ret (rcutils_ret);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
// Duplicate and store each type for the topic
|
|
|
|
size_t type_index = 0;
|
|
|
|
for (const auto & type : topic_n_types.second) {
|
2019-04-29 09:33:13 +02:00
|
|
|
char * type_name = rcutils_strdup (demangle_type (type).c_str (), *allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!type_name) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG_ALLOC ("failed to allocate memory for type name", *allocator)
|
|
|
|
fail_cleanup ();
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_BAD_ALLOC;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
topic_names_and_types->types[index].data[type_index] = type_name;
|
|
|
|
++type_index;
|
|
|
|
} // for each type
|
|
|
|
++index;
|
|
|
|
} // for each topic
|
|
|
|
}
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
#else
|
2019-04-29 09:33:13 +02:00
|
|
|
(void) node; (void) allocator; (void) no_demangle; (void) topic_names_and_types;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_TIMEOUT;
|
2018-07-09 13:22:25 +02:00
|
|
|
#endif
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_get_service_names_and_types (const rmw_node_t *node, rcutils_allocator_t *allocator, rmw_names_and_types_t *service_names_and_types)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2018-07-09 13:22:25 +02:00
|
|
|
#if 0 // NIY
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!allocator) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("allocator is null")
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_INVALID_ARGUMENT;
|
|
|
|
}
|
|
|
|
if (!node) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG_ALLOC ("null node handle", *allocator)
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_INVALID_ARGUMENT;
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_ret_t ret = rmw_names_and_types_check_zero (service_names_and_types);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (ret != RMW_RET_OK) {
|
|
|
|
return ret;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
// Get participant pointer from node
|
2019-05-03 17:12:51 +08:00
|
|
|
if (node->implementation_identifier != eclipse_cyclonedds_identifier) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG_ALLOC ("node handle not from this implementation", *allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
auto impl = static_cast<CustomParticipantInfo *> (node->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
|
|
|
|
// Access the slave Listeners, which are the ones that have the topicnamesandtypes member
|
|
|
|
// Get info from publisher and subscriber
|
|
|
|
// Combined results from the two lists
|
|
|
|
std::map<std::string, std::set<std::string>> services;
|
|
|
|
{
|
|
|
|
ReaderInfo * slave_target = impl->secondarySubListener;
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.lock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
for (auto it : slave_target->topicNtypes) {
|
2019-04-29 09:33:13 +02:00
|
|
|
std::string service_name = _demangle_service_from_topic (it.first);
|
|
|
|
if (!service_name.length ()) {
|
2018-07-10 08:14:20 +02:00
|
|
|
// not a service
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (auto & itt : it.second) {
|
2019-04-29 09:33:13 +02:00
|
|
|
std::string service_type = _demangle_service_type_only (itt);
|
|
|
|
if (service_type.length ()) {
|
|
|
|
services[service_name].insert (service_type);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.unlock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
{
|
|
|
|
WriterInfo * slave_target = impl->secondaryPubListener;
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.lock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
for (auto it : slave_target->topicNtypes) {
|
2019-04-29 09:33:13 +02:00
|
|
|
std::string service_name = _demangle_service_from_topic (it.first);
|
|
|
|
if (!service_name.length ()) {
|
2018-07-10 08:14:20 +02:00
|
|
|
// not a service
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (auto & itt : it.second) {
|
2019-04-29 09:33:13 +02:00
|
|
|
std::string service_type = _demangle_service_type_only (itt);
|
|
|
|
if (service_type.length ()) {
|
|
|
|
services[service_name].insert (service_type);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.unlock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
// Fill out service_names_and_types
|
2019-04-29 09:33:13 +02:00
|
|
|
if (services.size ()) {
|
2018-07-10 08:14:20 +02:00
|
|
|
// Setup string array to store names
|
|
|
|
rmw_ret_t rmw_ret =
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_names_and_types_init (service_names_and_types, services.size (), allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (rmw_ret != RMW_RET_OK) {
|
|
|
|
return rmw_ret;
|
|
|
|
}
|
|
|
|
// Setup cleanup function, in case of failure below
|
|
|
|
auto fail_cleanup = [&service_names_and_types]() {
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_ret_t rmw_ret = rmw_names_and_types_fini (service_names_and_types);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (rmw_ret != RMW_RET_OK) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RCUTILS_LOG_ERROR_NAMED (
|
2018-07-10 08:14:20 +02:00
|
|
|
"rmw_cyclonedds_cpp",
|
2019-04-29 09:33:13 +02:00
|
|
|
"error during report of error: %s", rmw_get_error_string_safe ());
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
// For each service, store the name, initialize the string array for types, and store all types
|
|
|
|
size_t index = 0;
|
|
|
|
for (const auto & service_n_types : services) {
|
|
|
|
// Duplicate and store the service_name
|
2019-04-29 09:33:13 +02:00
|
|
|
char * service_name = rcutils_strdup (service_n_types.first.c_str (), *allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!service_name) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG_ALLOC ("failed to allocate memory for service name", *allocator);
|
|
|
|
fail_cleanup ();
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_BAD_ALLOC;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
service_names_and_types->names.data[index] = service_name;
|
|
|
|
// Setup storage for types
|
|
|
|
{
|
2019-04-29 09:33:13 +02:00
|
|
|
rcutils_ret_t rcutils_ret = rcutils_string_array_init (
|
2018-07-10 08:14:20 +02:00
|
|
|
&service_names_and_types->types[index],
|
2019-04-29 09:33:13 +02:00
|
|
|
service_n_types.second.size (),
|
2018-07-10 08:14:20 +02:00
|
|
|
allocator);
|
|
|
|
if (rcutils_ret != RCUTILS_RET_OK) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG (rcutils_get_error_string_safe ())
|
|
|
|
fail_cleanup ();
|
|
|
|
return rmw_convert_rcutils_ret_to_rmw_ret (rcutils_ret);
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
// Duplicate and store each type for the service
|
|
|
|
size_t type_index = 0;
|
|
|
|
for (const auto & type : service_n_types.second) {
|
2019-04-29 09:33:13 +02:00
|
|
|
char * type_name = rcutils_strdup (type.c_str (), *allocator);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!type_name) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG_ALLOC ("failed to allocate memory for type name", *allocator)
|
|
|
|
fail_cleanup ();
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_BAD_ALLOC;
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
service_names_and_types->types[index].data[type_index] = type_name;
|
|
|
|
++type_index;
|
|
|
|
} // for each type
|
|
|
|
++index;
|
|
|
|
} // for each service
|
|
|
|
}
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
#else
|
2019-04-29 09:33:13 +02:00
|
|
|
(void) node; (void) allocator; (void) service_names_and_types;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_TIMEOUT;
|
2018-07-09 13:22:25 +02:00
|
|
|
#endif
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_service_server_is_available (const rmw_node_t * node, const rmw_client_t * client, bool * is_available)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2018-07-09 13:22:25 +02:00
|
|
|
#if 0 // NIY
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!node) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("node handle is null");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_CHECK_TYPE_IDENTIFIERS_MATCH (
|
2018-07-10 08:14:20 +02:00
|
|
|
node handle,
|
2019-05-03 17:12:51 +08:00
|
|
|
node->implementation_identifier, eclipse_cyclonedds_identifier,
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!client) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("client handle is null");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!is_available) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("is_available is null");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
auto client_info = static_cast<CustomClientInfo *> (client->data);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!client_info) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("client info handle is null");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
auto pub_topic_name =
|
2019-04-29 09:33:13 +02:00
|
|
|
client_info->request_publisher_->getAttributes ().topic.getTopicName ();
|
2018-07-10 08:14:20 +02:00
|
|
|
auto pub_partitions =
|
2019-04-29 09:33:13 +02:00
|
|
|
client_info->request_publisher_->getAttributes ().qos.m_partition.getNames ();
|
2018-07-10 08:14:20 +02:00
|
|
|
// every rostopic has exactly 1 partition field set
|
2019-04-29 09:33:13 +02:00
|
|
|
if (pub_partitions.size () != 1) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED (
|
2018-07-10 08:14:20 +02:00
|
|
|
"rmw_cyclonedds_cpp",
|
2019-04-29 09:33:13 +02:00
|
|
|
"Topic %s is not a ros topic", pub_topic_name.c_str ())
|
|
|
|
RMW_SET_ERROR_MSG ((std::string (pub_topic_name) + " is a non-ros topic\n").c_str ());
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
auto pub_fqdn = pub_partitions[0] + "/" + pub_topic_name;
|
2019-04-29 09:33:13 +02:00
|
|
|
pub_fqdn = _demangle_if_ros_topic (pub_fqdn);
|
2018-07-10 08:14:20 +02:00
|
|
|
|
|
|
|
auto sub_topic_name =
|
2019-04-29 09:33:13 +02:00
|
|
|
client_info->response_subscriber_->getAttributes ().topic.getTopicName ();
|
2018-07-10 08:14:20 +02:00
|
|
|
auto sub_partitions =
|
2019-04-29 09:33:13 +02:00
|
|
|
client_info->response_subscriber_->getAttributes ().qos.m_partition.getNames ();
|
2018-07-10 08:14:20 +02:00
|
|
|
// every rostopic has exactly 1 partition field set
|
2019-04-29 09:33:13 +02:00
|
|
|
if (sub_partitions.size () != 1) {
|
|
|
|
RCUTILS_LOG_ERROR_NAMED (
|
2018-07-10 08:14:20 +02:00
|
|
|
"rmw_cyclonedds_cpp",
|
2019-04-29 09:33:13 +02:00
|
|
|
"Topic %s is not a ros topic", pub_topic_name.c_str ())
|
|
|
|
RMW_SET_ERROR_MSG ((std::string (sub_topic_name) + " is a non-ros topic\n").c_str ());
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
auto sub_fqdn = sub_partitions[0] + "/" + sub_topic_name;
|
2019-04-29 09:33:13 +02:00
|
|
|
sub_fqdn = _demangle_if_ros_topic (sub_fqdn);
|
2018-07-10 08:14:20 +02:00
|
|
|
|
|
|
|
*is_available = false;
|
|
|
|
size_t number_of_request_subscribers = 0;
|
2019-04-29 09:33:13 +02:00
|
|
|
rmw_ret_t ret = rmw_count_subscribers (
|
2018-07-10 08:14:20 +02:00
|
|
|
node,
|
2019-04-29 09:33:13 +02:00
|
|
|
pub_fqdn.c_str (),
|
2018-07-10 08:14:20 +02:00
|
|
|
&number_of_request_subscribers);
|
|
|
|
if (ret != RMW_RET_OK) {
|
|
|
|
// error string already set
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (number_of_request_subscribers == 0) {
|
|
|
|
// not ready
|
|
|
|
return RMW_RET_OK;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
size_t number_of_response_publishers = 0;
|
2019-04-29 09:33:13 +02:00
|
|
|
ret = rmw_count_publishers (
|
2018-07-10 08:14:20 +02:00
|
|
|
node,
|
2019-04-29 09:33:13 +02:00
|
|
|
sub_fqdn.c_str (),
|
2018-07-10 08:14:20 +02:00
|
|
|
&number_of_response_publishers);
|
|
|
|
if (ret != RMW_RET_OK) {
|
|
|
|
// error string already set
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
if (number_of_response_publishers == 0) {
|
|
|
|
// not ready
|
2018-07-09 13:22:25 +02:00
|
|
|
return RMW_RET_OK;
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// all conditions met, there is a service server available
|
|
|
|
*is_available = true;
|
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
#else
|
2019-04-29 09:33:13 +02:00
|
|
|
(void) node; (void) client; (void) is_available;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_TIMEOUT;
|
2018-07-09 13:22:25 +02:00
|
|
|
#endif
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_count_publishers (const rmw_node_t *node, const char *topic_name, size_t *count)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2018-07-09 13:22:25 +02:00
|
|
|
#if 0
|
2018-07-10 08:14:20 +02:00
|
|
|
// safechecks
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!node) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("null node handle");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
// Get participant pointer from node
|
2019-05-03 17:12:51 +08:00
|
|
|
if (node->implementation_identifier != eclipse_cyclonedds_identifier) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("node handle not from this implementation");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
auto impl = static_cast<CustomParticipantInfo *> (node->data);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
WriterInfo * slave_target = impl->secondaryPubListener;
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.lock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
*count = 0;
|
|
|
|
for (auto it : slave_target->topicNtypes) {
|
2019-04-29 09:33:13 +02:00
|
|
|
auto topic_fqdn = _demangle_if_ros_topic (it.first);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (topic_fqdn == topic_name) {
|
2019-04-29 09:33:13 +02:00
|
|
|
*count += it.second.size ();
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.unlock ();
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
RCUTILS_LOG_DEBUG_NAMED (
|
2018-07-10 08:14:20 +02:00
|
|
|
"rmw_fastrtps_cpp",
|
|
|
|
"looking for subscriber topic: %s, number of matches: %zu",
|
2019-04-29 09:33:13 +02:00
|
|
|
topic_name, *count);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
#else
|
2019-04-29 09:33:13 +02:00
|
|
|
(void) node; (void) topic_name; (void) count;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_TIMEOUT;
|
2018-07-09 13:22:25 +02:00
|
|
|
#endif
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
extern "C" rmw_ret_t rmw_count_subscribers (const rmw_node_t *node, const char *topic_name, size_t *count)
|
2018-07-10 08:14:20 +02:00
|
|
|
{
|
2018-07-09 13:22:25 +02:00
|
|
|
#if 0
|
2018-07-10 08:14:20 +02:00
|
|
|
// safechecks
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
if (!node) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("null node handle");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
|
|
|
// Get participant pointer from node
|
2019-05-03 17:12:51 +08:00
|
|
|
if (node->implementation_identifier != eclipse_cyclonedds_identifier) {
|
2019-04-29 09:33:13 +02:00
|
|
|
RMW_SET_ERROR_MSG ("node handle not from this implementation");
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_ERROR;
|
|
|
|
}
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
CustomParticipantInfo * impl = static_cast<CustomParticipantInfo *> (node->data);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2018-07-10 08:14:20 +02:00
|
|
|
ReaderInfo * slave_target = impl->secondarySubListener;
|
|
|
|
*count = 0;
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.lock ();
|
2018-07-10 08:14:20 +02:00
|
|
|
for (auto it : slave_target->topicNtypes) {
|
2019-04-29 09:33:13 +02:00
|
|
|
auto topic_fqdn = _demangle_if_ros_topic (it.first);
|
2018-07-10 08:14:20 +02:00
|
|
|
if (topic_fqdn == topic_name) {
|
2019-04-29 09:33:13 +02:00
|
|
|
*count += it.second.size ();
|
2018-07-09 13:22:25 +02:00
|
|
|
}
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2019-04-29 09:33:13 +02:00
|
|
|
slave_target->mapmutex.unlock ();
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
RCUTILS_LOG_DEBUG_NAMED (
|
2018-07-10 08:14:20 +02:00
|
|
|
"rmw_fastrtps_cpp",
|
|
|
|
"looking for subscriber topic: %s, number of matches: %zu",
|
2019-04-29 09:33:13 +02:00
|
|
|
topic_name, *count);
|
2018-07-09 13:22:25 +02:00
|
|
|
|
2019-04-29 09:33:13 +02:00
|
|
|
return RMW_RET_OK;
|
2018-07-09 13:22:25 +02:00
|
|
|
#else
|
2019-04-29 09:33:13 +02:00
|
|
|
(void) node; (void) topic_name; (void) count;
|
2018-07-10 08:14:20 +02:00
|
|
|
return RMW_RET_TIMEOUT;
|
2018-07-09 13:22:25 +02:00
|
|
|
#endif
|
2018-07-10 08:14:20 +02:00
|
|
|
}
|
2019-05-03 17:12:51 +08:00
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_get_subscriber_names_and_types_by_node (const rmw_node_t *node, rcutils_allocator_t *allocator, const char *node_name, const char *node_namespace, bool no_demangle, rmw_names_and_types_t *topic_names_and_types)
|
|
|
|
{
|
|
|
|
(void) node; (void) allocator; (void) node_name; (void) node_namespace; (void) no_demangle; (void) topic_names_and_types;
|
|
|
|
return RMW_RET_TIMEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_get_publisher_names_and_types_by_node (const rmw_node_t *node, rcutils_allocator_t *allocator, const char *node_name, const char *node_namespace, bool no_demangle, rmw_names_and_types_t *topic_names_and_types)
|
|
|
|
{
|
|
|
|
(void) node; (void) allocator; (void) node_name; (void) node_namespace; (void) no_demangle; (void) topic_names_and_types;
|
|
|
|
return RMW_RET_TIMEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" rmw_ret_t rmw_get_service_names_and_types_by_node (const rmw_node_t *node, rcutils_allocator_t *allocator, const char *node_name, const char *node_namespace, bool no_demangle, rmw_names_and_types_t *topic_names_and_types)
|
|
|
|
{
|
|
|
|
(void) node; (void) allocator; (void) node_name; (void) node_namespace; (void) no_demangle; (void) topic_names_and_types;
|
|
|
|
return RMW_RET_TIMEOUT;
|
|
|
|
}
|