Introduction to OpenDDS

What is OpenDDS?

OpenDDS is an open-source C++ framework for exchanging data in distributed systems. It is an implementation of a group of related OMG specifications. OpenDDS is implemented in C++ and contains support for Java. Users in the OpenDDS community have contributed and maintain bindings for other languages that include C#, Node.js, and Python. OpenDDS is sponsored by the OpenDDS Foundation and is available via https://opendds.org and https://github.com/OpenDDS/OpenDDS.

Licensing Terms

OpenDDS is open source software. The source code may be freely downloaded and is open for inspection, review, comment, and improvement. Copies may be freely installed across all your systems and those of your customers. There is no charge for development or run-time licenses. The source code is designed to be compiled, and used, across a wide variety of hardware and operating systems architectures. You may modify it for your own needs, within the terms of the license agreements. You must not copyright OpenDDS software. For details of the licensing terms, see the file named LICENSE that is included in the OpenDDS source code distribution or visit https://opendds.org/about/license.html.

OpenDDS also utilizes other open source software products including MPC and ACE/TAO.

OpenDDS is open source and the development team welcomes contributions of code, tests, documentation, and ideas. Active participation by users ensures a robust implementation. Contact the OpenDDS Foundation if you are interested in contributing to the development of OpenDDS. Please note that any code or documentation that is contributed to and becomes part of the OpenDDS open source code base is subject to the same licensing terms as the rest of the OpenDDS code base.

Specifications

OpenDDS is an open source implementation of a group of related OMG specifications.

Data Distribution Service (DDS) for Real-Time Systems

This specification defines a service for efficiently distributing application data between participants in a distributed application. This is the core functionality implemented by OpenDDS for real-time publish and subscribe applications and is described throughout this document.

The version OpenDDS uses is DDS v1.4. Compliance with the specification is documented in DDS Compliance. More information about the DDS itself can be found on the DDS Foundation website.

Real-time Publish-Subscribe (RTPS)

The full name of this specification is the Real-time Publish-Subscribe Protocol DDS Interoperability Wire Protocol (DDSI-RTPS), but can also be just called RTPS. This specification describes the requirements for interoperability between DDS implementations. See RTPS Discovery and RTPS/UDP Transport for more information.

The version OpenDDS uses is RTPS v2.3. Although the document number is v2.3, it specifies protocol version 2.4. Compliance with the specification is documented in DDSI-RTPS Compliance.

DDS Security

This specification extends DDS with capabilities for authentication and encryption. OpenDDS’s support for the DDS Security specification is described in DDS Security.

The version OpenDDS uses is DDS Security v1.1. Compliance with the specification is documented in DDS Security Implementation Status.

Extensible and Dynamic Topic Types for DDS (XTypes)

This specification defines details of the type system used for the data exchanged on DDS Topics, including how schema and data are encoded for network transmission. OpenDDS’s support for XTypes is described in XTypes.

The version OpenDDS uses is DDS XTypes v1.3. Compliance with the specification is documented in Unimplemented Features and Differences From the Specification.

IDL

IDL is a language that can be used to define data structures and interfaces that can be mapped to multiple programming languages. The parser is implemented as part of tao_idl.

The version OpenDDS uses is IDL v4.2. Compliance with the specification is documented in IDL Compliance.

IDL to C++03 Language Mapping

This specification defines an IDL to C++ mapping. It’s generated by tao_idl, not opendds_idl.

The version OpenDDS uses is IDL to C++03 v1.3.

IDL to C++11 Language Mapping

This specification defines an IDL to C++ mapping that takes advantage of C++11 language features and standard library types. OpenDDS’s support for IDL to C++11 is described in Using the IDL-to-C++11 Mapping.

The version OpenDDS uses is IDL to C++11 v1.5.

IDL to Java Language Mapping

This specification defines an IDL to Java mapping and is used for the Java Bindings.

The version OpenDDS uses is IDL to Java v1.3.

Compliance

