Merge pull request #527 from eclipse-cyclonedds/security
Merge security into master
33
.travis.yml
|
@ -143,33 +143,37 @@ windows_vs2017: &windows_vs2017
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- <<: *linux_gcc8
|
- <<: *linux_gcc8
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", COVERITY_SCAN=true ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", COVERITY_SCAN=true ]
|
||||||
if: type = cron
|
if: type = cron
|
||||||
- <<: *linux_gcc8
|
- <<: *linux_gcc8
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
- <<: *linux_gcc8
|
- <<: *linux_gcc8
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", CONANFILE=conanfile102.txt ]
|
||||||
- <<: *linux_gcc8
|
- <<: *linux_gcc8
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=NO, LIFESPAN=NO, DEADLINE=NO, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
|
- <<: *linux_gcc8
|
||||||
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=NO, SECURITY=YES, LIFESPAN=NO, DEADLINE=NO, GENERATOR="Unix Makefiles" ]
|
||||||
- <<: *linux_clang
|
- <<: *linux_clang
|
||||||
env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
- <<: *linux_clang
|
- <<: *linux_clang
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, SECURITY=NO, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
|
- <<: *linux_clang
|
||||||
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
- <<: *osx_xcode9
|
- <<: *osx_xcode9
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
if: type = cron
|
if: type = cron
|
||||||
- <<: *osx_xcode
|
- <<: *osx_xcode
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", MACOSX_DEPLOYMENT_TARGET=10.12 ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=NO, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles", MACOSX_DEPLOYMENT_TARGET=10.12 ]
|
||||||
- <<: *osx_xcode
|
- <<: *osx_xcode
|
||||||
env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=address, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
- <<: *osx_xcode
|
- <<: *osx_xcode
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Unix Makefiles" ]
|
||||||
- <<: *windows_vs2017
|
- <<: *windows_vs2017
|
||||||
env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017" ]
|
env: [ ARCH=x86, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017", CONANFILE=conanfile102.txt ]
|
||||||
- <<: *windows_vs2017
|
- <<: *windows_vs2017
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017 Win64" ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Debug, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017 Win64" ]
|
||||||
- <<: *windows_vs2017
|
- <<: *windows_vs2017
|
||||||
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017 Win64" ]
|
env: [ ARCH=x86_64, ASAN=none, BUILD_TYPE=Release, SSL=YES, SECURITY=YES, LIFESPAN=YES, DEADLINE=YES, GENERATOR="Visual Studio 15 2017 Win64" ]
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- conan profile new default --detect
|
- conan profile new default --detect
|
||||||
|
@ -195,12 +199,13 @@ script:
|
||||||
- INSTALLPREFIX="$(pwd)/install"
|
- INSTALLPREFIX="$(pwd)/install"
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
- conan install -b missing -s arch=${ARCH} -s build_type=${BUILD_TYPE} ..
|
- conan install -b missing -s arch=${ARCH} -s build_type=${BUILD_TYPE} ../${CONANFILE:-conanfile.txt}
|
||||||
- which trang && BUILD_SCHEMA=1 || BUILD_SCHEMA=0
|
- which trang && BUILD_SCHEMA=1 || BUILD_SCHEMA=0
|
||||||
- cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
- cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
|
||||||
-DCMAKE_INSTALL_PREFIX=${INSTALLPREFIX}
|
-DCMAKE_INSTALL_PREFIX=${INSTALLPREFIX}
|
||||||
-DUSE_SANITIZER=${ASAN}
|
-DUSE_SANITIZER=${ASAN}
|
||||||
-DENABLE_SSL=${SSL}
|
-DENABLE_SSL=${SSL}
|
||||||
|
-DENABLE_SECURITY=${SECURITY}
|
||||||
-DENABLE_LIFESPAN=${LIFESPAN}
|
-DENABLE_LIFESPAN=${LIFESPAN}
|
||||||
-DENABLE_DEADLINE_MISSED=${DEADLINE}
|
-DENABLE_DEADLINE_MISSED=${DEADLINE}
|
||||||
-DBUILD_TESTING=on
|
-DBUILD_TESTING=on
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
#
|
#
|
||||||
cmake_minimum_required(VERSION 3.7)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
project(CycloneDDS VERSION 0.6.0)
|
project(CycloneDDS VERSION 0.7.0)
|
||||||
|
|
||||||
# Set a default build type if none was specified
|
# Set a default build type if none was specified
|
||||||
set(default_build_type "RelWithDebInfo")
|
set(default_build_type "RelWithDebInfo")
|
||||||
|
|
|
@ -281,12 +281,17 @@ function(add_cunit_executable TARGET)
|
||||||
set_property(
|
set_property(
|
||||||
TEST ${ctest}
|
TEST ${ctest}
|
||||||
PROPERTY ENVIRONMENT
|
PROPERTY ENVIRONMENT
|
||||||
"DYLD_LIBRARY_PATH=${CUNIT_LIBRARY_DIR}:$ENV{DYLD_LIBRARY_PATH}")
|
"DYLD_LIBRARY_PATH=${CUNIT_LIBRARY_DIR}:${CMAKE_LIBRARY_OUTPUT_DIRECTORY}:$ENV{DYLD_LIBRARY_PATH}")
|
||||||
elseif(WIN32 AND ${CUNIT_LIBRARY_TYPE} STREQUAL "SHARED_LIBRARY")
|
elseif(WIN32 AND ${CUNIT_LIBRARY_TYPE} STREQUAL "SHARED_LIBRARY")
|
||||||
set_property(
|
set_property(
|
||||||
TEST ${ctest}
|
TEST ${ctest}
|
||||||
PROPERTY ENVIRONMENT
|
PROPERTY ENVIRONMENT
|
||||||
"PATH=${CUNIT_LIBRARY_DIR};$ENV{PATH}")
|
"PATH=${CUNIT_LIBRARY_DIR};$ENV{PATH}")
|
||||||
|
else()
|
||||||
|
set_property(
|
||||||
|
TEST ${ctest}
|
||||||
|
PROPERTY ENVIRONMENT
|
||||||
|
"LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}:$ENV{LD_LIBRARY_PATH}")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
|
6
conanfile102.txt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[requires]
|
||||||
|
cunit/2.1-3@bincrafters/stable
|
||||||
|
OpenSSL/1.0.2@conan/stable
|
||||||
|
|
||||||
|
[generators]
|
||||||
|
cmake
|
406
docs/dev/dds_security_effort.md
Normal file
|
@ -0,0 +1,406 @@
|
||||||
|
# DDS Security effort
|
||||||
|
|
||||||
|
ADLink has decided to donate their Vortex OpenSplice DDS Security
|
||||||
|
implementation to the Cyclone DDS project. However, that will not be a simple
|
||||||
|
code drop.
|
||||||
|
|
||||||
|
This document catches all the work that is foreseen to port Vortex OpenSplice
|
||||||
|
DDS Security to Cyclone DDS.
|
||||||
|
|
||||||
|
This document can be removed when DDS Security has been implemented.
|
||||||
|
|
||||||
|
**Table of contents**
|
||||||
|
- [Definition of done](#done)
|
||||||
|
- [Footprint](#footprint)
|
||||||
|
- [Multi process testing (done)](#testing)
|
||||||
|
- [Runtime library loading (done)](#loading)
|
||||||
|
- [Hopscotch utility (done)](#hopscotch)
|
||||||
|
- [FSM utility (in progress)](#fsm)
|
||||||
|
- [Port DDS Security plugin API (done)](#port-api)
|
||||||
|
- [De-Serializing messages in DDSI (done)](#deserializing)
|
||||||
|
- [De-Serializing security message parameters in DDSI (done)](#deserializing_plist)
|
||||||
|
- [Port DDS Security builtin plugins (in progress)](#port-plugins)
|
||||||
|
- [Port DDSI DDS Security (in progress)](#port-ddsi)
|
||||||
|
- [Move configuration (in progress)](#Move-configuration)
|
||||||
|
- [Failure handling](#failures)
|
||||||
|
- [Multiple configurations](#multiple-configurations)
|
||||||
|
- [Example](#example)
|
||||||
|
- [QosProvider](#qosprovider)
|
||||||
|
- [Data Tags (optional)](#datatags)
|
||||||
|
|
||||||
|
|
||||||
|
## Definition of done<a name="done" />
|
||||||
|
|
||||||
|
When this document tells that a certain aspect is 'done', it means that it
|
||||||
|
has been accepted into the security branch of the cyclonedds repository
|
||||||
|
(https://github.com/eclipse-cyclonedds/cyclonedds/tree/security).
|
||||||
|
|
||||||
|
However, it is possible that various parts need some rework before the security
|
||||||
|
branch can be merged into the cyclonedds master branch.
|
||||||
|
|
||||||
|
|
||||||
|
## Footprint<a name="footprint" />
|
||||||
|
|
||||||
|
A non-functional requirement is that cyclonedds should be buildable without
|
||||||
|
the DDS Security support in it. That will reduce the footprint (and possibly
|
||||||
|
improve performance) for applications that don't need security.
|
||||||
|
|
||||||
|
For that, the ENABLE_SECURITY build option is introduced that translates into
|
||||||
|
the DDSI_INCLUDE_SECURITY compile switch. However, the usage of that switch
|
||||||
|
should not explode. That'll reduce the maintainability.
|
||||||
|
|
||||||
|
For instance, the usage of the switch can be minimized by using functions that
|
||||||
|
will reduce to an inline function that just returns a hardcode value when
|
||||||
|
security is not included (otherwise they'll do some certain task).
|
||||||
|
The compiler can use these inline functions to do clever stuff regarding
|
||||||
|
footprint and performance.
|
||||||
|
|
||||||
|
There can be other solutions to decrease security footprint without impeding
|
||||||
|
on the maintainability of the code by inserting the switch too much.
|
||||||
|
|
||||||
|
|
||||||
|
## Multi process testing (done)<a name="testing" />
|
||||||
|
|
||||||
|
To properly test DDS Security, multi process testing will be necessary.
|
||||||
|
This is not yet available in Cyclone DDS.
|
||||||
|
See the [Multi Process Testing](multi_process_testing.md) document for
|
||||||
|
more information.
|
||||||
|
|
||||||
|
|
||||||
|
## Runtime library loading (done)<a name="loading" />
|
||||||
|
|
||||||
|
The ddsi component needs to be able to load DDS Security plugins at runtime.
|
||||||
|
These plugins are provided as libraries.<br>
|
||||||
|
Loading libraries at runtime is currently not possible in Cyclone DDS.
|
||||||
|
|
||||||
|
|
||||||
|
## Hopscotch utility (done)<a name="hopscotch" />
|
||||||
|
|
||||||
|
This hash table is used by the Security plugins.<br>
|
||||||
|
Both versions on OpenSplice and Cyclone are equivalent.<br>
|
||||||
|
No additional effort is expected.
|
||||||
|
|
||||||
|
|
||||||
|
## FSM utility (in progress)<a name="fsm" />
|
||||||
|
|
||||||
|
The Finite State Machine utility has been introduced in OpenSplice to support
|
||||||
|
the handshake of DDS Security.<br>
|
||||||
|
This has to be ported to Cyclone.
|
||||||
|
|
||||||
|
However, it already has some technical dept, which should be removed before
|
||||||
|
adding it to Cyclone. This means that a refactor should happen as part of the
|
||||||
|
porting.
|
||||||
|
|
||||||
|
The related DBTs should also be ported to Cyclone unit tests.
|
||||||
|
|
||||||
|
It was decided to just port the FSM at the moment. The refactor will take place
|
||||||
|
when trying to get the security branch into master.
|
||||||
|
|
||||||
|
|
||||||
|
## Port DDS Security plugin API (done)<a name="port-api" />
|
||||||
|
|
||||||
|
The DDS Security plugin API are just a few header files. The ddsi component
|
||||||
|
uses that to link against. The implementation of the API is done in the
|
||||||
|
individual plugins. The plugins are [loaded at runtime](#loading) (when
|
||||||
|
configured).
|
||||||
|
|
||||||
|
This means that ddsi can be DDS Security prepared (after building against this
|
||||||
|
API) without there being actual DDS Security plugins.
|
||||||
|
|
||||||
|
It seems to be just a code drop of a number of header files.<br>
|
||||||
|
Maybe add some CMake module for both ddsi and the plugins to easily link
|
||||||
|
against?
|
||||||
|
|
||||||
|
|
||||||
|
## De-Serializing messages in DDSI (done)<a name="deserializing" />
|
||||||
|
|
||||||
|
DDSI needs to be able to (de)serialize a few Security messages. In OpenSplice,
|
||||||
|
some functionality of the database is used. This is unavailable in Cyclone.
|
||||||
|
|
||||||
|
What is available is a serializer that uses marshaling operations (see, for
|
||||||
|
for instance, m_ops in the dds_topic_descriptor struct).
|
||||||
|
|
||||||
|
The (de)serializing of the Security messages should be supported by supplying
|
||||||
|
the m_ops sequences, message structs (if not yet available) and some
|
||||||
|
convenience functions using both.
|
||||||
|
|
||||||
|
|
||||||
|
## De-Serializing security message parameters in DDSI (done)<a name="deserializing_plist" />
|
||||||
|
|
||||||
|
DDSI needs to be able to (de)serialize a few message parameters that have
|
||||||
|
been introduced by the DDS Security spec.
|
||||||
|
|
||||||
|
|
||||||
|
## Port DDS Security builtin plugins (in progress)<a name="port-plugins" />
|
||||||
|
|
||||||
|
No major changes between the DDS Security plugins in OpenSplice and Cyclone
|
||||||
|
are expected.
|
||||||
|
|
||||||
|
The DDS Security plugins require OpenSSL. Cyclone DDS already uses OpenSSL.
|
||||||
|
However, it expects (or at least it's preferred to have) version 1.1 or newer,
|
||||||
|
while the OpenSplice Security plugins are build against 1.0.2. There are some
|
||||||
|
API changes between the two versions. This will take some porting effort.
|
||||||
|
|
||||||
|
The build system should be ported from makefiles to cmake files.
|
||||||
|
|
||||||
|
There are security_plugin DBTs in OpenSplice. These tests are base on cunit,
|
||||||
|
which is also used in Cyclone. However, it is used slightly different. A small
|
||||||
|
porting effort is expected (i.e. let it work with cmake and runner generation).
|
||||||
|
|
||||||
|
This means some additional effort, compared to just a code drop. But it is not
|
||||||
|
expected to be major.
|
||||||
|
|
||||||
|
- Authentication plugin (done).
|
||||||
|
- Access Control plugin (in progress).
|
||||||
|
- Cryptography plugin (done).
|
||||||
|
|
||||||
|
There are a few sub-features that can be implemented separately.
|
||||||
|
- Check/handle expiry dates (in progress).
|
||||||
|
- Trusted directory support.
|
||||||
|
- etc?
|
||||||
|
|
||||||
|
|
||||||
|
## Port DDSI DDS Security (in progress)<a name="port-ddsi" />
|
||||||
|
|
||||||
|
There is already quite a bit of difference between the DDSI codebases in
|
||||||
|
OpenSplice and Cyclone. So, the copy/merge of the DDSI Security code from
|
||||||
|
OpenSplice to Cyclone will not be trivial.
|
||||||
|
|
||||||
|
Most parts of the merging will not be trivial, but should be quite
|
||||||
|
straightforward nonetheless. Things that are noticed to be somewhat different
|
||||||
|
between the DDSI code bases that could impact the merging work:
|
||||||
|
- Entity matching is slightly different.
|
||||||
|
- The q_entity.c has a lot of differences that can obfuscate the differences
|
||||||
|
related to DDS Security.
|
||||||
|
- Unacked messages logic has changed a bit. Does that impact gaps?
|
||||||
|
- (De)serializing, of course
|
||||||
|
(see also [De-Serializing in DDSI](#deserializing)).
|
||||||
|
- Writer history cache is different, which can impact the builtin volatile
|
||||||
|
Security endpoints.
|
||||||
|
- Unknown unknowns.
|
||||||
|
|
||||||
|
The buildsystem has to be upgraded.<br>
|
||||||
|
- A few files are added which are easy to add to cmake.<br>
|
||||||
|
- There's a new dependency on the [DDS Security API](#port-api), which is done.
|
||||||
|
|
||||||
|
Then, of course, there are the tests<br>
|
||||||
|
First of all, [Multi Process Testing](#testing) should be available, which now
|
||||||
|
it is.<br>
|
||||||
|
When that's the case, then the OpenSplice tests business
|
||||||
|
logic have to be ported from scripts and applications to that new framework.
|
||||||
|
That porting shouldn't be that hard. However, it will probably take a while.
|
||||||
|
|
||||||
|
The DDSI Port doesn't have to be a big bang. It can be split up into various
|
||||||
|
different pull requests. Examples are
|
||||||
|
- Extend configuration XML parsing with the security configuration (done).
|
||||||
|
- Extend nn_qos with security related policies. Fill them with values from the
|
||||||
|
configuration when applicable (done).
|
||||||
|
- Add DDS Security endpoints that are non-volatile (done).
|
||||||
|
- Add DDS Security endpoint that is volatile. This change has more impact than
|
||||||
|
all the non-volatile endpoints combined (done).
|
||||||
|
- Handshake (in progress).
|
||||||
|
- Payload (en)(de)coding (DDSI support: done. Wrapper: todo).
|
||||||
|
- Submsg (en)(de)coding (DDSI support: done. Wrapper: todo).
|
||||||
|
- RTPSmsg (en)(de)coding (DDSI support: done. Wrapper: todo).
|
||||||
|
- Etc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Move configuration (in progress)<a name="Move-configuration" />
|
||||||
|
|
||||||
|
After the port, the DDS Security configuration is still (partly) done through
|
||||||
|
the overall configuration XML file (rest is coming from the permissions and
|
||||||
|
governance files).<br>
|
||||||
|
However, according to the specification, the configuration should happen by
|
||||||
|
means of the Participant QoS.
|
||||||
|
|
||||||
|
The ddsc dds_qos_t is mapped on the ddsi xqos. The ddsi xqos already has the
|
||||||
|
necessary policy (after the [port](#port-ddsi)), namely the property_policy.
|
||||||
|
This means that the ddsc qos itself is automatically prepared.<br>
|
||||||
|
However, getting and setting policies are done through getter and setter
|
||||||
|
functions in ddsc.<br>
|
||||||
|
This means we have to add these functions for the security configuration values.
|
||||||
|
|
||||||
|
The ddsc policy getter and setter functions use (arrays of) primitive types as
|
||||||
|
arguments. The configuration of Security is given by means of the property
|
||||||
|
policy, which isn't a primitive. To keep in line with the QoS API, we could add
|
||||||
|
something like:
|
||||||
|
```cpp
|
||||||
|
typedef struct dds_properties_t; /* opaque type in API, but mapped to
|
||||||
|
nn_property_qospolicy_t internally */
|
||||||
|
dds_properties_t *dds_properties_create();
|
||||||
|
void dds_properties_delete(dds_properties_t *);
|
||||||
|
void dds_properties_merge(dds_properties_t *, dds_properties_t *);
|
||||||
|
void dds_properties_add_property(dds_properties_t *, char *name, char *value);
|
||||||
|
void dds_properties_add_binaryproperty(dds_properties_t *, char *name,
|
||||||
|
uchar *value, int valuelength);
|
||||||
|
void dds_qset_properties(dds_qos_t*, dds_properties_t *);
|
||||||
|
void dds_qget_properties(dds_qos_t*, dds_properties_t **);
|
||||||
|
```
|
||||||
|
But this is very preliminary and is still up for debate.
|
||||||
|
|
||||||
|
After moving the Security configuration to the participant QoS, it's possible
|
||||||
|
to have different configurations within a single application if you have
|
||||||
|
multiple participants. However, ddsi only supports one Security configuration
|
||||||
|
for now. That doesn't change by changing where that configuration comes
|
||||||
|
from.<br>
|
||||||
|
To solve this, it is expected that creation of a participant with a different
|
||||||
|
configuration will force a failure for now.
|
||||||
|
Until [Multiple Configurations](#multiple-configurations) is implemented.
|
||||||
|
|
||||||
|
After the ddsc API has been extended, we can decide on what to do with the
|
||||||
|
configuration through XML.
|
||||||
|
- Keep it. It seems usable: no need to change applications when changing (or
|
||||||
|
adding) Security settings. However, conflicts between XML and QoS
|
||||||
|
configuration could cause problems. Simplest seems to be to only allow QoS
|
||||||
|
security configuration when it's not configured in XML already.
|
||||||
|
- Remove it. No conflict resolving needed.
|
||||||
|
|
||||||
|
All the Security tests depend on providing (different) configurations through
|
||||||
|
XML. Depending on if we keep or remove the XML configuration option, a lot of
|
||||||
|
tests have to be updated, or a few added (that test security configuration
|
||||||
|
through QoS).
|
||||||
|
|
||||||
|
For the loading of the plugin libraries, properties with specific names have to
|
||||||
|
be added to the property policy to know the location and names of the plugins.
|
||||||
|
As inspiration, fastrtps can be used:
|
||||||
|
https://github.com/ros2/rmw_fastrtps/blob/master/rmw_fastrtps_shared_cpp/src/rmw_node.cpp#L296
|
||||||
|
|
||||||
|
|
||||||
|
## Failure handling<a name="failures" />
|
||||||
|
|
||||||
|
Currently, when an local action is tried that isn't allowed by DDS Security
|
||||||
|
(like creating a participant when it's not permitted), DDSI is shut down.<br>
|
||||||
|
Mainly because in OpenSplice it's quite hard to get a failure state from DDSI
|
||||||
|
to the application.
|
||||||
|
|
||||||
|
In Cyclone, however, ddsc::dds_create_participant() results in a direct call to
|
||||||
|
ddsi::new_participant(). This means that if creation of an entity (or
|
||||||
|
participant in this example) fails due to security issues in ddsi, we can fail
|
||||||
|
the actual ddsc API call with a proper error result (there's already the
|
||||||
|
DDS_RETCODE_NOT_ALLOWED_BY_SECURITY in the ddsc API (not used)).
|
||||||
|
|
||||||
|
Maybe we have to do some additional cleanup when a failure is encountered.
|
||||||
|
|
||||||
|
Some tests probably have to be adjusted for the new behaviour.
|
||||||
|
|
||||||
|
|
||||||
|
## Multiple configurations<a name="multiple-configurations" />
|
||||||
|
|
||||||
|
Currently (because it's done through the overall XML configuration), only one
|
||||||
|
DDS Security configuration could be supported. Because of this fact, at various
|
||||||
|
locations, shortcuts could be made in both DDSI and plugins.<br>
|
||||||
|
However, because the configuration is coming from participants now (see
|
||||||
|
[Move Configuration](#Move-configuration), we should be able to support
|
||||||
|
multiple different DDS Security configurations.
|
||||||
|
|
||||||
|
Until now, the creation of a second participant with a different configuration
|
||||||
|
would force a failure (again, see [Move Configuration](#Move-configuration)).
|
||||||
|
|
||||||
|
It is expected that the plugin loading still happens through the configuration
|
||||||
|
XML (see [Move Configuration](#Move-configuration)). This means that DDSI doesn't have to support
|
||||||
|
multiple sets of plugins. Just the one set, provided at initialization. This
|
||||||
|
means that DDSI shouldn't have to be changed to support this.
|
||||||
|
|
||||||
|
So, it's the plugins need to be able to support multiple configurations.
|
||||||
|
|
||||||
|
The Cryptography plugin doesn't seem to care about global DDS Security
|
||||||
|
configurations. It has basically configurations per participant/topic/
|
||||||
|
endpoints, which already works. So, this plugin doesn't have to be upgraded.
|
||||||
|
|
||||||
|
The Authentication plugin does have global DDS Security configurations. Main
|
||||||
|
function related to that is validate_local_identity(). This function already
|
||||||
|
creates a new local identity every time it is called. So, this plugin doesn't
|
||||||
|
have to be upgraded either.
|
||||||
|
|
||||||
|
That leaves the Access Control plugin.<br>
|
||||||
|
The main function related to configuration is validate_local_permissions().
|
||||||
|
This function creates access rights depending on Permissions and Governance
|
||||||
|
files. Currently, there's only one local 'rights' structure that is linked
|
||||||
|
directly to the plugin (see also the ACCESS_CONTROL_USE_ONE_PERMISSION compile
|
||||||
|
switch).<br>
|
||||||
|
This has to change.<br>
|
||||||
|
The local rights structure needs to be coupled to a participant. This also
|
||||||
|
means that we have to search for it instead of having direct access when
|
||||||
|
entering the plugin.<br>
|
||||||
|
The remote rights can be used as example. That is basically a list of rights/
|
||||||
|
permissions with the remote identity handle as key.
|
||||||
|
|
||||||
|
Tests have to be added to make sure that a setup with different Security
|
||||||
|
configurations works.
|
||||||
|
|
||||||
|
|
||||||
|
## Example<a name="example" />
|
||||||
|
|
||||||
|
A Security example has to be added.
|
||||||
|
|
||||||
|
|
||||||
|
## QosProvider<a name="qosprovider" />
|
||||||
|
|
||||||
|
The Participant QoS now contains Security related information. This means that
|
||||||
|
the QosProvider has to be upgraded to support that.
|
||||||
|
|
||||||
|
|
||||||
|
## Data Tags (optional)<a name="datatags" />
|
||||||
|
|
||||||
|
The specification is somewhat fuzzy about the data tags.
|
||||||
|
|
||||||
|
The following is a summary (still elaborate) of how it seems to work:
|
||||||
|
|
||||||
|
The permissions document can contain the <data_tags> tag on publish and
|
||||||
|
subscribe level. It's related to the data samples, but don't have to be related
|
||||||
|
to the keys of those samples.<br>
|
||||||
|
The QoS of a writer/reader can also have data tags by means of the
|
||||||
|
DataTagQosPolicy. A writer/reader can only be created when the data_tags in the
|
||||||
|
QoS matches those in the permissions document. This check should happen on both
|
||||||
|
the local and remote level.
|
||||||
|
|
||||||
|
This creation check is the only thing that DDS Security actually does with the
|
||||||
|
data tags. They are only authenticated by DDS Security, but not interpreted
|
||||||
|
further.<br>
|
||||||
|
This is only a minor security addition, because the publisher can still publish
|
||||||
|
data that doesn't match the data tags because DDS doesn't interpret the data
|
||||||
|
nor compares it with the data tags.
|
||||||
|
|
||||||
|
What it can be used for is a kind of custom access control scheme on the
|
||||||
|
application level.<br>
|
||||||
|
An application that consumes data can see if a publisher is allowed to publish
|
||||||
|
that sample by comparing the data within the sample with the data tag(s)
|
||||||
|
associated with that publisher. As said, this comparison is not done on the DDS
|
||||||
|
level, but has to be done within the application itself.
|
||||||
|
|
||||||
|
That leaves the question, how does the application get the tags associated with
|
||||||
|
the related writer?<br>
|
||||||
|
In other words; the application gets a sample. It has to know from which writer
|
||||||
|
it originated and it has to have access to the data tag(s) of that writer.
|
||||||
|
The dds_sample_info_t contains the dds_instance_handle_t publication_handle,
|
||||||
|
which is unique to the writer (locally).<br>
|
||||||
|
That dds_instance_handle_t can be used to get the right
|
||||||
|
DDS_Security_PublicationBuiltinTopicDataSecure sample for the related secure
|
||||||
|
builtin reader [**note1**].<br>
|
||||||
|
DDS_Security_PublicationBuiltinTopicDataSecure contains QoS information
|
||||||
|
regarding that writer, including the DataTagQosPolicy. The remote
|
||||||
|
DDS_Security_PublicationBuiltinTopicDataSecure contents have been authenticated
|
||||||
|
by DDS Security and the data tags can be trusted.<br>
|
||||||
|
The application can check the sample data against the data_tags within that
|
||||||
|
QoS.
|
||||||
|
|
||||||
|
Things to do:
|
||||||
|
- Add DataTagQosPolicy to the ddsc API and the related QoSses.
|
||||||
|
- Add DDS_Security_PublicationBuiltinTopicDataSecure data type to the ddsc API
|
||||||
|
(better yet, all secure builtin types).
|
||||||
|
- Add the related builtin reader to the ddsc99 API (better yet, all secure
|
||||||
|
builtin readers).
|
||||||
|
- Add test regarding the secure builtin readers and data.
|
||||||
|
- Add data tag comparisons between QoS and permission documents during local
|
||||||
|
and remote entity creation.
|
||||||
|
- Add data tag remote/local (mis)match tests.
|
||||||
|
|
||||||
|
Especially because of the lack of access to builtin secure readers, supporting
|
||||||
|
data tags doesn't seem feasible in the near future. Also, it's optional in the
|
||||||
|
specification.
|
||||||
|
|
||||||
|
**note1**
|
||||||
|
That DDS_Security_PublicationBuiltinTopicDataSecure reader is not yet available
|
||||||
|
within the ddsc API, nor is the related data type. Don't know how much work it
|
||||||
|
would be to add them to that API.
|
|
@ -195,3 +195,94 @@ automatic if the target supports it. Finalization is primarily used to release
|
||||||
thread-specific memory and call routines registered by
|
thread-specific memory and call routines registered by
|
||||||
`ddsrt_thread_cleanup_push`.
|
`ddsrt_thread_cleanup_push`.
|
||||||
|
|
||||||
|
|
||||||
|
## DDS Security
|
||||||
|
|
||||||
|
### Specification
|
||||||
|
|
||||||
|
DDS Security is an [OMG specification](https://www.omg.org/spec/DDS-SECURITY/1.1/PDF) which adds several “DDS Security Support”
|
||||||
|
compliance points to the DDS Specification.
|
||||||
|
The specification defines the Security Model and Service Plugin Interface (SPI)
|
||||||
|
architecture for compliant DDS implementations. The DDS Security Model is enforced
|
||||||
|
by the invocation of these SPIs by the DDS implementation.
|
||||||
|
Security Model for DDS defines the security principals (users of the system),
|
||||||
|
the objects that are being secured, and the operations on the objects that are
|
||||||
|
to be restricted.
|
||||||
|
|
||||||
|
SPIs are defined that when combined together provide Information Assurance to
|
||||||
|
DDS systems:
|
||||||
|
* Authentication Service Plugin. Provides the means to verify the identity of the
|
||||||
|
application and/or user that invokes operations on DDS. Includes facilities to
|
||||||
|
perform mutual authentication between participants and establish a shared secret.
|
||||||
|
* AccessControl Service Plugin. Provides the means to enforce policy decisions on
|
||||||
|
what DDS related operations an authenticated user can perform. For example, which
|
||||||
|
domains it can join, which Topics it can publish or subscribe to, etc.
|
||||||
|
* Cryptographic Service Plugin. Implements (or interfaces with libraries that
|
||||||
|
implement) all cryptographic operations including encryption, decryption,
|
||||||
|
* Logging Service Plugin. Supports auditing of all DDS security-relevant events
|
||||||
|
* Data Tagging Service Plugin. Provides a way to add tags to data samples.
|
||||||
|
|
||||||
|
<img src="pictures/dds_security_plugin_components.png" alt="DDS Security Plugin Components">
|
||||||
|
|
||||||
|
|
||||||
|
### Cyclone DDS Security
|
||||||
|
|
||||||
|
Cyclone DDS Security implementation is composed of the following components/modifications:
|
||||||
|
|
||||||
|
* DDS Security plugin API
|
||||||
|
* DDS Security built-in plugins that implement the API
|
||||||
|
* DDS Security Core Library that is used by the plugins and DDSI.
|
||||||
|
* Changes in the DDSI that moderate the specified security model.
|
||||||
|
|
||||||
|
The dependency diagram:
|
||||||
|
|
||||||
|
|
||||||
|
DDSI ----> DDS Security API (headers only) <----- DDS Security Plugins
|
||||||
|
| ^ |
|
||||||
|
| | |
|
||||||
|
| | |
|
||||||
|
-------> DDS Security Core <------------------------
|
||||||
|
| | |
|
||||||
|
| | |
|
||||||
|
| | |
|
||||||
|
| v |
|
||||||
|
-------> DDS_RT <------------------------
|
||||||
|
|
||||||
|
All security specific contents are under src/security.
|
||||||
|
|
||||||
|
##### DDS Security API
|
||||||
|
|
||||||
|
The DDS Security plugin API consists of just a few header files. There are separate
|
||||||
|
header files for each plugin: dds_security_api_authentication.h dds_security_api_cryptography.h
|
||||||
|
and dds_security_api_access_control.c
|
||||||
|
|
||||||
|
The API functions and types are prepared from the IDL by adding DDS_Security_ namespace
|
||||||
|
prefix to functions and data types. Instead of extending DDS builtin topic data types,
|
||||||
|
separate DDS_Security_ data type is defined for the current type and the new secure data type.
|
||||||
|
|
||||||
|
##### Built-in Plugins
|
||||||
|
|
||||||
|
Cyclone DDS Security comes with three mandatory plugins: authentication, cryptography and access control.
|
||||||
|
|
||||||
|
###### Authentication Plugin
|
||||||
|
|
||||||
|
This plugin implements authentication using a trusted Certificate Authority (CA). It performs
|
||||||
|
mutual authentication between discovered participants using the RSA or ECDSA Digital Signature
|
||||||
|
Algorithms and establishes a shared secret using Diffie-Hellman (DH) or Elliptic Curve Diffie-Hellman
|
||||||
|
(ECDH) Key Agreement Methods.
|
||||||
|
|
||||||
|
<img src="pictures/dds_security_authentication_plugin.png" alt="DDS Security Plugin Components">
|
||||||
|
|
||||||
|
###### Cryptography Plugin
|
||||||
|
|
||||||
|
This plugin provides authenticated encryption using Advanced Encryption Standard (AES) in
|
||||||
|
Galois Counter Mode (AES-GCM). It supports two AES key sizes: 128 bits and 256 bits. It may
|
||||||
|
also provide additional reader-specific message authentication codes (MACs) using Galois MAC (AES-GMAC).
|
||||||
|
|
||||||
|
<img src="pictures/dds_security_crypto_plugin.png" alt="DDS Security Plugin Components">
|
||||||
|
|
||||||
|
|
||||||
|
###### Access Control Plugin
|
||||||
|
|
||||||
|
<img src="pictures/dds_security_access_control_plugin.png" alt="DDS Security Plugin Components">
|
||||||
|
|
||||||
|
|
BIN
docs/dev/pictures/dds_security_access_control_plugin.png
Normal file
After Width: | Height: | Size: 552 KiB |
BIN
docs/dev/pictures/dds_security_authentication_plugin.png
Normal file
After Width: | Height: | Size: 432 KiB |
BIN
docs/dev/pictures/dds_security_crypto_plugin.png
Normal file
After Width: | Height: | Size: 502 KiB |
BIN
docs/dev/pictures/dds_security_plugin_components.png
Normal file
After Width: | Height: | Size: 236 KiB |
32
docs/dev/todo_list.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# TODO LIST
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
* Reassess Jeroen's comment:
|
||||||
|
https://github.com/eclipse-cyclonedds/cyclonedds/pull/177#issuecomment-494040238
|
||||||
|
> 5. If the security_api just becomes part of ddsc, and it should in my opinion, then I'd prefer you propagate the naming scheme as introduced in ddsrt etc and name the header files e.g. dds/ddssec/auth.h or something instead of dds/security/dds_security_api_authentication.h.
|
||||||
|
|
||||||
|
* Reassess Jeroen's comment:
|
||||||
|
https://github.com/eclipse-cyclonedds/cyclonedds/pull/177#issuecomment-494040238
|
||||||
|
> I've spent a great deal of time stripping out all the various different error codes and make it so that we simply use DDS_RETCODE_ constants everywhere. This pull request reintroduces separate error codes and that's something I really don't approve of. The security error codes start at an offset of 100 and should nicely integrate with the other codes in dds/ddsrt/retcode.h. The messages should be retrievable using dds_strretcode if you ask me.
|
||||||
|
|
||||||
|
|
||||||
|
* reassess Erik's comment
|
||||||
|
https://github.com/eclipse-cyclonedds/cyclonedds/pull/177#issuecomment-490718462
|
||||||
|
> GuidPrefix & BuiltinTopicKey change
|
||||||
|
|
||||||
|
* reassess erik's comment
|
||||||
|
https://github.com/eclipse-cyclonedds/cyclonedds/pull/177#issuecomment-490718462
|
||||||
|
> ddsrt_strchrs
|
||||||
|
|
||||||
|
* Reassess Jeroen's comment:
|
||||||
|
https://github.com/eclipse-cyclonedds/cyclonedds/pull/177#issuecomment-494040238
|
||||||
|
> If the security_api just becomes part of ddsc, and it should in my opinion, then I'd prefer you propagate the naming scheme as introduced in ddsrt etc and name the header files e.g. dds/ddssec/auth.h or something instead of dds/security/dds_security_api_authentication.h.
|
||||||
|
|
||||||
|
* Reassess Jeroen's comment:
|
||||||
|
https://github.com/eclipse-cyclonedds/cyclonedds/pull/177#issuecomment-494040238
|
||||||
|
> If the security_api just becomes part of ddsc, and it should in my opinion, then I'd prefer you propagate the naming scheme as introduced in ddsrt etc and name the header files e.g. dds/ddssec/auth.h or something instead of dds/security/dds_security_api_authentication.h.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
131
docs/dev/volatile_msg_secure.md
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
# ParticipantVolatileMessageSecure Handling
|
||||||
|
|
||||||
|
## Short Introduction
|
||||||
|
|
||||||
|
It is expected to have some knowledge of DDSI builtin (security) endpoints.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER 0xff0202c3
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER 0xff0202c4
|
||||||
|
```
|
||||||
|
These builtin endpoints have caused about the biggest code change in ddsi, regarding security.
|
||||||
|
|
||||||
|
Chapters 7.4.4.3 and 7.4.4.4 in the DDS Security specification indicates the main issue why these builtin endpoints are different from all the others and somewhat more complex.
|
||||||
|
|
||||||
|
> 7.4.4.3 Contents of the ParticipantVolatileMessageSecure
|
||||||
|
> The ParticipantVolatileMessageSecure is intended as a holder of secure information that
|
||||||
|
> is sent point-to-point from a DomainParticipant to another.
|
||||||
|
>
|
||||||
|
> [...]
|
||||||
|
>
|
||||||
|
> 7.4.4.4 Destination of the ParticipantVolatileMessageSecure
|
||||||
|
>
|
||||||
|
> If the destination_participant_guid member is not set to GUID_UNKNOWN, the message written is
|
||||||
|
> intended only for the BuiltinParticipantVolatileMessageSecureReader belonging to the
|
||||||
|
> DomainParticipant with a matching Participant Key.
|
||||||
|
>
|
||||||
|
> This is equivalent to saying that the BuiltinParticipantVolatileMessageSecureReader has an implied
|
||||||
|
> content filter with the logical expression:
|
||||||
|
>
|
||||||
|
> “destination_participant_guid == GUID_UNKNOWN
|
||||||
|
> || destination_participant_guid==BuiltinParticipantVolatileMessageSecureReader.participant.guid”
|
||||||
|
>
|
||||||
|
> Implementations of the specification can use this content filter or some other mechanism as long as the
|
||||||
|
> resulting behavior is equivalent to having this filter.
|
||||||
|
>
|
||||||
|
> [...]
|
||||||
|
|
||||||
|
The "point-to-point" and "content filter" remarks makes everything more elaborate.
|
||||||
|
|
||||||
|
|
||||||
|
## Complexity
|
||||||
|
|
||||||
|
It would be nice to be able to use the ```dds_set_topic_filter()``` functionality for these endpoints. However, that only works on the reader history cache (rhc), which is only available for ddsc entities and not for ddsi builtin entities. And it's the builtin entities that are being used.
|
||||||
|
|
||||||
|
The ```dds_set_topic_filter()``` basically simulates that the sample was inserted into the rhc (but didn't insert it), which causes the rest of ddsi (regarding heartbeat, acknacks, gaps, etc) to work as normal while the sample just isn't provided to the reader.
|
||||||
|
|
||||||
|
Unfortunately, the builtin volatile endpoints can not use that same simple sequence (just handle the sample but ignore it right at the end). Problem is, the sample is encoded. It can only decode samples that are intended for that reader. This would mean that it is best for the reader to only receive 'owned' samples that it can actually decode.
|
||||||
|
|
||||||
|
This has all kinds of affects regarding the heartbeat, acknacks, gaps, etc. Basically, every writer/reader combination should have information regarding gaps and sequence numbers between them, while normally such information about proxies are combined.
|
||||||
|
|
||||||
|
|
||||||
|
## Implementation Overview
|
||||||
|
|
||||||
|
This only depicts an overview. Some details will have been omitted.
|
||||||
|
|
||||||
|
|
||||||
|
### Writing
|
||||||
|
|
||||||
|
The function ```write_crypto_exchange_message()``` takes care of generating the right sample information and pass it on to ```write_sample_p2p_wrlock_held()```.
|
||||||
|
|
||||||
|
A proxy reader can now have a filter callback function (```proxy_reader::filter```). This indicates (on the writer side) if a sample will be accepted by the actual reader or not. This could be made more generic for proper 'writer side' content filter implementation. However, now it'll only be used by ParticipantVolatileMessageSecure and the filter is hardcoded to ```volatile_secure_data_filter()```.
|
||||||
|
|
||||||
|
So, if ```write_sample_p2p_wrlock_held()``` is called with a proxy reader with a filter, it will get 'send/acked sequences' information between the writer and proxy reader. This is used to determine if gap information has to be send alongside the sample.
|
||||||
|
|
||||||
|
Then, ```write_sample_p2p_wrlock_held()``` will enqueue the sample.
|
||||||
|
|
||||||
|
Just before the submessage is added to the rtps message and send, it is encoded (todo).
|
||||||
|
|
||||||
|
|
||||||
|
### Reading
|
||||||
|
|
||||||
|
First things first, the submessage is decoded when the rtps message is received (todo).
|
||||||
|
|
||||||
|
It is received on a builtin reader, so the builtin queue is used and ```builtins_dqueue_handler()``` is called. That will forward the sample to the token exchange functionality, ignoring every sample that isn't related to the related participant (todo).
|
||||||
|
|
||||||
|
|
||||||
|
### Gaps on reader side
|
||||||
|
|
||||||
|
The reader remembers the last_seq it knows from every connected proxy writer (```pwr_rd_match::last_seq```).
|
||||||
|
This is updated when handling heartbeats, gaps and regular messages and used to check if there are gaps.
|
||||||
|
Normally, the ```last_seq``` of a specific writer is used here. But when the reader knows that the writer uses a 'writer side content filter' (```proxy_writer::uses_filter```), it'll use the the ```last_seq``` that is related to the actual reader/writer match.
|
||||||
|
It is used to generate the AckNack (which contains gap information) response to the writer.
|
||||||
|
|
||||||
|
|
||||||
|
### Gaps on writer side
|
||||||
|
|
||||||
|
The writer remembers which sample sequence it send the last to a specific reader through ```wr_prd_match::lst_seq```.
|
||||||
|
This is used to determine if a reader has received all relevant samples (through handling of acknack).
|
||||||
|
It is also used to determine the gap information that is added to samples to a specific reader when necessary.
|
||||||
|
|
||||||
|
|
||||||
|
### Heartbeats
|
||||||
|
|
||||||
|
A writer is triggered to send heartbeats once in a while. Normally, that is broadcasted. But, for the volatile secure writer, it has to be send to each reader specifically. The heartbeat submessage that is send to each reader individually is encoded with a reader specific key. This key is generated from the shared secret which was determined during the authentication phase.
|
||||||
|
|
||||||
|
When a writer should send heartbeats, ```handle_xevk_heartbeat()``` is called. For the volatile secure writer, the control is immediately submitted to ```send_heartbeat_to_all_readers()```. This will add heartbeat submessages to an rtps message for every reader it deems necessary.
|
||||||
|
|
||||||
|
|
||||||
|
### Reorder
|
||||||
|
|
||||||
|
Normally received samples are placed in the reorder administration of the proxy_writer. However in this case the writer applies a content filter which is specific for each destinated reader. In that case the common reorder administration in the proxy_writer can not be used and the reader specific reorder administration must be used to handle the gap's which will be reader specific.
|
||||||
|
|
||||||
|
</br>
|
||||||
|
</br>
|
||||||
|
</br>
|
||||||
|
=================================================</br>
|
||||||
|
Notes</br>
|
||||||
|
=================================================</br>
|
||||||
|
|
||||||
|
### Trying to put the security participant volatile endpoint implementation into context.
|
||||||
|
|
||||||
|
The following elements are added to the data structures:
|
||||||
|
|
||||||
|
* struct wr_prd_match::lst_seq : Highest seq send to this reader used when filter is applied
|
||||||
|
* struct pwr_rd_match::last_seq : Reader specific last received sequence number from the writer.
|
||||||
|
* struct proxy_writer::uses_filter : Indicates that a content-filter is active
|
||||||
|
* struct proxy_reader::filter : The filter to apply for this specific reader
|
||||||
|
|
||||||
|
Functions added:
|
||||||
|
|
||||||
|
* writer_hbcontrol_p2p : This function creates a heartbeat destined for a specific reader. The volatile secure writer will use an submessage encoding which uses a distinct key for each reader. Therefor a reader specific heartbeat is needed.
|
||||||
|
* nn_defrag_prune : When a volatile secure reader is deleted then the defragmentation administration could still contain messages destined for this reader. This function removes these messages from the defragmentation administration.
|
||||||
|
* volatile_secure_data_filter : The filter applied to the secure volatile messages which filters on the destination participant guid.
|
||||||
|
* write_sample_p2p_wrlock_held : This function writes a message to a particular reader.
|
||||||
|
|
||||||
|
The use of the content-filter for the volatile secure writer implies that for each destination reader which message from the writer history cache is valid and had to be sent.
|
||||||
|
For messages that do not match this filter a GAP message should be sent to the reader. Each time a message is sent to a specific reader a possible gap message is added.
|
||||||
|
For the volatile secure writer the sequence number of the last message send to a particular reader is maintained in ```wr_prd_match::lst_seq'''. It is used to determine if a
|
||||||
|
HEARTBEAT has to send to this particular reader or that the reader has acknowledged all messages. At the reader side the sequence number of the last received message is
|
||||||
|
maintained in ```pwr_rd_match::last_seq'''. It is used to determine the contents of the ACKNACK message as response to a received HEARTBEAT.
|
||||||
|
When an ACKNACK (handle_AckNack) is received it is determined which samples should be resent related to the applied filter and for which sequence numbers a GAP message should be sent.
|
|
@ -486,6 +486,7 @@ sub read_config {
|
||||||
'DDSI_INCLUDE_SSL' => 1,
|
'DDSI_INCLUDE_SSL' => 1,
|
||||||
'DDSI_INCLUDE_NETWORK_PARTITIONS' => 1,
|
'DDSI_INCLUDE_NETWORK_PARTITIONS' => 1,
|
||||||
'DDSI_INCLUDE_SSM' => 1,
|
'DDSI_INCLUDE_SSM' => 1,
|
||||||
|
'DDSI_INCLUDE_SECURITY' => 1,
|
||||||
# excluded options
|
# excluded options
|
||||||
'DDSI_INCLUDE_NETWORK_CHANNELS' => 0,
|
'DDSI_INCLUDE_NETWORK_CHANNELS' => 0,
|
||||||
'DDSI_INCLUDE_BANDWIDTH_LIMITING' => 0);
|
'DDSI_INCLUDE_BANDWIDTH_LIMITING' => 0);
|
||||||
|
@ -625,7 +626,7 @@ sub read_config {
|
||||||
# skip reference to internal name (either ABSOFF(field),
|
# skip reference to internal name (either ABSOFF(field),
|
||||||
# RELOFF(field,field) or <int>,<int> (the latter being used by
|
# RELOFF(field,field) or <int>,<int> (the latter being used by
|
||||||
# "verbosity")
|
# "verbosity")
|
||||||
$rest =~ s/(ABSOFF *\( *[A-Za-z_0-9.]+ *\)|RELOFF *\( *[A-Za-z_0-9.]+ *, *[A-Za-z_0-9]+ *\)|[0-9]+ *, *[0-9]+) *, *//;
|
$rest =~ s/(ABSOFF *\( *[A-Za-z_0-9.]+ *\)|RELOFF *\( *[A-Za-z_0-9.]+ *, *[A-Za-z_0-9. ]+\)|[0-9]+ *, *[0-9]+) *, *//;
|
||||||
# skip init function
|
# skip init function
|
||||||
$rest =~ s/([A-Za-z_0-9]+|0) *, *//;
|
$rest =~ s/([A-Za-z_0-9]+|0) *, *//;
|
||||||
# type hint from conversion function
|
# type hint from conversion function
|
||||||
|
|
29
docs/manual/_static/example_governance.xml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?xml version="1.0" encoding=\"utf-8\"?>
|
||||||
|
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://www.omg.org/spec/DDS-SECURITY/20170901/omg_shared_ca_governance.xsd">
|
||||||
|
<domain_access_rules>
|
||||||
|
<domain_rule>
|
||||||
|
<domains>
|
||||||
|
<id_range>
|
||||||
|
<min>0</min>
|
||||||
|
<max>230</max>
|
||||||
|
</id_range>
|
||||||
|
</domains>
|
||||||
|
<allow_unauthenticated_participants>false</allow_unauthenticated_participants>
|
||||||
|
<enable_join_access_control>true</enable_join_access_control>
|
||||||
|
<discovery_protection_kind>NONE</discovery_protection_kind>
|
||||||
|
<liveliness_protection_kind>NONE</liveliness_protection_kind>
|
||||||
|
<rtps_protection_kind>NONE</rtps_protection_kind>
|
||||||
|
<topic_access_rules>
|
||||||
|
<topic_rule>
|
||||||
|
<topic_expression>*</topic_expression>
|
||||||
|
<enable_discovery_protection>true</enable_discovery_protection>
|
||||||
|
<enable_liveliness_protection>true</enable_liveliness_protection>
|
||||||
|
<enable_read_access_control>true</enable_read_access_control>
|
||||||
|
<enable_write_access_control>true</enable_write_access_control>
|
||||||
|
<metadata_protection_kind>SIGN</metadata_protection_kind>
|
||||||
|
<data_protection_kind>ENCRYPT</data_protection_kind>
|
||||||
|
</topic_rule>
|
||||||
|
</topic_access_rules>
|
||||||
|
</domain_rule>
|
||||||
|
</domain_access_rules>
|
||||||
|
</dds>
|
39
docs/manual/_static/example_permissions.xml
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://www.omg.org/spec/DDS-SECURITY/20170901/omg_shared_ca_permissions.xsd">
|
||||||
|
<permissions>
|
||||||
|
<grant name="default_permissions">
|
||||||
|
<subject_name>emailAddress=alice@cycloneddssecurity.adlinktech.com,CN=Alice Example,O=Example Organization,OU=Organizational Unit Name,L=Locality Name,ST=OV,C=NL</subject_name>
|
||||||
|
<validity>
|
||||||
|
<!-- Format is CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] in GMT -->
|
||||||
|
<not_before>2020-01-01T01:00:00</not_before>
|
||||||
|
<not_after>2120-01-01T01:00:00</not_after>
|
||||||
|
</validity>
|
||||||
|
<allow_rule>
|
||||||
|
<domains>
|
||||||
|
<id_range>
|
||||||
|
<min>0</min>
|
||||||
|
<max>230</max>
|
||||||
|
</id_range>
|
||||||
|
</domains>
|
||||||
|
<publish>
|
||||||
|
<topics>
|
||||||
|
<topic>*</topic>
|
||||||
|
</topics>
|
||||||
|
<partitions>
|
||||||
|
<partition>*</partition>
|
||||||
|
</partitions>
|
||||||
|
</publish>
|
||||||
|
<subscribe>
|
||||||
|
<topics>
|
||||||
|
<topic>*</topic>
|
||||||
|
</topics>
|
||||||
|
<partitions>
|
||||||
|
<partition>*</partition>
|
||||||
|
</partitions>
|
||||||
|
</subscribe>
|
||||||
|
</allow_rule>
|
||||||
|
<default>DENY</default>
|
||||||
|
</grant>
|
||||||
|
</permissions>
|
||||||
|
</dds>
|
After Width: | Height: | Size: 47 KiB |
BIN
docs/manual/_static/pictures/dds_security_overview.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
docs/manual/_static/pictures/pki_overview.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
docs/manual/_static/pictures/rtps_message_structure.png
Normal file
After Width: | Height: | Size: 14 KiB |
19
docs/manual/_static/security_by_config.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<Domain id="any">
|
||||||
|
<DDSSecurity>
|
||||||
|
<Authentication>
|
||||||
|
<Library initFunction="init_authentication" finalizeFunction="finalize_authentication" path="dds_security_auth"/>
|
||||||
|
<IdentityCA>file:/path/to/example_id_ca_cert.pem</IdentityCA>
|
||||||
|
<IdentityCertificate>file:/path/to/example_alice_cert.pem</IdentityCertificate>
|
||||||
|
<PrivateKey>file:/path/to/example_alice_priv_key.pem</PrivateKey>
|
||||||
|
</Authentication>
|
||||||
|
<Cryptographic>
|
||||||
|
<Library initFunction="init_crypto" finalizeFunction="finalize_crypto" path="dds_security_crypto"/>
|
||||||
|
</Cryptographic>
|
||||||
|
<AccessControl>
|
||||||
|
<Library initFunction="init_access_control" finalizeFunction="finalize_access_control" path="dds_security_ac"/>
|
||||||
|
<PermissionsCA>file:/path/to/example_perm_ca_cert.pem</PermissionsCA>
|
||||||
|
<Governance>file:/path/to/example_governance.p7s</Governance>
|
||||||
|
<Permissions>file:/path/to/example_permissions.p7s</Permissions>
|
||||||
|
</AccessControl>
|
||||||
|
</DDSSecurity>
|
||||||
|
</Domain>
|
21
docs/manual/_static/security_by_qos.c
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
dds_qos_t * qos = dds_create_qos();
|
||||||
|
|
||||||
|
dds_qset_prop(qos, "dds.sec.auth.library.path", "dds_security_auth");
|
||||||
|
dds_qset_prop(qos, "dds.sec.auth.library.init", "init_authentication");
|
||||||
|
dds_qset_prop(qos, "dds.sec.auth.library.finalize", "finalize_authentication");
|
||||||
|
dds_qset_prop(qos, "dds.sec.auth.identity_ca", "file:/path/to/example_id_ca_cert.pem");
|
||||||
|
dds_qset_prop(qos, "dds.sec.auth.private_key", "file:/path/to/example_alice_priv_key.pem");
|
||||||
|
dds_qset_prop(qos, "dds.sec.auth.identity_certificate", "file:/path/to/example_alice_cert.pem");
|
||||||
|
|
||||||
|
dds_qset_prop(qos, "dds.sec.crypto.library.path", "dds_security_crypto");
|
||||||
|
dds_qset_prop(qos, "dds.sec.crypto.library.init", "init_crypto");
|
||||||
|
dds_qset_prop(qos, "dds.sec.crypto.library.finalize", "finalize_crypto");
|
||||||
|
|
||||||
|
dds_qset_prop(qos, "dds.sec.access.library.path", "dds_security_ac");
|
||||||
|
dds_qset_prop(qos, "dds.sec.access.library.init", "init_access_control");
|
||||||
|
dds_qset_prop(qos, "dds.sec.access.library.finalize", "finalize_access_control");
|
||||||
|
dds_qset_prop(qos, "dds.sec.access.permissions_ca", "file:/path/to/example_perm_ca_cert.pem");
|
||||||
|
dds_qset_prop(qos, "dds.sec.access.governance", "file:/path/to/example_governance.p7s");
|
||||||
|
dds_qset_prop(qos, "dds.sec.access.permissions", "file:/path/to/example_permissions.p7s");
|
||||||
|
|
||||||
|
dds_entity_t participant = dds_create_participant(0, qos, NULL);
|
|
@ -21,6 +21,7 @@ Welcome to Eclipse Cyclone DDS's documentation!
|
||||||
GettingStartedGuide/index
|
GettingStartedGuide/index
|
||||||
ddsc
|
ddsc
|
||||||
config
|
config
|
||||||
|
security
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -8,7 +8,7 @@ CycloneDDS configuration
|
||||||
## //CycloneDDS/Domain
|
## //CycloneDDS/Domain
|
||||||
Attributes: [Id](#cycloneddsdomainid)
|
Attributes: [Id](#cycloneddsdomainid)
|
||||||
|
|
||||||
Children: [Compatibility](#cycloneddsdomaincompatibility), [Discovery](#cycloneddsdomaindiscovery), [General](#cycloneddsdomaingeneral), [Internal](#cycloneddsdomaininternal), [Partitioning](#cycloneddsdomainpartitioning), [SSL](#cycloneddsdomainssl), [Sizing](#cycloneddsdomainsizing), [TCP](#cycloneddsdomaintcp), [ThreadPool](#cycloneddsdomainthreadpool), [Threads](#cycloneddsdomainthreads), [Tracing](#cycloneddsdomaintracing)
|
Children: [Compatibility](#cycloneddsdomaincompatibility), [DDSSecurity](#cycloneddsdomainddssecurity), [Discovery](#cycloneddsdomaindiscovery), [General](#cycloneddsdomaingeneral), [Internal](#cycloneddsdomaininternal), [Partitioning](#cycloneddsdomainpartitioning), [SSL](#cycloneddsdomainssl), [Sizing](#cycloneddsdomainsizing), [TCP](#cycloneddsdomaintcp), [ThreadPool](#cycloneddsdomainthreadpool), [Threads](#cycloneddsdomainthreads), [Tracing](#cycloneddsdomaintracing)
|
||||||
|
|
||||||
|
|
||||||
The General element specifying Domain related settings.
|
The General element specifying Domain related settings.
|
||||||
|
@ -100,8 +100,370 @@ The default setting is "lax".
|
||||||
The default value is: "lax".
|
The default value is: "lax".
|
||||||
|
|
||||||
|
|
||||||
|
### //CycloneDDS/Domain/DDSSecurity
|
||||||
|
Children: [AccessControl](#cycloneddsdomainddssecurityaccesscontrol), [Authentication](#cycloneddsdomainddssecurityauthentication), [Cryptographic](#cycloneddsdomainddssecuritycryptographic)
|
||||||
|
|
||||||
|
|
||||||
|
This element is used to configure Cyclone DDS with the DDS Security
|
||||||
|
specification plugins and settings.
|
||||||
|
|
||||||
|
|
||||||
|
#### //CycloneDDS/Domain/DDSSecurity/AccessControl
|
||||||
|
Children: [Governance](#cycloneddsdomainddssecurityaccesscontrolgovernance), [Library](#cycloneddsdomainddssecurityaccesscontrollibrary), [Permissions](#cycloneddsdomainddssecurityaccesscontrolpermissions), [PermissionsCA](#cycloneddsdomainddssecurityaccesscontrolpermissionsca)
|
||||||
|
|
||||||
|
|
||||||
|
This element configures the Access Control plugin of the DDS Security
|
||||||
|
specification.
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/AccessControl/Governance
|
||||||
|
Text
|
||||||
|
|
||||||
|
URI to the shared Governance Document signed by the Permissions CA in
|
||||||
|
S/MIME format
|
||||||
|
|
||||||
|
URI schemes: file, data<br>
|
||||||
|
|
||||||
|
Examples file URIs:
|
||||||
|
|
||||||
|
<Governance>file:governance.smime</Governance>
|
||||||
|
|
||||||
|
<Governance>file:/home/myuser/governance.smime</Governance><br>
|
||||||
|
|
||||||
|
<Governance><![CDATA[data:,MIME-Version: 1.0
|
||||||
|
|
||||||
|
Content-Type: multipart/signed; protocol="application/x-pkcs7-signature";
|
||||||
|
micalg="sha-256"; boundary="----F9A8A198D6F08E1285A292ADF14DD04F"
|
||||||
|
|
||||||
|
This is an S/MIME signed message
|
||||||
|
|
||||||
|
------F9A8A198D6F08E1285A292ADF14DD04F
|
||||||
|
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
|
||||||
|
xsi:noNamespaceSchemaLocation="omg_shared_ca_governance.xsd">
|
||||||
|
|
||||||
|
<domain_access_rules>
|
||||||
|
|
||||||
|
. . .
|
||||||
|
|
||||||
|
</domain_access_rules>
|
||||||
|
|
||||||
|
</dds>
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
------F9A8A198D6F08E1285A292ADF14DD04F
|
||||||
|
|
||||||
|
Content-Type: application/x-pkcs7-signature; name="smime.p7s"
|
||||||
|
|
||||||
|
Content-Transfer-Encoding: base64
|
||||||
|
|
||||||
|
Content-Disposition: attachment; filename="smime.p7s"
|
||||||
|
|
||||||
|
MIIDuAYJKoZIhv ...al5s=
|
||||||
|
|
||||||
|
------F9A8A198D6F08E1285A292ADF14DD04F-]]</Governance>
|
||||||
|
|
||||||
|
The default value is: "".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/AccessControl/Library
|
||||||
|
Attributes: [finalizeFunction](#cycloneddsdomainddssecurityaccesscontrollibraryfinalizefunction), [initFunction](#cycloneddsdomainddssecurityaccesscontrollibraryinitfunction), [path](#cycloneddsdomainddssecurityaccesscontrollibrarypath)
|
||||||
|
|
||||||
|
|
||||||
|
This element specifies the library to be loaded as the DDS Security
|
||||||
|
Access Control plugin.
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/AccessControl/Library[@finalizeFunction]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element names the finalization function of Access Control plugin.
|
||||||
|
This function is called to let the plugin release its resources.
|
||||||
|
|
||||||
|
The default value is: "finalize_access_control".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/AccessControl/Library[@initFunction]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element names the initialization function of Access Control plugin.
|
||||||
|
This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Access Control interface.
|
||||||
|
|
||||||
|
The default value is: "init_access_control".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/AccessControl/Library[@path]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element points to the path of Access Control plugin library.
|
||||||
|
|
||||||
|
It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_ac ) or single file without extension (
|
||||||
|
dds_security_ac ).
|
||||||
|
|
||||||
|
If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.
|
||||||
|
|
||||||
|
The default value is: "dds_security_ac".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/AccessControl/Permissions
|
||||||
|
Text
|
||||||
|
|
||||||
|
URI to the DomainParticipant permissions document signed by the
|
||||||
|
Permissions CA in S/MIME format
|
||||||
|
|
||||||
|
The permissions document specifies the permissions to be applied to a
|
||||||
|
domain.<br>
|
||||||
|
|
||||||
|
Example file URIs:
|
||||||
|
|
||||||
|
<Permissions>file:permissions_document.p7s</Permissions>
|
||||||
|
|
||||||
|
<Permissions>file:/path_to/permissions_document.p7s</Permissions>
|
||||||
|
|
||||||
|
Example data URI:
|
||||||
|
|
||||||
|
<Permissions><![CDATA[data:,.........]]</Permissions>
|
||||||
|
|
||||||
|
The default value is: "".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/AccessControl/PermissionsCA
|
||||||
|
Text
|
||||||
|
|
||||||
|
URI to a X509 certificate for the PermissionsCA in PEM format.
|
||||||
|
|
||||||
|
Supported URI schemes: file, data
|
||||||
|
|
||||||
|
The file and data schemas shall refer to a X.509 v3 certificate (see
|
||||||
|
X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.<br>
|
||||||
|
|
||||||
|
Examples:<br>
|
||||||
|
|
||||||
|
<PermissionsCA>file:permissions_ca.pem</PermissionsCA>
|
||||||
|
|
||||||
|
<PermissionsCA>file:/home/myuser/permissions_ca.pem</PermissionsCA><br>
|
||||||
|
|
||||||
|
<PermissionsCA>data:<strong>,</strong>-----BEGIN CERTIFICATE-----
|
||||||
|
|
||||||
|
MIIC3DCCAcQCCQCWE5x+Z ... PhovK0mp2ohhRLYI0ZiyYQ==
|
||||||
|
|
||||||
|
-----END CERTIFICATE-----</PermissionsCA>
|
||||||
|
|
||||||
|
The default value is: "".
|
||||||
|
|
||||||
|
|
||||||
|
#### //CycloneDDS/Domain/DDSSecurity/Authentication
|
||||||
|
Children: [IdentityCA](#cycloneddsdomainddssecurityauthenticationidentityca), [IdentityCertificate](#cycloneddsdomainddssecurityauthenticationidentitycertificate), [IncludeOptionalFields](#cycloneddsdomainddssecurityauthenticationincludeoptionalfields), [Library](#cycloneddsdomainddssecurityauthenticationlibrary), [Password](#cycloneddsdomainddssecurityauthenticationpassword), [PrivateKey](#cycloneddsdomainddssecurityauthenticationprivatekey), [TrustedCADirectory](#cycloneddsdomainddssecurityauthenticationtrustedcadirectory)
|
||||||
|
|
||||||
|
|
||||||
|
This element configures the Authentication plugin of the DDS Security
|
||||||
|
specification.
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA
|
||||||
|
Text
|
||||||
|
|
||||||
|
URI to the X509 certificate [39] of the Identity CA that is the signer of
|
||||||
|
Identity Certificate.
|
||||||
|
|
||||||
|
Supported URI schemes: file, data
|
||||||
|
|
||||||
|
The file and data schemas shall refer to a X.509 v3 certificate (see
|
||||||
|
X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
<IdentityCA>file:identity_ca.pem</IdentityCA>
|
||||||
|
|
||||||
|
<IdentityCA>data:,-----BEGIN CERTIFICATE-----<br>
|
||||||
|
|
||||||
|
MIIC3DCCAcQCCQCWE5x+Z...PhovK0mp2ohhRLYI0ZiyYQ==<br>
|
||||||
|
|
||||||
|
-----END CERTIFICATE-----</IdentityCA>
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate
|
||||||
|
Text
|
||||||
|
|
||||||
|
Identity certificate that will be used for identifying all participants
|
||||||
|
in the OSPL instance.<br>The content is URI to a X509 certificate signed
|
||||||
|
by the IdentityCA in PEM format containing the signed public key.
|
||||||
|
|
||||||
|
Supported URI schemes: file, data
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
<IdentityCertificate>file:participant1_identity_cert.pem</IdentityCertificate>
|
||||||
|
|
||||||
|
<IdentityCertificate>data:,-----BEGIN CERTIFICATE-----<br>
|
||||||
|
|
||||||
|
MIIDjjCCAnYCCQDCEu9...6rmT87dhTo=<br>
|
||||||
|
|
||||||
|
-----END CERTIFICATE-----</IdentityCertificate>
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/IncludeOptionalFields
|
||||||
|
Boolean
|
||||||
|
|
||||||
|
The authentication handshake tokens may contain optional fields to be
|
||||||
|
included for finding interoperability problems.
|
||||||
|
|
||||||
|
If this parameter is set to true the optional fields are included in the
|
||||||
|
handshake token exchange.
|
||||||
|
|
||||||
|
The default value is: "false".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/Library
|
||||||
|
Attributes: [finalizeFunction](#cycloneddsdomainddssecurityauthenticationlibraryfinalizefunction), [initFunction](#cycloneddsdomainddssecurityauthenticationlibraryinitfunction), [path](#cycloneddsdomainddssecurityauthenticationlibrarypath)
|
||||||
|
|
||||||
|
|
||||||
|
This element specifies the library to be loaded as the DDS Security
|
||||||
|
Access Control plugin.
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/Library[@finalizeFunction]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element names the finalization function of Authentication plugin.
|
||||||
|
This function is called to let the plugin release its resources.
|
||||||
|
|
||||||
|
The default value is: "finalize_authentication".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/Library[@initFunction]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element names the initialization function of Authentication plugin.
|
||||||
|
This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Authentication interface.
|
||||||
|
|
||||||
|
The default value is: "init_authentication".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/Library[@path]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element points to the path of Authentication plugin library.
|
||||||
|
|
||||||
|
It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_auth ) or single file without extension (
|
||||||
|
dds_security_auth ).
|
||||||
|
|
||||||
|
If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.
|
||||||
|
|
||||||
|
The default value is: "dds_security_auth".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/Password
|
||||||
|
Text
|
||||||
|
|
||||||
|
A password used to decrypt the private_key.
|
||||||
|
|
||||||
|
The value of the password property shall be interpreted as the Base64
|
||||||
|
encoding of the AES-128 key that shall be used to decrypt the private_key
|
||||||
|
using AES128-CBC.
|
||||||
|
|
||||||
|
If the password property is not present, then the value supplied in the
|
||||||
|
private_key property must contain the unencrypted private key.
|
||||||
|
|
||||||
|
The default value is: "".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey
|
||||||
|
Text
|
||||||
|
|
||||||
|
URI to access the private Private Key for all of the participants in the
|
||||||
|
OSPL federation.
|
||||||
|
|
||||||
|
Supported URI schemes: file, data
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
<PrivateKey>file:identity_ca_private_key.pem</PrivateKey>
|
||||||
|
|
||||||
|
<PrivateKey>data:,-----BEGIN RSA PRIVATE KEY-----<br>
|
||||||
|
|
||||||
|
MIIEpAIBAAKCAQEA3HIh...AOBaaqSV37XBUJg==<br>
|
||||||
|
|
||||||
|
-----END RSA PRIVATE KEY-----</PrivateKey>
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Authentication/TrustedCADirectory
|
||||||
|
Text
|
||||||
|
|
||||||
|
Trusted CA Directory which contains trusted CA certificates as separated
|
||||||
|
files.
|
||||||
|
|
||||||
|
The default value is: "".
|
||||||
|
|
||||||
|
|
||||||
|
#### //CycloneDDS/Domain/DDSSecurity/Cryptographic
|
||||||
|
Children: [Library](#cycloneddsdomainddssecuritycryptographiclibrary)
|
||||||
|
|
||||||
|
|
||||||
|
This element configures the Cryptographic plugin of the DDS Security
|
||||||
|
specification.
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Cryptographic/Library
|
||||||
|
Attributes: [finalizeFunction](#cycloneddsdomainddssecuritycryptographiclibraryfinalizefunction), [initFunction](#cycloneddsdomainddssecuritycryptographiclibraryinitfunction), [path](#cycloneddsdomainddssecuritycryptographiclibrarypath)
|
||||||
|
|
||||||
|
|
||||||
|
This element specifies the library to be loaded as the DDS Security
|
||||||
|
Cryptographic plugin.
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Cryptographic/Library[@finalizeFunction]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element names the finalization function of Cryptographic plugin.
|
||||||
|
This function is called to let the plugin release its resources.
|
||||||
|
|
||||||
|
The default value is: "finalize_crypto".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Cryptographic/Library[@initFunction]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element names the initialization function of Cryptographic plugin.
|
||||||
|
This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Cryptographic interface.
|
||||||
|
|
||||||
|
The default value is: "init_crypto".
|
||||||
|
|
||||||
|
|
||||||
|
##### //CycloneDDS/Domain/DDSSecurity/Cryptographic/Library[@path]
|
||||||
|
Text
|
||||||
|
|
||||||
|
This element points to the path of Cryptographic plugin library.
|
||||||
|
|
||||||
|
It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_crypto ) or single file without extension (
|
||||||
|
dds_security_crypto ).
|
||||||
|
|
||||||
|
If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.
|
||||||
|
|
||||||
|
The default value is: "dds_security_crypto".
|
||||||
|
|
||||||
|
|
||||||
### //CycloneDDS/Domain/Discovery
|
### //CycloneDDS/Domain/Discovery
|
||||||
Children: [DSGracePeriod](#cycloneddsdomaindiscoverydsgraceperiod), [DefaultMulticastAddress](#cycloneddsdomaindiscoverydefaultmulticastaddress), [EnableTopicDiscovery](#cycloneddsdomaindiscoveryenabletopicdiscovery), [ExternalDomainId](#cycloneddsdomaindiscoveryexternaldomainid), [MaxAutoParticipantIndex](#cycloneddsdomaindiscoverymaxautoparticipantindex), [ParticipantIndex](#cycloneddsdomaindiscoveryparticipantindex), [Peers](#cycloneddsdomaindiscoverypeers), [Ports](#cycloneddsdomaindiscoveryports), [SPDPInterval](#cycloneddsdomaindiscoveryspdpinterval), [SPDPMulticastAddress](#cycloneddsdomaindiscoveryspdpmulticastaddress), [Tag](#cycloneddsdomaindiscoverytag)
|
Children: [DSGracePeriod](#cycloneddsdomaindiscoverydsgraceperiod), [DefaultMulticastAddress](#cycloneddsdomaindiscoverydefaultmulticastaddress), [ExternalDomainId](#cycloneddsdomaindiscoveryexternaldomainid), [MaxAutoParticipantIndex](#cycloneddsdomaindiscoverymaxautoparticipantindex), [ParticipantIndex](#cycloneddsdomaindiscoveryparticipantindex), [Peers](#cycloneddsdomaindiscoverypeers), [Ports](#cycloneddsdomaindiscoveryports), [SPDPInterval](#cycloneddsdomaindiscoveryspdpinterval), [SPDPMulticastAddress](#cycloneddsdomaindiscoveryspdpmulticastaddress), [Tag](#cycloneddsdomaindiscoverytag)
|
||||||
|
|
||||||
|
|
||||||
The Discovery element allows specifying various parameters related to the
|
The Discovery element allows specifying various parameters related to the
|
||||||
|
@ -132,14 +494,6 @@ Discovery/SPDPMulticastAddress.
|
||||||
The default value is: "auto".
|
The default value is: "auto".
|
||||||
|
|
||||||
|
|
||||||
#### //CycloneDDS/Domain/Discovery/EnableTopicDiscovery
|
|
||||||
Boolean
|
|
||||||
|
|
||||||
Do not use.
|
|
||||||
|
|
||||||
The default value is: "true".
|
|
||||||
|
|
||||||
|
|
||||||
#### //CycloneDDS/Domain/Discovery/ExternalDomainId
|
#### //CycloneDDS/Domain/Discovery/ExternalDomainId
|
||||||
Text
|
Text
|
||||||
|
|
||||||
|
@ -995,7 +1349,7 @@ is therefore recommended to set it to at least several seconds.
|
||||||
Valid values are finite durations with an explicit unit or the keyword
|
Valid values are finite durations with an explicit unit or the keyword
|
||||||
'inf' for infinity. Recognised units: ns, us, ms, s, min, hr, day.
|
'inf' for infinity. Recognised units: ns, us, ms, s, min, hr, day.
|
||||||
|
|
||||||
The default value is: "10s".
|
The default value is: "0s".
|
||||||
|
|
||||||
|
|
||||||
#### //CycloneDDS/Domain/Internal/RediscoveryBlacklistDuration[@enforce]
|
#### //CycloneDDS/Domain/Internal/RediscoveryBlacklistDuration[@enforce]
|
||||||
|
@ -1646,6 +2000,8 @@ threads exist:
|
||||||
|
|
||||||
* tev: general timed-event handling, retransmits and discovery;
|
* tev: general timed-event handling, retransmits and discovery;
|
||||||
|
|
||||||
|
* fsm: finite state machine thread for handling security handshake;
|
||||||
|
|
||||||
* xmit.CHAN: transmit thread for channel CHAN;
|
* xmit.CHAN: transmit thread for channel CHAN;
|
||||||
|
|
||||||
* dq.CHAN: delivery thread for channel CHAN;
|
* dq.CHAN: delivery thread for channel CHAN;
|
||||||
|
|
801
docs/manual/security.rst
Normal file
|
@ -0,0 +1,801 @@
|
||||||
|
.. _`DDS Security`:
|
||||||
|
|
||||||
|
############
|
||||||
|
DDS Security
|
||||||
|
############
|
||||||
|
|
||||||
|
CycloneDDS is compliant with The Object Management Group (OMG) DDS Security specification.
|
||||||
|
|
||||||
|
This specification defines the Security Model and Service Plugin Interface (SPI) architecture for
|
||||||
|
compliant DDS implementations. The DDS Security Model is enforced by the invocation of these SPIs
|
||||||
|
by the DDS implementation.
|
||||||
|
|
||||||
|
.. image:: ./_static/pictures/dds_security_overview.png
|
||||||
|
:width: 1000
|
||||||
|
|
||||||
|
The three plugins that comprise the DDS Security Model in CycloneDDS are:
|
||||||
|
|
||||||
|
|
||||||
|
**Authentication Service Plugin**
|
||||||
|
|
||||||
|
Provides the means to verify the identity of the application and/or user that invokes operations
|
||||||
|
on DDS. Includes facilities to perform mutual authentication between participants and establish
|
||||||
|
a shared secret.
|
||||||
|
|
||||||
|
**AccessControl Service Plugin**
|
||||||
|
|
||||||
|
Provides the means to enforce policy decisions on what DDS related operations an authenticated
|
||||||
|
user can perform. For example, which domains it can join, which Topics it can publish or
|
||||||
|
subscribe to, etc.
|
||||||
|
|
||||||
|
**Cryptographic Service Plugin**
|
||||||
|
|
||||||
|
Implements (or interfaces with libraries that implement) all cryptographic operations including
|
||||||
|
encryption, decryption, hashing, digital signatures, etc. This includes the means to derive keys
|
||||||
|
from a shared secret.
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
CycloneDDS provides built-in implementations of these plugins. Authentication uses PKI
|
||||||
|
(Public Key Infrastructure) with a pre-configured shared Certificate Authority, RSA is used for
|
||||||
|
authentication and Diffie-Hellman is used for key exchange. AccessControl use Permissions document
|
||||||
|
signed by shared Certificate Authority. Cryptography uses AES-GCM (AES using Galois Counter Mode)
|
||||||
|
for encryption and AES-GMAC for message authentication.
|
||||||
|
|
||||||
|
Security plugins are dynamically loaded where the locations are defined in CycloneDDS
|
||||||
|
configuration or Participant QoS settings.
|
||||||
|
|
||||||
|
|
||||||
|
*******************************************************
|
||||||
|
Brief information about PKI (public key infrastructure)
|
||||||
|
*******************************************************
|
||||||
|
|
||||||
|
The comprehensive system required to provide public-key encryption and digital signature services
|
||||||
|
is known as a public-key infrastructure (PKI). The purpose of a PKI is to manage keys and
|
||||||
|
certificates. By managing keys and certificates through a PKI, an organization establishes and
|
||||||
|
maintains a trustworthy networking environment.
|
||||||
|
|
||||||
|
Public Key Cryptography: Each user has a key pair, generated during the initial certificate
|
||||||
|
deployment process, that is comprised of a public key, which is shared, and a private key, which
|
||||||
|
is not shared. Data is encrypted with the user’s public key and decrypted with their private key.
|
||||||
|
Digital signatures, used for non-repudiation, authentication and data integrity, are also generated
|
||||||
|
using public key cryptography.
|
||||||
|
|
||||||
|
**Identity Certificate**
|
||||||
|
|
||||||
|
This is an electronic document used to prove the ownership of a public key. The certificate
|
||||||
|
includes information about the key, information about the identity of its owner (called the
|
||||||
|
subject), and the digital signature of an entity that has verified the certificate's contents
|
||||||
|
(called the issuer). If the signature is valid, and the software examining the certificate
|
||||||
|
trusts the issuer, then it can use that key to communicate securely with the certificate's
|
||||||
|
subject.
|
||||||
|
|
||||||
|
**Certificate Authority**
|
||||||
|
|
||||||
|
This issues user certificates and acts as the chief agent of trust. When issuing a certificate
|
||||||
|
to a user, the CA signs the certificate with its private key in order to validate it. During
|
||||||
|
electronic transactions the CA also confirms that certificates are still valid. Certificates
|
||||||
|
may be revoked for various reasons. For example, a user may leave the organization or they may
|
||||||
|
forget their secret passphrase, the certificate may expire or become corrupt. This process is
|
||||||
|
usually accomplished through the use of a Certificate Revocation List (CRL) which is a list of
|
||||||
|
the certificates that have been revoked. Only the certificates that have been revoked appear on
|
||||||
|
this list.
|
||||||
|
|
||||||
|
**Subject of Identity Certificate**
|
||||||
|
|
||||||
|
This is the identity to be secured. It contains information such as common name (CN),
|
||||||
|
organization (OU), state (ST) and country (C).
|
||||||
|
|
||||||
|
**Subject Name**
|
||||||
|
|
||||||
|
This is aka distinguished name and is the string representation of certificate subject.
|
||||||
|
|
||||||
|
ie: emailAddress=alice\@adlink.ist,CN=Alice,OU=IST,O=ADLink,ST=OV,C=NL
|
||||||
|
|
||||||
|
|
||||||
|
*************************
|
||||||
|
PKI Usage in DDS Security
|
||||||
|
*************************
|
||||||
|
|
||||||
|
.. image:: ./_static/pictures/pki_overview.png
|
||||||
|
:width: 1000
|
||||||
|
|
||||||
|
Alice and Bob are the DDS participants who have their private and public keys. Identitity
|
||||||
|
Certificate Authority (ID CA) has its own self-signed certificate (IdentityCA in the diagram).
|
||||||
|
ID CA gets Alice's subject information and public key and generates an IdentityCertificate for her.
|
||||||
|
Alice's certificate includes her public key and certificate of ID CA; so that her certificate can
|
||||||
|
be verified if it is really issued by ID CA.
|
||||||
|
|
||||||
|
Access Control is configured with governance and permissions files. Governance file defines the
|
||||||
|
security behavior of domains and topics. Permissions file contains the permissions of the domain
|
||||||
|
participant, topics, readers and writers, binds them to identity certificate by subject name
|
||||||
|
(distinguished name).
|
||||||
|
|
||||||
|
Governance files and Permissions files are signed by Permission CA. Signed documents also
|
||||||
|
contains Permissions CA certificate; so that they can be verified if they are really issued
|
||||||
|
by Permissions CA.
|
||||||
|
|
||||||
|
Authenticated participants perform a handshake with each other and generate a shared key by
|
||||||
|
Diffie-Hellman key exchange. This shared key is used for encrypting/decrypting data with AES.
|
||||||
|
|
||||||
|
During the handshake Alice checks Bob's certificate and Bob's Permissions file if they are really
|
||||||
|
issued by the ID CA certificate and Permissions CA Certificate that **she** has. Also Bob checks
|
||||||
|
Alice's certificate and Alice's Permissions file if they are really issued by the ID CA certificate
|
||||||
|
and Permissions CA that **he** has.
|
||||||
|
Permissions files can contain permissions for several identities; so subject name of identity
|
||||||
|
certificate exist in permissions file to establish a binding between identity and its permissions.
|
||||||
|
|
||||||
|
There are several ways to set up the certificates and signed configuration files to be used with
|
||||||
|
Cyclone DDS Security. One of them is using OpenSSL, which is described in section
|
||||||
|
`Creating certificates using OpenSSL`_.
|
||||||
|
|
||||||
|
*************
|
||||||
|
Configuration
|
||||||
|
*************
|
||||||
|
|
||||||
|
.. image:: ./_static/pictures/dds_security_configuration_overview.png
|
||||||
|
:width: 1000
|
||||||
|
|
||||||
|
|
||||||
|
The configuration of DDS Security is split up into two parts.
|
||||||
|
|
||||||
|
- `Plugins Configuration`_
|
||||||
|
- `Access Control Configuration`_
|
||||||
|
|
||||||
|
|
||||||
|
Plugins Configuration
|
||||||
|
*********************
|
||||||
|
|
||||||
|
CycloneDDS gets the security configuration from XML configuration elements or from
|
||||||
|
the participant QoS policies as stated in the DDS Security specification.
|
||||||
|
|
||||||
|
This behavior allows applications to use DDS Security without recompiling the binaries.
|
||||||
|
Only supplying a new configuration with DDS Security enabled is enough to switch from a
|
||||||
|
non-secure to a secure deployment. The configuration is at domain level, which means
|
||||||
|
that all participants created for that domain receive the same DDS security settings.
|
||||||
|
|
||||||
|
The configuration options for a domain are bundled in the ``DDSSecurity`` configuration
|
||||||
|
section in the CycloneDDS configuration. Every DDS Security plugin has its own configuration
|
||||||
|
sub-section.
|
||||||
|
|
||||||
|
.. _`Authentication Properties`:
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Authentication Properties
|
||||||
|
=========================
|
||||||
|
|
||||||
|
To enable authentication for a node, it has to be configured with an identity certificate
|
||||||
|
(``DDSSecurity/Authentication/IdentityCertificate``). This identity certificate is used to
|
||||||
|
authenticate all participants of that particular CycloneDDS domain. Associated with the
|
||||||
|
identity certificate is the corresponding private key
|
||||||
|
(``DDSSecurity/Authentication/PrivateKey``). The private key may either be a 2048-bit RSA
|
||||||
|
or a 256-bit Elliptic Curve Key with a prime256v1 curve.
|
||||||
|
|
||||||
|
The certificate of identity CA, which is the issuer of the node's identity certificate,
|
||||||
|
is configured in ``DDSSecurity/Authentication/IdentityCA``. The public key of the
|
||||||
|
identity CA (as part of its certificate) shall either be a 2048-bit RSA key or a 256-bit
|
||||||
|
Elliptic Curve Key for the prime256v1 curve. The identity CA certificate can be a
|
||||||
|
self-signed certificate.
|
||||||
|
|
||||||
|
The identity certificate, private key and the identity CA should be a X509 document in PEM
|
||||||
|
format. It may either be specified directly in the configuration file (as CDATA, prefixed
|
||||||
|
with ``data:,``) or the configuration file should contain a reference to a corresponding
|
||||||
|
file (prefixed with ``file:``).
|
||||||
|
|
||||||
|
Optionally the private key could be protected by a password
|
||||||
|
(``DDSSecurity/Authentication/Password``).
|
||||||
|
|
||||||
|
Furthermore the CycloneDDS configuration allows configuring a directory containing additional
|
||||||
|
identity CA's which are used to verify the identity certificates that are received from remote instances
|
||||||
|
(``DDSSecurity/Authentication/TrustedCADirectory``). This option allows multiple identity
|
||||||
|
CAs throughout the system.
|
||||||
|
|
||||||
|
.. _`Access Control Properties`:
|
||||||
|
|
||||||
|
=========================
|
||||||
|
Access Control Properties
|
||||||
|
=========================
|
||||||
|
|
||||||
|
A governance document (``DDSSecurity/AccessControl/Governance``), a permissions document
|
||||||
|
(``DDSSecurity/AccessControl/Permissions``) and the permissions CA certificate
|
||||||
|
(``DDSSecurity/AccessControl/PermissionsCA``) are required for the access control plugin.
|
||||||
|
Similar to the authentication plugin properties, these values can be provided as CDATA or
|
||||||
|
by using a path to a file.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Cryptography Properties`:
|
||||||
|
|
||||||
|
=======================
|
||||||
|
Cryptography Properties
|
||||||
|
=======================
|
||||||
|
|
||||||
|
The cryptography plugin has no properties in the configuration.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Access Control Configuration`:
|
||||||
|
|
||||||
|
Access Control Configuration
|
||||||
|
****************************
|
||||||
|
|
||||||
|
Access Control configuration consists of Governance document and Permissions document.
|
||||||
|
Both governance and permissions files must be signed by the Permissions CA in S/MIME format.
|
||||||
|
Participants use their own permissions CA to validate remote permissions. So, all permissions CA
|
||||||
|
Certificates must be the same for all participants.
|
||||||
|
|
||||||
|
The signed document should use S/MIME version 3.2 format as defined in IETF RFC 5761 using
|
||||||
|
SignedData Content Type (section 2.4.2 of IETF RFC 5761) formatted as multipart/signed (section
|
||||||
|
3.4.3 of IETF RFC 5761). This corresponds to the mime-type application/pkcs7-signature.
|
||||||
|
Additionally the signer certificate should be be included within the signature.
|
||||||
|
|
||||||
|
|
||||||
|
===================
|
||||||
|
Governance Document
|
||||||
|
===================
|
||||||
|
|
||||||
|
The Governance document defines the security behavior of domains and topics. It is an XML document
|
||||||
|
and its format is specified in OMG DDS Security Version 1.1 Section 9.4.1.2.3.
|
||||||
|
|
||||||
|
This section describes the properties that can be specified in a permissions document. An example
|
||||||
|
of a governance document is provided in `Create a signed governance document`_. The options
|
||||||
|
that are specified in Governance document must match with the remote node to establishing
|
||||||
|
communication.
|
||||||
|
|
||||||
|
|
||||||
|
Protection Kinds
|
||||||
|
================
|
||||||
|
|
||||||
|
The domain governance document provides a means for the application to configure the kinds of
|
||||||
|
cryptographic transformation applied to the complete RTPS Message, certain RTPS SubMessages, and
|
||||||
|
the SerializedPayload RTPS submessage element that appears within the Data.
|
||||||
|
|
||||||
|
.. image:: ./_static/pictures/rtps_message_structure.png
|
||||||
|
:width: 300
|
||||||
|
|
||||||
|
The configuration allows specification of five protection levels: NONE, SIGN, ENCRYPT,
|
||||||
|
SIGN_WITH_ORIGIN_AUTHENTICATION and ENCRYPT_WITH_ORIGIN_AUTHENTICATION.
|
||||||
|
|
||||||
|
**NONE**
|
||||||
|
indicates no cryptographic transformation is applied.
|
||||||
|
|
||||||
|
**SIGN**
|
||||||
|
indicates the cryptographic transformation shall be purely a message authentication code (MAC),
|
||||||
|
that is, no encryption is performed.
|
||||||
|
|
||||||
|
**ENCRYPT**
|
||||||
|
indicates the cryptographic transformation shall be an encryption followed by a message
|
||||||
|
authentication code (MAC) computed on the ciphertext, also known as Encrypt-then-MAC.
|
||||||
|
|
||||||
|
**SIGN_WITH_ORIGIN_AUTHENTICATION**
|
||||||
|
indicates the cryptographic transformation shall be purely a set of message authentication codes
|
||||||
|
(MAC), that is, no encryption is performed. This cryptographic transformation shall create a
|
||||||
|
first “common authenticationcode” similar to the case where Protection Kind is SIGN. In addition
|
||||||
|
the cryptographic transformation shall create additional authentication codes, each produced with
|
||||||
|
a different secret key. The additional MACs prove to the receiver that the sender originated the
|
||||||
|
message, preventing other receivers from impersonating the sender.
|
||||||
|
|
||||||
|
**ENCRYPT_WITH_ORIGIN_AUTHENTICATION**
|
||||||
|
indicates the cryptographic transformation shall be an encryption followed by a message
|
||||||
|
authentication code (MAC) computed on the ciphertext, followed by additional authentication
|
||||||
|
codes, Each of the additional authentication codes shall use a different secret key. The
|
||||||
|
encryption and first (common) authentication code is similar to ones produced when the Protection
|
||||||
|
Kind is ENCRYPT. The additional authentication codes are similar to the ones produced when the
|
||||||
|
Protection Kind is SIGN_WITH_ORIGIN_AUTHENTICATION.
|
||||||
|
|
||||||
|
|
||||||
|
Participant attributes
|
||||||
|
======================
|
||||||
|
|
||||||
|
**Allow Unauthenticated Participants**
|
||||||
|
This is used for allowing communication with non-secure participants. If this option is enabled,
|
||||||
|
secure participant can communicate with non-secure participant by only non-protected topics.
|
||||||
|
|
||||||
|
**Enable Join Access Control**
|
||||||
|
If this option is enabled, remote participant permissions are checked if its subject name is
|
||||||
|
allowed to create a topic anyhow.
|
||||||
|
|
||||||
|
**Discovery Protection Kind**
|
||||||
|
Protection attribute for discovery communication when it is enabled for topic. Please see the
|
||||||
|
DDS Security specification document for available options.
|
||||||
|
|
||||||
|
**Liveliness Protection Kind**
|
||||||
|
Protection attribute for liveliness communication when it is enabled for topic. Please see the
|
||||||
|
DDS Security specification document for available options.
|
||||||
|
|
||||||
|
**RTPS Protection Kind**
|
||||||
|
Protection attribute for all messages on the wire. Please see the DDS Security specification
|
||||||
|
document for available options. If encryption is selected for RTPS, there is no need to encrypt
|
||||||
|
submessages (metadata_protection_kind) and payloads (data_protection_kind) which are defined in
|
||||||
|
topic settings.
|
||||||
|
|
||||||
|
|
||||||
|
Topic Attributes
|
||||||
|
================
|
||||||
|
|
||||||
|
**Enable Discovery protection:**
|
||||||
|
If enabled, discovery is protected according to Discovery Protection Kind attribute of
|
||||||
|
corresponding participant.
|
||||||
|
|
||||||
|
**Enable Liveliness protection:**
|
||||||
|
If enabled, liveliness is protected according to Liveliness Protection Kind attribute of
|
||||||
|
corresponding participant.
|
||||||
|
|
||||||
|
**Enable Read Access Control:**
|
||||||
|
If enabled, the permissions document is checked if the participant is allowed to create
|
||||||
|
a datareader for the related topic.
|
||||||
|
|
||||||
|
**Enable Write Access Control:**
|
||||||
|
If enabled, the permissions document is checked if the participant is allowed to create
|
||||||
|
a datawriter for the related topic.
|
||||||
|
|
||||||
|
**Metadata protection Kind:**
|
||||||
|
Protection attribute for submessages.
|
||||||
|
|
||||||
|
**Data protection Kind:**
|
||||||
|
Protection attribute for data payload.
|
||||||
|
|
||||||
|
There are different settings for different domain ranges. The domain rules are evaluated in the
|
||||||
|
same order as they appear in the document. A rule only applies to a particular DomainParticipant
|
||||||
|
if the domain Section matches the DDS domain_id to which the participant belongs. If multiple
|
||||||
|
rules match, the first rule that matches is the only one that applies.
|
||||||
|
|
||||||
|
The topic access rules are evaluated in the same order as they appear within the
|
||||||
|
<topic_access_rules> Section. If multiple rules match the first rule that matches is the only one
|
||||||
|
that applies.
|
||||||
|
|
||||||
|
fnmatch pattern matching can be used for topic expressions including the following patterns
|
||||||
|
|
||||||
|
.. _`fnmatch pattern matching`:
|
||||||
|
|
||||||
|
+----------+----------------------------------+
|
||||||
|
|Pattern |Meaning |
|
||||||
|
+==========+==================================+
|
||||||
|
| \* | matches everything |
|
||||||
|
+----------+----------------------------------+
|
||||||
|
| \? | matches any single character |
|
||||||
|
+----------+----------------------------------+
|
||||||
|
| [seq] | matches any character in seq |
|
||||||
|
+----------+----------------------------------+
|
||||||
|
| [!seq] | matches any character not in seq |
|
||||||
|
+----------+----------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
====================
|
||||||
|
Permissions Document
|
||||||
|
====================
|
||||||
|
|
||||||
|
The permissions document is an XML document containing the permissions of the domain participant
|
||||||
|
and binding them to the subject name of the DomainParticipant as defined in the identity
|
||||||
|
certificate. Its format is specified in OMG DDS Security Version 1.1 Section 9.4.1.3.
|
||||||
|
|
||||||
|
This section describes the properties that can be specified in a permissions document. An example
|
||||||
|
of a permissions document is provided in `Creating a signed permissions document`_.
|
||||||
|
|
||||||
|
|
||||||
|
Validity period
|
||||||
|
===============
|
||||||
|
|
||||||
|
It is checked before creating participant. Validity period is also checked during handshake with
|
||||||
|
remote participant; expired remote permissions document prevents communications to be established.
|
||||||
|
|
||||||
|
|
||||||
|
Subject Name
|
||||||
|
============
|
||||||
|
|
||||||
|
The subject name must match with Identity Certificate subject. It is checked during create
|
||||||
|
participant and during handshake with remote participant. Use the following openssl command to get
|
||||||
|
subject name from identity certificate:
|
||||||
|
|
||||||
|
``openssl x509 -noout -subject -nameopt RFC2253 -in <identity_certificate_file.pem>``
|
||||||
|
|
||||||
|
|
||||||
|
Rules
|
||||||
|
=====
|
||||||
|
|
||||||
|
Participant permissions are defined by set of rules. The rules are applied in the same order
|
||||||
|
that appear in the document. If the criteria for the rule matches the domain_id join and/or publish
|
||||||
|
or subscribe operation that is being attempted, then the allow or deny decision is applied.
|
||||||
|
If the criteria for a rule does not match the operation being attempted, the evaluation
|
||||||
|
shall proceed to the next rule. If all rules have been examined without a match, then the
|
||||||
|
decision specified by the “default” rule is applied. The default rule, if present, must
|
||||||
|
appear after all allow and deny rules. If the default rule is not present, the
|
||||||
|
implied default decision is DENY. The matching criteria for each rule specify the domain_id,
|
||||||
|
topics (published and subscribed), the partitions (published and subscribed), and the data-tags
|
||||||
|
associated with the DataWriter and DataReader.
|
||||||
|
|
||||||
|
For the grant to match there shall be a match of the topics, partitions, and data-tags criteria.
|
||||||
|
This is interpreted as an AND of each of the criteria. For a specific criterion to match
|
||||||
|
(e.g., <topics>) it is enough that one of the topic expressions listed matches (i.e., an OR of
|
||||||
|
the expressions with the <topics> section).
|
||||||
|
|
||||||
|
`fnmatch pattern matching`_ can be used for topic expressions and partition expressions.
|
||||||
|
|
||||||
|
|
||||||
|
Logging and tracing
|
||||||
|
*******************
|
||||||
|
|
||||||
|
The security implementation uses the standard logging and tracing mechanism in CycloneDDS.
|
||||||
|
The following is written to log and trace:
|
||||||
|
|
||||||
|
- Configuration errors such as plugin library files, certificate files, governance and permissions
|
||||||
|
files that can not be found on filesystem.
|
||||||
|
- Permission errors such as denied permission for creating writer of a topic.
|
||||||
|
- Attribute mismatch errors such as mismatches of security attributes between participants, topics,
|
||||||
|
readers and writers.
|
||||||
|
- Integrity errors such as Permissions file-Permissions CA and Identity Cert-Identity CA integrity.
|
||||||
|
|
||||||
|
Local subscription, publication and topic permission errors are written as errors.
|
||||||
|
Remote participation, subscription and publication permission errors are written to log as
|
||||||
|
warning messages.
|
||||||
|
|
||||||
|
|
||||||
|
Data Communication And Handshake Process
|
||||||
|
****************************************
|
||||||
|
|
||||||
|
Authentication handshake between participants starts after participant discovery. If a reader and
|
||||||
|
a writer created during that period, their match will be delayed until after the handshake succeeds.
|
||||||
|
This means, during the handshake process, volatile data will be lost, just like there is no reader.
|
||||||
|
|
||||||
|
After publication match, the encryption / decryption keys are exchanged between reader and writer.
|
||||||
|
Best-effort data that are sent during this exchange will be lost, however reliable data will be
|
||||||
|
resent.
|
||||||
|
|
||||||
|
|
||||||
|
DDS Secure Discovery
|
||||||
|
********************
|
||||||
|
|
||||||
|
Just like normal operation, Cyclone DDS discovers remote participants, topics, readers and writers.
|
||||||
|
However, when DDS Security is enabled, it is more complex and will take a longer time (due to the
|
||||||
|
handshaking that is required). The effort to perform discovery grows quadratically in the number of
|
||||||
|
nodes. This can become a problem if the system contains a number of slow platforms or is large.
|
||||||
|
|
||||||
|
|
||||||
|
Proprietary builtin endpoints
|
||||||
|
*****************************
|
||||||
|
|
||||||
|
The DDS standard contains some builtin endpoints. A few are added by the DDS Security
|
||||||
|
specification. The behaviour of all these builtin endpoints are specified (and thus are be
|
||||||
|
handled by the plugins that implement the DDS Security specification), meaning that they
|
||||||
|
don't have to be present in the Governance or Permissions documents and the users don't
|
||||||
|
have to be bothered with them.
|
||||||
|
|
||||||
|
A few of these builtin endpoints slave according to the <discovery_protection_kind> within
|
||||||
|
the Governance document. In short, related submessages are protected according to the value
|
||||||
|
of <discovery_protection_kind>. This protects meta information that is send during the
|
||||||
|
discovery phase.
|
||||||
|
|
||||||
|
|
||||||
|
*******************
|
||||||
|
DataTag Permissions
|
||||||
|
*******************
|
||||||
|
|
||||||
|
Data Tags provide an extra (optional) level of identification. This can mean f.i. that
|
||||||
|
a certain reader is not allowed to read data from writer A but it is allowed to read from
|
||||||
|
writer B (all the same topic).
|
||||||
|
|
||||||
|
This optional feature is not yet supported.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Example configuration`:
|
||||||
|
|
||||||
|
*********************
|
||||||
|
Example configuration
|
||||||
|
*********************
|
||||||
|
|
||||||
|
This sections show an example configuration for DDS Security in Cyclone DDS. First step is
|
||||||
|
creating the required CA and identity certificates. Then a governance and permissions document
|
||||||
|
is created to configure access control. Next an example configuration (XML) that
|
||||||
|
is using these assets is shown, and a code fragment that shows how to set the security
|
||||||
|
properties by using the participant QoS.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Creating certificates using OpenSSL`:
|
||||||
|
|
||||||
|
Creating certificates using OpenSSL
|
||||||
|
***********************************
|
||||||
|
|
||||||
|
This section describes how to generate a set of CA and identity certificates using OpenSSL,
|
||||||
|
and how to use OpenSSL to sign the governance and access control configuration files.
|
||||||
|
|
||||||
|
First step is generation of the CA for identity management (authentication). First we create the
|
||||||
|
private key for the CA by:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl genrsa -out example_id_ca_priv_key.pem 2048
|
||||||
|
|
||||||
|
Next we can generate the certificate for the identity CA (which is in this case a self-signed
|
||||||
|
certificate):
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl req -x509 -key example_id_ca_priv_key.pem -out example_id_ca_cert.pem -days 3650 -subj "/C=NL/ST=OV/L=Locality Name/OU=Example OU/O=Example ID CA Organization/CN=Example ID CA/emailAddress=authority@cycloneddssecurity.adlinktech.com"
|
||||||
|
|
||||||
|
We repeat these steps for generating the private key of the permissions CA (used for
|
||||||
|
signing the AccessControl configiguration files):
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl genrsa -out example_perm_ca_priv_key.pem 2048
|
||||||
|
|
||||||
|
And the self-signed certificate for the permissions CA:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl req -x509 -key example_perm_ca_priv_key.pem -out example_perm_ca_cert.pem -days 3650 -subj "/C=NL/ST=OV/L=Locality Name/OU=Example OU/O=Example CA Organization/CN=Example Permissions CA/emailAddress=authority@cycloneddssecurity.adlinktech.com"
|
||||||
|
|
||||||
|
==============================
|
||||||
|
Create an Identity Certificate
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Now that we have set up the CA for identity management, we can create an identity certificate
|
||||||
|
signed by this CA and the private key corresponding to this identity. Here we are creating
|
||||||
|
a private key and certificate for identity named Alice. These steps need to be repeated for each
|
||||||
|
identity in the system.
|
||||||
|
|
||||||
|
Generating the private key for Alice's identity:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl genrsa -out example_alice_priv_key.pem 2048
|
||||||
|
|
||||||
|
Now we create a 'certificate signing request' (CSR) to request the identity CA to generate a certificate:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl req -new -key example_alice_priv_key.pem -out example_alice.csr -subj "/C=NL/ST=OV/L=Locality Name/OU=Organizational Unit Name/O=Example Organization/CN=Alice Example/emailAddress=alice@cycloneddssecurity.adlinktech.com"
|
||||||
|
|
||||||
|
Next Alice's identity certificate is created:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl x509 -req -CA example_id_ca_cert.pem -CAkey example_id_ca_priv_key.pem -CAcreateserial -days 3650 -in example_alice.csr -out example_alice_cert.pem
|
||||||
|
|
||||||
|
|
||||||
|
Now the file 'example_alice_cert.pem' can be used as ``IdentityCertificate`` in the DDS Security
|
||||||
|
authentication configuration and 'example_alice_priv_key.pem' for the ``PrivateKey`` setting. The
|
||||||
|
certificate of the CA used for signing this identity, 'example_id_ca_cert.pem' in this example,
|
||||||
|
should be used for the ``IdentityCA`` configuration setting.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Create a signed governance document`:
|
||||||
|
|
||||||
|
===================================
|
||||||
|
Create a signed governance document
|
||||||
|
===================================
|
||||||
|
|
||||||
|
An example of a governance document that is using signing for submessage and encrypted payload:
|
||||||
|
|
||||||
|
.. literalinclude:: _static/example_governance.xml
|
||||||
|
:linenos:
|
||||||
|
:language: xml
|
||||||
|
|
||||||
|
As mentioned before, the governance document needs to be signed by the permissions CA
|
||||||
|
that was created above. This can be done by using this openssl command:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl smime -sign -in example_governance.xml -text -out example_governance.p7s -signer example_perm_ca_cert.pem -inkey example_perm_ca_priv_key.pem
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Creating a signed permissions document`:
|
||||||
|
|
||||||
|
======================================
|
||||||
|
Creating a signed permissions document
|
||||||
|
======================================
|
||||||
|
|
||||||
|
The permissions document is an XML document that contains the permissions of the participant and
|
||||||
|
binds them to the subject name of the identity certificate (distinguished name) for the participant
|
||||||
|
as defined in the DDS:Auth:PKI-DH authentication plugin.
|
||||||
|
|
||||||
|
An example of a permissions document:
|
||||||
|
|
||||||
|
.. literalinclude:: _static/example_permissions.xml
|
||||||
|
:linenos:
|
||||||
|
:language: xml
|
||||||
|
|
||||||
|
This document also needs to be signed by the permissions CA:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
openssl smime -sign -in example_permissions.xml -text -out example_permissions.p7s -signer example_perm_ca_cert.pem -inkey example_perm_ca_priv_key.pem
|
||||||
|
|
||||||
|
|
||||||
|
Example DDS Security configuration
|
||||||
|
**********************************
|
||||||
|
|
||||||
|
With the above steps we have all certificates and documents that are required when configuring
|
||||||
|
security. In the next two sections, both configuring security by properties and configuring
|
||||||
|
security by DDS configuration are covered.
|
||||||
|
|
||||||
|
======================================
|
||||||
|
Security properties in participant QoS
|
||||||
|
======================================
|
||||||
|
|
||||||
|
This code fragment shows how to set the security properties to a QoS object and use this QoS
|
||||||
|
when creating a participant:
|
||||||
|
|
||||||
|
.. literalinclude:: _static/security_by_qos.c
|
||||||
|
:linenos:
|
||||||
|
:language: c
|
||||||
|
|
||||||
|
|
||||||
|
===========================================
|
||||||
|
Configure security in Cyclone configuration
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
As an alternative for using the QoS, security settings can also be applied using the CycloneDDS
|
||||||
|
configuration XML. In case both QoS and the configuration XML contain security settings, the values
|
||||||
|
from the QoS will be used and the security settings in the configuration XML are ignored.
|
||||||
|
|
||||||
|
The following XML fragment shows how to set security settings through configuration:
|
||||||
|
|
||||||
|
.. literalinclude:: _static/security_by_config.xml
|
||||||
|
:linenos:
|
||||||
|
:language: xml
|
||||||
|
|
||||||
|
To use this configuration file for an application, set the CYCLONEDDS_URI environment
|
||||||
|
variable to this config file:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
export CYCLONEDDS_URI=/path/to/secure_config.xml
|
||||||
|
|
||||||
|
Bacause this example configuration uses the attribute ``id=any`` for the ``domain`` element, any participant
|
||||||
|
that is created (which implicitly creates a domain) in an application using this configuration gets
|
||||||
|
these security settings.
|
||||||
|
|
||||||
|
***************************
|
||||||
|
External Plugin Development
|
||||||
|
***************************
|
||||||
|
|
||||||
|
DDS Security consists of three plugins (authentication, cryptography and access control).
|
||||||
|
CycloneDDS comes with built-in security plugins that comply with OMG DDS Security specification.
|
||||||
|
The plugins are loaded in the run-time. However, you can also implement your own custom plugin by
|
||||||
|
implementing the given API according to OMG DDS Security specification.
|
||||||
|
You can implement all of the plugins or just one of them.
|
||||||
|
|
||||||
|
The followings are the key points for implementing you own plugin:
|
||||||
|
|
||||||
|
|
||||||
|
Interface
|
||||||
|
*********
|
||||||
|
|
||||||
|
Implement all plugin specific functions with exactly same prototype. Plugin specific function
|
||||||
|
interfaces are in dds_security_api_access_control.h, dds_security_api_authentication.h and
|
||||||
|
dds_security_api_cryptography.h header files accordingly.
|
||||||
|
|
||||||
|
|
||||||
|
Init and Finalize
|
||||||
|
*****************
|
||||||
|
|
||||||
|
A plugin should have an init and a finalize functions. plugin_init and plugin_finalize
|
||||||
|
interfaces are given in dds_security_api.h header file and function should be same as in
|
||||||
|
configuration file.
|
||||||
|
Init function is called once, just after the plugin is loaded. Finalize function is
|
||||||
|
called once, just before the plugin is unloaded.
|
||||||
|
|
||||||
|
Inter Plugin Communication
|
||||||
|
**************************
|
||||||
|
|
||||||
|
There is a shared object (*DDS_Security_SharedSecretHandle*) within authentication and
|
||||||
|
cryptography plugins. If you want to implement only one of them and use the builtin for the
|
||||||
|
other one, you have to get or provide the shared object properly.
|
||||||
|
*DDS_Security_SharedSecretHandle* is the integer representation of
|
||||||
|
*DDS_Security_SharedSecretHandleImpl* struct object. Cryptography plugin gets the
|
||||||
|
*DDS_Security_SharedSecretHandle* from authentication plugin and casts to
|
||||||
|
*DDS_Security_SharedSecretHandleImpl* struct. Then all needed information can be retieved
|
||||||
|
through *DDS_Security_SharedSecretHandleImpl* struct:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
typedef struct DDS_Security_SharedSecretHandleImpl {
|
||||||
|
DDS_Security_octet* shared_secret;
|
||||||
|
DDS_Security_long shared_secret_size;
|
||||||
|
DDS_Security_octet challenge1[DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE];
|
||||||
|
DDS_Security_octet challenge2[DDS_SECURITY_AUTHENTICATION_CHALLENGE_SIZE];
|
||||||
|
|
||||||
|
} DDS_Security_SharedSecretHandleImpl;
|
||||||
|
|
||||||
|
|
||||||
|
Error Codes
|
||||||
|
***********
|
||||||
|
|
||||||
|
Most of the plugin functions have parameter for reporting exception. The following exception
|
||||||
|
codes should be used in the reported exception data according to the situation.
|
||||||
|
dds_security_api_err.h header file contains the code and message constants.
|
||||||
|
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| Code | Message |
|
||||||
|
+=======+================================================================+
|
||||||
|
| 0 | (OK) |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 100 | Can not generate random data |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 110 | Identity empty |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 111 | Participant Crypto Handle empty |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 112 | Permission Handle empty |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 113 | Invalid Crypto Handle |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 114 | Invalid argument |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 115 | Invalid Crypto token |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 116 | Invalid parameter |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 117 | File could not be found, opened or is empty, path: %s |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 118 | Unknown or unexpected transformation kind |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 119 | Message cannot be authenticated, incorrect signature |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 120 | Can not open trusted CA directory |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 121 | Identity CA is not trusted |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 122 | Certificate start date is in the future |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 123 | Certificate expired |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 125 | Certificate authentication algorithm unknown |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 126 | Failed to allocate internal structure |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 127 | Failed to parse PKCS7 SMIME document |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 128 | Property is missing: (%s) |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 129 | Permissions document is invalid |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 130 | Governance document is invalid |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 131 | Operation is not permitted in this state |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 132 | Remote permissions document is not available |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 133 | Certificate is invalid |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 134 | Certificate type is not supported |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 135 | Governance property is required |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 136 | Permissions CA property is required |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 137 | Can not parse governance file |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 138 | Can not parse permissions file |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 139 | Could not find permissions for topic |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 140 | Could not find domain %d in permissions |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 141 | Could not find domain %d in governance |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 142 | Could not find %s topic attributes for domain(%d) in governance|
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 143 | PluginClass in remote token is incompatible |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 144 | MajorVersion in remote token is incompatible |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 145 | Access denied by access control |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 146 | Subject name is invalid |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 147 | Permissions validity period expired for %s |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 148 | Permissions validity period has not started yet for %s |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 149 | Could not find valid grant in permissions |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 150 | Unsupported URI type: %s |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 151 | The payload is not aligned at 4 bytes |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 152 | Cannot open trusted CA directory: maximum number exceeded |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
| 200 | Undefined Error Message |
|
||||||
|
+-------+----------------------------------------------------------------+
|
||||||
|
|
||||||
|
.. EoF
|
|
@ -80,8 +80,319 @@ though there is no good reason not to.</li></ul>
|
||||||
element StandardsConformance {
|
element StandardsConformance {
|
||||||
("lax"|"strict"|"pedantic")
|
("lax"|"strict"|"pedantic")
|
||||||
}?
|
}?
|
||||||
|
}*
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element is used to configure Cyclone DDS with the DDS Security
|
||||||
|
specification plugins and settings.</p>""" ] ]
|
||||||
|
element DDSSecurity {
|
||||||
|
[ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element configures the Access Control plugin of the DDS Security
|
||||||
|
specification.</p>""" ] ]
|
||||||
|
element AccessControl {
|
||||||
|
[ a:documentation [ xml:lang="en" """
|
||||||
|
<p>URI to the shared Governance Document signed by the Permissions CA in
|
||||||
|
S/MIME format</p>
|
||||||
|
|
||||||
|
<p>URI schemes: file, data</p><br>
|
||||||
|
|
||||||
|
<p>Examples file URIs:</p>
|
||||||
|
|
||||||
|
<p><Governance>file:governance.smime</Governance></p>
|
||||||
|
|
||||||
|
<p><Governance>file:/home/myuser/governance.smime</Governance></p><br>
|
||||||
|
|
||||||
|
<p><Governance><![CDATA[data:,MIME-Version: 1.0</p>
|
||||||
|
|
||||||
|
<p>Content-Type: multipart/signed;
|
||||||
|
protocol="application/x-pkcs7-signature"; micalg="sha-256";
|
||||||
|
boundary="----F9A8A198D6F08E1285A292ADF14DD04F"</p>
|
||||||
|
|
||||||
|
<p>This is an S/MIME signed message </p>
|
||||||
|
|
||||||
|
<p>------F9A8A198D6F08E1285A292ADF14DD04F</p>
|
||||||
|
|
||||||
|
<p><?xml version="1.0" encoding="UTF-8"?></p>
|
||||||
|
|
||||||
|
<p><dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</p>
|
||||||
|
|
||||||
|
<p>xsi:noNamespaceSchemaLocation="omg_shared_ca_governance.xsd"></p>
|
||||||
|
|
||||||
|
<p><domain_access_rules></p>
|
||||||
|
|
||||||
|
<p> . . . </p>
|
||||||
|
|
||||||
|
<p></domain_access_rules></p>
|
||||||
|
|
||||||
|
<p></dds></p>
|
||||||
|
|
||||||
|
<p>...</p>
|
||||||
|
|
||||||
|
<p>------F9A8A198D6F08E1285A292ADF14DD04F</p>
|
||||||
|
|
||||||
|
<p>Content-Type: application/x-pkcs7-signature; name="smime.p7s"</p>
|
||||||
|
|
||||||
|
<p>Content-Transfer-Encoding: base64</p>
|
||||||
|
|
||||||
|
<p>Content-Disposition: attachment; filename="smime.p7s"</p>
|
||||||
|
|
||||||
|
<p>MIIDuAYJKoZIhv ...al5s=</p>
|
||||||
|
|
||||||
|
<p>------F9A8A198D6F08E1285A292ADF14DD04F-]]</Governance></p><p>The
|
||||||
|
default value is: "".</p>""" ] ]
|
||||||
|
element Governance {
|
||||||
|
text
|
||||||
}?
|
}?
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element specifies the library to be loaded as the DDS Security
|
||||||
|
Access Control plugin.</p>""" ] ]
|
||||||
|
element Library {
|
||||||
|
[ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element names the finalization function of Access Control plugin.
|
||||||
|
This function is called to let the plugin release its
|
||||||
|
resources.</p><p>The default value is:
|
||||||
|
"finalize_access_control".</p>""" ] ]
|
||||||
|
attribute finalizeFunction {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element names the initialization function of Access Control
|
||||||
|
plugin. This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Access Control interface.</p><p>The default value
|
||||||
|
is: "init_access_control".</p>""" ] ]
|
||||||
|
attribute initFunction {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element points to the path of Access Control plugin library.</p>
|
||||||
|
|
||||||
|
<p>It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_ac ) or single file without extension (
|
||||||
|
dds_security_ac ).</p>
|
||||||
|
|
||||||
|
<p>If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.</p><p>The default value is:
|
||||||
|
"dds_security_ac".</p>""" ] ]
|
||||||
|
attribute path {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>URI to the DomainParticipant permissions document signed by the
|
||||||
|
Permissions CA in S/MIME format</p>
|
||||||
|
|
||||||
|
<p>The permissions document specifies the permissions to be applied to a
|
||||||
|
domain.</p><br>
|
||||||
|
|
||||||
|
<p>Example file URIs:</p>
|
||||||
|
|
||||||
|
<p><Permissions>file:permissions_document.p7s</Permissions></p>
|
||||||
|
|
||||||
|
<p><Permissions>file:/path_to/permissions_document.p7s</Permissions></p>
|
||||||
|
|
||||||
|
<p>Example data URI:</p>
|
||||||
|
|
||||||
|
<p><Permissions><![CDATA[data:,.........]]</Permissions></p><p>The
|
||||||
|
default value is: "".</p>""" ] ]
|
||||||
|
element Permissions {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>URI to a X509 certificate for the PermissionsCA in PEM format.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>The file and data schemas shall refer to a X.509 v3 certificate (see
|
||||||
|
X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.</p><br>
|
||||||
|
|
||||||
|
<p>Examples:</p><br>
|
||||||
|
|
||||||
|
<p><PermissionsCA>file:permissions_ca.pem</PermissionsCA></p>
|
||||||
|
|
||||||
|
<p><PermissionsCA>file:/home/myuser/permissions_ca.pem</PermissionsCA></p><br>
|
||||||
|
|
||||||
|
<p><PermissionsCA>data:<strong>,</strong>-----BEGIN CERTIFICATE-----</p>
|
||||||
|
|
||||||
|
<p>MIIC3DCCAcQCCQCWE5x+Z ... PhovK0mp2ohhRLYI0ZiyYQ==</p>
|
||||||
|
|
||||||
|
<p>-----END CERTIFICATE-----</PermissionsCA></p><p>The default value is:
|
||||||
|
"".</p>""" ] ]
|
||||||
|
element PermissionsCA {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element configures the Authentication plugin of the DDS Security
|
||||||
|
specification.</p>""" ] ]
|
||||||
|
element Authentication {
|
||||||
|
[ a:documentation [ xml:lang="en" """
|
||||||
|
<p>URI to the X509 certificate [39] of the Identity CA that is the signer
|
||||||
|
of Identity Certificate.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>The file and data schemas shall refer to a X.509 v3 certificate (see
|
||||||
|
X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.</p>
|
||||||
|
|
||||||
|
<p>Examples:</p>
|
||||||
|
|
||||||
|
<p><IdentityCA>file:identity_ca.pem</IdentityCA></p>
|
||||||
|
|
||||||
|
<p><IdentityCA>data:,-----BEGIN CERTIFICATE-----<br>
|
||||||
|
|
||||||
|
MIIC3DCCAcQCCQCWE5x+Z...PhovK0mp2ohhRLYI0ZiyYQ==<br>
|
||||||
|
|
||||||
|
-----END CERTIFICATE-----</IdentityCA></p>""" ] ]
|
||||||
|
element IdentityCA {
|
||||||
|
text
|
||||||
|
}
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>Identity certificate that will be used for identifying all
|
||||||
|
participants in the OSPL instance.<br>The content is URI to a X509
|
||||||
|
certificate signed by the IdentityCA in PEM format containing the signed
|
||||||
|
public key.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>Examples:</p>
|
||||||
|
|
||||||
|
<p><IdentityCertificate>file:participant1_identity_cert.pem</IdentityCertificate></p>
|
||||||
|
|
||||||
|
<p><IdentityCertificate>data:,-----BEGIN CERTIFICATE-----<br>
|
||||||
|
|
||||||
|
MIIDjjCCAnYCCQDCEu9...6rmT87dhTo=<br>
|
||||||
|
|
||||||
|
-----END CERTIFICATE-----</IdentityCertificate></p>""" ] ]
|
||||||
|
element IdentityCertificate {
|
||||||
|
text
|
||||||
|
}
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>The authentication handshake tokens may contain optional fields to be
|
||||||
|
included for finding interoperability problems.
|
||||||
|
|
||||||
|
If this parameter is set to true the optional fields are included in the
|
||||||
|
handshake token exchange.</p><p>The default value is:
|
||||||
|
"false".</p>""" ] ]
|
||||||
|
element IncludeOptionalFields {
|
||||||
|
xsd:boolean
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element specifies the library to be loaded as the DDS Security
|
||||||
|
Access Control plugin.</p>""" ] ]
|
||||||
|
element Library {
|
||||||
|
[ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element names the finalization function of Authentication plugin.
|
||||||
|
This function is called to let the plugin release its
|
||||||
|
resources.</p><p>The default value is:
|
||||||
|
"finalize_authentication".</p>""" ] ]
|
||||||
|
attribute finalizeFunction {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element names the initialization function of Authentication
|
||||||
|
plugin. This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Authentication interface.</p><p>The default value
|
||||||
|
is: "init_authentication".</p>""" ] ]
|
||||||
|
attribute initFunction {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element points to the path of Authentication plugin library.</p>
|
||||||
|
|
||||||
|
<p>It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_auth ) or single file without extension (
|
||||||
|
dds_security_auth ).</p>
|
||||||
|
|
||||||
|
<p>If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.</p><p>The default value is:
|
||||||
|
"dds_security_auth".</p>""" ] ]
|
||||||
|
attribute path {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>A password used to decrypt the private_key.</p>
|
||||||
|
|
||||||
|
The value of the password property shall be interpreted as the Base64
|
||||||
|
encoding of the AES-128 key that shall be used to decrypt the private_key
|
||||||
|
using AES128-CBC.</p>
|
||||||
|
|
||||||
|
If the password property is not present, then the value supplied in the
|
||||||
|
private_key property must contain the unencrypted private key. </p><p>The
|
||||||
|
default value is: "".</p>""" ] ]
|
||||||
|
element Password {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>URI to access the private Private Key for all of the participants in
|
||||||
|
the OSPL federation.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>Examples:</p>
|
||||||
|
|
||||||
|
<p><PrivateKey>file:identity_ca_private_key.pem</PrivateKey></p>
|
||||||
|
|
||||||
|
<p><PrivateKey>data:,-----BEGIN RSA PRIVATE KEY-----<br>
|
||||||
|
|
||||||
|
MIIEpAIBAAKCAQEA3HIh...AOBaaqSV37XBUJg==<br>
|
||||||
|
|
||||||
|
-----END RSA PRIVATE KEY-----</PrivateKey></p>""" ] ]
|
||||||
|
element PrivateKey {
|
||||||
|
text
|
||||||
|
}
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>Trusted CA Directory which contains trusted CA certificates as
|
||||||
|
separated files.</p><p>The default value is: "".</p>""" ] ]
|
||||||
|
element TrustedCADirectory {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element configures the Cryptographic plugin of the DDS Security
|
||||||
|
specification.</p>""" ] ]
|
||||||
|
element Cryptographic {
|
||||||
|
[ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element specifies the library to be loaded as the DDS Security
|
||||||
|
Cryptographic plugin.</p>""" ] ]
|
||||||
|
element Library {
|
||||||
|
[ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element names the finalization function of Cryptographic plugin.
|
||||||
|
This function is called to let the plugin release its
|
||||||
|
resources.</p><p>The default value is: "finalize_crypto".</p>""" ] ]
|
||||||
|
attribute finalizeFunction {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element names the initialization function of Cryptographic
|
||||||
|
plugin. This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Cryptographic interface.</p><p>The default value
|
||||||
|
is: "init_crypto".</p>""" ] ]
|
||||||
|
attribute initFunction {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
|
<p>This element points to the path of Cryptographic plugin library.</p>
|
||||||
|
|
||||||
|
<p>It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_crypto ) or single file without extension (
|
||||||
|
dds_security_crypto ).</p>
|
||||||
|
|
||||||
|
<p>If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.</p><p>The default value is:
|
||||||
|
"dds_security_crypto".</p>""" ] ]
|
||||||
|
attribute path {
|
||||||
|
text
|
||||||
|
}?
|
||||||
|
}?
|
||||||
|
}?
|
||||||
|
}*
|
||||||
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The Discovery element allows specifying various parameters related to
|
<p>The Discovery element allows specifying various parameters related to
|
||||||
the discovery of peers.</p>""" ] ]
|
the discovery of peers.</p>""" ] ]
|
||||||
element Discovery {
|
element Discovery {
|
||||||
|
@ -106,11 +417,6 @@ Discovery/SPDPMulticastAddress.</p><p>The default value is:
|
||||||
text
|
text
|
||||||
}?
|
}?
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>Do not use.</p><p>The default value is: "true".</p>""" ] ]
|
|
||||||
element EnableTopicDiscovery {
|
|
||||||
xsd:boolean
|
|
||||||
}?
|
|
||||||
& [ a:documentation [ xml:lang="en" """
|
|
||||||
<p>An override for the domain id, to be used in discovery and for
|
<p>An override for the domain id, to be used in discovery and for
|
||||||
determining the port number mapping. This allows creating multiple
|
determining the port number mapping. This allows creating multiple
|
||||||
domains in a single process while making them appear as a single domain
|
domains in a single process while making them appear as a single domain
|
||||||
|
@ -272,7 +578,7 @@ be discovered.</p><p>The default value is: "".</p>""" ] ]
|
||||||
element Tag {
|
element Tag {
|
||||||
text
|
text
|
||||||
}?
|
}?
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The General element specifies overall Cyclone DDS service
|
<p>The General element specifies overall Cyclone DDS service
|
||||||
settings.</p>""" ] ]
|
settings.</p>""" ] ]
|
||||||
|
@ -807,7 +1113,7 @@ is therefore recommended to set it to at least several seconds.</p>
|
||||||
|
|
||||||
<p>Valid values are finite durations with an explicit unit or the keyword
|
<p>Valid values are finite durations with an explicit unit or the keyword
|
||||||
'inf' for infinity. Recognised units: ns, us, ms, s, min, hr,
|
'inf' for infinity. Recognised units: ns, us, ms, s, min, hr,
|
||||||
day.</p><p>The default value is: "10s".</p>""" ] ]
|
day.</p><p>The default value is: "0s".</p>""" ] ]
|
||||||
element RediscoveryBlacklistDuration {
|
element RediscoveryBlacklistDuration {
|
||||||
[ a:documentation [ xml:lang="en" """
|
[ a:documentation [ xml:lang="en" """
|
||||||
<p>This attribute controls whether the configured time during which
|
<p>This attribute controls whether the configured time during which
|
||||||
|
@ -1024,7 +1330,7 @@ s, min, hr, day.</p><p>The default value is: "1 s".</p>""" ] ]
|
||||||
element WriterLingerDuration {
|
element WriterLingerDuration {
|
||||||
duration
|
duration
|
||||||
}?
|
}?
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The Partitioning element specifies Cyclone DDS network partitions and
|
<p>The Partitioning element specifies Cyclone DDS network partitions and
|
||||||
how DCPS partition/topic combinations are mapped onto the network
|
how DCPS partition/topic combinations are mapped onto the network
|
||||||
|
@ -1114,7 +1420,7 @@ DCPSPartitionTopic attribute within this PartitionMapping element.</p>""" ] ]
|
||||||
}
|
}
|
||||||
}*
|
}*
|
||||||
}*
|
}*
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The SSL element allows specifying various parameters related to using
|
<p>The SSL element allows specifying various parameters related to using
|
||||||
SSL/TLS for DDSI over TCP.</p>""" ] ]
|
SSL/TLS for DDSI over TCP.</p>""" ] ]
|
||||||
|
@ -1174,7 +1480,7 @@ connecting client.</p><p>The default value is: "true".</p>""" ] ]
|
||||||
element VerifyClient {
|
element VerifyClient {
|
||||||
xsd:boolean
|
xsd:boolean
|
||||||
}?
|
}?
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The Sizing element specifies a variety of configuration settings
|
<p>The Sizing element specifies a variety of configuration settings
|
||||||
dealing with expected system sizes, buffer sizes, &c.</p>""" ] ]
|
dealing with expected system sizes, buffer sizes, &c.</p>""" ] ]
|
||||||
|
@ -1205,7 +1511,7 @@ MiB".</p>""" ] ]
|
||||||
element ReceiveBufferSize {
|
element ReceiveBufferSize {
|
||||||
memsize
|
memsize
|
||||||
}?
|
}?
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The TCP element allows specifying various parameters related to
|
<p>The TCP element allows specifying various parameters related to
|
||||||
running DDSI over TCP.</p>""" ] ]
|
running DDSI over TCP.</p>""" ] ]
|
||||||
|
@ -1262,7 +1568,7 @@ s, min, hr, day.</p><p>The default value is: "2 s".</p>""" ] ]
|
||||||
element WriteTimeout {
|
element WriteTimeout {
|
||||||
duration
|
duration
|
||||||
}?
|
}?
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The ThreadPool element allows specifying various parameters related to
|
<p>The ThreadPool element allows specifying various parameters related to
|
||||||
using a thread pool to send DDSI messages to multiple unicast addresses
|
using a thread pool to send DDSI messages to multiple unicast addresses
|
||||||
|
@ -1286,7 +1592,7 @@ pool.</p><p>The default value is: "4".</p>""" ] ]
|
||||||
element Threads {
|
element Threads {
|
||||||
xsd:integer
|
xsd:integer
|
||||||
}?
|
}?
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>This element is used to set thread properties.</p>""" ] ]
|
<p>This element is used to set thread properties.</p>""" ] ]
|
||||||
element Threads {
|
element Threads {
|
||||||
|
@ -1311,6 +1617,9 @@ for discovery;</li>
|
||||||
<li><i>tev</i>: general timed-event handling, retransmits and
|
<li><i>tev</i>: general timed-event handling, retransmits and
|
||||||
discovery;</li>
|
discovery;</li>
|
||||||
|
|
||||||
|
<li><i>fsm</i>: finite state machine thread for handling security
|
||||||
|
handshake;</li>
|
||||||
|
|
||||||
<li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li>
|
<li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li>
|
||||||
|
|
||||||
<li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li>
|
<li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li>
|
||||||
|
@ -1355,7 +1664,7 @@ default.</p>
|
||||||
memsize
|
memsize
|
||||||
}?
|
}?
|
||||||
}*
|
}*
|
||||||
}?
|
}*
|
||||||
& [ a:documentation [ xml:lang="en" """
|
& [ a:documentation [ xml:lang="en" """
|
||||||
<p>The Tracing element controls the amount and type of information that
|
<p>The Tracing element controls the amount and type of information that
|
||||||
is written into the tracing log by the DDSI service. This is useful to
|
is written into the tracing log by the DDSI service. This is useful to
|
||||||
|
@ -1472,8 +1781,8 @@ verbosity levels are <i>config</i>, <i>fine</i> and
|
||||||
element Verbosity {
|
element Verbosity {
|
||||||
("finest"|"finer"|"fine"|"config"|"info"|"warning"|"severe"|"none")
|
("finest"|"finer"|"fine"|"config"|"info"|"warning"|"severe"|"none")
|
||||||
}?
|
}?
|
||||||
}?
|
}*
|
||||||
}?
|
}*
|
||||||
}
|
}
|
||||||
bandwidth = xsd:token { pattern = "0|(\d+(\.\d*)?([Ee][\-+]?\d+)?|\.\d+([Ee][\-+]?\d+)?) *([kMG]i?)?[Bb][p/]s" }
|
bandwidth = xsd:token { pattern = "0|(\d+(\.\d*)?([Ee][\-+]?\d+)?|\.\d+([Ee][\-+]?\d+)?) *([kMG]i?)?[Bb][p/]s" }
|
||||||
duration = xsd:token { pattern = "0|(\d+(\.\d*)?([Ee][\-+]?\d+)?|\.\d+([Ee][\-+]?\d+)?) *([num]?s|min|hr|day)" }
|
duration = xsd:token { pattern = "0|(\d+(\.\d*)?([Ee][\-+]?\d+)?|\.\d+([Ee][\-+]?\d+)?) *([num]?s|min|hr|day)" }
|
||||||
|
|
|
@ -7,7 +7,7 @@ CycloneDDS configuration</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element minOccurs="0" ref="config:Domain"/>
|
<xs:element minOccurs="0" maxOccurs="unbounded" ref="config:Domain"/>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
@ -17,17 +17,18 @@ CycloneDDS configuration</xs:documentation>
|
||||||
<p>The General element specifying Domain related settings.</p></xs:documentation>
|
<p>The General element specifying Domain related settings.</p></xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:all>
|
<xs:choice minOccurs="0" maxOccurs="unbounded">
|
||||||
<xs:element minOccurs="0" ref="config:Compatibility"/>
|
<xs:element ref="config:Compatibility"/>
|
||||||
<xs:element minOccurs="0" ref="config:Discovery"/>
|
<xs:element ref="config:DDSSecurity"/>
|
||||||
<xs:element minOccurs="0" ref="config:General"/>
|
<xs:element ref="config:Discovery"/>
|
||||||
<xs:element minOccurs="0" ref="config:Internal"/>
|
<xs:element ref="config:General"/>
|
||||||
<xs:element minOccurs="0" ref="config:Partitioning"/>
|
<xs:element ref="config:Internal"/>
|
||||||
<xs:element minOccurs="0" ref="config:SSL"/>
|
<xs:element ref="config:Partitioning"/>
|
||||||
<xs:element minOccurs="0" ref="config:Sizing"/>
|
<xs:element ref="config:SSL"/>
|
||||||
<xs:element minOccurs="0" ref="config:TCP"/>
|
<xs:element ref="config:Sizing"/>
|
||||||
<xs:element minOccurs="0" ref="config:ThreadPool"/>
|
<xs:element ref="config:TCP"/>
|
||||||
<xs:element minOccurs="0" name="Threads">
|
<xs:element ref="config:ThreadPool"/>
|
||||||
|
<xs:element name="Threads">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>
|
<xs:documentation>
|
||||||
<p>This element is used to set thread properties.</p></xs:documentation>
|
<p>This element is used to set thread properties.</p></xs:documentation>
|
||||||
|
@ -38,8 +39,8 @@ CycloneDDS configuration</xs:documentation>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element minOccurs="0" ref="config:Tracing"/>
|
<xs:element ref="config:Tracing"/>
|
||||||
</xs:all>
|
</xs:choice>
|
||||||
<xs:attribute name="Id">
|
<xs:attribute name="Id">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>
|
<xs:documentation>
|
||||||
|
@ -146,6 +147,383 @@ though there is no good reason not to.</li></ul>
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
<xs:element name="DDSSecurity">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element is used to configure Cyclone DDS with the DDS Security
|
||||||
|
specification plugins and settings.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element minOccurs="0" ref="config:AccessControl"/>
|
||||||
|
<xs:element minOccurs="0" ref="config:Authentication"/>
|
||||||
|
<xs:element minOccurs="0" ref="config:Cryptographic"/>
|
||||||
|
</xs:all>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="AccessControl">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element configures the Access Control plugin of the DDS Security
|
||||||
|
specification.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element minOccurs="0" ref="config:Governance"/>
|
||||||
|
<xs:element minOccurs="0" name="Library">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element specifies the library to be loaded as the DDS Security
|
||||||
|
Access Control plugin.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="finalizeFunction">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element names the finalization function of Access Control plugin.
|
||||||
|
This function is called to let the plugin release its
|
||||||
|
resources.</p><p>The default value is:
|
||||||
|
&quot;finalize_access_control&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="initFunction">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element names the initialization function of Access Control
|
||||||
|
plugin. This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Access Control interface.</p><p>The default value
|
||||||
|
is: &quot;init_access_control&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="path">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element points to the path of Access Control plugin library.</p>
|
||||||
|
|
||||||
|
<p>It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_ac ) or single file without extension (
|
||||||
|
dds_security_ac ).</p>
|
||||||
|
|
||||||
|
<p>If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.</p><p>The default value is:
|
||||||
|
&quot;dds_security_ac&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element minOccurs="0" ref="config:Permissions"/>
|
||||||
|
<xs:element minOccurs="0" ref="config:PermissionsCA"/>
|
||||||
|
</xs:all>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Governance" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>URI to the shared Governance Document signed by the Permissions CA in
|
||||||
|
S/MIME format</p>
|
||||||
|
|
||||||
|
<p>URI schemes: file, data</p><br>
|
||||||
|
|
||||||
|
<p>Examples file URIs:</p>
|
||||||
|
|
||||||
|
<p><Governance>file:governance.smime</Governance></p>
|
||||||
|
|
||||||
|
<p><Governance>file:/home/myuser/governance.smime</Governance></p><br>
|
||||||
|
|
||||||
|
<p><Governance><![CDATA[data:,MIME-Version: 1.0</p>
|
||||||
|
|
||||||
|
<p>Content-Type: multipart/signed;
|
||||||
|
protocol="application/x-pkcs7-signature"; micalg="sha-256";
|
||||||
|
boundary="----F9A8A198D6F08E1285A292ADF14DD04F"</p>
|
||||||
|
|
||||||
|
<p>This is an S/MIME signed message </p>
|
||||||
|
|
||||||
|
<p>------F9A8A198D6F08E1285A292ADF14DD04F</p>
|
||||||
|
|
||||||
|
<p><?xml version="1.0" encoding="UTF-8"?></p>
|
||||||
|
|
||||||
|
<p><dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</p>
|
||||||
|
|
||||||
|
<p>xsi:noNamespaceSchemaLocation="omg_shared_ca_governance.xsd"></p>
|
||||||
|
|
||||||
|
<p><domain_access_rules></p>
|
||||||
|
|
||||||
|
<p> . . . </p>
|
||||||
|
|
||||||
|
<p></domain_access_rules></p>
|
||||||
|
|
||||||
|
<p></dds></p>
|
||||||
|
|
||||||
|
<p>...</p>
|
||||||
|
|
||||||
|
<p>------F9A8A198D6F08E1285A292ADF14DD04F</p>
|
||||||
|
|
||||||
|
<p>Content-Type: application/x-pkcs7-signature; name="smime.p7s"</p>
|
||||||
|
|
||||||
|
<p>Content-Transfer-Encoding: base64</p>
|
||||||
|
|
||||||
|
<p>Content-Disposition: attachment; filename="smime.p7s"</p>
|
||||||
|
|
||||||
|
<p>MIIDuAYJKoZIhv ...al5s=</p>
|
||||||
|
|
||||||
|
<p>------F9A8A198D6F08E1285A292ADF14DD04F-]]</Governance></p><p>The
|
||||||
|
default value is: &quot;&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Permissions" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>URI to the DomainParticipant permissions document signed by the
|
||||||
|
Permissions CA in S/MIME format</p>
|
||||||
|
|
||||||
|
<p>The permissions document specifies the permissions to be applied to a
|
||||||
|
domain.</p><br>
|
||||||
|
|
||||||
|
<p>Example file URIs:</p>
|
||||||
|
|
||||||
|
<p><Permissions>file:permissions_document.p7s</Permissions></p>
|
||||||
|
|
||||||
|
<p><Permissions>file:/path_to/permissions_document.p7s</Permissions></p>
|
||||||
|
|
||||||
|
<p>Example data URI:</p>
|
||||||
|
|
||||||
|
<p><Permissions><![CDATA[data:,.........]]</Permissions></p><p>The
|
||||||
|
default value is: &quot;&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="PermissionsCA" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>URI to a X509 certificate for the PermissionsCA in PEM format.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>The file and data schemas shall refer to a X.509 v3 certificate (see
|
||||||
|
X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.</p><br>
|
||||||
|
|
||||||
|
<p>Examples:</p><br>
|
||||||
|
|
||||||
|
<p><PermissionsCA>file:permissions_ca.pem</PermissionsCA></p>
|
||||||
|
|
||||||
|
<p><PermissionsCA>file:/home/myuser/permissions_ca.pem</PermissionsCA></p><br>
|
||||||
|
|
||||||
|
<p><PermissionsCA>data:<strong>,</strong>-----BEGIN CERTIFICATE-----</p>
|
||||||
|
|
||||||
|
<p>MIIC3DCCAcQCCQCWE5x+Z ... PhovK0mp2ohhRLYI0ZiyYQ==</p>
|
||||||
|
|
||||||
|
<p>-----END CERTIFICATE-----</PermissionsCA></p><p>The default value is:
|
||||||
|
&quot;&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Authentication">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element configures the Authentication plugin of the DDS Security
|
||||||
|
specification.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:all>
|
||||||
|
<xs:element ref="config:IdentityCA"/>
|
||||||
|
<xs:element ref="config:IdentityCertificate"/>
|
||||||
|
<xs:element minOccurs="0" ref="config:IncludeOptionalFields"/>
|
||||||
|
<xs:element minOccurs="0" name="Library">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element specifies the library to be loaded as the DDS Security
|
||||||
|
Access Control plugin.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="finalizeFunction">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element names the finalization function of Authentication plugin.
|
||||||
|
This function is called to let the plugin release its
|
||||||
|
resources.</p><p>The default value is:
|
||||||
|
&quot;finalize_authentication&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="initFunction">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element names the initialization function of Authentication
|
||||||
|
plugin. This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Authentication interface.</p><p>The default value
|
||||||
|
is: &quot;init_authentication&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="path">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element points to the path of Authentication plugin library.</p>
|
||||||
|
|
||||||
|
<p>It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_auth ) or single file without extension (
|
||||||
|
dds_security_auth ).</p>
|
||||||
|
|
||||||
|
<p>If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.</p><p>The default value is:
|
||||||
|
&quot;dds_security_auth&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element minOccurs="0" ref="config:Password"/>
|
||||||
|
<xs:element ref="config:PrivateKey"/>
|
||||||
|
<xs:element minOccurs="0" ref="config:TrustedCADirectory"/>
|
||||||
|
</xs:all>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="IdentityCA" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>URI to the X509 certificate [39] of the Identity CA that is the signer
|
||||||
|
of Identity Certificate.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>The file and data schemas shall refer to a X.509 v3 certificate (see
|
||||||
|
X.509 v3 ITU-T Recommendation X.509 (2005) [39]) in PEM format.</p>
|
||||||
|
|
||||||
|
<p>Examples:</p>
|
||||||
|
|
||||||
|
<p><IdentityCA>file:identity_ca.pem</IdentityCA></p>
|
||||||
|
|
||||||
|
<p><IdentityCA>data:,-----BEGIN CERTIFICATE-----<br>
|
||||||
|
|
||||||
|
MIIC3DCCAcQCCQCWE5x+Z...PhovK0mp2ohhRLYI0ZiyYQ==<br>
|
||||||
|
|
||||||
|
-----END CERTIFICATE-----</IdentityCA></p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="IdentityCertificate" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>Identity certificate that will be used for identifying all
|
||||||
|
participants in the OSPL instance.<br>The content is URI to a X509
|
||||||
|
certificate signed by the IdentityCA in PEM format containing the signed
|
||||||
|
public key.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>Examples:</p>
|
||||||
|
|
||||||
|
<p><IdentityCertificate>file:participant1_identity_cert.pem</IdentityCertificate></p>
|
||||||
|
|
||||||
|
<p><IdentityCertificate>data:,-----BEGIN CERTIFICATE-----<br>
|
||||||
|
|
||||||
|
MIIDjjCCAnYCCQDCEu9...6rmT87dhTo=<br>
|
||||||
|
|
||||||
|
-----END CERTIFICATE-----</IdentityCertificate></p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="IncludeOptionalFields" type="xs:boolean">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>The authentication handshake tokens may contain optional fields to be
|
||||||
|
included for finding interoperability problems.
|
||||||
|
|
||||||
|
If this parameter is set to true the optional fields are included in the
|
||||||
|
handshake token exchange.</p><p>The default value is:
|
||||||
|
&quot;false&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Password" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>A password used to decrypt the private_key.</p>
|
||||||
|
|
||||||
|
The value of the password property shall be interpreted as the Base64
|
||||||
|
encoding of the AES-128 key that shall be used to decrypt the private_key
|
||||||
|
using AES128-CBC.</p>
|
||||||
|
|
||||||
|
If the password property is not present, then the value supplied in the
|
||||||
|
private_key property must contain the unencrypted private key. </p><p>The
|
||||||
|
default value is: &quot;&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="PrivateKey" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>URI to access the private Private Key for all of the participants in
|
||||||
|
the OSPL federation.</p>
|
||||||
|
|
||||||
|
<p>Supported URI schemes: file, data</p>
|
||||||
|
|
||||||
|
<p>Examples:</p>
|
||||||
|
|
||||||
|
<p><PrivateKey>file:identity_ca_private_key.pem</PrivateKey></p>
|
||||||
|
|
||||||
|
<p><PrivateKey>data:,-----BEGIN RSA PRIVATE KEY-----<br>
|
||||||
|
|
||||||
|
MIIEpAIBAAKCAQEA3HIh...AOBaaqSV37XBUJg==<br>
|
||||||
|
|
||||||
|
-----END RSA PRIVATE KEY-----</PrivateKey></p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="TrustedCADirectory" type="xs:string">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>Trusted CA Directory which contains trusted CA certificates as
|
||||||
|
separated files.</p><p>The default value is: &quot;&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="Cryptographic">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element configures the Cryptographic plugin of the DDS Security
|
||||||
|
specification.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" name="Library">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element specifies the library to be loaded as the DDS Security
|
||||||
|
Cryptographic plugin.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:attribute name="finalizeFunction">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element names the finalization function of Cryptographic plugin.
|
||||||
|
This function is called to let the plugin release its
|
||||||
|
resources.</p><p>The default value is: &quot;finalize_crypto&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="initFunction">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element names the initialization function of Cryptographic
|
||||||
|
plugin. This function is called after loading the plugin library for
|
||||||
|
instantiation purposes. Init function must return an object that
|
||||||
|
implements DDS Security Cryptographic interface.</p><p>The default value
|
||||||
|
is: &quot;init_crypto&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="path">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>
|
||||||
|
<p>This element points to the path of Cryptographic plugin library.</p>
|
||||||
|
|
||||||
|
<p>It can be either absolute path excluding file extension (
|
||||||
|
/usr/lib/dds_security_crypto ) or single file without extension (
|
||||||
|
dds_security_crypto ).</p>
|
||||||
|
|
||||||
|
<p>If single file is supplied, the library located by way of the current
|
||||||
|
working directory, or LD_LIBRARY_PATH for Unix systems, and PATH for
|
||||||
|
Windows systems.</p><p>The default value is:
|
||||||
|
&quot;dds_security_crypto&quot;.</p></xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
<xs:element name="Discovery">
|
<xs:element name="Discovery">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>
|
<xs:documentation>
|
||||||
|
@ -156,7 +534,6 @@ the discovery of peers.</p></xs:documentation>
|
||||||
<xs:all>
|
<xs:all>
|
||||||
<xs:element minOccurs="0" ref="config:DSGracePeriod"/>
|
<xs:element minOccurs="0" ref="config:DSGracePeriod"/>
|
||||||
<xs:element minOccurs="0" ref="config:DefaultMulticastAddress"/>
|
<xs:element minOccurs="0" ref="config:DefaultMulticastAddress"/>
|
||||||
<xs:element minOccurs="0" ref="config:EnableTopicDiscovery"/>
|
|
||||||
<xs:element minOccurs="0" ref="config:ExternalDomainId"/>
|
<xs:element minOccurs="0" ref="config:ExternalDomainId"/>
|
||||||
<xs:element minOccurs="0" ref="config:MaxAutoParticipantIndex"/>
|
<xs:element minOccurs="0" ref="config:MaxAutoParticipantIndex"/>
|
||||||
<xs:element minOccurs="0" ref="config:ParticipantIndex"/>
|
<xs:element minOccurs="0" ref="config:ParticipantIndex"/>
|
||||||
|
@ -190,12 +567,6 @@ Discovery/SPDPMulticastAddress.</p><p>The default value is:
|
||||||
&quot;auto&quot;.</p></xs:documentation>
|
&quot;auto&quot;.</p></xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="EnableTopicDiscovery" type="xs:boolean">
|
|
||||||
<xs:annotation>
|
|
||||||
<xs:documentation>
|
|
||||||
<p>Do not use.</p><p>The default value is: &quot;true&quot;.</p></xs:documentation>
|
|
||||||
</xs:annotation>
|
|
||||||
</xs:element>
|
|
||||||
<xs:element name="ExternalDomainId" type="xs:string">
|
<xs:element name="ExternalDomainId" type="xs:string">
|
||||||
<xs:annotation>
|
<xs:annotation>
|
||||||
<xs:documentation>
|
<xs:documentation>
|
||||||
|
@ -1104,7 +1475,7 @@ is therefore recommended to set it to at least several seconds.</p>
|
||||||
|
|
||||||
<p>Valid values are finite durations with an explicit unit or the keyword
|
<p>Valid values are finite durations with an explicit unit or the keyword
|
||||||
'inf' for infinity. Recognised units: ns, us, ms, s, min, hr,
|
'inf' for infinity. Recognised units: ns, us, ms, s, min, hr,
|
||||||
day.</p><p>The default value is: &quot;10s&quot;.</p></xs:documentation>
|
day.</p><p>The default value is: &quot;0s&quot;.</p></xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:simpleContent>
|
<xs:simpleContent>
|
||||||
|
@ -1777,6 +2148,9 @@ for discovery;</li>
|
||||||
<li><i>tev</i>: general timed-event handling, retransmits and
|
<li><i>tev</i>: general timed-event handling, retransmits and
|
||||||
discovery;</li>
|
discovery;</li>
|
||||||
|
|
||||||
|
<li><i>fsm</i>: finite state machine thread for handling security
|
||||||
|
handshake;</li>
|
||||||
|
|
||||||
<li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li>
|
<li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li>
|
||||||
|
|
||||||
<li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li>
|
<li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||||
<package format="3">
|
<package format="3">
|
||||||
<name>cyclonedds</name>
|
<name>cyclonedds</name>
|
||||||
<version>0.6.0</version>
|
<version>0.7.0</version>
|
||||||
<description>Eclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project.</description>
|
<description>Eclipse Cyclone DDS is a very performant and robust open-source DDS implementation. Cyclone DDS is developed completely in the open as an Eclipse IoT project.</description>
|
||||||
<maintainer email="cyclonedds-dev@eclipse.org">Eclipse Foundation, Inc.</maintainer>
|
<maintainer email="cyclonedds-dev@eclipse.org">Eclipse Foundation, Inc.</maintainer>
|
||||||
<license>Eclipse Public License 2.0</license>
|
<license>Eclipse Public License 2.0</license>
|
||||||
|
|
|
@ -16,6 +16,69 @@ if(NOT ${PROJECT_NAME} STREQUAL "CycloneDDS")
|
||||||
message(FATAL_ERROR "Top-level CMakeLists.txt was moved to the top-level directory. Please run cmake on ${dir} instead of ${CMAKE_CURRENT_LIST_DIR}")
|
message(FATAL_ERROR "Top-level CMakeLists.txt was moved to the top-level directory. Please run cmake on ${dir} instead of ${CMAKE_CURRENT_LIST_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Generate a header file listing compile-time options relevant to the API. Define to
|
||||||
|
# "1" if enabled so that the generated features.h ends up having either
|
||||||
|
#
|
||||||
|
# - #define DDS_HAS_SECURITY 1
|
||||||
|
# or
|
||||||
|
# - /* #undef DDS_HAS_SECURITY */
|
||||||
|
#
|
||||||
|
# which caters both for those who prefer #ifdef DDS_HAS_SECURITY and for those who prefer
|
||||||
|
# #if DDS_HAS_SECURITY.
|
||||||
|
if(ENABLE_SECURITY)
|
||||||
|
set(DDS_HAS_SECURITY "1")
|
||||||
|
endif()
|
||||||
|
if(ENABLE_LIFESPAN)
|
||||||
|
set(DDS_HAS_LIFESPAN "1")
|
||||||
|
endif()
|
||||||
|
if(ENABLE_DEADLINE_MISSED)
|
||||||
|
set(DDS_HAS_DEADLINE_MISSED "1")
|
||||||
|
endif()
|
||||||
|
configure_file(features.h.in "${CMAKE_CURRENT_BINARY_DIR}/core/include/dds/features.h")
|
||||||
|
|
||||||
|
add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM)
|
||||||
|
|
||||||
|
# OpenSSL is huge, raising the RSS by 1MB or so, and moreover find_package(OpenSSL) causes
|
||||||
|
# trouble on some older CMake versions that otherwise work fine, so provide an option to avoid
|
||||||
|
# all OpenSSL related things.
|
||||||
|
#
|
||||||
|
# Historically the option was DDSC_ENABLE_OPENSSL so make some allowance for those who are
|
||||||
|
# currently relying on it.
|
||||||
|
option(ENABLE_SSL "Enable openssl support" ON)
|
||||||
|
option(DDSC_ENABLE_OPENSSL "Deprecated: please use ENABLE_SSL instead" ON)
|
||||||
|
if(NOT DDSC_ENABLE_OPENSSL)
|
||||||
|
message(ERROR "DDSC_ENABLE_OPENSSL is deprecated, please use ENABLE_SSL instead")
|
||||||
|
set(ENABLE_SSL OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_SSL)
|
||||||
|
find_package(OpenSSL)
|
||||||
|
if(OPENSSL_FOUND)
|
||||||
|
add_definitions(-DDDSI_INCLUDE_SSL)
|
||||||
|
message(STATUS "Building with OpenSSL support")
|
||||||
|
else()
|
||||||
|
message(STATUS "Building without OpenSSL support")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Support the OMG DDS Security within ddsc adds quite a bit of code.
|
||||||
|
option(ENABLE_SECURITY "Enable OMG DDS Security support" ON)
|
||||||
|
if(NOT ENABLE_SECURITY)
|
||||||
|
message(STATUS "Building without OMG DDS Security support")
|
||||||
|
else()
|
||||||
|
add_definitions(-DDDSI_INCLUDE_SECURITY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_LIFESPAN "Enable Lifespan QoS support" ON)
|
||||||
|
if(ENABLE_LIFESPAN)
|
||||||
|
add_definitions(-DDDSI_INCLUDE_LIFESPAN)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_DEADLINE_MISSED "Enable Deadline Missed QoS support" ON)
|
||||||
|
if(ENABLE_DEADLINE_MISSED)
|
||||||
|
add_definitions(-DDDSI_INCLUDE_DEADLINE_MISSED)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_subdirectory(ddsrt)
|
add_subdirectory(ddsrt)
|
||||||
|
|
||||||
# some of the tests in the core rely on preprocessing IDL, so idlc has to
|
# some of the tests in the core rely on preprocessing IDL, so idlc has to
|
||||||
|
@ -23,6 +86,7 @@ add_subdirectory(ddsrt)
|
||||||
if(BUILD_IDLC)
|
if(BUILD_IDLC)
|
||||||
add_subdirectory(idlc)
|
add_subdirectory(idlc)
|
||||||
endif()
|
endif()
|
||||||
|
add_subdirectory(security)
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
if(BUILD_TESTING AND HAVE_MULTI_PROCESS AND BUILD_IDLC)
|
if(BUILD_TESTING AND HAVE_MULTI_PROCESS AND BUILD_IDLC)
|
||||||
|
|
|
@ -25,42 +25,19 @@ else()
|
||||||
add_library(ddsc)
|
add_library(ddsc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_definitions(-DDDSI_INCLUDE_NETWORK_PARTITIONS -DDDSI_INCLUDE_SSM)
|
if(ENABLE_SSL AND OPENSSL_FOUND)
|
||||||
|
|
||||||
option(ENABLE_LIFESPAN "Enable Lifespan QoS support" ON)
|
|
||||||
if(ENABLE_LIFESPAN)
|
|
||||||
add_definitions(-DDDSI_INCLUDE_LIFESPAN)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(ENABLE_DEADLINE_MISSED "Enable Deadline Missed QoS support" ON)
|
|
||||||
if(ENABLE_DEADLINE_MISSED)
|
|
||||||
add_definitions(-DDDSI_INCLUDE_DEADLINE_MISSED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# OpenSSL is huge, raising the RSS by 1MB or so, and moreover find_package(OpenSSL) causes
|
|
||||||
# trouble on some older CMake versions that otherwise work fine, so provide an option to avoid
|
|
||||||
# all OpenSSL related things.
|
|
||||||
#
|
|
||||||
# Historically the option was DDSC_ENABLE_OPENSSL so make some allowance for those who are
|
|
||||||
# currently relying on it.
|
|
||||||
option(ENABLE_SSL "Enable openssl support" ON)
|
|
||||||
option(DDSC_ENABLE_OPENSSL "Deprecated: please use ENABLE_SSL instead" ON)
|
|
||||||
if(NOT DDSC_ENABLE_OPENSSL)
|
|
||||||
message(ERROR "DDSC_ENABLE_OPENSSL is deprecated, please use ENABLE_SSL instead")
|
|
||||||
set(ENABLE_SSL OFF)
|
|
||||||
endif()
|
|
||||||
if(ENABLE_SSL)
|
|
||||||
find_package(OpenSSL)
|
|
||||||
if(OPENSSL_FOUND)
|
|
||||||
add_definitions(-DDDSI_INCLUDE_SSL)
|
|
||||||
target_link_libraries(ddsc PRIVATE OpenSSL::SSL)
|
target_link_libraries(ddsc PRIVATE OpenSSL::SSL)
|
||||||
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
set_target_properties(ddsc PROPERTIES LINK_FLAGS "/ignore:4099")
|
set_target_properties(ddsc PROPERTIES LINK_FLAGS "/ignore:4099")
|
||||||
endif()
|
endif()
|
||||||
message(STATUS "Building with OpenSSL support")
|
|
||||||
else()
|
|
||||||
message(STATUS "Building without OpenSSL support")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Support the OMG DDS Security within ddsc adds quite a bit of code.
|
||||||
|
if(ENABLE_SECURITY)
|
||||||
|
target_link_libraries(ddsc PRIVATE security_core)
|
||||||
|
target_include_directories(
|
||||||
|
ddsc PUBLIC
|
||||||
|
$<BUILD_INTERFACE:$<TARGET_PROPERTY:security_api,INTERFACE_INCLUDE_DIRECTORIES>>)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(ddsi/CMakeLists.txt)
|
include(ddsi/CMakeLists.txt)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "dds/export.h"
|
#include "dds/export.h"
|
||||||
|
#include "dds/features.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle to an entity. A valid entity handle will always have a positive
|
* Handle to an entity. A valid entity handle will always have a positive
|
||||||
|
@ -89,6 +90,7 @@ typedef enum dds_status_id {
|
||||||
DDS_PUBLICATION_MATCHED_STATUS_ID,
|
DDS_PUBLICATION_MATCHED_STATUS_ID,
|
||||||
DDS_SUBSCRIPTION_MATCHED_STATUS_ID
|
DDS_SUBSCRIPTION_MATCHED_STATUS_ID
|
||||||
} dds_status_id_t;
|
} dds_status_id_t;
|
||||||
|
#define DDS_STATUS_ID_MAX (DDS_SUBSCRIPTION_MATCHED_STATUS_ID)
|
||||||
|
|
||||||
/** Another topic exists with the same name but with different characteristics. */
|
/** Another topic exists with the same name but with different characteristics. */
|
||||||
#define DDS_INCONSISTENT_TOPIC_STATUS (1u << DDS_INCONSISTENT_TOPIC_STATUS_ID)
|
#define DDS_INCONSISTENT_TOPIC_STATUS (1u << DDS_INCONSISTENT_TOPIC_STATUS_ID)
|
||||||
|
@ -762,8 +764,22 @@ dds_set_listener(dds_entity_t entity, const dds_listener_t * listener);
|
||||||
*
|
*
|
||||||
* @retval >0
|
* @retval >0
|
||||||
* A valid participant handle.
|
* A valid participant handle.
|
||||||
|
* @retval DDS_RETCODE_NOT_ALLOWED_BY_SECURITY
|
||||||
|
* An invalid DDS Security configuration was specified (whether
|
||||||
|
* that be missing or incorrect entries, expired certificates,
|
||||||
|
* or anything else related to the security settings and
|
||||||
|
* implementation).
|
||||||
|
* @retval DDS_RETCODE_PRECONDITION_NOT_MET
|
||||||
|
* Some security properties specified in the QoS, but the Cyclone
|
||||||
|
* build does not include support for DDS Security.
|
||||||
|
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||||
|
* Some resource limit (maximum participants, memory, handles,
|
||||||
|
* &c.) prevented creation of the participant.
|
||||||
* @retval DDS_RETCODE_ERROR
|
* @retval DDS_RETCODE_ERROR
|
||||||
* An internal error has occurred.
|
* The "CYCLONEDDS_URI" environment variable lists non-existent
|
||||||
|
* or invalid configuration files, or contains invalid embedded
|
||||||
|
* configuration items; or an unspecified internal error has
|
||||||
|
* occurred.
|
||||||
*/
|
*/
|
||||||
DDS_EXPORT dds_entity_t
|
DDS_EXPORT dds_entity_t
|
||||||
dds_create_participant(
|
dds_create_participant(
|
||||||
|
@ -2741,6 +2757,53 @@ dds_take_mask_wl(
|
||||||
uint32_t maxs,
|
uint32_t maxs,
|
||||||
uint32_t mask);
|
uint32_t mask);
|
||||||
|
|
||||||
|
#define DDS_HAS_READCDR 1
|
||||||
|
/**
|
||||||
|
* @brief Access the collection of serialized data values (of same type) and
|
||||||
|
* sample info from the data reader, readcondition or querycondition.
|
||||||
|
*
|
||||||
|
* This call accesses the serialized data from the data reader, readcondition or
|
||||||
|
* querycondition and makes it available to the application. The serialized data
|
||||||
|
* is made available through \ref ddsi_serdata structures. Returned samples are
|
||||||
|
* marked as READ.
|
||||||
|
*
|
||||||
|
* Return value provides information about the number of samples read, which will
|
||||||
|
* be <= maxs. Based on the count, the buffer will contain serialized data to be
|
||||||
|
* read only when valid_data bit in sample info structure is set.
|
||||||
|
* The buffer required for data values, could be allocated explicitly or can
|
||||||
|
* use the memory from data reader to prevent copy. In the latter case, buffer and
|
||||||
|
* sample_info should be returned back, once it is no longer using the data.
|
||||||
|
*
|
||||||
|
* @param[in] reader_or_condition Reader, readcondition or querycondition entity.
|
||||||
|
* @param[out] buf An array of pointers to \ref ddsi_serdata structures that contain
|
||||||
|
* the serialized data. The pointers can be NULL.
|
||||||
|
* @param[in] maxs Maximum number of samples to read.
|
||||||
|
* @param[out] si Pointer to an array of \ref dds_sample_info_t returned for each data value.
|
||||||
|
* @param[in] mask Filter the data based on dds_sample_state_t|dds_view_state_t|dds_instance_state_t.
|
||||||
|
*
|
||||||
|
* @returns A dds_return_t with the number of samples read or an error code.
|
||||||
|
*
|
||||||
|
* @retval >=0
|
||||||
|
* Number of samples read.
|
||||||
|
* @retval DDS_RETCODE_ERROR
|
||||||
|
* An internal error has occurred.
|
||||||
|
* @retval DDS_RETCODE_BAD_PARAMETER
|
||||||
|
* One of the given arguments is not valid.
|
||||||
|
* @retval DDS_RETCODE_ILLEGAL_OPERATION
|
||||||
|
* The operation is invoked on an inappropriate object.
|
||||||
|
* @retval DDS_RETCODE_ALREADY_DELETED
|
||||||
|
* The entity has already been deleted.
|
||||||
|
* @retval DDS_RETCODE_PRECONDITION_NOT_MET
|
||||||
|
* The precondition for this operation is not met.
|
||||||
|
*/
|
||||||
|
DDS_EXPORT dds_return_t
|
||||||
|
dds_readcdr(
|
||||||
|
dds_entity_t reader_or_condition,
|
||||||
|
struct ddsi_serdata **buf,
|
||||||
|
uint32_t maxs,
|
||||||
|
dds_sample_info_t *si,
|
||||||
|
uint32_t mask);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Access the collection of serialized data values (of same type) and
|
* @brief Access the collection of serialized data values (of same type) and
|
||||||
* sample info from the data reader, readcondition or querycondition.
|
* sample info from the data reader, readcondition or querycondition.
|
||||||
|
|
|
@ -225,6 +225,13 @@ enum dds_stream_typecode_subtype {
|
||||||
#define DDS_OP_FLAG_KEY 0x01 /* key field: applicable to {1,2,4,8}BY, STR, BST, ARR-of-{1,2,4,8}BY */
|
#define DDS_OP_FLAG_KEY 0x01 /* key field: applicable to {1,2,4,8}BY, STR, BST, ARR-of-{1,2,4,8}BY */
|
||||||
#define DDS_OP_FLAG_DEF 0x02 /* union has a default case (for DDS_OP_ADR | DDS_OP_TYPE_UNI) */
|
#define DDS_OP_FLAG_DEF 0x02 /* union has a default case (for DDS_OP_ADR | DDS_OP_TYPE_UNI) */
|
||||||
|
|
||||||
|
/* For a union: (1) the discriminator may be a key field; (2) there may be a default value;
|
||||||
|
and (3) the discriminator can be an integral type (or enumerated - here treated as equivalent).
|
||||||
|
What it can't be is a floating-point type. So DEF and FP need never be set at the same time.
|
||||||
|
There are only a few flag bits, so saving one is not such a bad idea. */
|
||||||
|
#define DDS_OP_FLAG_FP 0x02 /* floating-point: applicable to {4,8}BY and arrays, sequences of them */
|
||||||
|
#define DDS_OP_FLAG_SGN 0x04 /* signed: applicable to {1,2,4,8}BY and arrays, sequences of them */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description : Enable or disable write batching. Overrides default configuration
|
* Description : Enable or disable write batching. Overrides default configuration
|
||||||
* setting for write batching (Internal/WriteBatch).
|
* setting for write batching (Internal/WriteBatch).
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
#include "dds/export.h"
|
#include "dds/export.h"
|
||||||
#include "dds/ddsc/dds_public_qosdefs.h"
|
#include "dds/ddsc/dds_public_qosdefs.h"
|
||||||
|
|
||||||
|
/* Whether or not the "property list" QoS setting is supported in this version. If it is,
|
||||||
|
the "dds.sec." properties are treated specially, preventing the accidental creation of
|
||||||
|
an non-secure participant by an implementation built without support for DDS Security. */
|
||||||
|
#define DDS_HAS_PROPERTY_LIST_QOS 1
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -381,6 +386,72 @@ dds_qset_ignorelocal (
|
||||||
dds_qos_t * __restrict qos,
|
dds_qos_t * __restrict qos,
|
||||||
dds_ignorelocal_kind_t ignore);
|
dds_ignorelocal_kind_t ignore);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores a property with the provided name and string value in a qos structure.
|
||||||
|
*
|
||||||
|
* In the case a property with the provided name already exists in the qos structure,
|
||||||
|
* the value for this entry is overwritten with the provided string value. If more than
|
||||||
|
* one property with the provided name exists, only the value of the first of these
|
||||||
|
* properties is updated.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the property
|
||||||
|
* @param[in] name - Pointer to name of the property
|
||||||
|
* @param[in] value - Pointer to a (null-terminated) string that will be stored
|
||||||
|
*/
|
||||||
|
DDS_EXPORT void
|
||||||
|
dds_qset_prop (
|
||||||
|
dds_qos_t * __restrict qos,
|
||||||
|
const char * name,
|
||||||
|
const char * value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes the property with the provided name from a qos structure.
|
||||||
|
*
|
||||||
|
* In case more than one property exists with this name, only the first property
|
||||||
|
* is removed.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that contains the property
|
||||||
|
* @param[in] name - Pointer to name of the property
|
||||||
|
*/
|
||||||
|
DDS_EXPORT void
|
||||||
|
dds_qunset_prop (
|
||||||
|
dds_qos_t * __restrict qos,
|
||||||
|
const char * name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores the provided binary data as a property in a qos structure
|
||||||
|
*
|
||||||
|
* In the case a property with the provided name already exists in the qos structure,
|
||||||
|
* the value for this entry is overwritten with the provided data. If more than one
|
||||||
|
* property with the provided name exists, only the value of the first of these
|
||||||
|
* properties is updated.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the property
|
||||||
|
* @param[in] name - Pointer to name of the property
|
||||||
|
* @param[in] value - Pointer to data to be stored in the property
|
||||||
|
* @param[in] sz - Size of the data
|
||||||
|
*/
|
||||||
|
DDS_EXPORT void
|
||||||
|
dds_qset_bprop (
|
||||||
|
dds_qos_t * __restrict qos,
|
||||||
|
const char * name,
|
||||||
|
const void * value,
|
||||||
|
const size_t sz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Removes the binary property with the provided name from a qos structure.
|
||||||
|
*
|
||||||
|
* In case more than one binary property exists with this name, only the first binary
|
||||||
|
* property is removed.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that contains the binary property
|
||||||
|
* @param[in] name - Pointer to name of the property
|
||||||
|
*/
|
||||||
|
DDS_EXPORT void
|
||||||
|
dds_qunset_bprop (
|
||||||
|
dds_qos_t * __restrict qos,
|
||||||
|
const char * name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the userdata from a qos structure
|
* @brief Get the userdata from a qos structure
|
||||||
*
|
*
|
||||||
|
@ -682,6 +753,74 @@ dds_qget_ignorelocal (
|
||||||
const dds_qos_t * __restrict qos,
|
const dds_qos_t * __restrict qos,
|
||||||
dds_ignorelocal_kind_t *ignore);
|
dds_ignorelocal_kind_t *ignore);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the names of the properties from a qos structure.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that contains properties
|
||||||
|
* @param[in,out] n - Pointer to number of property names that are returned (optional)
|
||||||
|
* @param[in,out] names - Pointer that will store the string(s) containing property name(s) (optional). This function will allocate the memory for the list of names and for the strings containing the names; the caller gets ownership of the allocated memory
|
||||||
|
*
|
||||||
|
* @returns - false iff any of the arguments is invalid or the qos is not present in the qos object
|
||||||
|
*/
|
||||||
|
DDS_EXPORT bool
|
||||||
|
dds_qget_propnames (
|
||||||
|
const dds_qos_t * __restrict qos,
|
||||||
|
uint32_t * n,
|
||||||
|
char *** names);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the value of the property with the provided name from a qos structure.
|
||||||
|
*
|
||||||
|
* In case more than one property exists with this name, the value for the first
|
||||||
|
* property with this name will be returned.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that contains the property
|
||||||
|
* @param[in] name - Pointer to name of the property
|
||||||
|
* @param[in,out] value - Pointer to a string that will store the value of the property. The memory for storing the string value will be allocated by this function and the caller gets ownership of the allocated memory
|
||||||
|
*
|
||||||
|
* @returns - false iff any of the arguments is invalid, the qos is not present in the qos object or there was no property found with the provided name
|
||||||
|
*/
|
||||||
|
DDS_EXPORT bool
|
||||||
|
dds_qget_prop (
|
||||||
|
const dds_qos_t * __restrict qos,
|
||||||
|
const char * name,
|
||||||
|
char ** value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the names of the binary properties from a qos structure.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that contains binary properties
|
||||||
|
* @param[in,out] n - Pointer to number of binary property names that are returned (optional)
|
||||||
|
* @param[in,out] names - Pointer that will store the string(s) containing binary property name(s) (optional). This function will allocate the memory for the list of names and for the strings containing the names; the caller gets ownership of the allocated memory
|
||||||
|
*
|
||||||
|
* @returns - false iff any of the arguments is invalid or the qos is not present in the qos object
|
||||||
|
*/
|
||||||
|
DDS_EXPORT bool
|
||||||
|
dds_qget_bpropnames (
|
||||||
|
const dds_qos_t * __restrict qos,
|
||||||
|
uint32_t * n,
|
||||||
|
char *** names);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the value of the binary property with the provided name from a qos structure.
|
||||||
|
*
|
||||||
|
* In case more than one binary property exists with this name, the value for the first
|
||||||
|
* binary property with this name will be returned.
|
||||||
|
*
|
||||||
|
* @param[in,out] qos - Pointer to a dds_qos_t structure that contains the property
|
||||||
|
* @param[in] name - Pointer to name of the binary property
|
||||||
|
* @param[in,out] value - Pointer to a buffer that will store the value of the property. If sz = 0 then a NULL pointer. The memory for storing the value will be allocated by this function and the caller gets ownership of the allocated memory
|
||||||
|
* @param[in,out] sz - Pointer that will store the size of the returned buffer.
|
||||||
|
*
|
||||||
|
* @returns - false iff any of the arguments is invalid, the qos is not present in the qos object or there was no binary property found with the provided name
|
||||||
|
*/
|
||||||
|
DDS_EXPORT bool
|
||||||
|
dds_qget_bprop (
|
||||||
|
const dds_qos_t * __restrict qos,
|
||||||
|
const char * name,
|
||||||
|
void ** value,
|
||||||
|
size_t * sz);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,7 +50,8 @@ typedef enum dds_qos_policy_id {
|
||||||
DDS_GROUPDATA_QOS_POLICY_ID,
|
DDS_GROUPDATA_QOS_POLICY_ID,
|
||||||
DDS_TRANSPORTPRIORITY_QOS_POLICY_ID,
|
DDS_TRANSPORTPRIORITY_QOS_POLICY_ID,
|
||||||
DDS_LIFESPAN_QOS_POLICY_ID,
|
DDS_LIFESPAN_QOS_POLICY_ID,
|
||||||
DDS_DURABILITYSERVICE_QOS_POLICY_ID
|
DDS_DURABILITYSERVICE_QOS_POLICY_ID,
|
||||||
|
DDS_PROPERTY_QOS_POLICY_ID,
|
||||||
} dds_qos_policy_id_t;
|
} dds_qos_policy_id_t;
|
||||||
|
|
||||||
/* QoS structure is opaque */
|
/* QoS structure is opaque */
|
||||||
|
|
|
@ -27,9 +27,8 @@ struct dds_reader;
|
||||||
struct ddsi_tkmap;
|
struct ddsi_tkmap;
|
||||||
|
|
||||||
typedef dds_return_t (*dds_rhc_associate_t) (struct dds_rhc *rhc, struct dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap);
|
typedef dds_return_t (*dds_rhc_associate_t) (struct dds_rhc *rhc, struct dds_reader *reader, const struct ddsi_sertopic *topic, struct ddsi_tkmap *tkmap);
|
||||||
typedef int (*dds_rhc_read_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
typedef int32_t (*dds_rhc_read_take_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
||||||
typedef int (*dds_rhc_take_t) (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
typedef int32_t (*dds_rhc_read_take_cdr_t) (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
||||||
typedef int (*dds_rhc_takecdr_t) (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
|
||||||
|
|
||||||
typedef bool (*dds_rhc_add_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond);
|
typedef bool (*dds_rhc_add_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||||
typedef void (*dds_rhc_remove_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond);
|
typedef void (*dds_rhc_remove_readcondition_t) (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||||
|
@ -40,9 +39,10 @@ struct dds_rhc_ops {
|
||||||
/* A copy of DDSI rhc ops comes first so we can use either interface without
|
/* A copy of DDSI rhc ops comes first so we can use either interface without
|
||||||
additional indirections */
|
additional indirections */
|
||||||
struct ddsi_rhc_ops rhc_ops;
|
struct ddsi_rhc_ops rhc_ops;
|
||||||
dds_rhc_read_t read;
|
dds_rhc_read_take_t read;
|
||||||
dds_rhc_take_t take;
|
dds_rhc_read_take_t take;
|
||||||
dds_rhc_takecdr_t takecdr;
|
dds_rhc_read_take_cdr_t readcdr;
|
||||||
|
dds_rhc_read_take_cdr_t takecdr;
|
||||||
dds_rhc_add_readcondition_t add_readcondition;
|
dds_rhc_add_readcondition_t add_readcondition;
|
||||||
dds_rhc_remove_readcondition_t remove_readcondition;
|
dds_rhc_remove_readcondition_t remove_readcondition;
|
||||||
dds_rhc_lock_samples_t lock_samples;
|
dds_rhc_lock_samples_t lock_samples;
|
||||||
|
@ -76,13 +76,16 @@ DDS_EXPORT inline void dds_rhc_set_qos (struct dds_rhc *rhc, const struct dds_qo
|
||||||
DDS_EXPORT inline void dds_rhc_free (struct dds_rhc *rhc) {
|
DDS_EXPORT inline void dds_rhc_free (struct dds_rhc *rhc) {
|
||||||
rhc->common.ops->rhc_ops.free (&rhc->common.rhc);
|
rhc->common.ops->rhc_ops.free (&rhc->common.rhc);
|
||||||
}
|
}
|
||||||
DDS_EXPORT inline int dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) {
|
DDS_EXPORT inline int32_t dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) {
|
||||||
return (rhc->common.ops->read) (rhc, lock, values, info_seq, max_samples, mask, handle, cond);
|
return (rhc->common.ops->read) (rhc, lock, values, info_seq, max_samples, mask, handle, cond);
|
||||||
}
|
}
|
||||||
DDS_EXPORT inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) {
|
DDS_EXPORT inline int32_t dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond) {
|
||||||
return rhc->common.ops->take (rhc, lock, values, info_seq, max_samples, mask, handle, cond);
|
return rhc->common.ops->take (rhc, lock, values, info_seq, max_samples, mask, handle, cond);
|
||||||
}
|
}
|
||||||
DDS_EXPORT inline int dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) {
|
DDS_EXPORT inline int32_t dds_rhc_readcdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) {
|
||||||
|
return rhc->common.ops->readcdr (rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle);
|
||||||
|
}
|
||||||
|
DDS_EXPORT inline int32_t dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle) {
|
||||||
return rhc->common.ops->takecdr (rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle);
|
return rhc->common.ops->takecdr (rhc, lock, values, info_seq, max_samples, sample_states, view_states, instance_states, handle);
|
||||||
}
|
}
|
||||||
DDS_EXPORT inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond) {
|
DDS_EXPORT inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
||||||
QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS)
|
QP_DESTINATION_ORDER | QP_HISTORY | QP_RESOURCE_LIMITS)
|
||||||
|
|
||||||
#define DDS_PARTICIPANT_QOS_MASK \
|
#define DDS_PARTICIPANT_QOS_MASK \
|
||||||
(QP_USER_DATA | QP_ADLINK_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL)
|
(QP_USER_DATA | QP_ADLINK_ENTITY_FACTORY | QP_CYCLONE_IGNORELOCAL | QP_PROPERTY_LIST)
|
||||||
|
|
||||||
#define DDS_PUBLISHER_QOS_MASK \
|
#define DDS_PUBLISHER_QOS_MASK \
|
||||||
(QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \
|
(QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \
|
||||||
|
@ -36,7 +36,7 @@ extern "C" {
|
||||||
QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | \
|
QP_OWNERSHIP | QP_LIVELINESS | QP_TIME_BASED_FILTER | \
|
||||||
QP_RELIABILITY | QP_DESTINATION_ORDER | QP_HISTORY | \
|
QP_RELIABILITY | QP_DESTINATION_ORDER | QP_HISTORY | \
|
||||||
QP_RESOURCE_LIMITS | QP_ADLINK_READER_DATA_LIFECYCLE | \
|
QP_RESOURCE_LIMITS | QP_ADLINK_READER_DATA_LIFECYCLE | \
|
||||||
QP_CYCLONE_IGNORELOCAL)
|
QP_CYCLONE_IGNORELOCAL | QP_PROPERTY_LIST)
|
||||||
|
|
||||||
#define DDS_SUBSCRIBER_QOS_MASK \
|
#define DDS_SUBSCRIBER_QOS_MASK \
|
||||||
(QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \
|
(QP_PARTITION | QP_PRESENTATION | QP_GROUP_DATA | \
|
||||||
|
@ -48,7 +48,7 @@ extern "C" {
|
||||||
QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | \
|
QP_LIVELINESS | QP_RELIABILITY | QP_TRANSPORT_PRIORITY | \
|
||||||
QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | \
|
QP_LIFESPAN | QP_DESTINATION_ORDER | QP_HISTORY | \
|
||||||
QP_RESOURCE_LIMITS | QP_ADLINK_WRITER_DATA_LIFECYCLE | \
|
QP_RESOURCE_LIMITS | QP_ADLINK_WRITER_DATA_LIFECYCLE | \
|
||||||
QP_CYCLONE_IGNORELOCAL)
|
QP_CYCLONE_IGNORELOCAL | QP_PROPERTY_LIST)
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ DDS_EXPORT void dds_topic_set_filter_with_ctx
|
||||||
DDS_EXPORT dds_topic_intern_filter_fn dds_topic_get_filter_with_ctx
|
DDS_EXPORT dds_topic_intern_filter_fn dds_topic_get_filter_with_ctx
|
||||||
(dds_entity_t topic);
|
(dds_entity_t topic);
|
||||||
|
|
||||||
|
DDS_EXPORT dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertopic **sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,7 +23,7 @@ DEFINE_ENTITY_LOCK_UNLOCK(inline, dds_writer, DDS_KIND_WRITER)
|
||||||
struct status_cb_data;
|
struct status_cb_data;
|
||||||
|
|
||||||
void dds_writer_status_cb (void *entity, const struct status_cb_data * data);
|
void dds_writer_status_cb (void *entity, const struct status_cb_data * data);
|
||||||
dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, dds_time_t abstimeout);
|
DDS_EXPORT dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, ddsi_guid_t *rdguid, dds_time_t abstimeout);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "dds/ddsi/q_entity.h"
|
#include "dds/ddsi/q_entity.h"
|
||||||
#include "dds/ddsi/q_thread.h"
|
#include "dds/ddsi/q_thread.h"
|
||||||
#include "dds/ddsi/q_config.h"
|
#include "dds/ddsi/q_config.h"
|
||||||
|
#include "dds/ddsi/q_bswap.h"
|
||||||
#include "dds/ddsi/ddsi_domaingv.h"
|
#include "dds/ddsi/ddsi_domaingv.h"
|
||||||
#include "dds/ddsi/ddsi_plist.h"
|
#include "dds/ddsi/ddsi_plist.h"
|
||||||
#include "dds__init.h"
|
#include "dds__init.h"
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
#include "dds__builtin.h"
|
#include "dds__builtin.h"
|
||||||
#include "dds__entity.h"
|
#include "dds__entity.h"
|
||||||
#include "dds__subscriber.h"
|
#include "dds__subscriber.h"
|
||||||
|
#include "dds__topic.h"
|
||||||
#include "dds__write.h"
|
#include "dds__write.h"
|
||||||
#include "dds__writer.h"
|
#include "dds__writer.h"
|
||||||
#include "dds__whc_builtintopic.h"
|
#include "dds__whc_builtintopic.h"
|
||||||
|
@ -76,7 +78,7 @@ dds_entity_t dds__get_builtin_topic (dds_entity_t entity, dds_entity_t topic)
|
||||||
}
|
}
|
||||||
|
|
||||||
dds_qos_t *qos = dds__create_builtin_qos ();
|
dds_qos_t *qos = dds__create_builtin_qos ();
|
||||||
if ((tp = dds_create_topic_generic (par->m_entity.m_hdllink.hdl, &sertopic, qos, NULL, NULL)) > 0)
|
if ((tp = dds_create_topic_impl (par->m_entity.m_hdllink.hdl, &sertopic, qos, NULL, NULL)) > 0)
|
||||||
{
|
{
|
||||||
/* keep ownership for built-in sertopics because there are re-used, lifetime for these
|
/* keep ownership for built-in sertopics because there are re-used, lifetime for these
|
||||||
sertopics is bound to domain */
|
sertopics is bound to domain */
|
||||||
|
@ -180,10 +182,13 @@ static struct ddsi_tkmap_instance *dds__builtin_get_tkmap_entry (const struct dd
|
||||||
struct dds_domain *domain = vdomain;
|
struct dds_domain *domain = vdomain;
|
||||||
struct ddsi_tkmap_instance *tk;
|
struct ddsi_tkmap_instance *tk;
|
||||||
struct ddsi_serdata *sd;
|
struct ddsi_serdata *sd;
|
||||||
struct nn_keyhash kh;
|
union { ddsi_guid_t guid; struct ddsi_keyhash keyhash; } x;
|
||||||
memcpy (&kh, guid, sizeof (kh));
|
x.guid = nn_hton_guid (*guid);
|
||||||
/* any random builtin topic will do (provided it has a GUID for a key), because what matters is the "class" of the topic, not the actual topic; also, this is called early in the initialisation of the entity with this GUID, which simply causes serdata_from_keyhash to create a key-only serdata because the key lookup fails. */
|
/* any random builtin topic will do (provided it has a GUID for a key), because what matters is the "class"
|
||||||
sd = ddsi_serdata_from_keyhash (domain->builtin_participant_topic, &kh);
|
of the topic, not the actual topic; also, this is called early in the initialisation of the entity with
|
||||||
|
this GUID, which simply causes serdata_from_keyhash to create a key-only serdata because the key lookup
|
||||||
|
fails. */
|
||||||
|
sd = ddsi_serdata_from_keyhash (domain->builtin_participant_topic, &x.keyhash);
|
||||||
tk = ddsi_tkmap_find (domain->gv.m_tkmap, sd, true);
|
tk = ddsi_tkmap_find (domain->gv.m_tkmap, sd, true);
|
||||||
ddsi_serdata_unref (sd);
|
ddsi_serdata_unref (sd);
|
||||||
return tk;
|
return tk;
|
||||||
|
@ -195,7 +200,7 @@ struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, dd
|
||||||
struct dds_domain *dom = e->gv->builtin_topic_interface->arg;
|
struct dds_domain *dom = e->gv->builtin_topic_interface->arg;
|
||||||
struct ddsi_sertopic *topic = NULL;
|
struct ddsi_sertopic *topic = NULL;
|
||||||
struct ddsi_serdata *serdata;
|
struct ddsi_serdata *serdata;
|
||||||
struct nn_keyhash keyhash;
|
union { ddsi_guid_t guid; struct ddsi_keyhash keyhash; } x;
|
||||||
switch (e->kind)
|
switch (e->kind)
|
||||||
{
|
{
|
||||||
case EK_PARTICIPANT:
|
case EK_PARTICIPANT:
|
||||||
|
@ -212,8 +217,8 @@ struct ddsi_serdata *dds__builtin_make_sample (const struct entity_common *e, dd
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert (topic != NULL);
|
assert (topic != NULL);
|
||||||
memcpy (&keyhash, &e->guid, sizeof (keyhash));
|
x.guid = nn_hton_guid (e->guid);
|
||||||
serdata = ddsi_serdata_from_keyhash (topic, &keyhash);
|
serdata = ddsi_serdata_from_keyhash (topic, &x.keyhash);
|
||||||
serdata->timestamp = timestamp;
|
serdata->timestamp = timestamp;
|
||||||
serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER;
|
serdata->statusinfo = alive ? 0 : NN_STATUSINFO_DISPOSE | NN_STATUSINFO_UNREGISTER;
|
||||||
return serdata;
|
return serdata;
|
||||||
|
|
|
@ -90,8 +90,7 @@ void dds_listener_copy(dds_listener_t * __restrict dst, const dds_listener_t * _
|
||||||
static bool dds_combine_listener_merge (uint32_t inherited, void (*dst)(void), void (*src)(void))
|
static bool dds_combine_listener_merge (uint32_t inherited, void (*dst)(void), void (*src)(void))
|
||||||
{
|
{
|
||||||
(void)inherited;
|
(void)inherited;
|
||||||
(void)src;
|
return dst == 0 && src != 0;
|
||||||
return dst == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dds_combine_listener_override_inherited (uint32_t inherited, void (*dst)(void), void (*src)(void))
|
static bool dds_combine_listener_override_inherited (uint32_t inherited, void (*dst)(void), void (*src)(void))
|
||||||
|
|
|
@ -144,8 +144,7 @@ static dds_builtintopic_endpoint_t *make_builtintopic_endpoint (const ddsi_guid_
|
||||||
dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t writer, dds_instance_handle_t ih)
|
dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t writer, dds_instance_handle_t ih)
|
||||||
{
|
{
|
||||||
dds_writer *wr;
|
dds_writer *wr;
|
||||||
dds_return_t rc;
|
if (dds_writer_lock (writer, &wr))
|
||||||
if ((rc = dds_writer_lock (writer, &wr)) != DDS_RETCODE_OK)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -187,8 +186,7 @@ dds_builtintopic_endpoint_t *dds_get_matched_subscription_data (dds_entity_t wri
|
||||||
dds_builtintopic_endpoint_t *dds_get_matched_publication_data (dds_entity_t reader, dds_instance_handle_t ih)
|
dds_builtintopic_endpoint_t *dds_get_matched_publication_data (dds_entity_t reader, dds_instance_handle_t ih)
|
||||||
{
|
{
|
||||||
dds_reader *rd;
|
dds_reader *rd;
|
||||||
dds_return_t rc;
|
if (dds_reader_lock (reader, &rd))
|
||||||
if ((rc = dds_reader_lock (reader, &rd)) != DDS_RETCODE_OK)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,7 +96,7 @@ dds_entity_t dds_create_participant (const dds_domainid_t domain, const dds_qos_
|
||||||
dds_participant * pp;
|
dds_participant * pp;
|
||||||
ddsi_plist_t plist;
|
ddsi_plist_t plist;
|
||||||
dds_qos_t *new_qos = NULL;
|
dds_qos_t *new_qos = NULL;
|
||||||
char *config = "";
|
const char *config = "";
|
||||||
|
|
||||||
/* Make sure DDS instance is initialized. */
|
/* Make sure DDS instance is initialized. */
|
||||||
if ((ret = dds_init ()) < 0)
|
if ((ret = dds_init ()) < 0)
|
||||||
|
|
|
@ -114,7 +114,7 @@ dds_return_t dds_wait_for_acks (dds_entity_t publisher_or_writer, dds_duration_t
|
||||||
return DDS_RETCODE_UNSUPPORTED;
|
return DDS_RETCODE_UNSUPPORTED;
|
||||||
|
|
||||||
case DDS_KIND_WRITER:
|
case DDS_KIND_WRITER:
|
||||||
ret = dds__writer_wait_for_acks ((struct dds_writer *) p_or_w_ent, abstimeout);
|
ret = dds__writer_wait_for_acks ((struct dds_writer *) p_or_w_ent, NULL, abstimeout);
|
||||||
dds_entity_unpin (p_or_w_ent);
|
dds_entity_unpin (p_or_w_ent);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -335,6 +335,112 @@ void dds_qset_ignorelocal (dds_qos_t * __restrict qos, dds_ignorelocal_kind_t ig
|
||||||
qos->present |= QP_CYCLONE_IGNORELOCAL;
|
qos->present |= QP_CYCLONE_IGNORELOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dds_qprop_init (dds_qos_t * qos)
|
||||||
|
{
|
||||||
|
if (!(qos->present & QP_PROPERTY_LIST))
|
||||||
|
{
|
||||||
|
qos->property.value.n = 0;
|
||||||
|
qos->property.value.props = NULL;
|
||||||
|
qos->property.binary_value.n = 0;
|
||||||
|
qos->property.binary_value.props = NULL;
|
||||||
|
qos->present |= QP_PROPERTY_LIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DDS_QPROP_GET_INDEX(prop_type_, prop_field_) \
|
||||||
|
static bool dds_q##prop_type_##_get_index (const dds_qos_t * qos, const char * name, uint32_t * index) \
|
||||||
|
{ \
|
||||||
|
if (qos == NULL || name == NULL || index == NULL || !(qos->present & QP_PROPERTY_LIST)) \
|
||||||
|
return false; \
|
||||||
|
for (uint32_t i = 0; i < qos->property.prop_field_.n; i++) \
|
||||||
|
{ \
|
||||||
|
if (strcmp (qos->property.prop_field_.props[i].name, name) == 0) \
|
||||||
|
{ \
|
||||||
|
*index = i; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
DDS_QPROP_GET_INDEX (prop, value)
|
||||||
|
DDS_QPROP_GET_INDEX (bprop, binary_value)
|
||||||
|
|
||||||
|
#define DDS_QUNSET_PROP(prop_type_, prop_field_, value_field_) \
|
||||||
|
void dds_qunset_##prop_type_ (dds_qos_t * __restrict qos, const char * name) \
|
||||||
|
{ \
|
||||||
|
uint32_t i; \
|
||||||
|
if (qos == NULL || !(qos->present & QP_PROPERTY_LIST) || qos->property.prop_field_.n == 0 || name == NULL) \
|
||||||
|
return; \
|
||||||
|
if (dds_q##prop_type_##_get_index (qos, name, &i)) \
|
||||||
|
{ \
|
||||||
|
dds_free (qos->property.prop_field_.props[i].name); \
|
||||||
|
dds_free (qos->property.prop_field_.props[i].value_field_); \
|
||||||
|
if (qos->property.prop_field_.n > 1) \
|
||||||
|
{ \
|
||||||
|
if (i < (qos->property.prop_field_.n - 1)) \
|
||||||
|
memmove (qos->property.prop_field_.props + i, qos->property.prop_field_.props + i + 1, \
|
||||||
|
(qos->property.prop_field_.n - i - 1) * sizeof (*qos->property.prop_field_.props)); \
|
||||||
|
qos->property.prop_field_.props = dds_realloc (qos->property.prop_field_.props, \
|
||||||
|
(qos->property.prop_field_.n - 1) * sizeof (*qos->property.prop_field_.props)); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
dds_free (qos->property.prop_field_.props); \
|
||||||
|
qos->property.prop_field_.props = NULL; \
|
||||||
|
} \
|
||||||
|
qos->property.prop_field_.n--; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
DDS_QUNSET_PROP (prop, value, value)
|
||||||
|
DDS_QUNSET_PROP (bprop, binary_value, value.value)
|
||||||
|
|
||||||
|
void dds_qset_prop (dds_qos_t * __restrict qos, const char * name, const char * value)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
if (qos == NULL || name == NULL || value == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dds_qprop_init (qos);
|
||||||
|
if (dds_qprop_get_index (qos, name, &i))
|
||||||
|
{
|
||||||
|
assert (&qos->property.value.props[i] != NULL); /* for Clang static analyzer */
|
||||||
|
dds_free (qos->property.value.props[i].value);
|
||||||
|
qos->property.value.props[i].value = dds_string_dup (value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qos->property.value.props = dds_realloc (qos->property.value.props,
|
||||||
|
(qos->property.value.n + 1) * sizeof (*qos->property.value.props));
|
||||||
|
qos->property.value.props[qos->property.value.n].propagate = 0;
|
||||||
|
qos->property.value.props[qos->property.value.n].name = dds_string_dup (name);
|
||||||
|
qos->property.value.props[qos->property.value.n].value = dds_string_dup (value);
|
||||||
|
qos->property.value.n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dds_qset_bprop (dds_qos_t * __restrict qos, const char * name, const void * value, const size_t sz)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
if (qos == NULL || name == NULL || (value == NULL && sz > 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dds_qprop_init (qos);
|
||||||
|
if (dds_qbprop_get_index (qos, name, &i))
|
||||||
|
{
|
||||||
|
assert (&qos->property.binary_value.props[i].value != NULL); /* for Clang static analyzer */
|
||||||
|
dds_qos_data_copy_in (&qos->property.binary_value.props[i].value, value, sz, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qos->property.binary_value.props = dds_realloc (qos->property.binary_value.props,
|
||||||
|
(qos->property.binary_value.n + 1) * sizeof (*qos->property.binary_value.props));
|
||||||
|
qos->property.binary_value.props[qos->property.binary_value.n].propagate = 0;
|
||||||
|
qos->property.binary_value.props[qos->property.binary_value.n].name = dds_string_dup (name);
|
||||||
|
dds_qos_data_copy_in (&qos->property.binary_value.props[qos->property.binary_value.n].value, value, sz, false);
|
||||||
|
qos->property.binary_value.n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz)
|
bool dds_qget_userdata (const dds_qos_t * __restrict qos, void **value, size_t *sz)
|
||||||
{
|
{
|
||||||
if (qos == NULL || !(qos->present & QP_USER_DATA))
|
if (qos == NULL || !(qos->present & QP_USER_DATA))
|
||||||
|
@ -565,3 +671,66 @@ bool dds_qget_ignorelocal (const dds_qos_t * __restrict qos, dds_ignorelocal_kin
|
||||||
*ignore = qos->ignorelocal.value;
|
*ignore = qos->ignorelocal.value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DDS_QGET_PROPNAMES(prop_type_, prop_field_) \
|
||||||
|
bool dds_qget_##prop_type_##names (const dds_qos_t * __restrict qos, uint32_t * n, char *** names) \
|
||||||
|
{ \
|
||||||
|
bool props; \
|
||||||
|
if (qos == NULL || (n == NULL && names == NULL)) \
|
||||||
|
return false; \
|
||||||
|
props = (qos->present & QP_PROPERTY_LIST) && qos->property.prop_field_.n > 0; \
|
||||||
|
if (n != NULL) \
|
||||||
|
*n = props ? qos->property.prop_field_.n : 0; \
|
||||||
|
if (names != NULL) \
|
||||||
|
{ \
|
||||||
|
if (!props) \
|
||||||
|
*names = NULL; \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
*names = dds_alloc (sizeof (char *) * qos->property.prop_field_.n); \
|
||||||
|
for (uint32_t i = 0; i < qos->property.prop_field_.n; i++) \
|
||||||
|
(*names)[i] = dds_string_dup (qos->property.prop_field_.props[i].name); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return props; \
|
||||||
|
}
|
||||||
|
DDS_QGET_PROPNAMES (prop, value)
|
||||||
|
DDS_QGET_PROPNAMES (bprop, binary_value)
|
||||||
|
|
||||||
|
bool dds_qget_prop (const dds_qos_t * __restrict qos, const char * name, char ** value)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
bool found;
|
||||||
|
|
||||||
|
if (qos == NULL || name == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
found = dds_qprop_get_index (qos, name, &i);
|
||||||
|
if (value != NULL)
|
||||||
|
*value = found ? dds_string_dup (qos->property.value.props[i].value) : NULL;
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dds_qget_bprop (const dds_qos_t * __restrict qos, const char * name, void ** value, size_t * sz)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
bool found;
|
||||||
|
|
||||||
|
if (qos == NULL || name == NULL || (sz == NULL && value != NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
found = dds_qbprop_get_index (qos, name, &i);
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
if (value != NULL || sz != NULL)
|
||||||
|
dds_qos_data_copy_out (&qos->property.binary_value.props[i].value, value, sz);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value != NULL)
|
||||||
|
*value = NULL;
|
||||||
|
if (sz != NULL)
|
||||||
|
*sz = 0;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition,
|
||||||
#define NC_FREE_BUF 2u
|
#define NC_FREE_BUF 2u
|
||||||
#define NC_RESET_BUF 4u
|
#define NC_RESET_BUF 4u
|
||||||
|
|
||||||
if (buf == NULL || si == NULL || maxs == 0 || bufsz == 0 || bufsz < maxs)
|
if (buf == NULL || si == NULL || maxs == 0 || bufsz == 0 || bufsz < maxs || maxs > INT32_MAX)
|
||||||
return DDS_RETCODE_BAD_PARAMETER;
|
return DDS_RETCODE_BAD_PARAMETER;
|
||||||
|
|
||||||
if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) {
|
if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) {
|
||||||
|
@ -61,14 +61,6 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition,
|
||||||
|
|
||||||
thread_state_awake (ts1, &entity->m_domain->gv);
|
thread_state_awake (ts1, &entity->m_domain->gv);
|
||||||
|
|
||||||
if (hand != DDS_HANDLE_NIL)
|
|
||||||
{
|
|
||||||
if (ddsi_tkmap_find_by_id (entity->m_domain->gv.m_tkmap, hand) == NULL) {
|
|
||||||
ret = DDS_RETCODE_PRECONDITION_NOT_MET;
|
|
||||||
goto fail_awake_pinned;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate samples if not provided (assuming all or none provided) */
|
/* Allocate samples if not provided (assuming all or none provided) */
|
||||||
if (buf[0] == NULL)
|
if (buf[0] == NULL)
|
||||||
{
|
{
|
||||||
|
@ -142,8 +134,6 @@ static dds_return_t dds_read_impl (bool take, dds_entity_t reader_or_condition,
|
||||||
#undef NC_FREE_BUF
|
#undef NC_FREE_BUF
|
||||||
#undef NC_RESET_BUF
|
#undef NC_RESET_BUF
|
||||||
|
|
||||||
fail_awake_pinned:
|
|
||||||
thread_state_asleep (ts1);
|
|
||||||
fail_pinned:
|
fail_pinned:
|
||||||
dds_entity_unpin (entity);
|
dds_entity_unpin (entity);
|
||||||
fail:
|
fail:
|
||||||
|
@ -157,12 +147,8 @@ static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_conditio
|
||||||
struct dds_reader *rd;
|
struct dds_reader *rd;
|
||||||
struct dds_entity *entity;
|
struct dds_entity *entity;
|
||||||
|
|
||||||
assert (take);
|
if (buf == NULL || si == NULL || maxs == 0 || maxs > INT32_MAX)
|
||||||
assert (buf);
|
return DDS_RETCODE_BAD_PARAMETER;
|
||||||
assert (si);
|
|
||||||
assert (hand == DDS_HANDLE_NIL);
|
|
||||||
assert (maxs > 0);
|
|
||||||
(void)take;
|
|
||||||
|
|
||||||
if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) {
|
if ((ret = dds_entity_pin (reader_or_condition, &entity)) < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -185,7 +171,11 @@ static dds_return_t dds_readcdr_impl (bool take, dds_entity_t reader_or_conditio
|
||||||
assert (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER);
|
assert (dds_entity_kind (rd->m_entity.m_parent) == DDS_KIND_SUBSCRIBER);
|
||||||
dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS);
|
dds_entity_status_reset (rd->m_entity.m_parent, DDS_DATA_ON_READERS_STATUS);
|
||||||
|
|
||||||
|
if (take)
|
||||||
ret = dds_rhc_takecdr (rd->m_rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand);
|
ret = dds_rhc_takecdr (rd->m_rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand);
|
||||||
|
else
|
||||||
|
ret = dds_rhc_readcdr (rd->m_rhc, lock, buf, si, maxs, mask & DDS_ANY_SAMPLE_STATE, mask & DDS_ANY_VIEW_STATE, mask & DDS_ANY_INSTANCE_STATE, hand);
|
||||||
|
|
||||||
dds_entity_unpin (entity);
|
dds_entity_unpin (entity);
|
||||||
thread_state_asleep (ts1);
|
thread_state_asleep (ts1);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -239,6 +229,18 @@ dds_return_t dds_read_mask_wl (dds_entity_t rd_or_cnd, void **buf, dds_sample_in
|
||||||
return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false);
|
return dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dds_return_t dds_readcdr (dds_entity_t rd_or_cnd, struct ddsi_serdata **buf, uint32_t maxs, dds_sample_info_t *si, uint32_t mask)
|
||||||
|
{
|
||||||
|
bool lock = true;
|
||||||
|
if (maxs == DDS_READ_WITHOUT_LOCK)
|
||||||
|
{
|
||||||
|
lock = false;
|
||||||
|
/* FIXME: Fix the interface. */
|
||||||
|
maxs = 100;
|
||||||
|
}
|
||||||
|
return dds_readcdr_impl (false, rd_or_cnd, buf, maxs, si, mask, DDS_HANDLE_NIL, lock);
|
||||||
|
}
|
||||||
|
|
||||||
dds_return_t dds_read_instance (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, dds_instance_handle_t handle)
|
dds_return_t dds_read_instance (dds_entity_t rd_or_cnd, void **buf, dds_sample_info_t *si, size_t bufsz, uint32_t maxs, dds_instance_handle_t handle)
|
||||||
{
|
{
|
||||||
bool lock = true;
|
bool lock = true;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "dds__builtin.h"
|
#include "dds__builtin.h"
|
||||||
#include "dds/ddsi/ddsi_sertopic.h"
|
#include "dds/ddsi/ddsi_sertopic.h"
|
||||||
#include "dds/ddsi/ddsi_entity_index.h"
|
#include "dds/ddsi/ddsi_entity_index.h"
|
||||||
|
#include "dds/ddsi/ddsi_security_omg.h"
|
||||||
|
|
||||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader)
|
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_reader)
|
||||||
|
|
||||||
|
@ -430,6 +431,7 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
|
||||||
|
|
||||||
/* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null
|
/* Merge qos from topic and subscriber, dds_copy_qos only fails when it is passed a null
|
||||||
argument, but that isn't the case here */
|
argument, but that isn't the case here */
|
||||||
|
struct ddsi_domaingv *gv = &sub->m_entity.m_domain->gv;
|
||||||
rqos = dds_create_qos ();
|
rqos = dds_create_qos ();
|
||||||
if (qos)
|
if (qos)
|
||||||
ddsi_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK);
|
ddsi_xqos_mergein_missing (rqos, qos, DDS_READER_QOS_MASK);
|
||||||
|
@ -437,25 +439,42 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
|
||||||
ddsi_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0);
|
ddsi_xqos_mergein_missing (rqos, sub->m_entity.m_qos, ~(uint64_t)0);
|
||||||
if (tp->m_ktopic->qos)
|
if (tp->m_ktopic->qos)
|
||||||
ddsi_xqos_mergein_missing (rqos, tp->m_ktopic->qos, ~(uint64_t)0);
|
ddsi_xqos_mergein_missing (rqos, tp->m_ktopic->qos, ~(uint64_t)0);
|
||||||
ddsi_xqos_mergein_missing (rqos, &sub->m_entity.m_domain->gv.default_xqos_rd, ~(uint64_t)0);
|
ddsi_xqos_mergein_missing (rqos, &gv->default_xqos_rd, ~(uint64_t)0);
|
||||||
|
|
||||||
if ((rc = ddsi_xqos_valid (&sub->m_entity.m_domain->gv.logconfig, rqos)) < 0 ||
|
if ((rc = ddsi_xqos_valid (&gv->logconfig, rqos)) < 0 || (rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK)
|
||||||
(rc = validate_reader_qos(rqos)) != DDS_RETCODE_OK)
|
|
||||||
{
|
|
||||||
dds_delete_qos (rqos);
|
|
||||||
goto err_bad_qos;
|
goto err_bad_qos;
|
||||||
}
|
|
||||||
|
|
||||||
/* Additional checks required for built-in topics: we don't want to
|
/* Additional checks required for built-in topics: we don't want to
|
||||||
run into a resource limit on a built-in topic, it is a needless
|
run into a resource limit on a built-in topic, it is a needless
|
||||||
complication */
|
complication */
|
||||||
if (pseudo_topic && !dds__validate_builtin_reader_qos (tp->m_entity.m_domain, pseudo_topic, rqos))
|
if (pseudo_topic && !dds__validate_builtin_reader_qos (tp->m_entity.m_domain, pseudo_topic, rqos))
|
||||||
{
|
{
|
||||||
dds_delete_qos (rqos);
|
|
||||||
rc = DDS_RETCODE_INCONSISTENT_POLICY;
|
rc = DDS_RETCODE_INCONSISTENT_POLICY;
|
||||||
goto err_bad_qos;
|
goto err_bad_qos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread_state_awake (lookup_thread_state (), gv);
|
||||||
|
const struct ddsi_guid * ppguid = dds_entity_participant_guid (&sub->m_entity);
|
||||||
|
struct participant * pp = entidx_lookup_participant_guid (gv->entity_index, ppguid);
|
||||||
|
|
||||||
|
/* When deleting a participant, the child handles (that include the subscriber)
|
||||||
|
are removed before removing the DDSI participant. So at this point, within
|
||||||
|
the subscriber lock, we can assert that the participant exists. */
|
||||||
|
assert (pp != NULL);
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
/* Check if DDS Security is enabled */
|
||||||
|
if (q_omg_participant_is_secure (pp))
|
||||||
|
{
|
||||||
|
/* ask to access control security plugin for create reader permissions */
|
||||||
|
if (!q_omg_security_check_create_reader (pp, gv->config.domainId, tp->m_stopic->name, rqos))
|
||||||
|
{
|
||||||
|
rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
|
||||||
|
goto err_not_allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create reader and associated read cache (if not provided by caller) */
|
/* Create reader and associated read cache (if not provided by caller) */
|
||||||
struct dds_reader * const rd = dds_alloc (sizeof (*rd));
|
struct dds_reader * const rd = dds_alloc (sizeof (*rd));
|
||||||
const dds_entity_t reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, false, rqos, listener, DDS_READER_STATUS_MASK);
|
const dds_entity_t reader = dds_entity_init (&rd->m_entity, &sub->m_entity, DDS_KIND_READER, false, rqos, listener, DDS_READER_STATUS_MASK);
|
||||||
|
@ -474,8 +493,7 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
|
||||||
it; and then invoke those listeners that are in the pending set */
|
it; and then invoke those listeners that are in the pending set */
|
||||||
dds_entity_init_complete (&rd->m_entity);
|
dds_entity_init_complete (&rd->m_entity);
|
||||||
|
|
||||||
thread_state_awake (lookup_thread_state (), &sub->m_entity.m_domain->gv);
|
rc = new_reader (&rd->m_rd, &rd->m_entity.m_guid, NULL, pp, tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd);
|
||||||
rc = new_reader (&rd->m_rd, &rd->m_entity.m_domain->gv, &rd->m_entity.m_guid, NULL, dds_entity_participant_guid (&sub->m_entity), tp->m_stopic, rqos, &rd->m_rhc->common.rhc, dds_reader_status_cb, rd);
|
|
||||||
assert (rc == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */
|
assert (rc == DDS_RETCODE_OK); /* FIXME: can be out-of-resources at the very least */
|
||||||
thread_state_asleep (lookup_thread_state ());
|
thread_state_asleep (lookup_thread_state ());
|
||||||
|
|
||||||
|
@ -487,7 +505,12 @@ static dds_entity_t dds_create_reader_int (dds_entity_t participant_or_subscribe
|
||||||
dds_subscriber_unlock (sub);
|
dds_subscriber_unlock (sub);
|
||||||
return reader;
|
return reader;
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
err_not_allowed:
|
||||||
|
thread_state_asleep (lookup_thread_state ());
|
||||||
|
#endif
|
||||||
err_bad_qos:
|
err_bad_qos:
|
||||||
|
dds_delete_qos (rqos);
|
||||||
dds_topic_allow_set_qos (tp);
|
dds_topic_allow_set_qos (tp);
|
||||||
err_pp_mismatch:
|
err_pp_mismatch:
|
||||||
dds_topic_unpin (tp);
|
dds_topic_unpin (tp);
|
||||||
|
@ -632,3 +655,4 @@ DDS_GET_STATUS (reader, sample_rejected, SAMPLE_REJECTED,
|
||||||
DDS_GET_STATUS (reader, sample_lost, SAMPLE_LOST, total_count_change)
|
DDS_GET_STATUS (reader, sample_lost, SAMPLE_LOST, total_count_change)
|
||||||
DDS_GET_STATUS (reader, requested_deadline_missed, REQUESTED_DEADLINE_MISSED, total_count_change)
|
DDS_GET_STATUS (reader, requested_deadline_missed, REQUESTED_DEADLINE_MISSED, total_count_change)
|
||||||
DDS_GET_STATUS (reader, requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, total_count_change)
|
DDS_GET_STATUS (reader, requested_incompatible_qos, REQUESTED_INCOMPATIBLE_QOS, total_count_change)
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern inline void dds_rhc_set_qos (struct dds_rhc *rhc, const struct dds_qos *q
|
||||||
extern inline void dds_rhc_free (struct dds_rhc *rhc);
|
extern inline void dds_rhc_free (struct dds_rhc *rhc);
|
||||||
extern inline int dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
extern inline int dds_rhc_read (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
||||||
extern inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
extern inline int dds_rhc_take (struct dds_rhc *rhc, bool lock, void **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t mask, dds_instance_handle_t handle, struct dds_readcond *cond);
|
||||||
|
extern inline int dds_rhc_readcdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
||||||
extern inline int dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
extern inline int dds_rhc_takecdr (struct dds_rhc *rhc, bool lock, struct ddsi_serdata **values, dds_sample_info_t *info_seq, uint32_t max_samples, uint32_t sample_states, uint32_t view_states, uint32_t instance_states, dds_instance_handle_t handle);
|
||||||
extern inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond);
|
extern inline bool dds_rhc_add_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||||
extern inline void dds_rhc_remove_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond);
|
extern inline void dds_rhc_remove_readcondition (struct dds_rhc *rhc, struct dds_readcond *cond);
|
||||||
|
|
|
@ -126,14 +126,16 @@ static void from_entity_pwr (struct ddsi_serdata_builtintopic *d, const struct p
|
||||||
assert (d->xqos.present & QP_TYPE_NAME);
|
assert (d->xqos.present & QP_TYPE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi_sertopic *tpcmn, const nn_keyhash_t *keyhash)
|
static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash)
|
||||||
{
|
{
|
||||||
/* FIXME: not quite elegant to manage the creation of a serdata for a built-in topic via this function, but I also find it quite unelegant to let from_sample read straight from the underlying internal entity, and to_sample convert to the external format ... I could claim the internal entity is the "serialised form", but that forces wrapping it in a fragchain in one way or another, which, though possible, is also a bit lacking in elegance. */
|
/* FIXME: not quite elegant to manage the creation of a serdata for a built-in topic via this function, but I also find it quite unelegant to let from_sample read straight from the underlying internal entity, and to_sample convert to the external format ... I could claim the internal entity is the "serialised form", but that forces wrapping it in a fragchain in one way or another, which, though possible, is also a bit lacking in elegance. */
|
||||||
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn;
|
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn;
|
||||||
/* keyhash must in host format (which the GUIDs always are internally) */
|
union { ddsi_guid_t guid; ddsi_keyhash_t keyhash; } x;
|
||||||
struct entity_common *entity = entidx_lookup_guid_untyped (tp->c.gv->entity_index, (const ddsi_guid_t *) keyhash->value);
|
x.keyhash = *keyhash;
|
||||||
|
x.guid = nn_ntoh_guid (x.guid);
|
||||||
|
struct entity_common *entity = entidx_lookup_guid_untyped (tp->c.gv->entity_index, &x.guid);
|
||||||
struct ddsi_serdata_builtintopic *d = serdata_builtin_new (tp, entity ? SDK_DATA : SDK_KEY);
|
struct ddsi_serdata_builtintopic *d = serdata_builtin_new (tp, entity ? SDK_DATA : SDK_KEY);
|
||||||
memcpy (&d->key, keyhash->value, sizeof (d->key));
|
d->key = x.guid;
|
||||||
if (entity)
|
if (entity)
|
||||||
{
|
{
|
||||||
ddsrt_mutex_lock (&entity->qos_lock);
|
ddsrt_mutex_lock (&entity->qos_lock);
|
||||||
|
@ -169,6 +171,41 @@ static struct ddsi_serdata *ddsi_serdata_builtin_from_keyhash (const struct ddsi
|
||||||
return fix_serdata_builtin(d, tp->c.serdata_basehash);
|
return fix_serdata_builtin(d, tp->c.serdata_basehash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ddsi_serdata *ddsi_serdata_builtin_from_sample (const struct ddsi_sertopic *tpcmn, enum ddsi_serdata_kind kind, const void *sample)
|
||||||
|
{
|
||||||
|
const struct ddsi_sertopic_builtintopic *tp = (const struct ddsi_sertopic_builtintopic *)tpcmn;
|
||||||
|
union {
|
||||||
|
dds_guid_t extguid;
|
||||||
|
ddsi_keyhash_t keyhash;
|
||||||
|
} x;
|
||||||
|
|
||||||
|
/* no-one should be trying to convert user-provided data into a built-in topic sample, but converting
|
||||||
|
a key is something that can be necessary, e.g., dds_lookup_instance depends on it */
|
||||||
|
if (kind != SDK_KEY)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* memset x (even though it is entirely superfluous) so we can leave out a default case from the
|
||||||
|
switch (ensuring at least some compilers will warn when more types are added) without getting
|
||||||
|
warnings from any compiler */
|
||||||
|
memset (&x, 0, sizeof (x));
|
||||||
|
switch (tp->type)
|
||||||
|
{
|
||||||
|
case DSBT_PARTICIPANT: {
|
||||||
|
const dds_builtintopic_participant_t *s = sample;
|
||||||
|
x.extguid = s->key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DSBT_READER:
|
||||||
|
case DSBT_WRITER: {
|
||||||
|
const dds_builtintopic_endpoint_t *s = sample;
|
||||||
|
x.extguid = s->key;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ddsi_serdata_from_keyhash (tpcmn, &x.keyhash);
|
||||||
|
}
|
||||||
|
|
||||||
static struct ddsi_serdata *serdata_builtin_to_topicless (const struct ddsi_serdata *serdata_common)
|
static struct ddsi_serdata *serdata_builtin_to_topicless (const struct ddsi_serdata *serdata_common)
|
||||||
{
|
{
|
||||||
/* All built-in ones are currently topicless */
|
/* All built-in ones are currently topicless */
|
||||||
|
@ -289,12 +326,13 @@ const struct ddsi_serdata_ops ddsi_serdata_ops_builtintopic = {
|
||||||
.from_ser = 0,
|
.from_ser = 0,
|
||||||
.from_ser_iov = 0,
|
.from_ser_iov = 0,
|
||||||
.from_keyhash = ddsi_serdata_builtin_from_keyhash,
|
.from_keyhash = ddsi_serdata_builtin_from_keyhash,
|
||||||
.from_sample = 0,
|
.from_sample = ddsi_serdata_builtin_from_sample,
|
||||||
.to_ser = serdata_builtin_to_ser,
|
.to_ser = serdata_builtin_to_ser,
|
||||||
.to_sample = serdata_builtin_to_sample,
|
.to_sample = serdata_builtin_to_sample,
|
||||||
.to_ser_ref = serdata_builtin_to_ser_ref,
|
.to_ser_ref = serdata_builtin_to_ser_ref,
|
||||||
.to_ser_unref = serdata_builtin_to_ser_unref,
|
.to_ser_unref = serdata_builtin_to_ser_unref,
|
||||||
.to_topicless = serdata_builtin_to_topicless,
|
.to_topicless = serdata_builtin_to_topicless,
|
||||||
.topicless_to_sample = serdata_builtin_topicless_to_sample,
|
.topicless_to_sample = serdata_builtin_topicless_to_sample,
|
||||||
.print = serdata_builtin_topic_print
|
.print = serdata_builtin_topic_print,
|
||||||
|
.get_keyhash = 0
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "dds/ddsi/ddsi_plist.h"
|
#include "dds/ddsi/ddsi_plist.h"
|
||||||
#include "dds/ddsi/ddsi_domaingv.h"
|
#include "dds/ddsi/ddsi_domaingv.h"
|
||||||
#include "dds/ddsi/ddsi_cdrstream.h"
|
#include "dds/ddsi/ddsi_cdrstream.h"
|
||||||
|
#include "dds/ddsi/ddsi_security_omg.h"
|
||||||
#include "dds__serdata_builtintopic.h"
|
#include "dds__serdata_builtintopic.h"
|
||||||
|
|
||||||
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic)
|
DECL_ENTITY_LOCK_UNLOCK (extern inline, dds_topic)
|
||||||
|
@ -246,6 +247,7 @@ static dds_return_t lookup_and_check_ktopic (struct dds_ktopic **ktp_out, dds_pa
|
||||||
|
|
||||||
static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct dds_ktopic *ktp, bool implicit, struct ddsi_sertopic *sertopic_registered, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist)
|
static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct dds_ktopic *ktp, bool implicit, struct ddsi_sertopic *sertopic_registered, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist)
|
||||||
{
|
{
|
||||||
|
(void) sedp_plist;
|
||||||
dds_entity_t hdl;
|
dds_entity_t hdl;
|
||||||
dds_topic *tp = dds_alloc (sizeof (*tp));
|
dds_topic *tp = dds_alloc (sizeof (*tp));
|
||||||
hdl = dds_entity_init (&tp->m_entity, &pp->m_entity, DDS_KIND_TOPIC, implicit, NULL, listener, DDS_TOPIC_STATUS_MASK);
|
hdl = dds_entity_init (&tp->m_entity, &pp->m_entity, DDS_KIND_TOPIC, implicit, NULL, listener, DDS_TOPIC_STATUS_MASK);
|
||||||
|
@ -253,30 +255,11 @@ static dds_entity_t create_topic_pp_locked (struct dds_participant *pp, struct d
|
||||||
dds_entity_register_child (&pp->m_entity, &tp->m_entity);
|
dds_entity_register_child (&pp->m_entity, &tp->m_entity);
|
||||||
tp->m_ktopic = ktp;
|
tp->m_ktopic = ktp;
|
||||||
tp->m_stopic = sertopic_registered;
|
tp->m_stopic = sertopic_registered;
|
||||||
|
|
||||||
/* Publish Topic */
|
|
||||||
if (sedp_plist)
|
|
||||||
{
|
|
||||||
struct participant *ddsi_pp;
|
|
||||||
ddsi_plist_t plist;
|
|
||||||
|
|
||||||
thread_state_awake (lookup_thread_state (), &pp->m_entity.m_domain->gv);
|
|
||||||
ddsi_pp = entidx_lookup_participant_guid (pp->m_entity.m_domain->gv.entity_index, &pp->m_entity.m_guid);
|
|
||||||
assert (ddsi_pp);
|
|
||||||
|
|
||||||
ddsi_plist_init_empty (&plist);
|
|
||||||
ddsi_plist_mergein_missing (&plist, sedp_plist, ~(uint64_t)0, ~(uint64_t)0);
|
|
||||||
ddsi_xqos_mergein_missing (&plist.qos, ktp->qos, ~(uint64_t)0);
|
|
||||||
sedp_write_topic (ddsi_pp, &plist);
|
|
||||||
ddsi_plist_fini (&plist);
|
|
||||||
thread_state_asleep (lookup_thread_state ());
|
|
||||||
}
|
|
||||||
|
|
||||||
dds_entity_init_complete (&tp->m_entity);
|
dds_entity_init_complete (&tp->m_entity);
|
||||||
return hdl;
|
return hdl;
|
||||||
}
|
}
|
||||||
|
|
||||||
dds_entity_t dds_create_topic_generic (dds_entity_t participant, struct ddsi_sertopic **sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist)
|
dds_entity_t dds_create_topic_impl (dds_entity_t participant, struct ddsi_sertopic **sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist)
|
||||||
{
|
{
|
||||||
dds_return_t rc;
|
dds_return_t rc;
|
||||||
dds_participant *pp;
|
dds_participant *pp;
|
||||||
|
@ -315,10 +298,12 @@ dds_entity_t dds_create_topic_generic (dds_entity_t participant, struct ddsi_ser
|
||||||
* reliable ... (and keep behaviour unchanged) */
|
* reliable ... (and keep behaviour unchanged) */
|
||||||
struct ddsi_domaingv * const gv = &pp->m_entity.m_domain->gv;
|
struct ddsi_domaingv * const gv = &pp->m_entity.m_domain->gv;
|
||||||
if ((rc = ddsi_xqos_valid (&gv->logconfig, new_qos)) != DDS_RETCODE_OK)
|
if ((rc = ddsi_xqos_valid (&gv->logconfig, new_qos)) != DDS_RETCODE_OK)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!q_omg_security_check_create_topic (&pp->m_entity.m_domain->gv, &pp->m_entity.m_guid, (*sertopic)->name, new_qos))
|
||||||
{
|
{
|
||||||
dds_delete_qos (new_qos);
|
rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
|
||||||
dds_entity_unpin (&pp->m_entity);
|
goto error;
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if we're allowed to create the topic; ktp is returned pinned & locked
|
/* See if we're allowed to create the topic; ktp is returned pinned & locked
|
||||||
|
@ -331,9 +316,8 @@ dds_entity_t dds_create_topic_generic (dds_entity_t participant, struct ddsi_ser
|
||||||
if ((rc = lookup_and_check_ktopic (&ktp, pp, (*sertopic)->name, (*sertopic)->type_name, new_qos)) != DDS_RETCODE_OK)
|
if ((rc = lookup_and_check_ktopic (&ktp, pp, (*sertopic)->name, (*sertopic)->type_name, new_qos)) != DDS_RETCODE_OK)
|
||||||
{
|
{
|
||||||
GVTRACE ("dds_create_topic_generic: failed after compatibility check: %s\n", dds_strretcode (rc));
|
GVTRACE ("dds_create_topic_generic: failed after compatibility check: %s\n", dds_strretcode (rc));
|
||||||
dds_participant_unlock (pp);
|
ddsrt_mutex_unlock (&pp->m_entity.m_mutex);
|
||||||
dds_delete_qos (new_qos);
|
goto error;
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a ktopic if it doesn't exist yet, else reference existing one and delete the
|
/* Create a ktopic if it doesn't exist yet, else reference existing one and delete the
|
||||||
|
@ -375,13 +359,31 @@ dds_entity_t dds_create_topic_generic (dds_entity_t participant, struct ddsi_ser
|
||||||
hdl = create_topic_pp_locked (pp, ktp, (sertopic_registered->ops == &ddsi_sertopic_ops_builtintopic), sertopic_registered, listener, sedp_plist);
|
hdl = create_topic_pp_locked (pp, ktp, (sertopic_registered->ops == &ddsi_sertopic_ops_builtintopic), sertopic_registered, listener, sedp_plist);
|
||||||
ddsi_sertopic_unref (*sertopic);
|
ddsi_sertopic_unref (*sertopic);
|
||||||
*sertopic = sertopic_registered;
|
*sertopic = sertopic_registered;
|
||||||
dds_participant_unlock (pp);
|
ddsrt_mutex_unlock (&pp->m_entity.m_mutex);
|
||||||
|
dds_entity_unpin (&pp->m_entity);
|
||||||
GVTRACE ("dds_create_topic_generic: new topic %"PRId32"\n", hdl);
|
GVTRACE ("dds_create_topic_generic: new topic %"PRId32"\n", hdl);
|
||||||
return hdl;
|
return hdl;
|
||||||
|
|
||||||
|
error:
|
||||||
|
dds_entity_unpin (&pp->m_entity);
|
||||||
|
dds_delete_qos (new_qos);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
dds_entity_t dds_create_topic_generic (dds_entity_t participant, struct ddsi_sertopic **sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist)
|
||||||
|
{
|
||||||
|
if (sertopic == NULL || *sertopic == NULL || (*sertopic)->name == NULL)
|
||||||
|
return DDS_RETCODE_BAD_PARAMETER;
|
||||||
|
if (!strncmp((*sertopic)->name, "DCPS", 4))
|
||||||
|
return DDS_RETCODE_BAD_PARAMETER;
|
||||||
|
return dds_create_topic_impl (participant, sertopic, qos, listener, sedp_plist);
|
||||||
}
|
}
|
||||||
|
|
||||||
dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist)
|
dds_entity_t dds_create_topic_arbitrary (dds_entity_t participant, struct ddsi_sertopic *sertopic, const dds_qos_t *qos, const dds_listener_t *listener, const ddsi_plist_t *sedp_plist)
|
||||||
{
|
{
|
||||||
|
if (sertopic == NULL)
|
||||||
|
return DDS_RETCODE_BAD_PARAMETER;
|
||||||
|
|
||||||
dds_entity_t ret;
|
dds_entity_t ret;
|
||||||
struct ddsi_sertopic *st = sertopic;
|
struct ddsi_sertopic *st = sertopic;
|
||||||
ddsi_sertopic_ref (st);
|
ddsi_sertopic_ref (st);
|
||||||
|
|
|
@ -267,8 +267,7 @@ void dds_write_flush (dds_entity_t writer)
|
||||||
{
|
{
|
||||||
struct thread_state1 * const ts1 = lookup_thread_state ();
|
struct thread_state1 * const ts1 = lookup_thread_state ();
|
||||||
dds_writer *wr;
|
dds_writer *wr;
|
||||||
dds_return_t rc;
|
if (dds_writer_lock (writer, &wr) == DDS_RETCODE_OK)
|
||||||
if ((rc = dds_writer_lock (writer, &wr)) == DDS_RETCODE_OK)
|
|
||||||
{
|
{
|
||||||
thread_state_awake (ts1, &wr->m_entity.m_domain->gv);
|
thread_state_awake (ts1, &wr->m_entity.m_domain->gv);
|
||||||
nn_xpack_send (wr->m_xp, true);
|
nn_xpack_send (wr->m_xp, true);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "dds/ddsi/q_thread.h"
|
#include "dds/ddsi/q_thread.h"
|
||||||
#include "dds/ddsi/q_xmsg.h"
|
#include "dds/ddsi/q_xmsg.h"
|
||||||
#include "dds/ddsi/ddsi_entity_index.h"
|
#include "dds/ddsi/ddsi_entity_index.h"
|
||||||
|
#include "dds/ddsi/ddsi_security_omg.h"
|
||||||
#include "dds__writer.h"
|
#include "dds__writer.h"
|
||||||
#include "dds__listener.h"
|
#include "dds__listener.h"
|
||||||
#include "dds__init.h"
|
#include "dds__init.h"
|
||||||
|
@ -312,6 +313,7 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
||||||
dds_topic_defer_set_qos (tp);
|
dds_topic_defer_set_qos (tp);
|
||||||
|
|
||||||
/* Merge Topic & Publisher qos */
|
/* Merge Topic & Publisher qos */
|
||||||
|
struct ddsi_domaingv *gv = &pub->m_entity.m_domain->gv;
|
||||||
wqos = dds_create_qos ();
|
wqos = dds_create_qos ();
|
||||||
if (qos)
|
if (qos)
|
||||||
ddsi_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK);
|
ddsi_xqos_mergein_missing (wqos, qos, DDS_WRITER_QOS_MASK);
|
||||||
|
@ -319,29 +321,45 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
||||||
ddsi_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0);
|
ddsi_xqos_mergein_missing (wqos, pub->m_entity.m_qos, ~(uint64_t)0);
|
||||||
if (tp->m_ktopic->qos)
|
if (tp->m_ktopic->qos)
|
||||||
ddsi_xqos_mergein_missing (wqos, tp->m_ktopic->qos, ~(uint64_t)0);
|
ddsi_xqos_mergein_missing (wqos, tp->m_ktopic->qos, ~(uint64_t)0);
|
||||||
ddsi_xqos_mergein_missing (wqos, &pub->m_entity.m_domain->gv.default_xqos_wr, ~(uint64_t)0);
|
ddsi_xqos_mergein_missing (wqos, &gv->default_xqos_wr, ~(uint64_t)0);
|
||||||
|
|
||||||
if ((rc = ddsi_xqos_valid (&pub->m_entity.m_domain->gv.logconfig, wqos)) < 0 ||
|
if ((rc = ddsi_xqos_valid (&gv->logconfig, wqos)) < 0 || (rc = validate_writer_qos(wqos)) != DDS_RETCODE_OK)
|
||||||
(rc = validate_writer_qos(wqos)) != DDS_RETCODE_OK)
|
|
||||||
{
|
|
||||||
dds_delete_qos(wqos);
|
|
||||||
goto err_bad_qos;
|
goto err_bad_qos;
|
||||||
|
|
||||||
|
thread_state_awake (lookup_thread_state (), gv);
|
||||||
|
const struct ddsi_guid *ppguid = dds_entity_participant_guid (&pub->m_entity);
|
||||||
|
struct participant *pp = entidx_lookup_participant_guid (gv->entity_index, ppguid);
|
||||||
|
/* When deleting a participant, the child handles (that include the publisher)
|
||||||
|
are removed before removing the DDSI participant. So at this point, within
|
||||||
|
the publisher lock, we can assert that the participant exists. */
|
||||||
|
assert (pp != NULL);
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
/* Check if DDS Security is enabled */
|
||||||
|
if (q_omg_participant_is_secure (pp))
|
||||||
|
{
|
||||||
|
/* ask to access control security plugin for create writer permissions */
|
||||||
|
if (!q_omg_security_check_create_writer (pp, gv->config.domainId, tp->m_stopic->name, wqos))
|
||||||
|
{
|
||||||
|
rc = DDS_RETCODE_NOT_ALLOWED_BY_SECURITY;
|
||||||
|
goto err_not_allowed;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create writer */
|
/* Create writer */
|
||||||
ddsi_tran_conn_t conn = pub->m_entity.m_domain->gv.xmit_conn;
|
ddsi_tran_conn_t conn = gv->xmit_conn;
|
||||||
struct dds_writer * const wr = dds_alloc (sizeof (*wr));
|
struct dds_writer * const wr = dds_alloc (sizeof (*wr));
|
||||||
const dds_entity_t writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, false, wqos, listener, DDS_WRITER_STATUS_MASK);
|
const dds_entity_t writer = dds_entity_init (&wr->m_entity, &pub->m_entity, DDS_KIND_WRITER, false, wqos, listener, DDS_WRITER_STATUS_MASK);
|
||||||
wr->m_topic = tp;
|
wr->m_topic = tp;
|
||||||
dds_entity_add_ref_locked (&tp->m_entity);
|
dds_entity_add_ref_locked (&tp->m_entity);
|
||||||
wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), pub->m_entity.m_domain->gv.config.xpack_send_async);
|
wr->m_xp = nn_xpack_new (conn, get_bandwidth_limit (wqos->transport_priority), gv->config.xpack_send_async);
|
||||||
wrinfo = whc_make_wrinfo (wr, wqos);
|
wrinfo = whc_make_wrinfo (wr, wqos);
|
||||||
wr->m_whc = whc_new (&pub->m_entity.m_domain->gv, wrinfo);
|
wr->m_whc = whc_new (gv, wrinfo);
|
||||||
whc_free_wrinfo (wrinfo);
|
whc_free_wrinfo (wrinfo);
|
||||||
wr->whc_batch = pub->m_entity.m_domain->gv.config.whc_batch;
|
wr->whc_batch = gv->config.whc_batch;
|
||||||
|
|
||||||
thread_state_awake (lookup_thread_state (), &pub->m_entity.m_domain->gv);
|
rc = new_writer (&wr->m_wr, &wr->m_entity.m_guid, NULL, pp, tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
|
||||||
rc = new_writer (&wr->m_wr, &wr->m_entity.m_domain->gv, &wr->m_entity.m_guid, NULL, dds_entity_participant_guid (&pub->m_entity), tp->m_stopic, wqos, wr->m_whc, dds_writer_status_cb, wr);
|
|
||||||
assert(rc == DDS_RETCODE_OK);
|
assert(rc == DDS_RETCODE_OK);
|
||||||
thread_state_asleep (lookup_thread_state ());
|
thread_state_asleep (lookup_thread_state ());
|
||||||
|
|
||||||
|
@ -355,7 +373,12 @@ dds_entity_t dds_create_writer (dds_entity_t participant_or_publisher, dds_entit
|
||||||
dds_publisher_unlock (pub);
|
dds_publisher_unlock (pub);
|
||||||
return writer;
|
return writer;
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
err_not_allowed:
|
||||||
|
thread_state_asleep (lookup_thread_state ());
|
||||||
|
#endif
|
||||||
err_bad_qos:
|
err_bad_qos:
|
||||||
|
dds_delete_qos(wqos);
|
||||||
dds_topic_allow_set_qos (tp);
|
dds_topic_allow_set_qos (tp);
|
||||||
err_pp_mismatch:
|
err_pp_mismatch:
|
||||||
dds_topic_unpin (tp);
|
dds_topic_unpin (tp);
|
||||||
|
@ -387,14 +410,14 @@ dds_entity_t dds_get_publisher (dds_entity_t writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, dds_time_t abstimeout)
|
dds_return_t dds__writer_wait_for_acks (struct dds_writer *wr, ddsi_guid_t *rdguid, dds_time_t abstimeout)
|
||||||
{
|
{
|
||||||
/* during lifetime of the writer m_wr is constant, it is only during deletion that it
|
/* during lifetime of the writer m_wr is constant, it is only during deletion that it
|
||||||
gets erased at some point */
|
gets erased at some point */
|
||||||
if (wr->m_wr == NULL)
|
if (wr->m_wr == NULL)
|
||||||
return DDS_RETCODE_OK;
|
return DDS_RETCODE_OK;
|
||||||
else
|
else
|
||||||
return writer_wait_for_acks (wr->m_wr, abstimeout);
|
return writer_wait_for_acks (wr->m_wr, rdguid, abstimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
DDS_GET_STATUS(writer, publication_matched, PUBLICATION_MATCHED, total_count_change, current_count_change)
|
DDS_GET_STATUS(writer, publication_matched, PUBLICATION_MATCHED, total_count_change, current_count_change)
|
||||||
|
|
|
@ -59,7 +59,9 @@ set(ddsc_test_sources
|
||||||
"write_various_types.c"
|
"write_various_types.c"
|
||||||
"writer.c"
|
"writer.c"
|
||||||
"test_common.c"
|
"test_common.c"
|
||||||
"test_common.h")
|
"test_common.h"
|
||||||
|
"test_oneliner.c"
|
||||||
|
"test_oneliner.h")
|
||||||
|
|
||||||
if(ENABLE_LIFESPAN)
|
if(ENABLE_LIFESPAN)
|
||||||
list(APPEND ddsc_test_sources "lifespan.c")
|
list(APPEND ddsc_test_sources "lifespan.c")
|
||||||
|
@ -83,11 +85,10 @@ set(CUnit_ddsc_config_simple_udp_file "${CMAKE_CURRENT_LIST_DIR}/config_simple_u
|
||||||
set(CUnit_ddsc_config_simple_udp_uri "file://${CUnit_ddsc_config_simple_udp_file}")
|
set(CUnit_ddsc_config_simple_udp_uri "file://${CUnit_ddsc_config_simple_udp_file}")
|
||||||
set(CUnit_ddsc_config_simple_udp_max_participants "0")
|
set(CUnit_ddsc_config_simple_udp_max_participants "0")
|
||||||
set(CUnit_ddsc_config_simple_udp_env "${PROJECT_NAME_CAPS}_URI=${CUnit_ddsc_config_simple_udp_uri};MAX_PARTICIPANTS=${CUnit_ddsc_config_simple_udp_max_participants};${CUnit_ddsc_config_simple_udp_env}")
|
set(CUnit_ddsc_config_simple_udp_env "${PROJECT_NAME_CAPS}_URI=${CUnit_ddsc_config_simple_udp_uri};MAX_PARTICIPANTS=${CUnit_ddsc_config_simple_udp_max_participants};${CUnit_ddsc_config_simple_udp_env}")
|
||||||
|
|
||||||
set_tests_properties(
|
set_tests_properties(
|
||||||
CUnit_ddsc_config_simple_udp
|
CUnit_ddsc_config_simple_udp
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
REQUIRED_FILES ${CUnit_ddsc_config_simple_udp_file}
|
REQUIRED_FILES ${CUnit_ddsc_config_simple_udp_file}
|
||||||
ENVIRONMENT "${CUnit_ddsc_config_simple_udp_env}")
|
ENVIRONMENT "${CUnit_ddsc_config_simple_udp_env}")
|
||||||
|
|
||||||
configure_file("config_env.h.in" "config_env.h")
|
configure_file("config_env.h.in" "config_env.h" @ONLY)
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include "dds/ddsrt/cdtors.h"
|
#include "dds/ddsrt/cdtors.h"
|
||||||
#include "dds/ddsrt/environ.h"
|
#include "dds/ddsrt/environ.h"
|
||||||
#include "dds/ddsrt/heap.h"
|
#include "dds/ddsrt/heap.h"
|
||||||
|
#include "dds/ddsi/q_misc.h"
|
||||||
|
#include "dds/ddsi/ddsi_xqos.h"
|
||||||
|
|
||||||
#include "test_common.h"
|
#include "test_common.h"
|
||||||
|
|
||||||
|
@ -28,7 +30,7 @@
|
||||||
|
|
||||||
static void config__check_env (const char *env_variable, const char *expected_value)
|
static void config__check_env (const char *env_variable, const char *expected_value)
|
||||||
{
|
{
|
||||||
char *env_uri = NULL;
|
const char *env_uri = NULL;
|
||||||
ddsrt_getenv (env_variable, &env_uri);
|
ddsrt_getenv (env_variable, &env_uri);
|
||||||
#ifdef FORCE_ENV
|
#ifdef FORCE_ENV
|
||||||
{
|
{
|
||||||
|
@ -84,3 +86,99 @@ CU_Test (ddsc_config, user_config, .init = ddsrt_init, .fini = ddsrt_fini)
|
||||||
dds_delete (domain);
|
dds_delete (domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'found' variable will contain flags related to the expected log
|
||||||
|
* messages that were received.
|
||||||
|
* Using flags will allow to show that when message isn't received,
|
||||||
|
* which one it was.
|
||||||
|
*/
|
||||||
|
static uint32_t found;
|
||||||
|
static void logger(void *ptr, const dds_log_data_t *data)
|
||||||
|
{
|
||||||
|
char **expected = (char**)ptr;
|
||||||
|
for (uint32_t i = 0; expected[i] != NULL; i++) {
|
||||||
|
if (ddsi2_patmatch(expected[i], data->message)) {
|
||||||
|
found |= (uint32_t)(1 << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_security_config, empty, .init = ddsrt_init, .fini = ddsrt_fini)
|
||||||
|
{
|
||||||
|
/* Expected traces when creating participant with an empty security element. We need to
|
||||||
|
test this one here to be sure that it refuses to start when security is configured
|
||||||
|
but the implementation doesn't include support for it. */
|
||||||
|
const char *log_expected[] = {
|
||||||
|
#ifndef DDSI_INCLUDE_SECURITY
|
||||||
|
"config: //CycloneDDS/Domain: DDSSecurity: unknown element*",
|
||||||
|
#else
|
||||||
|
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCertificate/#text: element missing in configuration*",
|
||||||
|
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/IdentityCA/#text: element missing in configuration*",
|
||||||
|
"config: //CycloneDDS/Domain/DDSSecurity/Authentication/PrivateKey/#text: element missing in configuration*",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
dds_entity_t participant;
|
||||||
|
|
||||||
|
/* Set up the trace sinks to detect the config parsing. */
|
||||||
|
dds_set_log_mask(DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
|
||||||
|
dds_set_log_sink(&logger, (void*)log_expected);
|
||||||
|
dds_set_trace_sink(&logger, (void*)log_expected);
|
||||||
|
|
||||||
|
/* Create participant with an empty security element. */
|
||||||
|
found = 0;
|
||||||
|
ddsrt_setenv(URI_VARIABLE, "<DDSSecurity/>");
|
||||||
|
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
|
||||||
|
ddsrt_setenv(URI_VARIABLE, "");
|
||||||
|
CU_ASSERT_FATAL(participant < 0);
|
||||||
|
dds_set_log_sink(NULL, NULL);
|
||||||
|
dds_set_trace_sink(NULL, NULL);
|
||||||
|
|
||||||
|
/* All traces should have been provided. */
|
||||||
|
#ifndef DDSI_INCLUDE_SECURITY
|
||||||
|
CU_ASSERT_FATAL(found == 0x1);
|
||||||
|
#else
|
||||||
|
CU_ASSERT_FATAL(found == 0x7);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_security_qos, empty, .init = ddsrt_init, .fini = ddsrt_fini)
|
||||||
|
{
|
||||||
|
/* Expected traces when creating participant with some (not all) security QoS
|
||||||
|
settings. We need to test this one here to be sure that it also refuses to
|
||||||
|
start when security is configured but the implementation doesn't include
|
||||||
|
support for it. */
|
||||||
|
const char *log_expected[] = {
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
"new_participant(*): using security settings from QoS*",
|
||||||
|
"new_participant(*): required security property * missing*",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Set up the trace sinks to detect the config parsing. */
|
||||||
|
dds_set_log_mask (DDS_LC_FATAL|DDS_LC_ERROR|DDS_LC_WARNING|DDS_LC_CONFIG);
|
||||||
|
dds_set_log_sink (&logger, (void *) log_expected);
|
||||||
|
dds_set_trace_sink (&logger, (void *) log_expected);
|
||||||
|
|
||||||
|
/* Create participant with incomplete/nonsensical security configuration: this should always fail */
|
||||||
|
found = 0;
|
||||||
|
dds_qos_t *qos = dds_create_qos ();
|
||||||
|
dds_qset_prop (qos, "dds.sec.nonsense", "");
|
||||||
|
dds_entity_t domain = dds_create_domain (0, "<Tracing><Category>trace</Category>");
|
||||||
|
CU_ASSERT_FATAL (domain > 0);
|
||||||
|
dds_entity_t participant = dds_create_participant (0, qos, NULL);
|
||||||
|
dds_delete_qos (qos);
|
||||||
|
CU_ASSERT_FATAL (participant < 0);
|
||||||
|
(void) dds_delete (domain);
|
||||||
|
dds_set_log_sink (NULL, NULL);
|
||||||
|
dds_set_trace_sink (NULL, NULL);
|
||||||
|
|
||||||
|
/* All traces should have been provided. */
|
||||||
|
#ifndef DDSI_INCLUDE_SECURITY
|
||||||
|
CU_ASSERT_FATAL (found == 0x0);
|
||||||
|
#else
|
||||||
|
CU_ASSERT_FATAL (found == 0x3);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -125,6 +125,7 @@ static void deadline_init(void)
|
||||||
dds_qset_history(g_qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED);
|
dds_qset_history(g_qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED);
|
||||||
dds_qset_durability(g_qos, DDS_DURABILITY_TRANSIENT_LOCAL);
|
dds_qset_durability(g_qos, DDS_DURABILITY_TRANSIENT_LOCAL);
|
||||||
dds_qset_reliability(g_qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY);
|
dds_qset_reliability(g_qos, DDS_RELIABILITY_RELIABLE, DDS_INFINITY);
|
||||||
|
dds_qset_writer_data_lifecycle(g_qos, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deadline_fini(void)
|
static void deadline_fini(void)
|
||||||
|
@ -422,7 +423,10 @@ CU_Theory((int32_t n_inst, uint8_t unreg_nth, uint8_t dispose_nth), ddsc_deadlin
|
||||||
n_dispose++;
|
n_dispose++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n_alive = n_inst - n_dispose - n_unreg;
|
/* FIXME: should unregistered instances cause deadline expirations? I do think so
|
||||||
|
and that is what it actually implemented
|
||||||
|
if they shouldn't: n_alive = n_inst - n_dispose - n_unreg */
|
||||||
|
n_alive = n_inst - n_dispose;
|
||||||
|
|
||||||
/* Sleep deadline_dur + 50% and check missed deadline count */
|
/* Sleep deadline_dur + 50% and check missed deadline count */
|
||||||
sleepfor(3 * deadline_dur / 2);
|
sleepfor(3 * deadline_dur / 2);
|
||||||
|
|
|
@ -110,6 +110,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities)
|
||||||
CU_ASSERT_FATAL (result == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL (result == DDS_RETCODE_OK);
|
||||||
/* return resets buf[0] (so that it picks up the loan the next time) and zeros the data */
|
/* return resets buf[0] (so that it picks up the loan the next time) and zeros the data */
|
||||||
CU_ASSERT_FATAL (ptrs[0] == NULL);
|
CU_ASSERT_FATAL (ptrs[0] == NULL);
|
||||||
|
assert (ptr0copy != NULL); /* clang static analyzer */
|
||||||
CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0);
|
CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0);
|
||||||
|
|
||||||
/* read 3, return: should work fine, causes realloc */
|
/* read 3, return: should work fine, causes realloc */
|
||||||
|
@ -121,6 +122,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities)
|
||||||
result = dds_return_loan (reader, ptrs, n);
|
result = dds_return_loan (reader, ptrs, n);
|
||||||
CU_ASSERT_FATAL (result == DDS_RETCODE_OK);
|
CU_ASSERT_FATAL (result == DDS_RETCODE_OK);
|
||||||
CU_ASSERT_FATAL (ptrs[0] == NULL);
|
CU_ASSERT_FATAL (ptrs[0] == NULL);
|
||||||
|
assert (ptr0copy != NULL); /* clang static analyzer */
|
||||||
CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, 3 * sizeof (s)) == 0);
|
CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, 3 * sizeof (s)) == 0);
|
||||||
|
|
||||||
/* read 1 using loan, expecting to get the same address (no realloc needed), defer return.
|
/* read 1 using loan, expecting to get the same address (no realloc needed), defer return.
|
||||||
|
@ -145,6 +147,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities)
|
||||||
{
|
{
|
||||||
const struct RoundTripModule_DataType *a = ptrs[0];
|
const struct RoundTripModule_DataType *a = ptrs[0];
|
||||||
const struct RoundTripModule_DataType *b = ptrs2[0];
|
const struct RoundTripModule_DataType *b = ptrs2[0];
|
||||||
|
assert (a != NULL && b != NULL); /* clang static analyzer */
|
||||||
CU_ASSERT_FATAL (a->payload._length == b->payload._length);
|
CU_ASSERT_FATAL (a->payload._length == b->payload._length);
|
||||||
CU_ASSERT_FATAL (a->payload._buffer != b->payload._buffer);
|
CU_ASSERT_FATAL (a->payload._buffer != b->payload._buffer);
|
||||||
CU_ASSERT_FATAL (a->payload._buffer[0] == b->payload._buffer[0]);
|
CU_ASSERT_FATAL (a->payload._buffer[0] == b->payload._buffer[0]);
|
||||||
|
@ -164,6 +167,7 @@ CU_Test (ddsc_loan, success, .init = create_entities, .fini = delete_entities)
|
||||||
|
|
||||||
//This should be a use-after-free
|
//This should be a use-after-free
|
||||||
//CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0);
|
//CU_ASSERT_FATAL (memcmp (ptr0copy, zeros, sizeof (s)) == 0);
|
||||||
|
(void) ptr0copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
CU_Test (ddsc_loan, take_cleanup, .init = create_entities, .fini = delete_entities)
|
CU_Test (ddsc_loan, take_cleanup, .init = create_entities, .fini = delete_entities)
|
||||||
|
|
|
@ -111,7 +111,7 @@ CU_Test(ddsc_participant, create_with_conf_no_env) {
|
||||||
ddsrt_setenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI", CONFIG_ENV_SIMPLE_UDP);
|
ddsrt_setenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI", CONFIG_ENV_SIMPLE_UDP);
|
||||||
ddsrt_setenv("MAX_PARTICIPANTS", CONFIG_ENV_MAX_PARTICIPANTS);
|
ddsrt_setenv("MAX_PARTICIPANTS", CONFIG_ENV_MAX_PARTICIPANTS);
|
||||||
|
|
||||||
char * env_uri = NULL;
|
const char * env_uri = NULL;
|
||||||
ddsrt_getenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI", &env_uri);
|
ddsrt_getenv(DDS_PROJECT_NAME_NOSPACE_CAPS"_URI", &env_uri);
|
||||||
CU_ASSERT_PTR_NOT_EQUAL_FATAL(env_uri, NULL);
|
CU_ASSERT_PTR_NOT_EQUAL_FATAL(env_uri, NULL);
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
*/
|
*/
|
||||||
#include "CUnit/Test.h"
|
#include "CUnit/Test.h"
|
||||||
#include "dds/dds.h"
|
#include "dds/dds.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Convenience global policies
|
* Convenience global policies
|
||||||
|
@ -146,7 +147,10 @@ static const char* c_userdata = "user_key";
|
||||||
static const char* c_topicdata = "topic_key";
|
static const char* c_topicdata = "topic_key";
|
||||||
static const char* c_groupdata = "group_key";
|
static const char* c_groupdata = "group_key";
|
||||||
static const char* c_partitions[] = {"Partition1", "Partition2"};
|
static const char* c_partitions[] = {"Partition1", "Partition2"};
|
||||||
|
static const char* c_property_names[] = {"prop1", "prop2", "prop3"};
|
||||||
|
static const char* c_property_values[] = {"val1", "val2", "val3"};
|
||||||
|
static const char* c_bproperty_names[] = {"bprop1", "bprop2", "bprop3"};
|
||||||
|
static const unsigned char c_bproperty_values[3][3] = {{0x0, 0x1, 0x2}, {0x2, 0x3, 0x4}, {0x5, 0x6, 0x7}};
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -646,3 +650,191 @@ CU_Test(ddsc_qos, durability_service, .init=qos_init, .fini=qos_fini)
|
||||||
CU_ASSERT_EQUAL_FATAL(p.max_samples_per_instance, g_pol_durability_service.max_samples_per_instance);
|
CU_ASSERT_EQUAL_FATAL(p.max_samples_per_instance, g_pol_durability_service.max_samples_per_instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_qos, property, .init=qos_init, .fini=qos_fini)
|
||||||
|
{
|
||||||
|
char * value = NULL;
|
||||||
|
char ** names = NULL;
|
||||||
|
uint32_t cnt = 0;
|
||||||
|
|
||||||
|
/* NULLs shouldn't crash and be a noops. */
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_prop (g_qos, NULL, NULL));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_prop (g_qos, c_property_names[0], NULL));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_prop (g_qos, NULL, &value));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_prop (NULL, c_property_names[0], &value));
|
||||||
|
|
||||||
|
dds_qset_prop (g_qos, NULL, NULL);
|
||||||
|
dds_qset_prop (g_qos, NULL, c_property_values[0]);
|
||||||
|
dds_qset_prop (NULL, c_property_names[0], c_property_values[0]);
|
||||||
|
|
||||||
|
/* Set null value should not succeed, setting empty string should */
|
||||||
|
dds_qset_prop (g_qos, c_property_names[0], NULL);
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
dds_qset_prop (g_qos, c_property_names[0], "");
|
||||||
|
CU_ASSERT_FATAL (dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (value, "");
|
||||||
|
dds_free (value);
|
||||||
|
|
||||||
|
/* Getting after setting, should yield the original input. */
|
||||||
|
dds_qset_prop (g_qos, c_property_names[0], c_property_values[0]);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (value, c_property_values[0]);
|
||||||
|
dds_free (value);
|
||||||
|
|
||||||
|
/* Overwrite value for existing property (and reset value) */
|
||||||
|
dds_qset_prop (g_qos, c_property_names[0], c_property_values[1]);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (value, c_property_values[1]);
|
||||||
|
dds_free (value);
|
||||||
|
dds_qset_prop (g_qos, c_property_names[0], c_property_values[0]);
|
||||||
|
|
||||||
|
/* Set 2nd prop and get length */
|
||||||
|
dds_qset_prop (g_qos, c_property_names[1], c_property_values[1]);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_propnames (g_qos, &cnt, NULL));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 2);
|
||||||
|
|
||||||
|
/* Set another property and get list of property names */
|
||||||
|
dds_qset_prop (g_qos, c_property_names[2], c_property_values[2]);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_propnames (g_qos, &cnt, &names));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 3);
|
||||||
|
for (uint32_t i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (names[i], c_property_names[i]);
|
||||||
|
dds_free (names[i]);
|
||||||
|
}
|
||||||
|
dds_free (names);
|
||||||
|
|
||||||
|
/* Unset a property and check if removed */
|
||||||
|
dds_qunset_prop (g_qos, c_property_names[1]);
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_prop (g_qos, c_property_names[1], &value));
|
||||||
|
CU_ASSERT_FATAL (dds_qget_propnames (g_qos, &cnt, NULL));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 2);
|
||||||
|
CU_ASSERT_FATAL(dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (value, c_property_values[0]);
|
||||||
|
dds_free (value);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_prop (g_qos, c_property_names[2], &value));
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (value, c_property_values[2]);
|
||||||
|
dds_free (value);
|
||||||
|
dds_qunset_prop (g_qos, c_property_names[0]);
|
||||||
|
dds_qunset_prop (g_qos, c_property_names[2]);
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_propnames (g_qos, &cnt, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_qos, bproperty, .init=qos_init, .fini=qos_fini)
|
||||||
|
{
|
||||||
|
void * bvalue = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
char ** names = NULL;
|
||||||
|
uint32_t cnt = 0;
|
||||||
|
|
||||||
|
/* NULLs shouldn't crash and be a noops. */
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bprop (g_qos, NULL, NULL, NULL));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bprop (g_qos, c_bproperty_names[0], NULL, NULL));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bprop (g_qos, NULL, &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bprop (NULL, c_bproperty_names[0], &bvalue, &size));
|
||||||
|
|
||||||
|
dds_qset_bprop (g_qos, NULL, NULL, 0);
|
||||||
|
dds_qset_bprop (g_qos, NULL, &c_bproperty_values[0], 0);
|
||||||
|
dds_qset_bprop (NULL, c_bproperty_names[0], c_bproperty_values[0], 0);
|
||||||
|
|
||||||
|
/* Set null value should succeed */
|
||||||
|
dds_qset_bprop (g_qos, c_bproperty_names[0], NULL, 0);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_bproperty_names[0], &bvalue, &size));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (bvalue, NULL);
|
||||||
|
CU_ASSERT_EQUAL_FATAL (size, 0);
|
||||||
|
|
||||||
|
/* Getting after setting, should yield the original input. */
|
||||||
|
dds_qset_bprop (g_qos, c_bproperty_names[0], c_bproperty_values[0], 3);
|
||||||
|
CU_ASSERT_FATAL(dds_qget_bprop (g_qos, c_bproperty_names[0], &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (bvalue != NULL);
|
||||||
|
CU_ASSERT_EQUAL_FATAL (size, 3);
|
||||||
|
assert (c_bproperty_values[0] != NULL); /* for Clang static analyzer */
|
||||||
|
CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[0], size), 0);
|
||||||
|
dds_free (bvalue);
|
||||||
|
|
||||||
|
/* Overwrite value for existing binary property (and reset value) */
|
||||||
|
dds_qset_bprop (g_qos, c_bproperty_names[0], c_bproperty_values[1], 3);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_bproperty_names[0], &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (bvalue != NULL);
|
||||||
|
CU_ASSERT_EQUAL_FATAL (size, 3);
|
||||||
|
assert (c_bproperty_values[1] != NULL); /* for Clang static analyzer */
|
||||||
|
CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[1], size), 0);
|
||||||
|
dds_free (bvalue);
|
||||||
|
dds_qset_bprop (g_qos, c_bproperty_names[0], &c_bproperty_values[0], 3);
|
||||||
|
|
||||||
|
/* Set 2nd binary prop and get length */
|
||||||
|
dds_qset_bprop (g_qos, c_bproperty_names[1], &c_bproperty_values[1], 3);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bpropnames (g_qos, &cnt, NULL));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 2);
|
||||||
|
|
||||||
|
/* Set another binary property and get list of property names */
|
||||||
|
dds_qset_bprop (g_qos, c_bproperty_names[2], &c_bproperty_values[2], 3);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bpropnames (g_qos, &cnt, &names));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 3);
|
||||||
|
for (uint32_t i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (names[i], c_bproperty_names[i]);
|
||||||
|
dds_free (names[i]);
|
||||||
|
}
|
||||||
|
dds_free (names);
|
||||||
|
|
||||||
|
/* Unset a binary property and check if removed */
|
||||||
|
dds_qunset_bprop (g_qos, c_bproperty_names[1]);
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bprop (g_qos, c_bproperty_names[1], &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bpropnames (g_qos, &cnt, NULL));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 2);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_bproperty_names[0], &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (bvalue != NULL);
|
||||||
|
CU_ASSERT_EQUAL_FATAL (size, 3);
|
||||||
|
assert (c_bproperty_values[0] != NULL); /* for Clang static analyzer */
|
||||||
|
CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[0], size), 0);
|
||||||
|
dds_free (bvalue);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_bproperty_names[2], &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (bvalue != NULL);
|
||||||
|
CU_ASSERT_EQUAL_FATAL (size, 3);
|
||||||
|
assert (c_bproperty_values[2] != NULL); /* for Clang static analyzer */
|
||||||
|
CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[2], size), 0);
|
||||||
|
dds_free (bvalue);
|
||||||
|
dds_qunset_bprop (g_qos, c_bproperty_names[0]);
|
||||||
|
dds_qunset_bprop (g_qos, c_bproperty_names[2]);
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bpropnames (g_qos, &cnt, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
CU_Test(ddsc_qos, property_mixed, .init=qos_init, .fini=qos_fini)
|
||||||
|
{
|
||||||
|
char * value = NULL;
|
||||||
|
void * bvalue = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
uint32_t cnt = 0;
|
||||||
|
|
||||||
|
/* Set property and binary property with same name */
|
||||||
|
dds_qset_prop (g_qos, c_property_names[0], c_property_values[0]);
|
||||||
|
dds_qset_bprop (g_qos, c_property_names[0], c_bproperty_values[0], 3);
|
||||||
|
|
||||||
|
/* Check property values and count */
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bprop (g_qos, c_property_names[0], &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (bvalue != NULL);
|
||||||
|
CU_ASSERT_EQUAL_FATAL (size, 3);
|
||||||
|
assert (c_bproperty_values[0] != NULL); /* for Clang static analyzer */
|
||||||
|
CU_ASSERT_EQUAL_FATAL (memcmp (bvalue, c_bproperty_values[0], size), 0);
|
||||||
|
dds_free (bvalue);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (value, c_property_values[0]);
|
||||||
|
dds_free (value);
|
||||||
|
|
||||||
|
CU_ASSERT_FATAL (dds_qget_propnames (g_qos, &cnt, NULL));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 1);
|
||||||
|
CU_ASSERT_FATAL (dds_qget_bpropnames (g_qos, &cnt, NULL));
|
||||||
|
CU_ASSERT_EQUAL_FATAL (cnt, 1);
|
||||||
|
|
||||||
|
/* Unset and check */
|
||||||
|
dds_qunset_bprop (g_qos, c_property_names[0]);
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bprop (g_qos, c_property_names[0], &bvalue, &size));
|
||||||
|
CU_ASSERT_FATAL (dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
CU_ASSERT_STRING_EQUAL_FATAL (value, c_property_values[0]);
|
||||||
|
dds_free (value);
|
||||||
|
|
||||||
|
dds_qunset_prop (g_qos, c_property_names[0]);
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_prop (g_qos, c_property_names[0], &value));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_propnames (g_qos, &cnt, NULL));
|
||||||
|
CU_ASSERT_FATAL (!dds_qget_bpropnames (g_qos, &cnt, NULL));
|
||||||
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
#define MAX_SAMPLES 21
|
#define MAX_SAMPLES 21
|
||||||
|
|
||||||
#define RDR_NOT_READ_CNT 11
|
#define RDR_NOT_READ_CNT 11
|
||||||
#define RDR_INV_READ_CNT 1
|
#define RDR_INV_READ_CNT 2
|
||||||
int rdr_expected_long_2[RDR_NOT_READ_CNT] = { 0, 1, 2, 6, 7, 9, 11, 13, 14, 16, 19 };
|
int rdr_expected_long_2[RDR_NOT_READ_CNT] = { 0, 1, 2, 6, 7, 9, 11, 13, 14, 16, 19 };
|
||||||
|
|
||||||
/* Because we only read one sample at a time, only the first sample of an instance
|
/* Because we only read one sample at a time, only the first sample of an instance
|
||||||
|
|
1842
src/core/ddsc/tests/test_oneliner.c
Normal file
326
src/core/ddsc/tests/test_oneliner.h
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2020 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef _TEST_ONELINER_H_
|
||||||
|
#define _TEST_ONELINER_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#include "dds/dds.h"
|
||||||
|
#include "dds/ddsrt/sync.h"
|
||||||
|
|
||||||
|
/** @brief run a "test" consisting of a sequence of simplish operations
|
||||||
|
*
|
||||||
|
* This operation takes a test description, really a program in a bizarre syntax, and
|
||||||
|
* executes it. Any failures, be it because of error codes coming out of the Cyclone
|
||||||
|
* calls or expected values being wrong cause it to fail the test via CU_ASSERT_FATAL.
|
||||||
|
* While it is doing this, it outputs the test steps to stdout including some actual
|
||||||
|
* values. An invalid program is mostly reported by calling abort(). It is geared towards
|
||||||
|
* checking for listener invocations and the effects on statuses.
|
||||||
|
*
|
||||||
|
* Entities in play:
|
||||||
|
*
|
||||||
|
* - participants: P P' P''
|
||||||
|
* - subscribers: R R' R''
|
||||||
|
* - publishers: W W' W''
|
||||||
|
* - readers: r s t r' s' t' r'' s'' t''
|
||||||
|
* - writers: w x y w' x' y' w'' x'' y''
|
||||||
|
*
|
||||||
|
* The unprimed ones exist in domain 0, the primed ones in domain 1 (but configured such
|
||||||
|
* that it talks to domain 0), and the double-primed ones in domain 2 (again configured such
|
||||||
|
* that it talks to domain 0) so that network-related listener invocations can be checked
|
||||||
|
* as well.
|
||||||
|
*
|
||||||
|
* The first mention of an entity creates it as well as its ancestors. Implicitly created
|
||||||
|
* ancestors always have standard QoS and have no listeners. There is one topic that is
|
||||||
|
* created implicitly when the participant is created.
|
||||||
|
*
|
||||||
|
* Standard QoS is: default + reliable (100ms), by-source-timestamp, keep-all. The QoS of
|
||||||
|
* a reader/writer can be overridden at the first mention of it (i.e., when it is created)
|
||||||
|
* by appending a list of QoS overrides between parentheses.
|
||||||
|
*
|
||||||
|
* A program consists of a sequence of operations separated by whitespace, ';' or '/'
|
||||||
|
* (there is no meaning to the separators, they exist to allow visual grouping):
|
||||||
|
*
|
||||||
|
* PROGRAM ::= (OP (\s+|;)*)*
|
||||||
|
*
|
||||||
|
* OP ::= (LISTENER)* ENTITY-NAME[(QOS[,QOS[,QOS...]])]
|
||||||
|
*
|
||||||
|
* If entity ENTITY-NAME does not exist:
|
||||||
|
* creates the entity with the given listeners installed
|
||||||
|
* QOS can be used to override the standard QoS
|
||||||
|
* else
|
||||||
|
* changes the entity's listeners to the specified ones
|
||||||
|
* (see above for the valid ENTITY-NAMEs)
|
||||||
|
*
|
||||||
|
* | -ENTITY-NAME
|
||||||
|
*
|
||||||
|
* Deletes the specified entity
|
||||||
|
*
|
||||||
|
* | WRITE-LIKE[fail] ENTITY-NAME K[@DT]
|
||||||
|
* | WRITE-LIKE[fail] ENTITY-NAME (K,X,Y)[@DT]
|
||||||
|
*
|
||||||
|
* Writes/disposes/unregisters (K,0,0) (first form) or (K,X,Y). If
|
||||||
|
* "fail" is appended, the expectation is that it fails with a
|
||||||
|
* timeout, if @DT is appended, the timestamp is the start time of
|
||||||
|
* the test + <dt>s rather than the current time; DT is a
|
||||||
|
* floating-point number
|
||||||
|
*
|
||||||
|
* | READ-LIKE ENTITY-NAME
|
||||||
|
* | READ-LIKE(A,B) ENTITY-NAME
|
||||||
|
* | READ-LIKE{[S1[,S2[,S3...]][,...]} ENTITY-NAME
|
||||||
|
*
|
||||||
|
* Reads/takes at most 10 samples. The second form counts the
|
||||||
|
* number of valid and invalid samples seen and checks them against
|
||||||
|
* A and B.
|
||||||
|
*
|
||||||
|
* In the third form, the exact result set is given by the sample
|
||||||
|
* Si, which is a comma-separated list of samples:
|
||||||
|
*
|
||||||
|
* [STATE]K[ENTITY-NAME][@DT]
|
||||||
|
* [STATE](K,X,Y)[ENTITY-NAME][@DT]
|
||||||
|
*
|
||||||
|
* The first form is an invalid sample with only the (integer) key
|
||||||
|
* value K, the second form also specifies the two (integer)
|
||||||
|
* attribute fields.
|
||||||
|
*
|
||||||
|
* STATE specifies allowed sample (f - not-read (fresh), s - read
|
||||||
|
* (stale)), instance (a - alive, u - no-writers (unregistered) d -
|
||||||
|
* disposed) and view states (n - new, o - old). If no sample state
|
||||||
|
* is specified, all sample states are allowed, &c.
|
||||||
|
*
|
||||||
|
* ENTITY-NAME is the name of the publishing writer expected in the
|
||||||
|
* publication_handle. Not specifying a writer means any writer is
|
||||||
|
* ok. DT is the timestamp in the same manner as the write-like
|
||||||
|
* operations. Not specifying a timestamp means any timestamp is
|
||||||
|
* ok.
|
||||||
|
*
|
||||||
|
* If the expected set ends up with "..." there may be other samples
|
||||||
|
* in the result as well.
|
||||||
|
*
|
||||||
|
* | ?LISTENER[(ARGS)] ENTITY-NAME
|
||||||
|
*
|
||||||
|
* Waits until the specified listener has been invoked on <entity
|
||||||
|
* name> using a flag set by the listener function, resets the flag
|
||||||
|
* and verifies that neither the entity status bit nor the "change"
|
||||||
|
* fields in the various statuses were set.
|
||||||
|
*
|
||||||
|
* ARGS is used to check the status argument most recently passed to
|
||||||
|
* the listener:
|
||||||
|
*
|
||||||
|
* da(A) verifies that it has been invoked A times
|
||||||
|
* dor(A) see da
|
||||||
|
* it(A,B) verifies count and change match A and B, policy
|
||||||
|
* matches RELIABILITY
|
||||||
|
* lc(A,B,C,D,E) verifies that alive and not-alive counts match A
|
||||||
|
* and B, that alive and not-alive changes match C and D
|
||||||
|
* and that the last handle matches E if an entity name
|
||||||
|
* (ignored if E = "*")
|
||||||
|
* ll (A,B) verifies count and change match A and B
|
||||||
|
* odm (A,B) verifies count and change match A and B, last handle
|
||||||
|
* is ignored
|
||||||
|
* oiq (A,B,C) verifies that total count and change match A and B
|
||||||
|
* and that the mismatching QoS is C (using the same
|
||||||
|
* abbreviations as used for defining QoS on entity
|
||||||
|
* creation)
|
||||||
|
* pm (A,B,C,D,E) verifies that total count and change match A and
|
||||||
|
* B, that current count and change match C and D and
|
||||||
|
* that the last handle matches E if an entity name
|
||||||
|
* (ignored if E = "*")
|
||||||
|
* rdm see odm
|
||||||
|
* riq see oiq
|
||||||
|
* sl (A,B) verifies that total count and change match A and B
|
||||||
|
* sr (A,B,C) verifies total count and change match A and B, and
|
||||||
|
* that the reason matches C (one of "s" for samples,
|
||||||
|
* "i" for instances, "spi" for samples per instance)
|
||||||
|
* sm see pm
|
||||||
|
*
|
||||||
|
* | ?!LISTENER
|
||||||
|
*
|
||||||
|
* (Not listener) tests that LISTENER has not been invoked since
|
||||||
|
* last reset
|
||||||
|
*
|
||||||
|
* | sleep D
|
||||||
|
*
|
||||||
|
* Delay program execution for D s (D is a floating-point number)
|
||||||
|
*
|
||||||
|
* | deaf ENTITY-NAME
|
||||||
|
* | hearing ENTITY-NAME
|
||||||
|
*
|
||||||
|
* Makes the domain wherein the specified entity exists deaf,
|
||||||
|
* respectively restoring hearing. The entity must be either P or
|
||||||
|
* P' and both must exist. Plays some tricks to speed up lease
|
||||||
|
* expiry and reconnection (like forcibly deleting a proxy
|
||||||
|
* participant or triggering the publication of SPDP packets).
|
||||||
|
*
|
||||||
|
* WRITE-LIKE ::= wr write
|
||||||
|
* | wrdisp write-dispose
|
||||||
|
* | disp dispose
|
||||||
|
* | unreg unregister
|
||||||
|
*
|
||||||
|
* READ-LIKE ::= read dds_read (so any state)
|
||||||
|
* | take dds_take (so any state)
|
||||||
|
*
|
||||||
|
* LISTENER ::= da data available (acts on a reader)
|
||||||
|
* | dor data on readers (acts on a subcsriber)
|
||||||
|
* | it incompatible topic (acts on a topic)
|
||||||
|
* | lc liveliness changed (acts on a reader)
|
||||||
|
* | ll liveliness lost (acts on a writer)
|
||||||
|
* | odm offered deadline missed (acts on a writer)
|
||||||
|
* | oiq offered incompatible QoS (acts on a writer)
|
||||||
|
* | pm publication matched (acts on a writer)
|
||||||
|
* | rdm requested deadline missed (acts on a reader)
|
||||||
|
* | riq requested incompatible QoS (acts on a reader)
|
||||||
|
* | sl sample lost (acts on a reader)
|
||||||
|
* | sr sample rejected (acts on a reader)
|
||||||
|
* | sm subscription matched (acts on a reader)
|
||||||
|
*
|
||||||
|
* QOS ::= ad={y|n} auto-dispose unregistered instances
|
||||||
|
* | d={v|tl|t|p} durability
|
||||||
|
* | dl={inf|DT} deadline (infinite or DT seconds)
|
||||||
|
* | ds=DT/H/RL durability service: cleanup delay, history,
|
||||||
|
* resource limits
|
||||||
|
* | do={r|s} by-reception or by-source destination order
|
||||||
|
* | h={N|all} history keep-last-N or keep-all
|
||||||
|
* | lb={inf|DT} latency budget
|
||||||
|
* | ll={a[:DT]|p:DT|w:DT} liveliness (automatic, manual by
|
||||||
|
* participant, manual by topic)
|
||||||
|
* | ls={inf|DT} lifespan
|
||||||
|
* | o={s|x[:N]} ownership shared or exclusive (strength N)
|
||||||
|
* | p={i|t|g} presentation: instance, coherent-topic or
|
||||||
|
* coherent-group
|
||||||
|
* | r={be|r[:DT]} best-effort or reliable (with max blocking time)
|
||||||
|
* | rl=N[/N[/N]] resource limits (sample, instances, samples per
|
||||||
|
* instance; "inf" is allowed, ommitted ones are
|
||||||
|
* unlimited)
|
||||||
|
* | tp=N transport-priority
|
||||||
|
* | ud=... user data (with escape sequences and hex/octal
|
||||||
|
* input allowed)
|
||||||
|
*
|
||||||
|
* All entities share the listeners with their global state. Only the latest invocation is visible.
|
||||||
|
*
|
||||||
|
* @param[in] ops Program to execute.
|
||||||
|
*
|
||||||
|
* @return > 0 success, 0 failure, < 0 invalid input
|
||||||
|
*/
|
||||||
|
int test_oneliner (const char *ops);
|
||||||
|
|
||||||
|
union oneliner_tokval {
|
||||||
|
int i;
|
||||||
|
int64_t d;
|
||||||
|
char n[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct oneliner_lex {
|
||||||
|
const char *inp;
|
||||||
|
dds_time_t tref;
|
||||||
|
int tok;
|
||||||
|
union oneliner_tokval v;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct oneliner_ctx;
|
||||||
|
|
||||||
|
struct oneliner_cb {
|
||||||
|
struct oneliner_ctx *ctx;
|
||||||
|
dds_listener_t *list;
|
||||||
|
uint32_t cb_called[DDS_STATUS_ID_MAX + 1];
|
||||||
|
dds_entity_t cb_topic, cb_writer, cb_reader, cb_subscriber;
|
||||||
|
dds_inconsistent_topic_status_t cb_inconsistent_topic_status;
|
||||||
|
dds_liveliness_changed_status_t cb_liveliness_changed_status;
|
||||||
|
dds_liveliness_lost_status_t cb_liveliness_lost_status;
|
||||||
|
dds_offered_deadline_missed_status_t cb_offered_deadline_missed_status;
|
||||||
|
dds_offered_incompatible_qos_status_t cb_offered_incompatible_qos_status;
|
||||||
|
dds_publication_matched_status_t cb_publication_matched_status;
|
||||||
|
dds_requested_deadline_missed_status_t cb_requested_deadline_missed_status;
|
||||||
|
dds_requested_incompatible_qos_status_t cb_requested_incompatible_qos_status;
|
||||||
|
dds_sample_lost_status_t cb_sample_lost_status;
|
||||||
|
dds_sample_rejected_status_t cb_sample_rejected_status;
|
||||||
|
dds_subscription_matched_status_t cb_subscription_matched_status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct oneliner_ctx {
|
||||||
|
struct oneliner_lex l;
|
||||||
|
|
||||||
|
dds_entity_t es[3 * 9];
|
||||||
|
dds_entity_t tps[3];
|
||||||
|
dds_entity_t doms[3];
|
||||||
|
dds_instance_handle_t esi[3 * 9];
|
||||||
|
// built-in topic readers for cross-referencing instance handles
|
||||||
|
dds_entity_t pubrd[3];
|
||||||
|
dds_entity_t subrd[3];
|
||||||
|
// topic name used for data
|
||||||
|
char topicname[100];
|
||||||
|
|
||||||
|
const dds_qos_t *qos;
|
||||||
|
dds_qos_t *rwqos;
|
||||||
|
|
||||||
|
int result;
|
||||||
|
char msg[256];
|
||||||
|
|
||||||
|
jmp_buf jb;
|
||||||
|
|
||||||
|
ddsrt_mutex_t g_mutex;
|
||||||
|
ddsrt_cond_t g_cond;
|
||||||
|
struct oneliner_cb cb[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Initialize a "oneliner test" context
|
||||||
|
*
|
||||||
|
* @param[out] ctx context to initialize
|
||||||
|
*/
|
||||||
|
void test_oneliner_init (struct oneliner_ctx *ctx);
|
||||||
|
|
||||||
|
/** @brief Run a sequence of operations in an initialized context
|
||||||
|
*
|
||||||
|
* If the context indicates a preceding step has failed, this is a
|
||||||
|
* no-op and the previous result is propagated to the return value.
|
||||||
|
*
|
||||||
|
* @param[in,out] ctx context to operate in
|
||||||
|
* @param[in] ops sequence of operations to execute (@ref test_oneliner)
|
||||||
|
*
|
||||||
|
* @return integer indicating success or failure
|
||||||
|
*
|
||||||
|
* @retval 1 success
|
||||||
|
* @retval 0 test failure
|
||||||
|
* @retval <0 syntax error unexpected error
|
||||||
|
*/
|
||||||
|
int test_oneliner_step (struct oneliner_ctx *ctx, const char *ops);
|
||||||
|
|
||||||
|
/** @brief Get a pointer to the error message from a "oneliner test"
|
||||||
|
*
|
||||||
|
* If a preceding step has failed, this returns a pointer to a message
|
||||||
|
* containing some information about the failure. If no error
|
||||||
|
* occurred, the message is meaningless.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param[in] ctx context to retrieve message from
|
||||||
|
*
|
||||||
|
* @return pointer to null-terminated string aliasing a string in ctx
|
||||||
|
*/
|
||||||
|
const char *test_oneliner_message (const struct oneliner_ctx *ctx);
|
||||||
|
|
||||||
|
/** @brief Deinitialize a "oneliner test" context
|
||||||
|
*
|
||||||
|
* This releases all resources used by the context.
|
||||||
|
*
|
||||||
|
* @param[in,out] ctx context to operate in
|
||||||
|
*
|
||||||
|
* @return integer indicating success or failure in any of the
|
||||||
|
* preceding steps. If no steps were taken, the result is success.
|
||||||
|
*
|
||||||
|
* @retval 1 success
|
||||||
|
* @retval 0 test failure
|
||||||
|
* @retval <0 syntax error unexpected error
|
||||||
|
*/
|
||||||
|
int test_oneliner_fini (struct oneliner_ctx *ctx);
|
||||||
|
|
||||||
|
#endif
|
|
@ -170,7 +170,7 @@ CU_Test(ddsc_topic_create, desc_null, .init=ddsc_topic_init, .fini=ddsc_topic_fi
|
||||||
|
|
||||||
|
|
||||||
CU_TheoryDataPoints(ddsc_topic_create, invalid_names) = {
|
CU_TheoryDataPoints(ddsc_topic_create, invalid_names) = {
|
||||||
CU_DataPoints(char *, NULL, "", "mi-dle", "-start", "end-", "1st", "Thus$", "pl+s", "t(4)"),
|
CU_DataPoints(char *, NULL, "", "mi-dle", "-start", "end-", "1st", "Thus$", "pl+s", "t(4)", "DCPSmytopic"),
|
||||||
};
|
};
|
||||||
CU_Theory((char *name), ddsc_topic_create, invalid_names, .init=ddsc_topic_init, .fini=ddsc_topic_fini)
|
CU_Theory((char *name), ddsc_topic_create, invalid_names, .init=ddsc_topic_init, .fini=ddsc_topic_fini)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,11 +18,18 @@ PREPEND(srcs_ddsi "${CMAKE_CURRENT_LIST_DIR}/src"
|
||||||
ddsi_raweth.c
|
ddsi_raweth.c
|
||||||
ddsi_ipaddr.c
|
ddsi_ipaddr.c
|
||||||
ddsi_mcgroup.c
|
ddsi_mcgroup.c
|
||||||
|
ddsi_security_util.c
|
||||||
|
ddsi_security_omg.c
|
||||||
ddsi_portmapping.c
|
ddsi_portmapping.c
|
||||||
|
ddsi_handshake.c
|
||||||
ddsi_serdata.c
|
ddsi_serdata.c
|
||||||
ddsi_serdata_default.c
|
ddsi_serdata_default.c
|
||||||
|
ddsi_serdata_pserop.c
|
||||||
|
ddsi_serdata_plist.c
|
||||||
ddsi_sertopic.c
|
ddsi_sertopic.c
|
||||||
ddsi_sertopic_default.c
|
ddsi_sertopic_default.c
|
||||||
|
ddsi_sertopic_pserop.c
|
||||||
|
ddsi_sertopic_plist.c
|
||||||
ddsi_iid.c
|
ddsi_iid.c
|
||||||
ddsi_tkmap.c
|
ddsi_tkmap.c
|
||||||
ddsi_vendor.c
|
ddsi_vendor.c
|
||||||
|
@ -81,10 +88,15 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
|
||||||
ddsi_ipaddr.h
|
ddsi_ipaddr.h
|
||||||
ddsi_mcgroup.h
|
ddsi_mcgroup.h
|
||||||
ddsi_plist_generic.h
|
ddsi_plist_generic.h
|
||||||
|
ddsi_security_util.h
|
||||||
|
ddsi_security_omg.h
|
||||||
ddsi_portmapping.h
|
ddsi_portmapping.h
|
||||||
|
ddsi_handshake.h
|
||||||
ddsi_serdata.h
|
ddsi_serdata.h
|
||||||
ddsi_sertopic.h
|
ddsi_sertopic.h
|
||||||
ddsi_serdata_default.h
|
ddsi_serdata_default.h
|
||||||
|
ddsi_serdata_pserop.h
|
||||||
|
ddsi_serdata_plist.h
|
||||||
ddsi_iid.h
|
ddsi_iid.h
|
||||||
ddsi_tkmap.h
|
ddsi_tkmap.h
|
||||||
ddsi_vendor.h
|
ddsi_vendor.h
|
||||||
|
@ -92,6 +104,7 @@ PREPEND(hdrs_private_ddsi "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
|
||||||
ddsi_builtin_topic_if.h
|
ddsi_builtin_topic_if.h
|
||||||
ddsi_rhc.h
|
ddsi_rhc.h
|
||||||
ddsi_guid.h
|
ddsi_guid.h
|
||||||
|
ddsi_keyhash.h
|
||||||
ddsi_entity_index.h
|
ddsi_entity_index.h
|
||||||
ddsi_deadline.h
|
ddsi_deadline.h
|
||||||
ddsi_deliver_locally.h
|
ddsi_deliver_locally.h
|
||||||
|
@ -142,6 +155,19 @@ endif()
|
||||||
target_sources(ddsc
|
target_sources(ddsc
|
||||||
PRIVATE ${srcs_ddsi} ${hdrs_private_ddsi})
|
PRIVATE ${srcs_ddsi} ${hdrs_private_ddsi})
|
||||||
|
|
||||||
|
if(ENABLE_SECURITY)
|
||||||
|
PREPEND(security_srcs "${CMAKE_CURRENT_LIST_DIR}/src"
|
||||||
|
ddsi_security_msg.c
|
||||||
|
ddsi_security_exchange.c)
|
||||||
|
|
||||||
|
PREPEND(security_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/dds/ddsi"
|
||||||
|
ddsi_security_msg.h
|
||||||
|
ddsi_security_exchange.h)
|
||||||
|
|
||||||
|
target_sources(ddsc
|
||||||
|
PRIVATE ${security_srcs} ${security_hdrs})
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(ddsc
|
target_include_directories(ddsc
|
||||||
PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include")
|
PRIVATE "${CMAKE_CURRENT_LIST_DIR}/include")
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@ struct ddsi_tran_factory;
|
||||||
struct ddsrt_thread_pool_s;
|
struct ddsrt_thread_pool_s;
|
||||||
struct debug_monitor;
|
struct debug_monitor;
|
||||||
struct ddsi_tkmap;
|
struct ddsi_tkmap;
|
||||||
|
struct dds_security_context;
|
||||||
|
struct dds_security_match_index;
|
||||||
|
struct ddsi_hsadmin;
|
||||||
|
|
||||||
typedef struct config_in_addr_node {
|
typedef struct config_in_addr_node {
|
||||||
nn_locator_t loc;
|
nn_locator_t loc;
|
||||||
|
@ -258,6 +261,12 @@ struct ddsi_domaingv {
|
||||||
dds_qos_t spdp_endpoint_xqos;
|
dds_qos_t spdp_endpoint_xqos;
|
||||||
dds_qos_t builtin_endpoint_xqos_rd;
|
dds_qos_t builtin_endpoint_xqos_rd;
|
||||||
dds_qos_t builtin_endpoint_xqos_wr;
|
dds_qos_t builtin_endpoint_xqos_wr;
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
dds_qos_t builtin_volatile_xqos_rd;
|
||||||
|
dds_qos_t builtin_volatile_xqos_wr;
|
||||||
|
dds_qos_t builtin_stateless_xqos_rd;
|
||||||
|
dds_qos_t builtin_stateless_xqos_wr;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* SPDP packets get very special treatment (they're the only packets
|
/* SPDP packets get very special treatment (they're the only packets
|
||||||
we accept from writers we don't know) and have their very own
|
we accept from writers we don't know) and have their very own
|
||||||
|
@ -285,8 +294,18 @@ struct ddsi_domaingv {
|
||||||
transmit queue*/
|
transmit queue*/
|
||||||
struct serdatapool *serpool;
|
struct serdatapool *serpool;
|
||||||
struct nn_xmsgpool *xmsgpool;
|
struct nn_xmsgpool *xmsgpool;
|
||||||
struct ddsi_sertopic *plist_topic; /* used for all discovery data */
|
struct ddsi_sertopic *spdp_topic; /* key = participant GUID */
|
||||||
struct ddsi_sertopic *rawcdr_topic; /* used for participant message data */
|
struct ddsi_sertopic *sedp_reader_topic; /* key = endpoint GUID */
|
||||||
|
struct ddsi_sertopic *sedp_writer_topic; /* key = endpoint GUID */
|
||||||
|
struct ddsi_sertopic *pmd_topic; /* participant message data */
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct ddsi_sertopic *spdp_secure_topic; /* key = participant GUID */
|
||||||
|
struct ddsi_sertopic *sedp_reader_secure_topic; /* key = endpoint GUID */
|
||||||
|
struct ddsi_sertopic *sedp_writer_secure_topic; /* key = endpoint GUID */
|
||||||
|
struct ddsi_sertopic *pmd_secure_topic; /* participant message data */
|
||||||
|
struct ddsi_sertopic *pgm_stateless_topic; /* participant generic message */
|
||||||
|
struct ddsi_sertopic *pgm_volatile_topic; /* participant generic message */
|
||||||
|
#endif
|
||||||
|
|
||||||
ddsrt_mutex_t sendq_lock;
|
ddsrt_mutex_t sendq_lock;
|
||||||
ddsrt_cond_t sendq_cond;
|
ddsrt_cond_t sendq_cond;
|
||||||
|
@ -306,6 +325,14 @@ struct ddsi_domaingv {
|
||||||
|
|
||||||
ddsrt_mutex_t sertopics_lock;
|
ddsrt_mutex_t sertopics_lock;
|
||||||
struct ddsrt_hh *sertopics;
|
struct ddsrt_hh *sertopics;
|
||||||
|
|
||||||
|
/* security globals */
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct dds_security_context *security_context;
|
||||||
|
struct ddsi_hsadmin *hsadmin;
|
||||||
|
bool handshake_include_optional;
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
|
|
|
@ -112,6 +112,7 @@ struct entidx_enum_proxy_reader { struct entidx_enum st; };
|
||||||
|
|
||||||
void entidx_enum_init (struct entidx_enum *st, const struct entity_index *ei, enum entity_kind kind) ddsrt_nonnull_all;
|
void entidx_enum_init (struct entidx_enum *st, const struct entity_index *ei, enum entity_kind kind) ddsrt_nonnull_all;
|
||||||
void entidx_enum_init_topic (struct entidx_enum *st, const struct entity_index *gh, enum entity_kind kind, const char *topic, struct match_entities_range_key *max) ddsrt_nonnull_all;
|
void entidx_enum_init_topic (struct entidx_enum *st, const struct entity_index *gh, enum entity_kind kind, const char *topic, struct match_entities_range_key *max) ddsrt_nonnull_all;
|
||||||
|
void entidx_enum_init_topic_w_prefix (struct entidx_enum *st, const struct entity_index *ei, enum entity_kind kind, const char *topic, const ddsi_guid_prefix_t *prefix, struct match_entities_range_key *max) ddsrt_nonnull_all;
|
||||||
void *entidx_enum_next_max (struct entidx_enum *st, const struct match_entities_range_key *max) ddsrt_nonnull_all;
|
void *entidx_enum_next_max (struct entidx_enum *st, const struct match_entities_range_key *max) ddsrt_nonnull_all;
|
||||||
void *entidx_enum_next (struct entidx_enum *st) ddsrt_nonnull_all;
|
void *entidx_enum_next (struct entidx_enum *st) ddsrt_nonnull_all;
|
||||||
void entidx_enum_fini (struct entidx_enum *st) ddsrt_nonnull_all;
|
void entidx_enum_fini (struct entidx_enum *st) ddsrt_nonnull_all;
|
||||||
|
|
226
src/core/ddsi/include/dds/ddsi/ddsi_handshake.h
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSI_HANDSHAKE_H
|
||||||
|
#define DDSI_HANDSHAKE_H
|
||||||
|
|
||||||
|
#include "dds/ddsi/q_entity.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct participant;
|
||||||
|
struct proxy_participant;
|
||||||
|
struct ddsi_handshake;
|
||||||
|
struct dssi_hsadmin;
|
||||||
|
|
||||||
|
enum ddsi_handshake_state {
|
||||||
|
STATE_HANDSHAKE_IN_PROGRESS,
|
||||||
|
STATE_HANDSHAKE_TIMED_OUT,
|
||||||
|
STATE_HANDSHAKE_FAILED,
|
||||||
|
STATE_HANDSHAKE_PROCESSED,
|
||||||
|
STATE_HANDSHAKE_SEND_TOKENS,
|
||||||
|
STATE_HANDSHAKE_OK
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The handshake will not use the related handshake object after this callback
|
||||||
|
* was executed. This means that it can be deleted in this callback. */
|
||||||
|
typedef void (*ddsi_handshake_end_cb_t)(
|
||||||
|
struct ddsi_handshake *handshake,
|
||||||
|
struct participant *pp,
|
||||||
|
struct proxy_participant *proxypp,
|
||||||
|
enum ddsi_handshake_state result);
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
|
||||||
|
#include "dds/ddsi/ddsi_security_msg.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release the handshake.
|
||||||
|
*
|
||||||
|
* This function will decrement the refcount associated with the handshake
|
||||||
|
* and delete the handshake when the refcount becomes 0.
|
||||||
|
*
|
||||||
|
* @param[in] handshake The handshake.
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_release(struct ddsi_handshake *handshake);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle an authentication handshake message received from the remote participant.
|
||||||
|
*
|
||||||
|
* During the authentication phase handshake messages are being exchanged between the local and
|
||||||
|
* the remote participant. THis function will handle a handshake message received from a remote
|
||||||
|
* participant.
|
||||||
|
*
|
||||||
|
* @param[in] handshake The handshake.
|
||||||
|
* @param[in] pp The local participant.
|
||||||
|
* @param[in] proxypp The remote participant.
|
||||||
|
* @param[in] msg The handshake message received.
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_handle_message(struct ddsi_handshake *handshake, const struct participant *pp, const struct proxy_participant *proxypp, const struct nn_participant_generic_message *msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Notify the handshake that crypto tokens have been received.
|
||||||
|
*
|
||||||
|
* The handshake could be finished at one end while the other side has not yet processed the
|
||||||
|
* final handshake messages. The arrival of crypto tokens signals that the other side has also finished
|
||||||
|
* processing the handshake. This function is used to signal the handshake that crypto tokens have been
|
||||||
|
* received.
|
||||||
|
*
|
||||||
|
* @param[in] handshake The handshake.
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_crypto_tokens_received(struct ddsi_handshake *handshake);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the shared secret handle.
|
||||||
|
*
|
||||||
|
* During the handshake a shared secret is established which is used to encrypt
|
||||||
|
* and decrypt the crypto token exchange messages. This function will return a
|
||||||
|
* handle to the shared secret which will be passed to the crypto plugin to
|
||||||
|
* determine the session keys used for the echange of the the crypto tokens.
|
||||||
|
*
|
||||||
|
* @param[in] handshake The handshake.
|
||||||
|
*
|
||||||
|
* @returns handle to the shared sercet.
|
||||||
|
*/
|
||||||
|
int64_t ddsi_handshake_get_shared_secret(const struct ddsi_handshake *handshake);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the handshake handle
|
||||||
|
*
|
||||||
|
* This function returns the handshake handle that was returned by the authentication plugin
|
||||||
|
* when starting the handshake.
|
||||||
|
*
|
||||||
|
* @param[in] handshake The handshake.
|
||||||
|
*
|
||||||
|
* @returns The handshake handle.
|
||||||
|
*/
|
||||||
|
int64_t ddsi_handshake_get_handle(const struct ddsi_handshake *handshake);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create and start the handshake for the participants
|
||||||
|
*
|
||||||
|
* This function will create a handshake for the specified local
|
||||||
|
* and remote participants when it does not yet exists. It will start the
|
||||||
|
* handshake procedure by calling the corresponding functions of the authentication plugin.
|
||||||
|
* The callback function is called by the handshake when to report events,
|
||||||
|
* for example to indicate that the handshake has finished or has failed.
|
||||||
|
*
|
||||||
|
* @param[in] pp The local participant.
|
||||||
|
* @param[in] proxypp The remote participant.
|
||||||
|
* @param[in] callback The callback function.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_register(struct participant *pp, struct proxy_participant *proxypp, ddsi_handshake_end_cb_t callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove the handshake associated with the specified participants.
|
||||||
|
*
|
||||||
|
* This function will remove the handshake from the handshake administation and release
|
||||||
|
* the handshake. When the handshake argument is not specified the handshake is searched
|
||||||
|
* in the handshake administation.
|
||||||
|
*
|
||||||
|
* @param[in] pp The local participant.
|
||||||
|
* @param[in] proxypp The remote participant.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_remove(struct participant *pp, struct proxy_participant *proxypp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Searches for the handshake associated with the specified participants
|
||||||
|
*
|
||||||
|
* This function will search through the handshake administration to find the handshake
|
||||||
|
* corresponding the to specified local and remote participant.
|
||||||
|
*
|
||||||
|
* @param[in] pp The local participant.
|
||||||
|
* @param[in] proxypp The remote participant.
|
||||||
|
*
|
||||||
|
* @returns The handshake
|
||||||
|
*/
|
||||||
|
struct ddsi_handshake * ddsi_handshake_find(struct participant *pp, struct proxy_participant *proxypp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Searches for the handshake associated with the specified participants
|
||||||
|
*
|
||||||
|
* This function will search through the handshake administration to find the handshake
|
||||||
|
* corresponding the to specified local and remote participant.
|
||||||
|
*
|
||||||
|
* @param[in] pp The local participant.
|
||||||
|
* @param[in] proxypp The remote participant.
|
||||||
|
*
|
||||||
|
* @returns The handshake
|
||||||
|
*/
|
||||||
|
struct ddsi_handshake * ddsi_handshake_find(struct participant *pp, struct proxy_participant *proxypp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the handshake administration
|
||||||
|
*
|
||||||
|
* @param[in] gv The global parameters
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_admin_init(struct ddsi_domaingv *gv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop handshake background processing.
|
||||||
|
*
|
||||||
|
* @param[in] gv The global parameters
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_admin_stop(struct ddsi_domaingv *gv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialze the handshake administration.
|
||||||
|
*
|
||||||
|
* @param[in] gv The global parameters
|
||||||
|
*/
|
||||||
|
void ddsi_handshake_admin_deinit(struct ddsi_domaingv *gv);
|
||||||
|
|
||||||
|
#else /* DDSI_INCLUDE_SECURITY */
|
||||||
|
|
||||||
|
#include "dds/ddsi/q_unused.h"
|
||||||
|
|
||||||
|
inline void ddsi_handshake_register(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(ddsi_handshake_end_cb_t callback))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ddsi_handshake_release(UNUSED_ARG(struct ddsi_handshake *handshake))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ddsi_handshake_crypto_tokens_received(UNUSED_ARG(struct ddsi_handshake *handshake))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t ddsi_handshake_get_shared_secret(UNUSED_ARG(const struct ddsi_handshake *handshake))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t ddsi_handshake_get_handle(UNUSED_ARG(const struct ddsi_handshake *handshake))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ddsi_handshake_remove(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp), UNUSED_ARG(struct ddsi_handshake *handshake))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline struct ddsi_handshake * ddsi_handshake_find(UNUSED_ARG(struct participant *pp), UNUSED_ARG(struct proxy_participant *proxypp))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* DDSI_INCLUDE_SECURITY */
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DDSI_HANDSHAKE_H */
|
27
src/core/ddsi/include/dds/ddsi/ddsi_keyhash.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2020 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSI_KEYHASH_H
|
||||||
|
#define DDSI_KEYHASH_H
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct ddsi_keyhash {
|
||||||
|
unsigned char value[16];
|
||||||
|
} ddsi_keyhash_t;
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "dds/ddsi/q_feature_check.h"
|
#include "dds/ddsi/q_feature_check.h"
|
||||||
#include "dds/ddsi/ddsi_xqos.h"
|
#include "dds/ddsi/ddsi_xqos.h"
|
||||||
|
#include "dds/ddsi/ddsi_keyhash.h"
|
||||||
#include "dds/ddsi/ddsi_tran.h" /* FIXME: eliminate */
|
#include "dds/ddsi/ddsi_tran.h" /* FIXME: eliminate */
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
|
@ -51,11 +52,15 @@ extern "C" {
|
||||||
#ifdef DDSI_INCLUDE_SSM
|
#ifdef DDSI_INCLUDE_SSM
|
||||||
#define PP_READER_FAVOURS_SSM ((uint64_t)1 << 29)
|
#define PP_READER_FAVOURS_SSM ((uint64_t)1 << 29)
|
||||||
#endif
|
#endif
|
||||||
|
#define PP_DOMAIN_ID ((uint64_t)1 << 30)
|
||||||
|
#define PP_DOMAIN_TAG ((uint64_t)1 << 31)
|
||||||
/* Security extensions. */
|
/* Security extensions. */
|
||||||
#define PP_IDENTITY_TOKEN ((uint64_t)1 << 30)
|
#define PP_IDENTITY_TOKEN ((uint64_t)1 << 32)
|
||||||
#define PP_PERMISSIONS_TOKEN ((uint64_t)1 << 31)
|
#define PP_PERMISSIONS_TOKEN ((uint64_t)1 << 33)
|
||||||
#define PP_DOMAIN_ID ((uint64_t)1 << 32)
|
#define PP_ENDPOINT_SECURITY_INFO ((uint64_t)1 << 34)
|
||||||
#define PP_DOMAIN_TAG ((uint64_t)1 << 33)
|
#define PP_PARTICIPANT_SECURITY_INFO ((uint64_t)1 << 35)
|
||||||
|
#define PP_IDENTITY_STATUS_TOKEN ((uint64_t)1 << 36)
|
||||||
|
#define PP_DATA_TAGS ((uint64_t)1 << 37)
|
||||||
/* Set for unrecognized parameters that are in the reserved space or
|
/* Set for unrecognized parameters that are in the reserved space or
|
||||||
in our own vendor-specific space that have the
|
in our own vendor-specific space that have the
|
||||||
PID_UNRECOGNIZED_INCOMPATIBLE_FLAG set (see DDSI 2.1 9.6.2.2.1) */
|
PID_UNRECOGNIZED_INCOMPATIBLE_FLAG set (see DDSI 2.1 9.6.2.2.1) */
|
||||||
|
@ -93,10 +98,21 @@ typedef uint32_t nn_ipv4address_t;
|
||||||
|
|
||||||
typedef uint32_t nn_port_t;
|
typedef uint32_t nn_port_t;
|
||||||
|
|
||||||
typedef struct nn_keyhash {
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
unsigned char value[16];
|
typedef struct nn_tag {
|
||||||
} nn_keyhash_t;
|
char *name;
|
||||||
|
char *value;
|
||||||
|
} nn_tag_t;
|
||||||
|
|
||||||
|
typedef struct nn_tagseq {
|
||||||
|
uint32_t n;
|
||||||
|
nn_tag_t *tags;
|
||||||
|
} nn_tagseq_t;
|
||||||
|
|
||||||
|
typedef struct nn_datatags {
|
||||||
|
nn_tagseq_t tags;
|
||||||
|
} nn_datatags_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DDSI_INCLUDE_SSM
|
#ifdef DDSI_INCLUDE_SSM
|
||||||
typedef struct nn_reader_favours_ssm {
|
typedef struct nn_reader_favours_ssm {
|
||||||
|
@ -104,6 +120,57 @@ typedef struct nn_reader_favours_ssm {
|
||||||
} nn_reader_favours_ssm_t;
|
} nn_reader_favours_ssm_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
typedef struct nn_dataholder
|
||||||
|
{
|
||||||
|
char *class_id;
|
||||||
|
dds_propertyseq_t properties;
|
||||||
|
dds_binarypropertyseq_t binary_properties;
|
||||||
|
} nn_dataholder_t;
|
||||||
|
|
||||||
|
typedef struct nn_dataholderseq {
|
||||||
|
uint32_t n;
|
||||||
|
nn_dataholder_t *tags;
|
||||||
|
} nn_dataholderseq_t;
|
||||||
|
|
||||||
|
typedef nn_dataholder_t nn_token_t;
|
||||||
|
|
||||||
|
/* Used for both nn_participant_security_info and nn_endpoint_security_info. */
|
||||||
|
typedef struct nn_security_info
|
||||||
|
{
|
||||||
|
uint32_t security_attributes;
|
||||||
|
uint32_t plugin_security_attributes;
|
||||||
|
} nn_security_info_t;
|
||||||
|
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_READ_PROTECTED (1u << 0)
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_WRITE_PROTECTED (1u << 1)
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_PROTECTED (1u << 2)
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_PROTECTED (1u << 3)
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_PAYLOAD_PROTECTED (1u << 4)
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_KEY_PROTECTED (1u << 5)
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_PROTECTED (1u << 6)
|
||||||
|
#define NN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_VALID (1u << 31)
|
||||||
|
|
||||||
|
#define NN_PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ENCRYPTED (1u << 0)
|
||||||
|
#define NN_PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_PAYLOAD_ENCRYPTED (1u << 1)
|
||||||
|
#define NN_PLUGIN_ENDPOINT_SECURITY_ATTRIBUTES_FLAG_IS_SUBMESSAGE_ORIGIN_AUTHENTICATED (1u << 2)
|
||||||
|
|
||||||
|
#define NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_PROTECTED (1u << 0)
|
||||||
|
#define NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_PROTECTED (1u << 1)
|
||||||
|
#define NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_PROTECTED (1u << 2)
|
||||||
|
#define NN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_VALID (1u << 31)
|
||||||
|
|
||||||
|
#define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_ENCRYPTED (1u << 0)
|
||||||
|
#define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_ENCRYPTED (1u << 1)
|
||||||
|
#define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_ENCRYPTED (1u << 2)
|
||||||
|
#define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_RTPS_AUTHENTICATED (1u << 3)
|
||||||
|
#define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_DISCOVERY_AUTHENTICATED (1u << 4)
|
||||||
|
#define NN_PLUGIN_PARTICIPANT_SECURITY_ATTRIBUTES_FLAG_IS_LIVELINESS_AUTHENTICATED (1u << 5)
|
||||||
|
#else
|
||||||
|
struct nn_security_info;
|
||||||
|
typedef struct nn_security_info nn_security_info_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct nn_adlink_participant_version_info
|
typedef struct nn_adlink_participant_version_info
|
||||||
{
|
{
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
@ -142,11 +209,19 @@ typedef struct ddsi_plist {
|
||||||
uint32_t builtin_endpoint_set;
|
uint32_t builtin_endpoint_set;
|
||||||
/* int type_max_size_serialized; */
|
/* int type_max_size_serialized; */
|
||||||
char *entity_name;
|
char *entity_name;
|
||||||
nn_keyhash_t keyhash;
|
ddsi_keyhash_t keyhash;
|
||||||
uint32_t statusinfo;
|
uint32_t statusinfo;
|
||||||
nn_adlink_participant_version_info_t adlink_participant_version_info;
|
nn_adlink_participant_version_info_t adlink_participant_version_info;
|
||||||
char *type_description;
|
char *type_description;
|
||||||
nn_sequence_number_t coherent_set_seqno;
|
nn_sequence_number_t coherent_set_seqno;
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
nn_token_t identity_token;
|
||||||
|
nn_token_t permissions_token;
|
||||||
|
nn_security_info_t endpoint_security_info;
|
||||||
|
nn_security_info_t participant_security_info;
|
||||||
|
nn_token_t identity_status_token;
|
||||||
|
nn_datatags_t data_tags;
|
||||||
|
#endif
|
||||||
#ifdef DDSI_INCLUDE_SSM
|
#ifdef DDSI_INCLUDE_SSM
|
||||||
nn_reader_favours_ssm_t reader_favours_ssm;
|
nn_reader_favours_ssm_t reader_favours_ssm;
|
||||||
#endif
|
#endif
|
||||||
|
@ -225,6 +300,7 @@ DDS_EXPORT void ddsi_plist_fini (ddsi_plist_t *ps);
|
||||||
DDS_EXPORT void ddsi_plist_fini_mask (ddsi_plist_t *plist, uint64_t pmask, uint64_t qmask);
|
DDS_EXPORT void ddsi_plist_fini_mask (ddsi_plist_t *plist, uint64_t pmask, uint64_t qmask);
|
||||||
DDS_EXPORT void ddsi_plist_unalias (ddsi_plist_t *plist);
|
DDS_EXPORT void ddsi_plist_unalias (ddsi_plist_t *plist);
|
||||||
DDS_EXPORT void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted);
|
DDS_EXPORT void ddsi_plist_addtomsg (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted);
|
||||||
|
DDS_EXPORT void ddsi_plist_addtomsg_bo (struct nn_xmsg *m, const ddsi_plist_t *ps, uint64_t pwanted, uint64_t qwanted, bool be);
|
||||||
DDS_EXPORT void ddsi_plist_init_default_participant (ddsi_plist_t *plist);
|
DDS_EXPORT void ddsi_plist_init_default_participant (ddsi_plist_t *plist);
|
||||||
DDS_EXPORT void ddsi_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const ddsi_plist_t *x, const ddsi_plist_t *y, uint64_t pmask, uint64_t qmask);
|
DDS_EXPORT void ddsi_plist_delta (uint64_t *pdelta, uint64_t *qdelta, const ddsi_plist_t *x, const ddsi_plist_t *y, uint64_t pmask, uint64_t qmask);
|
||||||
DDS_EXPORT void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const ddsi_plist_t *plist);
|
DDS_EXPORT void ddsi_plist_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const ddsi_plist_t *plist);
|
||||||
|
@ -235,7 +311,7 @@ struct nn_rsample_info;
|
||||||
struct nn_rdata;
|
struct nn_rdata;
|
||||||
|
|
||||||
DDS_EXPORT unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const ddsi_plist_src_t *src);
|
DDS_EXPORT unsigned char *ddsi_plist_quickscan (struct nn_rsample_info *dest, const struct nn_rmsg *rmsg, const ddsi_plist_src_t *src);
|
||||||
DDS_EXPORT const unsigned char *ddsi_plist_findparam_native_unchecked (const void *src, nn_parameterid_t pid);
|
DDS_EXPORT dds_return_t ddsi_plist_findparam_checking (const void *buf, size_t bufsz, uint16_t encoding, nn_parameterid_t needle, void **needlep, size_t *needlesz);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "dds/export.h"
|
#include "dds/export.h"
|
||||||
|
|
||||||
#include "dds/ddsrt/attributes.h"
|
#include "dds/ddsrt/attributes.h"
|
||||||
|
#include "dds/ddsrt/retcode.h"
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -34,6 +35,7 @@ enum pserop {
|
||||||
Xi, Xix2, Xix3, Xix4, /* int32_t, 1 .. 4 in a row */
|
Xi, Xix2, Xix3, Xix4, /* int32_t, 1 .. 4 in a row */
|
||||||
Xu, Xux2, Xux3, Xux4, Xux5, /* uint32_t, 1 .. 5 in a row */
|
Xu, Xux2, Xux3, Xux4, Xux5, /* uint32_t, 1 .. 5 in a row */
|
||||||
XD, XDx2, /* duration, 1 .. 2 in a row */
|
XD, XDx2, /* duration, 1 .. 2 in a row */
|
||||||
|
Xl, /* int64_t */
|
||||||
Xo, Xox2, /* octet, 1 .. 2 in a row */
|
Xo, Xox2, /* octet, 1 .. 2 in a row */
|
||||||
Xb, Xbx2, /* boolean, 1 .. 2 in a row */
|
Xb, Xbx2, /* boolean, 1 .. 2 in a row */
|
||||||
XbCOND, /* boolean: compare to ignore remainder if false (for use_... flags) */
|
XbCOND, /* boolean: compare to ignore remainder if false (for use_... flags) */
|
||||||
|
@ -44,21 +46,14 @@ enum pserop {
|
||||||
Xopt, /* remainder is optional on deser, 0-init if not present */
|
Xopt, /* remainder is optional on deser, 0-init if not present */
|
||||||
} ddsrt_attribute_packed;
|
} ddsrt_attribute_packed;
|
||||||
|
|
||||||
inline bool pserop_seralign_is_1 (enum pserop op) {
|
|
||||||
/* NB: XbPROP is never serialized, so its alignment is irrelevant. If ever there
|
|
||||||
is a need to allow calling this function when op = XbPROP, it needs to be changed
|
|
||||||
to taking the address of the pserop, and in that case inspect the following
|
|
||||||
operator */
|
|
||||||
assert (op != XbPROP && op != Xopt && op != XSTOP);
|
|
||||||
return (op >= Xo && op <= XK);
|
|
||||||
}
|
|
||||||
|
|
||||||
DDS_EXPORT void plist_fini_generic (void * __restrict dst, const enum pserop *desc, bool aliased);
|
DDS_EXPORT void plist_fini_generic (void * __restrict dst, const enum pserop *desc, bool aliased);
|
||||||
DDS_EXPORT dds_return_t plist_deser_generic (void * __restrict dst, const void * __restrict src, size_t srcsize, bool bswap, const enum pserop * __restrict desc);
|
DDS_EXPORT dds_return_t plist_deser_generic (void * __restrict dst, const void * __restrict src, size_t srcsize, bool bswap, const enum pserop * __restrict desc);
|
||||||
DDS_EXPORT dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc);
|
DDS_EXPORT dds_return_t plist_ser_generic (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc);
|
||||||
|
DDS_EXPORT dds_return_t plist_ser_generic_be (void **dst, size_t *dstsize, const void *src, const enum pserop * __restrict desc);
|
||||||
DDS_EXPORT dds_return_t plist_unalias_generic (void * __restrict dst, const enum pserop * __restrict desc);
|
DDS_EXPORT dds_return_t plist_unalias_generic (void * __restrict dst, const enum pserop * __restrict desc);
|
||||||
DDS_EXPORT bool plist_equal_generic (const void *srcx, const void *srcy, const enum pserop * __restrict desc);
|
DDS_EXPORT bool plist_equal_generic (const void *srcx, const void *srcy, const enum pserop * __restrict desc);
|
||||||
DDS_EXPORT size_t plist_memsize_generic (const enum pserop * __restrict desc);
|
DDS_EXPORT size_t plist_memsize_generic (const enum pserop * __restrict desc);
|
||||||
|
DDS_EXPORT size_t plist_print_generic (char * __restrict buf, size_t bufsize, const void * __restrict src, const enum pserop * __restrict desc);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,12 @@
|
||||||
#ifndef DDSI_PMD_H
|
#ifndef DDSI_PMD_H
|
||||||
#define DDSI_PMD_H
|
#define DDSI_PMD_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include "dds/ddsrt/time.h"
|
#include "dds/ddsrt/time.h"
|
||||||
|
#include "dds/ddsi/ddsi_serdata.h"
|
||||||
|
#include "dds/ddsi/ddsi_plist_generic.h"
|
||||||
|
#include "dds/ddsi/ddsi_guid.h"
|
||||||
|
#include "dds/ddsi/ddsi_xqos.h"
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -25,9 +30,20 @@ struct nn_xpack;
|
||||||
struct participant;
|
struct participant;
|
||||||
struct receiver_state;
|
struct receiver_state;
|
||||||
|
|
||||||
|
typedef struct ParticipantMessageData {
|
||||||
|
ddsi_guid_prefix_t participantGuidPrefix;
|
||||||
|
uint32_t kind; /* really 4 octets */
|
||||||
|
ddsi_octetseq_t value;
|
||||||
|
} ParticipantMessageData_t;
|
||||||
|
|
||||||
|
extern const enum pserop participant_message_data_ops[];
|
||||||
|
extern size_t participant_message_data_nops;
|
||||||
|
extern const enum pserop participant_message_data_ops_key[];
|
||||||
|
extern size_t participant_message_data_nops_key;
|
||||||
|
|
||||||
void write_pmd_message_guid (struct ddsi_domaingv * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind);
|
void write_pmd_message_guid (struct ddsi_domaingv * const gv, struct ddsi_guid *pp_guid, unsigned pmd_kind);
|
||||||
void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind);
|
void write_pmd_message (struct thread_state1 * const ts1, struct nn_xpack *xp, struct participant *pp, unsigned pmd_kind);
|
||||||
void handle_pmd_message (const struct receiver_state *rst, ddsrt_wctime_t timestamp, uint32_t statusinfo, const void *vdata, uint32_t len);
|
void handle_pmd_message (const struct receiver_state *rst, struct ddsi_serdata *sample_common);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
49
src/core/ddsi/include/dds/ddsi/ddsi_security_exchange.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSI_SECURITY_EXCHANGE_H
|
||||||
|
#define DDSI_SECURITY_EXCHANGE_H
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "dds/ddsi/q_rtps.h"
|
||||||
|
#include "dds/ddsi/q_radmin.h"
|
||||||
|
#include "dds/ddsi/q_entity.h"
|
||||||
|
#include "dds/ddsi/ddsi_security_msg.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define GMCLASSID_SECURITY_PARTICIPANT_CRYPTO_TOKENS "dds.sec.participant_crypto_tokens"
|
||||||
|
#define GMCLASSID_SECURITY_DATAWRITER_CRYPTO_TOKENS "dds.sec.datawriter_crypto_tokens"
|
||||||
|
#define GMCLASSID_SECURITY_DATAREADER_CRYPTO_TOKENS "dds.sec.datareader_crypto_tokens"
|
||||||
|
|
||||||
|
bool write_auth_handshake_message(const struct participant *pp, const struct proxy_participant *proxypp, nn_dataholderseq_t *mdata, bool request, const nn_message_identity_t *related_message_id);
|
||||||
|
void handle_auth_handshake_message(const struct receiver_state *rst, ddsi_entityid_t wr_entity_id, struct ddsi_serdata *sample);
|
||||||
|
void handle_crypto_exchange_message(const struct receiver_state *rst, struct ddsi_serdata *sample);
|
||||||
|
void auth_get_serialized_participant_data(struct participant *pp, ddsi_octetseq_t *seq);
|
||||||
|
bool write_crypto_participant_tokens(const struct participant *pp, const struct proxy_participant *proxypp, const nn_dataholderseq_t *tokens);
|
||||||
|
bool write_crypto_writer_tokens(const struct writer *wr, const struct proxy_reader *prd, const nn_dataholderseq_t *tokens);
|
||||||
|
bool write_crypto_reader_tokens(const struct reader *rd, const struct proxy_writer *pwr, const nn_dataholderseq_t *tokens);
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* DDSI_INCLUDE_SECURITY */
|
||||||
|
|
||||||
|
#define volatile_secure_data_filter NULL
|
||||||
|
|
||||||
|
#endif /* DDSI_INCLUDE_SECURITY */
|
||||||
|
|
||||||
|
#endif /* DDSI_SECURITY_EXCHANGE_H */
|
112
src/core/ddsi/include/dds/ddsi/ddsi_security_msg.h
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSI_SECURITY_MSG_H
|
||||||
|
#define DDSI_SECURITY_MSG_H
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
|
||||||
|
#include "dds/ddsi/ddsi_plist.h"
|
||||||
|
#include "dds/ddsi/ddsi_guid.h"
|
||||||
|
#include "dds/ddsrt/retcode.h"
|
||||||
|
#include "dds/ddsi/ddsi_plist_generic.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct participant;
|
||||||
|
struct writer;
|
||||||
|
struct proxy_reader;
|
||||||
|
struct ddsi_serdata;
|
||||||
|
|
||||||
|
#define DDS_SECURITY_AUTH_REQUEST "dds.sec.auth_request"
|
||||||
|
#define DDS_SECURITY_AUTH_HANDSHAKE "dds.sec.auth"
|
||||||
|
#define DDS_SECURITY_AUTH_REQUEST_TOKEN_CLASS_ID "DDS:Auth:PKI-DH:1.0+AuthReq"
|
||||||
|
#define DDS_SECURITY_AUTH_HANDSHAKE_REQUEST_TOKEN_ID "DDS:Auth:PKI-DH:1.0+Req"
|
||||||
|
#define DDS_SECURITY_AUTH_HANDSHAKE_REPLY_TOKEN_ID "DDS:Auth:PKI-DH:1.0+Reply"
|
||||||
|
#define DDS_SECURITY_AUTH_HANDSHAKE_FINAL_TOKEN_ID "DDS:Auth:PKI-DH:1.0+Final"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct nn_message_identity {
|
||||||
|
ddsi_guid_t source_guid;
|
||||||
|
int64_t sequence_number;
|
||||||
|
} nn_message_identity_t;
|
||||||
|
|
||||||
|
typedef struct nn_participant_generic_message {
|
||||||
|
nn_message_identity_t message_identity;
|
||||||
|
nn_message_identity_t related_message_identity;
|
||||||
|
ddsi_guid_t destination_participant_guid;
|
||||||
|
ddsi_guid_t destination_endpoint_guid;
|
||||||
|
ddsi_guid_t source_endpoint_guid;
|
||||||
|
const char *message_class_id;
|
||||||
|
nn_dataholderseq_t message_data;
|
||||||
|
} nn_participant_generic_message_t;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The arguments are aliased in the resulting message structure.
|
||||||
|
* This means that the lifecycle of the arguments should be longer
|
||||||
|
* then that of the message.
|
||||||
|
*/
|
||||||
|
DDS_EXPORT void
|
||||||
|
nn_participant_generic_message_init(
|
||||||
|
nn_participant_generic_message_t *msg,
|
||||||
|
const ddsi_guid_t *wrguid,
|
||||||
|
int64_t wrseq,
|
||||||
|
const ddsi_guid_t *dstpguid,
|
||||||
|
const ddsi_guid_t *dsteguid,
|
||||||
|
const ddsi_guid_t *srceguid,
|
||||||
|
const char *classid,
|
||||||
|
const nn_dataholderseq_t *mdata,
|
||||||
|
const nn_message_identity_t *rmid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Aliased struct variables will not be freed.
|
||||||
|
*/
|
||||||
|
DDS_EXPORT void
|
||||||
|
nn_participant_generic_message_deinit(
|
||||||
|
nn_participant_generic_message_t *msg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some struct variables are aliased to the given buffer.
|
||||||
|
* This means that the lifecycle of the data buffer should be
|
||||||
|
* longer then that of the message.
|
||||||
|
*/
|
||||||
|
DDS_EXPORT dds_return_t
|
||||||
|
nn_participant_generic_message_deseralize(
|
||||||
|
nn_participant_generic_message_t *msg,
|
||||||
|
const unsigned char *data,
|
||||||
|
size_t len,
|
||||||
|
bool bswap);
|
||||||
|
|
||||||
|
DDS_EXPORT dds_return_t
|
||||||
|
nn_participant_generic_message_serialize(
|
||||||
|
const nn_participant_generic_message_t *msg,
|
||||||
|
unsigned char **data,
|
||||||
|
size_t *len);
|
||||||
|
|
||||||
|
DDS_EXPORT extern const enum pserop pserop_participant_generic_message[];
|
||||||
|
DDS_EXPORT extern const size_t pserop_participant_generic_message_nops;
|
||||||
|
|
||||||
|
DDS_EXPORT int
|
||||||
|
volatile_secure_data_filter(
|
||||||
|
struct writer *wr,
|
||||||
|
struct proxy_reader *prd,
|
||||||
|
struct ddsi_serdata *serdata);
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DDSI_SECURITY_MSG_H */
|
1418
src/core/ddsi/include/dds/ddsi/ddsi_security_omg.h
Normal file
64
src/core/ddsi/include/dds/ddsi/ddsi_security_util.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSI_SECURITY_UTIL_H
|
||||||
|
#define DDSI_SECURITY_UTIL_H
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
|
||||||
|
#include "dds/ddsi/ddsi_plist.h"
|
||||||
|
#include "dds/security/core/dds_security_utils.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void g_omg_shallow_copy_StringSeq(DDS_Security_StringSeq *dst, const ddsi_stringseq_t *src);
|
||||||
|
void g_omg_shallow_free_StringSeq(DDS_Security_StringSeq *obj);
|
||||||
|
void q_omg_copy_PropertySeq(DDS_Security_PropertySeq *dst, const dds_propertyseq_t *src);
|
||||||
|
void q_omg_shallow_copyin_PropertySeq(DDS_Security_PropertySeq *dst, const dds_propertyseq_t *src);
|
||||||
|
void q_omg_shallow_copyout_PropertySeq(dds_propertyseq_t *dst, const DDS_Security_PropertySeq *src);
|
||||||
|
void q_omg_shallow_free_PropertySeq(DDS_Security_PropertySeq *obj);
|
||||||
|
void q_omg_shallow_copyin_BinaryPropertySeq(DDS_Security_BinaryPropertySeq *dst, const dds_binarypropertyseq_t *src);
|
||||||
|
void q_omg_shallow_copyout_BinaryPropertySeq(dds_binarypropertyseq_t *dst, const DDS_Security_BinaryPropertySeq *src);
|
||||||
|
void q_omg_shallow_free_BinaryPropertySeq(DDS_Security_BinaryPropertySeq *obj);
|
||||||
|
void q_omg_shallow_copy_PropertyQosPolicy(DDS_Security_PropertyQosPolicy *dst, const dds_property_qospolicy_t *src);
|
||||||
|
void q_omg_shallow_copy_security_qos(DDS_Security_Qos *dst, const struct dds_qos *src);
|
||||||
|
void q_omg_shallow_free_PropertyQosPolicy(DDS_Security_PropertyQosPolicy *obj);
|
||||||
|
void q_omg_shallow_free_security_qos(DDS_Security_Qos *obj);
|
||||||
|
void q_omg_security_dataholder_copyin(nn_dataholder_t *dh, const DDS_Security_DataHolder *holder);
|
||||||
|
void q_omg_security_dataholder_copyout(DDS_Security_DataHolder *holder, const nn_dataholder_t *dh);
|
||||||
|
void q_omg_shallow_copyin_DataHolder(DDS_Security_DataHolder *dst, const nn_dataholder_t *src);
|
||||||
|
void q_omg_shallow_copyout_DataHolder(nn_dataholder_t *dst, const DDS_Security_DataHolder *src);
|
||||||
|
void q_omg_shallow_free_DataHolder(DDS_Security_DataHolder *obj);
|
||||||
|
void q_omg_shallow_free_nn_dataholder(nn_dataholder_t *holder);
|
||||||
|
void q_omg_shallow_copyin_DataHolderSeq(DDS_Security_DataHolderSeq *dst, const nn_dataholderseq_t *src);
|
||||||
|
void q_omg_copyin_DataHolderSeq(DDS_Security_DataHolderSeq *dst, const nn_dataholderseq_t *src);
|
||||||
|
void q_omg_shallow_copyout_DataHolderSeq(nn_dataholderseq_t *dst, const DDS_Security_DataHolderSeq *src);
|
||||||
|
void q_omg_shallow_free_DataHolderSeq(DDS_Security_DataHolderSeq *obj);
|
||||||
|
void q_omg_shallow_free_nn_dataholderseq(nn_dataholderseq_t *obj);
|
||||||
|
void q_omg_shallow_copy_ParticipantBuiltinTopicDataSecure(DDS_Security_ParticipantBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const ddsi_plist_t *plist);
|
||||||
|
void q_omg_shallow_free_ParticipantBuiltinTopicDataSecure(DDS_Security_ParticipantBuiltinTopicDataSecure *obj);
|
||||||
|
void q_omg_shallow_copy_SubscriptionBuiltinTopicDataSecure(DDS_Security_SubscriptionBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const struct dds_qos *qos, const nn_security_info_t *secinfo);
|
||||||
|
void q_omg_shallow_free_SubscriptionBuiltinTopicDataSecure(DDS_Security_SubscriptionBuiltinTopicDataSecure *obj);
|
||||||
|
void q_omg_shallow_copy_PublicationBuiltinTopicDataSecure(DDS_Security_PublicationBuiltinTopicDataSecure *dst, const ddsi_guid_t *guid, const struct dds_qos *qos, const nn_security_info_t *secinfo);
|
||||||
|
void q_omg_shallow_free_PublicationBuiltinTopicDataSecure(DDS_Security_PublicationBuiltinTopicDataSecure *obj);
|
||||||
|
void q_omg_shallow_copy_TopicBuiltinTopicData(DDS_Security_TopicBuiltinTopicData *dst, const char *topic_name, const char *type_name);
|
||||||
|
void q_omg_shallow_free_TopicBuiltinTopicData(DDS_Security_TopicBuiltinTopicData *obj);
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* DDSI_INCLUDE_SECURITY */
|
||||||
|
|
||||||
|
#endif /* DDSI_SECURITY_UTIL_H */
|
|
@ -14,13 +14,13 @@
|
||||||
|
|
||||||
#include "dds/ddsrt/sockets.h"
|
#include "dds/ddsrt/sockets.h"
|
||||||
#include "dds/ddsi/ddsi_sertopic.h"
|
#include "dds/ddsi/ddsi_sertopic.h"
|
||||||
|
#include "dds/ddsi/ddsi_keyhash.h"
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct nn_rdata;
|
struct nn_rdata;
|
||||||
struct nn_keyhash;
|
|
||||||
|
|
||||||
enum ddsi_serdata_kind {
|
enum ddsi_serdata_kind {
|
||||||
SDK_EMPTY,
|
SDK_EMPTY,
|
||||||
|
@ -64,7 +64,7 @@ typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_t) (const struct ddsi_sert
|
||||||
typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_iov_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size);
|
typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_iov_t) (const struct ddsi_sertopic *topic, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size);
|
||||||
|
|
||||||
/* Construct a serdata from a keyhash (an SDK_KEY by definition) */
|
/* Construct a serdata from a keyhash (an SDK_KEY by definition) */
|
||||||
typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash);
|
typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertopic *topic, const struct ddsi_keyhash *keyhash);
|
||||||
|
|
||||||
/* Construct a serdata from an application sample
|
/* Construct a serdata from an application sample
|
||||||
- "kind" is KEY or DATA depending on the operation invoked by the application;
|
- "kind" is KEY or DATA depending on the operation invoked by the application;
|
||||||
|
@ -134,7 +134,10 @@ typedef bool (*ddsi_serdata_eqkey_t) (const struct ddsi_serdata *a, const struct
|
||||||
returning bufsize-1) if it had to truncate) */
|
returning bufsize-1) if it had to truncate) */
|
||||||
typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size);
|
typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertopic *topic, const struct ddsi_serdata *d, char *buf, size_t size);
|
||||||
|
|
||||||
#define DDSI_SERDATA_HAS_FROM_SER_IOV 1
|
/* Add keyhash (from serdata) to buffer (forcing md5 when necessary).
|
||||||
|
- key needs to be set within serdata (can already be md5)
|
||||||
|
- buf needs to be at least 16 bytes large */
|
||||||
|
typedef void (*ddsi_serdata_get_keyhash_t) (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5);
|
||||||
|
|
||||||
struct ddsi_serdata_ops {
|
struct ddsi_serdata_ops {
|
||||||
ddsi_serdata_eqkey_t eqkey;
|
ddsi_serdata_eqkey_t eqkey;
|
||||||
|
@ -151,9 +154,12 @@ struct ddsi_serdata_ops {
|
||||||
ddsi_serdata_topicless_to_sample_t topicless_to_sample;
|
ddsi_serdata_topicless_to_sample_t topicless_to_sample;
|
||||||
ddsi_serdata_free_t free;
|
ddsi_serdata_free_t free;
|
||||||
ddsi_serdata_print_t print;
|
ddsi_serdata_print_t print;
|
||||||
|
ddsi_serdata_get_keyhash_t get_keyhash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DDSI_SERDATA_HAS_PRINT 1
|
#define DDSI_SERDATA_HAS_PRINT 1
|
||||||
|
#define DDSI_SERDATA_HAS_FROM_SER_IOV 1
|
||||||
|
#define DDSI_SERDATA_HAS_GET_KEYHASH 1
|
||||||
|
|
||||||
DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertopic *tp, enum ddsi_serdata_kind kind);
|
DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertopic *tp, enum ddsi_serdata_kind kind);
|
||||||
|
|
||||||
|
@ -180,7 +186,7 @@ DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct d
|
||||||
return topic->serdata_ops->from_ser_iov (topic, kind, niov, iov, size);
|
return topic->serdata_ops->from_ser_iov (topic, kind, niov, iov, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct nn_keyhash *keyhash) {
|
DDS_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertopic *topic, const struct ddsi_keyhash *keyhash) {
|
||||||
return topic->serdata_ops->from_keyhash (topic, keyhash);
|
return topic->serdata_ops->from_keyhash (topic, keyhash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +236,10 @@ DDS_EXPORT inline bool ddsi_serdata_print_topicless (const struct ddsi_sertopic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DDS_EXPORT inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5) {
|
||||||
|
d->ops->get_keyhash (d, buf, force_md5);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "dds/ddsrt/avl.h"
|
#include "dds/ddsrt/avl.h"
|
||||||
#include "dds/ddsi/ddsi_serdata.h"
|
#include "dds/ddsi/ddsi_serdata.h"
|
||||||
#include "dds/ddsi/ddsi_sertopic.h"
|
#include "dds/ddsi/ddsi_sertopic.h"
|
||||||
|
#include "dds/ddsi/ddsi_plist_generic.h"
|
||||||
|
|
||||||
#include "dds/dds.h"
|
#include "dds/dds.h"
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@ typedef struct dds_keyhash {
|
||||||
unsigned char m_hash [16]; /* Key hash value. Also possibly key. Suitably aligned for accessing as uint32_t's */
|
unsigned char m_hash [16]; /* Key hash value. Also possibly key. Suitably aligned for accessing as uint32_t's */
|
||||||
unsigned m_set : 1; /* has it been initialised? */
|
unsigned m_set : 1; /* has it been initialised? */
|
||||||
unsigned m_iskey : 1; /* m_hash is key value */
|
unsigned m_iskey : 1; /* m_hash is key value */
|
||||||
|
unsigned m_keysize : 5; /* size of the key within the hash buffer */
|
||||||
} dds_keyhash_t;
|
} dds_keyhash_t;
|
||||||
|
|
||||||
/* Debug builds may want to keep some additional state */
|
/* Debug builds may want to keep some additional state */
|
||||||
|
@ -135,8 +137,6 @@ extern DDS_EXPORT const struct ddsi_sertopic_ops ddsi_sertopic_ops_default;
|
||||||
|
|
||||||
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr;
|
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr;
|
||||||
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey;
|
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_cdr_nokey;
|
||||||
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_plist;
|
|
||||||
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_rawcdr;
|
|
||||||
|
|
||||||
struct serdatapool * ddsi_serdatapool_new (void);
|
struct serdatapool * ddsi_serdatapool_new (void);
|
||||||
void ddsi_serdatapool_free (struct serdatapool * pool);
|
void ddsi_serdatapool_free (struct serdatapool * pool);
|
||||||
|
|
76
src/core/ddsi/include/dds/ddsi/ddsi_serdata_plist.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSI_SERDATA_PLIST_H
|
||||||
|
#define DDSI_SERDATA_PLIST_H
|
||||||
|
|
||||||
|
#include "dds/ddsi/q_protocol.h" /* for nn_parameterid_t */
|
||||||
|
#include "dds/ddsi/ddsi_keyhash.h"
|
||||||
|
#include "dds/ddsi/ddsi_serdata.h"
|
||||||
|
#include "dds/ddsi/ddsi_sertopic.h"
|
||||||
|
|
||||||
|
#include "dds/dds.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* There is an alignment requirement on the raw data (it must be at
|
||||||
|
offset mod 8 for the conversion to/from a dds_stream to work).
|
||||||
|
So we define two types: one without any additional padding, and
|
||||||
|
one where the appropriate amount of padding is inserted */
|
||||||
|
#define DDSI_SERDATA_PLIST_PREPAD \
|
||||||
|
struct ddsi_serdata c; \
|
||||||
|
uint32_t pos; \
|
||||||
|
uint32_t size; \
|
||||||
|
nn_vendorid_t vendorid; \
|
||||||
|
nn_protocol_version_t protoversion; \
|
||||||
|
ddsi_keyhash_t keyhash
|
||||||
|
#define DDSI_SERDATA_PLIST_POSTPAD \
|
||||||
|
uint16_t identifier; \
|
||||||
|
uint16_t options; \
|
||||||
|
char data[]
|
||||||
|
|
||||||
|
struct ddsi_serdata_plist_unpadded {
|
||||||
|
DDSI_SERDATA_PLIST_PREPAD;
|
||||||
|
DDSI_SERDATA_PLIST_POSTPAD;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define DDSI_SERDATA_PLIST_PAD(n) ((n) % 8)
|
||||||
|
#else
|
||||||
|
#define DDSI_SERDATA_PLIST_PAD(n) (n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ddsi_serdata_plist {
|
||||||
|
DDSI_SERDATA_PLIST_PREPAD;
|
||||||
|
char pad[DDSI_SERDATA_PLIST_PAD (8 - (offsetof (struct ddsi_serdata_plist_unpadded, data) % 8))];
|
||||||
|
DDSI_SERDATA_PLIST_POSTPAD;
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef DDSI_SERDATA_PLIST_PAD
|
||||||
|
#undef DDSI_SERDATA_PLIST_POSTPAD
|
||||||
|
#undef DDSI_SERDATA_PLIST_PREPAD
|
||||||
|
|
||||||
|
struct ddsi_sertopic_plist {
|
||||||
|
struct ddsi_sertopic c;
|
||||||
|
uint16_t native_encoding_identifier; /* PL_CDR_(LE|BE) */
|
||||||
|
nn_parameterid_t keyparam;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DDS_EXPORT const struct ddsi_sertopic_ops ddsi_sertopic_ops_plist;
|
||||||
|
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_plist;
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
78
src/core/ddsi/include/dds/ddsi/ddsi_serdata_pserop.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made available under the
|
||||||
|
* terms of the Eclipse Public License v. 2.0 which is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
|
||||||
|
* v. 1.0 which is available at
|
||||||
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#ifndef DDSI_SERDATA_PSEROP_H
|
||||||
|
#define DDSI_SERDATA_PSEROP_H
|
||||||
|
|
||||||
|
#include "dds/ddsi/ddsi_serdata.h"
|
||||||
|
#include "dds/ddsi/ddsi_sertopic.h"
|
||||||
|
#include "dds/ddsi/ddsi_plist_generic.h"
|
||||||
|
|
||||||
|
#include "dds/dds.h"
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* There is an alignment requirement on the raw data (it must be at
|
||||||
|
offset mod 8 for the conversion to/from a dds_stream to work).
|
||||||
|
So we define two types: one without any additional padding, and
|
||||||
|
one where the appropriate amount of padding is inserted */
|
||||||
|
#define DDSI_SERDATA_PSEROP_PREPAD \
|
||||||
|
struct ddsi_serdata c; \
|
||||||
|
void *sample; \
|
||||||
|
bool keyless; /*cached from topic*/ \
|
||||||
|
uint32_t pos; \
|
||||||
|
uint32_t size
|
||||||
|
#define DDSI_SERDATA_PSEROP_POSTPAD \
|
||||||
|
uint16_t identifier; \
|
||||||
|
uint16_t options; \
|
||||||
|
char data[]
|
||||||
|
|
||||||
|
struct ddsi_serdata_pserop_unpadded {
|
||||||
|
DDSI_SERDATA_PSEROP_PREPAD;
|
||||||
|
DDSI_SERDATA_PSEROP_POSTPAD;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define DDSI_SERDATA_PSEROP_PAD(n) ((n) % 8)
|
||||||
|
#else
|
||||||
|
#define DDSI_SERDATA_PSEROP_PAD(n) (n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ddsi_serdata_pserop {
|
||||||
|
DDSI_SERDATA_PSEROP_PREPAD;
|
||||||
|
char pad[DDSI_SERDATA_PSEROP_PAD (8 - (offsetof (struct ddsi_serdata_pserop_unpadded, data) % 8))];
|
||||||
|
DDSI_SERDATA_PSEROP_POSTPAD;
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef DDSI_SERDATA_PSEROP_PAD
|
||||||
|
#undef DDSI_SERDATA_PSEROP_POSTPAD
|
||||||
|
#undef DDSI_SERDATA_PSEROP_PREPAD
|
||||||
|
|
||||||
|
struct ddsi_sertopic_pserop {
|
||||||
|
struct ddsi_sertopic c;
|
||||||
|
uint16_t native_encoding_identifier; /* CDR_(LE|BE) */
|
||||||
|
size_t memsize;
|
||||||
|
size_t nops;
|
||||||
|
const enum pserop *ops;
|
||||||
|
size_t nops_key;
|
||||||
|
const enum pserop *ops_key; /* NULL <=> no key; != NULL <=> 16-byte key at offset 0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DDS_EXPORT const struct ddsi_sertopic_ops ddsi_sertopic_ops_pserop;
|
||||||
|
extern DDS_EXPORT const struct ddsi_serdata_ops ddsi_serdata_ops_pserop;
|
||||||
|
|
||||||
|
#if defined (__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -322,6 +322,13 @@ DDS_EXPORT void ddsi_xqos_addtomsg (struct nn_xmsg *m, const dds_qos_t *xqos, ui
|
||||||
DDS_EXPORT void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos);
|
DDS_EXPORT void ddsi_xqos_log (uint32_t cat, const struct ddsrt_log_cfg *logcfg, const dds_qos_t *xqos);
|
||||||
DDS_EXPORT size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos);
|
DDS_EXPORT size_t ddsi_xqos_print (char * __restrict buf, size_t bufsize, const dds_qos_t *xqos);
|
||||||
DDS_EXPORT dds_qos_t *ddsi_xqos_dup (const dds_qos_t *src);
|
DDS_EXPORT dds_qos_t *ddsi_xqos_dup (const dds_qos_t *src);
|
||||||
|
DDS_EXPORT bool ddsi_xqos_has_prop_prefix (const dds_qos_t *xqos, const char *nameprefix);
|
||||||
|
DDS_EXPORT bool ddsi_xqos_find_prop (const dds_qos_t *xqos, const char *name, const char **value);
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct omg_security_configuration_type;
|
||||||
|
DDS_EXPORT void ddsi_xqos_mergein_security_config (dds_qos_t *xqos, const struct omg_security_configuration_type *cfg);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ ddsi_guid_prefix_t nn_hton_guid_prefix (ddsi_guid_prefix_t p);
|
||||||
ddsi_guid_prefix_t nn_ntoh_guid_prefix (ddsi_guid_prefix_t p);
|
ddsi_guid_prefix_t nn_ntoh_guid_prefix (ddsi_guid_prefix_t p);
|
||||||
ddsi_entityid_t nn_hton_entityid (ddsi_entityid_t e);
|
ddsi_entityid_t nn_hton_entityid (ddsi_entityid_t e);
|
||||||
ddsi_entityid_t nn_ntoh_entityid (ddsi_entityid_t e);
|
ddsi_entityid_t nn_ntoh_entityid (ddsi_entityid_t e);
|
||||||
ddsi_guid_t nn_hton_guid (ddsi_guid_t g);
|
DDS_EXPORT ddsi_guid_t nn_hton_guid (ddsi_guid_t g);
|
||||||
ddsi_guid_t nn_ntoh_guid (ddsi_guid_t g);
|
DDS_EXPORT ddsi_guid_t nn_ntoh_guid (ddsi_guid_t g);
|
||||||
|
|
||||||
void bswap_sequence_number_set_hdr (nn_sequence_number_set_header_t *snset);
|
void bswap_sequence_number_set_hdr (nn_sequence_number_set_header_t *snset);
|
||||||
void bswap_sequence_number_set_bitmap (nn_sequence_number_set_header_t *snset, uint32_t *bits);
|
void bswap_sequence_number_set_bitmap (nn_sequence_number_set_header_t *snset, uint32_t *bits);
|
||||||
|
|
|
@ -161,6 +161,42 @@ enum many_sockets_mode {
|
||||||
MSM_MANY_UNICAST
|
MSM_MANY_UNICAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
typedef struct plugin_library_properties_type{
|
||||||
|
char *library_path;
|
||||||
|
char *library_init;
|
||||||
|
char *library_finalize;
|
||||||
|
} plugin_library_properties_type;
|
||||||
|
|
||||||
|
typedef struct authentication_properties_type{
|
||||||
|
char *identity_certificate;
|
||||||
|
char *identity_ca;
|
||||||
|
char *private_key;
|
||||||
|
char *password;
|
||||||
|
char *trusted_ca_dir;
|
||||||
|
int include_optional_fields;
|
||||||
|
} authentication_properties_type;
|
||||||
|
|
||||||
|
typedef struct access_control_properties_type{
|
||||||
|
char *permissions;
|
||||||
|
char *permissions_ca;
|
||||||
|
char *governance;
|
||||||
|
} access_control_properties_type;
|
||||||
|
|
||||||
|
typedef struct omg_security_configuration_type {
|
||||||
|
authentication_properties_type authentication_properties;
|
||||||
|
access_control_properties_type access_control_properties;
|
||||||
|
plugin_library_properties_type authentication_plugin;
|
||||||
|
plugin_library_properties_type access_control_plugin;
|
||||||
|
plugin_library_properties_type cryptography_plugin;
|
||||||
|
} omg_security_configuration_type;
|
||||||
|
|
||||||
|
struct config_omg_security_listelem {
|
||||||
|
struct config_omg_security_listelem *next;
|
||||||
|
omg_security_configuration_type cfg;
|
||||||
|
};
|
||||||
|
#endif /* DDSI_INCLUDE_SECURITY */
|
||||||
|
|
||||||
#ifdef DDSI_INCLUDE_SSL
|
#ifdef DDSI_INCLUDE_SSL
|
||||||
struct ssl_min_version {
|
struct ssl_min_version {
|
||||||
int major;
|
int major;
|
||||||
|
@ -226,8 +262,6 @@ struct config
|
||||||
|
|
||||||
unsigned delivery_queue_maxsamples;
|
unsigned delivery_queue_maxsamples;
|
||||||
|
|
||||||
int do_topic_discovery;
|
|
||||||
|
|
||||||
uint32_t max_msg_size;
|
uint32_t max_msg_size;
|
||||||
uint32_t fragment_size;
|
uint32_t fragment_size;
|
||||||
|
|
||||||
|
@ -333,6 +367,10 @@ struct config
|
||||||
|
|
||||||
int use_multicast_if_mreqn;
|
int use_multicast_if_mreqn;
|
||||||
struct prune_deleted_ppant prune_deleted_ppant;
|
struct prune_deleted_ppant prune_deleted_ppant;
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct config_omg_security_listelem *omg_security_configuration;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cfgst;
|
struct cfgst;
|
||||||
|
|
|
@ -25,6 +25,12 @@ struct nn_rsample_info;
|
||||||
struct nn_rdata;
|
struct nn_rdata;
|
||||||
struct ddsi_plist;
|
struct ddsi_plist;
|
||||||
|
|
||||||
|
struct participant_builtin_topic_data_locators {
|
||||||
|
struct nn_locators_one def_uni_loc_one, def_multi_loc_one, meta_uni_loc_one, meta_multi_loc_one;
|
||||||
|
};
|
||||||
|
|
||||||
|
void get_participant_builtin_topic_data (const struct participant *pp, ddsi_plist_t *dst, struct participant_builtin_topic_data_locators *locs);
|
||||||
|
|
||||||
int spdp_write (struct participant *pp);
|
int spdp_write (struct participant *pp);
|
||||||
int spdp_dispose_unregister (struct participant *pp);
|
int spdp_dispose_unregister (struct participant *pp);
|
||||||
|
|
||||||
|
@ -33,8 +39,6 @@ int sedp_write_reader (struct reader *rd);
|
||||||
int sedp_dispose_unregister_writer (struct writer *wr);
|
int sedp_dispose_unregister_writer (struct writer *wr);
|
||||||
int sedp_dispose_unregister_reader (struct reader *rd);
|
int sedp_dispose_unregister_reader (struct reader *rd);
|
||||||
|
|
||||||
int sedp_write_topic (struct participant *pp, const struct ddsi_plist *datap);
|
|
||||||
|
|
||||||
int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg);
|
int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
|
|
|
@ -18,11 +18,14 @@
|
||||||
#include "dds/ddsrt/fibheap.h"
|
#include "dds/ddsrt/fibheap.h"
|
||||||
#include "dds/ddsrt/sync.h"
|
#include "dds/ddsrt/sync.h"
|
||||||
#include "dds/ddsi/q_rtps.h"
|
#include "dds/ddsi/q_rtps.h"
|
||||||
|
#include "dds/ddsi/ddsi_plist.h"
|
||||||
#include "dds/ddsi/q_protocol.h"
|
#include "dds/ddsi/q_protocol.h"
|
||||||
#include "dds/ddsi/q_lat_estim.h"
|
#include "dds/ddsi/q_lat_estim.h"
|
||||||
#include "dds/ddsi/q_hbcontrol.h"
|
#include "dds/ddsi/q_hbcontrol.h"
|
||||||
#include "dds/ddsi/q_feature_check.h"
|
#include "dds/ddsi/q_feature_check.h"
|
||||||
#include "dds/ddsi/q_inverse_uint32_set.h"
|
#include "dds/ddsi/q_inverse_uint32_set.h"
|
||||||
|
#include "dds/ddsi/ddsi_serdata_default.h"
|
||||||
|
#include "dds/ddsi/ddsi_handshake.h"
|
||||||
|
|
||||||
#include "dds/ddsi/ddsi_tran.h"
|
#include "dds/ddsi/ddsi_tran.h"
|
||||||
|
|
||||||
|
@ -42,6 +45,10 @@ struct whc;
|
||||||
struct dds_qos;
|
struct dds_qos;
|
||||||
struct ddsi_plist;
|
struct ddsi_plist;
|
||||||
struct lease;
|
struct lease;
|
||||||
|
struct participant_sec_attributes;
|
||||||
|
struct proxy_participant_sec_attributes;
|
||||||
|
struct writer_sec_attributes;
|
||||||
|
struct reader_sec_attributes;
|
||||||
|
|
||||||
struct proxy_group;
|
struct proxy_group;
|
||||||
struct proxy_endpoint_common;
|
struct proxy_endpoint_common;
|
||||||
|
@ -80,6 +87,9 @@ typedef void (*status_cb_t) (void *entity, const status_cb_data_t *data);
|
||||||
struct prd_wr_match {
|
struct prd_wr_match {
|
||||||
ddsrt_avl_node_t avlnode;
|
ddsrt_avl_node_t avlnode;
|
||||||
ddsi_guid_t wr_guid;
|
ddsi_guid_t wr_guid;
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
int64_t crypto_handle;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rd_pwr_match {
|
struct rd_pwr_match {
|
||||||
|
@ -91,6 +101,9 @@ struct rd_pwr_match {
|
||||||
nn_locator_t ssm_mc_loc;
|
nn_locator_t ssm_mc_loc;
|
||||||
nn_locator_t ssm_src_loc;
|
nn_locator_t ssm_src_loc;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
int64_t crypto_handle;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wr_rd_match {
|
struct wr_rd_match {
|
||||||
|
@ -115,6 +128,7 @@ struct wr_prd_match {
|
||||||
seqno_t min_seq; /* smallest ack'd seq nr in subtree */
|
seqno_t min_seq; /* smallest ack'd seq nr in subtree */
|
||||||
seqno_t max_seq; /* sort-of highest ack'd seq nr in subtree (see augment function) */
|
seqno_t max_seq; /* sort-of highest ack'd seq nr in subtree (see augment function) */
|
||||||
seqno_t seq; /* highest acknowledged seq nr */
|
seqno_t seq; /* highest acknowledged seq nr */
|
||||||
|
seqno_t last_seq; /* highest seq send to this reader used when filter is applied */
|
||||||
int32_t num_reliable_readers_where_seq_equals_max;
|
int32_t num_reliable_readers_where_seq_equals_max;
|
||||||
ddsi_guid_t arbitrary_unacked_reader;
|
ddsi_guid_t arbitrary_unacked_reader;
|
||||||
nn_count_t next_acknack; /* next acceptable acknack sequence number */
|
nn_count_t next_acknack; /* next acceptable acknack sequence number */
|
||||||
|
@ -124,6 +138,9 @@ struct wr_prd_match {
|
||||||
ddsrt_wctime_t hb_to_ack_latency_tlastlog;
|
ddsrt_wctime_t hb_to_ack_latency_tlastlog;
|
||||||
uint32_t non_responsive_count;
|
uint32_t non_responsive_count;
|
||||||
uint32_t rexmit_requests;
|
uint32_t rexmit_requests;
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
int64_t crypto_handle;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
enum pwr_rd_match_syncstate {
|
enum pwr_rd_match_syncstate {
|
||||||
|
@ -142,14 +159,19 @@ struct pwr_rd_match {
|
||||||
ddsrt_etime_t t_heartbeat_accepted; /* (local) time a heartbeat was last accepted */
|
ddsrt_etime_t t_heartbeat_accepted; /* (local) time a heartbeat was last accepted */
|
||||||
ddsrt_mtime_t t_last_nack; /* (local) time we last sent a NACK */ /* FIXME: probably elapsed time is better */
|
ddsrt_mtime_t t_last_nack; /* (local) time we last sent a NACK */ /* FIXME: probably elapsed time is better */
|
||||||
seqno_t seq_last_nack; /* last seq for which we requested a retransmit */
|
seqno_t seq_last_nack; /* last seq for which we requested a retransmit */
|
||||||
|
seqno_t last_seq; /* last known sequence number from this writer */
|
||||||
struct xevent *acknack_xevent; /* entry in xevent queue for sending acknacks */
|
struct xevent *acknack_xevent; /* entry in xevent queue for sending acknacks */
|
||||||
enum pwr_rd_match_syncstate in_sync; /* whether in sync with the proxy writer */
|
enum pwr_rd_match_syncstate in_sync; /* whether in sync with the proxy writer */
|
||||||
|
unsigned filtered:1;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
seqno_t end_of_tl_seq; /* when seq >= end_of_tl_seq, it's in sync, =0 when not tl */
|
seqno_t end_of_tl_seq; /* when seq >= end_of_tl_seq, it's in sync, =0 when not tl */
|
||||||
struct nn_reorder *reorder; /* can be done (mostly) per proxy writer, but that is harder; only when state=OUT_OF_SYNC */
|
struct nn_reorder *reorder; /* can be done (mostly) per proxy writer, but that is harder; only when state=OUT_OF_SYNC */
|
||||||
} not_in_sync;
|
} not_in_sync;
|
||||||
} u;
|
} u;
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
int64_t crypto_handle;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nn_rsample_info;
|
struct nn_rsample_info;
|
||||||
|
@ -209,8 +231,12 @@ struct participant
|
||||||
int32_t builtin_refc; /* number of built-in endpoints in this participant [refc_lock] */
|
int32_t builtin_refc; /* number of built-in endpoints in this participant [refc_lock] */
|
||||||
int builtins_deleted; /* whether deletion of built-in endpoints has been initiated [refc_lock] */
|
int builtins_deleted; /* whether deletion of built-in endpoints has been initiated [refc_lock] */
|
||||||
ddsrt_fibheap_t ldur_auto_wr; /* Heap that contains lease duration for writers with automatic liveliness in this participant */
|
ddsrt_fibheap_t ldur_auto_wr; /* Heap that contains lease duration for writers with automatic liveliness in this participant */
|
||||||
ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness writer's lease */
|
ddsrt_atomic_voidp_t minl_man; /* clone of min(leaseheap_man) */
|
||||||
ddsrt_fibheap_t leaseheap_man; /* keeps leases for this participant's writers (with liveliness manual-by-participant) */
|
ddsrt_fibheap_t leaseheap_man; /* keeps leases for this participant's writers (with liveliness manual-by-participant) */
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct participant_sec_attributes *sec_attr;
|
||||||
|
nn_security_info_t security_info;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct endpoint_common {
|
struct endpoint_common {
|
||||||
|
@ -257,6 +283,7 @@ struct writer
|
||||||
unsigned reliable: 1; /* iff 1, writer is reliable <=> heartbeat_xevent != NULL */
|
unsigned reliable: 1; /* iff 1, writer is reliable <=> heartbeat_xevent != NULL */
|
||||||
unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */
|
unsigned handle_as_transient_local: 1; /* controls whether data is retained in WHC */
|
||||||
unsigned include_keyhash: 1; /* iff 1, this writer includes a keyhash; keyless topics => include_keyhash = 0 */
|
unsigned include_keyhash: 1; /* iff 1, this writer includes a keyhash; keyless topics => include_keyhash = 0 */
|
||||||
|
unsigned force_md5_keyhash: 1; /* iff 1, when keyhash has to be hashed, no matter the size */
|
||||||
unsigned retransmitting: 1; /* iff 1, this writer is currently retransmitting */
|
unsigned retransmitting: 1; /* iff 1, this writer is currently retransmitting */
|
||||||
unsigned alive: 1; /* iff 1, the writer is alive (lease for this writer is not expired); field may be modified only when holding both wr->e.lock and wr->c.pp->e.lock */
|
unsigned alive: 1; /* iff 1, the writer is alive (lease for this writer is not expired); field may be modified only when holding both wr->e.lock and wr->c.pp->e.lock */
|
||||||
#ifdef DDSI_INCLUDE_SSM
|
#ifdef DDSI_INCLUDE_SSM
|
||||||
|
@ -264,7 +291,7 @@ struct writer
|
||||||
struct addrset *ssm_as;
|
struct addrset *ssm_as;
|
||||||
#endif
|
#endif
|
||||||
uint32_t alive_vclock; /* virtual clock counting transitions between alive/not-alive */
|
uint32_t alive_vclock; /* virtual clock counting transitions between alive/not-alive */
|
||||||
const struct ddsi_sertopic * topic; /* topic, but may be NULL for built-ins */
|
const struct ddsi_sertopic * topic; /* topic */
|
||||||
struct addrset *as; /* set of addresses to publish to */
|
struct addrset *as; /* set of addresses to publish to */
|
||||||
struct addrset *as_group; /* alternate case, used for SPDP, when using Cloud with multiple bootstrap locators */
|
struct addrset *as_group; /* alternate case, used for SPDP, when using Cloud with multiple bootstrap locators */
|
||||||
struct xevent *heartbeat_xevent; /* timed event for "periodically" publishing heartbeats when unack'd data present, NULL <=> unreliable */
|
struct xevent *heartbeat_xevent; /* timed event for "periodically" publishing heartbeats when unack'd data present, NULL <=> unreliable */
|
||||||
|
@ -273,6 +300,7 @@ struct writer
|
||||||
uint32_t whc_low, whc_high; /* watermarks for WHC in bytes (counting only unack'd data) */
|
uint32_t whc_low, whc_high; /* watermarks for WHC in bytes (counting only unack'd data) */
|
||||||
ddsrt_etime_t t_rexmit_end; /* time of last 1->0 transition of "retransmitting" */
|
ddsrt_etime_t t_rexmit_end; /* time of last 1->0 transition of "retransmitting" */
|
||||||
ddsrt_etime_t t_whc_high_upd; /* time "whc_high" was last updated for controlled ramp-up of throughput */
|
ddsrt_etime_t t_whc_high_upd; /* time "whc_high" was last updated for controlled ramp-up of throughput */
|
||||||
|
uint32_t num_readers; /* total number of matching PROXY readers */
|
||||||
int32_t num_reliable_readers; /* number of matching reliable PROXY readers */
|
int32_t num_reliable_readers; /* number of matching reliable PROXY readers */
|
||||||
ddsrt_avl_tree_t readers; /* all matching PROXY readers, see struct wr_prd_match */
|
ddsrt_avl_tree_t readers; /* all matching PROXY readers, see struct wr_prd_match */
|
||||||
ddsrt_avl_tree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */
|
ddsrt_avl_tree_t local_readers; /* all matching LOCAL readers, see struct wr_rd_match */
|
||||||
|
@ -288,6 +316,9 @@ struct writer
|
||||||
struct xeventq *evq; /* timed event queue to be used by this writer */
|
struct xeventq *evq; /* timed event queue to be used by this writer */
|
||||||
struct local_reader_ary rdary; /* LOCAL readers for fast-pathing; if not fast-pathed, fall back to scanning local_readers */
|
struct local_reader_ary rdary; /* LOCAL readers for fast-pathing; if not fast-pathed, fall back to scanning local_readers */
|
||||||
struct lease *lease; /* for liveliness administration (writer can only become inactive when using manual liveliness) */
|
struct lease *lease; /* for liveliness administration (writer can only become inactive when using manual liveliness) */
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct writer_sec_attributes *sec_attr;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline seqno_t writer_read_seq_xmit (const struct writer *wr) {
|
inline seqno_t writer_read_seq_xmit (const struct writer *wr) {
|
||||||
|
@ -319,11 +350,15 @@ struct reader
|
||||||
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
#ifdef DDSI_INCLUDE_NETWORK_PARTITIONS
|
||||||
struct addrset *as;
|
struct addrset *as;
|
||||||
#endif
|
#endif
|
||||||
const struct ddsi_sertopic * topic; /* topic is NULL for built-in readers */
|
const struct ddsi_sertopic * topic; /* topic */
|
||||||
|
uint32_t num_writers; /* total number of matching PROXY writers */
|
||||||
ddsrt_avl_tree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */
|
ddsrt_avl_tree_t writers; /* all matching PROXY writers, see struct rd_pwr_match */
|
||||||
ddsrt_avl_tree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */
|
ddsrt_avl_tree_t local_writers; /* all matching LOCAL writers, see struct rd_wr_match */
|
||||||
ddsi2direct_directread_cb_t ddsi2direct_cb;
|
ddsi2direct_directread_cb_t ddsi2direct_cb;
|
||||||
void *ddsi2direct_cbarg;
|
void *ddsi2direct_cbarg;
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct reader_sec_attributes *sec_attr;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct proxy_participant
|
struct proxy_participant
|
||||||
|
@ -334,9 +369,9 @@ struct proxy_participant
|
||||||
unsigned bes; /* built-in endpoint set */
|
unsigned bes; /* built-in endpoint set */
|
||||||
ddsi_guid_t privileged_pp_guid; /* if this PP depends on another PP for its SEDP writing */
|
ddsi_guid_t privileged_pp_guid; /* if this PP depends on another PP for its SEDP writing */
|
||||||
struct ddsi_plist *plist; /* settings/QoS for this participant */
|
struct ddsi_plist *plist; /* settings/QoS for this participant */
|
||||||
ddsrt_atomic_voidp_t minl_auto; /* lease object for shortest automatic liveliness pwr's lease (includes this proxypp's lease) */
|
ddsrt_atomic_voidp_t minl_auto; /* clone of min(leaseheap_auto) */
|
||||||
ddsrt_fibheap_t leaseheap_auto; /* keeps leases for this proxypp and leases for pwrs (with liveliness automatic) */
|
ddsrt_fibheap_t leaseheap_auto; /* keeps leases for this proxypp and leases for pwrs (with liveliness automatic) */
|
||||||
ddsrt_atomic_voidp_t minl_man; /* lease object for shortest manual-by-participant liveliness pwr's lease */
|
ddsrt_atomic_voidp_t minl_man; /* clone of min(leaseheap_man) */
|
||||||
ddsrt_fibheap_t leaseheap_man; /* keeps leases for this proxypp and leases for pwrs (with liveliness manual-by-participant) */
|
ddsrt_fibheap_t leaseheap_man; /* keeps leases for this proxypp and leases for pwrs (with liveliness manual-by-participant) */
|
||||||
struct lease *lease; /* lease for this proxypp */
|
struct lease *lease; /* lease for this proxypp */
|
||||||
struct addrset *as_default; /* default address set to use for user data traffic */
|
struct addrset *as_default; /* default address set to use for user data traffic */
|
||||||
|
@ -344,7 +379,6 @@ struct proxy_participant
|
||||||
struct proxy_endpoint_common *endpoints; /* all proxy endpoints can be reached from here */
|
struct proxy_endpoint_common *endpoints; /* all proxy endpoints can be reached from here */
|
||||||
ddsrt_avl_tree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */
|
ddsrt_avl_tree_t groups; /* table of all groups (publisher, subscriber), see struct proxy_group */
|
||||||
seqno_t seq; /* sequence number of most recent SPDP message */
|
seqno_t seq; /* sequence number of most recent SPDP message */
|
||||||
unsigned kernel_sequence_numbers : 1; /* whether this proxy participant generates OSPL kernel sequence numbers */
|
|
||||||
unsigned implicitly_created : 1; /* participants are implicitly created for Cloud/Fog discovered endpoints */
|
unsigned implicitly_created : 1; /* participants are implicitly created for Cloud/Fog discovered endpoints */
|
||||||
unsigned is_ddsi2_pp: 1; /* if this is the federation-leader on the remote node */
|
unsigned is_ddsi2_pp: 1; /* if this is the federation-leader on the remote node */
|
||||||
unsigned minimal_bes_mode: 1;
|
unsigned minimal_bes_mode: 1;
|
||||||
|
@ -352,6 +386,10 @@ struct proxy_participant
|
||||||
unsigned deleting: 1;
|
unsigned deleting: 1;
|
||||||
unsigned proxypp_have_spdp: 1;
|
unsigned proxypp_have_spdp: 1;
|
||||||
unsigned owns_lease: 1;
|
unsigned owns_lease: 1;
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
nn_security_info_t security_info;
|
||||||
|
struct proxy_participant_sec_attributes *sec_attr;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Representing proxy subscriber & publishers as "groups": until DDSI2
|
/* Representing proxy subscriber & publishers as "groups": until DDSI2
|
||||||
|
@ -379,6 +417,9 @@ struct proxy_endpoint_common
|
||||||
ddsi_guid_t group_guid; /* 0:0:0:0 if not available */
|
ddsi_guid_t group_guid; /* 0:0:0:0 if not available */
|
||||||
nn_vendorid_t vendor; /* cached from proxypp->vendor */
|
nn_vendorid_t vendor; /* cached from proxypp->vendor */
|
||||||
seqno_t seq; /* sequence number of most recent SEDP message */
|
seqno_t seq; /* sequence number of most recent SEDP message */
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
nn_security_info_t security_info;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct generic_proxy_endpoint {
|
struct generic_proxy_endpoint {
|
||||||
|
@ -401,6 +442,7 @@ struct proxy_writer {
|
||||||
unsigned have_seen_heartbeat: 1; /* iff 1, we have received at least on heartbeat from this proxy writer */
|
unsigned have_seen_heartbeat: 1; /* iff 1, we have received at least on heartbeat from this proxy writer */
|
||||||
unsigned local_matching_inprogress: 1; /* iff 1, we are still busy matching local readers; this is so we don't deliver incoming data to some but not all readers initially */
|
unsigned local_matching_inprogress: 1; /* iff 1, we are still busy matching local readers; this is so we don't deliver incoming data to some but not all readers initially */
|
||||||
unsigned alive: 1; /* iff 1, the proxy writer is alive (lease for this proxy writer is not expired); field may be modified only when holding both pwr->e.lock and pwr->c.proxypp->e.lock */
|
unsigned alive: 1; /* iff 1, the proxy writer is alive (lease for this proxy writer is not expired); field may be modified only when holding both pwr->e.lock and pwr->c.proxypp->e.lock */
|
||||||
|
unsigned filtered: 1; /* iff 1, builtin proxy writer uses content filter, which affects heartbeats and gaps. */
|
||||||
#ifdef DDSI_INCLUDE_SSM
|
#ifdef DDSI_INCLUDE_SSM
|
||||||
unsigned supports_ssm: 1; /* iff 1, this proxy writer supports SSM */
|
unsigned supports_ssm: 1; /* iff 1, this proxy writer supports SSM */
|
||||||
#endif
|
#endif
|
||||||
|
@ -415,6 +457,9 @@ struct proxy_writer {
|
||||||
struct lease *lease;
|
struct lease *lease;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (*filter_fn_t)(struct writer *wr, struct proxy_reader *prd, struct ddsi_serdata *serdata);
|
||||||
|
|
||||||
struct proxy_reader {
|
struct proxy_reader {
|
||||||
struct entity_common e;
|
struct entity_common e;
|
||||||
struct proxy_endpoint_common c;
|
struct proxy_endpoint_common c;
|
||||||
|
@ -424,6 +469,7 @@ struct proxy_reader {
|
||||||
unsigned favours_ssm: 1; /* iff 1, this proxy reader favours SSM when available */
|
unsigned favours_ssm: 1; /* iff 1, this proxy reader favours SSM when available */
|
||||||
#endif
|
#endif
|
||||||
ddsrt_avl_tree_t writers; /* matching LOCAL writers */
|
ddsrt_avl_tree_t writers; /* matching LOCAL writers */
|
||||||
|
filter_fn_t filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
DDS_EXPORT extern const ddsrt_avl_treedef_t wr_readers_treedef;
|
DDS_EXPORT extern const ddsrt_avl_treedef_t wr_readers_treedef;
|
||||||
|
@ -507,8 +553,8 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e);
|
||||||
/**
|
/**
|
||||||
* @brief Create a new participant with a given GUID in the domain.
|
* @brief Create a new participant with a given GUID in the domain.
|
||||||
*
|
*
|
||||||
* @param[in] ppguid
|
* @param[in,out] ppguid
|
||||||
* The GUID of the new participant.
|
* The GUID of the new participant, may be adjusted by security.
|
||||||
* @param[in] flags
|
* @param[in] flags
|
||||||
* Zero or more of:
|
* Zero or more of:
|
||||||
* - RTPS_PF_NO_BUILTIN_READERS do not create discovery readers in new ppant
|
* - RTPS_PF_NO_BUILTIN_READERS do not create discovery readers in new ppant
|
||||||
|
@ -529,7 +575,7 @@ nn_vendorid_t get_entity_vendorid (const struct entity_common *e);
|
||||||
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
* @retval DDS_RETCODE_OUT_OF_RESOURCES
|
||||||
* The configured maximum number of participants has been reached.
|
* The configured maximum number of participants has been reached.
|
||||||
*/
|
*/
|
||||||
dds_return_t new_participant_guid (const ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct ddsi_plist *plist);
|
dds_return_t new_participant_guid (ddsi_guid_t *ppguid, struct ddsi_domaingv *gv, unsigned flags, const struct ddsi_plist *plist);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a new participant in the domain. See also new_participant_guid.
|
* @brief Create a new participant in the domain. See also new_participant_guid.
|
||||||
|
@ -596,9 +642,8 @@ DDS_EXPORT struct writer *get_builtin_writer (const struct participant *pp, unsi
|
||||||
GUID "ppguid". May return NULL if participant unknown or
|
GUID "ppguid". May return NULL if participant unknown or
|
||||||
writer/reader already known. */
|
writer/reader already known. */
|
||||||
|
|
||||||
dds_return_t new_writer (struct writer **wr_out, struct ddsi_domaingv *gv, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg);
|
dds_return_t new_writer (struct writer **wr_out, struct ddsi_guid *wrguid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct whc * whc, status_cb_t status_cb, void *status_cb_arg);
|
||||||
|
dds_return_t new_reader (struct reader **rd_out, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, struct participant *pp, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, status_cb_t status_cb, void *status_cb_arg);
|
||||||
dds_return_t new_reader (struct reader **rd_out, struct ddsi_domaingv *gv, struct ddsi_guid *rdguid, const struct ddsi_guid *group_guid, const struct ddsi_guid *ppguid, const struct ddsi_sertopic *topic, const struct dds_qos *xqos, struct ddsi_rhc * rhc, status_cb_t status_cb, void *status_cb_arg);
|
|
||||||
|
|
||||||
void update_reader_qos (struct reader *rd, const struct dds_qos *xqos);
|
void update_reader_qos (struct reader *rd, const struct dds_qos *xqos);
|
||||||
void update_writer_qos (struct writer *wr, const struct dds_qos *xqos);
|
void update_writer_qos (struct writer *wr, const struct dds_qos *xqos);
|
||||||
|
@ -610,7 +655,7 @@ seqno_t writer_max_drop_seq (const struct writer *wr);
|
||||||
int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_state *whcst);
|
int writer_must_have_hb_scheduled (const struct writer *wr, const struct whc_state *whcst);
|
||||||
void writer_set_retransmitting (struct writer *wr);
|
void writer_set_retransmitting (struct writer *wr);
|
||||||
void writer_clear_retransmitting (struct writer *wr);
|
void writer_clear_retransmitting (struct writer *wr);
|
||||||
dds_return_t writer_wait_for_acks (struct writer *wr, dds_time_t abstimeout);
|
dds_return_t writer_wait_for_acks (struct writer *wr, const ddsi_guid_t *rdguid, dds_time_t abstimeout);
|
||||||
|
|
||||||
dds_return_t unblock_throttled_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid);
|
dds_return_t unblock_throttled_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid);
|
||||||
dds_return_t delete_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid);
|
dds_return_t delete_writer (struct ddsi_domaingv *gv, const struct ddsi_guid *guid);
|
||||||
|
@ -638,22 +683,20 @@ int writer_set_notalive (struct writer *wr, bool notify);
|
||||||
XX --
|
XX --
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Set this custom flag when using nn_adlink_writer_info_t iso nn_adlink_writer_info_old_t */
|
|
||||||
#define CF_INC_KERNEL_SEQUENCE_NUMBERS (1 << 0)
|
|
||||||
/* Set when this proxy participant is created implicitly and has to be deleted upon disappearance
|
/* Set when this proxy participant is created implicitly and has to be deleted upon disappearance
|
||||||
of its last endpoint. FIXME: Currently there is a potential race with adding a new endpoint
|
of its last endpoint. FIXME: Currently there is a potential race with adding a new endpoint
|
||||||
in parallel to deleting the last remaining one. The endpoint will then be created, added to the
|
in parallel to deleting the last remaining one. The endpoint will then be created, added to the
|
||||||
proxy participant and then both are deleted. With the current single-threaded discovery
|
proxy participant and then both are deleted. With the current single-threaded discovery
|
||||||
this can only happen when it is all triggered by lease expiry. */
|
this can only happen when it is all triggered by lease expiry. */
|
||||||
#define CF_IMPLICITLY_CREATED_PROXYPP (1 << 1)
|
#define CF_IMPLICITLY_CREATED_PROXYPP (1 << 0)
|
||||||
/* Set when this proxy participant is a DDSI2 participant, to help Cloud figure out whom to send
|
/* Set when this proxy participant is a DDSI2 participant, to help Cloud figure out whom to send
|
||||||
discovery data when used in conjunction with the networking bridge */
|
discovery data when used in conjunction with the networking bridge */
|
||||||
#define CF_PARTICIPANT_IS_DDSI2 (1 << 2)
|
#define CF_PARTICIPANT_IS_DDSI2 (1 << 1)
|
||||||
/* Set when this proxy participant is not to be announced on the built-in topics yet */
|
/* Set when this proxy participant is not to be announced on the built-in topics yet */
|
||||||
#define CF_PROXYPP_NO_SPDP (1 << 3)
|
#define CF_PROXYPP_NO_SPDP (1 << 2)
|
||||||
|
|
||||||
void new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct ddsi_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, ddsrt_wctime_t timestamp, seqno_t seq);
|
bool new_proxy_participant (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, uint32_t bes, const struct ddsi_guid *privileged_pp_guid, struct addrset *as_default, struct addrset *as_meta, const struct ddsi_plist *plist, dds_duration_t tlease_dur, nn_vendorid_t vendor, unsigned custom_flags, ddsrt_wctime_t timestamp, seqno_t seq);
|
||||||
int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, ddsrt_wctime_t timestamp, int isimplicit);
|
DDS_EXPORT int delete_proxy_participant_by_guid (struct ddsi_domaingv *gv, const struct ddsi_guid *guid, ddsrt_wctime_t timestamp, int isimplicit);
|
||||||
|
|
||||||
int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp);
|
int update_proxy_participant_plist_locked (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp);
|
||||||
int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp);
|
int update_proxy_participant_plist (struct proxy_participant *proxypp, seqno_t seq, const struct ddsi_plist *datap, ddsrt_wctime_t timestamp);
|
||||||
|
@ -696,6 +739,10 @@ void rebuild_or_clear_writer_addrsets(struct ddsi_domaingv *gv, int rebuild);
|
||||||
|
|
||||||
void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok);
|
void local_reader_ary_setfastpath_ok (struct local_reader_ary *x, bool fastpath_ok);
|
||||||
|
|
||||||
|
void connect_writer_with_proxy_reader_secure(struct writer *wr, struct proxy_reader *prd, ddsrt_mtime_t tnow, int64_t crypto_handle);
|
||||||
|
void connect_reader_with_proxy_writer_secure(struct reader *rd, struct proxy_writer *pwr, ddsrt_mtime_t tnow, int64_t crypto_handle);
|
||||||
|
|
||||||
|
|
||||||
struct ddsi_writer_info;
|
struct ddsi_writer_info;
|
||||||
DDS_EXPORT void ddsi_make_writer_info(struct ddsi_writer_info *wrinfo, const struct entity_common *e, const struct dds_qos *xqos, uint32_t statusinfo);
|
DDS_EXPORT void ddsi_make_writer_info(struct ddsi_writer_info *wrinfo, const struct entity_common *e, const struct dds_qos *xqos, uint32_t statusinfo);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ extern "C" {
|
||||||
|
|
||||||
struct writer;
|
struct writer;
|
||||||
struct whc_state;
|
struct whc_state;
|
||||||
|
struct proxy_reader;
|
||||||
|
|
||||||
struct hbcontrol {
|
struct hbcontrol {
|
||||||
ddsrt_mtime_t t_of_last_write;
|
ddsrt_mtime_t t_of_last_write;
|
||||||
|
@ -36,6 +37,11 @@ struct nn_xmsg *writer_hbcontrol_piggyback (struct writer *wr, const struct whc_
|
||||||
int writer_hbcontrol_must_send (const struct writer *wr, const struct whc_state *whcst, ddsrt_mtime_t tnow);
|
int writer_hbcontrol_must_send (const struct writer *wr, const struct whc_state *whcst, ddsrt_mtime_t tnow);
|
||||||
struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const struct whc_state *whcst, ddsrt_mtime_t tnow, int hbansreq, int issync);
|
struct nn_xmsg *writer_hbcontrol_create_heartbeat (struct writer *wr, const struct whc_state *whcst, ddsrt_mtime_t tnow, int hbansreq, int issync);
|
||||||
|
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
struct nn_xmsg *writer_hbcontrol_p2p(struct writer *wr, const struct whc_state *whcst, int hbansreq, struct proxy_reader *prd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,7 +29,7 @@ struct lease {
|
||||||
ddsrt_fibheap_node_t heapnode;
|
ddsrt_fibheap_node_t heapnode;
|
||||||
ddsrt_fibheap_node_t pp_heapnode;
|
ddsrt_fibheap_node_t pp_heapnode;
|
||||||
ddsrt_etime_t tsched; /* access guarded by leaseheap_lock */
|
ddsrt_etime_t tsched; /* access guarded by leaseheap_lock */
|
||||||
ddsrt_atomic_uint64_t tend; /* really an nn_etime_t */
|
ddsrt_atomic_uint64_t tend; /* really an ddsrt_etime_t */
|
||||||
dds_duration_t tdur; /* constant (renew depends on it) */
|
dds_duration_t tdur; /* constant (renew depends on it) */
|
||||||
struct entity_common *entity; /* constant */
|
struct entity_common *entity; /* constant */
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,10 @@ unsigned char normalize_data_datafrag_flags (const SubmessageHeader_t *smhdr);
|
||||||
int WildcardOverlap(char * p1, char * p2);
|
int WildcardOverlap(char * p1, char * p2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ddsi2_patmatch (const char *pat, const char *str);
|
DDS_EXPORT bool guid_prefix_zero (const ddsi_guid_prefix_t *a);
|
||||||
|
DDS_EXPORT int guid_prefix_eq (const ddsi_guid_prefix_t *a, const ddsi_guid_prefix_t *b);
|
||||||
|
DDS_EXPORT int guid_eq (const struct ddsi_guid *a, const struct ddsi_guid *b);
|
||||||
|
DDS_EXPORT int ddsi2_patmatch (const char *pat, const char *str);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,13 +89,21 @@ typedef struct {
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER (1u << 12)
|
#define NN_DISC_BUILTIN_ENDPOINT_TOPIC_ANNOUNCER (1u << 12)
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_TOPIC_DETECTOR (1u << 13)
|
#define NN_DISC_BUILTIN_ENDPOINT_TOPIC_DETECTOR (1u << 13)
|
||||||
|
|
||||||
/* Adlink extensions: */
|
/* Security extensions: */
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_WRITER (1u << 0)
|
#define NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_ANNOUNCER (1u<<16)
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_CM_PARTICIPANT_READER (1u << 1)
|
#define NN_BUILTIN_ENDPOINT_PUBLICATION_MESSAGE_SECURE_DETECTOR (1u<<17)
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_WRITER (1u << 2)
|
#define NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_ANNOUNCER (1u<<18)
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_CM_PUBLISHER_READER (1u << 3)
|
#define NN_BUILTIN_ENDPOINT_SUBSCRIPTION_MESSAGE_SECURE_DETECTOR (1u<<19)
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_WRITER (1u << 4)
|
#define NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_ANNOUNCER (1u<<20)
|
||||||
#define NN_DISC_BUILTIN_ENDPOINT_CM_SUBSCRIBER_READER (1u << 5)
|
#define NN_BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_SECURE_DETECTOR (1u<<21)
|
||||||
|
#define NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_ANNOUNCER (1u<<22)
|
||||||
|
#define NN_BUILTIN_ENDPOINT_PARTICIPANT_STATELESS_MESSAGE_DETECTOR (1u<<23)
|
||||||
|
#define NN_BUILTIN_ENDPOINT_PARTICIPANT_VOLATILE_SECURE_ANNOUNCER (1u<<24)
|
||||||
|
#define NN_BUILTIN_ENDPOINT_PARTICIPANT_VOLATILE_SECURE_DETECTOR (1u<<25)
|
||||||
|
#define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_ANNOUNCER (1u << 26)
|
||||||
|
#define NN_DISC_BUILTIN_ENDPOINT_PARTICIPANT_SECURE_DETECTOR (1u << 27)
|
||||||
|
|
||||||
|
#define NN_BES_MASK_NON_SECURITY 0xf000ffffu
|
||||||
|
|
||||||
#define NN_LOCATOR_KIND_INVALID -1
|
#define NN_LOCATOR_KIND_INVALID -1
|
||||||
#define NN_LOCATOR_KIND_RESERVED 0
|
#define NN_LOCATOR_KIND_RESERVED 0
|
||||||
|
@ -149,6 +157,12 @@ typedef enum SubmessageKind {
|
||||||
SMID_HEARTBEAT_FRAG = 0x13,
|
SMID_HEARTBEAT_FRAG = 0x13,
|
||||||
SMID_DATA = 0x15,
|
SMID_DATA = 0x15,
|
||||||
SMID_DATA_FRAG = 0x16,
|
SMID_DATA_FRAG = 0x16,
|
||||||
|
/* security-specific sub messages */
|
||||||
|
SMID_SEC_BODY = 0x30,
|
||||||
|
SMID_SEC_PREFIX = 0x31,
|
||||||
|
SMID_SEC_POSTFIX = 0x32,
|
||||||
|
SMID_SRTPS_PREFIX = 0x33,
|
||||||
|
SMID_SRTPS_POSTFIX = 0x34,
|
||||||
/* vendor-specific sub messages (0x80 .. 0xff) */
|
/* vendor-specific sub messages (0x80 .. 0xff) */
|
||||||
SMID_ADLINK_MSG_LEN = 0x81,
|
SMID_ADLINK_MSG_LEN = 0x81,
|
||||||
SMID_ADLINK_ENTITY_ID = 0x82
|
SMID_ADLINK_ENTITY_ID = 0x82
|
||||||
|
@ -189,7 +203,7 @@ typedef uint16_t nn_parameterid_t; /* spec says short */
|
||||||
typedef struct nn_parameter {
|
typedef struct nn_parameter {
|
||||||
nn_parameterid_t parameterid;
|
nn_parameterid_t parameterid;
|
||||||
uint16_t length; /* spec says signed short */
|
uint16_t length; /* spec says signed short */
|
||||||
/* char value[]; O! how I long for C99 */
|
/* char value[] */
|
||||||
} nn_parameter_t;
|
} nn_parameter_t;
|
||||||
|
|
||||||
typedef struct Data_DataFrag_common {
|
typedef struct Data_DataFrag_common {
|
||||||
|
@ -304,18 +318,10 @@ typedef union Submessage {
|
||||||
NackFrag_t nackfrag;
|
NackFrag_t nackfrag;
|
||||||
} Submessage_t;
|
} Submessage_t;
|
||||||
|
|
||||||
DDSRT_WARNING_MSVC_OFF(4200)
|
|
||||||
typedef struct ParticipantMessageData {
|
|
||||||
ddsi_guid_prefix_t participantGuidPrefix;
|
|
||||||
uint32_t kind; /* really 4 octets */
|
|
||||||
uint32_t length;
|
|
||||||
char value[];
|
|
||||||
} ParticipantMessageData_t;
|
|
||||||
DDSRT_WARNING_MSVC_ON(4200)
|
|
||||||
#define PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN 0x0u
|
#define PARTICIPANT_MESSAGE_DATA_KIND_UNKNOWN 0x0u
|
||||||
#define PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE 0x1u
|
#define PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE 0x1u
|
||||||
#define PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE 0x2u
|
#define PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE 0x2u
|
||||||
#define PARTICIPANT_MESSAGE_DATA_VENDER_SPECIFIC_KIND_FLAG 0x8000000u
|
#define PARTICIPANT_MESSAGE_DATA_VENDOR_SPECIFIC_KIND_FLAG 0x8000000u
|
||||||
|
|
||||||
#define PID_VENDORSPECIFIC_FLAG 0x8000u
|
#define PID_VENDORSPECIFIC_FLAG 0x8000u
|
||||||
#define PID_UNRECOGNIZED_INCOMPATIBLE_FLAG 0x4000u
|
#define PID_UNRECOGNIZED_INCOMPATIBLE_FLAG 0x4000u
|
||||||
|
@ -384,6 +390,10 @@ DDSRT_WARNING_MSVC_ON(4200)
|
||||||
/* Security related PID values. */
|
/* Security related PID values. */
|
||||||
#define PID_IDENTITY_TOKEN 0x1001u
|
#define PID_IDENTITY_TOKEN 0x1001u
|
||||||
#define PID_PERMISSIONS_TOKEN 0x1002u
|
#define PID_PERMISSIONS_TOKEN 0x1002u
|
||||||
|
#define PID_DATA_TAGS 0x1003u
|
||||||
|
#define PID_ENDPOINT_SECURITY_INFO 0x1004u
|
||||||
|
#define PID_PARTICIPANT_SECURITY_INFO 0x1005u
|
||||||
|
#define PID_IDENTITY_STATUS_TOKEN 0x1006u
|
||||||
|
|
||||||
#ifdef DDSI_INCLUDE_SSM
|
#ifdef DDSI_INCLUDE_SSM
|
||||||
/* To indicate whether a reader favours the use of SSM. Iff the
|
/* To indicate whether a reader favours the use of SSM. Iff the
|
||||||
|
|
|
@ -113,7 +113,8 @@ struct receiver_state {
|
||||||
ddsi_guid_prefix_t src_guid_prefix; /* 12 */
|
ddsi_guid_prefix_t src_guid_prefix; /* 12 */
|
||||||
ddsi_guid_prefix_t dst_guid_prefix; /* 12 */
|
ddsi_guid_prefix_t dst_guid_prefix; /* 12 */
|
||||||
struct addrset *reply_locators; /* 4/8 */
|
struct addrset *reply_locators; /* 4/8 */
|
||||||
int forme; /* 4 */
|
uint32_t forme:1; /* 4 */
|
||||||
|
uint32_t rtps_encoded:1; /* - */
|
||||||
nn_vendorid_t vendor; /* 2 */
|
nn_vendorid_t vendor; /* 2 */
|
||||||
nn_protocol_version_t protocol_version; /* 2 => 44/48 */
|
nn_protocol_version_t protocol_version; /* 2 => 44/48 */
|
||||||
ddsi_tran_conn_t conn; /* Connection for request */
|
ddsi_tran_conn_t conn; /* Connection for request */
|
||||||
|
@ -223,6 +224,7 @@ void nn_defrag_free (struct nn_defrag *defrag);
|
||||||
struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata *rdata, const struct nn_rsample_info *sampleinfo);
|
struct nn_rsample *nn_defrag_rsample (struct nn_defrag *defrag, struct nn_rdata *rdata, const struct nn_rsample_info *sampleinfo);
|
||||||
void nn_defrag_notegap (struct nn_defrag *defrag, seqno_t min, seqno_t maxp1);
|
void nn_defrag_notegap (struct nn_defrag *defrag, seqno_t min, seqno_t maxp1);
|
||||||
int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnum, struct nn_fragment_number_set_header *map, uint32_t *mapbits, uint32_t maxsz);
|
int nn_defrag_nackmap (struct nn_defrag *defrag, seqno_t seq, uint32_t maxfragnum, struct nn_fragment_number_set_header *map, uint32_t *mapbits, uint32_t maxsz);
|
||||||
|
void nn_defrag_prune (struct nn_defrag *defrag, ddsi_guid_prefix_t *dst, seqno_t min);
|
||||||
|
|
||||||
struct nn_reorder *nn_reorder_new (const struct ddsrt_log_cfg *logcfg, enum nn_reorder_mode mode, uint32_t max_samples, bool late_ack_mode);
|
struct nn_reorder *nn_reorder_new (const struct ddsrt_log_cfg *logcfg, enum nn_reorder_mode mode, uint32_t max_samples, bool late_ack_mode);
|
||||||
void nn_reorder_free (struct nn_reorder *r);
|
void nn_reorder_free (struct nn_reorder *r);
|
||||||
|
@ -233,6 +235,7 @@ nn_reorder_result_t nn_reorder_gap (struct nn_rsample_chain *sc, struct nn_reord
|
||||||
int nn_reorder_wantsample (struct nn_reorder *reorder, seqno_t seq);
|
int nn_reorder_wantsample (struct nn_reorder *reorder, seqno_t seq);
|
||||||
unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t maxseq, struct nn_sequence_number_set_header *map, uint32_t *mapbits, uint32_t maxsz, int notail);
|
unsigned nn_reorder_nackmap (struct nn_reorder *reorder, seqno_t base, seqno_t maxseq, struct nn_sequence_number_set_header *map, uint32_t *mapbits, uint32_t maxsz, int notail);
|
||||||
seqno_t nn_reorder_next_seq (const struct nn_reorder *reorder);
|
seqno_t nn_reorder_next_seq (const struct nn_reorder *reorder);
|
||||||
|
void nn_reorder_set_next_seq (struct nn_reorder *reorder, seqno_t seq);
|
||||||
|
|
||||||
struct nn_dqueue *nn_dqueue_new (const char *name, const struct ddsi_domaingv *gv, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg);
|
struct nn_dqueue *nn_dqueue_new (const char *name, const struct ddsi_domaingv *gv, uint32_t max_samples, nn_dqueue_handler_t handler, void *arg);
|
||||||
void nn_dqueue_free (struct nn_dqueue *q);
|
void nn_dqueue_free (struct nn_dqueue *q);
|
||||||
|
|
|
@ -21,11 +21,25 @@ struct nn_rsample_info;
|
||||||
struct nn_rdata;
|
struct nn_rdata;
|
||||||
struct ddsi_tran_listener;
|
struct ddsi_tran_listener;
|
||||||
struct recv_thread_arg;
|
struct recv_thread_arg;
|
||||||
|
struct writer;
|
||||||
|
struct proxy_reader;
|
||||||
|
|
||||||
|
struct nn_gap_info {
|
||||||
|
int64_t gapstart;
|
||||||
|
int64_t gapend;
|
||||||
|
unsigned gapnumbits;
|
||||||
|
unsigned gapbits[256 / 32];
|
||||||
|
};
|
||||||
|
|
||||||
|
void nn_gap_info_init(struct nn_gap_info *gi);
|
||||||
|
void nn_gap_info_update(struct ddsi_domaingv *gv, struct nn_gap_info *gi, int64_t seqnr);
|
||||||
|
struct nn_xmsg * nn_gap_info_create_gap(struct writer *wr, struct proxy_reader *prd, struct nn_gap_info *gi);
|
||||||
|
|
||||||
void trigger_recv_threads (const struct ddsi_domaingv *gv);
|
void trigger_recv_threads (const struct ddsi_domaingv *gv);
|
||||||
uint32_t recv_thread (void *vrecv_thread_arg);
|
uint32_t recv_thread (void *vrecv_thread_arg);
|
||||||
uint32_t listen_thread (struct ddsi_tran_listener * listener);
|
uint32_t listen_thread (struct ddsi_tran_listener * listener);
|
||||||
int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg);
|
int user_dqueue_handler (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, const ddsi_guid_t *rdguid, void *qarg);
|
||||||
|
int add_Gap (struct nn_xmsg *msg, struct writer *wr, struct proxy_reader *prd, seqno_t start, seqno_t base, uint32_t numbits, const uint32_t *bits);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,20 @@ typedef int64_t seqno_t;
|
||||||
#define NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER 0x100c7
|
#define NN_ENTITYID_SPDP_BUILTIN_PARTICIPANT_READER 0x100c7
|
||||||
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER 0x200c2
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER 0x200c2
|
||||||
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER 0x200c7
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER 0x200c7
|
||||||
|
|
||||||
|
#define NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_WRITER 0xff0003c2
|
||||||
|
#define NN_ENTITYID_SEDP_BUILTIN_PUBLICATIONS_SECURE_READER 0xff0003c7
|
||||||
|
#define NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_WRITER 0xff0004c2
|
||||||
|
#define NN_ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_SECURE_READER 0xff0004c7
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_WRITER 0x201c3
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_STATELESS_MESSAGE_READER 0x201c4
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_WRITER 0xff0200c2
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_SECURE_READER 0xff0200c7
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_WRITER 0xff0202c3
|
||||||
|
#define NN_ENTITYID_P2P_BUILTIN_PARTICIPANT_VOLATILE_SECURE_READER 0xff0202c4
|
||||||
|
#define NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_WRITER 0xff0101c2
|
||||||
|
#define NN_ENTITYID_SPDP_RELIABLE_BUILTIN_PARTICIPANT_SECURE_READER 0xff0101c7
|
||||||
|
|
||||||
#define NN_ENTITYID_SOURCE_MASK 0xc0
|
#define NN_ENTITYID_SOURCE_MASK 0xc0
|
||||||
#define NN_ENTITYID_SOURCE_USER 0x00
|
#define NN_ENTITYID_SOURCE_USER 0x00
|
||||||
#define NN_ENTITYID_SOURCE_BUILTIN 0xc0
|
#define NN_ENTITYID_SOURCE_BUILTIN 0xc0
|
||||||
|
|
|
@ -44,6 +44,7 @@ dds_return_t create_fragment_message (struct writer *wr, seqno_t seq, const stru
|
||||||
int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew);
|
int enqueue_sample_wrlock_held (struct writer *wr, seqno_t seq, const struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct proxy_reader *prd, int isnew);
|
||||||
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, int hbliveliness, ddsi_entityid_t dst, int issync);
|
void add_Heartbeat (struct nn_xmsg *msg, struct writer *wr, const struct whc_state *whcst, int hbansreq, int hbliveliness, ddsi_entityid_t dst, int issync);
|
||||||
dds_return_t write_hb_liveliness (struct ddsi_domaingv * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp);
|
dds_return_t write_hb_liveliness (struct ddsi_domaingv * const gv, struct ddsi_guid *wr_guid, struct nn_xpack *xp);
|
||||||
|
int write_sample_p2p_wrlock_held(struct writer *wr, seqno_t seq, struct ddsi_plist *plist, struct ddsi_serdata *serdata, struct ddsi_tkmap_instance *tk, struct proxy_reader *prd);
|
||||||
|
|
||||||
#if defined (__cplusplus)
|
#if defined (__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,10 @@ DDS_EXPORT dds_return_t xeventq_start (struct xeventq *evq, const char *name); /
|
||||||
DDS_EXPORT void xeventq_stop (struct xeventq *evq);
|
DDS_EXPORT void xeventq_stop (struct xeventq *evq);
|
||||||
|
|
||||||
DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg);
|
DDS_EXPORT void qxev_msg (struct xeventq *evq, struct nn_xmsg *msg);
|
||||||
DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, ddsi_guid_prefix_t * id);
|
|
||||||
DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, ddsi_guid_prefix_t * id);
|
DDS_EXPORT void qxev_pwr_entityid (struct proxy_writer * pwr, const ddsi_guid_t *guid);
|
||||||
|
DDS_EXPORT void qxev_prd_entityid (struct proxy_reader * prd, const ddsi_guid_t *guid);
|
||||||
|
DDS_EXPORT void qxev_nt_callback (struct xeventq *evq, void (*cb) (void *arg), void *arg);
|
||||||
|
|
||||||
/* Returns 1 if queued, 0 otherwise (no point in returning the
|
/* Returns 1 if queued, 0 otherwise (no point in returning the
|
||||||
event, you can't do anything with it anyway) */
|
event, you can't do anything with it anyway) */
|
||||||
|
|
|
@ -26,6 +26,8 @@ struct ddsi_serdata;
|
||||||
struct addrset;
|
struct addrset;
|
||||||
struct proxy_reader;
|
struct proxy_reader;
|
||||||
struct proxy_writer;
|
struct proxy_writer;
|
||||||
|
struct writer;
|
||||||
|
struct participant;
|
||||||
|
|
||||||
struct nn_adlink_participant_version_info;
|
struct nn_adlink_participant_version_info;
|
||||||
struct nn_xmsgpool;
|
struct nn_xmsgpool;
|
||||||
|
@ -41,7 +43,8 @@ struct nn_xmsg_marker {
|
||||||
enum nn_xmsg_kind {
|
enum nn_xmsg_kind {
|
||||||
NN_XMSG_KIND_CONTROL,
|
NN_XMSG_KIND_CONTROL,
|
||||||
NN_XMSG_KIND_DATA,
|
NN_XMSG_KIND_DATA,
|
||||||
NN_XMSG_KIND_DATA_REXMIT
|
NN_XMSG_KIND_DATA_REXMIT,
|
||||||
|
NN_XMSG_KIND_DATA_REXMIT_NOMERGE
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XMSGPOOL */
|
/* XMSGPOOL */
|
||||||
|
@ -54,10 +57,11 @@ void nn_xmsgpool_free (struct nn_xmsgpool *pool);
|
||||||
/* To allocate a new xmsg from the pool; if expected_size is NOT
|
/* To allocate a new xmsg from the pool; if expected_size is NOT
|
||||||
exceeded, no reallocs will be performed, else the address of the
|
exceeded, no reallocs will be performed, else the address of the
|
||||||
xmsg may change because of reallocing when appending to it. */
|
xmsg may change because of reallocing when appending to it. */
|
||||||
struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const ddsi_guid_prefix_t *src_guid_prefix, size_t expected_size, enum nn_xmsg_kind kind);
|
struct nn_xmsg *nn_xmsg_new (struct nn_xmsgpool *pool, const ddsi_guid_t *src_guid, struct participant *pp, size_t expected_size, enum nn_xmsg_kind kind);
|
||||||
|
|
||||||
/* For sending to a particular destination (participant) */
|
/* For sending to a particular destination (participant) */
|
||||||
void nn_xmsg_setdst1 (struct nn_xmsg *m, const ddsi_guid_prefix_t *gp, const nn_locator_t *addr);
|
void nn_xmsg_setdst1 (struct ddsi_domaingv *gv, struct nn_xmsg *m, const ddsi_guid_prefix_t *gp, const nn_locator_t *addr);
|
||||||
|
bool nn_xmsg_getdst1prefix (struct nn_xmsg *m, ddsi_guid_prefix_t *gp);
|
||||||
|
|
||||||
/* For sending to a particular proxy reader; this is a convenience
|
/* For sending to a particular proxy reader; this is a convenience
|
||||||
routine that extracts a suitable address from the proxy reader's
|
routine that extracts a suitable address from the proxy reader's
|
||||||
|
@ -114,15 +118,23 @@ void nn_xmsg_guid_seq_fragid (const struct nn_xmsg *m, ddsi_guid_t *wrguid, seqn
|
||||||
void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
|
void *nn_xmsg_submsg_from_marker (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
|
||||||
void *nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz);
|
void *nn_xmsg_append (struct nn_xmsg *m, struct nn_xmsg_marker *marker, size_t sz);
|
||||||
void nn_xmsg_shrink (struct nn_xmsg *m, struct nn_xmsg_marker marker, size_t sz);
|
void nn_xmsg_shrink (struct nn_xmsg *m, struct nn_xmsg_marker marker, size_t sz);
|
||||||
void nn_xmsg_serdata (struct nn_xmsg *m, struct ddsi_serdata *serdata, size_t off, size_t len);
|
void nn_xmsg_serdata (struct nn_xmsg *m, struct ddsi_serdata *serdata, size_t off, size_t len, struct writer *wr);
|
||||||
|
#ifdef DDSI_INCLUDE_SECURITY
|
||||||
|
size_t nn_xmsg_submsg_size (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
|
||||||
|
void nn_xmsg_submsg_remove (struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker);
|
||||||
|
void nn_xmsg_submsg_replace (struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker, unsigned char *new_submsg, size_t new_len);
|
||||||
|
void nn_xmsg_submsg_append_refd_payload (struct nn_xmsg *msg, struct nn_xmsg_marker sm_marker);
|
||||||
|
#endif
|
||||||
void nn_xmsg_submsg_setnext (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
|
void nn_xmsg_submsg_setnext (struct nn_xmsg *msg, struct nn_xmsg_marker marker);
|
||||||
void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, SubmessageKind_t smkind);
|
void nn_xmsg_submsg_init (struct nn_xmsg *msg, struct nn_xmsg_marker marker, SubmessageKind_t smkind);
|
||||||
void nn_xmsg_add_timestamp (struct nn_xmsg *m, ddsrt_wctime_t t);
|
void nn_xmsg_add_timestamp (struct nn_xmsg *m, ddsrt_wctime_t t);
|
||||||
void nn_xmsg_add_entityid (struct nn_xmsg * m);
|
void nn_xmsg_add_entityid (struct nn_xmsg * m);
|
||||||
|
void *nn_xmsg_addpar_bo (struct nn_xmsg *m, nn_parameterid_t pid, size_t len, bool be);
|
||||||
void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len);
|
void *nn_xmsg_addpar (struct nn_xmsg *m, nn_parameterid_t pid, size_t len);
|
||||||
void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata);
|
void nn_xmsg_addpar_keyhash (struct nn_xmsg *m, const struct ddsi_serdata *serdata, bool force_md5);
|
||||||
void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo);
|
void nn_xmsg_addpar_statusinfo (struct nn_xmsg *m, unsigned statusinfo);
|
||||||
void nn_xmsg_addpar_sentinel (struct nn_xmsg *m);
|
void nn_xmsg_addpar_sentinel (struct nn_xmsg *m);
|
||||||
|
void nn_xmsg_addpar_sentinel_bo (struct nn_xmsg * m, bool be);
|
||||||
int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m);
|
int nn_xmsg_addpar_sentinel_ifparam (struct nn_xmsg *m);
|
||||||
|
|
||||||
/* XPACK */
|
/* XPACK */
|
||||||
|
|
|
@ -364,6 +364,7 @@ static void dds_stream_countops1 (const uint32_t * __restrict ops, const uint32_
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DDS_OP_JSR: {
|
case DDS_OP_JSR: {
|
||||||
|
if (DDS_OP_JUMP (insn) > 0)
|
||||||
dds_stream_countops1 (ops + DDS_OP_JUMP (insn), ops_end);
|
dds_stream_countops1 (ops + DDS_OP_JUMP (insn), ops_end);
|
||||||
ops++;
|
ops++;
|
||||||
break;
|
break;
|
||||||
|
@ -1909,7 +1910,10 @@ void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t *
|
||||||
const struct ddsi_sertopic_default_desc *desc = &topic->type;
|
const struct ddsi_sertopic_default_desc *desc = &topic->type;
|
||||||
kh->m_set = 1;
|
kh->m_set = 1;
|
||||||
if (desc->m_nkeys == 0)
|
if (desc->m_nkeys == 0)
|
||||||
|
{
|
||||||
kh->m_iskey = 1;
|
kh->m_iskey = 1;
|
||||||
|
kh->m_keysize = 0;
|
||||||
|
}
|
||||||
else if (desc->m_flagset & DDS_TOPIC_FIXED_KEY)
|
else if (desc->m_flagset & DDS_TOPIC_FIXED_KEY)
|
||||||
{
|
{
|
||||||
dds_ostreamBE_t os;
|
dds_ostreamBE_t os;
|
||||||
|
@ -1922,12 +1926,14 @@ void dds_stream_extract_keyhash (dds_istream_t * __restrict is, dds_keyhash_t *
|
||||||
else
|
else
|
||||||
dds_stream_extract_keyBE_from_data (is, &os, topic);
|
dds_stream_extract_keyBE_from_data (is, &os, topic);
|
||||||
assert (os.x.m_index <= 16);
|
assert (os.x.m_index <= 16);
|
||||||
|
kh->m_keysize = (unsigned)os.x.m_index & 0x1f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dds_ostreamBE_t os;
|
dds_ostreamBE_t os;
|
||||||
ddsrt_md5_state_t md5st;
|
ddsrt_md5_state_t md5st;
|
||||||
kh->m_iskey = 0;
|
kh->m_iskey = 0;
|
||||||
|
kh->m_keysize = 16;
|
||||||
dds_ostreamBE_init (&os, 0);
|
dds_ostreamBE_init (&os, 0);
|
||||||
if (just_key)
|
if (just_key)
|
||||||
dds_stream_extract_keyBE_from_key (is, &os, topic);
|
dds_stream_extract_keyBE_from_key (is, &os, topic);
|
||||||
|
@ -1990,14 +1996,42 @@ static size_t isprint_runlen (const unsigned char *s, size_t n)
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, enum dds_stream_typecode type)
|
static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, enum dds_stream_typecode type, unsigned flags)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case DDS_OP_VAL_1BY: return prtf (buf, bufsize, "%"PRIu8, dds_is_get1 (is));
|
case DDS_OP_VAL_1BY: {
|
||||||
case DDS_OP_VAL_2BY: return prtf (buf, bufsize, "%"PRIu16, dds_is_get2 (is));
|
const union { int8_t s; uint8_t u; } x = { .u = dds_is_get1 (is) };
|
||||||
case DDS_OP_VAL_4BY: return prtf (buf, bufsize, "%"PRIu32, dds_is_get4 (is));
|
if (flags & DDS_OP_FLAG_SGN)
|
||||||
case DDS_OP_VAL_8BY: return prtf (buf, bufsize, "%"PRIu64, dds_is_get8 (is));
|
return prtf (buf, bufsize, "%"PRId8, x.s);
|
||||||
|
else
|
||||||
|
return prtf (buf, bufsize, "%"PRIu8, x.u);
|
||||||
|
}
|
||||||
|
case DDS_OP_VAL_2BY: {
|
||||||
|
const union { int16_t s; uint16_t u; } x = { .u = dds_is_get2 (is) };
|
||||||
|
if (flags & DDS_OP_FLAG_SGN)
|
||||||
|
return prtf (buf, bufsize, "%"PRId16, x.s);
|
||||||
|
else
|
||||||
|
return prtf (buf, bufsize, "%"PRIu16, x.u);
|
||||||
|
}
|
||||||
|
case DDS_OP_VAL_4BY: {
|
||||||
|
const union { int32_t s; uint32_t u; float f; } x = { .u = dds_is_get4 (is) };
|
||||||
|
if (flags & DDS_OP_FLAG_FP)
|
||||||
|
return prtf (buf, bufsize, "%g", x.f);
|
||||||
|
else if (flags & DDS_OP_FLAG_SGN)
|
||||||
|
return prtf (buf, bufsize, "%"PRId32, x.s);
|
||||||
|
else
|
||||||
|
return prtf (buf, bufsize, "%"PRIu32, x.u);
|
||||||
|
}
|
||||||
|
case DDS_OP_VAL_8BY: {
|
||||||
|
const union { int64_t s; uint64_t u; double f; } x = { .u = dds_is_get8 (is) };
|
||||||
|
if (flags & DDS_OP_FLAG_FP)
|
||||||
|
return prtf (buf, bufsize, "%g", x.f);
|
||||||
|
else if (flags & DDS_OP_FLAG_SGN)
|
||||||
|
return prtf (buf, bufsize, "%"PRId64, x.s);
|
||||||
|
else
|
||||||
|
return prtf (buf, bufsize, "%"PRIu64, x.u);
|
||||||
|
}
|
||||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: return prtf_str (buf, bufsize, is);
|
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST: return prtf_str (buf, bufsize, is);
|
||||||
case DDS_OP_VAL_ARR: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
case DDS_OP_VAL_ARR: case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
||||||
abort ();
|
abort ();
|
||||||
|
@ -2005,7 +2039,7 @@ static bool prtf_simple (char * __restrict *buf, size_t * __restrict bufsize, dd
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, uint32_t num, enum dds_stream_typecode type)
|
static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsize, dds_istream_t * __restrict is, uint32_t num, enum dds_stream_typecode type, unsigned flags)
|
||||||
{
|
{
|
||||||
bool cont = prtf (buf, bufsize, "{");
|
bool cont = prtf (buf, bufsize, "{");
|
||||||
switch (type)
|
switch (type)
|
||||||
|
@ -2028,7 +2062,7 @@ static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsi
|
||||||
{
|
{
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
(void) prtf (buf, bufsize, ",");
|
(void) prtf (buf, bufsize, ",");
|
||||||
cont = prtf_simple (buf, bufsize, is, type);
|
cont = prtf_simple (buf, bufsize, is, type, flags);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2040,7 +2074,7 @@ static bool prtf_simple_array (char * __restrict *buf, size_t * __restrict bufsi
|
||||||
{
|
{
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
(void) prtf (buf, bufsize, ",");
|
(void) prtf (buf, bufsize, ",");
|
||||||
cont = prtf_simple (buf, bufsize, is, type);
|
cont = prtf_simple (buf, bufsize, is, type, flags);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2065,10 +2099,10 @@ static const uint32_t *prtf_seq (char * __restrict *buf, size_t *bufsize, dds_is
|
||||||
switch (subtype)
|
switch (subtype)
|
||||||
{
|
{
|
||||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||||
(void) prtf_simple_array (buf, bufsize, is, num, subtype);
|
(void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn));
|
||||||
return ops + 2;
|
return ops + 2;
|
||||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||||
(void) prtf_simple_array (buf, bufsize, is, num, subtype);
|
(void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn));
|
||||||
return ops + (subtype == DDS_OP_VAL_STR ? 2 : 3);
|
return ops + (subtype == DDS_OP_VAL_STR ? 2 : 3);
|
||||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: {
|
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: {
|
||||||
const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]);
|
const uint32_t jmp = DDS_OP_ADR_JMP (ops[3]);
|
||||||
|
@ -2093,10 +2127,10 @@ static const uint32_t *prtf_arr (char * __restrict *buf, size_t *bufsize, dds_is
|
||||||
switch (subtype)
|
switch (subtype)
|
||||||
{
|
{
|
||||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||||
(void) prtf_simple_array (buf, bufsize, is, num, subtype);
|
(void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn));
|
||||||
return ops + 3;
|
return ops + 3;
|
||||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||||
(void) prtf_simple_array (buf, bufsize, is, num, subtype);
|
(void) prtf_simple_array (buf, bufsize, is, num, subtype, DDS_OP_FLAGS (insn));
|
||||||
return ops + (subtype == DDS_OP_VAL_STR ? 3 : 5);
|
return ops + (subtype == DDS_OP_VAL_STR ? 3 : 5);
|
||||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: {
|
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU: {
|
||||||
const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]);
|
const uint32_t *jsr_ops = ops + DDS_OP_ADR_JSR (ops[3]);
|
||||||
|
@ -2127,7 +2161,7 @@ static const uint32_t *prtf_uni (char * __restrict *buf, size_t *bufsize, dds_is
|
||||||
{
|
{
|
||||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||||
(void) prtf_simple (buf, bufsize, is, valtype);
|
(void) prtf_simple (buf, bufsize, is, valtype, DDS_OP_FLAGS (jeq_op[0]));
|
||||||
break;
|
break;
|
||||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_ARR: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
||||||
(void) dds_stream_print_sample1 (buf, bufsize, is, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), valtype == DDS_OP_VAL_STU);
|
(void) dds_stream_print_sample1 (buf, bufsize, is, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]), valtype == DDS_OP_VAL_STU);
|
||||||
|
@ -2156,11 +2190,11 @@ static bool dds_stream_print_sample1 (char * __restrict *buf, size_t * __restric
|
||||||
{
|
{
|
||||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||||
case DDS_OP_VAL_STR:
|
case DDS_OP_VAL_STR:
|
||||||
cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn));
|
cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn), DDS_OP_FLAGS (insn));
|
||||||
ops += 2;
|
ops += 2;
|
||||||
break;
|
break;
|
||||||
case DDS_OP_VAL_BST:
|
case DDS_OP_VAL_BST:
|
||||||
cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn));
|
cont = prtf_simple (buf, bufsize, is, DDS_OP_TYPE (insn), DDS_OP_FLAGS (insn));
|
||||||
ops += 3;
|
ops += 3;
|
||||||
break;
|
break;
|
||||||
case DDS_OP_VAL_SEQ:
|
case DDS_OP_VAL_SEQ:
|
||||||
|
@ -2212,10 +2246,10 @@ size_t dds_stream_print_key (dds_istream_t * __restrict is, const struct ddsi_se
|
||||||
{
|
{
|
||||||
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
case DDS_OP_VAL_1BY: case DDS_OP_VAL_2BY: case DDS_OP_VAL_4BY: case DDS_OP_VAL_8BY:
|
||||||
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
case DDS_OP_VAL_STR: case DDS_OP_VAL_BST:
|
||||||
cont = prtf_simple (&buf, &bufsize, is, DDS_OP_TYPE (*op));
|
cont = prtf_simple (&buf, &bufsize, is, DDS_OP_TYPE (*op), DDS_OP_FLAGS (*op));
|
||||||
break;
|
break;
|
||||||
case DDS_OP_VAL_ARR:
|
case DDS_OP_VAL_ARR:
|
||||||
cont = prtf_simple_array (&buf, &bufsize, is, op[2], DDS_OP_SUBTYPE (*op));
|
cont = prtf_simple_array (&buf, &bufsize, is, op[2], DDS_OP_SUBTYPE (*op), DDS_OP_FLAGS (*op));
|
||||||
break;
|
break;
|
||||||
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
case DDS_OP_VAL_SEQ: case DDS_OP_VAL_UNI: case DDS_OP_VAL_STU:
|
||||||
abort ();
|
abort ();
|
||||||
|
|
|
@ -25,8 +25,8 @@ static void instance_deadline_missed_cb (struct xevent *xev, void *varg, ddsrt_m
|
||||||
|
|
||||||
/* Gets the instance from the list in deadline admin that has the earliest missed deadline and
|
/* Gets the instance from the list in deadline admin that has the earliest missed deadline and
|
||||||
* removes the instance element from the list. If no more instances with missed deadline exist
|
* removes the instance element from the list. If no more instances with missed deadline exist
|
||||||
* in the list, the deadline (nn_mtime_t) for the first instance to 'expire' is returned. If the
|
* in the list, the deadline (ddsrt_mtime_t) for the first instance to 'expire' is returned. If
|
||||||
* list is empty, DDSRT_MTIME_NEVER is returned */
|
* the list is empty, DDSRT_MTIME_NEVER is returned */
|
||||||
ddsrt_mtime_t deadline_next_missed_locked (struct deadline_adm *deadline_adm, ddsrt_mtime_t tnow, void **instance)
|
ddsrt_mtime_t deadline_next_missed_locked (struct deadline_adm *deadline_adm, ddsrt_mtime_t tnow, void **instance)
|
||||||
{
|
{
|
||||||
struct deadline_elem *elem = NULL;
|
struct deadline_elem *elem = NULL;
|
||||||
|
|
|
@ -70,20 +70,6 @@ static int entity_guid_eq_wrapper (const void *a, const void *b)
|
||||||
return entity_guid_eq (a, b);
|
return entity_guid_eq (a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int all_entities_compare_isbuiltin (const struct entity_common *e, nn_vendorid_t vendor)
|
|
||||||
{
|
|
||||||
const unsigned char *guid_bytes = (const unsigned char *) &e->guid;
|
|
||||||
if (guid_bytes[0] != 0 && guid_bytes[0] != 0xff)
|
|
||||||
return is_builtin_endpoint (e->guid.entityid, vendor);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (size_t i = 1; i < sizeof (e->guid); i++)
|
|
||||||
if (guid_bytes[i] != guid_bytes[0])
|
|
||||||
return is_builtin_endpoint (e->guid.entityid, vendor) && !is_local_orphan_endpoint (e);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int all_entities_compare (const void *va, const void *vb)
|
static int all_entities_compare (const void *va, const void *vb)
|
||||||
{
|
{
|
||||||
const struct entity_common *a = va;
|
const struct entity_common *a = va;
|
||||||
|
@ -104,28 +90,20 @@ static int all_entities_compare (const void *va, const void *vb)
|
||||||
case EK_WRITER: {
|
case EK_WRITER: {
|
||||||
const struct writer *wra = va;
|
const struct writer *wra = va;
|
||||||
const struct writer *wrb = vb;
|
const struct writer *wrb = vb;
|
||||||
if (!all_entities_compare_isbuiltin (a, NN_VENDORID_ECLIPSE)) {
|
|
||||||
assert ((wra->xqos->present & QP_TOPIC_NAME) && wra->xqos->topic_name);
|
assert ((wra->xqos->present & QP_TOPIC_NAME) && wra->xqos->topic_name);
|
||||||
tp_a = wra->xqos->topic_name;
|
|
||||||
}
|
|
||||||
if (!all_entities_compare_isbuiltin (b, NN_VENDORID_ECLIPSE)) {
|
|
||||||
assert ((wrb->xqos->present & QP_TOPIC_NAME) && wrb->xqos->topic_name);
|
assert ((wrb->xqos->present & QP_TOPIC_NAME) && wrb->xqos->topic_name);
|
||||||
|
tp_a = wra->xqos->topic_name;
|
||||||
tp_b = wrb->xqos->topic_name;
|
tp_b = wrb->xqos->topic_name;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EK_READER: {
|
case EK_READER: {
|
||||||
const struct reader *rda = va;
|
const struct reader *rda = va;
|
||||||
const struct reader *rdb = vb;
|
const struct reader *rdb = vb;
|
||||||
if (!all_entities_compare_isbuiltin (a, NN_VENDORID_ECLIPSE)) {
|
|
||||||
assert ((rda->xqos->present & QP_TOPIC_NAME) && rda->xqos->topic_name);
|
assert ((rda->xqos->present & QP_TOPIC_NAME) && rda->xqos->topic_name);
|
||||||
tp_a = rda->xqos->topic_name;
|
|
||||||
}
|
|
||||||
if (!all_entities_compare_isbuiltin (b, NN_VENDORID_ECLIPSE)) {
|
|
||||||
assert ((rdb->xqos->present & QP_TOPIC_NAME) && rdb->xqos->topic_name);
|
assert ((rdb->xqos->present & QP_TOPIC_NAME) && rdb->xqos->topic_name);
|
||||||
|
tp_a = rda->xqos->topic_name;
|
||||||
tp_b = rdb->xqos->topic_name;
|
tp_b = rdb->xqos->topic_name;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,14 +111,11 @@ static int all_entities_compare (const void *va, const void *vb)
|
||||||
case EK_PROXY_READER: {
|
case EK_PROXY_READER: {
|
||||||
const struct generic_proxy_endpoint *ga = va;
|
const struct generic_proxy_endpoint *ga = va;
|
||||||
const struct generic_proxy_endpoint *gb = vb;
|
const struct generic_proxy_endpoint *gb = vb;
|
||||||
if (!all_entities_compare_isbuiltin (a, ga->c.vendor)) {
|
/* built-in reader/writer proxies don't have topic name set */
|
||||||
assert ((ga->c.xqos->present & QP_TOPIC_NAME) && ga->c.xqos->topic_name);
|
if (ga->c.xqos->present & QP_TOPIC_NAME)
|
||||||
tp_a = ga->c.xqos->topic_name;
|
tp_a = ga->c.xqos->topic_name;
|
||||||
}
|
if (gb->c.xqos->present & QP_TOPIC_NAME)
|
||||||
if (!all_entities_compare_isbuiltin (b, gb->c.vendor)) {
|
|
||||||
assert ((gb->c.xqos->present & QP_TOPIC_NAME) && gb->c.xqos->topic_name);
|
|
||||||
tp_b = gb->c.xqos->topic_name;
|
tp_b = gb->c.xqos->topic_name;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,6 +414,18 @@ void entidx_enum_init_topic (struct entidx_enum *st, const struct entity_index *
|
||||||
st->cur = NULL;
|
st->cur = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void entidx_enum_init_topic_w_prefix (struct entidx_enum *st, const struct entity_index *ei, enum entity_kind kind, const char *topic, const ddsi_guid_prefix_t *prefix, struct match_entities_range_key *max)
|
||||||
|
{
|
||||||
|
assert (kind == EK_READER || kind == EK_WRITER || kind == EK_PROXY_READER || kind == EK_PROXY_WRITER);
|
||||||
|
struct match_entities_range_key min;
|
||||||
|
match_endpoint_range (kind, topic, &min, max);
|
||||||
|
min.entity.e.guid.prefix = *prefix;
|
||||||
|
max->entity.e.guid.prefix = *prefix;
|
||||||
|
entidx_enum_init_minmax_int (st, ei, &min);
|
||||||
|
if (st->cur && all_entities_compare (st->cur, &max->entity) > 0)
|
||||||
|
st->cur = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void entidx_enum_init (struct entidx_enum *st, const struct entity_index *ei, enum entity_kind kind)
|
void entidx_enum_init (struct entidx_enum *st, const struct entity_index *ei, enum entity_kind kind)
|
||||||
{
|
{
|
||||||
struct match_entities_range_key min;
|
struct match_entities_range_key min;
|
||||||
|
|
1302
src/core/ddsi/src/ddsi_handshake.c
Normal file
|
@ -34,7 +34,7 @@ static void lifespan_rhc_node_exp (struct xevent *xev, void *varg, ddsrt_mtime_t
|
||||||
|
|
||||||
|
|
||||||
/* Gets the sample from the fibheap in lifespan admin that was expired first. If no more
|
/* Gets the sample from the fibheap in lifespan admin that was expired first. If no more
|
||||||
* expired samples exist in the fibheap, the expiry time (nn_mtime_t) for the next sample to
|
* expired samples exist in the fibheap, the expiry time (ddsrt_mtime_t) for the next sample to
|
||||||
* expire is returned. If the fibheap contains no more samples, DDSRT_MTIME_NEVER is returned */
|
* expire is returned. If the fibheap contains no more samples, DDSRT_MTIME_NEVER is returned */
|
||||||
ddsrt_mtime_t lifespan_next_expired_locked (const struct lifespan_adm *lifespan_adm, ddsrt_mtime_t tnow, void **sample)
|
ddsrt_mtime_t lifespan_next_expired_locked (const struct lifespan_adm *lifespan_adm, ddsrt_mtime_t tnow, void **sample)
|
||||||
{
|
{
|
||||||
|
|
|
@ -203,7 +203,7 @@ static int joinleave_mcgroups (const struct ddsi_domaingv *gv, ddsi_tran_conn_t
|
||||||
{
|
{
|
||||||
if (gv->recvips_mode == RECVIPS_MODE_ALL || interface_in_recvips_p (gv->recvips, &gv->interfaces[i]))
|
if (gv->recvips_mode == RECVIPS_MODE_ALL || interface_in_recvips_p (gv->recvips, &gv->interfaces[i]))
|
||||||
{
|
{
|
||||||
if ((rc = joinleave_mcgroup (conn, join, srcloc, mcloc, &gv->interfaces[i])) < 0)
|
if (joinleave_mcgroup (conn, join, srcloc, mcloc, &gv->interfaces[i]) < 0)
|
||||||
fails++;
|
fails++;
|
||||||
else
|
else
|
||||||
oks++;
|
oks++;
|
||||||
|
|
|
@ -103,10 +103,10 @@ int find_own_ip (struct ddsi_domaingv *gv, const char *requested_address)
|
||||||
switch (ifa->type)
|
switch (ifa->type)
|
||||||
{
|
{
|
||||||
case DDSRT_IFTYPE_WIFI:
|
case DDSRT_IFTYPE_WIFI:
|
||||||
DDS_LOG(DDS_LC_CONFIG, " wireless");
|
GVLOG (DDS_LC_CONFIG, " wireless");
|
||||||
break;
|
break;
|
||||||
case DDSRT_IFTYPE_WIRED:
|
case DDSRT_IFTYPE_WIRED:
|
||||||
DDS_LOG(DDS_LC_CONFIG, " wired");
|
GVLOG (DDS_LC_CONFIG, " wired");
|
||||||
break;
|
break;
|
||||||
case DDSRT_IFTYPE_UNKNOWN:
|
case DDSRT_IFTYPE_UNKNOWN:
|
||||||
break;
|
break;
|
||||||
|
|