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 (Make Project Creator), ACE (the ADAPTIVE Communication Environment), and TAO (The ACE ORB).

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 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:

  • RELIABILITY.kind = RELIABLE is supported by the RTPS_UDP transport, the TCP transport, or the IP Multicast transport (when configured as reliable).

  • TRANSPORT_PRIORITY is not implemented as changeable.

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 DURABLE data

    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.

Extensible Transport Framework (ETF)#

OpenDDS uses the IDL interfaces defined by the DDS specification to initialize and control service usage. Data transmission is accomplished via an OpenDDS-specific transport framework that allows the service to be used with a variety of transport protocols. This is referred to as pluggable transports and makes the extensibility of OpenDDS an important part of its architecture. OpenDDS currently supports TCP/IP, UDP/IP, IP multicast, shared-memory, and RTPS_UDP transport protocols as shown below.

../_images/pluggable.png

OpenDDS Transport Framework#

Transports are typically specified via configuration files and are attached to various entities in the publisher and subscriber processes. See Transport Configuration Options for details on configuring ETF components.

The ETF 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 (see Discovery, Matching, and Association). OpenDDS provides three options for discovery: DCPSInfoRepo, 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. Two notable exceptions are:

  1. If using DDS Security, RTPS must be used for both the transport and discovery.

  2. RTPS must be used for the transport when using Static Discovery.

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

DCPSInfoRepo#

../_images/inforepo_discovery.png

Centralized Discovery with DCPSInfoRepo#

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. 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. See Configuring Applications for DCPSInfoRepo for details on how applications can be configured to use the DCPSInfoRepo.

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.

RTPS Discovery#

../_images/rtps_discovery.png

Peer-to-peer Discovery with RTPS#

RTPS Discovery is an implementation of the OMG DDSI-RTPS (formal/2014-09-01) specification (see RTPS v2.3 8.5 Discovery Module). RTPS Discovery uses the RTPS protocol to advertise and discover participants, data writers, and data readers. RTPS Discovery uses multicast to discover participants and builtin endpoints (not to be confused with Builtin Topics). This part of RTPS discovery is called the Simple Participant Discovery Protocol (SPDP). After the builtin 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. RTPS is interoperable and supports DDS Security. RTPS discovery populates the Builtin Topics for a participant. See Configuring for DDSI-RTPS Discovery for details on how applications can be configured to use RTPS Discovery. See also RTPS_UDP Transport Configuration Options as the parameters for configuring an RTPS transport also apply to SEDP.

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. OpenDDS’s native multicast transport does not work with RTPS Discovery due to the way GUIDs are assigned (a warning will be issued if this is attempted).

Static Discovery#

In Static Discovery, each particpant starts with a database containing identifiers, QoS settings, and network locators for all participants, topics, data writers, data readers. The RTPS transport must be used with 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. See Configuring for Static Discovery for details on how applications can be configured to use Static Discovery.

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 (see 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.