OpenDDS complies with the OMG DDS and the OMG DDSI-RTPS specifications. Details of that compliance follows here. OpenDDS also implements the OMG DDS Security specification. See Specifications for how OpenDDS complies with other specifications it implements.

DDS Compliance

Section 2 of the DDS specification defines five compliance points for a DDS implementation:

  • Minimum Profile

  • Content-Subscription Profile

  • Persistence Profile

  • Ownership Profile

  • Object Model Profile

OpenDDS complies with the entire DDS specification (including all optional profiles). This includes the implementation of all Quality of Service policies with the following notes:

Although version 1.5 of the DDS specification is not yet published, OpenDDS incorporates some changes planned for that version that are required for a robust implementation:

DDSI-RTPS Compliance

The OpenDDS implementation complies with the requirements of the OMG DDSI-RTPS specification.

OpenDDS RTPS Implementation Notes

The OMG DDSI-RTPS specification supplies statements for implementation, but not required for compliance. The following items should be taken into consideration when utilizing the OpenDDS RTPS functionality for transport and/or discovery. Section numbers of the DDSI-RTPS specification are supplied with each item for further reference.

Items not implemented in OpenDDS:

  1. Writer-side content filtering (RTPS v2.3 8.7.3 Content-filtered Topics)

    OpenDDS may still drop samples that aren’t needed (due to content filtering) by any associated readers – this is done above the transport layer

  2. RTPS v2.3 8.7.6 Coherent Sets for Presentation QoS

  3. RTPS v2.3 8.7.7 Directed Write

    OpenDDS will use the Directed Write parameter if it’s present on incoming messages (for example, messages generated by a different DDS implementation)

  4. RTPS v2.3 8.7.8 Property Lists

  5. RTPS v2.3 8.7.9 Original Writer Info for Durability QoS

    This would only be used for transient and persistent durability, which are not supported by the RTPS specification

  6. Key Hashes are not generated, but the specification makes them optional

  7. nackSuppressionDuration (Table 8.47 in RTPS v2.3 8.4.7.1 RTPS Writer) and heartbeatSuppressionDuration (Table 8.62 in RTPS v2.3 8.4.10.1 RTPS Reader).

Note

Items 3 and 4 above are described in the DDSI-RTPS specification. However, they do not have a corresponding concept in the DDS specification.

IDL Compliance

OMG IDL is used in a few different ways in the OpenDDS code base and downstream applications that use it:

  • Files that come with OpenDDS such as dds/DdsDcpsTopic.idl define parts of the API between the middleware libraries and the application. This is known as the OMG IDL Platform Specific Model (PSM).

  • Users of OpenDDS author IDL files in addition to source code files in C++ or Java.

This section only describes the latter use.

The IDL specification (version 4.2) uses the term “building block” to define subsets of the overall IDL grammar that may be supported by certain tools. OpenDDS supports the following building blocks, with notes/caveats listed below each:

  • Core Data Types

    • Support for the “fixed” data type (fixed point decimal) is incomplete.

  • Anonymous Types

    • There is limited support for anonymous types when they appear as sequence/array instantiations directly as struct field types. Using an explicitly-named type is recommended.

  • Annotations

  • Extended Data Types

    • The integer types int8, uint8, int16, uin16, int32 uint32, int64, and uint64 are supported.

    • The rest of the building block is not supported.

Extensions to the DDS Specification

Data types, interfaces, and constants in the DDS IDL module (C++ namespace, Java package) correspond directly to the DDS specification with very few exceptions:

  • DDS::SampleInfo contains an extra field starting with opendds_reserved.

  • Type-specific DataReaders (including those for Built-in Topics) have additional operations read_instance_w_condition() and take_instance_w_condition().

