- Update FSM implementation (add Strong and Weak states).

- Replace REGISTER dialog state machine by our own FSM.
- Replace SUBSCRIBE dialog state machine by our own FSM.
This commit is contained in:
bossiel 2010-02-18 00:52:36 +00:00
parent 8e7fd29c1c
commit 9c98f2a38d
12 changed files with 1772 additions and 1453 deletions

View File

@ -33,7 +33,7 @@
#include "tsk_debug.h"
int tsk_fsm_exec_nothing(va_list *app){ return 1; }
int tsk_fsm_cond_always(void* data1, void* data2) { return 1; }
int tsk_fsm_cond_always(const void* data1, const void* data2) { return 1; }
int tsk_fsm_set(tsk_fsm_t* self, ...)
{
@ -57,7 +57,7 @@ int tsk_fsm_set(tsk_fsm_t* self, ...)
entry->exec = va_arg(args, tsk_fsm_exec);
entry->desc = va_arg(args, const char*);
tsk_list_push_back_data(self->entries, (void**)&entry);
tsk_list_push_descending_data(self->entries, (void**)&entry);
}
}
va_end(args);
@ -76,12 +76,13 @@ int tsk_fsm_set_callback_terminated(tsk_fsm_t* self, tsk_fsm_onterminated callba
return -1;
}
int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, void* cond_data1, void* cond_data2, ...)
int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, const void* cond_data1, const void* cond_data2, ...)
{
tsk_list_item_t *item;
va_list ap;
int found = 0;
int ret_exec = 0;
if(!self){
TSK_DEBUG_ERROR("Null FSM.");
return -1;
@ -98,32 +99,29 @@ int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, void* cond_data1, voi
tsk_list_foreach(item, self->entries)
{
tsk_fsm_entry_t* entry = item->data;
if((entry->from != self->current)){
if((entry->from != tsk_fsm_state_any) && (entry->from != self->current)){
continue;
}
if((entry->action != action) && (entry->action != tsk_fsm_state_any)){
if((entry->action != tsk_fsm_action_any) && (entry->action != action)){
continue;
}
// check condition
if(entry->cond(cond_data1, cond_data2)){
self->current = entry->to;
if(entry->exec){
entry->exec(&ap);
}
found = 1;
// For debug information
if(self->debug){
TSK_DEBUG_INFO("State machine: %s", entry->desc);
}
if(self->current == self->term){
if(self->callback_term){
self->callback_term(self->callback_data);
self->current = entry->to;
if(entry->exec){
if((ret_exec = entry->exec(&ap))){
TSK_DEBUG_INFO("State machine: Exec function failed. Moving to terminal state.");
self->current = self->term;
}
}
found = 1;
break;
}
}
@ -132,6 +130,12 @@ int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, void* cond_data1, voi
// unlock
tsk_safeobj_unlock(self);
/* Only call the callback function after unlock. */
if(self->current == self->term){
if(self->callback_term){
self->callback_term(self->callback_data);
}
}
if(!found){
TSK_DEBUG_WARN("State machine: No matching state found.");
}
@ -209,17 +213,26 @@ static void* tsk_fsm_entry_destroy(void * self)
return self;
}
static int tsk_string_cmp(const void *obj1, const void *obj2)
static int tsk_fsm_entry_cmp(const void *obj1, const void *obj2)
{
const tsk_fsm_entry_t* entry1 = obj1;
const tsk_fsm_entry_t* entry2 = obj2;
if(entry1 && entry2)
{
/* Put "Any" states at the bottom. (Strong)*/
if(entry1->from == tsk_fsm_state_any){
return -1;
return -20;
}
else if(entry2->from == tsk_fsm_state_any){
return 1;
return +20;
}
/* Put "Any" actions at the bottom. (Weak)*/
if(entry1->action == tsk_fsm_action_any){
return -10;
}
else if(entry1->action == tsk_fsm_action_any){
return +10;
}
}
return 0;
@ -230,6 +243,6 @@ static const tsk_object_def_t tsk_fsm_entry_def_s =
sizeof(tsk_fsm_entry_t),
tsk_fsm_entry_create,
tsk_fsm_entry_destroy,
0,
tsk_fsm_entry_cmp,
};
const void *tsk_fsm_entry_def_t = &tsk_fsm_entry_def_s;

View File

@ -39,15 +39,7 @@ TSK_BEGIN_DECLS
#define TSK_FSM_CREATE(state_curr, state_term) tsk_object_new(tsk_fsm_def_t, (tsk_fsm_state_id)state_curr, (tsk_fsm_state_id)state_term)
#define TSK_FSM_ENTRY_CREATE() tsk_object_new(tsk_fsm_entry_def_t)
/*==============
* from (stateA) ---> [fsm_actionB {fsm_cond_B or fsm_cond_always}] ---> to (stateB) ==> execute(fsm_functionB)
* ---> [fsm_actionC {fsm_cond_C or fsm_cond_always}] ---> to (stateC) ==> execute(fsm_functionC)
*
* The starting state is "stateA". If after executing "fsm_actionB" action, "fsm_cond_B" or "fsm_cond_always" condition is true
* then we can move to "stateB". At "stateB" we execute "fsm_functionB" function.
*/
#define TSK_FSM_ONTERMINATED(self) (tsk_fsm_onterminated)(self)
#define tsk_fsm_state_any -0xFFFF
#define tsk_fsm_state_default -0xFFF0
@ -58,7 +50,7 @@ TSK_BEGIN_DECLS
typedef int tsk_fsm_state_id;
typedef int tsk_fsm_action_id;
typedef int (*tsk_fsm_cond)(void*, void*);
typedef int (*tsk_fsm_cond)(const void*, const void*);
typedef int (*tsk_fsm_exec)(va_list *app);
typedef int (*tsk_fsm_onterminated)(const void*);
@ -108,11 +100,10 @@ typedef struct tsk_fsm_s
tsk_fsm_t;
TINYSAK_API int tsk_fsm_exec_nothing(va_list *app);
TINYSAK_API int tsk_fsm_cond_always(void*, void*);
TINYSAK_API int tsk_fsm_cond_always(const void*, const void*);
TINYSAK_API int tsk_fsm_set(tsk_fsm_t* self, ...);
TINYSAK_API int tsk_fsm_set_callback_terminated(tsk_fsm_t* self, tsk_fsm_onterminated callback, const void* callbackdata);
TINYSAK_API int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, void* cond_data1, void* cond_data2, ...);
TINYSAK_API int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, const void* cond_data1, const void* cond_data2, ...);
TINYSAK_GEXTERN const void *tsk_fsm_def_t;
TINYSAK_GEXTERN const void *tsk_fsm_entry_def_t;

View File

@ -32,7 +32,7 @@
#include "tsk_macros.h"
#include "tsk_debug.h"
#include <assert.h>
//#include <assert.h>
#include <string.h>
// FIXME: remove asserts
@ -220,7 +220,7 @@ void tsk_list_remove_item_by_data(tsk_list_t* list, const void * tskobj)
tsk_list_item_t *prev = 0;
tsk_list_item_t *curr = prev = list->head;
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
while(curr)
{
@ -261,7 +261,7 @@ void tsk_list_remove_item_by_data(tsk_list_t* list, const void * tskobj)
}
}
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
}
/**@ingroup tsk_list_group
@ -314,7 +314,7 @@ void tsk_list_remove_item_by_pred(tsk_list_t* list, tsk_list_func_predicate pred
curr = curr->next;
}
}
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -366,7 +366,7 @@ tsk_list_item_t* tsk_list_pop_first_item(tsk_list_t* list)
}
}
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
}
return item;
@ -392,7 +392,7 @@ void tsk_list_push_item(tsk_list_t* list, tsk_list_item_t** item, int back)
}
(*item) = 0;
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
}
/**@ingroup tsk_list_group
@ -432,7 +432,7 @@ void tsk_list_push_filtered_item(tsk_list_t* list, tsk_list_item_t** item, int a
tsk_list_push_back_item(list, item);
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
}
}
@ -477,7 +477,7 @@ void tsk_list_push_data(tsk_list_t* list, void** data, int back)
{
TSK_DEBUG_WARN("Cannot add an uninitialized data to the list");
}
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
}
/**@ingroup tsk_list_group
@ -493,7 +493,7 @@ void tsk_list_push_filtered_data(tsk_list_t* list, void** data, int ascending)
tsk_list_push_filtered_item(list, &item, ascending);
(*data) = 0;
assert((list && list->tail) ? !list->tail->next : 1);
//assert((list && list->tail) ? !list->tail->next : 1);
}
else
{

View File

@ -62,8 +62,8 @@ TSIP_BEGIN_DECLS
//#define TSIP_DIALOG_ALERT_USER(self, code, reason_phrase, incoming, type) \
// tsip_stack_alert(TSIP_DIALOG(self)->stack, /*tsip_operation_get_id(TSIP_DIALOG(self)->operation)*/0, code, reason_phrase, incoming, type)
#define DIALOG_REMOVE_SCHEDULE() \
tsk_timer_manager_schedule(TSIP_DIALOG_GET_STACK(self)->timer_mgr, 0, TSK_TIMER_CALLBACK(tsip_dialog_remove_callback), self)
//#define DIALOG_REMOVE_SCHEDULE() \
// tsk_timer_manager_schedule(TSIP_DIALOG_GET_STACK(self)->timer_mgr, 0, TSK_TIMER_CALLBACK(tsip_dialog_remove_callback), self)
#define TSIP_DIALOG_EXPIRES_DEFAULT 3600
@ -113,7 +113,7 @@ typedef struct tsip_dialog_s
TSK_DECLARE_OBJECT;
tsip_dialog_type_t type;
tsip_stack_handle_t *stack;
tsip_operation_handle_t* operation;
@ -143,7 +143,7 @@ typedef struct tsip_dialog_s
tsip_dialog_event_callback callback;
TSK_DECLARE_SAFEOBJ;
TSK_DECLARE_SAFEOBJ; // FIXME
}
tsip_dialog_t;
@ -164,7 +164,7 @@ int tsip_dialog_update(tsip_dialog_t *self, const tsip_response_t* response);
int tsip_dialog_init(tsip_dialog_t *self, tsip_dialog_type_t type, tsip_stack_handle_t * stack, const char* call_id, tsip_operation_handle_t* operation);
int tsip_dialog_hangup(tsip_dialog_t *self);
int tsip_dialog_remove_callback(const tsip_dialog_t* self, tsk_timer_id_t timer_id);
int tsip_dialog_remove(const tsip_dialog_t* self);
int tsip_dialog_cmp(const tsip_dialog_t *d1, const tsip_dialog_t *d2);
int tsip_dialog_deinit(tsip_dialog_t *self);

