==============================================================
RTI Connext DDS hello_lightweight_security Example Application
==============================================================

Welcome to Connext! This example features communication between a publisher and
a subscriber using the Lightweight Security Plugins. You can read more about
this capability in the Security Plugins User's Manual chapter called "The
Lightweight Security Plugins".

Compiling this Example
======================
You must set the environment variable NDDSHOME to your Connext
installation directory.

To build this example on a Windows platform, open the appropriate solution
file for your version of Microsoft Visual Studio in the win32 directory. Select
from the configuration pull-down menu: Debug, Release, Debug DLL, or Release
DLL, where "DLL" is for dynamic linking.

To build this example for a QNX platform, you must set the environment variables
QNX_HOST and QNX_TARGET. For example:

setenv QNX_BASE /opt/qnx660
setenv QNX_HOST ${QNX_BASE}/host/linux/x86
setenv QNX_TARGET ${QNX_BASE}/target/qnx6

To build this example on a Linux or macOS system, type the following in a
command shell:

  > make -f makefile_HelloWorld_<architecture>

This example is not supported on Android architectures.

All combinations of static/dynamic libraries and release/debug libraries are
supported. The dynamic libraries use the QoS profile for specifying the security
plugin, and the static libraries use code for that. Static/release is the
default. To use dynamic libraries, run:

 > make -f makefile_HelloWorld_<architecture> SHAREDLIB=1

To use debug libraries, run:

 > make -f makefile_HelloWorld_<architecture> DEBUG=1

By default, the OpenSSL crypto library is used. To use the wolfSSL crypto
library, run:

> make -f makefile_HelloWorld_<architecture> WOLFSSL=1

or

> make -f makefile_HelloWorld_<architecture> CRYPTO_LIB=WOLFSSL

You can use the wolfSSL crypto library if your Connext installation includes the
Security Plugins for wolfSSL.

Running this Example
====================

Linux and macOS systems
-----------------------
If you are using dynamic libraries, your LD_LIBRARY_PATH must include
$NDDSHOME/lib/<architecture>.

You must also include the path to your crypto library. If you are compiling
against the Security Plugins with OpenSSL, your LD_LIBRARY_PATH must include
$NDDSHOME/third_party/openssl-<version>/<architecture>/<release or debug>/lib
(location of libcrypto.so).
If you are compiling against the Security Plugins for use with wolfSSL, your
LD_LIBRARY_PATH must include $NDDSHOME/third_party/wolfssl-<version>/<architecture>/<release or debug>/lib
(location of libwolfssl.so).

If you are compiling for wolfSSL, your LD_LIBRARY_PATH must also include the
path to the Security Plugins for wolfSSL libraries
(libnddslightweightsecurity.so). Add
$NDDSHOME/lib/<architecture>/wolfssl-<version>/ to your LD_LIBRARY_PATH. Make
sure to add this before the path to the general libraries
($NDDSHOME/lib/<architecture>). Otherwise, your application may attempt to load
the default Security Plugins for OpenSSL library.

If using Certicom Security Builder Engine for QNX, your LD_LIBRARY_PATH must include
$NDDSHOME/third_party/openssl-<version>/<architecture>/release/lib/:$CERTICOM_SBENGINEHOME/tools/sb/sb-$CERTICOMOS/lib/:$CERTICOM_SBENGINEHOME/lib/$CERTICOMOS.

To run this example, type the following commands in two different command shells
(one command in each shell), either on the same machine or on different machines:

  > objs/<architecture>/HelloWorld_subscriber
  > objs/<architecture>/HelloWorld_publisher

Windows systems
---------------
If using dynamic libraries, your PATH must include
%NDDSHOME%\lib\<architecture> and %NDDSHOME%\third_party\openssl-<version>\<architecture>\<release or debug>\bin
(location of the libcrypto DLL).

To run this example, type the following commands in two different command shells
(one command in each shell), either on the same machine or on different machines:

  > objs\<architecture>\HelloWorld_subscriber.exe
  > objs\<architecture>\HelloWorld_publisher.exe

VxWorks Kernel Mode
-------------------
In case the application is linked dynamically (using SHAREDLIB=1 when compiling the example with make),
run these commands to load the Connext libraries:
  -> ld 1 < <NDDSHOME>/lib/<architecture>/libnddscore.so
  -> ld 1 < <NDDSHOME>/lib/<architecture>/libnddsc.so
  -> ld 1 < <NDDSHOME>/lib/<architecture>/libnddslightweightsecurity.so

Then load the publisher and subscriber modules:
  -> ld 1 < objs/<architecture>/HelloWorld_publisher.so
  -> ld 1 < objs/<architecture>/HelloWorld_subscriber.so

If you compiled the pubsub single DKM (using the "pubsub" argument when calling make), load it instead:
  -> ld 1 < objs/<architecture>/HelloWorld_pubsub.so

Before running the publisher and subscriber, make sure that your current working
directory is in the hello_lightweight_security folder. This directory must contain the USER_QOS_PROFILES.xml. Otherwise,
the publisher and subscriber won't be able to read the example QoS profiles. Also, take into account
that the USER_QOS_PROFILES.xml relies on files under <rti_workspace>/examples/dds_security being relative paths, so make
sure the location is available in your target.
Spawn the corresponding kernel tasks with the following commands:
  -> taskSpawn "Publisher", 100, 0x01000000, <stack_size>, publisher_main, <domain_id>, <sample_count>, <seed_in_file>
  -> taskSpawn "Subscriber", 100, 0x01000000, <stack_size>, subscriber_main, <domain_id>, <sample_count>, <seed_in_file>

