FSM combine event and timeout thread

Signed-off-by: Marcel Jordense <marcel.jordense@adlinktech.com>
This commit is contained in:
Marcel Jordense 2020-01-14 11:26:59 +01:00 committed by eboasson
parent 0b1804e039
commit a9b9a65e1b
10 changed files with 755 additions and 895 deletions

View file

@ -1994,6 +1994,8 @@ threads exist:
* tev: general timed-event handling, retransmits and discovery; * tev: general timed-event handling, retransmits and discovery;
* fsm: finite state machine thread for handling security handshake;
* xmit.CHAN: transmit thread for channel CHAN; * xmit.CHAN: transmit thread for channel CHAN;
* dq.CHAN: delivery thread for channel CHAN; * dq.CHAN: delivery thread for channel CHAN;

View file

@ -1609,6 +1609,9 @@ for discovery;</li>
<li><i>tev</i>: general timed-event handling, retransmits and <li><i>tev</i>: general timed-event handling, retransmits and
discovery;</li> discovery;</li>
<li><i>fsm</i>: finite state machine thread for handling security
handshake;</li>
<li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li> <li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li>
<li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li> <li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li>

View file

@ -2133,6 +2133,9 @@ for discovery;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;tev&lt;/i&gt;: general timed-event handling, retransmits and &lt;li&gt;&lt;i&gt;tev&lt;/i&gt;: general timed-event handling, retransmits and
discovery;&lt;/li&gt; discovery;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;fsm&lt;/i&gt;: finite state machine thread for handling security
handshake;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;xmit.CHAN&lt;/i&gt;: transmit thread for channel CHAN;&lt;/li&gt; &lt;li&gt;&lt;i&gt;xmit.CHAN&lt;/i&gt;: transmit thread for channel CHAN;&lt;/li&gt;
&lt;li&gt;&lt;i&gt;dq.CHAN&lt;/i&gt;: delivery thread for channel CHAN;&lt;/li&gt; &lt;li&gt;&lt;i&gt;dq.CHAN&lt;/i&gt;: delivery thread for channel CHAN;&lt;/li&gt;

View file

@ -531,6 +531,7 @@ static const struct cfgelem thread_properties_cfgattrs[] = {
<li><i>dq.builtins</i>: delivery thread for DDSI-builtin data, primarily for discovery;</li>\n\ <li><i>dq.builtins</i>: delivery thread for DDSI-builtin data, primarily for discovery;</li>\n\
<li><i>lease</i>: DDSI liveliness monitoring;</li>\n\ <li><i>lease</i>: DDSI liveliness monitoring;</li>\n\
<li><i>tev</i>: general timed-event handling, retransmits and discovery;</li>\n\ <li><i>tev</i>: general timed-event handling, retransmits and discovery;</li>\n\
<li><i>fsm</i>: finite state machine thread for handling security handshake;</li>\n\
<li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li>\n\ <li><i>xmit.CHAN</i>: transmit thread for channel CHAN;</li>\n\
<li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li>\n\ <li><i>dq.CHAN</i>: delivery thread for channel CHAN;</li>\n\
<li><i>tev.CHAN</i>: timed-even thread for channel CHAN.</li></ul>") }, <li><i>tev.CHAN</i>: timed-even thread for channel CHAN.</li></ul>") },

View file

@ -397,10 +397,10 @@ static int known_channel_p (const struct q_globals *gv, const char *name)
static int check_thread_properties (const struct q_globals *gv) static int check_thread_properties (const struct q_globals *gv)
{ {
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS #ifdef DDSI_INCLUDE_NETWORK_CHANNELS
static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "debmon", NULL }; static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "debmon", "fsm", NULL };
static const char *chanprefix[] = { "xmit.", "tev.","dq.",NULL }; static const char *chanprefix[] = { "xmit.", "tev.","dq.",NULL };
#else #else
static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "xmit.user", "dq.user", "debmon", NULL }; static const char *fixed[] = { "recv", "tev", "gc", "lease", "dq.builtins", "xmit.user", "dq.user", "debmon", "fsm", NULL };
#endif #endif
const struct config_thread_properties_listelem *e; const struct config_thread_properties_listelem *e;
int ok = 1, i; int ok = 1, i;

View file

@ -55,3 +55,4 @@ install(
COMPONENT dev) COMPONENT dev)
add_subdirectory(tests) add_subdirectory(tests)
add_subdirectory(tests/plugin_loading)

View file