View File

@ -32,7 +32,8 @@
#include "tinysip_config.h"
#include "tinysip/dialogs/tsip_dialog.h"
#include "tinysip/smc/tsip_dialog_register_sm.h"
#include "tsk_fsm.h"
TSIP_BEGIN_DECLS
@ -44,8 +45,8 @@ typedef struct tsip_dialog_register
{
TSIP_DECLARE_DIALOG;
struct tsip_dialog_registerContext _fsm;
tsk_fsm_t *fsm;
tsip_timer_t timerrefresh;
unsigned unregistering:1;
@ -55,21 +56,6 @@ tsip_dialog_register_t;
//void tsip_dialog_register_init(tsip_dialog_register_t *self);
int tsip_dialog_register_start(tsip_dialog_register_t *self);
void tsip_dialog_register_Started_2_Trying_X_send(tsip_dialog_register_t *self);
void tsip_dialog_register_Trying_2_Trying_X_1xx(tsip_dialog_register_t *self, const tsip_message_t *msg);
void tsip_dialog_register_Trying_2_Connected_X_2xx(tsip_dialog_register_t *self, const tsip_message_t *msg);
void tsip_dialog_register_Trying_2_Terminated_X_2xx(tsip_dialog_register_t *self, const tsip_message_t *msg);
void tsip_dialog_register_Trying_2_Trying_X_401_407_421_494(tsip_dialog_register_t *self, const tsip_message_t *msg);
void tsip_dialog_register_Trying_2_Trying_X_423(tsip_dialog_register_t *self, const tsip_message_t *msg);
void tsip_dialog_register_Trying_2_Terminated_X_300_to_699(tsip_dialog_register_t *self, const tsip_message_t *msg);
void tsip_dialog_register_Trying_2_Terminated_X_cancel(tsip_dialog_register_t *self);
void tsip_dialog_register_Connected_2_Trying_X_unregister(tsip_dialog_register_t *self);
void tsip_dialog_register_Connected_2_Trying_X_refresh(tsip_dialog_register_t *self);
void tsip_dialog_register_Any_2_Trying_X_hangup(tsip_dialog_register_t *self);
void tsip_dialog_register_Any_2_Terminated_X_transportError(tsip_dialog_register_t *self);
void tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self);
TINYSIP_GEXTERN const void *tsip_dialog_register_def_t;
TSIP_END_DECLS

View File

