Allow unique prefix matches for elements and attributes specified in
directly in CYCLONEDDS_URI. That mode already has a few niceties for
quickly specifying some configuration overrides, this is simply one
more.
Signed-off-by: Erik Boasson <eb@ilities.com>
The ``docs/makernc.pl`` perl script can extract the options from the
source code for the configuration processing and turn these into a
GitHub MarkDown document and a RELAX NG Compact form (RNC) description
of the options. Standard conversion tools can be used to turn the RNC
file into an XSD.
Although they are generated by a mechanical transformation, it is not
(yet) part of the build process, in no small part because there no
proper generation and publishing system has yet been set up for the
documentation.
Now that there is an XSD and a Markdown file for discovering the
options, there is no need to retain the configuration editing tool. Any
decent editor will do a better job.
Signed-off-by: Erik Boasson <eb@ilities.com>
From a distant past came code to encrypt data on the wire, but it hasn't
been functional in Cyclone for a long time and it only ever provided
protection against casual eavesdroppers. It is better to delete it.
Signed-off-by: Erik Boasson <eb@ilities.com>
* GUID, keyhash compare (currently no reliance on this comparison, so
not causing trouble in Cyclone for applications)
* comparing "propagate" boolean in plist (newly added for security,
not yet used)
* fix memory leak in plist_unalias (currently only used in duplicating
them, in which case the memory leak doesn't occur)
* add unit tests for plist handling
Signed-off-by: Erik Boasson <eb@ilities.com>
* Fix type of num reliable readers (int to int32_t)
* Conversion codes in debug monitor printf formats
* Dead code elimination
* Skipping a test case where SIZE_MAX is assumed > INT32_MAX if
assumption is false on target platform
* Error handling in os_sockWaitsetNew
* Stick to unsigned in fragment size calculations
This check is actually guarded by valid_DataFrag and was safe for
datagrams up to 2GB, but the unintended and implicit conversion to is
still best eliminated.
* A "server" connection never has an invalid socket in TCP wrapper
* Handle error return from gethostname in SPDP write (CID 248183)
* Handle extended retcodes in dds_strretcode
CID 248131, introduced by 19aec98b8a
* Remove dead code in ddsrt logging test (CID 248195)
* Validate command-line argument in process test (CID 248117)
* Allow for extremely delayed store in test
Test is constructed to have the events trigger only at the appropriate
times, but it does assume that the store to cb_called becomes visible
prior to the listener callback. I'm pretty sure that will always be
the case in practice, but I'm also pretty sure there is no formal
guarantee without a memory barrier, which mutex_unlock provides.
CID 248088, 248136, 248177, 253590, 253591, 253593
* Check unsetenv return value in test (CID 248099)
Signed-off-by: Erik Boasson <eb@ilities.com>
In the case of when a DATA_ON_READERS listener is set, but with the
corresponding status mask is set to suppress the event, the reader lock
would not be in locked, resulting in a unlocked access of status flags
and a double unlock.
Signed-off-by: Erik Boasson <eb@ilities.com>
For targets that do not support ddsrt_setenv and ddsrt_getenv, an alternative
method is needed to supply an application specific configuration. One way to
implement this, is to add a function for creating a domain with a string
arguments, which needs to be called before any call to dds_create_participant
for given domain identifier.
The function dds_create_domain has been added, which has as arguments a domain
identifier and a configuration string. The string is treated in the same way
as the string that is retrieved from the environment variable, in that it may
containt a comma separated list of file names and/or XML fragments for the
configuration.
Two tests have been added. One limits the number of participants to two and
verifies that creating a third participant fails. The other tests checks
incorrect calls to dds_create_domain.
An assert in dds_handle_delete has been weakened.
Signed-off-by: Frans Faase <frans.faase@adlinktech.com>
Rare intermittent failure appears to be timing. Increasing the timeout
doesn't affect the duration of a successful run and will still signal an
missing trigger.
Signed-off-by: Erik Boasson <eb@ilities.com>
Deleting participant does: add to "deleted participants", remove from
GUID hash table; so SPDP processing must first check for an existing
participant and check deleted participants if nothing found.
Signed-off-by: Erik Boasson <eb@ilities.com>
So dds_read/dds_take should pass it the address of the first pointer,
rather than the first pointer itself, or the freeing of memory allocated
for samples because of an outstanding loan will crash. Add a test that
reliable detects this case when no other participants are around.
Signed-off-by: Erik Boasson <eb@ilities.com>
Deleting entities concurrently with operating on them or creating child
entities should work properly, even if it is essentially abuse. This
commit fixes (most?) of them, with exception of some nastiness when
deleting the last entity, and thus deinitialising the library, in
parallel to attempting to operate on a (by definition invalid) handle.
* Interrupting a blocked operation at the beginning of "delete" is now a
separate operation. E.g., a wait call on a waitset must be interrupted,
but the data structures can't be touched yet because other threads may
be doing an attach/detach in parallel.
* DDSI writer can now be switched to an intermediate state,
"INTERRUPTED", to indicate that it should unblock any waiting threads
and refuse to transmit any further data, but without actually
embarking on the path of deleting data structures.
* The extra "pinning" of readers and writers is now gone, they remain
fully functional until the no other threads can still access the
entity.
* Future listener invocations are prevented as part of deleting the
entity, but now it also guarantees the application can no longer
re-enable them. It furthermore waits until there are no further
current or pending listener invocations, rather than simply no current
ones.
* The internal state of the waitset now has its own lock, otherwise
attaching the parent entity of the waitset can require locking the
waitset after having locking the parent, which violates locking order.
* Handles are created in a pending state, where they are not included in
a dds_get_children operation and refuse to be pinned. This makes it
possible (in a future commit) to undo deletion of complex entities.
* There is a test (ddsc_waitset_torture) that exercises some of these
corner cases.
Signed-off-by: Erik Boasson <eb@ilities.com>
This fixes a possible deadlock when detaching an entity at the same time
it is triggering: a triggering entity holds its m_observers_lock while
trying to acquire waiset::m_mutex, and so attach and detach must not do
the opposite. The deadlock had excellent reproducibility in a seemingly
unrelated ROS2 application; this changes fixes it.
Signed-off-by: Erik Boasson <eb@ilities.com>
The default RHC implementation is not always ideal and rather than
trying to squeeze everything in a fixed interface it makes more sense to
allow the caller to provide an arbitrary implementation of the
interface.
This is not yet a stable interface.
Signed-off-by: Erik Boasson <eb@ilities.com>
This makes it possible to write one's own RHC implementation. This is
not a stable interface. It shuffles a few things around and renames
some types used throughout the code to stick to having a "dds" prefix
for all the external things.
Signed-off-by: Erik Boasson <eb@ilities.com>
All functions creating an entity pin the parent, which guarantees that
the CLOSED is not set yet, but as setting it occurs within the mutex, it
may be set by the time the parent has been locked. One should not try
to add a child entity at that point, so check it again.
Signed-off-by: Erik Boasson <eb@ilities.com>
Leak a small amount of memory when there are still application threads
around, that's slightly less problematic than the old code. It really
needs an overhaul.
Signed-off-by: Erik Boasson <eb@ilities.com>
Require that all entities attached to waitset are in the same
participant (if the waitset's parent is a participant) or in the same
domain (if the waitset's parent is a domain). There used to be no check
on this, but it always seemed unhygenic and now that domains and the
entire library instantiation can be used as parents, it seems much
better to enforce this scoping rule.
Signed-off-by: Erik Boasson <eb@ilities.com>
This commit adds two entity types: a "domain", which is the parent of
participants and which is instantiated for each domain that has at least
one participant in it; and "cyclonedds", which is a representation of
the (initialized) Cyclone DDS library in the process and that is the
parent of all domain entities. The handle of the latter is a
compile-constant, DDS_CYCLONEDDS_HANDLE.
This changes the return value from dds_get_parent when executed on a
participant: it now returns the handle of the entity representing the
domain the participant is attached to. Two participants in the same
domain self-evidently return the same domain entity.
This allows deleting all participants in a domain by calling dds_delete
on the domain entity, or tearing down everything and deinitializing the
library by calling dds_delete on the top-level entity.
Signed-off-by: Erik Boasson <eb@ilities.com>
Things go really badly wrong when topics from one participant are used
to create a reader/writer in another participant. This returns an error
if they are not.
Signed-off-by: Erik Boasson <eb@ilities.com>
* Fix compilation errors for RMW build on Windows
This commit fixes the compilation errors that occur when building
the ROS2 rmw_cyclonedds_cpp module on Windows with the msvc C++
compiler. The error are fixed by adding explicit casts when calling
operations on atomics and a different syntax is used for compound
literals (the c99 syntax is not supported in msvc in C++ mode).
In additionally some warnings related to emtpy array usage
in structs are suppressed for msvc.
Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
* Restructured macros for vendor id cast and casts for atomic operations
To improve readability I've restructured the macros that are used
for vendor id casts on msvc in c++ mode and macros for type-casting
arguments in operations on atomics (as suggested in the review of
my previous commit)
Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
* Moved atomic function suffix to macro
Moved the suffix for (msvc) 64 bit atomic functions to the
DDSRT_ATOMIC_OP64 macro
Signed-off-by: Dennis Potman <dennis.potman@adlinktech.com>
While commit a652ecb78e addressed most of
the issues with a new reader possibly not accepting all samples a proxy
writer published after it matched that reader, it failed to do so
properly for 2nd and later readers. The cause was, once again,
prematurely considering the reader to be "in sync" with the proxy
writer and not requesting any old samples.
The desire to consider them "in sync" from the very beginning is that it
avoids a lot of network traffic. With this commit, all new readers are
treated equally, despite the additional traffic that generates.
Signed-off-by: Erik Boasson <eb@ilities.com>
Dropping a match from a data reader generated unregisters and signalled
a SUBSCRIPTION_MATCHED event even when another thread raced it and did
so before. The consequence is possible undercounting of the number of
matched writers.
Signed-off-by: Erik Boasson <eb@ilities.com>
The only place it was used for more than printing the name (which is
available via the QoS object) was in deserializing the sample, but there
is never a need to deserialize a sample if there is no local reader. So
instead of caching the topic object in the proxy endpoint, take it from
a reader to which it is to be delivered and avoid having to keep things
in sync.
Signed-off-by: Erik Boasson <eb@ilities.com>
Submit to the tyranny of the majority:
The DCPS specification makes no distinction between topics with and
topics without key fields: in the latter case, there is simply a single
instance but that instance obeys all the normal rules. In particular,
this implies dispose/unregister work regardless of whether a topic has
key fields.
The DDSI specification makes a distinction between WITH_KEY endpoints
and NO_KEY endpoints and does not support dispose/unregister operations
on NO_KEY endpoints. This implies that a DCPS implementation must limit
itself to the use of WITH_KEY endpoints.
Most implementations nonetheless map topics without key fields to the
NO_KEY type, and as the DDSI specification also states that a WITH_KEY
reader/writer does not match a NO_KEY writer/reader, Cyclone's correctly
mapping everything to WITH_KEY means there are interoperability problems
for topics without key fields.
This commit changes Cyclone to use NO_KEY like the others, but without
changing any other part of its behaviour: it continues to support
dispose/unregister operations regardless of whether a topic has key
fields or not. That is the lesser of the two evils.
Signed-off-by: Erik Boasson <eb@ilities.com>
The pre-emptive ACKNACK messages from FastRTPS have a base sequence
number of 0, which is malformed and must be rejected according to DDSI
8.3.7.1 / 8.3.5.5.
Signed-off-by: Erik Boasson <eb@ilities.com>
Change the structure of the configuration file (in a backwards
compatible manner) to allow specifying configurations for multiple
domains in a file. (Listing multiple files in CYCLONEDDS_URI was
already supported.) A configuration specifies an id, with a default of
any, configurations for an incompatible id are ignored.
If the application specifies an id other than DDS_DOMAIN_DEFAULT in the
call to create_participant, then only configuration specifications for
Domain elements with that id or with id "any" will be used. If the
application does specify DDS_DOMAIN_DEFAULT, then the id will be taken
from the first Domain element that specifies an id. If none do, the
domain id defaults to 0. Each applicable domain specification is taken
as a separate source and may override settings made previously.
All settings moved from the top-level CycloneDDS element to the
CycloneDDS/Domain element. The CycloneDDS/Domain/Id element moved to
become the "id" attribute of CycloneDDS/Domain. The old locations still
work, with appropriate deprecation warnings.
Signed-off-by: Erik Boasson <eb@ilities.com>
The default participant QoS/plist that is used for defaulting received
QoS and for determining which QoS/plist entries to send in discovery
data was mixed up with the one that contains local process information
such as hostname and process id.
It moreover was modified after starting up the protocol stack, and hence
after discovery of remote participants. While unlikely, this could lead
to an assertion in plist_or_xqos_mergein_missing.
Signed-off-by: Erik Boasson <eb@ilities.com>
A QoS change can happen at the same time that a new reader for a
built-in topic is provisioned with historical data, and so cause reading
in inconsistent QoS, use-after-free or other fun things.
During QoS matching it is also necessary to guarantee the QoS doesn't
change (QoS changes affecting matching will be supported at some point,
and manipulating complex data structures where bitmasks determine which
parts are defined while reading the same data concurrently is a recipe
for disaster.
Signed-off-by: Erik Boasson <eb@ilities.com>