Additional extended behavior is provided by various classes and interfaces in the OpenDDS module/namespace/package. Those include features like Recorder and Replayer (Alternate Interfaces to Data) and also:

  • OpenDDS::DCPS::TypeSupport adds the unregister_type() operation not found in the DDS spec.

  • OpenDDS::DCPS::ALL_STATUS_MASK, NO_STATUS_MASK, and DEFAULT_STATUS_MASK are useful constants for the DDS::StatusMask type used by DDS::Entity, DDS::StatusCondition, and the various create_*() operations.

OpenDDS Implementation and Architecture

This section gives a brief overview of the OpenDDS implementation, its features, and some of its components.

Source Code Organization

Relative to DDS_ROOT:

  • the dds/ directory contains the source code for OpenDDS.

  • the tests/ directory contains tests.

  • the tools/ directory contains tools and libraries like the DCPSInfoRepo, RtpsRelay, and the Modeling SDK.

  • the DevGuideExamples/ directory contains examples used in this guide.

  • the examples/ directory contains examples not used in this guide.

  • the docs/ directory contains documentation for users and developers of OpenDDS.

Design Philosophy

The OpenDDS implementation and API is based on a fairly strict interpretation of the OMG IDL PSM. In almost all cases the OMG’s IDL-to-C++ Language Mapping is used to define how the IDL in the DDS specification is mapped into the C++ APIs that OpenDDS exposes to the client.

The main deviation from the OMG IDL PSM is that local interfaces are used for the entities and various other interfaces. These are defined as unconstrained (non-local) interfaces in the DDS specification. Defining them as local interfaces improves performance, reduces memory usage, simplifies the client’s interaction with these interfaces, and makes it easier for clients to build their own implementations.

Plugins

OpenDDS puts many implementation details into libraries that are outside the core OpenDDS_Dcps library. Making these features modular allows users to build and distribute their applications without building or distributing code their applications won’t use. It also makes it easier to replace these libraries with custom ones.

How to enable and use a particular plugin will differ based on the kind of plugin and the plugin itself, but generally they are enabled by some form of configuration setting, for example using [transport] transport_type or DCPSSecurity in a configuration file. The plugin will also have to be linked and initialized at runtime. For dynamic libraries (.dll, .dynlib or, .so files) this is done automatically as the OpenDDS will load the dynamic library and then run any initialization the plugin requires. When the plugins are statically linked, then it requires explicit linking and including an initialization header in the application that contains a global object that will initialize the plugin. If OpenDDS was built using CMake, then dds/DCPS/StaticIncludes.h can be included and the initialization headers will be included automatically based on the static libraries that were linked. Explicit linking and initialization headers can also be used with dynamic libraries. This will always load and initialize the plugin when the application starts instead of delaying until the plugin is needed.

Transports

Transmission of samples and information related to their management is accomplished via an OpenDDS-specific transport framework that allows the service to be used with a variety of transport protocols. Transports are typically specified via configuration files and are attached to various entities in the publisher and subscriber processes. See Transport Configuration for details on configuring transports generally.

.---------------------------.  .---------------------------. |  "Publisher Application"  |  |  "Subscriber Application" | | +-----------------------+ |  | +-----------------------+ | | |      "DataWriter"     | |  | |      "DataReader"     | | | +-----------------------+ |  | +-----------------------+ | | |      "Publisher"      | |  | |      "Subscriber"     | | | +-----------------------+ |  | +-----------------------+ | | |  "DomainParticipant"  | |  | |  "DomainParticipant"  | | | +-----------+-----------+ |  | +-----------+-----------+ | | |"Discovery"|"Transport"| |  | |"Transport"|"Discovery"| | | +-----o-----+-----o-----+ |  | +-----o-----+-----o-----+ | |       |           |       |  |       |           |       | |       +-----+-----+       |  |       +-----+-----+       | `-------------|-------------'  `-------------|-------------'               |                              |               |           "Network"          | ==============#==============================#==============

Transports are used along with discovery to define how OpenDDS communicates.

TCP Transport

The TCP transport (tcp) uses TCP as the transmission mechanism. It’s the default transport normally. It’s reliable, regardless of configuration.

Important