VxWorks RTP Mode
----------------
If the example was dynamically linked, the Connext libraries must be
available in the VxWorks target so LD_LIBRARY_PATH can point to it,
along with any system libraries from the VSB (such as libc.so.1). Before
running the example make sure you set the LD_LIBRARY_PATH:
  -> putenv "LD_LIBRARY_PATH=<path_to_ndds_libraries>;<path_to_system_libraries>"

Run the examples from the hello_lightweight_security folder so the provided USER_QOS_PROFILES.xml
file is used. Also, take into account that the USER_QOS_PROFILES.xml relies on
files under <rti_workspace>/examples/dds_security being relative paths, so make
sure the location is available in your target.
  -> cmd rtp exec objs/<architecture>/HelloWorld_publisher.vxe -- <domain_id> <sample_count> <seed_in_file>
  -> cmd rtp exec objs/<architecture>/HelloWorld_subscriber.vxe -- <domain_id> <sample_count> <seed_in_file>

Accepted parameters
-------------------
This example is a modified version of an rtiddsgen generated HelloWorld
application. It has been modified to use security profiles. The publisher and
the subscriber sides accept a domain ID and a sample count as the first two
parameters, just like the hello_world example.

The publisher and subscriber applications also accept a third parameter that
indicates how to read the value of the pre-shared key. If you pass -file as the
third parameter, then these applications will read the pre-shared key from the
file specified in the dds.sec.crypto.rtps_psk_secret_passphrase property. You
can change the contents of this file at runtime and see how the key is updated.
If you don't pass -file as the third argument, then the property will contain
directly the identifier and value of the passphrase (prepended by the data:,
prefix). This example does not support changing between the data:, and file:
options at runtime.

Demonstrating the Lightweight Security Plugins
----------------------------------------------
The example uses a scripted set of actions in order to demonstrate the
Lightweight Security Plugins and the mutability of the pre-shared key.
If you prefer to choose your own set of actions, you can uncomment this line in
HelloWorld_publisher.c and HelloWorld_subscriber.c:

/* #define RTI_INTERACTIVE_MODE */

The following steps are suggested for the demonstration:

1. Run objs/x64Linux4gcc7.3.0/HelloWorld_publisher <domainId>
2. Run objs/x64Linux4gcc7.3.0/HelloWorld_subscriber <domainId>

Publisher output if using OpenSSL:
    Waiting for discovery...
    publication matched count changed by 1. Current count: 1
    Discovery complete! Writing samples and performing an action every 5 samples...
    [...]
    Writing HelloWorld, count 3
    Writing HelloWorld, count 4
    Update pre-shared key seed? (y/n):	y
    Writing HelloWorld, count 5
    Writing HelloWorld, count 6
    Writing HelloWorld, count 7
    [...]
    Writing HelloWorld, count 13
    Writing HelloWorld, count 14

Subscriber output if using OpenSSL:
    Waiting for discovery...
    subscription matched count changed by 1. Current count: 1
    Received data

    [...]
    msg: "Hello Lightweight World (3)"
    HelloWorld subscriber sleeping for 4 sec...
    Received data

    msg: "Hello Lightweight World (4)"
    HelloWorld subscriber sleeping for 4 sec...
    HelloWorld subscriber sleeping for 4 sec...
    HelloWorld subscriber sleeping for 4 sec...
    HelloWorld subscriber sleeping for 4 sec...

    [...]
    Update pre-shared key seed? (y/n):	y
    HelloWorld subscriber sleeping for 4 sec...
    Received data

    msg: "Hello Lightweight World (9)"
    HelloWorld subscriber sleeping for 4 sec...
    Received data

    msg: "Hello Lightweight World (10)"
    HelloWorld subscriber sleeping for 4 sec...
    Received data

    msg: "Hello Lightweight World (11)"

In the beginning, both the publisher and subscriber start with the same value of
the dds.sec.crypto.rtps_psk_secret_passphrase property. They can communicate
successfully with each other.

After a few samples, the publisher DomainParticipant updates the value of its
pre-shared key, and the subscriber DomainParticipant stops receiving the data.

If you modify the USER_QOS_PROFILES.xml file and change the verbosity of the
Security Plugins:

    <domain_participant_qos>
        <property>
            <value>
                [...]
                <element>
                    <name>com.rti.serv.secure.logging.verbosity</name>
                    <value>WARNING</value>
                </element>
            </value>
        </property>
    </domain_participant_qos>

Then you will see log messages similar to this one (but with your key ids):

    WARNING [...]|DECODE RTPS message from [...]
    RTI_Security_CryptographyLightweight_decode_rtps_message: [...]
    "received message encoded using a different pre-shared key. Current
    pre-shared key has id=1, but remote message was encoded with pre-shared key
    id=0"

The situation continues until the subscriber updates its pre-shared key so that
it has the same value as the publisher's. At that point, communication between
the publisher and subscriber DomainParticipants resumes.

Interoperability with the full Security Plugins
-----------------------------------------------

Run a publisher from the hello_security example using the "preshared" profile
(third command-line argument). Make sure that it can communicate with the
subscriber from this example. Communication should also succeed if the
publisher is a DomainParticipant from the Lightweight Security Plugins and the
subscriber is a DomainParticipant from the full Security Plugins.

Communication should not take place when running the hello_security example
with the default profile.
