#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Hello.h"
#include "ndds/ndds_c.h"
#include "HelloPublisher.h"
#include "HelloSubscriber.h"
#include "ndds/transport_tcp/transport_tcp_tcpv4.h"
#define DEFAULT_DOMAIN_ID 0
#define APPLICATION_NAME "Hello"
#define DEFAULT_PAYLOAD 1023
#define MAX_PAYLOAD 1023
#define MIN_PAYLOAD 10
#define APP_MODE_UNDEFINED 0
#define APP_MODE_PUBLISHER 1
#define APP_MODE_SUBSCRIBER 2
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#endif
#define DEFAULT_TOPIC_NAME "Hello Builtin"
#define DOMAIN_ID_MAX 250
typedef struct CommandLineArguments_t {
const char * topic_name;
const char * addr;
char * tls_ca_cert;
char * tls_cert_chain;
} CommandLineArguments;
static void CommandLineArguments_initialize(
CommandLineArguments *arg) {
arg->mode = APP_MODE_UNDEFINED;
arg->domain_id = DEFAULT_DOMAIN_ID;
arg->data_size = DEFAULT_PAYLOAD;
arg->verbose = 0;
arg->topic_name = DEFAULT_TOPIC_NAME;
arg->sample_count = 0;
arg->addr = NULL;
arg->port = 0;
arg->tls_ca_cert = NULL;
arg->tls_cert_chain = NULL;
}
FILE *fp;
#if defined(RTI_WIN32) && (_MSC_VER > 1310)
fopen_s(&fp, "USER_QOS_PROFILES.xml", "r");
#else
fp = fopen("USER_QOS_PROFILES.xml", "r");
#endif
if (fp != NULL) {
fclose(fp);
}
}
const CommandLineArguments *arg) {
NDDS_Transport_Plugin *tcp_transport = NULL;
puts("# The output below depends on the QoS profile");
puts("# provided to this application.");
puts("# -> For more information on the provided example");
puts("# profiles, please see the Getting Started Guide.");
puts("# -> For detailed product performance metrics, visit");
puts("# http://www.rti.com/products/data_distribution/index.html");
puts("# and click on Benchmarks.\n");
if (!file_exist("USER_QOS_PROFILES.xml")) {
char *envVal;
#if defined(RTI_WIN32) && (_MSC_VER > 1310)
size_t envValSize;
_dupenv_s(&envVal, &envValSize, "NDDS_QOS_PROFILES");
#else
envVal = getenv("NDDS_QOS_PROFILES");
#endif
if (envVal == NULL || !file_exist(envVal)) {
puts("! Warning:");
puts("! Default QoS profile definition file not found.");
puts("! The application will use the DDS default QoS.");
puts("! If you want to use different QoS, make sure you have the "
"QoS definition file");
puts("! (USER_QOS_PROFILES.xml) in the current working directory");
puts("! or set the environment variable NDDS_QOS_PROFILES to");
puts("! point to a file containing the default QoS profile");
}
#if defined(RTI_WIN32) && (_MSC_VER > 1310)
if (envVal) free(envVal);
#endif
}
if (arg->verbose) {
printf("Creating domain participant...\n");
}
fprintf(stderr, "! unable to get default participant qos: %d\n", rc);
return -1;
}
{
fprintf(stderr, "! unable to get participant factory qos: %d\n", rc);
return -1;
}
fprintf(stderr, "! unable to set participant factory qos: %d\n", rc);
return -1;
}
}
{
if (arg->tls_ca_cert) {
}
if (arg->addr != NULL && arg->port != 0) {
arg->addr,
RTI_FALSE)) {
fprintf(stderr, "! unable to set TCP property 'public_address'\n");
return RTI_FALSE;
}
} else if (arg->port == 0) {
if (arg->addr != NULL) {
fprintf(stderr, "You specified a public address but the node is unreachable (the server port is not set)\n"
"The server public address parameter will be ignored.\n");
}
} else {
}
if (arg->verbose > 1) {
}
if (tcp_transport == NULL) {
fprintf(stderr, "! unable to create TCP transport plugin\n");
return RTI_FALSE;
}
}
arg->domain_id,
&part_qos,
NULL,
if (participant == NULL) {
fprintf(stderr, "! Unable to create DDS domain participant\n");
goto exitFn;
}
{
const char* ALIASES[] = { "tcp1" };
if (!DDS_StringSeq_from_array(&aliases, ALIASES, 1)) {
fprintf(stderr, "! unable to create transport alias string sequence\n");
goto exitFn;
}
participant,
tcp_transport,
&aliases,
&defaultNetworkAddress);
fprintf(stderr, "! unable to register TCP transport\n");
goto exitFn;
}
DDS_StringSeq_finalize(&aliases);
}
fprintf(stderr, "! unable to enable domain participant: %d\n", rc);
return -1;
}
if (arg->verbose) {
printf("Creating the topic...\n");
}
participant,
arg->topic_name,
NULL,
if (topic == NULL) {
fprintf(stderr, "! Unable to create topic '%s'\n",
arg->topic_name);
goto exitFn;
}
if (arg->mode == APP_MODE_PUBLISHER) {
if (!start_publisher(
participant,
topic,
arg->verbose,
arg->data_size,
arg->sample_count)) {
goto exitFn;
}
} else {
if (!start_subscriber(
participant,
topic,
arg->verbose,
arg->sample_count)) {
goto exitFn;
}
}
exitFn:
if (arg->verbose) {
printf("Cleaning up...\n");
}
if (participant != NULL) {
fprintf(stderr, "! Unable to delete participant contained "
"entities: %d\n", rc);
}
participant);
fprintf(stderr, "! Unable to delete participant: %d\n", rc);
}
}
return return_value;
}
static void usage() {
printf("Usage:\n");
printf(" %s pub [arguments] Run as publisher\n", APPLICATION_NAME);
printf(" %s sub [arguments] Run as subscriber\n", APPLICATION_NAME);
printf("Where arguments are:\n");
printf(" -h | --help "
"Shows this page\n");
printf(" -v | --verbose "
"Increase output verbosity (can be repeated)\n");
printf(" -d | --domain <domainID> "
"Sets the DDS domain ID [default=%d]\n", DEFAULT_DOMAIN_ID);
printf(" -t | --topic <name> "
"Sets topic name [default=%s]\n", DEFAULT_TOPIC_NAME);
printf(" -s | --size <num> "
"Sets payload size in bytes [default=%d]\n", DEFAULT_PAYLOAD);
printf(" -c | --sampleCount <num> "
"Sets number of samples to send/receive [default=0(UNLIMITED)]\n");
printf("TCP-transport only:\n");
printf(" --async "
"Use asynchronous send [default=use synchronous send]\n");
printf(" -a | --address <ip:port> "
"Enable WAN mode and sets the public IP and port for the TCP transport\n");
printf(" -p | --port <port> "
"Sets the server binding port and define this node as reachable (Symmetric mode)\n");
printf(" --tls-cert <ca_cert> "
"Sets certificate of authority used in TLS configuration\n");
printf(" --tls-chain <cert_chain> "
"Sets certificate chain file used in TLS configuration\n");
printf("\nConfiguration notes:\n");
printf("- If the public IP and port is not set, the transport will work in LAN\n"
" configuration mode, where all the local IP address(es) will be used \n"
" for the communication (using server binding port).\n"
"- If the server bind port (--port argument) is not provided, the node\n"
" is considered as unreachable and can only communicate with peers that\n"
" are reachable.\n");
printf("\n");
}
#define ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, arg_name) \
if (i+1 >= argc) { \
usage(); \
fprintf(stderr, "! Error: missing value for %s argument\n", \
arg_name); \
return EXIT_FAILURE; \
}
int main(int argc, char **argv) {
CommandLineArguments arg;
int i;
CommandLineArguments_initialize(&arg);
printf("Hello Example Application for TCP transport\n");
printf("Copyright 2008 Real-Time Innovations, Inc.\n\n");
if (argc < 2) {
usage();
fprintf(stderr, "! Invalid number of arguments.\n"
"! You must specify at least running mode (pub/sub)\n");
return EXIT_FAILURE;
}
if (RTI_STRCASECMP(argv[1], "pub") == 0) {
arg.mode = APP_MODE_PUBLISHER;
} else if (RTI_STRCASECMP(argv[1], "sub") == 0) {
arg.mode = APP_MODE_SUBSCRIBER;
} else if (!RTI_STRNCMP(argv[1], "-h", 2) ||
!RTI_STRNCMP(argv[1], "--help", 6)) {
usage();
return EXIT_SUCCESS;
} else {
usage();
fprintf(stderr, "! Invalid mode: '%s'\n"
"! Valid modes are only 'pub' or 'sub'.\n", argv[1]);
return EXIT_FAILURE;
}
for (i = 2; i < argc; ++i) {
if (!RTI_STRNCMP(argv[i], "-h", 2) ||
!RTI_STRNCMP(argv[i], "--help", 6)) {
usage();
return EXIT_SUCCESS;
}
if (!RTI_STRNCMP(argv[i], "-v", 2) ||
!RTI_STRNCMP(argv[i], "--verbose", 9)) {
++arg.verbose;
continue;
}
if (!RTI_STRNCMP(argv[i], "-d", 2) ||
!RTI_STRNCMP(argv[i], "--domain", 8)) {
char *ptr;
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--domain")
arg.domain_id = strtol(argv[++i], &ptr, 10);
if (*ptr != '\0') {
usage();
fprintf(stderr, "! Value of --domain argument is not "
"a number: %s\n", argv[i]);
return EXIT_FAILURE;
}
if (arg.domain_id < 0 || arg.domain_id > DOMAIN_ID_MAX) {
usage();
fprintf(stderr, "! Invalid DDS Domain ID: %d\n",
arg.domain_id);
fprintf(stderr, "! The domain ID must be between "
"0 and %d (inclusive)\n", DOMAIN_ID_MAX);
return EXIT_FAILURE;
}
continue;
}
if (!RTI_STRNCMP(argv[i], "-s", 2) ||
!RTI_STRNCMP(argv[i], "--size", 6)) {
char *ptr;
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--size")
arg.data_size = strtol(argv[++i], &ptr, 10);
if (*ptr != '\0') {
usage();
fprintf(stderr, "! Invalid value for --size option: %s\n",
argv[i]);
return EXIT_FAILURE;
}
if (arg.data_size <= 0) {
usage();
fprintf(stderr, "! Invalid value for --size argument: %d\n",
arg.data_size);
return EXIT_FAILURE;
}
if (arg.data_size > MAX_PAYLOAD) {
usage();
fprintf(stderr, "! Value too big for --size "
"argument: %d\n", arg.data_size);
fprintf(stderr, "! For built-in types, the default max "
"string size is set to %d\n", MAX_PAYLOAD);
fprintf(stderr, "! See manual on built-in types for "
"more information.\n");
return EXIT_FAILURE;
}
if (arg.data_size < MIN_PAYLOAD) {
usage();
fprintf(stderr, "! Value too small for --size "
"argument: %d\n", arg.data_size);
fprintf(stderr, "! For this example, the size of the string "
"cannot be smaller than %d\n", MIN_PAYLOAD);
return EXIT_FAILURE;
}
continue;
}
if (!RTI_STRNCMP(argv[i], "-t", 2) ||
!RTI_STRNCMP(argv[i], "--topic", 7)) {
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--topic")
arg.topic_name = argv[++i];
continue;
}
if (!RTI_STRNCMP(argv[i], "--tls-cert", 10)) {
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--tls-cert")
arg.tls_ca_cert = argv[++i];
continue;
}
if (!RTI_STRNCMP(argv[i], "--tls_chain", 10)) {
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--tls_chain")
arg.tls_cert_chain = argv[++i];
continue;
}
if (!RTI_STRNCMP(argv[i], "-c", 2) ||
!RTI_STRNCMP(argv[i], "--sampleCount", 13)) {
char *ptr;
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--sampleCount")
arg.sample_count = strtol(argv[++i], &ptr, 10);
if (*ptr != '\0') {
usage();
fprintf(stderr, "! Invalid value for --sampleCount option: %s\n",
argv[i]);
return EXIT_FAILURE;
}
if (arg.sample_count < 0) {
usage();
fprintf(stderr, "! Invalid value for --sampleCount argument: %d\n",
arg.data_size);
return EXIT_FAILURE;
}
continue;
}
if (!RTI_STRNCMP(argv[i], "-a", 2) ||
!RTI_STRNCMP(argv[i], "--address", 9)) {
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--address")
arg.addr = argv[++i];
continue;
}
if (!RTI_STRNCMP(argv[i], "--tls-cert", 10)) {
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--tls-cert")
arg.tls_ca_cert = argv[++i];
continue;
}
if (!RTI_STRNCMP(argv[i], "--tls-chain", 11)) {
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--tls-chain")
arg.tls_cert_chain = argv[++i];
continue;
}
if (!RTI_STRNCMP(argv[i], "-p", 2) ||
!RTI_STRNCMP(argv[i], "--port", 6)) {
char *ptr;
ENSURE_ONE_MORE_ARGUMENT(argc, argv, i, "--port")
arg.port = strtol(argv[++i], &ptr, 10);
if (*ptr != '\0') {
usage();
fprintf(stderr, "! Value of --port argument is not "
"a number: %s\n", argv[i]);
return EXIT_FAILURE;
}
if (arg.port < 0 || arg.port > 65535) {
usage();
fprintf(stderr, "! Invalid server port number: %d\n",
arg.port);
return EXIT_FAILURE;
}
continue;
}
if (!RTI_STRNCMP(argv[i], "--async", 7)) {
arg.async_send = RTI_TRUE;
continue;
}
usage();
fprintf(stderr, "! Unknown argument %s\n", argv[i]);
return EXIT_FAILURE;
}
if ((arg.tls_ca_cert && !arg.tls_cert_chain) ||
(!arg.tls_ca_cert && arg.tls_cert_chain)) {
fprintf(stderr, "! to enable TLS you must specify both --tls-cert and "
"--tls-chain arguments\n");
return EXIT_FAILURE;
}
if (arg.verbose) {
printf("Running with the following arguments:\n");
printf(" Verbosity level.. : %d\n", (int) arg.verbose);
printf(" Payload size..... : %d\n", (int) arg.data_size);
printf(" Sample count..... : %d\n", (int) arg.sample_count);
printf(" Domain ID........ : %d\n", (int) arg.domain_id);
printf(" Topic name....... : %s\n", arg.topic_name);
printf("RTI Product Version.. : %d.%d.%d.%d\n",
printf("TCP Settings:\n");
printf(" Public address... : %s\n",
(arg.addr == NULL ? "not set (use LAN mode)" : arg.addr));
if (arg.port) {
printf(" Server bind port. : %d\n", arg.port);
} else {
printf(" Server bind port. : not set (node is unreachable)\n");
}
printf(" Use async send... : %s\n", (arg.async_send ? "YES" : "NO"));
if (arg.tls_ca_cert) {
printf(" Use TLS ......... : YES\n");
printf(" TLS CA Cert ..... : %s\n", arg.tls_ca_cert);
printf(" TLS Cert Chain .. : %s\n", arg.tls_cert_chain);
} else {
printf(" Use TLS ......... : NO\n");
}
}
if (arg.verbose > 1) {
}
start_application(&arg);
printf("Done.\n");
return EXIT_SUCCESS;
}