Library filename: OpenDDS_Tcp

MPC base project name: dcps_tcp

CMake target Name: OpenDDS::Tcp

Initialization header: dds/DCPS/transport/tcp/Tcp.h

[transport] transport_type: tcp

Configuration: TCP Transport Configuration Properties

RTPS/UDP Transport

The RTPS/UDP transport (rtps_udp) uses the UDP-based transport described in Real-time Publish-Subscribe (RTPS) as the transmission mechanism. It’s interoperable with other DDS implementations when used with RTPS Discovery. It’s the default transport when Safety Profile is being used. It supports reliability.

Important

Library filename: OpenDDS_Rtps_Udp

MPC base project name: dcps_rtps_udp

CMake target Name: OpenDDS::Rtps_Udp

Initialization header: dds/DCPS/transport/rtps_udp/RtpsUdp.h

[transport] transport_type: rtps_udp

Configuration: RTPS UDP Transport Configuration Properties

See also

DDS Security

For security capabilities that are possible when using RTPS Discovery and the RTPS/UDP Transport

Internet-Enabled RTPS

For using RTPS Discovery and the RTPS/UDP Transport over the internet

UDP Transport

The UDP transport (udp) uses unicasted UDP as the transmission mechanism. It doesn’t support reliability at all.

Important

Library filename: OpenDDS_Udp

MPC base project name: dcps_udp

CMake target Name: OpenDDS::Udp

Initialization header: dds/DCPS/transport/udp/Udp.h

[transport] transport_type: udp

Configuration: UDP Transport Configuration Properties

Multicast Transport

The multicast transport (mutlicast) uses multicasted UDP as the transmission mechanism. It supports reliability.

Shared Memory Transport

Note

This transport is not currently supported on macOS because macOS lacks support for POSIX unnamed semaphores.

The shared memory transport (shmem) uses shared memory on the local host as the transmission mechanism. It’s reliable, regardless of configuration.

Important

Library filename: OpenDDS_Shmem

MPC base project name: dcps_shmem

CMake target Name: OpenDDS::Shmem

Initialization header: dds/DCPS/transport/shmem/Shmem.h

[transport] transport_type: shmem

Configuration: Shared Memory Transport Configuration Properties

Custom Transports

The transport framework enables application developers to implement their own customized transports. Implementing a custom transport involves specializing a number of classes defined in the transport framework. The udp transport provides a good foundation developers may use when creating their own implementation. See the dds/DCPS/transport/udp/ directory for details.

Discovery

DDS applications must discover one another via some central agent or through some distributed scheme. OpenDDS provides three options for discovery: InfoRepo Discovery, RTPS Discovery, and Static Discovery. The choice of discovery is independent of the choice of transport in most cases. For example, one can use the TCP Transport with RTPS Discovery. Notable exceptions are:

  1. DDS Security requires using both RTPS Discovery and the RTPS/UDP Transport.

  2. To get the most out of XTypes, it’s recommended to both RTPS Discovery and the RTPS/UDP Transport

  3. Static Discovery requires RTPS/UDP Transport.

Like transports, additional discovery implementations can be created and plugged in.

InfoRepo Discovery

Note

InfoRepo discovery is scheduled for deprecation with OpenDDS 4 and scheduled for removal with OpenDDS 5.