@ -14,14 +14,18 @@
#define DDS_SECURITY_FSM_H #define DDS_SECURITY_FSM_H
#include "dds/ddsrt/time.h" #include "dds/ddsrt/time.h"
#include "dds/ddsrt/threads.h" #include "dds/ddsi/q_globals.h"
#if defined (__cplusplus) #if defined (__cplusplus)
extern "C" { extern "C" {
#endif #endif
#define DDS_SECURITY_FSM_EVENT_AUTO (-1) #define DDS_SECURITY_FSM_EVENT_AUTO (-1)
#define DDS_SECURITY_FSM_EVENT_TIMEOUT (-2) #define DDS_SECURITY_FSM_EVENT_TIMEOUT (-2)
#define DDS_SECURITY_FSM_EVENT_DELETE (-3)
struct dds_security_fsm;
struct dds_security_fsm_control;
typedef enum { typedef enum {
DDS_SECURITY_FSM_DEBUG_ACT_DISPATCH, DDS_SECURITY_FSM_DEBUG_ACT_DISPATCH,
@ -29,13 +33,6 @@ typedef enum {
DDS_SECURITY_FSM_DEBUG_ACT_HANDLING DDS_SECURITY_FSM_DEBUG_ACT_HANDLING
} DDS_SECURITY_FSM_DEBUG_ACT; } DDS_SECURITY_FSM_DEBUG_ACT;
struct dds_security_fsm;
struct dds_security_fsm_context;
typedef ddsrt_thread_t (*dds_security_fsm_thread_create_func)(const char *name, ddsrt_thread_routine_t f, void *arg);
typedef void (*dds_security_fsm_thread_destroy_func)( ddsrt_thread_t tid);
/** /**
* Template for user-defined state methods. * Template for user-defined state methods.
* It is allowed to call dds_security_fsm_dispatch() from within a dispatch function. * It is allowed to call dds_security_fsm_dispatch() from within a dispatch function.
@ -62,8 +59,7 @@ typedef struct dds_security_fsm_state {
* It is not allowed to call any fsm API functions from within this * It is not allowed to call any fsm API functions from within this
* debug callback. * debug callback.
*/ */
typedef void (*dds_security_fsm_debug)(struct dds_security_fsm *fsm, DDS_SECURITY_FSM_DEBUG_ACT act, typedef void (*dds_security_fsm_debug)(struct dds_security_fsm *fsm, DDS_SECURITY_FSM_DEBUG_ACT act, const dds_security_fsm_state *current, int event_id, void *arg);
const dds_security_fsm_state *current, int event_id, void *arg);
/** /**
* Transition definitions * Transition definitions
@ -80,34 +76,6 @@ typedef struct dds_security_fsm_transition {
const dds_security_fsm_state *end; const dds_security_fsm_state *end;
} dds_security_fsm_transition; } dds_security_fsm_transition;
/**
* Create a new fsm context
* Creates an fsm context. The fsm context manages the global state of the fsm's created within
* this context. The fsm context uses a number of threads to control the state machined allocated
* to this context. A thread create callback has to be provided to created the threads in the
* context of the caller.
*
* @param thr_create_func a callback function used to created the threads used to manage
* the allocated state machines
*
* @return Returns the new fsm context on success. Null on failure.
*/
DDS_EXPORT struct dds_security_fsm_context *
dds_security_fsm_context_create( dds_security_fsm_thread_create_func thr_create_func);
/**
* Destroys a fsm context
* The function clears the fsm context and stops the associated threads. The thread destroy
* function is called to allow the caller to free resources associated with the threads and
* to wait for the threads to exit.
*
* @param context the context to be destroyed
* @param thr_destroy_func a callback function used to wait a thread to terminate
* the allocated state machine
*/
DDS_EXPORT void
dds_security_fsm_context_destroy(struct dds_security_fsm_context *context,
dds_security_fsm_thread_destroy_func thr_destroy_func);
/** /**
* Create a new fsm * Create a new fsm
@ -121,8 +89,8 @@ dds_security_fsm_context_destroy(struct dds_security_fsm_context *context,
* @return Returns the new created state machine on success. Null on failure. * @return Returns the new created state machine on success. Null on failure.
*/ */
DDS_EXPORT struct dds_security_fsm * DDS_EXPORT struct dds_security_fsm *
dds_security_fsm_create(struct dds_security_fsm_context *context, dds_security_fsm_create(struct dds_security_fsm_control *control, const dds_security_fsm_transition *transitions, uint32_t size, void *arg);
const dds_security_fsm_transition *transitions, int size, void *arg);
/** /**
* Start a fsm * Start a fsm
@ -164,20 +132,10 @@ dds_security_fsm_set_debug(struct dds_security_fsm *fsm, dds_security_fsm_debug
* *
* @param fsm The state machine * @param fsm The state machine
* @param event_id Indicate where to transisition to (outcome of current state) * @param event_id Indicate where to transisition to (outcome of current state)
* @param prio Indicates if the event has to be scheduled with priority.
*/ */
DDS_EXPORT void DDS_EXPORT void
dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id); dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id, bool prio);
/**
* Dispatches the next event with priority
* Assignment for the state machine to transisiton to the next state.
* This event will be placed at the top of the event list.
*
* @param fsm The state machine
* @param event_id Indicate where to transisition to (outcome of current state)
*/
DDS_EXPORT void
dds_security_fsm_dispatch_direct(struct dds_security_fsm *fsm, int32_t event_id);
/** /**
* Retrieve the current state of a given state machine * Retrieve the current state of a given state machine
@ -190,17 +148,7 @@ DDS_EXPORT const dds_security_fsm_state*
dds_security_fsm_current_state(struct dds_security_fsm *fsm); dds_security_fsm_current_state(struct dds_security_fsm *fsm);
/** /**
* Clean the given state machine * Free the state machine.
* Cleaning up the given state machine. This will abort all timeouts for
* this state machine and remove all events from the internals.
*
* @param fsm The state machine to clean.
*/
DDS_EXPORT void
dds_security_fsm_cleanup(struct dds_security_fsm *fsm);
/**
* Freeing the state machine.
* Stops all running timeouts and events and cleaning all memory * Stops all running timeouts and events and cleaning all memory
* related to this machine. * related to this machine.
* *
@ -212,11 +160,51 @@ dds_security_fsm_cleanup(struct dds_security_fsm *fsm);
* not block. It will garbage collect when the event has been * not block. It will garbage collect when the event has been
* handled. * handled.
* *
* @param fsm The state machine to free * @param fsm The state machine to be removed
*/ */
DDS_EXPORT void /* Implicit cleanup. */ DDS_EXPORT void
dds_security_fsm_free(struct dds_security_fsm *fsm); dds_security_fsm_free(struct dds_security_fsm *fsm);
/**
* Create a new fsm control context,
* The fsm control context manages the global state of the fsm's created within
* this context. The fsm control a thread to control the state machined allocated
* to this control.
*
* @param gv The global settings.
*
* @return Returns the new fsm control on success. Null on failure.
*/
DDS_EXPORT struct dds_security_fsm_control *
dds_security_fsm_control_create (struct q_globals *gv);
/**
* Frees the fsm control and the allocated fsm's.
* A precondition is that the fsm control is stopped.
*
* @param control The fsm control to be freed.
*/
DDS_EXPORT void
dds_security_fsm_control_free(struct dds_security_fsm_control *control);
/**
* Starts the thread that handles the events and timeouts associated
* with the fsm that are managed by this fsm control.
*
* @param control The fsm control to be started.
*/
DDS_EXPORT dds_return_t
dds_security_fsm_control_start (struct dds_security_fsm_control *control, const char *name);
/**
* Stops the thread that handles the events and timeouts.
*
* @param control The fsm control to be started.
*/
DDS_EXPORT void
dds_security_fsm_control_stop(struct dds_security_fsm_control *control);
#if defined (__cplusplus) #if defined (__cplusplus)
} }
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -27,13 +27,10 @@ target_include_directories(
"$<BUILD_INTERFACE:$<TARGET_PROPERTY:security_core,INTERFACE_INCLUDE_DIRECTORIES>>" "$<BUILD_INTERFACE:$<TARGET_PROPERTY:security_core,INTERFACE_INCLUDE_DIRECTORIES>>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/../../../../core/ddsi/include>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../../core/ddsi/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../../core/ddsc/src>"
) )
target_link_libraries(cunit_security_core PRIVATE ddsc security_api) target_link_libraries(cunit_security_core PRIVATE ddsc security_api)
target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
# configure_file("config_env.h.in" "config_env.h")

