Using Dynamic or Static Libraries with DDS Secure

When you link your application with the RTI Connext DDS libraries, you can choose whether to use dynamic or static linking. But what is the best approach if you want to use the DDS Secure plug-in? There are some situations that you need to be aware of and avoid. This article describes the possible scenarios and explains what could go wrong if you are not careful with your choice.

The examples in this article are for Linux, but except for small differences in names, the same concepts apply to Windows and Mac OS as well.

Suppose you have Connext DDS-based application myApp and you want to use the DDS Secure plugin to protect the communication. The library dependency is something like this:

Library dependencies

This is a very simple and common situation, but there are some cases that you need to be aware of, where you may end up with a circular dependency between the libraries.

In particular, the problem may occur when you enable the DDS Security Plugin distributed logger (see How to use DDS Secure Logging). In this case the DDS Security Plugins now performs calls into the DDS Core library, potentially creating a dangerous situation:

Library dependencies with logger enabled

 


Dynamic Linking

The easiest and more flexible situation is to use dynamic linking. Your application will load at run-time the DDS libraries (Unix: libnddsc.so, libnddscore.so), and everything can be controlled from the QoS defined in an XML file. To specify dynamic linking you are going to use something like this during the link phase of your application:

gcc -o myApp myApp.o -L$NDDSHOME/lib/$ARCH -lnddsc -lnddscore

Note: the DDS Security Plugins is NOT included in the list of required libraries because it will be dynamically loaded at run-time from the participant QoS 'com.rti.serv.secure.library':

<participant_qos>
  <property>
    <value>
      <element>
        <name>com.rti.serv.secure.library</name>
        <value>nddssecurity</value>
      </element>
    </value>
  </property>
</participant_qos>   

This is particularly useful if, for example, you are using your own security plugins library, as it can be easily defined at run-time through the QoS.

  • When your application starts, the dynamic loader will automatically load the RTI Connext DDS libraries (libnddsc.so, libnddscore.so) from your dynamic library search path. 
  • When the domain participant is created and the QoS set, the Connext core will dynamically load the security library (library will be loaded at run-time). Because the DDS Security Plugins library depends on the libnddscore.so, the dynamic loader knows that the library has been already loaded, and will automatically resolve the undefined symbols to use the currently loaded library.
  • The security library will then initialize and create the internal logger. The internal logger will initialize the DomainParticipantFactory (which is implemented in the Connext core library) and everything is good.

 


Static Linking

If you choose to statically link the RTI libraries, the mechanism for dynamic selecting and loading of the DDS Security Plugins is no longer available.
Compared to dynamic linking you need to pay attention to two items:
 
#1:
You need to include the
 DDS Secure library AND the OpenSSL dependency libraries to the list of libraries needed during linking:
gcc -o myApp myApp.o -L$NDDSHOME/lib/$ARCH -lnddscz -lnddscorez -lnddssecurityz -lcryptoz -lsslz
 
 
# 2:
In your code you need to manually tell Connext DDS the pointer to the function of the entry point of the security plugins before you create the domain participant as shown in this snippet:
#include "security/security_default.h"
 
 struct DDS_DomainParticipantQos participant_qos = DDS_DomainParticipantQos_INITIALIZER;
DDS_ReturnCode_t retcode;

retcode = DDS_DomainParticipantFactory_get_participant_qos_from_profile(
        DDS_TheParticipantFactory, &participant_qos, "AppQosLibrary::MyAppProfile",
        profile);
if (retcode != DDS_RETCODE_OK) {
    // error: Unable to get default participant qos
    [...]
}

retcode = DDS_PropertyQosPolicyHelper_assert_pointer_property(
        &participant_qos.property, 
        BUILTIN_PLUGIN_NAME ".create_function_ptr",
        RTI_Security_PluginSuite_create);
if (retcode != DDS_RETCODE_OK) {
    // error: Unable to assert create_function_ptr property
    [...]
}
/* Create the domain participant on domain ID 18 */
participant = DDS_DomainParticipantFactory_create_participant(
        DDS_TheParticipantFactory,
        18, /* Domain ID */
        &participant_qos, /* Qos */
        NULL, /* Listener */
        DDS_STATUS_MASK_NONE);
[...] 
 

IMPORTANT:
If you link statically the DDS Secure Plugins, the QoS property 'com.rti.serv.secure.library' will be silently ignored if defined!! The DDS Secure Plugins is only set at compile time. There is no run-time selection.

The example above works for RTI Connext DDS version 6.0 and newer. For older version, refer to the example code 'examples/connext_dds/c/hello_security/src/HelloWorld_subscriber.c).

 


Mixed Linking

The last scenario is when you have your application statically linked with the RTI Connext library, but you dynamically select the DDS Secure library to load at run-time.

THIS SCENARIO IS NOT VALID AND YOU SHOULD AVOID IT

You can easily end up in this faulty scenario without realizing the implications. For example you designed your statically linked application without security in mind, then you add security from the QoS. 

This scenario is not valid because when the run-time dynamic loader will load the DDS Secure library, it will also load a second copy of the Connext core libraries in memory as shown by this picture:

Library dependencies with double core libs

If you enable the distributed logger, the moment the DDS Secure library is loaded, you will get an error message like the following:

 

DDS_DomainParticipantGlobals_initializeWorkerFactoryI:!Potential library mismatch.
This may happen if your application uses the static and the shared RTI core
libraries simultaneously.
For example, using the shared RTI Monitoring library
and linking statically with the RTI core libraries will cause this mismatch

 

If you don't have the DDS Security logger enabled, your application might still work (because the detection of this condition is implemented in the initializer of the DDS Domain Participant Factory), but it is not supported and you might end up with some unexpected behavior at run-time.