OpenDDS contains a standalone CORBA service called The DCPS Information Repository. An instance of the DCPSInfoRepo is shared by all the participants in a domain and constitutes a centralized approach to discovery. Each OpenDDS application connects to the DCPSInfoRepo and creates records for its participants, topics, data writers, and data readers. As records for data writers and data readers are created, they are matched against the existing set of records. When matches are found, the DCPSInfoRepo invokes the participant to perform the necessary associations.

        .---------------------------.  .---------------------------.         |  "Publisher Application"  |  |  "Subscriber Application" |         | +-----------------------+ |  | +-----------------------+ |         | |      "DataWriter"     | |  | |      "DataReader"     | |         | +-----------------------+ |  | +-----------------------+ |         | |      "Publisher"      | |  | |      "Subscriber"     | |         | +-----------------------+ |  | +-----------------------+ |         | |  "DomainParticipant"  | |  | |  "DomainParticipant"  | |         | +-----------+-----------+ |  | +-----------+-----------+ |         | |"InfoRepo" |"Transport"| |  | |"Transport"|"InfoRepo" | |         | |"Discovery"|           | |  | |           |"Discovery"| |         | +-----o-----+-----o-----+ |  | +-----------+-----------+ |         |       |           |       |  |       ^           ^       |         `-------|-----------|-------'  `-------|-----------|-------'                 |           +------------------+           | "1. Publisher"  |       "3. Publisher Writes Samples"      |2. Subscriber "   Advertises" |                                          |   Discovers "   Topic"      |        .------------------------.        |   Topic                 +------->+ "InfoRepo Application" +--------+                          `------------------------'

Important

Library filename: OpenDDS_InfoRepoDiscovery

MPC base project name: dcps_inforepodiscovery

CMake target Name: OpenDDS::InfoRepoDiscovery

Initialization header: dds/DCPS/InfoRepoDiscovery/InfoRepoDiscovery.h

Configuration: Configuring for InfoRepo Discovery

The DCPSInfoRepo is not involved in data propagation; its role is limited in scope to OpenDDS applications discovering one another. The DCPSInfoRepo populates the Built-in Topics (BITs) for a participant if configured to do so. OpenDDS creates its own ORB and a separate thread to run that ORB when using DCPSInfoRepo discovery.

Application developers are free to run multiple information repositories with each managing their own non-overlapping sets of DCPS domains.

It is also possible to operate domains with more than a single repository, thus forming a distributed virtual repository. This is known as Repository Federation. In order for individual repositories to participate in a federation, each one must specify its own federation identifier value (a 32-bit numeric value) upon start-up. See Repository Federation for further information about repository federations.

See also

The DCPS Information Repository

Documentation on the DCPSInfoRepo program

RTPS Discovery

RTPS discovery is a peer-to-peer discovery mechanism standardized as part of the RTPS spec. Other DDS implementations can interoperate with OpenDDS when RTPS discovery is used with the RTPS/UDP Transport.

        .---------------------------.  .---------------------------.         |  "Publisher Application"  |  |  "Subscriber Application" |         | +-----------------------+ |  | +-----------------------+ |         | |      "DataWriter"     | |  | |      "DataReader"     | |         | +-----------------------+ |  | +-----------------------+ |         | |      "Publisher"      | |  | |      "Subscriber"     | |         | +-----------------------+ |  | +-----------------------+ |         | |  "DomainParticipant"  | |  | |  "DomainParticipant"  | |         | +-----------+-----------+ |  | +-----------+-----------+ |         | |"RTPS"     |"Transport"| |  | |"Transport"|"RTPS"     | |         | |"Discovery"|           | |  | |           |"Discovery"| |         | +-----o-----+-----o-----+ |  | +-----------+-----------+ |         |       |           |       |  |       ^           ^       |         `-------|-----------|-------'  `-------|-----------|-------'                 |           +------------------+           | "1. Publisher"  |       "3. Publisher Writes Samples"      |2. Subscriber "   Advertises" |                                          |   Discovers "   Topic"      |                                          |   Topic                 |         "RTPS SPDP Multicast Group"      |         ========#==========================================#========

Important

Library filename: OpenDDS_Rtps

MPC base project name: dcps_rtps

CMake target Name: OpenDDS::Rtps

Initialization header: dds/DCPS/RTPS/RtpsDiscovery.h

Configuration: Configuring for RTPS Discovery