View file

@ -1,43 +1,45 @@
#include "dds/security/core/dds_security_fsm.h" /*
#include "dds/ddsrt/sync.h" * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#include "dds/ddsrt/misc.h" *
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include "dds/ddsrt/sync.h"
#include "dds/ddsrt/misc.h"
#include "CUnit/CUnit.h" #include "CUnit/CUnit.h"
#include "CUnit/Test.h" #include "CUnit/Test.h"
#include "dds/dds.h"
#include "dds__types.h"
#include "dds__entity.h"
#include "dds/security/core/dds_security_fsm.h"
#define CHECK_BIT(var, pos) ((var) & (1<<(pos))) #define CHECK_BIT(var, pos) ((var) & (1<<(pos)))
#define FSM_AUTH_ARG 10 #define FSM_AUTH_ARG 10
#define DB_TC_PRINT_DEBUG (false) #define DB_TC_PRINT_DEBUG (true)
static struct dds_security_fsm *fsm_auth; static dds_entity_t g_participant = 0;
static struct dds_security_fsm *fsm_test; static struct dds_security_fsm_control *g_fsm_control = NULL;
static struct dds_security_fsm *fsm_timeout; static const dds_duration_t msec100 = DDS_MSECS(100);
static struct dds_security_fsm *fsm_timeout2;
static struct dds_security_fsm *fsm_timeout3;
static uint32_t visited_auth = 0; //static int fsm_arg = FSM_AUTH_ARG;
static uint32_t visited_test = 0;
static uint32_t visited_timeout = 0;
uint32_t correct_fsm = 0;
uint32_t correct_arg = 0;
uint32_t correct_fsm_timeout = 0;
uint32_t correct_arg_timeout = 0;
static ddsrt_cond_t stop_timeout_cond; /**********************************************************************
static ddsrt_mutex_t stop_timeout_cond_mutex;
static uint32_t stop_timeout_cond_cnt = 0;
static int validate_remote_identity_first = 1;
static int begin_handshake_reply_first = 1;
static int do_stuff_counter = 0;
static int do_other_stuff_counter = 0;
/*
* Authentication State Machine properties and methods * Authentication State Machine properties and methods
*/ **********************************************************************/
typedef enum { typedef enum {
VALIDATION_PENDING_RETRY, VALIDATION_PENDING_RETRY,
VALIDATION_FAILED, VALIDATION_FAILED,
@ -48,8 +50,16 @@ typedef enum {
PluginReturn_MAX PluginReturn_MAX
} PluginReturn; } PluginReturn;
static PluginReturn validate_remote_identity(void) { static struct dds_security_fsm *fsm_auth;
static uint32_t visited_auth = 0;
static uint32_t correct_fsm = 0;
static uint32_t correct_arg = 0;
static int validate_remote_identity_first = 1;
static int begin_handshake_reply_first = 1;
static PluginReturn validate_remote_identity(void)
{
if (DB_TC_PRINT_DEBUG) { if (DB_TC_PRINT_DEBUG) {
printf("validate_remote_identity - %d\n", validate_remote_identity_first); printf("validate_remote_identity - %d\n", validate_remote_identity_first);
} }
@ -60,8 +70,8 @@ static PluginReturn validate_remote_identity(void) {
return VALIDATION_PENDING_HANDSHAKE_MESSAGE; return VALIDATION_PENDING_HANDSHAKE_MESSAGE;
} }
static PluginReturn begin_handshake_reply(void) { static PluginReturn begin_handshake_reply(void)
{
if (DB_TC_PRINT_DEBUG) { if (DB_TC_PRINT_DEBUG) {
printf("begin_handshake_reply - %d\n", begin_handshake_reply_first); printf("begin_handshake_reply - %d\n", begin_handshake_reply_first);
} }
@ -72,12 +82,14 @@ static PluginReturn begin_handshake_reply(void) {
return VALIDATION_OK_FINAL_MESSAGE; return VALIDATION_OK_FINAL_MESSAGE;
} }
static PluginReturn get_shared_secret(void) { static PluginReturn get_shared_secret(void)
{
return VALIDATION_OK; return VALIDATION_OK;
} }
/* State actions. */ /* State actions. */
static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg) { static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg)
{
PluginReturn ret; PluginReturn ret;
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
@ -88,10 +100,11 @@ static void fsm_validate_remote_identity(struct dds_security_fsm *fsm, void *arg
printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret);
} }
dds_security_fsm_dispatch(fsm, (int32_t) ret); dds_security_fsm_dispatch(fsm, (int32_t) ret, false);
} }
static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) { static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg)
{
PluginReturn ret; PluginReturn ret;
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
@ -105,18 +118,18 @@ static void fsm_begin_handshake_reply(struct dds_security_fsm *fsm, void *arg) {
printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret); printf("[%p] State %s (ret %d)\n", fsm, __FUNCTION__, (int) ret);
} }
dds_security_fsm_dispatch(fsm, (int32_t) ret); dds_security_fsm_dispatch(fsm, (int32_t) ret, false);
} }
/* A few states from the handshake state-machine. */ /* A few states from the handshake state-machine. */
static dds_security_fsm_state StateValidateRemoteIdentity = { static dds_security_fsm_state StateValidateRemoteIdentity = {fsm_validate_remote_identity, 0};
fsm_validate_remote_identity, 0};
static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000}; static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000};
static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0}; static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0};
static dds_security_fsm_state StateBeginHandshakeReply = {fsm_begin_handshake_reply, 0}; static dds_security_fsm_state StateBeginHandshakeReply = {fsm_begin_handshake_reply, 0};
static dds_security_fsm_state StateBeginHsReplyWait = {NULL, 100000000}; static dds_security_fsm_state StateBeginHsReplyWait = {NULL, 100000000};
static void a(struct dds_security_fsm *fsm, void *arg) { static void a(struct dds_security_fsm *fsm, void *arg)
{
int *fsm_arg; int *fsm_arg;
if (DB_TC_PRINT_DEBUG) { if (DB_TC_PRINT_DEBUG) {
@ -141,7 +154,8 @@ static void a(struct dds_security_fsm *fsm, void *arg) {
visited_auth |= 1UL << 0; visited_auth |= 1UL << 0;
} }
static void b(struct dds_security_fsm *fsm, void *arg) { static void b(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -149,7 +163,8 @@ static void b(struct dds_security_fsm *fsm, void *arg) {
visited_auth |= 1UL << 1; visited_auth |= 1UL << 1;
} }
static void c(struct dds_security_fsm *fsm, void *arg) { static void c(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -157,7 +172,8 @@ static void c(struct dds_security_fsm *fsm, void *arg) {
visited_auth |= 1UL << 2; visited_auth |= 1UL << 2;
} }
static void d(struct dds_security_fsm *fsm, void *arg) { static void d(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -165,7 +181,8 @@ static void d(struct dds_security_fsm *fsm, void *arg) {
visited_auth |= 1UL << 3; visited_auth |= 1UL << 3;
} }
static void e(struct dds_security_fsm *fsm, void *arg) { static void e(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -173,7 +190,8 @@ static void e(struct dds_security_fsm *fsm, void *arg) {
visited_auth |= 1UL << 4; visited_auth |= 1UL << 4;
} }
static void f(struct dds_security_fsm *fsm, void *arg) { static void f(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -181,7 +199,8 @@ static void f(struct dds_security_fsm *fsm, void *arg) {
visited_auth |= 1UL << 5; visited_auth |= 1UL << 5;
} }
static void g(struct dds_security_fsm *fsm, void *arg) { static void g(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -189,7 +208,8 @@ static void g(struct dds_security_fsm *fsm, void *arg) {
visited_auth |= 1UL << 6; visited_auth |= 1UL << 6;
} }
static void h(struct dds_security_fsm *fsm, void *arg) { static void h(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -233,34 +253,35 @@ static void h(struct dds_security_fsm *fsm, void *arg) {
* .-. * .-.
* '-' * '-'
*/ */
dds_security_fsm_transition HandshakeTransistions[] = static dds_security_fsm_transition HandshakeTransistions[] = {
{{NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state {NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state
{&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, &StateValRemIdentityRetryWait},
&StateValRemIdentityRetryWait}, {&StateValidateRemoteIdentity, VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, &StateHandshakeInitMessageWait},
{&StateValidateRemoteIdentity, {&StateValRemIdentityRetryWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity},
VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, {&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, &StateBeginHandshakeReply},
&StateHandshakeInitMessageWait}, {&StateBeginHandshakeReply, VALIDATION_PENDING_RETRY, f, &StateBeginHsReplyWait},
{&StateValRemIdentityRetryWait, {&StateBeginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram
DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity}, {&StateBeginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h, &StateBeginHandshakeReply}
{ };
&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, static const uint32_t HandshakeTransistionsSize = sizeof(HandshakeTransistions)/sizeof(HandshakeTransistions[0]);
&StateBeginHandshakeReply},
{&StateBeginHandshakeReply,
VALIDATION_PENDING_RETRY, f, &StateBeginHsReplyWait},
{
&StateBeginHandshakeReply, VALIDATION_OK, g, NULL}, // Reaching NULL means end of state-diagram
{&StateBeginHsReplyWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, h,
&StateBeginHandshakeReply},};
/*
/**********************************************************************
* Example State Machine properties and methods * Example State Machine properties and methods
*/ **********************************************************************/
typedef enum { typedef enum {
eventX, eventY, eventZ, eventX, eventY, eventZ,
} test_events; } test_events;
static struct dds_security_fsm *fsm_test;
static uint32_t visited_test = 0;
static int do_stuff_counter = 0;
static int do_other_stuff_counter = 0;
/* The functions called from the state-machine. */ /* The functions called from the state-machine. */
static void doStart(struct dds_security_fsm *fsm, void *arg) { static void doStart(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -268,7 +289,8 @@ static void doStart(struct dds_security_fsm *fsm, void *arg) {
visited_test |= 1UL << 0; visited_test |= 1UL << 0;
} }
static void doRestart(struct dds_security_fsm *fsm, void *arg) { static void doRestart(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -276,7 +298,8 @@ static void doRestart(struct dds_security_fsm *fsm, void *arg) {
visited_test |= 1UL << 1; visited_test |= 1UL << 1;
} }
static void doEventStuff(struct dds_security_fsm *fsm, void *arg) { static void doEventStuff(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) if (DB_TC_PRINT_DEBUG)
@ -284,8 +307,8 @@ static void doEventStuff(struct dds_security_fsm *fsm, void *arg) {
visited_test |= 1UL << 4; visited_test |= 1UL << 4;
} }
static void doStuff(struct dds_security_fsm *fsm, void *arg) { static void doStuff(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
@ -294,15 +317,16 @@ static void doStuff(struct dds_security_fsm *fsm, void *arg) {
} }
visited_test |= 1UL << 2; visited_test |= 1UL << 2;
if (do_stuff_counter == 0) { if (do_stuff_counter < 2) {
dds_security_fsm_dispatch(fsm, eventZ); dds_security_fsm_dispatch(fsm, eventZ, false);
} else if (do_stuff_counter == 2) { } else if (do_stuff_counter == 2) {
dds_security_fsm_dispatch(fsm, eventY); dds_security_fsm_dispatch(fsm, eventY, false);
} }
++do_stuff_counter; ++do_stuff_counter;
} }
static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) { static void doOtherStuff(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
@ -311,43 +335,54 @@ static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) {
} }
visited_test |= 1UL << 3; visited_test |= 1UL << 3;
if (do_other_stuff_counter == 0) { if (do_other_stuff_counter == 0) {
dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO); dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false);
} }
if (do_other_stuff_counter == 1) { if (do_other_stuff_counter == 1) {
dds_security_fsm_dispatch(fsm, eventY); dds_security_fsm_dispatch(fsm, eventY, false);
} else if (do_other_stuff_counter == 2) { } else if (do_other_stuff_counter == 2) {
dds_security_fsm_dispatch(fsm, eventX); dds_security_fsm_dispatch(fsm, eventX, false);
} }
++do_other_stuff_counter; ++do_other_stuff_counter;
} }
dds_security_fsm_state StateA = {doStuff, 0}; static dds_security_fsm_state StateA = {doStuff, 0};
dds_security_fsm_state StateB = {doStuff, 100000000}; static dds_security_fsm_state StateB = {doStuff, 100000000};
dds_security_fsm_state StateC = {NULL, 0}; static dds_security_fsm_state StateC = {NULL, 0};
dds_security_fsm_state StateD = {doOtherStuff, 0}; static dds_security_fsm_state StateD = {doOtherStuff, 0};
dds_security_fsm_transition transitions[] = { static dds_security_fsm_transition Transitions[] = {
{NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state {NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state
{&StateA, eventZ, NULL, &StateB}, {&StateA, eventZ, NULL, &StateB},
{&StateA, eventY, doOtherStuff, &StateC}, {&StateA, eventY, doOtherStuff, &StateC},
{&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram {&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram
{&StateB, eventZ, doRestart, &StateA}, {&StateB, eventZ, doRestart, &StateA},
{&StateC, DDS_SECURITY_FSM_EVENT_AUTO, {&StateC, DDS_SECURITY_FSM_EVENT_AUTO, doEventStuff, &StateD},
doEventStuff, &StateD}, {&StateD, eventY, doEventStuff, &StateD},
{&StateD, eventY, doEventStuff, &StateD}, {&StateD, eventX, doStuff, NULL}, // Reaching NULL means end of sttimeoutate-diagram
{
&StateD, eventX, doStuff, NULL}, // Reaching NULL means end of state-diagram
}; };
static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0]);
/*
/**********************************************************************
* Timeout State Machine properties and methods * Timeout State Machine properties and methods
*/ **********************************************************************/
typedef enum { typedef enum {
eventToTimeout, eventToEnd, eventToTimeout, eventToEnd,
} timeout_events; } timeout_events;
/* The functions callld from the state-machine. */ static struct dds_security_fsm *fsm_timeout;
static void doInterupt(struct dds_security_fsm *fsm, void *arg) { static uint32_t visited_timeout = 0;
static uint32_t correct_fsm_timeout = 0;
static uint32_t correct_arg_timeout = 0;
static ddsrt_cond_t stop_timeout_cond;
static ddsrt_mutex_t stop_timeout_cond_mutex;
static uint32_t stop_timeout_cond_cnt = 0;
/* The functions called from the state-machine. */
static void doInterupt(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) { if (DB_TC_PRINT_DEBUG) {
@ -356,7 +391,8 @@ static void doInterupt(struct dds_security_fsm *fsm, void *arg) {
visited_timeout |= 1UL << 0; visited_timeout |= 1UL << 0;
} }
static void doTimeout(struct dds_security_fsm *fsm, void *arg) { static void doTimeout(struct dds_security_fsm *fsm, void *arg)
{
dds_duration_t delay4 = 4 * DDS_NSECS_IN_SEC; dds_duration_t delay4 = 4 * DDS_NSECS_IN_SEC;
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
@ -377,10 +413,11 @@ static void doTimeout(struct dds_security_fsm *fsm, void *arg) {
printf("Transition <<<< %s %d\n", __FUNCTION__, stop_timeout_cond_cnt); printf("Transition <<<< %s %d\n", __FUNCTION__, stop_timeout_cond_cnt);
} }
dds_security_fsm_dispatch(fsm, eventToTimeout); dds_security_fsm_dispatch(fsm, eventToTimeout, false);
} }
static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) { static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg)
{
int *fsm_arg; int *fsm_arg;
if (DB_TC_PRINT_DEBUG) { if (DB_TC_PRINT_DEBUG) {
@ -405,7 +442,8 @@ static void TimeoutCallback(struct dds_security_fsm *fsm, void *arg) {
} }
} }
static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) { static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
if (DB_TC_PRINT_DEBUG) { if (DB_TC_PRINT_DEBUG) {
@ -414,86 +452,121 @@ static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) {
visited_timeout |= 1UL << 3; visited_timeout |= 1UL << 3;
} }
dds_security_fsm_state StateTimeout = {doTimeout, 0}; static dds_security_fsm_state StateTimeout = {doTimeout, 0};static int fsm_arg = FSM_AUTH_ARG;
dds_security_fsm_state StateInterupt = {doInterupt, 0};
dds_security_fsm_transition timeout_transitions[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, static dds_security_fsm_state StateInterupt = {doInterupt, 0};
&StateTimeout}, // NULL state is the start state
{&StateTimeout, eventToTimeout, NULL, &StateInterupt}, static const dds_security_fsm_transition TimeoutTransitions[] = {
{&StateInterupt, {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateTimeout}, // NULL state is the start state
eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram {&StateTimeout, eventToTimeout, NULL, &StateInterupt},
{&StateInterupt,eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram
}; };
static const uint32_t TimeoutTransitionsSize = sizeof(TimeoutTransitions)/sizeof(TimeoutTransitions[0]);
/**********************************************************************
* Parallel Timeout State Machines properties and methods
**********************************************************************/
static struct dds_security_fsm *fsm_timeout1;
static struct dds_security_fsm *fsm_timeout2;
static struct dds_security_fsm *fsm_timeout3;
static dds_time_t time0 = 0; static dds_time_t time0 = 0;
static dds_time_t time1 = 0; static dds_time_t time1 = 0;
static dds_time_t time2 = 0; static dds_time_t time2 = 0;
static dds_time_t time3 = 0; static dds_time_t time3 = 0;
static void StateParTime1(struct dds_security_fsm *fsm, void *arg) { static void StateParTime1(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
time1 = dds_time(); time1 = dds_time();
} }
static void StateParTime2(struct dds_security_fsm *fsm, void *arg) { static void StateParTime2(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
time2 = dds_time(); time2 = dds_time();
} }
static void StateParTime3(struct dds_security_fsm *fsm, void *arg) { static void StateParTime3(struct dds_security_fsm *fsm, void *arg)
{
DDSRT_UNUSED_ARG(fsm); DDSRT_UNUSED_ARG(fsm);
DDSRT_UNUSED_ARG(arg); DDSRT_UNUSED_ARG(arg);
time3 = dds_time(); time3 = dds_time();
} }
dds_security_fsm_state StateParTimeout1 = {NULL, DDS_NSECS_IN_SEC}; static dds_security_fsm_state StateParTimeout1 = {NULL, DDS_SECS(1)};
dds_security_fsm_state StateParTimeout2 = {NULL, 2 * DDS_NSECS_IN_SEC}; static dds_security_fsm_state StateParTimeout2 = {NULL, DDS_SECS(2)};
dds_security_fsm_state StateParTimeout3 = {NULL, DDS_NSECS_IN_SEC}; static dds_security_fsm_state StateParTimeout3 = {NULL, DDS_SECS(1)};
dds_security_fsm_transition par_timeout_transitions_1[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, static dds_security_fsm_transition ParallelTimeoutTransitions_1[] = {
NULL, &StateParTimeout1}, // NULL state is the start state {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout1}, // NULL state is the startfsm_control_thread state
{&StateParTimeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime1, NULL}, // Reaching NULL means end of state-diagram {&StateParTimeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime1, NULL}, // Reaching NULL means end of state-diagram
}; };
static const uint32_t ParallelTimeoutTransitionsSize_1 = sizeof(ParallelTimeoutTransitions_1) / sizeof(ParallelTimeoutTransitions_1[0]);
dds_security_fsm_transition par_timeout_transitions_2[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, static dds_security_fsm_transition ParallelTimeoutTransitions_2[] = {
NULL, &StateParTimeout2}, // NULL state is the start state {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout2}, // NULL state is the start state
{&StateParTimeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime2, NULL}, // Reaching NULL means end of state-diagram {&StateParTimeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime2, NULL}, // Reaching NULL means end of state-diagram
}; };
static const uint32_t ParallelTimeoutTransitionsSize_2 = sizeof(ParallelTimeoutTransitions_2) / sizeof(ParallelTimeoutTransitions_2[0]);
dds_security_fsm_transition par_timeout_transitions_3[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, static dds_security_fsm_transition ParallelTimeoutTransitions_3[] = {
NULL, &StateParTimeout3}, // NULL state is the start state {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateParTimeout3}, // NULL state is the start state
{&StateParTimeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime3, NULL}, // Reaching NULL means end of state-diagram {&StateParTimeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime3, NULL}, // Reaching NULL means end of state-diagram
}; };
static const uint32_t ParallelTimeoutTransitionsSize_3 = sizeof(ParallelTimeoutTransitions_3) / sizeof(ParallelTimeoutTransitions_3[0]);
int fsm_arg = FSM_AUTH_ARG;
dds_time_t delay1 = DDS_NSECS_IN_SEC;
dds_time_t delay2 = 2 * DDS_NSECS_IN_SEC;
dds_time_t delay30 = 30 * DDS_NSECS_IN_SEC;
int timeout;
static const dds_duration_t msec100 = 100 * DDS_NSECS_IN_MSEC;
static void init_testcase(void) {
(void) ddsrt_mutex_init(&stop_timeout_cond_mutex);
(void) ddsrt_cond_init(&stop_timeout_cond);
static void fsm_control_init(void)
{
dds_return_t rc;
struct dds_entity *e;
g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
CU_ASSERT_FATAL(g_participant > 0);
rc = dds_entity_pin(g_participant, &e);
CU_ASSERT_FATAL(rc == 0);
g_fsm_control = dds_security_fsm_control_create (&e->m_domain->gv);
CU_ASSERT_FATAL (g_fsm_control != NULL);
dds_entity_unpin (e);
rc = dds_security_fsm_control_start (g_fsm_control, NULL);
CU_ASSERT_FATAL(rc == 0);
ddsrt_mutex_init(&stop_timeout_cond_mutex);
ddsrt_cond_init(&stop_timeout_cond);
} }
static void fini_testcase(void) { static void fsm_control_fini(void)
{
ddsrt_cond_destroy(&stop_timeout_cond); ddsrt_cond_destroy(&stop_timeout_cond);
ddsrt_mutex_destroy(&stop_timeout_cond_mutex); ddsrt_mutex_destroy(&stop_timeout_cond_mutex);
dds_security_fsm_control_stop(g_fsm_control);
dds_security_fsm_control_free(g_fsm_control);
dds_delete(g_participant);
} }
CU_Test(ddssec_fsm, create, .init = init_testcase, .fini = fini_testcase) { CU_Test(ddssec_fsm, create, .init = fsm_control_init, .fini = fsm_control_fini)
{
dds_time_t delay30 = DDS_SECS(30);
int timeout;
/* /*
* Test single running state machine * Test single running state machine
* Check creation of a single State Machine * Check creation of a single State Machine
*/ */
fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, &fsm_arg);
fsm_auth = dds_security_fsm_create(NULL, HandshakeTransistions,
sizeof(HandshakeTransistions) / sizeof(HandshakeTransistions[0]),
&fsm_arg);
CU_ASSERT_FATAL(fsm_auth != NULL) CU_ASSERT_FATAL(fsm_auth != NULL)
// set a delay that doesn't expire. Should be terminate when fsm is freed. // set a delay that doesn't expire. Should be terminate when fsm is freed.
@ -506,21 +579,20 @@ CU_Test(ddssec_fsm, create, .init = init_testcase, .fini = fini_testcase) {
// Wait for the last state to occur // Wait for the last state to occur
timeout = 100; /* 10 sec */ timeout = 100; /* 10 sec */
while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) {
&& (timeout > 0)) {
dds_sleepfor(msec100); dds_sleepfor(msec100);
timeout--; timeout--;
} }
CU_ASSERT(timeout > 0); CU_ASSERT(timeout > 0);
dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED); dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false);
timeout = 100; /* 10 sec */ timeout = 100; /* 10 sec */
while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) {
dds_sleepfor(msec100); dds_sleepfor(msec100);
timeout--; timeout--;
} }
CU_ASSERT(timeout > 0); CU_ASSERT(timeout > 0);
CU_ASSERT( CU_ASSERT(
CHECK_BIT(visited_auth, 0) && CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) && CHECK_BIT(visited_auth, 0) && CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) &&
CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && CHECK_BIT(visited_auth, 5) && CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && CHECK_BIT(visited_auth, 5) &&
@ -539,54 +611,61 @@ CU_Test(ddssec_fsm, create, .init = init_testcase, .fini = fini_testcase) {
/* /*
* Test multiple (2) running state machines * Test multiple (2) running state machines
*/ */
CU_Test(ddssec_fsm, multiple, .init = init_testcase, .fini = fini_testcase) { CU_Test(ddssec_fsm, multiple, .init = fsm_control_init, .fini = fsm_control_fini)
{
int timeout;
/*Check creation of multiple (2) State Machines*/ /*Check creation of multiple (2) State Machines*/
validate_remote_identity_first = 0; validate_remote_identity_first = 0;
begin_handshake_reply_first = 0; begin_handshake_reply_first = 0;
visited_auth = 0; visited_auth = 0;
visited_test = 0;
fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, NULL);
CU_ASSERT_FATAL(fsm_auth != NULL);
fsm_test = dds_security_fsm_create(g_fsm_control, Transitions, TransitionsSize, NULL);
CU_ASSERT_FATAL(fsm_test != NULL);
fsm_auth = dds_security_fsm_create(NULL, HandshakeTransistions,
sizeof(HandshakeTransistions) / sizeof(HandshakeTransistions[0]), NULL);
fsm_test = dds_security_fsm_create(NULL, transitions,
sizeof(transitions) / sizeof(transitions[0]), NULL);
CU_ASSERT_FALSE(fsm_auth == NULL || fsm_test == NULL);
dds_security_fsm_start(fsm_auth); dds_security_fsm_start(fsm_auth);
dds_security_fsm_start(fsm_test); dds_security_fsm_start(fsm_test);
/*Check the results of multiple running State Machines */ /* Check the results of multiple running State Machines */
// Wait for the last state to occur /* Wait for the last state to occur */
timeout = 100; /* 10 sec */ timeout = 100; /* 10 sec */
while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) {
&& (timeout > 0)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC); dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--; timeout--;
} }
CU_ASSERT_FATAL(timeout > 0); CU_ASSERT_FATAL(timeout > 0);
timeout = 100; /* 10 sec */ timeout = 100; /* 10 sec */
dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED); dds_security_fsm_dispatch(fsm_auth, SHM_MSG_RECEIVED, false);
while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) { while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC); dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--; timeout--;
} }
CU_ASSERT_FATAL(timeout > 0); CU_ASSERT_FATAL(timeout > 0);
// not all bits are set since we're running the state machine a second time // not all bits are set since we're running the state machine a second time
CU_ASSERT_FATAL( CU_ASSERT_FATAL(
CHECK_BIT(visited_auth, 0) && !CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) && CHECK_BIT(visited_auth, 0) && !CHECK_BIT(visited_auth, 1) && CHECK_BIT(visited_auth, 2) &&
!CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && !CHECK_BIT(visited_auth, 5) && !CHECK_BIT(visited_auth, 3) && CHECK_BIT(visited_auth, 4) && !CHECK_BIT(visited_auth, 5) &&
CHECK_BIT(visited_auth, 6) && !CHECK_BIT(visited_auth, 7)); CHECK_BIT(visited_auth, 6) && !CHECK_BIT(visited_auth, 7));
/* Wait for the last state to occur */
timeout = 100; /* 10 sec */ timeout = 100; /* 10 sec */
// Wait for the last state to occur
while ((dds_security_fsm_current_state(fsm_test) != NULL) && timeout > 0) { while ((dds_security_fsm_current_state(fsm_test) != NULL) && timeout > 0) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC); dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--; timeout--;
} }
CU_ASSERT_FATAL(timeout > 0); CU_ASSERT_FATAL(timeout > 0);
CU_ASSERT_FATAL(
CU_ASSERT(
CHECK_BIT(visited_test, 0) && CHECK_BIT(visited_test, 1) && CHECK_BIT(visited_test, 2) && CHECK_BIT(visited_test, 0) && CHECK_BIT(visited_test, 1) && CHECK_BIT(visited_test, 2) &&
CHECK_BIT(visited_test, 3)); CHECK_BIT(visited_test, 3));
dds_security_fsm_free(fsm_auth); dds_security_fsm_free(fsm_auth);
dds_security_fsm_free(fsm_test); dds_security_fsm_free(fsm_test);
@ -595,13 +674,15 @@ CU_Test(ddssec_fsm, multiple, .init = init_testcase, .fini = fini_testcase) {
/** /**
* Check creation of State Machine for timeout purposes * Check creation of State Machine for timeout purposes
*/ */
CU_Test(ddssec_fsm, timeout, .init = init_testcase, .fini = fini_testcase) { CU_Test(ddssec_fsm, timeout, .init = fsm_control_init, .fini = fsm_control_fini)
{
dds_time_t delay1 = DDS_SECS(1);
int timeout;
/* /*
* Test timeout monitoring of state machines * Test timeout monitoring of state machines
*/ */
fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions, fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg);
sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg);
CU_ASSERT(fsm_timeout != NULL); CU_ASSERT(fsm_timeout != NULL);
dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1);
@ -627,15 +708,19 @@ CU_Test(ddssec_fsm, timeout, .init = init_testcase, .fini = fini_testcase) {
/** /**
* Check the double global timeout * Check the double global timeout
*/ */
CU_Test(ddssec_fsm, double_timeout, .init = init_testcase, .fini = fini_testcase) { CU_Test(ddssec_fsm, double_timeout, .init = fsm_control_init, .fini = fsm_control_fini)
{
dds_time_t delay1 = DDS_SECS(1);
dds_time_t delay2 = DDS_SECS(2);
int timeout;
visited_timeout = 0; visited_timeout = 0;
fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions, fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg);
sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg);
CU_ASSERT(fsm_timeout != NULL); CU_ASSERT(fsm_timeout != NULL);
fsm_timeout2 = dds_security_fsm_create(NULL, timeout_transitions,
sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg); fsm_timeout2 = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg);
CU_ASSERT(fsm_timeout2 != NULL); CU_ASSERT(fsm_timeout2 != NULL);
dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1); dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1);
dds_security_fsm_set_timeout(fsm_timeout2, TimeoutCallback2, delay2); dds_security_fsm_set_timeout(fsm_timeout2, TimeoutCallback2, delay2);
dds_security_fsm_start(fsm_timeout); dds_security_fsm_start(fsm_timeout);
@ -646,7 +731,7 @@ CU_Test(ddssec_fsm, double_timeout, .init = init_testcase, .fini = fini_testcase
timeout--; timeout--;
} }
CU_ASSERT(CHECK_BIT(visited_timeout, 2)); CU_ASSERT(CHECK_BIT(visited_timeout, 2));
dds_security_fsm_cleanup(fsm_timeout); // dds_security_fsm_cleanup(fsm_timeout);
timeout = 100; /* 10 sec */ timeout = 100; /* 10 sec */
while ((CHECK_BIT(visited_timeout, 3) == 0) && (timeout > 0)) { while ((CHECK_BIT(visited_timeout, 3) == 0) && (timeout > 0)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC); dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
@ -664,40 +749,41 @@ CU_Test(ddssec_fsm, double_timeout, .init = init_testcase, .fini = fini_testcase
/** /**
* Check parallel state timeouts * Check parallel state timeouts
*/ */
CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testcase) { CU_Test(ddssec_fsm, parallel_timeout, .init = fsm_control_init, .fini = fsm_control_fini)
visited_timeout = 0; {
fsm_timeout = dds_security_fsm_create(NULL, par_timeout_transitions_1,
sizeof(par_timeout_transitions_1) / sizeof(par_timeout_transitions_1[0]),
&fsm_arg);
CU_ASSERT(fsm_timeout != NULL);
fsm_timeout2 = dds_security_fsm_create(NULL, par_timeout_transitions_2,
sizeof(par_timeout_transitions_2) / sizeof(par_timeout_transitions_2[0]),
&fsm_arg);
CU_ASSERT(fsm_timeout2 != NULL);
fsm_timeout3 = dds_security_fsm_create(NULL, par_timeout_transitions_3,
sizeof(par_timeout_transitions_3) / sizeof(par_timeout_transitions_3[0]),
&fsm_arg);
CU_ASSERT(fsm_timeout3 != NULL);
dds_duration_t delta1; dds_duration_t delta1;
dds_duration_t delta2; dds_duration_t delta2;
dds_duration_t delta3; dds_duration_t delta3;
int timeout;
visited_timeout = 0;
fsm_timeout1 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_1, ParallelTimeoutTransitionsSize_1, &fsm_arg);
CU_ASSERT_FATAL(fsm_timeout1 != NULL);
fsm_timeout2 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_2, ParallelTimeoutTransitionsSize_2, &fsm_arg);
CU_ASSERT_FATAL(fsm_timeout2 != NULL);
fsm_timeout3 = dds_security_fsm_create(g_fsm_control, ParallelTimeoutTransitions_3, ParallelTimeoutTransitionsSize_3, &fsm_arg);
CU_ASSERT_FATAL(fsm_timeout3 != NULL);
time0 = dds_time(); time0 = dds_time();
dds_security_fsm_start(fsm_timeout); dds_security_fsm_start(fsm_timeout1);
dds_security_fsm_start(fsm_timeout2); dds_security_fsm_start(fsm_timeout2);
dds_security_fsm_start(fsm_timeout3); dds_security_fsm_start(fsm_timeout3);
/* Wait for both to end. */ /* Wait for both to end. */
timeout = 100; /* 10 sec */ timeout = 300; /* 10 sec */
/* First, they have to be started. */ /* First, they have to be started. */
while (((dds_security_fsm_current_state(fsm_timeout) == NULL) while (((dds_security_fsm_current_state(fsm_timeout1) == NULL)
|| (dds_security_fsm_current_state(fsm_timeout2) == NULL) || (dds_security_fsm_current_state(fsm_timeout2) == NULL)
|| (dds_security_fsm_current_state(fsm_timeout3) == NULL)) && (timeout > 0)) { || (dds_security_fsm_current_state(fsm_timeout3) == NULL)) && (timeout > 0)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC); dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--; timeout--;
} }
/* Then, they have to have ended. */ /* Then, they have to have ended. */
while (((dds_security_fsm_current_state(fsm_timeout) != NULL) while (((dds_security_fsm_current_state(fsm_timeout1) != NULL)
|| (dds_security_fsm_current_state(fsm_timeout2) != NULL) || (dds_security_fsm_current_state(fsm_timeout2) != NULL)
|| (dds_security_fsm_current_state(fsm_timeout3) != NULL)) && (timeout > 0)) { || (dds_security_fsm_current_state(fsm_timeout3) != NULL)) && (timeout > 0)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC); dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
@ -727,7 +813,7 @@ CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testca
CU_ASSERT(delta3 > 750 * DDS_NSECS_IN_MSEC); CU_ASSERT(delta3 > 750 * DDS_NSECS_IN_MSEC);
CU_ASSERT(delta3 < 1250 * DDS_NSECS_IN_MSEC); CU_ASSERT(delta3 < 1250 * DDS_NSECS_IN_MSEC);
dds_security_fsm_free(fsm_timeout); dds_security_fsm_free(fsm_timeout1);
dds_security_fsm_free(fsm_timeout2); dds_security_fsm_free(fsm_timeout2);
dds_security_fsm_free(fsm_timeout3); dds_security_fsm_free(fsm_timeout3);
@ -736,11 +822,13 @@ CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testca
/** /**
* Delete with event timeout * Delete with event timeout
*/ */
CU_Test(ddssec_fsm, delete_with_timeout, .init = init_testcase, .fini = fini_testcase) { CU_Test(ddssec_fsm, delete_with_timeout, .init = fsm_control_init, .fini = fsm_control_fini)
{
int timeout;
fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg);
CU_ASSERT (fsm_timeout != NULL)
fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions,
sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg);
CU_ASSERT (fsm_timeout != NULL);
visited_timeout = 0; visited_timeout = 0;
dds_security_fsm_start(fsm_timeout); dds_security_fsm_start(fsm_timeout);