@ -32,7 +32,8 @@
#include "tinysip_config.h"
#include "tinysip/dialogs/tsip_dialog.h"
#include "tinysip/smc/tsip_dialog_subscribe_sm.h"
#include "tsk_fsm.h"
TSIP_BEGIN_DECLS
@ -44,8 +45,8 @@ typedef struct tsip_dialog_subscribe
{
TSIP_DECLARE_DIALOG;
struct tsip_dialog_subscribeContext _fsm;
tsk_fsm_t *fsm;
tsip_timer_t timerrefresh;
unsigned unsubscribing:1;
@ -56,24 +57,6 @@ tsip_dialog_subscribe_t;
int tsip_dialog_subscribe_start(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_Started_2_Trying_X_send(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_Trying_2_Trying_X_1xx(tsip_dialog_subscribe_t *self, const tsip_response_t* response);
void tsip_dialog_subscribe_Trying_2_Terminated_X_2xx(tsip_dialog_subscribe_t *self, const tsip_response_t* response);
void tsip_dialog_subscribe_Trying_2_Connected_X_2xx(tsip_dialog_subscribe_t *self, const tsip_response_t* response);
void tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494(tsip_dialog_subscribe_t *self, const tsip_response_t* response);
void tsip_dialog_subscribe_Trying_2_Trying_X_423(tsip_dialog_subscribe_t *self, const tsip_response_t* response);
void tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699(tsip_dialog_subscribe_t *self, const tsip_response_t* response);
void tsip_dialog_subscribe_Trying_2_Terminated_X_cancel(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request);
void tsip_dialog_subscribe_Connected_2_Trying_X_unsubscribe(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_Connected_2_Trying_X_refresh(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request);
void tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request);
void tsip_dialog_subscribe_Any_2_Trying_X_hangup(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_Any_2_Terminated_X_transportError(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self);
void tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self);
TINYSIP_GEXTERN const void *tsip_dialog_subscribe_def_t;
TSIP_END_DECLS

View File

@ -724,10 +724,10 @@ int tsip_dialog_init(tsip_dialog_t *self, tsip_dialog_type_t type, tsip_stack_ha
/* Expires */
if((param = tsip_operation_get_param(TSIP_DIALOG(self)->operation, "expires"))){
TSIP_DIALOG(self)->expires = atoi(param->value);
self->expires = atoi(param->value);
}
else{
TSIP_DIALOG(self)->expires = TSIP_DIALOG_EXPIRES_DEFAULT;
self->expires = TSIP_DIALOG_EXPIRES_DEFAULT;
}
self->initialized = 1;
@ -745,7 +745,7 @@ int tsip_dialog_hangup(tsip_dialog_t *self)
return -1;
}
int tsip_dialog_remove_callback(const tsip_dialog_t* self, tsk_timer_id_t timer_id)
int tsip_dialog_remove(const tsip_dialog_t* self)
{
return tsip_dialog_layer_remove(TSIP_STACK(self->stack)->layer_dialog, TSIP_DIALOG(self));
}

View File

@ -52,7 +52,67 @@
#define TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, type, code, phrase) TSIP_DIALOG_REGISTER_SIGNAL(self, type, code, phrase, 1)
#define TSIP_DIALOG_REGISTER_SIGNAL_OUTGOING(self, type, code, phrase) TSIP_DIALOG_REGISTER_SIGNAL(self, type, code, phrase, 0)
/* ======================== internal functions ======================== */
int send_register(tsip_dialog_register_t *self);
int tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self);
/* ======================== transitions ======================== */
int tsip_dialog_register_Started_2_Trying_X_send(va_list *app);
int tsip_dialog_register_Trying_2_Trying_X_1xx(va_list *app);
int tsip_dialog_register_Trying_2_Terminated_X_2xx(va_list *app);
int tsip_dialog_register_Trying_2_Connected_X_2xx(va_list *app);
int tsip_dialog_register_Trying_2_Trying_X_401_407_421_494(va_list *app);
int tsip_dialog_register_Trying_2_Trying_X_423(va_list *app);
int tsip_dialog_register_Trying_2_Terminated_X_300_to_699(va_list *app);
int tsip_dialog_register_Trying_2_Terminated_X_cancel(va_list *app);
int tsip_dialog_register_Trying_2_Trying_X_NOTIFY(va_list *app);
int tsip_dialog_register_Connected_2_Trying_X_unregister(va_list *app);
int tsip_dialog_register_Connected_2_Trying_X_refresh(va_list *app);
int tsip_dialog_register_Connected_2_Connected_X_NOTIFY(va_list *app);
int tsip_dialog_register_Connected_2_Terminated_X_NOTIFY(va_list *app);
int tsip_dialog_register_Any_2_Trying_X_hangup(va_list *app);
int tsip_dialog_register_Any_2_Terminated_X_transportError(va_list *app);
int tsip_dialog_register_Any_2_Terminated_X_Error(va_list *app);
/* ======================== conds ======================== */
int _fsm_cond_unregistering(tsip_dialog_register_t* dialog, tsip_message_t* message)
{
return dialog->unregistering ? 1 : 0;
}
int _fsm_cond_registering(tsip_dialog_register_t* dialog, tsip_message_t* message)
{
return !_fsm_cond_unregistering(dialog, message);
}
/* ======================== actions ======================== */
typedef enum _fsm_action_e
{
_fsm_action_send,
_fsm_action_1xx,
_fsm_action_2xx,
_fsm_action_401_407_421_494,
_fsm_action_423,
_fsm_action_300_to_699,
_fsm_action_cancel,
_fsm_action_unregister,
_fsm_action_refresh,
_fsm_action_hangup,
_fsm_action_transporterror,
_fsm_action_error,
}
_fsm_action_t;
/* ======================== states ======================== */
typedef enum _fsm_state_e
{
_fsm_state_Started,
_fsm_state_Trying,
_fsm_state_Connected,
_fsm_state_Terminated
}
_fsm_state_t;
/**
* @fn int tsip_dialog_register_event_callback(const tsip_dialog_register_t *self, tsip_dialog_event_type_t type,
@ -71,7 +131,7 @@ int send_register(tsip_dialog_register_t *self);
**/
int tsip_dialog_register_event_callback(const tsip_dialog_register_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
{
TSIP_DIALOG_SYNC_BEGIN(self);
int ret = -1;
switch(type)
{
@ -84,24 +144,24 @@ int tsip_dialog_register_event_callback(const tsip_dialog_register_t *self, tsip
//
if(TSIP_RESPONSE_IS_1XX(msg))
{
tsip_dialog_registerContext_sm_1xx(&TSIP_DIALOG_REGISTER(self)->_fsm, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_1xx, self, msg, self, msg);
}
else if(TSIP_RESPONSE_IS_2XX(msg))
{
tsip_dialog_registerContext_sm_2xx(&TSIP_DIALOG_REGISTER(self)->_fsm, TSIP_DIALOG_REGISTER(self)->unregistering, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_2xx, self, msg, self, msg);
}
else if(TSIP_RESPONSE_IS(msg,401) || TSIP_RESPONSE_IS(msg,407) || TSIP_RESPONSE_IS(msg,421) || TSIP_RESPONSE_IS(msg,494))
{
tsip_dialog_registerContext_sm_401_407_421_494(&TSIP_DIALOG_REGISTER(self)->_fsm, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_401_407_421_494, self, msg, self, msg);
}
else if(TSIP_RESPONSE_IS(msg,423))
{
tsip_dialog_registerContext_sm_423(&TSIP_DIALOG_REGISTER(self)->_fsm, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_423, self, msg, self, msg);
}
else
{
// Alert User
TSIP_DIALOG_REGISTER_SIGNAL_ERROR(self);
ret = tsk_fsm_act((self)->fsm, _fsm_action_error, self, msg, self, msg);
TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg));
}
}
@ -116,13 +176,13 @@ int tsip_dialog_register_event_callback(const tsip_dialog_register_t *self, tsip
case tsip_dialog_hang_up:
{
tsip_dialog_registerContext_sm_hangup(&TSIP_DIALOG_REGISTER(self)->_fsm);
ret = tsk_fsm_act((self)->fsm, _fsm_action_hangup, self, msg, self, msg);
break;
}
case tsip_dialog_canceled:
{
tsip_dialog_registerContext_sm_cancel(&TSIP_DIALOG_REGISTER(self)->_fsm);
ret = tsk_fsm_act((self)->fsm, _fsm_action_cancel, self, msg, self, msg);
break;
}
@ -131,14 +191,12 @@ int tsip_dialog_register_event_callback(const tsip_dialog_register_t *self, tsip
case tsip_dialog_error:
case tsip_dialog_transport_error:
{
tsip_dialog_registerContext_sm_transportError(&TSIP_DIALOG_REGISTER(self)->_fsm);
ret = tsk_fsm_act((self)->fsm, _fsm_action_transporterror, self, msg, self, msg);
break;
}
}
TSIP_DIALOG_SYNC_END(self);
return 0;
return ret;
}
/**
@ -161,21 +219,16 @@ int tsip_dialog_register_timer_callback(const tsip_dialog_register_t* self, tsk_
if(self)
{
TSIP_DIALOG_SYNC_BEGIN(self);
if(timer_id == self->timerrefresh.id)
{
tsip_dialog_registerContext_sm_refresh(&TSIP_DIALOG_REGISTER(self)->_fsm);
ret = 0;
ret = tsk_fsm_act((self)->fsm, _fsm_action_refresh, self, TSK_NULL, self, TSK_NULL);
}
TSIP_DIALOG_SYNC_END(self);
}
return ret;
}
/**
* @fn void tsip_dialog_register_init(tsip_dialog_register_t *self)
* @fn int tsip_dialog_register_init(tsip_dialog_register_t *self)
*
* @brief Initializes the dialog.
*
@ -184,11 +237,64 @@ int tsip_dialog_register_timer_callback(const tsip_dialog_register_t* self, tsk_
*
* @param [in,out] self The dialog to initialize.
**/
void tsip_dialog_register_init(tsip_dialog_register_t *self)
int tsip_dialog_register_init(tsip_dialog_register_t *self)
{
/* Initialize the state machine.
*/
tsip_dialog_registerContext_Init(&self->_fsm, self);
/* Initialize the state machine. */
tsk_fsm_set(self->fsm,
/*=======================
* === Started ===
*/
// Started -> (Send) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_send, _fsm_state_Trying, tsip_dialog_register_Started_2_Trying_X_send, "tsip_dialog_register_Started_2_Trying_X_send"),
// Started -> (Any) -> Started
TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_register_Started_2_Started_X_any"),
/*=======================
* === Trying ===
*/
// Trying -> (1xx) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_1xx, _fsm_state_Trying, tsip_dialog_register_Trying_2_Trying_X_1xx, "tsip_dialog_register_Trying_2_Trying_X_1xx"),
// Trying -> (2xx) -> Terminated
TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_unregistering, _fsm_state_Terminated, tsip_dialog_register_Trying_2_Terminated_X_2xx, "tsip_dialog_register_Trying_2_Terminated_X_2xx"),
// Trying -> (2xx) -> Connected
TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_registering, _fsm_state_Connected, tsip_dialog_register_Trying_2_Connected_X_2xx, "tsip_dialog_register_Trying_2_Connected_X_2xx"),
// Trying -> (401/407/421/494) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_401_407_421_494, _fsm_state_Trying, tsip_dialog_register_Trying_2_Trying_X_401_407_421_494, "tsip_dialog_register_Trying_2_Trying_X_401_407_421_494"),
// Trying -> (423) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_423, _fsm_state_Trying, tsip_dialog_register_Trying_2_Trying_X_423, "tsip_dialog_register_Trying_2_Trying_X_423"),
// Trying -> (300_to_699) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_300_to_699, _fsm_state_Terminated, tsip_dialog_register_Trying_2_Terminated_X_300_to_699, "tsip_dialog_register_Trying_2_Terminated_X_300_to_699"),
// Trying -> (cancel) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_cancel, _fsm_state_Terminated, tsip_dialog_register_Trying_2_Terminated_X_cancel, "tsip_dialog_register_Trying_2_Terminated_X_cancel"),
// Trying -> (Any) -> Trying
TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Trying, "tsip_dialog_register_Trying_2_Trying_X_any"),
/*=======================
* === Connected ===
*/
// Connected -> (unregister) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_unregister, _fsm_state_Trying, tsip_dialog_register_Connected_2_Trying_X_unregister, "tsip_dialog_register_Connected_2_Trying_X_unregister"),
// Connected -> (refresh) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_refresh, _fsm_state_Trying, tsip_dialog_register_Connected_2_Trying_X_refresh, "tsip_dialog_register_Connected_2_Trying_X_refresh"),
// Connected -> (Any) -> Connected
TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Connected, "tsip_dialog_register_Connected_2_Connected_X_any"),
/*=======================
* === Any ===
*/
// Any -> (transport error) -> Terminated
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_dialog_register_Any_2_Terminated_X_transportError, "tsip_dialog_register_Any_2_Terminated_X_transportError"),
// Any -> (transport error) -> Terminated
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_dialog_register_Any_2_Terminated_X_Error, "tsip_dialog_register_Any_2_Terminated_X_Error"),
// Any -> (hangup) -> Terminated
// Any -> (hangup) -> Trying
TSK_FSM_ADD_NULL());
TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK(tsip_dialog_register_event_callback);
@ -199,9 +305,7 @@ void tsip_dialog_register_init(tsip_dialog_register_t *self)
self->timerrefresh.id = TSK_INVALID_TIMER_ID;
self->timerrefresh.timeout = TSIP_DIALOG(self)->expires;
#if defined(_DEBUG) || defined(DEBUG)
setDebugFlag(&(self->_fsm), DEBUG_STATE_MACHINE);
#endif
return 0;
}
/**
@ -221,12 +325,8 @@ int tsip_dialog_register_start(tsip_dialog_register_t *self)
int ret = -1;
if(self && !TSIP_DIALOG(self)->running)
{
/* Set state machine state to started */
setState(&self->_fsm, &tsip_dialog_register_Started);
/* Send request */
tsip_dialog_registerContext_sm_send(&self->_fsm);
ret = 0;
ret = tsk_fsm_act(self->fsm, _fsm_action_send, self, TSK_NULL, self, TSK_NULL);
}
return ret;
}
@ -238,26 +338,35 @@ int tsip_dialog_register_start(tsip_dialog_register_t *self)
/* Started -> (send) -> Trying
*/
void tsip_dialog_register_Started_2_Trying_X_send(tsip_dialog_register_t *self)
int tsip_dialog_register_Started_2_Trying_X_send(va_list *app)
{
send_register(self);
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
return send_register(self);
}
/* Trying -> (1xx) -> Trying
*/
void tsip_dialog_register_Trying_2_Trying_X_1xx(tsip_dialog_register_t *self, const tsip_message_t* msg)
int tsip_dialog_register_Trying_2_Trying_X_1xx(va_list *app)
{
tsip_dialog_update(TSIP_DIALOG(self), msg);
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
return tsip_dialog_update(TSIP_DIALOG(self), message);
}
/* Trying -> (2xx) -> Connected
*/
//#include "tsk_thread.h"
void tsip_dialog_register_Trying_2_Connected_X_2xx(tsip_dialog_register_t *self, const tsip_message_t* msg)
int tsip_dialog_register_Trying_2_Connected_X_2xx(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
/* Alert the user. */
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_register_ok,
TSIP_RESPONSE_CODE(msg), TSIP_RESPONSE_PHRASE(msg));
TSIP_RESPONSE_CODE(message), TSIP_RESPONSE_PHRASE(message));
/* - Set P-associated-uriS
* - Update service-routes
@ -276,7 +385,7 @@ void tsip_dialog_register_Trying_2_Connected_X_2xx(tsip_dialog_register_t *self,
TSK_OBJECT_SAFE_FREE(TSIP_DIALOG_GET_STACK(self)->paths);
/* Associated URIs */
for(index = 0; (hdr_P_Associated_URI_t = (const tsip_header_P_Associated_URI_t*)tsip_message_get_headerAt(msg, tsip_htype_P_Associated_URI, index)); index++){
for(index = 0; (hdr_P_Associated_URI_t = (const tsip_header_P_Associated_URI_t*)tsip_message_get_headerAt(message, tsip_htype_P_Associated_URI, index)); index++){
if(!TSIP_DIALOG_GET_STACK(self)->associated_uris){
TSIP_DIALOG_GET_STACK(self)->associated_uris = TSK_LIST_CREATE();
}
@ -285,7 +394,7 @@ void tsip_dialog_register_Trying_2_Connected_X_2xx(tsip_dialog_register_t *self,
}
/* Service-Route */
for(index = 0; (hdr_Service_Route = (const tsip_header_Service_Route_t*)tsip_message_get_headerAt(msg, tsip_htype_Service_Route, index)); index++){
for(index = 0; (hdr_Service_Route = (const tsip_header_Service_Route_t*)tsip_message_get_headerAt(message, tsip_htype_Service_Route, index)); index++){
if(!TSIP_DIALOG_GET_STACK(self)->service_routes){
TSIP_DIALOG_GET_STACK(self)->service_routes = TSK_LIST_CREATE();
}
@ -294,7 +403,7 @@ void tsip_dialog_register_Trying_2_Connected_X_2xx(tsip_dialog_register_t *self,
}
/* Paths */
for(index = 0; (hdr_Path = (const tsip_header_Path_t*)tsip_message_get_headerAt(msg, tsip_htype_Path, index)); index++){
for(index = 0; (hdr_Path = (const tsip_header_Path_t*)tsip_message_get_headerAt(message, tsip_htype_Path, index)); index++){
if(TSIP_DIALOG_GET_STACK(self)->paths == 0){
TSIP_DIALOG_GET_STACK(self)->paths = TSK_LIST_CREATE();
}
@ -304,46 +413,57 @@ void tsip_dialog_register_Trying_2_Connected_X_2xx(tsip_dialog_register_t *self,
}
/* Update the dialog state. */
tsip_dialog_update(TSIP_DIALOG(self), msg);
tsip_dialog_update(TSIP_DIALOG(self), message);
/* Request timeout for dialog refresh (re-registration). */
self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), msg);
self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), message);
TSIP_DIALOG_REGISTER_TIMER_SCHEDULE(refresh);
return 0;
}
/* Trying -> (2xx) -> Terminated
*/
void tsip_dialog_register_Trying_2_Terminated_X_2xx(tsip_dialog_register_t *self, const tsip_message_t* msg)
int tsip_dialog_register_Trying_2_Terminated_X_2xx(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
/* Alert the user. */
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_unregister_ok, TSIP_RESPONSE_CODE(msg), TSIP_RESPONSE_PHRASE(msg));
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_unregister_ok, TSIP_RESPONSE_CODE(message), TSIP_RESPONSE_PHRASE(message));
return 0;
}
/* Trying --> (401/407/421/494) --> Trying
*/
void tsip_dialog_register_Trying_2_Trying_X_401_407_421_494(tsip_dialog_register_t *self, const tsip_message_t* msg)
int tsip_dialog_register_Trying_2_Trying_X_401_407_421_494(va_list *app)
{
if(tsip_dialog_update(TSIP_DIALOG(self), msg))
{
TSIP_DIALOG_REGISTER_SIGNAL_ERROR(self);
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
int ret;
if((ret = tsip_dialog_update(TSIP_DIALOG(self), message)))
{
/* Alert the user. */
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, self->unregistering ? tsip_unregistering : tsip_registering,
TSIP_RESPONSE_CODE(msg), TSIP_RESPONSE_PHRASE(msg));
TSIP_RESPONSE_CODE(message), TSIP_RESPONSE_PHRASE(message));
goto bail;
return ret;
}
send_register(self);
bail:;
return send_register(self);
}
/* Trying -> (423) -> Trying
*/
void tsip_dialog_register_Trying_2_Trying_X_423(tsip_dialog_register_t *self, const tsip_message_t* msg)
int tsip_dialog_register_Trying_2_Trying_X_423(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
tsip_header_Min_Expires_t *hdr;
int ret = 0;
/*
RFC 3261 - 10.2.8 Error Responses
@ -354,66 +474,99 @@ void tsip_dialog_register_Trying_2_Trying_X_423(tsip_dialog_register_t *self, co
expiration interval within the Min-Expires header field of the 423
(Interval Too Brief) response.
*/
hdr = (tsip_header_Min_Expires_t*)tsip_message_get_header(msg, tsip_htype_Min_Expires);
hdr = (tsip_header_Min_Expires_t*)tsip_message_get_header(message, tsip_htype_Min_Expires);
if(hdr)
{
TSIP_DIALOG(self)->expires = hdr->value;
send_register(self);
ret = send_register(self);
}
else
{
TSIP_DIALOG_REGISTER_SIGNAL_ERROR(self);
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, self->unregistering ? tsip_unregistering : tsip_registering,
TSIP_RESPONSE_CODE(msg), TSIP_RESPONSE_PHRASE(msg));
ret = -1;
}
return ret;
}
/* Trying -> (300-699) -> Terminated
*/
void tsip_dialog_register_Trying_2_Terminated_X_300_to_699(tsip_dialog_register_t *self, const tsip_message_t* msg)
int tsip_dialog_register_Trying_2_Terminated_X_300_to_699(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
/* Alert the user. */
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_register_nok, TSIP_RESPONSE_CODE(msg), TSIP_RESPONSE_PHRASE(msg));
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_register_nok, TSIP_RESPONSE_CODE(message), TSIP_RESPONSE_PHRASE(message));
return 0;
}
/* Trying -> (cancel) -> Terminated
*/
void tsip_dialog_register_Trying_2_Terminated_X_cancel(tsip_dialog_register_t *self)
int tsip_dialog_register_Trying_2_Terminated_X_cancel(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
/* Alert the user. */
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_register_cancelled, 701, "Registration cancelled");
return 0;
}
/* Connected -> (Unregister) -> Trying
*/
void tsip_dialog_register_Connected_2_Trying_X_unregister(tsip_dialog_register_t *self)
int tsip_dialog_register_Connected_2_Trying_X_unregister(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
return 0;
}
/* Connected -> (refresh) -> Trying
*/
void tsip_dialog_register_Connected_2_Trying_X_refresh(tsip_dialog_register_t *self)
int tsip_dialog_register_Connected_2_Trying_X_refresh(va_list *app)
{
send_register(self);
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
return send_register(self);
}
/* Any -> (hangup) -> Trying
*/
void tsip_dialog_register_Any_2_Trying_X_hangup(tsip_dialog_register_t *self)
int tsip_dialog_register_Any_2_Trying_X_hangup(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
self->unregistering = 1;
send_register(self);
return send_register(self);
}
/* Any -> (transport error) -> Terminated
*/
void tsip_dialog_register_Any_2_Terminated_X_transportError(tsip_dialog_register_t *self)
int tsip_dialog_register_Any_2_Terminated_X_transportError(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_register_transporterr, 702, "Transport error.");
return 0;
}
/* Any -> (error) -> Terminated
*/
int tsip_dialog_register_Any_2_Terminated_X_Error(va_list *app)
{
tsip_dialog_register_t *self = va_arg(*app, tsip_dialog_register_t *);
const tsip_message_t *message = va_arg(*app, const tsip_message_t *);
return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// == STATE MACHINE END ==
@ -490,7 +643,7 @@ int send_register(tsip_dialog_register_t *self)
/**
* @fn void tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self)
* @fn int tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self)
*
* @brief Callback function called by the state machine manager to signal that the final state has been reached.
*
@ -499,18 +652,20 @@ int send_register(tsip_dialog_register_t *self)
*
* @param [in,out] self The state machine owner.
**/
void tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self)
int tsip_dialog_register_OnTerminated(tsip_dialog_register_t *self)
{
TSK_DEBUG_INFO("=== Dialog terminated ===");
TSK_DEBUG_INFO("=== REGISTER Dialog terminated ===");
/* Cancel all timers */
DIALOG_TIMER_CANCEL(refresh);
/* Alert user */
TSIP_DIALOG_REGISTER_SIGNAL_INCOMING(self, tsip_register_terminated, 700, "Dialog terminated.");
/* Destroy asynchronously */
DIALOG_REMOVE_SCHEDULE();
/* Remove from the dialog layer. */
tsip_dialog_remove(TSIP_DIALOG(self));
return 0;
}
@ -537,6 +692,11 @@ static void* tsip_dialog_register_create(void * self, va_list * app)
tsip_stack_handle_t *stack = va_arg(*app, tsip_stack_handle_t *);
tsip_operation_handle_t *operation = va_arg(*app, tsip_operation_handle_t *);
/* create FSM */
dialog->fsm = TSK_FSM_CREATE(_fsm_state_Started, _fsm_state_Terminated);
dialog->fsm->debug = DEBUG_STATE_MACHINE;
tsk_fsm_set_callback_terminated(dialog->fsm, TSK_FSM_ONTERMINATED(tsip_dialog_register_OnTerminated), (const void*)dialog);
/* Initialize base class */
tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_register, stack, 0, operation);
@ -553,6 +713,9 @@ static void* tsip_dialog_register_destroy(void * self)
{
/* DeInitialize base class */
tsip_dialog_deinit(TSIP_DIALOG(self));
/* FSM */
TSK_OBJECT_SAFE_FREE(dialog->fsm);
}
return self;
}

View File

@ -40,17 +40,90 @@
#define DEBUG_STATE_MACHINE 1
#define TSIP_DIALOG_SUBSCRIBE_TIMER_SCHEDULE(TX) TSIP_DIALOG_TIMER_SCHEDULE(subscribe, TX)
#define TSIP_DIALOG_SUBSCRIBE_SIGNAL_ERROR(self) \
TSIP_DIALOG_SYNC_BEGIN(self); \
tsip_dialog_subscribeContext_sm_error(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm); \
TSIP_DIALOG_SYNC_END(self);
#define TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, type, code, phrase, incoming) \
tsip_subscribe_event_signal(type, TSIP_DIALOG_GET_STACK(self),/*tsip_operation_get_id(TSIP_DIALOG(self)->operation)*/0, code, phrase, incoming)
#define TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, type, code, phrase) TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, type, code, phrase, 1)
#define TSIP_DIALOG_SUBSCRIBE_SIGNAL_OUTGOING(self, type, code, phrase) TSIP_DIALOG_SUBSCRIBE_SIGNAL(self, type, code, phrase, 0)
/* ======================== internal functions ======================== */
int send_subscribe(tsip_dialog_subscribe_t *self);
int send_notify_200ok(tsip_dialog_subscribe_t *self, const tsip_request_t* request);
int tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self);
/* ======================== transitions ======================== */
int tsip_dialog_subscribe_Started_2_Trying_X_send(va_list *app);
int tsip_dialog_subscribe_Trying_2_Trying_X_1xx(va_list *app);
int tsip_dialog_subscribe_Trying_2_Terminated_X_2xx(va_list *app);
int tsip_dialog_subscribe_Trying_2_Connected_X_2xx(va_list *app);
int tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494(va_list *app);
int tsip_dialog_subscribe_Trying_2_Trying_X_423(va_list *app);
int tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699(va_list *app);
int tsip_dialog_subscribe_Trying_2_Terminated_X_cancel(va_list *app);
int tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY(va_list *app);
int tsip_dialog_subscribe_Connected_2_Trying_X_unsubscribe(va_list *app);
int tsip_dialog_subscribe_Connected_2_Trying_X_refresh(va_list *app);
int tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY(va_list *app);
int tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY(va_list *app);
int tsip_dialog_subscribe_Any_2_Trying_X_hangup(va_list *app);
int tsip_dialog_subscribe_Any_2_Terminated_X_transportError(va_list *app);
int tsip_dialog_subscribe_Any_2_Terminated_X_Error(va_list *app);
/* ======================== conds ======================== */
int _fsm_cond_unsubscribing(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
{
return dialog->unsubscribing ? 1 : 0;
}
int _fsm_cond_subscribing(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
{
return !_fsm_cond_unsubscribing(dialog, message);
}
int _fsm_cond_notify_terminated(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
{
const tsip_header_Subscription_State_t *hdr_state;
if((hdr_state = (const tsip_header_Subscription_State_t*)tsip_message_get_header(message, tsip_htype_Subscription_State)))
{
return tsk_striequals(hdr_state->state, "terminated") &&
(hdr_state->expires < 0 || tsk_striequals(hdr_state->reason, "rejected") || tsk_striequals(hdr_state->reason, "noresource"));
}
return 0;
}
int _fsm_cond_notify_not_terminated(tsip_dialog_subscribe_t* dialog, tsip_message_t* message)
{
return !_fsm_cond_notify_terminated(dialog, message);
}
/* ======================== actions ======================== */
typedef enum _fsm_action_e
{
_fsm_action_send,
_fsm_action_1xx,
_fsm_action_2xx,
_fsm_action_401_407_421_494,
_fsm_action_423,
_fsm_action_300_to_699,
_fsm_action_cancel,
_fsm_action_notify,
_fsm_action_unsubscribe,
_fsm_action_refresh,
_fsm_action_hangup,
_fsm_action_transporterror,
_fsm_action_error,
}
_fsm_action_t;
/* ======================== states ======================== */
typedef enum _fsm_state_e
{
_fsm_state_Started,
_fsm_state_Trying,
_fsm_state_Connected,
_fsm_state_Terminated
}
_fsm_state_t;
/**
* @fn int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, tsip_dialog_event_type_t type,
@ -69,7 +142,7 @@ int send_notify_200ok(tsip_dialog_subscribe_t *self, const tsip_request_t* reque
**/
int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, tsip_dialog_event_type_t type, const tsip_message_t *msg)
{
TSIP_DIALOG_SYNC_BEGIN(self);
int ret = -1;
switch(type)
{
@ -82,24 +155,24 @@ int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, ts
//
if(TSIP_RESPONSE_IS_1XX(msg))
{
tsip_dialog_subscribeContext_sm_1xx(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_1xx, self, msg, self, msg);
}
else if(TSIP_RESPONSE_IS_2XX(msg))
{
tsip_dialog_subscribeContext_sm_2xx(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm, TSIP_DIALOG_SUBSCRIBE(self)->unsubscribing, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_2xx, self, msg, self, msg);
}
else if(TSIP_RESPONSE_IS(msg,401) || TSIP_RESPONSE_IS(msg,407) || TSIP_RESPONSE_IS(msg,421) || TSIP_RESPONSE_IS(msg,494))
{
tsip_dialog_subscribeContext_sm_401_407_421_494(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_401_407_421_494, self, msg, self, msg);
}
else if(TSIP_RESPONSE_IS(msg,423))
{
tsip_dialog_subscribeContext_sm_423(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm, msg);
ret = tsk_fsm_act(self->fsm, _fsm_action_423, self, msg, self, msg);
}
else
{
// Alert User
TSIP_DIALOG_SUBSCRIBE_SIGNAL_ERROR(self);
ret = tsk_fsm_act((self)->fsm, _fsm_action_error, self, msg, self, msg);
TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg));
}
}
@ -108,22 +181,8 @@ int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, ts
//
// REQUEST
//
if(tsk_striequals(TSIP_REQUEST_METHOD(msg), "NOTIFY"))
{
const tsip_header_Subscription_State_t *hdr_state;
if((hdr_state = (const tsip_header_Subscription_State_t*)tsip_message_get_header(msg, tsip_htype_Subscription_State)))
{
const char* state = hdr_state->state;
const char* reason = hdr_state->reason;
int32_t expires = hdr_state->expires;
int terminated = tsk_striequals(state, "terminated") &&
(expires < 0 || tsk_striequals(reason, "rejected") || tsk_striequals(reason, "noresource"));
tsip_dialog_subscribeContext_sm_NOTIFY(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm, terminated, msg);
}
else{
tsip_dialog_subscribeContext_sm_NOTIFY(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm, 1, msg);// FIXME: send error
}
if(tsk_striequals(TSIP_REQUEST_METHOD(msg), "NOTIFY")){
ret = tsk_fsm_act((self)->fsm, _fsm_action_notify, self, msg, self, msg);
}
else
{
@ -135,13 +194,13 @@ int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, ts
case tsip_dialog_hang_up:
{
tsip_dialog_subscribeContext_sm_hangup(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm);
ret = tsk_fsm_act(self->fsm, _fsm_action_hangup, self, msg, self, msg);
break;
}
case tsip_dialog_canceled:
{
tsip_dialog_subscribeContext_sm_cancel(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm);
ret = tsk_fsm_act(self->fsm, _fsm_action_cancel, self, msg, self, msg);
break;
}
@ -150,14 +209,12 @@ int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, ts
case tsip_dialog_error:
case tsip_dialog_transport_error:
{
tsip_dialog_subscribeContext_sm_transportError(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm);
ret = tsk_fsm_act(self->fsm, _fsm_action_transporterror, self, msg, self, msg);
break;
}
}
TSIP_DIALOG_SYNC_END(self);
return 0;
return ret;
}
/**
@ -180,33 +237,87 @@ int tsip_dialog_subscribe_timer_callback(const tsip_dialog_subscribe_t* self, ts
if(self)
{
TSIP_DIALOG_SYNC_BEGIN(self);
if(timer_id == self->timerrefresh.id)
{
tsip_dialog_subscribeContext_sm_refresh(&TSIP_DIALOG_SUBSCRIBE(self)->_fsm);
tsk_fsm_act(self->fsm, _fsm_action_refresh, self, TSK_NULL, self, TSK_NULL);
ret = 0;
}
TSIP_DIALOG_SYNC_END(self);
}
return ret;
}
/**
* @fn void tsip_dialog_subscribe_init(tsip_dialog_subscribe_t *self)
* @fn int tsip_dialog_subscribe_init(tsip_dialog_subscribe_t *self)
*
* @brief Initializes the dialog.
*
* @param [in,out] self The dialog to initialize.
**/
void tsip_dialog_subscribe_init(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_init(tsip_dialog_subscribe_t *self)
{
const tsk_param_t* param;
tsip_uri_t* uri = 0;
/* Initialize the state machine.
*/
tsip_dialog_subscribeContext_Init(&self->_fsm, self);
/* Initialize the State Machine. */
tsk_fsm_set(self->fsm,
/*=======================
* === Started ===
*/
// Started -> (Send) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_send, _fsm_state_Trying, tsip_dialog_subscribe_Started_2_Trying_X_send, "tsip_dialog_subscribe_Started_2_Trying_X_send"),
// Started -> (Any) -> Started
TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_dialog_subscribe_Started_2_Started_X_any"),
/*=======================
* === Trying ===
*/
// Trying -> (1xx) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_1xx, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_1xx, "tsip_dialog_subscribe_Trying_2_Trying_X_1xx"),
// Trying -> (2xx) -> Terminated
TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_unsubscribing, _fsm_state_Terminated, tsip_dialog_subscribe_Trying_2_Terminated_X_2xx, "tsip_dialog_subscribe_Trying_2_Terminated_X_2xx"),
// Trying -> (2xx) -> Connected
TSK_FSM_ADD(_fsm_state_Trying, _fsm_action_2xx, _fsm_cond_subscribing, _fsm_state_Connected, tsip_dialog_subscribe_Trying_2_Connected_X_2xx, "tsip_dialog_subscribe_Trying_2_Connected_X_2xx"),
// Trying -> (401/407/421/494) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_401_407_421_494, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494, "tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494"),
// Trying -> (423) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_423, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_423, "tsip_dialog_subscribe_Trying_2_Trying_X_423"),
// Trying -> (300_to_699) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_300_to_699, _fsm_state_Terminated, tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699, "tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699"),
// Trying -> (cancel) -> Terminated
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_cancel, _fsm_state_Terminated, tsip_dialog_subscribe_Trying_2_Terminated_X_cancel, "tsip_dialog_subscribe_Trying_2_Terminated_X_cancel"),
// Trying -> (Notify) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_notify, _fsm_state_Trying, tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY, "tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY"),
// Trying -> (Any) -> Trying
TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Trying, "tsip_dialog_subscribe_Trying_2_Trying_X_any"),
/*=======================
* === Connected ===
*/
// Connected -> (unsubscribe) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_unsubscribe, _fsm_state_Trying, tsip_dialog_subscribe_Connected_2_Trying_X_unsubscribe, "tsip_dialog_subscribe_Connected_2_Trying_X_unsubscribe"),
// Connected -> (refresh) -> Trying
TSK_FSM_ADD_ALWAYS(_fsm_state_Connected, _fsm_action_refresh, _fsm_state_Trying, tsip_dialog_subscribe_Connected_2_Trying_X_refresh, "tsip_dialog_subscribe_Connected_2_Trying_X_refresh"),
// Connected -> (NOTIFY) -> Connected
TSK_FSM_ADD(_fsm_state_Connected, _fsm_action_notify, _fsm_cond_notify_not_terminated, _fsm_state_Connected, tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY, "tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY"),
// Connected -> (NOTIFY) -> Terminated
TSK_FSM_ADD(_fsm_state_Connected, _fsm_action_notify, _fsm_cond_notify_terminated, _fsm_state_Terminated, tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY, "tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY"),
// Connected -> (Any) -> Connected
TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Connected, "tsip_dialog_subscribe_Connected_2_Connected_X_any"),
/*=======================
* === Any ===
*/
// Any -> (transport error) -> Terminated
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_dialog_subscribe_Any_2_Terminated_X_transportError, "tsip_dialog_subscribe_Any_2_Terminated_X_transportError"),
// Any -> (transport error) -> Terminated
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_dialog_subscribe_Any_2_Terminated_X_Error, "tsip_dialog_subscribe_Any_2_Terminated_X_Error"),
// Any -> (hangup) -> Terminated
// Any -> (hangup) -> Trying
TSK_FSM_ADD_NULL());
/* Package. */
if((param = tsip_operation_get_param(TSIP_DIALOG(self)->operation, "package"))){
@ -233,9 +344,7 @@ void tsip_dialog_subscribe_init(tsip_dialog_subscribe_t *self)
tsk_object_unref(uri);
#if defined(_DEBUG) || defined(DEBUG)
setDebugFlag(&(self->_fsm), DEBUG_STATE_MACHINE);
#endif
return 0;
}
int tsip_dialog_subscribe_start(tsip_dialog_subscribe_t *self)
@ -243,12 +352,8 @@ int tsip_dialog_subscribe_start(tsip_dialog_subscribe_t *self)
int ret = -1;
if(self && !TSIP_DIALOG(self)->running)
{
/* Set state machine state to started */
setState(&self->_fsm, &tsip_dialog_subscribe_Started);
/* Send request */
tsip_dialog_subscribeContext_sm_send(&self->_fsm);
ret = 0;
ret = tsk_fsm_act(self->fsm, _fsm_action_send, self, TSK_NULL, self, TSK_NULL);
}
return ret;
}
@ -260,29 +365,44 @@ int tsip_dialog_subscribe_start(tsip_dialog_subscribe_t *self)
/* Started -> (send) -> Trying
*/
void tsip_dialog_subscribe_Started_2_Trying_X_send(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_Started_2_Trying_X_send(va_list *app)
{
send_subscribe(self);
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
return send_subscribe(self);
}
/* Trying -> (1xx) -> Trying
*/
void tsip_dialog_subscribe_Trying_2_Trying_X_1xx(tsip_dialog_subscribe_t *self, const tsip_response_t* response)
int tsip_dialog_subscribe_Trying_2_Trying_X_1xx(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
return 0;
}
/* Trying -> (2xx) -> Terminated
*/
void tsip_dialog_subscribe_Trying_2_Terminated_X_2xx(tsip_dialog_subscribe_t *self, const tsip_response_t* response)
int tsip_dialog_subscribe_Trying_2_Terminated_X_2xx(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
/* Alert the user. */
TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, tsip_unsubscribe_ok, TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response));
return 0;
}
/* Trying -> (2xx) -> Connected
*/
void tsip_dialog_subscribe_Trying_2_Connected_X_2xx(tsip_dialog_subscribe_t *self, const tsip_response_t* response)
int tsip_dialog_subscribe_Trying_2_Connected_X_2xx(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
/* Alert the user. */
TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, tsip_subscribe_ok,
TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response));
@ -293,32 +413,36 @@ void tsip_dialog_subscribe_Trying_2_Connected_X_2xx(tsip_dialog_subscribe_t *sel
/* Request timeout for dialog refresh (re-subscribtion). */
self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), response);
TSIP_DIALOG_SUBSCRIBE_TIMER_SCHEDULE(refresh);
return 0;
}
/* Trying -> (401/407/421/494) -> Trying
*/
void tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494(tsip_dialog_subscribe_t *self, const tsip_response_t* response)
int tsip_dialog_subscribe_Trying_2_Trying_X_401_407_421_494(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
if(tsip_dialog_update(TSIP_DIALOG(self), response))
{
TSIP_DIALOG_SUBSCRIBE_SIGNAL_ERROR(self);
/* Alert the user. */
TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, self->unsubscribing ? tsip_unsubscribing : tsip_subscribing,
TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response));
goto bail;
return -1;
}
send_subscribe(self);
bail:;
return send_subscribe(self);
}
/* Trying -> (423) -> Trying
*/
void tsip_dialog_subscribe_Trying_2_Trying_X_423(tsip_dialog_subscribe_t *self, const tsip_response_t* response)
int tsip_dialog_subscribe_Trying_2_Trying_X_423(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
tsip_header_Min_Expires_t *hdr;
/*
@ -338,52 +462,80 @@ void tsip_dialog_subscribe_Trying_2_Trying_X_423(tsip_dialog_subscribe_t *self,
}
else
{
TSIP_DIALOG_SUBSCRIBE_SIGNAL_ERROR(self);
TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, self->unsubscribing ? tsip_unsubscribing : tsip_subscribing,
TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response));
return -1;
}
return 0;
}
/* Trying -> (300-699) -> Terminated
*/
void tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699(tsip_dialog_subscribe_t *self, const tsip_response_t* response)
int tsip_dialog_subscribe_Trying_2_Terminated_X_300_to_699(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
/* Alert the user. */
TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, tsip_subscribe_nok, TSIP_RESPONSE_CODE(response), TSIP_RESPONSE_PHRASE(response));
return 0;
}
/* Trying -> (cancel) -> Terminated
*/
void tsip_dialog_subscribe_Trying_2_Terminated_X_cancel(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_Trying_2_Terminated_X_cancel(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
/* Alert the user. */
TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, tsip_subscribe_cancelled, 801, "Subscribtion cancelled");
return 0;
}
/* Trying -> (NOTIFY) -> Trying
*/
void tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request)
int tsip_dialog_subscribe_Trying_2_Trying_X_NOTIFY(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
send_notify_200ok(self, request);
return 0;
}
/* Connected -> (unsubscribe) -> Trying
*/
void tsip_dialog_subscribe_Connected_2_Trying_X_unsubscribe(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_Connected_2_Trying_X_unsubscribe(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
return 0;
}
/* Connected -> (refresh) -> Trying
*/
void tsip_dialog_subscribe_Connected_2_Trying_X_refresh(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_Connected_2_Trying_X_refresh(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
return 0;
}
/* Connected -> (NOTIFY) -> Connected
*/
void tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request)
int tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
send_notify_200ok(self, request);
/* Alert the user */
@ -393,27 +545,49 @@ void tsip_dialog_subscribe_Connected_2_Connected_X_NOTIFY(tsip_dialog_subscribe_
/* Request timeout for dialog refresh (re-registration). */
self->timerrefresh.timeout = tsip_dialog_get_newdelay(TSIP_DIALOG(self), request);
TSIP_DIALOG_SUBSCRIBE_TIMER_SCHEDULE(refresh);
return 0;
}
/* Connected -> (NOTIFY) -> Terminated
*/
void tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY(tsip_dialog_subscribe_t *self, const tsip_request_t* request)
int tsip_dialog_subscribe_Connected_2_Terminated_X_NOTIFY(va_list *app)
{
send_notify_200ok(self, request);
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_request_t *request = va_arg(*app, const tsip_request_t *);
return send_notify_200ok(self, request);
}
/* Any -> (hangup) -> Trying
*/
void tsip_dialog_subscribe_Any_2_Trying_X_hangup(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_Any_2_Trying_X_hangup(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
return 0;
}
/* Any -> (transport error) -> Terminated
*/
void tsip_dialog_subscribe_Any_2_Terminated_X_transportError(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_Any_2_Terminated_X_transportError(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
return 0;
}
/* Any -> (error) -> Terminated
*/
int tsip_dialog_subscribe_Any_2_Terminated_X_Error(va_list *app)
{
tsip_dialog_subscribe_t *self = va_arg(*app, tsip_dialog_subscribe_t *);
const tsip_response_t *response = va_arg(*app, const tsip_response_t *);
return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@ -467,7 +641,7 @@ int send_notify_200ok(tsip_dialog_subscribe_t *self, const tsip_request_t* reque
}
/**
* @fn void tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self)
* @fn int tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self)
*
* @brief Callback function called by the state machine manager to signal that the final state has been reached.
*
@ -476,9 +650,9 @@ int send_notify_200ok(tsip_dialog_subscribe_t *self, const tsip_request_t* reque
*
* @param [in,out] self The state machine owner.
**/
void tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self)
int tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self)
{
TSK_DEBUG_INFO("=== Dialog terminated ===");
TSK_DEBUG_INFO("=== SUBSCRIBE Dialog terminated ===");
/* Cancel all timers */
DIALOG_TIMER_CANCEL(refresh);
@ -486,8 +660,10 @@ void tsip_dialog_subscribe_OnTerminated(tsip_dialog_subscribe_t *self)
/* Alert user */
TSIP_DIALOG_SUBSCRIBE_SIGNAL_INCOMING(self, tsip_subscribe_terminated, 700, "Dialog terminated.");
/* Destroy asynchronously */
DIALOG_REMOVE_SCHEDULE();
/* Remove from the dialog layer. */
tsip_dialog_remove(TSIP_DIALOG(self));
return 0;
}
@ -502,6 +678,11 @@ static void* tsip_dialog_subscribe_create(void * self, va_list * app)
tsip_stack_handle_t *stack = va_arg(*app, tsip_stack_handle_t *);
tsip_operation_handle_t *operation = va_arg(*app, tsip_operation_handle_t *);
/* create FSM */
dialog->fsm = TSK_FSM_CREATE(_fsm_state_Started, _fsm_state_Terminated);
dialog->fsm->debug = DEBUG_STATE_MACHINE;
tsk_fsm_set_callback_terminated(dialog->fsm, TSK_FSM_ONTERMINATED(tsip_dialog_subscribe_OnTerminated), (const void*)dialog);
/* Initialize base class */
tsip_dialog_init(TSIP_DIALOG(self), tsip_dialog_subscribe, stack, 0, operation);
@ -519,6 +700,9 @@ static void* tsip_dialog_subscribe_destroy(void * self)
/* DeInitialize base class */
tsip_dialog_deinit(TSIP_DIALOG(self));
/* FSM */
TSK_OBJECT_SAFE_FREE(dialog->fsm);
TSK_FREE(dialog->package);
}
return self;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -92,7 +92,7 @@ int tsip_registration_callback(const tsip_register_event_t *sipevent)
void test_stack()
{
/*
tsip_stack_handle_t *stack = tsip_stack_create(test_stack_callback,
TSIP_STACK_SET_DISPLAY_NAME("2233392625"),
TSIP_STACK_SET_PUBLIC_IDENTITY("sip:2233392625@sip2sip.info"),
@ -108,7 +108,7 @@ void test_stack()
TSIP_STACK_SET_MOBILITY("fixed"),
TSIP_STACK_SET_DEVICE_ID("DD1289FA-C3D7-47bd-A40D-F1F1B2CC5FFC"),
TSIP_STACK_SET_NETINFO("ADSL;utran-cell-id-3gpp=00000000"),
*/
/*
tsip_stack_handle_t *stack = tsip_stack_create(test_stack_callback,
TSIP_STACK_SET_DISPLAY_NAME("Mamadou"),
@ -126,7 +126,6 @@ void test_stack()
TSIP_STACK_SET_DEVICE_ID("DD1289FA-C3D7-47bd-A40D-F1F1B2CC5FFC"),
TSIP_STACK_SET_NETINFO("ADSL;utran-cell-id-3gpp=00000000"),
*/
TSIP_STACK_SET_NULL());
tsip_operation_handle_t *op = TSIP_OPERATION_CREATE(stack,
@ -144,14 +143,14 @@ void test_stack()
tsip_register(stack, op);
tsk_thread_sleep(2000);
tsk_thread_sleep(1000);
{
tsip_operation_handle_t *op2 = TSIP_OPERATION_CREATE(stack,
TSIP_OPERATION_SET_PARAM("expires", "30"),
TSIP_OPERATION_SET_PARAM("package", "reg"),
TSIP_OPERATION_SET_PARAM("package", "presence"),
TSIP_OPERATION_SET_PARAM("accept", "application/reginfo+xml"),
TSIP_OPERATION_SET_PARAM("to", "sip:mamadou@ims.inexbee.com"),
TSIP_OPERATION_SET_PARAM("to", "sip:2233392625@sip2sip.info"),
TSIP_OPERATION_SET_NULL());
tsip_subscribe(stack, op2);