RTPS Discovery uses the RTPS protocol to advertise and discover participants, data writers, and data readers. RTPS Discovery uses multicast to discover participants and built-in endpoints (not to be confused with built-in topics) each other without a centralized broker such as InfoRepo. This part of RTPS discovery is called the Simple Participant Discovery Protocol (SPDP). After the built-in endpoints are discovered and associated, they exchange information about data writers and data readers which are called endpoints. This part of RTPS discovery is called Simple Endpoint Discovery Protocol (SEDP). RTPS Discovery is a peer-to-peer approach to discovery as each participant interacts directly with other participants to accomplish discovery.

The following are additional implementation limits that developers need to take into consideration when developing and deploying applications that use RTPS discovery:

  1. Domain IDs should be between 0 and 231 (inclusive) due to the way UDP ports are assigned to domain IDs. In each OpenDDS process, up to 120 domain participants are supported in each domain.

  2. Topic names and type identifiers are limited to 256 characters.

  3. The Multicast Transport does not work with RTPS Discovery due to the way GUIDs are assigned (a warning will be issued if this is attempted).

See also

XTypes

For expanded type-system capabilities that are possible when using RTPS discovery

DDS Security

For security capabilities that are possible when using RTPS Discovery and the RTPS/UDP Transport

Internet-Enabled RTPS

For using RTPS Discovery and the RTPS/UDP Transport over the internet

Static Discovery

In Static Discovery, each participant starts with a database containing identifiers, QoS settings, and network locators for all participants, topics, data writers, data readers.

.---------------------------.  .---------------------------. |  "Publisher Application"  |  |  "Subscriber Application" | | +-----------------------+ |  | +-----------------------+ | | |      "DataWriter"     | |  | |      "DataReader"     | | | +-----------------------+ |  | +-----------------------+ | | |      "Publisher"      | |  | |      "Subscriber"     | | | +-----------------------+ |  | +-----------------------+ | | |  "DomainParticipant"  | |  | |  "DomainParticipant"  | | | +-----------+-----------+ |  | +-----------+-----------+ | | |"Static"   |"RTPS UDP" | |  | |"RTPS UDP" |"Static"   | | | |"Discovery"|"Transport"| |  | |"Transport"|"Discovery"| | | +-----------+-----o-----+ |  | +-----------+-----------+ | |                   |       |  |       ^                   | `-------------------|-------'  `-------|-------------------'                     +------------------+                 "2. Publisher Writes Samples"                                               1. Subscriber                                                  Assumes Topic

Important

The RTPS/UDP Transport is the only transport that can be used with Static Discovery.

Static Discovery is built-in to the core Dcps library, so it doesn’t require linking a separate library or including an initialization header.

Configuration: Configuring for Static Discovery

When an application creates a data writer or data reader, Static Discovery causes it to send out periodic announcements. Upon receiving one of these announcements, Static Discovery consults its local database of entities to look up the details necessary for matching and matches it against local entities.

Static Discovery requires that the User Data QoS be configured for each participant, data writer, and data reader. This user data must contain the identifier of the entity that is being created. Thus, the user data QoS is not available for general use when using Static Discovery. Static Discovery also requires that the network locators for all entities be determined up front by configuring the transport with the necessary networking information.

Threading

OpenDDS creates its own threads for handling I/O, timers, asynchronous jobs, and cleanup tasks. These threads are collectively called service threads. Applications may receive a callback from these threads via Listeners.

When publishing a sample, OpenDDS normally attempts to send the sample to any connected subscribers using the calling thread. If the send call would block, then the sample may be queued for sending on a separate service thread. This behavior depends on the QoS policies described in Quality of Service.

All incoming data is read by a service thread and queued for reading in DataReaders by the application. If a DataReader has a listener that should be invoked when data is available, then the listener is invoked by the service thread.

Configuration

OpenDDS includes a file-based configuration framework for configuring both global items such as debug level, memory allocation, and discovery, as well as transport implementation details for publishers and subscribers. Configuration can also be achieved directly in code, however, it is recommended that configuration be externalized for ease of maintenance and reduction in runtime errors. The complete set of configuration options are described in Run-time Configuration.

Footnotes