- 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:
parent
8e7fd29c1c
commit
9c98f2a38d
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue