diff --git a/docs/manual/options.md b/docs/manual/options.md
index f875c77..85ae1eb 100644
--- a/docs/manual/options.md
+++ b/docs/manual/options.md
@@ -1994,6 +1994,8 @@ threads exist:
* tev: general timed-event handling, retransmits and discovery;
+* fsm: finite state machine thread for handling security handshake;
+
* xmit.CHAN: transmit thread for channel CHAN;
* dq.CHAN: delivery thread for channel CHAN;
diff --git a/etc/cyclonedds.rnc b/etc/cyclonedds.rnc
index eac2679..9f03f62 100644
--- a/etc/cyclonedds.rnc
+++ b/etc/cyclonedds.rnc
@@ -1609,6 +1609,9 @@ for 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;
dq.CHAN: delivery thread for channel CHAN;
diff --git a/etc/cyclonedds.xsd b/etc/cyclonedds.xsd
index 8821495..d0d21dd 100644
--- a/etc/cyclonedds.xsd
+++ b/etc/cyclonedds.xsd
@@ -2133,6 +2133,9 @@ for discovery;</li>
<li><i>tev</i>: general timed-event handling, retransmits and
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>dq.CHAN</i>: delivery thread for channel CHAN;</li>
diff --git a/src/core/ddsi/src/q_config.c b/src/core/ddsi/src/q_config.c
index a419f93..53533b0 100644
--- a/src/core/ddsi/src/q_config.c
+++ b/src/core/ddsi/src/q_config.c
@@ -531,6 +531,7 @@ static const struct cfgelem thread_properties_cfgattrs[] = {
dq.builtins: delivery thread for DDSI-builtin data, primarily for discovery;\n\
lease: DDSI liveliness monitoring;\n\
tev: general timed-event handling, retransmits and discovery;\n\
+fsm: finite state machine thread for handling security handshake;\n\
xmit.CHAN: transmit thread for channel CHAN;\n\
dq.CHAN: delivery thread for channel CHAN;\n\
tev.CHAN: timed-even thread for channel CHAN.") },
diff --git a/src/core/ddsi/src/q_init.c b/src/core/ddsi/src/q_init.c
index 498e069..7765f59 100644
--- a/src/core/ddsi/src/q_init.c
+++ b/src/core/ddsi/src/q_init.c
@@ -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)
{
#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 };
#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
const struct config_thread_properties_listelem *e;
int ok = 1, i;
diff --git a/src/security/core/CMakeLists.txt b/src/security/core/CMakeLists.txt
index b0701e9..836bc70 100644
--- a/src/security/core/CMakeLists.txt
+++ b/src/security/core/CMakeLists.txt
@@ -55,3 +55,4 @@ install(
COMPONENT dev)
add_subdirectory(tests)
+add_subdirectory(tests/plugin_loading)
diff --git a/src/security/core/include/dds/security/core/dds_security_fsm.h b/src/security/core/include/dds/security/core/dds_security_fsm.h
index db6374a..198c1c4 100644
--- a/src/security/core/include/dds/security/core/dds_security_fsm.h
+++ b/src/security/core/include/dds/security/core/dds_security_fsm.h
@@ -14,14 +14,18 @@
#define DDS_SECURITY_FSM_H
#include "dds/ddsrt/time.h"
-#include "dds/ddsrt/threads.h"
+#include "dds/ddsi/q_globals.h"
#if defined (__cplusplus)
extern "C" {
#endif
-#define DDS_SECURITY_FSM_EVENT_AUTO (-1)
-#define DDS_SECURITY_FSM_EVENT_TIMEOUT (-2)
+#define DDS_SECURITY_FSM_EVENT_AUTO (-1)
+#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 {
DDS_SECURITY_FSM_DEBUG_ACT_DISPATCH,
@@ -29,13 +33,6 @@ typedef enum {
DDS_SECURITY_FSM_DEBUG_ACT_HANDLING
} 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.
* 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
* debug callback.
*/
-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);
+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);
/**
* Transition definitions
@@ -80,34 +76,6 @@ typedef struct dds_security_fsm_transition {
const dds_security_fsm_state *end;
} 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
@@ -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.
*/
DDS_EXPORT struct dds_security_fsm *
-dds_security_fsm_create(struct dds_security_fsm_context *context,
- const dds_security_fsm_transition *transitions, int size, void *arg);
+dds_security_fsm_create(struct dds_security_fsm_control *control, const dds_security_fsm_transition *transitions, uint32_t size, void *arg);
+
/**
* 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 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_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id);
-
-/**
- * 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);
+dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id, bool prio);
/**
* 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);
/**
- * Clean the given 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.
+ * Free the state machine.
* Stops all running timeouts and events and cleaning all memory
* 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
* 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);
+/**
+ * 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)
}
#endif
diff --git a/src/security/core/src/dds_security_fsm.c b/src/security/core/src/dds_security_fsm.c
index 220b017..4fa9d8e 100644
--- a/src/security/core/src/dds_security_fsm.c
+++ b/src/security/core/src/dds_security_fsm.c
@@ -9,91 +9,87 @@
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
-
#include
#include
-#include "dds/security/core/dds_security_fsm.h"
-#include "dds/ddsrt/threads.h"
+#include
+
#include "dds/ddsrt/sync.h"
#include "dds/ddsrt/heap.h"
#include "dds/ddsrt/atomics.h"
#include "dds/ddsrt/retcode.h"
#include "dds/ddsrt/time.h"
#include "dds/ddsrt/timeconv.h"
-#include
+#include "dds/ddsrt/fibheap.h"
+#include "dds/ddsi/q_thread.h"
+#include "dds/security/core/dds_security_fsm.h"
-typedef struct dds_security_fsm {
- const dds_security_fsm_transition *transitions;
- int size;
- void *arg;
- const dds_security_fsm_state *current;
- dds_time_t current_state_endtime;
- ddsrt_atomic_uint32_t ref_cnt;
- dds_security_fsm_debug debug_func;
- struct dds_security_fsm_context *context;
- struct dds_security_fsm *next;
- struct dds_security_fsm *prev;
-} dds_security_fsm;
-
-typedef struct fsm_event {
+struct fsm_event
+{
struct dds_security_fsm *fsm;
int event_id;
struct fsm_event *next;
struct fsm_event *prev;
-} fsm_event;
+};
-typedef struct fsm_state_timeout {
+typedef enum fsm_timeout_kind {
+ FSM_TIMEOUT_STATE,
+ FSM_TIMEOUT_OVERALL
+} fsm_timeout_kind_t;
+
+struct fsm_timer_event
+{
+ ddsrt_fibheap_node_t heapnode;
struct dds_security_fsm *fsm;
+ fsm_timeout_kind_t kind;
dds_time_t endtime;
-} fsm_state_timeout;
+};
-typedef struct fsm_overall_timeout {
- struct dds_security_fsm *fsm;
- dds_time_t endtime;
- dds_security_fsm_action func;
- struct fsm_overall_timeout *next;
- struct fsm_overall_timeout *prev;
-} fsm_overall_timeout;
+struct dds_security_fsm
+{
+ struct dds_security_fsm *next_fsm;
+ struct dds_security_fsm *prev_fsm;
+ bool active;
+ struct dds_security_fsm_control *control;
+ const dds_security_fsm_transition *transitions;
+ uint32_t size;
+ void *arg;
+ const dds_security_fsm_state *current;
+ struct fsm_timer_event state_timeout_event;
+ struct fsm_timer_event overall_timeout_event;
+ dds_security_fsm_action overall_timeout_action;
+ dds_security_fsm_debug debug_func;
+};
-typedef struct dds_security_fsm_context {
- ddsrt_thread_t fsm_tid;
- ddsrt_thread_t fsm_timeout_tid;
- bool fsm_teardown;
- fsm_event *fsm_queue;
- fsm_overall_timeout *fsm_overall_timeouts;
- ddsrt_mutex_t fsm_fsms_mutex;
- dds_security_fsm *fsm_fsms;
- fsm_state_timeout *fsm_next_state_timeout;
- ddsrt_mutex_t fsm_state_timeout_mutex;
- ddsrt_cond_t fsm_event_cond;
- ddsrt_mutex_t fsm_event_cond_mutex;
+struct dds_security_fsm_control
+{
+ ddsrt_mutex_t lock;
+ ddsrt_cond_t cond;
+ struct thread_state1 *ts;
+ struct q_globals *gv;
+ struct dds_security_fsm *first_fsm;
+ struct dds_security_fsm *last_fsm;
+ struct fsm_event *event_queue;
+ ddsrt_fibheap_t timers;
+ bool running;
+};
- // Overall timeout guard
- ddsrt_cond_t fsm_overall_timeout_cond;
- ddsrt_mutex_t fsm_overall_timeout_cond_mutex;
-} dds_security_fsm_context;
+static int compare_timer_event (const void *va, const void *vb);
+static void fsm_delete (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm);
-static dds_security_fsm_context *fsm_context = NULL;
+const ddsrt_fibheap_def_t timer_events_fhdef = DDSRT_FIBHEAPDEF_INITIALIZER(offsetof (struct fsm_timer_event, heapnode), compare_timer_event);
-// Thread safe initialization of the Generic State Machine Utility
-bool dds_security_fsm_initialized = false;
-static ddsrt_atomic_uint32_t _fsmInitCount = DDSRT_ATOMIC_UINT32_INIT(0);
+static int compare_timer_event (const void *va, const void *vb)
+{
+ const struct fsm_timer_event *a = va;
+ const struct fsm_timer_event *b = vb;
+ return (a->endtime == b->endtime) ? 0 : (a->endtime < b->endtime) ? -1 : 1;
+}
-static void fsm_dispatch(struct dds_security_fsm *fsm, int event_id, int lifo) {
- fsm_event *event;
- dds_security_fsm_context *context;
-
- assert(fsm);
-
- if (fsm->size < 0) {
- /* This fsm is cleaned up (but probably not freed yet).
- * So, ignore the new event. */
- return;
- }
-
- context = fsm->context;
- assert(context);
+static void fsm_dispatch (struct dds_security_fsm *fsm, int event_id, bool lifo)
+{
+ struct dds_security_fsm_control *control = fsm->control;
+ struct fsm_event *event;
if (fsm->debug_func) {
fsm->debug_func(fsm,
@@ -101,7 +97,7 @@ static void fsm_dispatch(struct dds_security_fsm *fsm, int event_id, int lifo) {
fsm->current, event_id, fsm->arg);
}
- event = ddsrt_malloc(sizeof(fsm_event));
+ event = ddsrt_malloc (sizeof(struct fsm_event));
event->fsm = fsm;
event->event_id = event_id;
event->next = NULL;
@@ -109,641 +105,422 @@ static void fsm_dispatch(struct dds_security_fsm *fsm, int event_id, int lifo) {
if (lifo) {
/* Insert event at the top of the event list */
- if (context->fsm_queue) {
- context->fsm_queue->prev = event;
+ if (control->event_queue) {
+ control->event_queue->prev = event;
}
- event->next = context->fsm_queue;
- context->fsm_queue = event;
+ event->next = control->event_queue;
+ control->event_queue = event;
} else {
/* Insert FIFO event */
- if (context->fsm_queue) {
- fsm_event *last = context->fsm_queue;
+ if (control->event_queue) {
+ struct fsm_event *last = control->event_queue;
while (last->next != NULL ) {
last = last->next;
}
last->next = event;
event->prev = last;
} else {
- context->fsm_queue = event;
+ control->event_queue = event;
}
}
}
-static void fsm_set_next_state_timeout(dds_security_fsm_context *context,
- dds_security_fsm *ignore) {
- dds_security_fsm *fsm;
+static void set_state_timer (struct dds_security_fsm *fsm)
+{
+ struct dds_security_fsm_control *control = fsm->control;
- ddsrt_mutex_lock(&context->fsm_event_cond_mutex);
-
- // reset the current time
- context->fsm_next_state_timeout->endtime = DDS_NEVER;
- context->fsm_next_state_timeout->fsm = NULL;
-
- fsm = context->fsm_fsms;
- while (fsm) {
- if ((fsm->current) && (fsm->current->timeout) && (fsm != ignore)) {
- // first set the endtime of this state (if not set)
- if (fsm->current_state_endtime == 0) {
- fsm->current_state_endtime = ddsrt_time_add_duration(dds_time(),
- fsm->current->timeout);
- }
- // Initialize the current endtime
- if (context->fsm_next_state_timeout->fsm == NULL) {
- context->fsm_next_state_timeout->endtime = fsm->current_state_endtime;
- context->fsm_next_state_timeout->fsm = fsm;
- } else if (fsm->current_state_endtime
- < context->fsm_next_state_timeout->endtime) {
- context->fsm_next_state_timeout->endtime = fsm->current_state_endtime;
- context->fsm_next_state_timeout->fsm = fsm;
- }
- }
- fsm = fsm->next;
+ if (fsm->current && fsm->current->timeout > 0 && fsm->current->timeout != DDS_NEVER)
+ {
+ fsm->state_timeout_event.endtime = ddsrt_time_add_duration (dds_time(), fsm->current->timeout);
+ ddsrt_fibheap_insert (&timer_events_fhdef, &control->timers, &fsm->state_timeout_event);
}
-
- ddsrt_mutex_unlock(&context->fsm_event_cond_mutex);
+ else
+ fsm->state_timeout_event.endtime = DDS_NEVER;
}
-static void fsm_state_change(fsm_event *event) {
- dds_security_fsm *fsm = event->fsm;
- dds_security_fsm_context *context = fsm->context;
+static void clear_state_timer (struct dds_security_fsm *fsm)
+{
+ struct dds_security_fsm_control *control = fsm->control;
+
+ if (fsm->current && fsm->state_timeout_event.endtime != DDS_NEVER)
+ ddsrt_fibheap_delete (&timer_events_fhdef, &control->timers, &fsm->state_timeout_event);
+}
+
+static void clear_overall_timer (struct dds_security_fsm *fsm)
+{
+ struct dds_security_fsm_control *control = fsm->control;
+
+ if (fsm->current && fsm->overall_timeout_event.endtime != DDS_NEVER)
+ ddsrt_fibheap_delete (&timer_events_fhdef, &control->timers, &fsm->overall_timeout_event);
+}
+
+static dds_time_t first_timeout (struct dds_security_fsm_control *control)
+{
+ struct fsm_timer_event *min;
+ if ((min = ddsrt_fibheap_min (&timer_events_fhdef, &control->timers)) != NULL)
+ return min->endtime;
+ return DDS_NEVER;
+}
+
+static void fsm_check_auto_state_change (struct dds_security_fsm *fsm)
+{
+ if (fsm->current)
+ {
+ uint32_t i;
+
+ for (i = 0; i < fsm->size; i++)
+ {
+ if (fsm->transitions[i].begin == fsm->current && fsm->transitions[i].event_id == DDS_SECURITY_FSM_EVENT_AUTO)
+ {
+ fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_AUTO, true);
+ break;
+ }
+ }
+ }
+}
+
+static void fsm_state_change (struct dds_security_fsm_control *control, struct fsm_event *event)
+{
+ struct dds_security_fsm *fsm = event->fsm;
int event_id = event->event_id;
- int i, j;
+ uint32_t i;
- if (fsm->debug_func) {
- fsm->debug_func(fsm, DDS_SECURITY_FSM_DEBUG_ACT_HANDLING, fsm->current, event_id,
- fsm->arg);
- }
+ if (fsm->active)
+ {
+ if (fsm->debug_func)
+ fsm->debug_func (fsm, DDS_SECURITY_FSM_DEBUG_ACT_HANDLING, fsm->current, event_id, fsm->arg);
- for (i = 0; !context->fsm_teardown && i < fsm->size; i++) {
- if ((fsm->transitions[i].begin == fsm->current)
- && (fsm->transitions[i].event_id == event_id)) {
- /* Transition. */
- if (fsm->transitions[i].func) {
- fsm->transitions[i].func(fsm, fsm->arg);
- }
- /* New state. */
- fsm->current = fsm->transitions[i].end;
- if (fsm->current) {
- if (fsm->current->func) {
- fsm->current->func(fsm, fsm->arg);
- }
- /* Reset timeout. */
- fsm->current_state_endtime = ddsrt_time_add_duration(dds_time(),
- fsm->current->timeout);
- /* Check if an auto transition is to be dispatched */
- for (j = 0; j < fsm->size; j++) {
- if ((fsm->transitions[j].begin == fsm->current)
- && (fsm->transitions[j].event_id == DDS_SECURITY_FSM_EVENT_AUTO)) {
- dds_security_fsm_dispatch_direct(fsm, DDS_SECURITY_FSM_EVENT_AUTO);
- }
- }
+ for (i = 0; i < fsm->size; i++)
+ {
+ if ((fsm->transitions[i].begin == fsm->current) && (fsm->transitions[i].event_id == event_id))
+ {
+ clear_state_timer (fsm);
+ fsm->current = fsm->transitions[i].end;
+ set_state_timer (fsm);
+
+ ddsrt_mutex_unlock (&control->lock);
+ if (fsm->transitions[i].func)
+ fsm->transitions[i].func (fsm, fsm->arg);
+ if (fsm->current && fsm->current->func)
+ fsm->current->func (fsm, fsm->arg);
+ ddsrt_mutex_lock (&control->lock);
+ fsm_check_auto_state_change (fsm);
+ break;
}
}
}
+ else if (event_id == DDS_SECURITY_FSM_EVENT_DELETE)
+ fsm_delete (control, fsm);
+
}
-static uint32_t
-fsm_thread(void *a) {
- dds_security_fsm_context *context = a;
- dds_duration_t dur_to_wait;
- dds_time_t now = DDS_TIME_INVALID;
- fsm_event *event;
+static void fsm_handle_timeout (struct dds_security_fsm_control *control, struct fsm_timer_event *timer_event)
+{
+ struct dds_security_fsm *fsm = timer_event->fsm;
- while (!context->fsm_teardown) {
- event = NULL;
-
- ddsrt_mutex_lock(&context->fsm_event_cond_mutex);
- if (!context->fsm_queue) {
- if (context->fsm_next_state_timeout->endtime == DDS_NEVER) {
- dur_to_wait = DDS_NEVER;
- } else {
- now = dds_time();
- dur_to_wait = context->fsm_next_state_timeout->endtime - now;
- }
- if (dur_to_wait > 0) {
- if (ddsrt_cond_waitfor(&context->fsm_event_cond,
- &context->fsm_event_cond_mutex, dur_to_wait) == false) {
- if (context->fsm_next_state_timeout->fsm) {
- /* Next timeout could have changed. */
- if (context->fsm_next_state_timeout->endtime != DDS_NEVER
- && (context->fsm_next_state_timeout->endtime - now <= 0)) {
- fsm_dispatch(context->fsm_next_state_timeout->fsm,
- DDS_SECURITY_FSM_EVENT_TIMEOUT, 1);
- }
- }
- }
- } else {
- if (context->fsm_next_state_timeout->fsm) {
- fsm_dispatch(context->fsm_next_state_timeout->fsm,
- DDS_SECURITY_FSM_EVENT_TIMEOUT, 1);
- }
- }
- } else {
- event = context->fsm_queue;
- context->fsm_queue = context->fsm_queue->next;
- if (context->fsm_queue) {
- context->fsm_queue->prev = NULL;
- }
- ddsrt_atomic_inc32(&(event->fsm->ref_cnt));
+ if (fsm->active)
+ {
+ switch (timer_event->kind)
+ {
+ case FSM_TIMEOUT_STATE:
+ fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_TIMEOUT, true);
+ break;
+ case FSM_TIMEOUT_OVERALL:
+ ddsrt_mutex_unlock (&control->lock);
+ if (fsm->overall_timeout_action)
+ fsm->overall_timeout_action (fsm, fsm->arg);
+ ddsrt_mutex_lock (&control->lock);
+ break;
}
- ddsrt_mutex_unlock(&context->fsm_event_cond_mutex);
-
- if (event) {
- fsm_state_change(event);
- if (ddsrt_atomic_dec32_nv(&(event->fsm->ref_cnt)) == 0) {
- ddsrt_free(event->fsm);
- }
- ddsrt_free(event);
- }
- fsm_set_next_state_timeout(context, NULL);
}
+
+ /* mark timer event as being processed */
+ timer_event->endtime = DDS_NEVER;
+}
+
+static uint32_t handle_events (struct dds_security_fsm_control *control)
+{
+ struct thread_state1 * const ts1 = lookup_thread_state ();
+
+ ddsrt_mutex_lock (&control->lock);
+ thread_state_awake (ts1, control->gv);
+ while (control->running)
+ {
+ if (control->event_queue)
+ {
+ struct fsm_event *event = control->event_queue;
+
+ control->event_queue = event->next;
+ if (control->event_queue)
+ control->event_queue->prev = NULL;
+ fsm_state_change (control, event);
+ ddsrt_free (event);
+ }
+ else
+ {
+ dds_time_t timeout = first_timeout (control);
+
+ if (timeout > dds_time ())
+ {
+ thread_state_asleep (ts1);
+ (void)ddsrt_cond_waituntil( &control->cond, &control->lock, timeout);
+ thread_state_awake (ts1, control->gv);
+ }
+ else
+ {
+ struct fsm_timer_event *timer_event = ddsrt_fibheap_extract_min (&timer_events_fhdef, &control->timers);
+ fsm_handle_timeout (control, timer_event);
+ }
+ }
+ }
+ thread_state_asleep (ts1);
+ ddsrt_mutex_unlock (&control->lock);
+
return 0;
}
-static fsm_overall_timeout *
-fsm_get_first_overall_timeout(dds_security_fsm_context *context) {
- fsm_overall_timeout *timeout;
- fsm_overall_timeout *first_timeout;
- dds_time_t first_time = DDS_NEVER;
+void dds_security_fsm_set_timeout (struct dds_security_fsm *fsm, dds_security_fsm_action action, dds_duration_t timeout)
+{
+ assert(fsm);
+ assert(fsm->control);
+ assert(timeout > 0);
- timeout = context->fsm_overall_timeouts;
- first_timeout = context->fsm_overall_timeouts;
- while (timeout) {
- if (timeout->endtime < first_time) {
- first_time = timeout->endtime;
- first_timeout = timeout;
+ ddsrt_mutex_lock (&fsm->control->lock);
+ if (fsm->active)
+ {
+ if (timeout != DDS_NEVER)
+ {
+ clear_overall_timer(fsm);
+ fsm->overall_timeout_action = action;
+ fsm->overall_timeout_event.endtime = ddsrt_time_add_duration(dds_time(), timeout);
+ ddsrt_fibheap_insert (&timer_events_fhdef, &fsm->control->timers, &fsm->overall_timeout_event);
+ if (fsm->overall_timeout_event.endtime < first_timeout(fsm->control))
+ ddsrt_cond_signal (&fsm->control->cond);
}
- timeout = timeout->next;
+ else
+ clear_overall_timer (fsm);
}
-
- return first_timeout;
+ ddsrt_mutex_unlock (&fsm->control->lock);
}
-static void fsm_remove_overall_timeout_from_list(dds_security_fsm_context *context,
- fsm_overall_timeout *timeout) {
- fsm_overall_timeout *tmp_next_timeout;
- fsm_overall_timeout *tmp_prev_timeout;
+void dds_security_fsm_dispatch (struct dds_security_fsm *fsm, int32_t event_id, bool prio)
+{
+ assert(fsm);
+ assert(fsm->control);
- if (timeout) {
-
- tmp_next_timeout = timeout->next;
- tmp_prev_timeout = timeout->prev;
- if (tmp_prev_timeout) {
- tmp_prev_timeout->next = tmp_next_timeout;
- }
- if (tmp_next_timeout) {
- tmp_next_timeout->prev = tmp_prev_timeout;
- }
-
- if (timeout == context->fsm_overall_timeouts) {
- context->fsm_overall_timeouts = tmp_next_timeout;
- }
-
- ddsrt_free(timeout);
- timeout = NULL;
+ ddsrt_mutex_lock (&fsm->control->lock);
+ if (fsm->active)
+ {
+ fsm_dispatch (fsm, event_id, prio);
+ ddsrt_cond_signal (&fsm->control->cond);
}
+ ddsrt_mutex_unlock (&fsm->control->lock);
}
-static uint32_t
-fsm_run_timeout(void *arg) {
- dds_security_fsm_context *context = arg;
- dds_return_t result;
- fsm_overall_timeout *to;
- dds_time_t time_to_wait;
- dds_time_t now;
+const dds_security_fsm_state * dds_security_fsm_current_state (struct dds_security_fsm *fsm)
+{
+ const dds_security_fsm_state *state;
- while (!context->fsm_teardown) {
- ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex);
- to = fsm_get_first_overall_timeout(context);
- if (to) {
- struct dds_security_fsm *fsm = to->fsm;
- ddsrt_atomic_inc32(&(fsm->ref_cnt));
+ assert(fsm);
+ assert(fsm->active);
- result = DDS_RETCODE_TIMEOUT;
- now = dds_time();
- if (to->endtime > now) {
- time_to_wait = to->endtime - now;
- result = ddsrt_cond_waitfor(&context->fsm_overall_timeout_cond,
- &context->fsm_overall_timeout_cond_mutex, time_to_wait);
- }
+ ddsrt_mutex_lock (&fsm->control->lock);
+ state = fsm->current;
+ ddsrt_mutex_unlock (&fsm->control->lock);
- if (result == DDS_RETCODE_TIMEOUT) {
- /* Prevent calling timeout when the fsm has been cleaned. */
- dds_security_fsm_action func = to->func;
- fsm_remove_overall_timeout_from_list(context, to);
- if (fsm->size > 0) {
- ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex);
- func(fsm, fsm->arg);
- ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex);
- }
- }
-
- if (ddsrt_atomic_dec32_nv(&(fsm->ref_cnt)) == 0) {
- ddsrt_free(fsm);
- }
- } else {
- ddsrt_cond_wait(&context->fsm_overall_timeout_cond,
- &context->fsm_overall_timeout_cond_mutex);
- }
- ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex);
- }
- return 0;
+ return state;
}
-static void fsm_remove_fsm_list(dds_security_fsm *fsm) {
- dds_security_fsm_context *context;
- dds_security_fsm *tmp_next_fsm;
- dds_security_fsm *tmp_prev_fsm;
+void dds_security_fsm_set_debug (struct dds_security_fsm *fsm, dds_security_fsm_debug func)
+{
+ assert(fsm);
- if (fsm) {
- context = fsm->context;
-
- ddsrt_mutex_lock(&context->fsm_fsms_mutex);
- tmp_next_fsm = fsm->next;
- tmp_prev_fsm = fsm->prev;
- if (tmp_prev_fsm) {
- tmp_prev_fsm->next = tmp_next_fsm;
- }
- if (tmp_next_fsm) {
- tmp_next_fsm->prev = tmp_prev_fsm;
- }
- if (fsm == context->fsm_fsms) {
- context->fsm_fsms = tmp_next_fsm;
- }
- ddsrt_mutex_unlock(&context->fsm_fsms_mutex);
-
- ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex);
- ddsrt_cond_signal(&context->fsm_overall_timeout_cond);
- ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex);
- }
+ ddsrt_mutex_lock (&fsm->control->lock);
+ fsm->debug_func = func;
+ ddsrt_mutex_unlock (&fsm->control->lock);
}
-static ddsrt_thread_t fsm_thread_create( const char *name,
- ddsrt_thread_routine_t f, void *arg) {
- ddsrt_thread_t tid;
- ddsrt_threadattr_t threadAttr;
+static bool fsm_validate (const dds_security_fsm_transition *transitions, uint32_t size)
+{
+ uint32_t i;
- ddsrt_threadattr_init(&threadAttr);
- if (ddsrt_thread_create(&tid, name, &threadAttr, f, arg) != DDS_RETCODE_OK) {
- memset(&tid, 0, sizeof(ddsrt_thread_t));
- }
- return tid;
-}
-#ifdef AT_PROC_EXIT_IMPLEMENTED
-static void fsm_thread_destroy( ddsrt_thread_t tid) {
- uint32_t thread_result;
-
- (void) ddsrt_thread_join( tid, &thread_result);
-}
-#endif
-
-struct dds_security_fsm_context *
-dds_security_fsm_context_create( dds_security_fsm_thread_create_func thr_create_func) {
- struct dds_security_fsm_context *context;
-
- context = ddsrt_malloc(sizeof(*context));
-
- context->fsm_next_state_timeout = ddsrt_malloc(sizeof(fsm_state_timeout));
- context->fsm_next_state_timeout->endtime = DDS_NEVER;
- context->fsm_next_state_timeout->fsm = NULL;
-
- context->fsm_teardown = false;
- context->fsm_queue = NULL;
- context->fsm_overall_timeouts = NULL;
- context->fsm_fsms = NULL;
-
- (void) ddsrt_mutex_init( &context->fsm_fsms_mutex );
-
- // Overall timeout guard
- (void) ddsrt_mutex_init( &context->fsm_overall_timeout_cond_mutex );
- (void) ddsrt_cond_init( &context->fsm_overall_timeout_cond );
-
- // State timeouts
- (void) ddsrt_mutex_init(&context->fsm_state_timeout_mutex );
-
- // Events
- (void) ddsrt_mutex_init(&context->fsm_event_cond_mutex );
- (void) ddsrt_cond_init(&context->fsm_event_cond );
-
- context->fsm_tid = thr_create_func( "dds_security_fsm", fsm_thread, context);
- context->fsm_timeout_tid = thr_create_func( "dds_security_fsm_timeout",
- fsm_run_timeout, context);
-
- return context;
-}
-
-void dds_security_fsm_context_destroy(dds_security_fsm_context *context,
- dds_security_fsm_thread_destroy_func thr_destroy_func) {
- if (context) {
- context->fsm_teardown = true;
-
- ddsrt_mutex_lock( &context->fsm_overall_timeout_cond_mutex);
- ddsrt_cond_signal( &context->fsm_overall_timeout_cond);
- ddsrt_mutex_unlock( &context->fsm_overall_timeout_cond_mutex);
-
- ddsrt_mutex_lock(&context->fsm_event_cond_mutex);
- ddsrt_cond_signal(&context->fsm_event_cond);
- ddsrt_mutex_unlock(&context->fsm_event_cond_mutex);
-
- thr_destroy_func( context->fsm_tid);
- ddsrt_mutex_destroy(&context->fsm_event_cond_mutex);
- ddsrt_cond_destroy(&context->fsm_event_cond);
-
- thr_destroy_func( context->fsm_timeout_tid);
- ddsrt_mutex_destroy(&context->fsm_fsms_mutex);
- ddsrt_mutex_destroy(&context->fsm_overall_timeout_cond_mutex);
- ddsrt_cond_destroy(&context->fsm_overall_timeout_cond);
-
- ddsrt_free(context->fsm_next_state_timeout);
- }
-}
-#ifdef AT_PROC_EXIT_IMPLEMENTED
-static void fsm_fini(void) {
- dds_security_fsm_context_destroy(fsm_context, NULL, fsm_thread_destroy);
-
- /* os_osExit(); ???? */
-}
-
-#endif
-static bool fsm_init_once(void) {
- bool ret = true;
- uint32_t initCount;
-
- initCount = ddsrt_atomic_inc32_nv(&_fsmInitCount);
-
- if (initCount == 1) {
- assert( dds_security_fsm_initialized == false );
-
- /* ddsrt_osInit(); ??? */
-
- fsm_context = dds_security_fsm_context_create( fsm_thread_create);
-
- if (fsm_context) {
- /* os_procAtExit( fsm_fini ); ??? */
- dds_security_fsm_initialized = true;
- } else {
- ret = false;
- }
- } else {
- if (dds_security_fsm_initialized == false) {
- /* Another thread is currently initializing the fsm. Since
- * both results (osr_fsm and osr_timeout) should be ddsrt_resultSuccess
- * a sleep is performed, to ensure that (if succeeded) successive
- * init calls will also actually pass.
- */
- dds_sleepfor( DDS_MSECS( 100 ));
- }
- if (dds_security_fsm_initialized == false) {
- /* Initialization did not succeed, undo increment and return error */
- initCount = ddsrt_atomic_dec32_nv(&_fsmInitCount);
- ret = false;
- }
- }
- return ret;
-}
-
-static int /* 1 = ok, other = error */
-fsm_validate(const dds_security_fsm_transition *transitions, int size) {
- int i;
-
- for (i = 0; i < size; i++) {
+ for (i = 0; i < size; i++)
+ {
/* It needs to have a start. */
- if ((transitions[i].begin == NULL )
- && (transitions[i].event_id == DDS_SECURITY_FSM_EVENT_AUTO)) {
- return 1;
- }
+ if (transitions[i].begin && transitions[i].event_id == DDS_SECURITY_FSM_EVENT_AUTO)
+ return true;
}
-
- return 0;
+ return true;
}
-struct dds_security_fsm *
-dds_security_fsm_create(struct dds_security_fsm_context *context,
- const dds_security_fsm_transition *transitions, int size, void *arg) {
- struct dds_security_fsm* fsm = NULL;
- struct dds_security_fsm_context *ctx = NULL;
-
- assert(transitions);
- assert(size > 0);
-
- if (context == NULL) {
- if (fsm_init_once()) {
- ctx = fsm_context;
- }
- } else {
- ctx = context;
+static void add_fsm_to_list (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm)
+{
+ fsm->next_fsm = NULL;
+ fsm->prev_fsm = control->last_fsm;
+ if (control->last_fsm)
+ {
+ assert(control->first_fsm != NULL);
+ control->last_fsm->next_fsm = fsm;
}
+ else
+ {
+ assert(control->first_fsm == NULL);
+ control->first_fsm = fsm;
+ }
+ control->last_fsm = fsm;
+}
- if (ctx) {
- if (fsm_validate(transitions, size) == 1) {
- fsm = ddsrt_malloc(sizeof(struct dds_security_fsm));
- fsm->transitions = transitions;
- fsm->size = size;
- fsm->arg = arg;
- fsm->current = NULL;
- fsm->debug_func = NULL;
- fsm->next = NULL;
- fsm->prev = NULL;
- fsm->context = ctx;
- ddsrt_atomic_st32( &fsm->ref_cnt, 1 );
- fsm->current_state_endtime = 0;
+static void remove_fsm_from_list (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm)
+{
+ if (fsm->prev_fsm)
+ fsm->prev_fsm->next_fsm = fsm->next_fsm;
+ else
+ control->first_fsm = fsm->next_fsm;
- ddsrt_mutex_lock(&fsm->context->fsm_fsms_mutex);
- if (fsm->context->fsm_fsms) {
- dds_security_fsm *last = fsm->context->fsm_fsms;
- while (last->next != NULL ) {
- last = last->next;
- }
- last->next = fsm;
- fsm->prev = last;
- } else {
- fsm->context->fsm_fsms = fsm;
- }
- ddsrt_mutex_unlock(&fsm->context->fsm_fsms_mutex);
- }
+ if (fsm->next_fsm)
+ fsm->next_fsm->prev_fsm = fsm->prev_fsm;
+ else
+ control->last_fsm = fsm->prev_fsm;
+}
+
+struct dds_security_fsm * dds_security_fsm_create (struct dds_security_fsm_control *control, const dds_security_fsm_transition *transitions, uint32_t size, void *arg)
+{
+ struct dds_security_fsm *fsm = NULL;
+
+ assert(control);
+ assert(transitions);
+
+ if (fsm_validate (transitions, size))
+ {
+ fsm = ddsrt_malloc (sizeof(struct dds_security_fsm));
+ fsm->transitions = transitions;
+ fsm->size = size;
+ fsm->arg = arg;
+ fsm->current = NULL;
+ fsm->debug_func = NULL;
+ fsm->overall_timeout_action = NULL;
+ fsm->state_timeout_event.kind = FSM_TIMEOUT_STATE;
+ fsm->state_timeout_event.endtime = DDS_NEVER;
+ fsm->state_timeout_event.fsm = fsm;
+ fsm->overall_timeout_event.kind = FSM_TIMEOUT_OVERALL;
+ fsm->overall_timeout_event.endtime = DDS_NEVER;
+ fsm->overall_timeout_event.fsm = fsm;
+ fsm->active = true;
+ fsm->next_fsm = NULL;
+ fsm->prev_fsm = NULL;
+ fsm->control = control;
+
+ ddsrt_mutex_lock (&control->lock);
+ add_fsm_to_list (control, fsm);
+ ddsrt_mutex_unlock (&control->lock);
}
return fsm;
}
-void dds_security_fsm_start(struct dds_security_fsm *fsm) {
- assert(fsm);
- dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO);
+void
+dds_security_fsm_start (struct dds_security_fsm *fsm)
+{
+ dds_security_fsm_dispatch(fsm, DDS_SECURITY_FSM_EVENT_AUTO, false);
}
-void dds_security_fsm_set_timeout(struct dds_security_fsm *fsm, dds_security_fsm_action func,
- dds_time_t timeout) {
- fsm_overall_timeout *to;
- dds_security_fsm_context *context;
-
- assert(fsm);
-
- context = fsm->context;
- assert(context);
-
- to = ddsrt_malloc(sizeof(fsm_overall_timeout));
- to->fsm = fsm;
- to->func = func;
- to->endtime = ddsrt_time_add_duration( dds_time(), timeout);
- to->next = NULL;
- to->prev = NULL;
-
- ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex);
- if (context->fsm_overall_timeouts) {
- fsm_overall_timeout *last = context->fsm_overall_timeouts;
- while (last->next != NULL ) {
- last = last->next;
- }
- last->next = to;
- to->prev = last;
- } else {
- context->fsm_overall_timeouts = to;
- }
- ddsrt_cond_signal(&context->fsm_overall_timeout_cond);
- ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex);
-}
-
-void dds_security_fsm_set_debug(struct dds_security_fsm *fsm, dds_security_fsm_debug func) {
- dds_security_fsm_context *context;
-
- assert(fsm);
-
- context = fsm->context;
- assert(context);
-
- ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex);
- fsm->debug_func = func;
- ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex);
-}
-
-void dds_security_fsm_dispatch(struct dds_security_fsm *fsm, int32_t event_id) {
- dds_security_fsm_context *context;
-
- assert(fsm);
-
- context = fsm->context;
- assert(context);
-
- ddsrt_mutex_lock(&context->fsm_event_cond_mutex);
- fsm_dispatch(fsm, event_id, 0);
- ddsrt_cond_signal(&context->fsm_event_cond);
- ddsrt_mutex_unlock(&context->fsm_event_cond_mutex);
-}
-
-void dds_security_fsm_dispatch_direct(struct dds_security_fsm *fsm, int32_t event_id) {
- dds_security_fsm_context *context;
-
- assert(fsm);
-
- context = fsm->context;
- assert(context);
-
- ddsrt_mutex_lock(&context->fsm_event_cond_mutex);
- fsm_dispatch(fsm, event_id, 1);
- ddsrt_cond_signal(&context->fsm_event_cond);
- ddsrt_mutex_unlock(&context->fsm_event_cond_mutex);
-}
-
-const dds_security_fsm_state*
-dds_security_fsm_current_state(struct dds_security_fsm *fsm) {
- assert(fsm);
- return fsm->current;
-}
-
-void dds_security_fsm_cleanup(struct dds_security_fsm *fsm) {
- dds_security_fsm_context *context;
- fsm_event *event;
- fsm_event *tmp_prev_event;
- fsm_event *tmp_next_event;
- fsm_overall_timeout *timeout;
-
- assert(fsm);
-
- context = fsm->context;
- assert(context);
-
- // Signal the timeout thread.
- // First hold to lock to the overall timeout list
- // so that the next timeout can't be determined until
- // we've done removing the overall timeout of this fsm
-
- // Signal the thread so that it's not using timeout structs
- ddsrt_mutex_lock(&context->fsm_overall_timeout_cond_mutex);
- ddsrt_cond_signal(&context->fsm_overall_timeout_cond);
-
- timeout = context->fsm_overall_timeouts;
-
- // Search the overall timeout of this fsm
- while (timeout) {
- if (timeout->fsm == fsm) {
- break;
- }
- timeout = timeout->next;
- }
- fsm_remove_overall_timeout_from_list(context, timeout);
- ddsrt_mutex_unlock(&context->fsm_overall_timeout_cond_mutex);
-
- /* The current fsm could be the one that would trigger a possible timeout.
- * Reset the state timeout and make sure it's not the current fsm. */
- fsm_set_next_state_timeout(context, fsm);
-
- /* Now, remove all possible events from the queue related to the fsm. */
- ddsrt_mutex_lock(&context->fsm_event_cond_mutex);
- event = context->fsm_queue;
- while (event) {
- if (event->fsm == fsm) {
- tmp_next_event = event->next;
- tmp_prev_event = event->prev;
- if (tmp_prev_event) {
- tmp_prev_event->next = tmp_next_event;
- }
- if (tmp_next_event) {
- tmp_next_event->prev = tmp_prev_event;
- }
- if (event == context->fsm_queue) {
- context->fsm_queue = tmp_next_event;
- }
- ddsrt_free(event);
- event = tmp_next_event;
- } else {
- event = event->next;
- }
- }
- ddsrt_cond_signal(&context->fsm_event_cond);
- ddsrt_mutex_unlock(&context->fsm_event_cond_mutex);
-}
-
-void dds_security_fsm_free(struct dds_security_fsm *fsm) {
- ddsrt_tid_t self = ddsrt_gettid_for_thread( ddsrt_thread_self() );
- dds_security_fsm_context *context;
-
- assert(fsm);
-
- context = fsm->context;
- assert(context);
-
- /* Indicate termination. */
- fsm->size = -1;
-
- /* Cleanup stuff. */
- dds_security_fsm_cleanup(fsm);
- fsm_remove_fsm_list(fsm);
-
- /* Is this being freed from the FSM context? */
- if ((self == ddsrt_gettid_for_thread( context->fsm_tid ) )
- || (self == ddsrt_gettid_for_thread( context->fsm_timeout_tid ) ) ) {
- /* Yes.
- * Just reduce the reference count and let the garbage collection be
- * done by the FSM context after event handling. */
- ddsrt_atomic_dec32(&(fsm->ref_cnt));
- } else {
- /* No.
- * Block the outside thread until a possible concurrent event
- * has being handled. */
- while (ddsrt_atomic_ld32( &(fsm->ref_cnt)) > 1) {
- /* Currently, an event is still being handled for this FSM. */
- dds_sleepfor( 10 * DDS_NSECS_IN_MSEC );
- }
- /* We have the only reference, so it's safe to free the FSM. */
- ddsrt_free(fsm);
+static void fsm_deactivate (struct dds_security_fsm *fsm, bool gen_del_event)
+{
+ if (fsm->active)
+ {
+ fsm->active = false;
+ clear_state_timer (fsm);
+ clear_overall_timer (fsm);
+ fsm->current = NULL;
+ if (gen_del_event)
+ fsm_dispatch (fsm, DDS_SECURITY_FSM_EVENT_DELETE, false);
}
}
+
+void dds_security_fsm_free (struct dds_security_fsm *fsm)
+{
+ struct dds_security_fsm_control *control;
+
+ assert(fsm);
+ assert(fsm->control);
+
+ control = fsm->control;
+ ddsrt_mutex_lock (&control->lock);
+ fsm_deactivate (fsm, true);
+ ddsrt_mutex_unlock (&control->lock);
+}
+
+static void fsm_delete (struct dds_security_fsm_control *control, struct dds_security_fsm *fsm)
+{
+ fsm_deactivate (fsm, false);
+ remove_fsm_from_list (control, fsm);
+ ddsrt_free(fsm);
+}
+
+struct dds_security_fsm_control * dds_security_fsm_control_create (struct q_globals *gv)
+{
+ struct dds_security_fsm_control *control;
+
+ control = ddsrt_malloc (sizeof(*control));
+ control->running = false;
+ control->event_queue = NULL;
+ control->first_fsm = NULL;
+ control->last_fsm = NULL;
+ control->gv = gv;
+ ddsrt_mutex_init (&control->lock);
+ ddsrt_cond_init (&control->cond);
+ ddsrt_fibheap_init (&timer_events_fhdef, &control->timers);
+
+ return control;
+}
+
+void dds_security_fsm_control_free (struct dds_security_fsm_control *control)
+{
+ struct dds_security_fsm *fsm;
+ struct fsm_event *event;
+
+ assert(control);
+ assert(!control->running);
+
+ while ((fsm = control->first_fsm) != NULL)
+ {
+ control->first_fsm = fsm->next_fsm;
+ fsm_deactivate (fsm, false);
+ ddsrt_free (fsm);
+ }
+ while ((event = control->event_queue) != NULL)
+ {
+ control->event_queue = event->next;
+ ddsrt_free (event);
+ }
+
+ ddsrt_cond_destroy (&control->cond);
+ ddsrt_mutex_destroy (&control->lock);
+ ddsrt_free (control);
+}
+
+dds_return_t dds_security_fsm_control_start (struct dds_security_fsm_control *control, const char *name)
+{
+ dds_return_t rc;
+ const char *fsm_name = name ? name : "fsm";
+
+ assert(control);
+
+ control->running = true;
+ rc = create_thread (&control->ts, control->gv, fsm_name, (uint32_t (*) (void *)) handle_events, control);
+
+ return rc;
+}
+
+void dds_security_fsm_control_stop (struct dds_security_fsm_control *control)
+{
+ assert(control);
+ assert(control->running);
+
+ ddsrt_mutex_lock (&control->lock);
+ control->running = false;
+ ddsrt_cond_signal (&control->cond);
+ ddsrt_mutex_unlock (&control->lock);
+
+ join_thread (control->ts);
+ control->ts = NULL;
+}
diff --git a/src/security/core/tests/CMakeLists.txt b/src/security/core/tests/CMakeLists.txt
index e002ba4..40a6650 100644
--- a/src/security/core/tests/CMakeLists.txt
+++ b/src/security/core/tests/CMakeLists.txt
@@ -27,13 +27,10 @@ target_include_directories(
"$>"
"$"
"$"
- "$"
+ "$"
+ "$"
)
target_link_libraries(cunit_security_core PRIVATE ddsc security_api)
target_include_directories(cunit_security_core PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
-
-
-
-# configure_file("config_env.h.in" "config_env.h")
\ No newline at end of file
diff --git a/src/security/core/tests/tc_fsm.c b/src/security/core/tests/tc_fsm.c
index 442b921..c2c7647 100644
--- a/src/security/core/tests/tc_fsm.c
+++ b/src/security/core/tests/tc_fsm.c
@@ -1,43 +1,45 @@
-#include "dds/security/core/dds_security_fsm.h"
-#include "dds/ddsrt/sync.h"
-#include "dds/ddsrt/misc.h"
+/*
+ * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
+ *
+ * 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
#include
+
+#include "dds/ddsrt/sync.h"
+#include "dds/ddsrt/misc.h"
+
#include "CUnit/CUnit.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 FSM_AUTH_ARG 10
-#define DB_TC_PRINT_DEBUG (false)
+#define DB_TC_PRINT_DEBUG (true)
-static struct dds_security_fsm *fsm_auth;
-static struct dds_security_fsm *fsm_test;
-static struct dds_security_fsm *fsm_timeout;
-static struct dds_security_fsm *fsm_timeout2;
-static struct dds_security_fsm *fsm_timeout3;
+static dds_entity_t g_participant = 0;
+static struct dds_security_fsm_control *g_fsm_control = NULL;
+static const dds_duration_t msec100 = DDS_MSECS(100);
-static uint32_t visited_auth = 0;
-static uint32_t visited_test = 0;
-static uint32_t visited_timeout = 0;
+//static int fsm_arg = FSM_AUTH_ARG;
-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
- */
+ **********************************************************************/
+
typedef enum {
VALIDATION_PENDING_RETRY,
VALIDATION_FAILED,
@@ -48,8 +50,16 @@ typedef enum {
PluginReturn_MAX
} 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) {
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;
}
-static PluginReturn begin_handshake_reply(void) {
-
+static PluginReturn begin_handshake_reply(void)
+{
if (DB_TC_PRINT_DEBUG) {
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;
}
-static PluginReturn get_shared_secret(void) {
+static PluginReturn get_shared_secret(void)
+{
return VALIDATION_OK;
}
/* 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;
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);
}
- 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;
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);
}
- 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. */
-static dds_security_fsm_state StateValidateRemoteIdentity = {
- fsm_validate_remote_identity, 0};
+static dds_security_fsm_state StateValidateRemoteIdentity = {fsm_validate_remote_identity, 0};
static dds_security_fsm_state StateValRemIdentityRetryWait = {NULL, 100000000};
static dds_security_fsm_state StateHandshakeInitMessageWait = {NULL, 0};
static dds_security_fsm_state StateBeginHandshakeReply = {fsm_begin_handshake_reply, 0};
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;
if (DB_TC_PRINT_DEBUG) {
@@ -141,7 +154,8 @@ static void a(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -149,7 +163,8 @@ static void b(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -157,7 +172,8 @@ static void c(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -165,7 +181,8 @@ static void d(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -173,7 +190,8 @@ static void e(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -181,7 +199,8 @@ static void f(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -189,7 +208,8 @@ static void g(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -233,34 +253,35 @@ static void h(struct dds_security_fsm *fsm, void *arg) {
* .-.
* '-'
*/
-dds_security_fsm_transition HandshakeTransistions[] =
- {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state
- {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b,
- &StateValRemIdentityRetryWait},
- {&StateValidateRemoteIdentity,
- VALIDATION_PENDING_HANDSHAKE_MESSAGE, c,
- &StateHandshakeInitMessageWait},
- {&StateValRemIdentityRetryWait,
- DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity},
- {
- &StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e,
- &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},};
+static dds_security_fsm_transition HandshakeTransistions[] = {
+ {NULL, DDS_SECURITY_FSM_EVENT_AUTO, a, &StateValidateRemoteIdentity}, // NULL state is the start state
+ {&StateValidateRemoteIdentity, VALIDATION_PENDING_RETRY, b, &StateValRemIdentityRetryWait},
+ {&StateValidateRemoteIdentity, VALIDATION_PENDING_HANDSHAKE_MESSAGE, c, &StateHandshakeInitMessageWait},
+ {&StateValRemIdentityRetryWait, DDS_SECURITY_FSM_EVENT_TIMEOUT, d, &StateValidateRemoteIdentity},
+ {&StateHandshakeInitMessageWait, SHM_MSG_RECEIVED, e, &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}
+};
+static const uint32_t HandshakeTransistionsSize = sizeof(HandshakeTransistions)/sizeof(HandshakeTransistions[0]);
-/*
+
+/**********************************************************************
* Example State Machine properties and methods
- */
+ **********************************************************************/
+
typedef enum {
eventX, eventY, eventZ,
} 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. */
-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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -268,7 +289,8 @@ static void doStart(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -276,7 +298,8 @@ static void doRestart(struct dds_security_fsm *fsm, void *arg) {
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(arg);
if (DB_TC_PRINT_DEBUG)
@@ -284,8 +307,8 @@ static void doEventStuff(struct dds_security_fsm *fsm, void *arg) {
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(arg);
@@ -294,15 +317,16 @@ static void doStuff(struct dds_security_fsm *fsm, void *arg) {
}
visited_test |= 1UL << 2;
- if (do_stuff_counter == 0) {
- dds_security_fsm_dispatch(fsm, eventZ);
+ if (do_stuff_counter < 2) {
+ dds_security_fsm_dispatch(fsm, eventZ, false);
} else if (do_stuff_counter == 2) {
- dds_security_fsm_dispatch(fsm, eventY);
+ dds_security_fsm_dispatch(fsm, eventY, false);
}
++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(arg);
@@ -311,43 +335,54 @@ static void doOtherStuff(struct dds_security_fsm *fsm, void *arg) {
}
visited_test |= 1UL << 3;
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) {
- dds_security_fsm_dispatch(fsm, eventY);
+ dds_security_fsm_dispatch(fsm, eventY, false);
} else if (do_other_stuff_counter == 2) {
- dds_security_fsm_dispatch(fsm, eventX);
+ dds_security_fsm_dispatch(fsm, eventX, false);
}
++do_other_stuff_counter;
}
-dds_security_fsm_state StateA = {doStuff, 0};
-dds_security_fsm_state StateB = {doStuff, 100000000};
-dds_security_fsm_state StateC = {NULL, 0};
-dds_security_fsm_state StateD = {doOtherStuff, 0};
+static dds_security_fsm_state StateA = {doStuff, 0};
+static dds_security_fsm_state StateB = {doStuff, 100000000};
+static dds_security_fsm_state StateC = {NULL, 0};
+static dds_security_fsm_state StateD = {doOtherStuff, 0};
-dds_security_fsm_transition transitions[] = {
- {NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state
- {&StateA, eventZ, NULL, &StateB},
- {&StateA, eventY, doOtherStuff, &StateC},
- {&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram
- {&StateB, eventZ, doRestart, &StateA},
- {&StateC, DDS_SECURITY_FSM_EVENT_AUTO,
- doEventStuff, &StateD},
- {&StateD, eventY, doEventStuff, &StateD},
- {
- &StateD, eventX, doStuff, NULL}, // Reaching NULL means end of state-diagram
+static dds_security_fsm_transition Transitions[] = {
+ {NULL, DDS_SECURITY_FSM_EVENT_AUTO, doStart, &StateA}, // NULL state is the start state
+ {&StateA, eventZ, NULL, &StateB},
+ {&StateA, eventY, doOtherStuff, &StateC},
+ {&StateB, eventX, NULL, NULL}, // Reaching NULL means end of state-diagram
+ {&StateB, eventZ, doRestart, &StateA},
+ {&StateC, DDS_SECURITY_FSM_EVENT_AUTO, doEventStuff, &StateD},
+ {&StateD, eventY, doEventStuff, &StateD},
+ {&StateD, eventX, doStuff, NULL}, // Reaching NULL means end of sttimeoutate-diagram
};
+static const uint32_t TransitionsSize = sizeof(Transitions)/sizeof(Transitions[0]);
-/*
+
+/**********************************************************************
* Timeout State Machine properties and methods
- */
+ **********************************************************************/
+
typedef enum {
eventToTimeout, eventToEnd,
} timeout_events;
-/* The functions callld from the state-machine. */
-static void doInterupt(struct dds_security_fsm *fsm, void *arg) {
+static struct dds_security_fsm *fsm_timeout;
+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(arg);
if (DB_TC_PRINT_DEBUG) {
@@ -356,7 +391,8 @@ static void doInterupt(struct dds_security_fsm *fsm, void *arg) {
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;
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);
}
- 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;
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(arg);
if (DB_TC_PRINT_DEBUG) {
@@ -414,86 +452,121 @@ static void TimeoutCallback2(struct dds_security_fsm *fsm, void *arg) {
visited_timeout |= 1UL << 3;
}
-dds_security_fsm_state StateTimeout = {doTimeout, 0};
-dds_security_fsm_state StateInterupt = {doInterupt, 0};
+static dds_security_fsm_state StateTimeout = {doTimeout, 0};static int fsm_arg = FSM_AUTH_ARG;
-dds_security_fsm_transition timeout_transitions[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL,
- &StateTimeout}, // NULL state is the start state
- {&StateTimeout, eventToTimeout, NULL, &StateInterupt},
- {&StateInterupt,
- eventToEnd, NULL, NULL}, // Reaching NULL means end of state-diagram
+static dds_security_fsm_state StateInterupt = {doInterupt, 0};
+
+static const dds_security_fsm_transition TimeoutTransitions[] = {
+ {NULL, DDS_SECURITY_FSM_EVENT_AUTO, NULL, &StateTimeout}, // NULL state is the start state
+ {&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 time1 = 0;
static dds_time_t time2 = 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(arg);
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(arg);
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(arg);
time3 = dds_time();
}
-dds_security_fsm_state StateParTimeout1 = {NULL, DDS_NSECS_IN_SEC};
-dds_security_fsm_state StateParTimeout2 = {NULL, 2 * DDS_NSECS_IN_SEC};
-dds_security_fsm_state StateParTimeout3 = {NULL, DDS_NSECS_IN_SEC};
+static dds_security_fsm_state StateParTimeout1 = {NULL, DDS_SECS(1)};
+static dds_security_fsm_state StateParTimeout2 = {NULL, DDS_SECS(2)};
+static dds_security_fsm_state StateParTimeout3 = {NULL, DDS_SECS(1)};
-dds_security_fsm_transition par_timeout_transitions_1[] = {{NULL, DDS_SECURITY_FSM_EVENT_AUTO,
- NULL, &StateParTimeout1}, // NULL state is the start state
- {&StateParTimeout1, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime1, NULL}, // Reaching NULL means end of state-diagram
+static dds_security_fsm_transition ParallelTimeoutTransitions_1[] = {
+ {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
};
+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,
- NULL, &StateParTimeout2}, // NULL state is the start state
- {&StateParTimeout2, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime2, NULL}, // Reaching NULL means end of state-diagram
+static dds_security_fsm_transition ParallelTimeoutTransitions_2[] = {
+ {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
};
+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,
- NULL, &StateParTimeout3}, // NULL state is the start state
- {&StateParTimeout3, DDS_SECURITY_FSM_EVENT_TIMEOUT, &StateParTime3, NULL}, // Reaching NULL means end of state-diagram
+static dds_security_fsm_transition ParallelTimeoutTransitions_3[] = {
+ {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
};
+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_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
* Check creation of a single State Machine
*/
-
- fsm_auth = dds_security_fsm_create(NULL, HandshakeTransistions,
- sizeof(HandshakeTransistions) / sizeof(HandshakeTransistions[0]),
- &fsm_arg);
+ fsm_auth = dds_security_fsm_create(g_fsm_control, HandshakeTransistions, HandshakeTransistionsSize, &fsm_arg);
CU_ASSERT_FATAL(fsm_auth != NULL)
// 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
timeout = 100; /* 10 sec */
- while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait)
- && (timeout > 0)) {
+ while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) {
dds_sleepfor(msec100);
timeout--;
}
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 */
while ((dds_security_fsm_current_state(fsm_auth) != NULL) && (timeout > 0)) {
dds_sleepfor(msec100);
timeout--;
}
-
CU_ASSERT(timeout > 0);
+
CU_ASSERT(
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) &&
@@ -539,54 +611,61 @@ CU_Test(ddssec_fsm, create, .init = init_testcase, .fini = fini_testcase) {
/*
* 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*/
validate_remote_identity_first = 0;
begin_handshake_reply_first = 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_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 */
- while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait)
- && (timeout > 0)) {
+ while ((dds_security_fsm_current_state(fsm_auth) != &StateHandshakeInitMessageWait) && (timeout > 0)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--;
}
CU_ASSERT_FATAL(timeout > 0);
+
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)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--;
}
CU_ASSERT_FATAL(timeout > 0);
+
// not all bits are set since we're running the state machine a second time
CU_ASSERT_FATAL(
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, 6) && !CHECK_BIT(visited_auth, 7));
+ /* Wait for the last state to occur */
timeout = 100; /* 10 sec */
- // Wait for the last state to occur
while ((dds_security_fsm_current_state(fsm_test) != NULL) && timeout > 0) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--;
}
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, 3));
+
dds_security_fsm_free(fsm_auth);
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
*/
-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
*/
- fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions,
- sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg);
+ fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg);
CU_ASSERT(fsm_timeout != NULL);
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
*/
-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;
- fsm_timeout = dds_security_fsm_create(NULL, timeout_transitions,
- sizeof(timeout_transitions) / sizeof(timeout_transitions[0]), &fsm_arg);
+ fsm_timeout = dds_security_fsm_create(g_fsm_control, TimeoutTransitions, TimeoutTransitionsSize, &fsm_arg);
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);
+
dds_security_fsm_set_timeout(fsm_timeout, TimeoutCallback, delay1);
dds_security_fsm_set_timeout(fsm_timeout2, TimeoutCallback2, delay2);
dds_security_fsm_start(fsm_timeout);
@@ -646,7 +731,7 @@ CU_Test(ddssec_fsm, double_timeout, .init = init_testcase, .fini = fini_testcase
timeout--;
}
CU_ASSERT(CHECK_BIT(visited_timeout, 2));
- dds_security_fsm_cleanup(fsm_timeout);
+// dds_security_fsm_cleanup(fsm_timeout);
timeout = 100; /* 10 sec */
while ((CHECK_BIT(visited_timeout, 3) == 0) && (timeout > 0)) {
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
*/
-CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testcase) {
- 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);
+CU_Test(ddssec_fsm, parallel_timeout, .init = fsm_control_init, .fini = fsm_control_fini)
+{
dds_duration_t delta1;
dds_duration_t delta2;
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();
- dds_security_fsm_start(fsm_timeout);
+ dds_security_fsm_start(fsm_timeout1);
dds_security_fsm_start(fsm_timeout2);
dds_security_fsm_start(fsm_timeout3);
/* Wait for both to end. */
- timeout = 100; /* 10 sec */
+ timeout = 300; /* 10 sec */
/* 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_timeout3) == NULL)) && (timeout > 0)) {
dds_sleepfor(100 * DDS_NSECS_IN_MSEC);
timeout--;
}
+
/* 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_timeout3) != NULL)) && (timeout > 0)) {
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 < 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_timeout3);
@@ -736,11 +822,13 @@ CU_Test(ddssec_fsm, parallel_timeout, .init = init_testcase, .fini = fini_testca
/**
* 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;
dds_security_fsm_start(fsm_timeout);