diff options
Diffstat (limited to 'tinySIP/src/transactions')
-rwxr-xr-x | tinySIP/src/transactions/tsip_transac.c | 340 | ||||
-rwxr-xr-x | tinySIP/src/transactions/tsip_transac_ict.c | 1180 | ||||
-rwxr-xr-x | tinySIP/src/transactions/tsip_transac_ist.c | 1008 | ||||
-rwxr-xr-x | tinySIP/src/transactions/tsip_transac_layer.c | 472 | ||||
-rwxr-xr-x | tinySIP/src/transactions/tsip_transac_nict.c | 806 | ||||
-rwxr-xr-x | tinySIP/src/transactions/tsip_transac_nist.c | 611 |
6 files changed, 2186 insertions, 2231 deletions
diff --git a/tinySIP/src/transactions/tsip_transac.c b/tinySIP/src/transactions/tsip_transac.c index 1ecac59..6498f51 100755 --- a/tinySIP/src/transactions/tsip_transac.c +++ b/tinySIP/src/transactions/tsip_transac.c @@ -2,19 +2,19 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -43,232 +43,226 @@ static tsk_object_t* tsip_transac_dst_ctor(tsk_object_t * _self, va_list * app) { - tsip_transac_dst_t *dst = _self; - if(dst){ - - } - return _self; + tsip_transac_dst_t *dst = _self; + if(dst) { + + } + return _self; } static tsk_object_t* tsip_transac_dst_dtor(tsk_object_t * _self) -{ - tsip_transac_dst_t *dst = _self; - if(dst){ - TSK_OBJECT_SAFE_FREE(dst->stack); - switch(dst->type){ - case tsip_transac_dst_type_dialog: - { - TSK_OBJECT_SAFE_FREE(dst->dialog.dlg); - break; - } - case tsip_transac_dst_type_net: - { - break; - } - } - } - return _self; -} -static const tsk_object_def_t tsip_transac_dst_def_s = { - sizeof(tsip_transac_dst_t), - tsip_transac_dst_ctor, - tsip_transac_dst_dtor, - tsk_null, + tsip_transac_dst_t *dst = _self; + if(dst) { + TSK_OBJECT_SAFE_FREE(dst->stack); + switch(dst->type) { + case tsip_transac_dst_type_dialog: { + TSK_OBJECT_SAFE_FREE(dst->dialog.dlg); + break; + } + case tsip_transac_dst_type_net: { + break; + } + } + } + return _self; +} +static const tsk_object_def_t tsip_transac_dst_def_s = { + sizeof(tsip_transac_dst_t), + tsip_transac_dst_ctor, + tsip_transac_dst_dtor, + tsk_null, }; const tsk_object_def_t *tsip_transac_dst_def_t = &tsip_transac_dst_def_s; static struct tsip_transac_dst_s* tsip_transac_dst_create(tsip_transac_dst_type_t type, struct tsip_stack_s* stack) { - struct tsip_transac_dst_s* dst = tsk_object_new(tsip_transac_dst_def_t); - if(dst){ - dst->type = type; - dst->stack = tsk_object_ref(stack); - } - return dst; + struct tsip_transac_dst_s* dst = tsk_object_new(tsip_transac_dst_def_t); + if(dst) { + dst->type = type; + dst->stack = tsk_object_ref(stack); + } + return dst; } struct tsip_transac_dst_s* tsip_transac_dst_dialog_create(tsip_dialog_t *dlg) { - struct tsip_transac_dst_s* dst; - if((dst = tsip_transac_dst_create(tsip_transac_dst_type_dialog, TSIP_DIALOG_GET_STACK(dlg)))){ - dst->dialog.dlg = tsk_object_ref(dlg); - } - return dst; + struct tsip_transac_dst_s* dst; + if((dst = tsip_transac_dst_create(tsip_transac_dst_type_dialog, TSIP_DIALOG_GET_STACK(dlg)))) { + dst->dialog.dlg = tsk_object_ref(dlg); + } + return dst; } struct tsip_transac_dst_s* tsip_transac_dst_net_create(struct tsip_stack_s* stack) { - struct tsip_transac_dst_s* dst; - if((dst = tsip_transac_dst_create(tsip_transac_dst_type_net, stack))){ - } - return dst; + struct tsip_transac_dst_s* dst; + if((dst = tsip_transac_dst_create(tsip_transac_dst_type_net, stack))) { + } + return dst; } static int tsip_transac_dst_deliver(struct tsip_transac_dst_s* self, tsip_dialog_event_type_t event_type, const tsip_message_t *msg) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - switch(self->type){ - case tsip_transac_dst_type_dialog: - { - return self->dialog.dlg->callback( - self->dialog.dlg, - event_type, - msg - ); - } - case tsip_transac_dst_type_net: - { - if(!msg){ - TSK_DEBUG_ERROR("Message is null"); - return -1; - } - - // all messages coming from WebSocket transport have to be updated (AoR, Via...) before network delivering - // all other messages MUST not unless specified from the dialog layer - TSIP_MESSAGE(msg)->update |= (TNET_SOCKET_TYPE_IS_WS(msg->src_net_type) || TNET_SOCKET_TYPE_IS_WSS(msg->src_net_type)); - - return tsip_transport_layer_send( - self->stack->layer_transport, - msg->firstVia ? msg->firstVia->branch : tsk_null, - TSIP_MESSAGE(msg) - ); - } - default: - { - TSK_DEBUG_ERROR("Unexpected code called"); - return -2; - } - } + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + switch(self->type) { + case tsip_transac_dst_type_dialog: { + return self->dialog.dlg->callback( + self->dialog.dlg, + event_type, + msg + ); + } + case tsip_transac_dst_type_net: { + if(!msg) { + TSK_DEBUG_ERROR("Message is null"); + return -1; + } + + // all messages coming from WebSocket transport have to be updated (AoR, Via...) before network delivering + // all other messages MUST not unless specified from the dialog layer + TSIP_MESSAGE(msg)->update |= (TNET_SOCKET_TYPE_IS_WS(msg->src_net_type) || TNET_SOCKET_TYPE_IS_WSS(msg->src_net_type)); + + return tsip_transport_layer_send( + self->stack->layer_transport, + msg->firstVia ? msg->firstVia->branch : tsk_null, + TSIP_MESSAGE(msg) + ); + } + default: { + TSK_DEBUG_ERROR("Unexpected code called"); + return -2; + } + } } int tsip_transac_init(tsip_transac_t *self, tsip_transac_type_t type, int32_t cseq_value, const char* cseq_method, const char* callid, struct tsip_transac_dst_s* dst, tsk_fsm_state_id curr, tsk_fsm_state_id term) { - if(self && !self->initialized){ - self->type = type; - self->cseq_value = cseq_value; - tsk_strupdate(&self->cseq_method, cseq_method); - tsk_strupdate(&self->callid, callid); - self->dst = tsk_object_ref(dst); - - /* FSM */ - self->fsm = tsk_fsm_create(curr, term); - - self->initialized = tsk_true; - - return 0; - } - return -1; + if(self && !self->initialized) { + self->type = type; + self->cseq_value = cseq_value; + tsk_strupdate(&self->cseq_method, cseq_method); + tsk_strupdate(&self->callid, callid); + self->dst = tsk_object_ref(dst); + + /* FSM */ + self->fsm = tsk_fsm_create(curr, term); + + self->initialized = tsk_true; + + return 0; + } + return -1; } int tsip_transac_deinit(tsip_transac_t *self) { - if(self && self->initialized){ - /* FSM */ - TSK_OBJECT_SAFE_FREE(self->fsm); - - TSK_FREE(self->branch); - TSK_FREE(self->cseq_method); - TSK_FREE(self->callid); - TSK_OBJECT_SAFE_FREE(self->dst); - - self->initialized = tsk_false; - - return 0; - } - return -1; + if(self && self->initialized) { + /* FSM */ + TSK_OBJECT_SAFE_FREE(self->fsm); + + TSK_FREE(self->branch); + TSK_FREE(self->cseq_method); + TSK_FREE(self->callid); + TSK_OBJECT_SAFE_FREE(self->dst); + + self->initialized = tsk_false; + + return 0; + } + return -1; } int tsip_transac_start(tsip_transac_t *self, const tsip_request_t* request) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - switch(self->type){ - case tsip_transac_type_nist:{ - return tsip_transac_nist_start(TSIP_TRANSAC_NIST(self), request); - } - case tsip_transac_type_ist:{ - return tsip_transac_ist_start(TSIP_TRANSAC_IST(self), request); - } - case tsip_transac_type_nict:{ - return tsip_transac_nict_start(TSIP_TRANSAC_NICT(self), request); - } - case tsip_transac_type_ict:{ - return tsip_transac_ict_start(TSIP_TRANSAC_ICT(self), request); - } - } - - TSK_DEBUG_ERROR("Unexpected code called"); - return -2; + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + switch(self->type) { + case tsip_transac_type_nist: { + return tsip_transac_nist_start(TSIP_TRANSAC_NIST(self), request); + } + case tsip_transac_type_ist: { + return tsip_transac_ist_start(TSIP_TRANSAC_IST(self), request); + } + case tsip_transac_type_nict: { + return tsip_transac_nict_start(TSIP_TRANSAC_NICT(self), request); + } + case tsip_transac_type_ict: { + return tsip_transac_ict_start(TSIP_TRANSAC_ICT(self), request); + } + } + + TSK_DEBUG_ERROR("Unexpected code called"); + return -2; } // deliver the message to the destination (e.g. local dialog) int tsip_transac_deliver(tsip_transac_t* self, tsip_dialog_event_type_t event_type, const tsip_message_t *msg) { - if(!self){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - return tsip_transac_dst_deliver(self->dst, event_type, msg); + if(!self) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + return tsip_transac_dst_deliver(self->dst, event_type, msg); } // send the message over the network int tsip_transac_send(tsip_transac_t *self, const char *branch, tsip_message_t *msg) { - if(self && TSIP_TRANSAC_GET_STACK(self)->layer_transport && msg){ - const struct tsip_ssession_s* ss = TSIP_TRANSAC_GET_SESSION(self); - if(ss){ - // set SigComp identifier as the message is directly sent to the transport layer - tsk_strupdate(&msg->sigcomp_id, ss->sigcomp_id); - } - return tsip_transport_layer_send(TSIP_TRANSAC_GET_STACK(self)->layer_transport, branch, TSIP_MESSAGE(msg)); - } - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; + if(self && TSIP_TRANSAC_GET_STACK(self)->layer_transport && msg) { + const struct tsip_ssession_s* ss = TSIP_TRANSAC_GET_SESSION(self); + if(ss) { + // set SigComp identifier as the message is directly sent to the transport layer + tsk_strupdate(&msg->sigcomp_id, ss->sigcomp_id); + } + return tsip_transport_layer_send(TSIP_TRANSAC_GET_STACK(self)->layer_transport, branch, TSIP_MESSAGE(msg)); + } + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; } int tsip_transac_cmp(const tsip_transac_t *t1, const tsip_transac_t *t2) { - if(t1 && t2){ - if(tsk_strequals(t1->branch, t2->branch) && tsk_strequals(t1->cseq_method, t2->cseq_method)){ - return 0; - } - } - return -1; + if(t1 && t2) { + if(tsk_strequals(t1->branch, t2->branch) && tsk_strequals(t1->cseq_method, t2->cseq_method)) { + return 0; + } + } + return -1; } int tsip_transac_remove(const tsip_transac_t* self) { - int ret; - tsip_transac_t* safe_copy; - - safe_copy = (tsip_transac_t*)tsk_object_ref(TSK_OBJECT(self)); - ret = tsip_transac_layer_remove(TSIP_TRANSAC_GET_STACK(self)->layer_transac, safe_copy); - tsk_object_unref(safe_copy); - - return ret; + int ret; + tsip_transac_t* safe_copy; + + safe_copy = (tsip_transac_t*)tsk_object_ref(TSK_OBJECT(self)); + ret = tsip_transac_layer_remove(TSIP_TRANSAC_GET_STACK(self)->layer_transac, safe_copy); + tsk_object_unref(safe_copy); + + return ret; } int tsip_transac_fsm_act(tsip_transac_t* self, tsk_fsm_action_id action_id, const tsip_message_t* message) { - int ret; - tsip_transac_t* safe_copy; + int ret; + tsip_transac_t* safe_copy; - if(!self || !self->fsm){ - TSK_DEBUG_WARN("Invalid parameter."); - return -1; - } + if(!self || !self->fsm) { + TSK_DEBUG_WARN("Invalid parameter."); + return -1; + } - safe_copy = tsk_object_ref(TSK_OBJECT(self)); - ret = tsk_fsm_act(self->fsm, action_id, safe_copy, message, self, message); - tsk_object_unref(safe_copy); + safe_copy = tsk_object_ref(TSK_OBJECT(self)); + ret = tsk_fsm_act(self->fsm, action_id, safe_copy, message, self, message); + tsk_object_unref(safe_copy); - return ret; + return ret; } diff --git a/tinySIP/src/transactions/tsip_transac_ict.c b/tinySIP/src/transactions/tsip_transac_ict.c index 8678851..c2b9b13 100755 --- a/tinySIP/src/transactions/tsip_transac_ict.c +++ b/tinySIP/src/transactions/tsip_transac_ict.c @@ -2,19 +2,19 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -111,32 +111,30 @@ int tsip_transac_ict_Any_2_Terminated_X_cancel(va_list *app); /* doubango-specif /* ======================== conds ======================== */ /* ======================== actions ======================== */ -typedef enum _fsm_action_e -{ - _fsm_action_cancel = tsip_atype_cancel, - - _fsm_action_send = 0xFF, - _fsm_action_timerA, - _fsm_action_timerB, - _fsm_action_timerD, - _fsm_action_timerM, - _fsm_action_1xx, - _fsm_action_2xx, - _fsm_action_300_to_699, - _fsm_action_transporterror, - _fsm_action_error, +typedef enum _fsm_action_e { + _fsm_action_cancel = tsip_atype_cancel, + + _fsm_action_send = 0xFF, + _fsm_action_timerA, + _fsm_action_timerB, + _fsm_action_timerD, + _fsm_action_timerM, + _fsm_action_1xx, + _fsm_action_2xx, + _fsm_action_300_to_699, + _fsm_action_transporterror, + _fsm_action_error, } _fsm_action_t; /* ======================== states ======================== */ -typedef enum _fsm_state_e -{ - _fsm_state_Started, - _fsm_state_Calling, - _fsm_state_Proceeding, - _fsm_state_Completed, - _fsm_state_Accepted, - _fsm_state_Terminated +typedef enum _fsm_state_e { + _fsm_state_Started, + _fsm_state_Calling, + _fsm_state_Proceeding, + _fsm_state_Completed, + _fsm_state_Accepted, + _fsm_state_Terminated } _fsm_state_t; @@ -145,88 +143,84 @@ _fsm_state_t; * Callback function called by the transport layer to alert the transaction for incoming messages * or errors (e.g. transport error). * - * @param [in,out] self A pointer to the IC transaction. - * @param type The event type. + * @param [in,out] self A pointer to the IC transaction. + * @param type The event type. * @param [in,out] msg The incoming message. * - * @return Zero if succeed and no-zero error code otherwise. + * @return Zero if succeed and no-zero error code otherwise. **/ int tsip_transac_ict_event_callback(const tsip_transac_ict_t *self, tsip_transac_event_type_t type, const tsip_message_t *msg) -{ - /* draft-sparks-sip-invfix-03 - 7.2. UAC Impacts - Any response received which does not match an existing client transaction state machine is simply dropped. - */ - switch(type){ - - case tsip_transac_incoming_msg: - { - if(msg) - { - if(TSIP_MESSAGE_IS_RESPONSE(msg)){ - if(TSIP_RESPONSE_IS_1XX(msg)){ - return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_1xx, msg); - } - else if(TSIP_RESPONSE_IS_2XX(msg)){ - return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_2xx, msg); - } - else if(TSIP_RESPONSE_IS_3456(msg)){ - return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_300_to_699, msg); - } - else{ - TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); - return 0; - } - } - // any other response have to be delivered if dst_type is 'network' - if(TSIP_TRANSAC(self)->dst->type == tsip_transac_dst_type_net){ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_transac_incoming_msg, msg); - } - } - break; - } - - case tsip_transac_canceled: - case tsip_transac_terminated: - case tsip_transac_timedout: - break; - - case tsip_transac_error: - { - return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); - } - - case tsip_transac_transport_error: - { - return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); - } - - default: break; - } - - return 0; +{ + /* draft-sparks-sip-invfix-03 - 7.2. UAC Impacts + Any response received which does not match an existing client transaction state machine is simply dropped. + */ + switch(type) { + + case tsip_transac_incoming_msg: { + if(msg) { + if(TSIP_MESSAGE_IS_RESPONSE(msg)) { + if(TSIP_RESPONSE_IS_1XX(msg)) { + return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_1xx, msg); + } + else if(TSIP_RESPONSE_IS_2XX(msg)) { + return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_2xx, msg); + } + else if(TSIP_RESPONSE_IS_3456(msg)) { + return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_300_to_699, msg); + } + else { + TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); + return 0; + } + } + // any other response have to be delivered if dst_type is 'network' + if(TSIP_TRANSAC(self)->dst->type == tsip_transac_dst_type_net) { + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_transac_incoming_msg, msg); + } + } + break; + } + + case tsip_transac_canceled: + case tsip_transac_terminated: + case tsip_transac_timedout: + break; + + case tsip_transac_error: { + return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); + } + + case tsip_transac_transport_error: { + return tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); + } + + default: + break; + } + + return 0; } int tsip_transac_ict_timer_callback(const tsip_transac_ict_t* self, tsk_timer_id_t timer_id) { - int ret = -1; - - if(self && TSIP_TRANSAC(self)) - { - if(timer_id == self->timerA.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerA, tsk_null); - } - else if(timer_id == self->timerB.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerB, tsk_null); - } - else if(timer_id == self->timerD.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerD, tsk_null); - } - else if(timer_id == self->timerM.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerM, tsk_null); - } - } - - return ret; + int ret = -1; + + if(self && TSIP_TRANSAC(self)) { + if(timer_id == self->timerA.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerA, tsk_null); + } + else if(timer_id == self->timerB.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerB, tsk_null); + } + else if(timer_id == self->timerD.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerD, tsk_null); + } + else if(timer_id == self->timerM.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerM, tsk_null); + } + } + + return ret; } @@ -239,135 +233,135 @@ int tsip_transac_ict_timer_callback(const tsip_transac_ict_t* self, tsk_timer_id **/ int tsip_transac_ict_init(tsip_transac_ict_t *self) { - /* Initialize the state machine. */ - tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), - - /*======================= - * === Started === - */ - // Started -> (Send) -> Calling - TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_send, _fsm_state_Calling, tsip_transac_ict_Started_2_Calling_X_send, "tsip_transac_ict_Started_2_Calling_X_send"), - // Started -> (Any) -> Started - TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_ict_Started_2_Started_X_any"), - - /*======================= - * === Calling === - */ - // Calling -> (timerA) -> Calling - TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_timerA, _fsm_state_Calling, tsip_transac_ict_Calling_2_Calling_X_timerA, "tsip_transac_ict_Calling_2_Calling_X_timerA"), - // Calling -> (timerB) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_timerB, _fsm_state_Terminated, tsip_transac_ict_Calling_2_Terminated_X_timerB, "tsip_transac_ict_Calling_2_Terminated_X_timerB"), - // Calling -> (300-699) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_300_to_699, _fsm_state_Completed, tsip_transac_ict_Calling_2_Completed_X_300_to_699, "tsip_transac_ict_Calling_2_Completed_X_300_to_699"), - // Calling -> (1xx) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_ict_Calling_2_Proceeding_X_1xx, "tsip_transac_ict_Calling_2_Proceeding_X_1xx"), - // Calling -> (2xx) -> Accepted - TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_2xx, _fsm_state_Accepted, tsip_transac_ict_Calling_2_Accepted_X_2xx, "tsip_transac_ict_Calling_2_Accepted_X_2xx"), - - /*======================= - * === Proceeding === - */ - // Proceeding -> (1xx) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_ict_Proceeding_2_Proceeding_X_1xx, "tsip_transac_ict_Proceeding_2_Proceeding_X_1xx"), - // Proceeding -> (300-699) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_300_to_699, _fsm_state_Completed, tsip_transac_ict_Proceeding_2_Completed_X_300_to_699, "tsip_transac_ict_Proceeding_2_Completed_X_300_to_699"), - // Proceeding -> (2xx) -> Accepted - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_2xx, _fsm_state_Accepted, tsip_transac_ict_Proceeding_2_Accepted_X_2xx, "tsip_transac_ict_Proceeding_2_Accepted_X_2xx"), - - /*======================= - * === Completed === - */ - // Completed -> (300-699) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_300_to_699, _fsm_state_Completed, tsip_transac_ict_Completed_2_Completed_X_300_to_699, "tsip_transac_ict_Completed_2_Completed_X_300_to_699"), - // Completed -> (timerD) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerD, _fsm_state_Terminated, tsip_transac_ict_Completed_2_Terminated_X_timerD, "tsip_transac_ict_Completed_2_Terminated_X_timerD"), - - /*======================= - * === Accepted === - */ - // Accepted -> (2xx) -> Accepted - TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_2xx, _fsm_state_Accepted, tsip_transac_ict_Accepted_2_Accepted_X_2xx, "tsip_transac_ict_Accepted_2_Accepted_X_2xx"), - // Accepted -> (timerM) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_timerM, _fsm_state_Terminated, tsip_transac_ict_Accepted_2_Terminated_X_timerM, "tsip_transac_ict_Accepted_2_Terminated_X_timerM"), - - /*======================= - * === Any === - */ - // Any -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_ict_Any_2_Terminated_X_transportError, "tsip_transac_ict_Any_2_Terminated_X_transportError"), - // Any -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_ict_Any_2_Terminated_X_Error, "tsip_transac_ict_Any_2_Terminated_X_Error"), - // Any -> (cancel) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_ict_Any_2_Terminated_X_cancel, "tsip_transac_ict_Any_2_Terminated_X_cancel"), - - TSK_FSM_ADD_NULL()); - - - /* Set callback function to call when new messages arrive or errors happen in - the transport layer. - */ - TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_ict_event_callback); - - /* Timers */ - self->timerA.id = TSK_INVALID_TIMER_ID; - self->timerB.id = TSK_INVALID_TIMER_ID; - self->timerD.id = TSK_INVALID_TIMER_ID; - self->timerM.id = TSK_INVALID_TIMER_ID; - - self->timerA.timeout = TSIP_TIMER_GET(A); - self->timerB.timeout = TSIP_TIMER_GET(B); - self->timerM.timeout = TSIP_TIMER_GET(M); - - return 0; + /* Initialize the state machine. */ + tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), + + /*======================= + * === Started === + */ + // Started -> (Send) -> Calling + TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_send, _fsm_state_Calling, tsip_transac_ict_Started_2_Calling_X_send, "tsip_transac_ict_Started_2_Calling_X_send"), + // Started -> (Any) -> Started + TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_ict_Started_2_Started_X_any"), + + /*======================= + * === Calling === + */ + // Calling -> (timerA) -> Calling + TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_timerA, _fsm_state_Calling, tsip_transac_ict_Calling_2_Calling_X_timerA, "tsip_transac_ict_Calling_2_Calling_X_timerA"), + // Calling -> (timerB) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_timerB, _fsm_state_Terminated, tsip_transac_ict_Calling_2_Terminated_X_timerB, "tsip_transac_ict_Calling_2_Terminated_X_timerB"), + // Calling -> (300-699) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_300_to_699, _fsm_state_Completed, tsip_transac_ict_Calling_2_Completed_X_300_to_699, "tsip_transac_ict_Calling_2_Completed_X_300_to_699"), + // Calling -> (1xx) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_ict_Calling_2_Proceeding_X_1xx, "tsip_transac_ict_Calling_2_Proceeding_X_1xx"), + // Calling -> (2xx) -> Accepted + TSK_FSM_ADD_ALWAYS(_fsm_state_Calling, _fsm_action_2xx, _fsm_state_Accepted, tsip_transac_ict_Calling_2_Accepted_X_2xx, "tsip_transac_ict_Calling_2_Accepted_X_2xx"), + + /*======================= + * === Proceeding === + */ + // Proceeding -> (1xx) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_ict_Proceeding_2_Proceeding_X_1xx, "tsip_transac_ict_Proceeding_2_Proceeding_X_1xx"), + // Proceeding -> (300-699) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_300_to_699, _fsm_state_Completed, tsip_transac_ict_Proceeding_2_Completed_X_300_to_699, "tsip_transac_ict_Proceeding_2_Completed_X_300_to_699"), + // Proceeding -> (2xx) -> Accepted + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_2xx, _fsm_state_Accepted, tsip_transac_ict_Proceeding_2_Accepted_X_2xx, "tsip_transac_ict_Proceeding_2_Accepted_X_2xx"), + + /*======================= + * === Completed === + */ + // Completed -> (300-699) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_300_to_699, _fsm_state_Completed, tsip_transac_ict_Completed_2_Completed_X_300_to_699, "tsip_transac_ict_Completed_2_Completed_X_300_to_699"), + // Completed -> (timerD) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerD, _fsm_state_Terminated, tsip_transac_ict_Completed_2_Terminated_X_timerD, "tsip_transac_ict_Completed_2_Terminated_X_timerD"), + + /*======================= + * === Accepted === + */ + // Accepted -> (2xx) -> Accepted + TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_2xx, _fsm_state_Accepted, tsip_transac_ict_Accepted_2_Accepted_X_2xx, "tsip_transac_ict_Accepted_2_Accepted_X_2xx"), + // Accepted -> (timerM) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_timerM, _fsm_state_Terminated, tsip_transac_ict_Accepted_2_Terminated_X_timerM, "tsip_transac_ict_Accepted_2_Terminated_X_timerM"), + + /*======================= + * === Any === + */ + // Any -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_ict_Any_2_Terminated_X_transportError, "tsip_transac_ict_Any_2_Terminated_X_transportError"), + // Any -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_ict_Any_2_Terminated_X_Error, "tsip_transac_ict_Any_2_Terminated_X_Error"), + // Any -> (cancel) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_ict_Any_2_Terminated_X_cancel, "tsip_transac_ict_Any_2_Terminated_X_cancel"), + + TSK_FSM_ADD_NULL()); + + + /* Set callback function to call when new messages arrive or errors happen in + the transport layer. + */ + TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_ict_event_callback); + + /* Timers */ + self->timerA.id = TSK_INVALID_TIMER_ID; + self->timerB.id = TSK_INVALID_TIMER_ID; + self->timerD.id = TSK_INVALID_TIMER_ID; + self->timerM.id = TSK_INVALID_TIMER_ID; + + self->timerA.timeout = TSIP_TIMER_GET(A); + self->timerB.timeout = TSIP_TIMER_GET(B); + self->timerM.timeout = TSIP_TIMER_GET(M); + + return 0; } tsip_transac_ict_t* tsip_transac_ict_create(int32_t cseq_value, const char* callid, tsip_transac_dst_t* dst) { - tsip_transac_ict_t* transac = tsk_object_new(tsip_transac_ict_def_t); - if(transac){ - // initialize base class - tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_ict, cseq_value, "INVITE", callid, dst, _fsm_state_Started, _fsm_state_Terminated); - - // init FSM - TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; - tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_ict_OnTerminated), (const void*)transac); - - // initialize ICT object - tsip_transac_ict_init(transac); - } - return transac; + tsip_transac_ict_t* transac = tsk_object_new(tsip_transac_ict_def_t); + if(transac) { + // initialize base class + tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_ict, cseq_value, "INVITE", callid, dst, _fsm_state_Started, _fsm_state_Terminated); + + // init FSM + TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; + tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_ict_OnTerminated), (const void*)transac); + + // initialize ICT object + tsip_transac_ict_init(transac); + } + return transac; } /** * Starts the client transaction. * - * @param [in,out] self The client transaction to start. - * @param [in,out] request The SIP/IMS INVITE request to send. + * @param [in,out] self The client transaction to start. + * @param [in,out] request The SIP/IMS INVITE request to send. * - * @return Zero if succeed and non-zero error code otherwise. + * @return Zero if succeed and non-zero error code otherwise. **/ int tsip_transac_ict_start(tsip_transac_ict_t *self, const tsip_request_t* request) { - int ret = -1; - if(self && request && !TSIP_TRANSAC(self)->running){ - /* Add branch to the new client transaction - * - Transac will use request branch if exit (e.g. when request received over websocket) - */ - if((request->firstVia && !tsk_strnullORempty(request->firstVia->branch))){ - tsk_strupdate(&TSIP_TRANSAC(self)->branch, (request->firstVia ? request->firstVia->branch : "doubango")); - } - else if((TSIP_TRANSAC(self)->branch = tsk_strdup(TSIP_TRANSAC_MAGIC_COOKIE))){ - tsk_istr_t branch; - tsk_strrandom(&branch); - tsk_strcat_2(&(TSIP_TRANSAC(self)->branch), "-%s", branch); - } - - TSIP_TRANSAC(self)->running = 1; - self->request = tsk_object_ref((void*)request); - - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send, tsk_null); - } - return ret; + int ret = -1; + if(self && request && !TSIP_TRANSAC(self)->running) { + /* Add branch to the new client transaction + * - Transac will use request branch if exit (e.g. when request received over websocket) + */ + if((request->firstVia && !tsk_strnullORempty(request->firstVia->branch))) { + tsk_strupdate(&TSIP_TRANSAC(self)->branch, (request->firstVia ? request->firstVia->branch : "doubango")); + } + else if((TSIP_TRANSAC(self)->branch = tsk_strdup(TSIP_TRANSAC_MAGIC_COOKIE))) { + tsk_istr_t branch; + tsk_strrandom(&branch); + tsk_strcat_2(&(TSIP_TRANSAC(self)->branch), "-%s", branch); + } + + TSIP_TRANSAC(self)->running = 1; + self->request = tsk_object_ref((void*)request); + + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send, tsk_null); + } + return ret; } @@ -382,367 +376,367 @@ int tsip_transac_ict_start(tsip_transac_ict_t *self, const tsip_request_t* reque */ int tsip_transac_ict_Started_2_Calling_X_send(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - //== Send the request - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(self->request)); - - // Now that the first request is sent using the best transport mean we know if it's reliable or not - if(TNET_SOCKET_TYPE_IS_VALID(self->request->dst_net_type)){ - TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(self->request->dst_net_type); - self->timerD.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(D); - } - - /* RFC 3261 - 17.1.1.2 Formal Description - If an unreliable transport is being used, the client transaction MUST - start timer A with a value of T1. - If a reliable transport is being used, the client transaction SHOULD - NOT start timer A (Timer A controls request retransmissions). For - any transport, the client transaction MUST start timer B with a value - of 64*T1 seconds (Timer B controls transaction timeouts). - */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_ICT_TIMER_SCHEDULE(A); - } - TRANSAC_ICT_TIMER_SCHEDULE(B); - - return 0; + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + //== Send the request + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(self->request)); + + // Now that the first request is sent using the best transport mean we know if it's reliable or not + if(TNET_SOCKET_TYPE_IS_VALID(self->request->dst_net_type)) { + TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(self->request->dst_net_type); + self->timerD.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(D); + } + + /* RFC 3261 - 17.1.1.2 Formal Description + If an unreliable transport is being used, the client transaction MUST + start timer A with a value of T1. + If a reliable transport is being used, the client transaction SHOULD + NOT start timer A (Timer A controls request retransmissions). For + any transport, the client transaction MUST start timer B with a value + of 64*T1 seconds (Timer B controls transaction timeouts). + */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_ICT_TIMER_SCHEDULE(A); + } + TRANSAC_ICT_TIMER_SCHEDULE(B); + + return 0; } /* Calling -> (timerA) -> Calling */ int tsip_transac_ict_Calling_2_Calling_X_timerA(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* RFC 3261 - 17.1.1.2 Formal Description - When timer A fires, the client transaction MUST retransmit the - request by passing it to the transport layer, and MUST reset the - timer with a value of 2*T1. The formal definition of retransmit + /* RFC 3261 - 17.1.1.2 Formal Description + When timer A fires, the client transaction MUST retransmit the + request by passing it to the transport layer, and MUST reset the + timer with a value of 2*T1. The formal definition of retransmit - within the context of the transaction layer is to take the message - previously sent to the transport layer and pass it to the transport - layer once more. + within the context of the transaction layer is to take the message + previously sent to the transport layer and pass it to the transport + layer once more. - When timer A fires 2*T1 seconds later, the request MUST be - retransmitted again (assuming the client transaction is still in this - state). This process MUST continue so that the request is - retransmitted with intervals that double after each transmission. - These retransmissions SHOULD only be done while the client - transaction is in the "calling" state. - */ + When timer A fires 2*T1 seconds later, the request MUST be + retransmitted again (assuming the client transaction is still in this + state). This process MUST continue so that the request is + retransmitted with intervals that double after each transmission. + These retransmissions SHOULD only be done while the client + transaction is in the "calling" state. + */ - //== Send the request - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->request); + //== Send the request + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->request); - self->timerA.timeout *= 2; /* Will not raise indefinitely ==> see timer B */ - TRANSAC_ICT_TIMER_SCHEDULE(A); + self->timerA.timeout *= 2; /* Will not raise indefinitely ==> see timer B */ + TRANSAC_ICT_TIMER_SCHEDULE(A); - return 0; + return 0; } /* Calling -> (timerB) -> Terminated */ int tsip_transac_ict_Calling_2_Terminated_X_timerB(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - /* RFC 3261 - 17.1.1.2 Formal Description - If the client transaction is still in the "Calling" state when timer - B fires, the client transaction SHOULD inform the TU that a timeout - has occurred. The client transaction MUST NOT generate an ACK. The - value of 64*T1 is equal to the amount of time required to send seven - requests in the case of an unreliable transport. - */ - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_timedout, tsk_null); - - return 0; + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + /* RFC 3261 - 17.1.1.2 Formal Description + If the client transaction is still in the "Calling" state when timer + B fires, the client transaction SHOULD inform the TU that a timeout + has occurred. The client transaction MUST NOT generate an ACK. The + value of 64*T1 is equal to the amount of time required to send seven + requests in the case of an unreliable transport. + */ + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_timedout, tsk_null); + + return 0; } /* Calling -> (300-699) -> Completed */ int tsip_transac_ict_Calling_2_Completed_X_300_to_699(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; - - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - When in either the "Calling" or "Proceeding" states, reception of - a response with status code from 300-699 MUST cause the client - transaction to transition to "Completed". The client transaction - MUST pass the received response up to the TU, and the client - transaction MUST generate an ACK request, even if the transport is - reliable (guidelines for constructing the ACK from the response - are given in Section 17.1.1.3) and then pass the ACK to the - transport layer for transmission. The ACK MUST be sent to the - same address, port, and transport to which the original request - was sent. - */ - /* Do not retransmit */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(A); - } - TRANSAC_TIMER_CANCEL(B); /* Now it's up to the UAS to update the FSM. */ - - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - The client transaction MUST start timer D when it enters the - "Completed" state for any reason, with a value of at least 32 - seconds for unreliable transports, and a value of zero seconds for - reliable transports. Timer D reflects the amount of time that the - server transaction can remain in the "Completed" state when - unreliable transports are used. - */ - TRANSAC_ICT_TIMER_SCHEDULE(D); /* timerD already have the right value (0 if reliable and non-zero otherwise) */ - - /* Send ACK */ - if((ret = tsip_transac_ict_send_ACK(self, response))){ - return ret; - } - - /* Pass the response to the dialog. */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; + + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + When in either the "Calling" or "Proceeding" states, reception of + a response with status code from 300-699 MUST cause the client + transaction to transition to "Completed". The client transaction + MUST pass the received response up to the TU, and the client + transaction MUST generate an ACK request, even if the transport is + reliable (guidelines for constructing the ACK from the response + are given in Section 17.1.1.3) and then pass the ACK to the + transport layer for transmission. The ACK MUST be sent to the + same address, port, and transport to which the original request + was sent. + */ + /* Do not retransmit */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(A); + } + TRANSAC_TIMER_CANCEL(B); /* Now it's up to the UAS to update the FSM. */ + + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + The client transaction MUST start timer D when it enters the + "Completed" state for any reason, with a value of at least 32 + seconds for unreliable transports, and a value of zero seconds for + reliable transports. Timer D reflects the amount of time that the + server transaction can remain in the "Completed" state when + unreliable transports are used. + */ + TRANSAC_ICT_TIMER_SCHEDULE(D); /* timerD already have the right value (0 if reliable and non-zero otherwise) */ + + /* Send ACK */ + if((ret = tsip_transac_ict_send_ACK(self, response))) { + return ret; + } + + /* Pass the response to the dialog. */ + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); } /* Calling -> (1xx) -> Proceeding */ int tsip_transac_ict_Calling_2_Proceeding_X_1xx(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - - /* RFC 3261 - 17.1.1.2 Formal Description - If the client transaction receives a provisional response while in - the "Calling" state, it transitions to the "Proceeding" state. In the - "Proceeding" state, the client transaction SHOULD NOT retransmit the - request any longer. Furthermore, the provisional response MUST be - passed to the TU. Any further provisional responses MUST be passed - up to the TU while in the "Proceeding" state. - */ - - /* Do not retransmit */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(A); - } - TRANSAC_TIMER_CANCEL(B); /* Now it's up to the UAS to update the FSM. */ - - /* Pass the provisional response to the dialog. */ - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); - - return 0; + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + + /* RFC 3261 - 17.1.1.2 Formal Description + If the client transaction receives a provisional response while in + the "Calling" state, it transitions to the "Proceeding" state. In the + "Proceeding" state, the client transaction SHOULD NOT retransmit the + request any longer. Furthermore, the provisional response MUST be + passed to the TU. Any further provisional responses MUST be passed + up to the TU while in the "Proceeding" state. + */ + + /* Do not retransmit */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(A); + } + TRANSAC_TIMER_CANCEL(B); /* Now it's up to the UAS to update the FSM. */ + + /* Pass the provisional response to the dialog. */ + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); + + return 0; } /* Calling -> (2xx) -> Accepted */ int tsip_transac_ict_Calling_2_Accepted_X_2xx(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - When a 2xx response is received while in either the "Calling" or - "Proceeding" states, the client transaction MUST transition to the - "Accepted" state, and Timer M MUST be started with a value of - 64*T1. The 2xx response MUST be passed up to the TU. The client - transaction MUST NOT generate an ACK to the 2xx response - its - handling is delegated to the TU. - */ - - /* Schedule timer M */ - TRANSAC_ICT_TIMER_SCHEDULE(M); - - /* Cancel timers A and B */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_ICT_TIMER_SCHEDULE(A); - } - TRANSAC_ICT_TIMER_SCHEDULE(B); - - /* pass the response to the TU (dialog) */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + When a 2xx response is received while in either the "Calling" or + "Proceeding" states, the client transaction MUST transition to the + "Accepted" state, and Timer M MUST be started with a value of + 64*T1. The 2xx response MUST be passed up to the TU. The client + transaction MUST NOT generate an ACK to the 2xx response - its + handling is delegated to the TU. + */ + + /* Schedule timer M */ + TRANSAC_ICT_TIMER_SCHEDULE(M); + + /* Cancel timers A and B */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_ICT_TIMER_SCHEDULE(A); + } + TRANSAC_ICT_TIMER_SCHEDULE(B); + + /* pass the response to the TU (dialog) */ + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); } /* Proceeding -> (1xx) -> Proceeding */ int tsip_transac_ict_Proceeding_2_Proceeding_X_1xx(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - /* pass the response to the TU (dialog) */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); + /* pass the response to the TU (dialog) */ + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); } /* Proceeding -> (300-699) -> Completed */ int tsip_transac_ict_Proceeding_2_Completed_X_300_to_699(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; - - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - When in either the "Calling" or "Proceeding" states, reception of - a response with status code from 300-699 MUST cause the client - transaction to transition to "Completed". The client transaction - MUST pass the received response up to the TU, and the client - transaction MUST generate an ACK request, even if the transport is - reliable (guidelines for constructing the ACK from the response - are given in Section 17.1.1.3) and then pass the ACK to the - transport layer for transmission. The ACK MUST be sent to the - same address, port, and transport to which the original request - was sent. - */ - /* Do not retransmit */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(A); - } - TRANSAC_TIMER_CANCEL(B); /* Now it's up to the UAS to update the FSM. */ - - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - The client transaction MUST start timer D when it enters the - "Completed" state for any reason, with a value of at least 32 - seconds for unreliable transports, and a value of zero seconds for - reliable transports. Timer D reflects the amount of time that the - server transaction can remain in the "Completed" state when - unreliable transports are used. - */ - TRANSAC_ICT_TIMER_SCHEDULE(D); /* timerD already have the right value (0 if reliable and non-zero otherwise) */ - - /* Send ACK */ - if((ret = tsip_transac_ict_send_ACK(self, response))){ - return ret; - } - - /* Pass the response to the dialog. */ - ret = tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); - - return ret; + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; + + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + When in either the "Calling" or "Proceeding" states, reception of + a response with status code from 300-699 MUST cause the client + transaction to transition to "Completed". The client transaction + MUST pass the received response up to the TU, and the client + transaction MUST generate an ACK request, even if the transport is + reliable (guidelines for constructing the ACK from the response + are given in Section 17.1.1.3) and then pass the ACK to the + transport layer for transmission. The ACK MUST be sent to the + same address, port, and transport to which the original request + was sent. + */ + /* Do not retransmit */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(A); + } + TRANSAC_TIMER_CANCEL(B); /* Now it's up to the UAS to update the FSM. */ + + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + The client transaction MUST start timer D when it enters the + "Completed" state for any reason, with a value of at least 32 + seconds for unreliable transports, and a value of zero seconds for + reliable transports. Timer D reflects the amount of time that the + server transaction can remain in the "Completed" state when + unreliable transports are used. + */ + TRANSAC_ICT_TIMER_SCHEDULE(D); /* timerD already have the right value (0 if reliable and non-zero otherwise) */ + + /* Send ACK */ + if((ret = tsip_transac_ict_send_ACK(self, response))) { + return ret; + } + + /* Pass the response to the dialog. */ + ret = tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); + + return ret; } /* Proceeding -> (2xx) -> Accepted */ int tsip_transac_ict_Proceeding_2_Accepted_X_2xx(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - When a 2xx response is received while in either the "Calling" or - "Proceeding" states, the client transaction MUST transition to the - "Accepted" state, and Timer M MUST be started with a value of - 64*T1. The 2xx response MUST be passed up to the TU. The client - transaction MUST NOT generate an ACK to the 2xx response - its - handling is delegated to the TU. - */ - - /* Schedule timer M */ - TRANSAC_ICT_TIMER_SCHEDULE(M); - - /* Cancel timers A and B */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_ICT_TIMER_SCHEDULE(A); - } - TRANSAC_ICT_TIMER_SCHEDULE(B); - - /* pass the response to the TU (dialog) */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + When a 2xx response is received while in either the "Calling" or + "Proceeding" states, the client transaction MUST transition to the + "Accepted" state, and Timer M MUST be started with a value of + 64*T1. The 2xx response MUST be passed up to the TU. The client + transaction MUST NOT generate an ACK to the 2xx response - its + handling is delegated to the TU. + */ + + /* Schedule timer M */ + TRANSAC_ICT_TIMER_SCHEDULE(M); + + /* Cancel timers A and B */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_ICT_TIMER_SCHEDULE(A); + } + TRANSAC_ICT_TIMER_SCHEDULE(B); + + /* pass the response to the TU (dialog) */ + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); } /* Completed -> (300-699) -> Completed */ int tsip_transac_ict_Completed_2_Completed_X_300_to_699(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - Any retransmissions of a response with status code 300-699 that - are received while in the "Completed" state MUST cause the ACK to - be re-passed to the transport layer for retransmission, but the - newly received response MUST NOT be passed up to the TU. - */ - - return tsip_transac_ict_send_ACK(self, response); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + Any retransmissions of a response with status code 300-699 that + are received while in the "Completed" state MUST cause the ACK to + be re-passed to the transport layer for retransmission, but the + newly received response MUST NOT be passed up to the TU. + */ + + return tsip_transac_ict_send_ACK(self, response); } /* Completed -> (timerD) -> Terminated */ int tsip_transac_ict_Completed_2_Terminated_X_timerD(va_list *app) { - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - If timer D fires while the client transaction is in the - "Completed" state, the client transaction MUST move to the - "Terminated" state. - */ - - /* Timers will be canceled by "tsip_transac_ict_OnTerminated" */ - return 0; + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + If timer D fires while the client transaction is in the + "Completed" state, the client transaction MUST move to the + "Terminated" state. + */ + + /* Timers will be canceled by "tsip_transac_ict_OnTerminated" */ + return 0; } /* Accepted -> (2xx) -> Accepted */ int tsip_transac_ict_Accepted_2_Accepted_X_2xx(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - - /* draft-sparks-sip-invfix-03 - 7.2. UAC Impacts - A 2xx response received while in the "Accepted" state MUST be passed to the TU and - the machine remains in the "Accepted" state. The client transaction - MUST NOT generate an ACK to any 2xx response on its own. The TU - responsible for the transaction will generate the ACK. - */ - - /* Pass the response to the TU. */ - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); - - return 0; + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + + /* draft-sparks-sip-invfix-03 - 7.2. UAC Impacts + A 2xx response received while in the "Accepted" state MUST be passed to the TU and + the machine remains in the "Accepted" state. The client transaction + MUST NOT generate an ACK to any 2xx response on its own. The TU + responsible for the transaction will generate the ACK. + */ + + /* Pass the response to the TU. */ + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, response); + + return 0; } /* Accepted -> (timerM) -> Terminated */ int tsip_transac_ict_Accepted_2_Terminated_X_timerM(va_list *app) { - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - If timer M fires while the client transaction is in the "Accepted" - state, the client transaction MUST move to the "Terminated" state. - */ - return 0; + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + If timer M fires while the client transaction is in the "Accepted" + state, the client transaction MUST move to the "Terminated" state. + */ + return 0; } /* Any -> (Transport Error) -> Terminated */ int tsip_transac_ict_Any_2_Terminated_X_transportError(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_ict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_ict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); } /* Any -> (Error) -> Terminated */ int tsip_transac_ict_Any_2_Terminated_X_Error(va_list *app) { - tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_ict_t *self = va_arg(*app, tsip_transac_ict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_ict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_ict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); } /* Any -> (cancel) -> Terminated */ int tsip_transac_ict_Any_2_Terminated_X_cancel(va_list *app) { - /* doubango-specific */ - return 0; + /* doubango-specific */ + return 0; } @@ -754,102 +748,101 @@ int tsip_transac_ict_Any_2_Terminated_X_cancel(va_list *app) */ int tsip_transac_ict_send_ACK(tsip_transac_ict_t *self, const tsip_response_t* response) { - int ret = -1; - tsip_request_t *request = tsk_null; - const tsk_list_item_t* item; - - if(!self || !self->request || !response){ - goto bail; - } - - // check lastINVITE - if( !self->request->firstVia || - !self->request->From || - !self->request->line.request.uri || - !self->request->Call_ID || - !self->request->CSeq) - { - ret = -2; - goto bail; - } - - // check response - if(!response->To){ - ret = -3; - goto bail; - } - - /* RFC 3261 - 17.1.1.3 Construction of the ACK Request - - The ACK request constructed by the client transaction MUST contain - values for the Call-ID, From, and Request-URI that are equal to the - values of those header fields in the request passed to the transport - by the client transaction (call this the "original request"). The To - header field in the ACK MUST equal the To header field in the - response being acknowledged, and therefore will usually differ from - the To header field in the original request by the addition of the - tag parameter. The ACK MUST contain a single Via header field, and - this MUST be equal to the top Via header field of the original - request. The CSeq header field in the ACK MUST contain the same - value for the sequence number as was present in the original request, - but the method parameter MUST be equal to "ACK". - - If the INVITE request whose response is being acknowledged had Route - header fields, those header fields MUST appear in the ACK. This is - to ensure that the ACK can be routed properly through any downstream - stateless proxies. - - Although any request MAY contain a body, a body in an ACK is special - since the request cannot be rejected if the body is not understood. - Therefore, placement of bodies in ACK for non-2xx is NOT RECOMMENDED, - but if done, the body types are restricted to any that appeared in - the INVITE, assuming that the response to the INVITE was not 415. If - it was, the body in the ACK MAY be any type listed in the Accept - header field in the 415. - */ - if((request = tsip_request_new("ACK", self->request->line.request.uri, self->request->From->uri, response->To->uri, self->request->Call_ID->value, self->request->CSeq->seq))){ - // Via - request->firstVia = tsk_object_ref((void*)self->request->firstVia); - // tags - if(request->From){ - request->From->tag = tsk_strdup(self->request->From->tag); - } - if(request->To){ - request->To->tag = tsk_strdup(response->To->tag); - } - // Routes - tsk_list_foreach(item, self->request->headers){ - const tsip_header_t* curr = item->data; - if(curr->type == tsip_htype_Route){ - tsip_message_add_header(request, curr); - } - } - - // SigComp - if(TSIP_TRANSAC_GET_SESSION(self) && TSIP_TRANSAC_GET_SESSION(self)->sigcomp_id){ - request->sigcomp_id = tsk_strdup(TSIP_TRANSAC_GET_SESSION(self)->sigcomp_id); - } - - // send the request - ret = tsip_transac_send(TSIP_TRANSAC(self), request->firstVia->branch, request); - TSK_OBJECT_SAFE_FREE(request); - } + int ret = -1; + tsip_request_t *request = tsk_null; + const tsk_list_item_t* item; + + if(!self || !self->request || !response) { + goto bail; + } + + // check lastINVITE + if( !self->request->firstVia || + !self->request->From || + !self->request->line.request.uri || + !self->request->Call_ID || + !self->request->CSeq) { + ret = -2; + goto bail; + } + + // check response + if(!response->To) { + ret = -3; + goto bail; + } + + /* RFC 3261 - 17.1.1.3 Construction of the ACK Request + + The ACK request constructed by the client transaction MUST contain + values for the Call-ID, From, and Request-URI that are equal to the + values of those header fields in the request passed to the transport + by the client transaction (call this the "original request"). The To + header field in the ACK MUST equal the To header field in the + response being acknowledged, and therefore will usually differ from + the To header field in the original request by the addition of the + tag parameter. The ACK MUST contain a single Via header field, and + this MUST be equal to the top Via header field of the original + request. The CSeq header field in the ACK MUST contain the same + value for the sequence number as was present in the original request, + but the method parameter MUST be equal to "ACK". + + If the INVITE request whose response is being acknowledged had Route + header fields, those header fields MUST appear in the ACK. This is + to ensure that the ACK can be routed properly through any downstream + stateless proxies. + + Although any request MAY contain a body, a body in an ACK is special + since the request cannot be rejected if the body is not understood. + Therefore, placement of bodies in ACK for non-2xx is NOT RECOMMENDED, + but if done, the body types are restricted to any that appeared in + the INVITE, assuming that the response to the INVITE was not 415. If + it was, the body in the ACK MAY be any type listed in the Accept + header field in the 415. + */ + if((request = tsip_request_new("ACK", self->request->line.request.uri, self->request->From->uri, response->To->uri, self->request->Call_ID->value, self->request->CSeq->seq))) { + // Via + request->firstVia = tsk_object_ref((void*)self->request->firstVia); + // tags + if(request->From) { + request->From->tag = tsk_strdup(self->request->From->tag); + } + if(request->To) { + request->To->tag = tsk_strdup(response->To->tag); + } + // Routes + tsk_list_foreach(item, self->request->headers) { + const tsip_header_t* curr = item->data; + if(curr->type == tsip_htype_Route) { + tsip_message_add_header(request, curr); + } + } + + // SigComp + if(TSIP_TRANSAC_GET_SESSION(self) && TSIP_TRANSAC_GET_SESSION(self)->sigcomp_id) { + request->sigcomp_id = tsk_strdup(TSIP_TRANSAC_GET_SESSION(self)->sigcomp_id); + } + + // send the request + ret = tsip_transac_send(TSIP_TRANSAC(self), request->firstVia->branch, request); + TSK_OBJECT_SAFE_FREE(request); + } bail: - return ret; + return ret; } /*== TERMINATED */ int tsip_transac_ict_OnTerminated(tsip_transac_ict_t *self) { - /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 - The client transaction MUST be destroyed the instant it enters the "Terminated" state. - */ - TSK_DEBUG_INFO("=== ICT terminated ==="); - - /* Remove (and destroy) the transaction from the layer. */ - return tsip_transac_remove(TSIP_TRANSAC(self)); + /* draft-sparks-sip-invfix-03 - 8.4. Pages 126 through 128 + The client transaction MUST be destroyed the instant it enters the "Terminated" state. + */ + TSK_DEBUG_INFO("=== ICT terminated ==="); + + /* Remove (and destroy) the transaction from the layer. */ + return tsip_transac_remove(TSIP_TRANSAC(self)); } @@ -883,45 +876,44 @@ int tsip_transac_ict_OnTerminated(tsip_transac_ict_t *self) // static tsk_object_t* tsip_transac_ict_ctor(tsk_object_t * self, va_list * app) { - tsip_transac_ict_t *transac = self; - if(transac){ - } - return self; + tsip_transac_ict_t *transac = self; + if(transac) { + } + return self; } static tsk_object_t* tsip_transac_ict_dtor(tsk_object_t * _self) -{ - tsip_transac_ict_t *self = _self; - if(self){ - /* Cancel timers */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(A); - } - TRANSAC_TIMER_CANCEL(B); - TRANSAC_TIMER_CANCEL(D); - TRANSAC_TIMER_CANCEL(M); - - TSIP_TRANSAC(self)->running = tsk_false; - TSK_OBJECT_SAFE_FREE(self->request); - - /* DeInitialize base class */ - tsip_transac_deinit(TSIP_TRANSAC(self)); - - TSK_DEBUG_INFO("*** ICT destroyed ***"); - } - return _self; +{ + tsip_transac_ict_t *self = _self; + if(self) { + /* Cancel timers */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(A); + } + TRANSAC_TIMER_CANCEL(B); + TRANSAC_TIMER_CANCEL(D); + TRANSAC_TIMER_CANCEL(M); + + TSIP_TRANSAC(self)->running = tsk_false; + TSK_OBJECT_SAFE_FREE(self->request); + + /* DeInitialize base class */ + tsip_transac_deinit(TSIP_TRANSAC(self)); + + TSK_DEBUG_INFO("*** ICT destroyed ***"); + } + return _self; } static int tsip_transac_ict_cmp(const tsk_object_t *t1, const tsk_object_t *t2) { - return tsip_transac_cmp(t1, t2); + return tsip_transac_cmp(t1, t2); } -static const tsk_object_def_t tsip_transac_ict_def_s = -{ - sizeof(tsip_transac_ict_t), - tsip_transac_ict_ctor, - tsip_transac_ict_dtor, - tsip_transac_ict_cmp, +static const tsk_object_def_t tsip_transac_ict_def_s = { + sizeof(tsip_transac_ict_t), + tsip_transac_ict_ctor, + tsip_transac_ict_dtor, + tsip_transac_ict_cmp, }; const tsk_object_def_t *tsip_transac_ict_def_t = &tsip_transac_ict_def_s; diff --git a/tinySIP/src/transactions/tsip_transac_ist.c b/tinySIP/src/transactions/tsip_transac_ist.c index f4f9233..fc03388 100755 --- a/tinySIP/src/transactions/tsip_transac_ist.c +++ b/tinySIP/src/transactions/tsip_transac_ist.c @@ -2,19 +2,19 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -120,241 +120,233 @@ static int tsip_transac_ist_Any_2_Terminated_X_cancel(va_list *app); /* doubango /* ======================== conds ======================== */ static tsk_bool_t _fsm_cond_is_resp2INVITE(tsip_transac_ist_t* self, tsip_message_t* message) { - return TSIP_RESPONSE_IS_TO_INVITE(message); + return TSIP_RESPONSE_IS_TO_INVITE(message); } /* ======================== actions ======================== */ -typedef enum _fsm_action_e -{ - _fsm_action_cancel = tsip_atype_cancel, - - _fsm_action_recv_INVITE = 0xFF, - _fsm_action_recv_ACK, - _fsm_action_send_1xx, - _fsm_action_send_2xx, - _fsm_action_send_300_to_699, - _fsm_action_send_non1xx, - _fsm_action_timerH, - _fsm_action_timerI, - _fsm_action_timerG, - _fsm_action_timerL, - _fsm_action_timerX, - _fsm_action_transporterror, - _fsm_action_error, +typedef enum _fsm_action_e { + _fsm_action_cancel = tsip_atype_cancel, + + _fsm_action_recv_INVITE = 0xFF, + _fsm_action_recv_ACK, + _fsm_action_send_1xx, + _fsm_action_send_2xx, + _fsm_action_send_300_to_699, + _fsm_action_send_non1xx, + _fsm_action_timerH, + _fsm_action_timerI, + _fsm_action_timerG, + _fsm_action_timerL, + _fsm_action_timerX, + _fsm_action_transporterror, + _fsm_action_error, } _fsm_action_t; /* ======================== states ======================== */ -typedef enum _fsm_state_e -{ - _fsm_state_Started, - _fsm_state_Proceeding, - _fsm_state_Completed, - _fsm_state_Accepted, - _fsm_state_Confirmed, - _fsm_state_Terminated +typedef enum _fsm_state_e { + _fsm_state_Started, + _fsm_state_Proceeding, + _fsm_state_Completed, + _fsm_state_Accepted, + _fsm_state_Confirmed, + _fsm_state_Terminated } _fsm_state_t; int tsip_transac_ist_event_callback(const tsip_transac_ist_t *self, tsip_transac_event_type_t type, const tsip_message_t *msg) { - int ret = -1; - - switch(type) - { - case tsip_transac_incoming_msg: /* From Transport Layer to Transaction Layer */ - { - if(msg && TSIP_MESSAGE_IS_REQUEST(msg)){ - if(TSIP_REQUEST_IS_INVITE(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_recv_INVITE, msg); - } - else if(TSIP_REQUEST_IS_ACK(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_recv_ACK, msg); - } - } - break; - } - - case tsip_transac_outgoing_msg: /* From TU to Transport Layer */ - { - if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)) - { - if(TSIP_RESPONSE_IS_1XX(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_1xx, msg); - } - else if(TSIP_RESPONSE_IS_2XX(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_2xx, msg); - } - else if(TSIP_RESPONSE_IS_3456(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_300_to_699, msg); - } - } - break; - } - - case tsip_transac_canceled: - case tsip_transac_terminated: - case tsip_transac_timedout: - break; - - case tsip_transac_error: - { - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); - break; - } - - case tsip_transac_transport_error: - { - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); - break; - } - } - - return ret; + int ret = -1; + + switch(type) { + case tsip_transac_incoming_msg: { /* From Transport Layer to Transaction Layer */ + if(msg && TSIP_MESSAGE_IS_REQUEST(msg)) { + if(TSIP_REQUEST_IS_INVITE(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_recv_INVITE, msg); + } + else if(TSIP_REQUEST_IS_ACK(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_recv_ACK, msg); + } + } + break; + } + + case tsip_transac_outgoing_msg: { /* From TU to Transport Layer */ + if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)) { + if(TSIP_RESPONSE_IS_1XX(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_1xx, msg); + } + else if(TSIP_RESPONSE_IS_2XX(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_2xx, msg); + } + else if(TSIP_RESPONSE_IS_3456(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_300_to_699, msg); + } + } + break; + } + + case tsip_transac_canceled: + case tsip_transac_terminated: + case tsip_transac_timedout: + break; + + case tsip_transac_error: { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); + break; + } + + case tsip_transac_transport_error: { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); + break; + } + } + + return ret; } int tsip_transac_ist_timer_callback(const tsip_transac_ist_t* self, tsk_timer_id_t timer_id) { - int ret = -1; - - if(self){ - if(timer_id == self->timerH.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerH, tsk_null); - } - else if(timer_id == self->timerI.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerI, tsk_null); - } - else if(timer_id == self->timerG.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerG, tsk_null); - } - else if(timer_id == self->timerL.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerL, tsk_null); - } - else if(timer_id == self->timerX.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerX, tsk_null); - } - } - - return ret; + int ret = -1; + + if(self) { + if(timer_id == self->timerH.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerH, tsk_null); + } + else if(timer_id == self->timerI.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerI, tsk_null); + } + else if(timer_id == self->timerG.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerG, tsk_null); + } + else if(timer_id == self->timerL.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerL, tsk_null); + } + else if(timer_id == self->timerX.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerX, tsk_null); + } + } + + return ret; } int tsip_transac_ist_init(tsip_transac_ist_t *self) { - /* Initialize the state machine. - */ - tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), - - /*======================= - * === Started === - */ - // Started -> (recv INVITE) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_recv_INVITE, _fsm_state_Proceeding, tsip_transac_ist_Started_2_Proceeding_X_INVITE, "tsip_transac_ist_Started_2_Proceeding_X_INVITE"), - // Started -> (Any other) -> Started - TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_ist_Started_2_Started_X_any"), - - /*======================= - * === Proceeding === - */ - // Proceeding -> (recv INVITE) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_recv_INVITE, _fsm_state_Proceeding, tsip_transac_ist_Proceeding_2_Proceeding_X_INVITE, "tsip_transac_ist_Proceeding_2_Proceeding_X_INVITE"), - // Proceeding -> (send 1xx) -> Proceeding - TSK_FSM_ADD(_fsm_state_Proceeding, _fsm_action_send_1xx, _fsm_cond_is_resp2INVITE, _fsm_state_Proceeding, tsip_transac_ist_Proceeding_2_Proceeding_X_1xx, "tsip_transac_ist_Proceeding_2_Proceeding_X_1xx"), - // Proceeding -> (send 300to699) -> Completed - TSK_FSM_ADD(_fsm_state_Proceeding, _fsm_action_send_300_to_699, _fsm_cond_is_resp2INVITE, _fsm_state_Completed, tsip_transac_ist_Proceeding_2_Completed_X_300_to_699, "tsip_transac_ist_Proceeding_2_Completed_X_300_to_699"), - // Proceeding -> (send 2xx) -> Accepted - TSK_FSM_ADD(_fsm_state_Proceeding, _fsm_action_send_2xx, _fsm_cond_is_resp2INVITE, _fsm_state_Accepted, tsip_transac_ist_Proceeding_2_Accepted_X_2xx, "tsip_transac_ist_Proceeding_2_Accepted_X_2xx"), - - /*======================= - * === Completed === - */ - // Completed -> (recv INVITE) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_recv_INVITE, _fsm_state_Completed, tsip_transac_ist_Completed_2_Completed_INVITE, "tsip_transac_ist_Completed_2_Completed_INVITE"), - // Completed -> (timer G) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerG, _fsm_state_Completed, tsip_transac_ist_Completed_2_Completed_timerG, "tsip_transac_ist_Completed_2_Completed_timerG"), - // Completed -> (timerH) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerH, _fsm_state_Terminated, tsip_transac_ist_Completed_2_Terminated_timerH, "tsip_transac_ist_Completed_2_Terminated_timerH"), - // Completed -> (recv ACK) -> Confirmed - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_recv_ACK, _fsm_state_Confirmed, tsip_transac_ist_Completed_2_Confirmed_ACK, "tsip_transac_ist_Completed_2_Confirmed_ACK"), - - /*======================= - * === Accepted === - */ - // Accepted -> (recv INVITE) -> Accepted - TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_recv_INVITE, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_INVITE, "tsip_transac_ist_Accepted_2_Accepted_INVITE"), - // Accepted -> (send 2xx) -> Accepted - TSK_FSM_ADD(_fsm_state_Accepted, _fsm_action_send_2xx, _fsm_cond_is_resp2INVITE, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_2xx, "tsip_transac_ist_Accepted_2_Accepted_2xx"), - // Accepted -> (timer X) -> Accepted - TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_timerX, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_timerX, "tsip_transac_ist_Accepted_2_Accepted_timerX"), - // Accepted -> (recv ACK) -> Accepted - TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_recv_ACK, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_iACK, "tsip_transac_ist_Accepted_2_Accepted_iACK"), - // Accepted -> (timerL) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_timerL, _fsm_state_Terminated, tsip_transac_ist_Accepted_2_Terminated_timerL, "tsip_transac_ist_Accepted_2_Terminated_timerL"), - - /*======================= - * === Confirmed === - */ - // Confirmed -> (timerI) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Confirmed, _fsm_action_timerI, _fsm_state_Terminated, tsip_transac_ist_Confirmed_2_Terminated_timerI, "tsip_transac_ist_Confirmed_2_Terminated_timerI"), - - - /*======================= - * === Any === - */ - // Any -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_ist_Any_2_Terminated_X_transportError, "tsip_transac_ist_Any_2_Terminated_X_transportError"), - // Any -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_ist_Any_2_Terminated_X_Error, "tsip_transac_ist_Any_2_Terminated_X_Error"), - // Any -> (cancel) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_ist_Any_2_Terminated_X_cancel, "tsip_transac_ist_Any_2_Terminated_X_cancel"), - - - TSK_FSM_ADD_NULL()); - - /* Set callback function to call when new messages arrive or errors happen at - the transport layer. - */ - TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_ist_event_callback); - - /* Set Timers - * RFC 3261 17.2.1: For unreliable transports, timer G is set to fire in T1 seconds, and is not set to fire for - reliable transports. - */ - self->timerH.timeout = TSIP_TIMER_GET(H); - self->timerG.timeout = TSIP_TIMER_GET(G); - self->timerL.timeout = TSIP_TIMER_GET(L); - self->timerX.timeout = TSIP_TIMER_GET(G); - - return 0; + /* Initialize the state machine. + */ + tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), + + /*======================= + * === Started === + */ + // Started -> (recv INVITE) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_recv_INVITE, _fsm_state_Proceeding, tsip_transac_ist_Started_2_Proceeding_X_INVITE, "tsip_transac_ist_Started_2_Proceeding_X_INVITE"), + // Started -> (Any other) -> Started + TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_ist_Started_2_Started_X_any"), + + /*======================= + * === Proceeding === + */ + // Proceeding -> (recv INVITE) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_recv_INVITE, _fsm_state_Proceeding, tsip_transac_ist_Proceeding_2_Proceeding_X_INVITE, "tsip_transac_ist_Proceeding_2_Proceeding_X_INVITE"), + // Proceeding -> (send 1xx) -> Proceeding + TSK_FSM_ADD(_fsm_state_Proceeding, _fsm_action_send_1xx, _fsm_cond_is_resp2INVITE, _fsm_state_Proceeding, tsip_transac_ist_Proceeding_2_Proceeding_X_1xx, "tsip_transac_ist_Proceeding_2_Proceeding_X_1xx"), + // Proceeding -> (send 300to699) -> Completed + TSK_FSM_ADD(_fsm_state_Proceeding, _fsm_action_send_300_to_699, _fsm_cond_is_resp2INVITE, _fsm_state_Completed, tsip_transac_ist_Proceeding_2_Completed_X_300_to_699, "tsip_transac_ist_Proceeding_2_Completed_X_300_to_699"), + // Proceeding -> (send 2xx) -> Accepted + TSK_FSM_ADD(_fsm_state_Proceeding, _fsm_action_send_2xx, _fsm_cond_is_resp2INVITE, _fsm_state_Accepted, tsip_transac_ist_Proceeding_2_Accepted_X_2xx, "tsip_transac_ist_Proceeding_2_Accepted_X_2xx"), + + /*======================= + * === Completed === + */ + // Completed -> (recv INVITE) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_recv_INVITE, _fsm_state_Completed, tsip_transac_ist_Completed_2_Completed_INVITE, "tsip_transac_ist_Completed_2_Completed_INVITE"), + // Completed -> (timer G) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerG, _fsm_state_Completed, tsip_transac_ist_Completed_2_Completed_timerG, "tsip_transac_ist_Completed_2_Completed_timerG"), + // Completed -> (timerH) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerH, _fsm_state_Terminated, tsip_transac_ist_Completed_2_Terminated_timerH, "tsip_transac_ist_Completed_2_Terminated_timerH"), + // Completed -> (recv ACK) -> Confirmed + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_recv_ACK, _fsm_state_Confirmed, tsip_transac_ist_Completed_2_Confirmed_ACK, "tsip_transac_ist_Completed_2_Confirmed_ACK"), + + /*======================= + * === Accepted === + */ + // Accepted -> (recv INVITE) -> Accepted + TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_recv_INVITE, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_INVITE, "tsip_transac_ist_Accepted_2_Accepted_INVITE"), + // Accepted -> (send 2xx) -> Accepted + TSK_FSM_ADD(_fsm_state_Accepted, _fsm_action_send_2xx, _fsm_cond_is_resp2INVITE, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_2xx, "tsip_transac_ist_Accepted_2_Accepted_2xx"), + // Accepted -> (timer X) -> Accepted + TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_timerX, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_timerX, "tsip_transac_ist_Accepted_2_Accepted_timerX"), + // Accepted -> (recv ACK) -> Accepted + TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_recv_ACK, _fsm_state_Accepted, tsip_transac_ist_Accepted_2_Accepted_iACK, "tsip_transac_ist_Accepted_2_Accepted_iACK"), + // Accepted -> (timerL) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_timerL, _fsm_state_Terminated, tsip_transac_ist_Accepted_2_Terminated_timerL, "tsip_transac_ist_Accepted_2_Terminated_timerL"), + + /*======================= + * === Confirmed === + */ + // Confirmed -> (timerI) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Confirmed, _fsm_action_timerI, _fsm_state_Terminated, tsip_transac_ist_Confirmed_2_Terminated_timerI, "tsip_transac_ist_Confirmed_2_Terminated_timerI"), + + + /*======================= + * === Any === + */ + // Any -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_ist_Any_2_Terminated_X_transportError, "tsip_transac_ist_Any_2_Terminated_X_transportError"), + // Any -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_ist_Any_2_Terminated_X_Error, "tsip_transac_ist_Any_2_Terminated_X_Error"), + // Any -> (cancel) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_ist_Any_2_Terminated_X_cancel, "tsip_transac_ist_Any_2_Terminated_X_cancel"), + + + TSK_FSM_ADD_NULL()); + + /* Set callback function to call when new messages arrive or errors happen at + the transport layer. + */ + TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_ist_event_callback); + + /* Set Timers + * RFC 3261 17.2.1: For unreliable transports, timer G is set to fire in T1 seconds, and is not set to fire for + reliable transports. + */ + self->timerH.timeout = TSIP_TIMER_GET(H); + self->timerG.timeout = TSIP_TIMER_GET(G); + self->timerL.timeout = TSIP_TIMER_GET(L); + self->timerX.timeout = TSIP_TIMER_GET(G); + + return 0; } tsip_transac_ist_t* tsip_transac_ist_create(int32_t cseq_value, const char* callid, tsip_transac_dst_t* dst) { - tsip_transac_ist_t* transac = tsk_object_new(tsip_transac_ist_def_t); - if(transac){ - // initialize base class - tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_ist, cseq_value, "INVITE", callid, dst, _fsm_state_Started, _fsm_state_Terminated); - - // init FSM - TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; - tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_ist_OnTerminated), (const void*)transac); - - // initialize IST object - tsip_transac_ist_init(transac); - } - return transac; + tsip_transac_ist_t* transac = tsk_object_new(tsip_transac_ist_def_t); + if(transac) { + // initialize base class + tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_ist, cseq_value, "INVITE", callid, dst, _fsm_state_Started, _fsm_state_Terminated); + + // init FSM + TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; + tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_ist_OnTerminated), (const void*)transac); + + // initialize IST object + tsip_transac_ist_init(transac); + } + return transac; } int tsip_transac_ist_start(tsip_transac_ist_t *self, const tsip_request_t* request) { - int ret = -1; - - if(self && !TSIP_TRANSAC(self)->running && request){ - TSIP_TRANSAC(self)->running = 1; - if((ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_recv_INVITE, request))){ - // - } - } - return ret; + int ret = -1; + + if(self && !TSIP_TRANSAC(self)->running && request) { + TSIP_TRANSAC(self)->running = 1; + if((ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_recv_INVITE, request))) { + // + } + } + return ret; } @@ -369,286 +361,286 @@ int tsip_transac_ist_start(tsip_transac_ist_t *self, const tsip_request_t* reque */ int tsip_transac_ist_Started_2_Proceeding_X_INVITE(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - const tsip_request_t *request = va_arg(*app, const tsip_request_t *); - int ret = -1; - - if(TNET_SOCKET_TYPE_IS_VALID(request->src_net_type)){ - TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(request->src_net_type); - } - - /* Set Timers */ - self->timerI.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(I); - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - When a server transaction is constructed for a request, it enters the - "Proceeding" state. The server transaction MUST generate a 100 - (Trying) response unless it knows that the TU will generate a - provisional or final response within 200 ms, in which case it MAY - generate a 100 (Trying) response. - - RFC 3262 - 3. UAS Behavior - A UAS MUST NOT attempt to send a 100 (Trying) response reliably. - */ - if(request){ - tsip_response_t* response; - if((response = tsip_response_new(100, "Trying (sent from the Transaction Layer)", request))){ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, response); - TRANSAC_IST_SET_LAST_RESPONSE(self, response); // Update last response - TSK_OBJECT_SAFE_FREE(response); - } - } - if(!ret){ /* Send "100 Trying" is OK ==> alert dialog for the incoming INVITE */ - ret = tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, request); - } - return ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + const tsip_request_t *request = va_arg(*app, const tsip_request_t *); + int ret = -1; + + if(TNET_SOCKET_TYPE_IS_VALID(request->src_net_type)) { + TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(request->src_net_type); + } + + /* Set Timers */ + self->timerI.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(I); + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + When a server transaction is constructed for a request, it enters the + "Proceeding" state. The server transaction MUST generate a 100 + (Trying) response unless it knows that the TU will generate a + provisional or final response within 200 ms, in which case it MAY + generate a 100 (Trying) response. + + RFC 3262 - 3. UAS Behavior + A UAS MUST NOT attempt to send a 100 (Trying) response reliably. + */ + if(request) { + tsip_response_t* response; + if((response = tsip_response_new(100, "Trying (sent from the Transaction Layer)", request))) { + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, response); + TRANSAC_IST_SET_LAST_RESPONSE(self, response); // Update last response + TSK_OBJECT_SAFE_FREE(response); + } + } + if(!ret) { /* Send "100 Trying" is OK ==> alert dialog for the incoming INVITE */ + ret = tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, request); + } + return ret; } /* Proceeding --> (recv INVITE) --> Proceeding */ int tsip_transac_ist_Proceeding_2_Proceeding_X_INVITE(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_request_t *request = va_arg(*app, const tsip_request_t *); - int ret = -1; - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - If a request retransmission is received while in the "Proceeding" state, the most - recent provisional response that was received from the TU MUST be - passed to the transport layer for retransmission. - */ - if(self->lastResponse){ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); - } - - return ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_request_t *request = va_arg(*app, const tsip_request_t *); + int ret = -1; + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + If a request retransmission is received while in the "Proceeding" state, the most + recent provisional response that was received from the TU MUST be + passed to the transport layer for retransmission. + */ + if(self->lastResponse) { + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); + } + + return ret; } /* Proceeding --> (send 1xx) --> Proceeding */ int tsip_transac_ist_Proceeding_2_Proceeding_X_1xx(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; - /* Send to the transport layer */ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + /* Send to the transport layer */ + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - /* Update last response */ - TRANSAC_IST_SET_LAST_RESPONSE(self, response); + /* Update last response */ + TRANSAC_IST_SET_LAST_RESPONSE(self, response); - return ret; + return ret; } /* Proceeding --> (send 300-699) --> Completed */ int tsip_transac_ist_Proceeding_2_Completed_X_300_to_699(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; - - /* RFC 3264 17.2.1 INVITE Server Transaction - While in the "Proceeding" state, if the TU passes a response with - status code from 300 to 699 to the server transaction, the response - MUST be passed to the transport layer for transmission, and the state - machine MUST enter the "Completed" state. For unreliable transports, timer G is set to fire in T1 seconds, - and is not set to fire for reliable transports. - */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_IST_TIMER_SCHEDULE(G); - } - - /* Send to the transport layer */ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - - /* Update last response */ - TRANSAC_IST_SET_LAST_RESPONSE(self, response); - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - When the "Completed" state is entered, timer H MUST be set to fire in - 64*T1 seconds for all transports. - */ - TRANSAC_IST_TIMER_SCHEDULE(H); - - return ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; + + /* RFC 3264 17.2.1 INVITE Server Transaction + While in the "Proceeding" state, if the TU passes a response with + status code from 300 to 699 to the server transaction, the response + MUST be passed to the transport layer for transmission, and the state + machine MUST enter the "Completed" state. For unreliable transports, timer G is set to fire in T1 seconds, + and is not set to fire for reliable transports. + */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_IST_TIMER_SCHEDULE(G); + } + + /* Send to the transport layer */ + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + + /* Update last response */ + TRANSAC_IST_SET_LAST_RESPONSE(self, response); + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + When the "Completed" state is entered, timer H MUST be set to fire in + 64*T1 seconds for all transports. + */ + TRANSAC_IST_TIMER_SCHEDULE(H); + + return ret; } /* Proceeding --> (send 2xx) --> Accepted */ int tsip_transac_ist_Proceeding_2_Accepted_X_2xx(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret = -1; - - /* draft-sparks-sip-invfix-03 - 8.5. Pages 134 to 135 - If, while in the "Proceeding" state, the TU passes a 2xx response - to the server transaction, the server transaction MUST pass this - response to the transport layer for transmission. It is not - retransmitted by the server transaction; retransmissions of 2xx - responses are handled by the TU. The server transaction MUST then - transition to the "Accepted" state. - */ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - - /* Update last response */ - TRANSAC_IST_SET_LAST_RESPONSE(self, response); - - /* RFC 3261 - 13.3.1.4 The INVITE is Accepted - Since 2xx is retransmitted end-to-end, there may be hops between - UAS and UAC that are UDP. To ensure reliable delivery across - these hops, the response is retransmitted periodically even if the - transport at the UAS is reliable. - */ - TRANSAC_IST_TIMER_SCHEDULE(X); - self->timerX.timeout <<= 1; - - /* draft-sparks-sip-invfix-03 - 8.7. Page 137 - When the INVITE server transaction enters the "Accepted" state, - Timer L MUST be set to fire in 64*T1 for all transports. This - value matches both Timer B in the next upstream client state - machine (the amount of time the previous hop will wait for a - response when no provisionals have been sent) and the amount of - time this (or any downstream) UAS core might be retransmitting the - 2xx while waiting for an ACK. - */ - TRANSAC_IST_TIMER_SCHEDULE(L); - - return ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret = -1; + + /* draft-sparks-sip-invfix-03 - 8.5. Pages 134 to 135 + If, while in the "Proceeding" state, the TU passes a 2xx response + to the server transaction, the server transaction MUST pass this + response to the transport layer for transmission. It is not + retransmitted by the server transaction; retransmissions of 2xx + responses are handled by the TU. The server transaction MUST then + transition to the "Accepted" state. + */ + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + + /* Update last response */ + TRANSAC_IST_SET_LAST_RESPONSE(self, response); + + /* RFC 3261 - 13.3.1.4 The INVITE is Accepted + Since 2xx is retransmitted end-to-end, there may be hops between + UAS and UAC that are UDP. To ensure reliable delivery across + these hops, the response is retransmitted periodically even if the + transport at the UAS is reliable. + */ + TRANSAC_IST_TIMER_SCHEDULE(X); + self->timerX.timeout <<= 1; + + /* draft-sparks-sip-invfix-03 - 8.7. Page 137 + When the INVITE server transaction enters the "Accepted" state, + Timer L MUST be set to fire in 64*T1 for all transports. This + value matches both Timer B in the next upstream client state + machine (the amount of time the previous hop will wait for a + response when no provisionals have been sent) and the amount of + time this (or any downstream) UAS core might be retransmitting the + 2xx while waiting for an ACK. + */ + TRANSAC_IST_TIMER_SCHEDULE(L); + + return ret; } /* Completed --> (recv INVITE) --> Completed */ int tsip_transac_ist_Completed_2_Completed_INVITE(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - int ret = -1; - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - Furthermore, while in the "Completed" state, if a request retransmission is - received, the server SHOULD pass the response to the transport for - retransmission. - */ - if(self->lastResponse){ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); - } - - return ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + int ret = -1; + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + Furthermore, while in the "Completed" state, if a request retransmission is + received, the server SHOULD pass the response to the transport for + retransmission. + */ + if(self->lastResponse) { + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); + } + + return ret; } /* Completed --> (timerG) --> Completed */ int tsip_transac_ist_Completed_2_Completed_timerG(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - int ret = -1; - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - If timer G fires, the response is passed to the transport layer once - more for retransmission, and timer G is set to fire in MIN(2*T1, T2) seconds. - From then on, when timer G fires, the response is passed to the transport again for - transmission, and timer G is reset with a value that doubles, unless - that value exceeds T2, in which case it is reset with the value of T2. - */ - if(self->lastResponse){ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); - } - self->timerG.timeout = TSK_MIN(self->timerG.timeout*2, TSIP_TIMER_GET(T2)); - TRANSAC_IST_TIMER_SCHEDULE(G); - - return ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + int ret = -1; + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + If timer G fires, the response is passed to the transport layer once + more for retransmission, and timer G is set to fire in MIN(2*T1, T2) seconds. + From then on, when timer G fires, the response is passed to the transport again for + transmission, and timer G is reset with a value that doubles, unless + that value exceeds T2, in which case it is reset with the value of T2. + */ + if(self->lastResponse) { + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); + } + self->timerG.timeout = TSK_MIN(self->timerG.timeout*2, TSIP_TIMER_GET(T2)); + TRANSAC_IST_TIMER_SCHEDULE(G); + + return ret; } /* Completed --> (timerH) --> Terminated */ int tsip_transac_ist_Completed_2_Terminated_timerH(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - If timer H fires while in the "Completed" state, it implies that the - ACK was never received. In this case, the server transaction MUST - transition to the "Terminated" state, and MUST indicate to the TU - that a transaction failure has occurred. - */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + If timer H fires while in the "Completed" state, it implies that the + ACK was never received. In this case, the server transaction MUST + transition to the "Terminated" state, and MUST indicate to the TU + that a transaction failure has occurred. + */ + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); } /* Completed --> (recv ACK) --> Confirmed */ int tsip_transac_ist_Completed_2_Confirmed_ACK(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - If an ACK is received while the server transaction is in the - "Completed" state, the server transaction MUST transition to the - "Confirmed" state. As Timer G is ignored in this state, any - retransmissions of the response will cease - */ - TRANSAC_TIMER_CANCEL(G);/* To avoid warnings from FSM manager. */ - - /* RFC 3261 - 17.2.1 INVITE Server Transaction - The purpose of the "Confirmed" state is to absorb any additional ACK - messages that arrive, triggered from retransmissions of the final - response. When this state is entered, timer I is set to fire in T4 - seconds for unreliable transports, and zero seconds for reliable - transports. - */ - TRANSAC_IST_TIMER_SCHEDULE(I); /* Has the right value (zero of reliable and ...) */ - - - return 0; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + If an ACK is received while the server transaction is in the + "Completed" state, the server transaction MUST transition to the + "Confirmed" state. As Timer G is ignored in this state, any + retransmissions of the response will cease + */ + TRANSAC_TIMER_CANCEL(G);/* To avoid warnings from FSM manager. */ + + /* RFC 3261 - 17.2.1 INVITE Server Transaction + The purpose of the "Confirmed" state is to absorb any additional ACK + messages that arrive, triggered from retransmissions of the final + response. When this state is entered, timer I is set to fire in T4 + seconds for unreliable transports, and zero seconds for reliable + transports. + */ + TRANSAC_IST_TIMER_SCHEDULE(I); /* Has the right value (zero of reliable and ...) */ + + + return 0; } /* Accepted --> (recv INVITE) --> Accepted */ int tsip_transac_ist_Accepted_2_Accepted_INVITE(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - - /* draft-sparks-sip-invfix-03 - 8.7. Page 137 - The purpose of the "Accepted" state is to absorb retransmissions - of an accepted INVITE request. Any such retransmissions are - absorbed entirely within the server transaction. They are not - passed up to the TU since any downstream UAS cores that accepted - the request have taken responsibility for reliability and will - already retransmit their 2xx responses if neccessary. - */ - - /* Do not pass to the TU (see above) - VERY IMPORTANT: INVITE dialog is responsible for reliability of the 2xx response. - */ - if(self->lastResponse){ - return tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); - } - return 0; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + + /* draft-sparks-sip-invfix-03 - 8.7. Page 137 + The purpose of the "Accepted" state is to absorb retransmissions + of an accepted INVITE request. Any such retransmissions are + absorbed entirely within the server transaction. They are not + passed up to the TU since any downstream UAS cores that accepted + the request have taken responsibility for reliability and will + already retransmit their 2xx responses if neccessary. + */ + + /* Do not pass to the TU (see above) + VERY IMPORTANT: INVITE dialog is responsible for reliability of the 2xx response. + */ + if(self->lastResponse) { + return tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); + } + return 0; } /* Accepted --> (send 2xx) --> Accepted */ int tsip_transac_ist_Accepted_2_Accepted_2xx(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; - /* draft-sparks-sip-invfix-03 - 8.7. Page 137 - While in the "Accepted" state, if the TU passes a 2xx response, - the server transaction MUST pass the response to the transport - layer for transmission. - */ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - - /* Update last response */ - TRANSAC_IST_SET_LAST_RESPONSE(self, response); - - return ret; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; + /* draft-sparks-sip-invfix-03 - 8.7. Page 137 + While in the "Accepted" state, if the TU passes a 2xx response, + the server transaction MUST pass the response to the transport + layer for transmission. + */ + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + + /* Update last response */ + TRANSAC_IST_SET_LAST_RESPONSE(self, response); + + return ret; } /* Accepted --> (timer X) --> Accepted @@ -656,14 +648,14 @@ int tsip_transac_ist_Accepted_2_Accepted_2xx(va_list *app) */ static int tsip_transac_ist_Accepted_2_Accepted_timerX(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - if(self->lastResponse){ - int ret; - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); - self->timerX.timeout <<= 1; - TRANSAC_IST_TIMER_SCHEDULE(X); - } - return 0; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + if(self->lastResponse) { + int ret; + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); + self->timerX.timeout <<= 1; + TRANSAC_IST_TIMER_SCHEDULE(X); + } + return 0; } /* Accepted --> (Recv ACK) --> Accepted @@ -671,77 +663,77 @@ static int tsip_transac_ist_Accepted_2_Accepted_timerX(va_list *app) */ int tsip_transac_ist_Accepted_2_Accepted_iACK(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - const tsip_request_t *request = va_arg(*app, const tsip_request_t *); - self->acked = tsk_true; - TRANSAC_TIMER_CANCEL(X); - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, request); + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + const tsip_request_t *request = va_arg(*app, const tsip_request_t *); + self->acked = tsk_true; + TRANSAC_TIMER_CANCEL(X); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, request); } /* Accepted --> (timerL) --> Terminated */ static int tsip_transac_ist_Accepted_2_Terminated_timerL(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - /* draft-sparks-sip-invfix-03 - 8.7. Page 137 - If Timer L fires while the INVITE server transaction is in the "Accepted" state, the transaction - MUST transition to the "Terminated" state. Once the transaction is in the "Terminated" state, it MUST be - destroyed immediately. - */ - if(!self->acked){ - TSK_DEBUG_ERROR("ACK not received"); - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); - } - return 0; + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + /* draft-sparks-sip-invfix-03 - 8.7. Page 137 + If Timer L fires while the INVITE server transaction is in the "Accepted" state, the transaction + MUST transition to the "Terminated" state. Once the transaction is in the "Terminated" state, it MUST be + destroyed immediately. + */ + if(!self->acked) { + TSK_DEBUG_ERROR("ACK not received"); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); + } + return 0; } /* Confirmed --> (timerI) --> Terminated */ static int tsip_transac_ist_Confirmed_2_Terminated_timerI(va_list *app) { - /* RFC 3261 - 17.2.1 INVITE Server Transaction - Once timer I fires, the server MUST transition to the - "Terminated" state. - - Once the transaction is in the "Terminated" state, it MUST be - destroyed immediately. As with client transactions, this is needed - to ensure reliability of the 2xx responses to INVITE. - */ - return 0; + /* RFC 3261 - 17.2.1 INVITE Server Transaction + Once timer I fires, the server MUST transition to the + "Terminated" state. + + Once the transaction is in the "Terminated" state, it MUST be + destroyed immediately. As with client transactions, this is needed + to ensure reliability of the 2xx responses to INVITE. + */ + return 0; } /* Any -> (Transport Error) -> Terminated */ static int tsip_transac_ist_Any_2_Terminated_X_transportError(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); } /* Any -> (Error) -> Terminated */ static int tsip_transac_ist_Any_2_Terminated_X_Error(va_list *app) { - tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_ist_t *self = va_arg(*app, tsip_transac_ist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); } /* Any -> (cancel) -> Terminated */ static int tsip_transac_ist_Any_2_Terminated_X_cancel(va_list *app) { - /* doubango-specific */ - return 0; + /* doubango-specific */ + return 0; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -754,10 +746,10 @@ static int tsip_transac_ist_Any_2_Terminated_X_cancel(va_list *app) */ static int tsip_transac_ist_OnTerminated(tsip_transac_ist_t *self) { - TSK_DEBUG_INFO("=== IST terminated ==="); - - /* Remove (and destroy) the transaction from the layer. */ - return tsip_transac_remove(TSIP_TRANSAC(self)); + TSK_DEBUG_INFO("=== IST terminated ==="); + + /* Remove (and destroy) the transaction from the layer. */ + return tsip_transac_remove(TSIP_TRANSAC(self)); } @@ -777,47 +769,45 @@ static int tsip_transac_ist_OnTerminated(tsip_transac_ist_t *self) // static tsk_object_t* tsip_transac_ist_ctor(tsk_object_t * self, va_list * app) { - tsip_transac_ist_t *transac = self; - if(transac){ - } - return self; + tsip_transac_ist_t *transac = self; + if(transac) { + } + return self; } static tsk_object_t* tsip_transac_ist_dtor(tsk_object_t * _self) -{ - tsip_transac_ist_t *self = _self; - if(self) - { - /* Cancel timers */ - TRANSAC_TIMER_CANCEL(H); - TRANSAC_TIMER_CANCEL(I); - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(G); - } - TRANSAC_TIMER_CANCEL(L); - TRANSAC_TIMER_CANCEL(X); - - TSIP_TRANSAC(self)->running = tsk_false; - TSK_OBJECT_SAFE_FREE(self->lastResponse); - - /* DeInitialize base class */ - tsip_transac_deinit(TSIP_TRANSAC(self)); - - TSK_DEBUG_INFO("*** IST destroyed ***"); - } - return _self; +{ + tsip_transac_ist_t *self = _self; + if(self) { + /* Cancel timers */ + TRANSAC_TIMER_CANCEL(H); + TRANSAC_TIMER_CANCEL(I); + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(G); + } + TRANSAC_TIMER_CANCEL(L); + TRANSAC_TIMER_CANCEL(X); + + TSIP_TRANSAC(self)->running = tsk_false; + TSK_OBJECT_SAFE_FREE(self->lastResponse); + + /* DeInitialize base class */ + tsip_transac_deinit(TSIP_TRANSAC(self)); + + TSK_DEBUG_INFO("*** IST destroyed ***"); + } + return _self; } static int tsip_transac_ist_cmp(const tsk_object_t *t1, const tsk_object_t *t2) { - return tsip_transac_cmp(t1, t2); + return tsip_transac_cmp(t1, t2); } -static const tsk_object_def_t tsip_transac_ist_def_s = -{ - sizeof(tsip_transac_ist_t), - tsip_transac_ist_ctor, - tsip_transac_ist_dtor, - tsip_transac_ist_cmp, +static const tsk_object_def_t tsip_transac_ist_def_s = { + sizeof(tsip_transac_ist_t), + tsip_transac_ist_ctor, + tsip_transac_ist_dtor, + tsip_transac_ist_cmp, }; const tsk_object_def_t *tsip_transac_ist_def_t = &tsip_transac_ist_def_s; diff --git a/tinySIP/src/transactions/tsip_transac_layer.c b/tinySIP/src/transactions/tsip_transac_layer.c index b3cf167..767dfb6 100755 --- a/tinySIP/src/transactions/tsip_transac_layer.c +++ b/tinySIP/src/transactions/tsip_transac_layer.c @@ -2,19 +2,19 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -39,220 +39,215 @@ tsip_transac_layer_t* tsip_transac_layer_create(tsip_stack_t* stack) { - return tsk_object_new(tsip_transac_layer_def_t, stack); + return tsk_object_new(tsip_transac_layer_def_t, stack); } tsip_transac_t* tsip_transac_layer_new(const tsip_transac_layer_t *self, tsk_bool_t isCT, const tsip_message_t* msg, tsip_transac_dst_t* dst) { - tsip_transac_t *ret = tsk_null; - tsip_transac_t *transac = tsk_null; - - tsk_safeobj_lock(self); - - if(self && msg) - { - if(TSIP_MESSAGE_IS_REQUEST(msg)) - { - if(isCT) /* Client transaction */ - { - if(TSIP_REQUEST_IS_INVITE(msg)){ - // INVITE Client transaction (ICT) - transac = (tsip_transac_t *)tsip_transac_ict_create(msg->CSeq->seq, msg->Call_ID->value, dst); - } - else{ - // NON-INVITE Client transaction (NICT) - transac = (tsip_transac_t *)tsip_transac_nict_create(msg->CSeq->seq, msg->CSeq->method, msg->Call_ID->value, dst); - } - } - else /* Server transaction */ - { - if(TSIP_REQUEST_IS_INVITE(msg)){ - // INVITE Server transaction (IST) - transac = (tsip_transac_t *)tsip_transac_ist_create(msg->CSeq->seq, msg->Call_ID->value, dst); - } - else{ - // NON-INVITE Server transaction (NIST) - transac = (tsip_transac_t *)tsip_transac_nist_create(msg->CSeq->seq, msg->CSeq->method, msg->Call_ID->value, dst); - } - - if(transac){ /* Copy branch from the message */ - transac->branch = tsk_strdup(msg->firstVia->branch); - } - } - - /* Add new transaction */ - if(transac){ - ret = tsk_object_ref(transac); - tsk_list_push_back_data(self->transactions, (void**)&transac); - } - } - } - - tsk_safeobj_unlock(self); - - return ret; + tsip_transac_t *ret = tsk_null; + tsip_transac_t *transac = tsk_null; + + tsk_safeobj_lock(self); + + if(self && msg) { + if(TSIP_MESSAGE_IS_REQUEST(msg)) { + if(isCT) { /* Client transaction */ + if(TSIP_REQUEST_IS_INVITE(msg)) { + // INVITE Client transaction (ICT) + transac = (tsip_transac_t *)tsip_transac_ict_create(msg->CSeq->seq, msg->Call_ID->value, dst); + } + else { + // NON-INVITE Client transaction (NICT) + transac = (tsip_transac_t *)tsip_transac_nict_create(msg->CSeq->seq, msg->CSeq->method, msg->Call_ID->value, dst); + } + } + else { /* Server transaction */ + if(TSIP_REQUEST_IS_INVITE(msg)) { + // INVITE Server transaction (IST) + transac = (tsip_transac_t *)tsip_transac_ist_create(msg->CSeq->seq, msg->Call_ID->value, dst); + } + else { + // NON-INVITE Server transaction (NIST) + transac = (tsip_transac_t *)tsip_transac_nist_create(msg->CSeq->seq, msg->CSeq->method, msg->Call_ID->value, dst); + } + + if(transac) { /* Copy branch from the message */ + transac->branch = tsk_strdup(msg->firstVia->branch); + } + } + + /* Add new transaction */ + if(transac) { + ret = tsk_object_ref(transac); + tsk_list_push_back_data(self->transactions, (void**)&transac); + } + } + } + + tsk_safeobj_unlock(self); + + return ret; } int tsip_transac_layer_remove(tsip_transac_layer_t *self, const tsip_transac_t *transac) { - if(transac && self){ - tsk_safeobj_lock(self); - tsk_list_remove_item_by_data(self->transactions, transac); - tsk_safeobj_unlock(self); + if(transac && self) { + tsk_safeobj_lock(self); + tsk_list_remove_item_by_data(self->transactions, transac); + tsk_safeobj_unlock(self); - return 0; - } + return 0; + } - return -1; + return -1; } /* cancel all transactions related to this dialog */ int tsip_transac_layer_cancel_by_dialog(tsip_transac_layer_t *self, const struct tsip_dialog_s* dialog) { - tsk_list_item_t *item; - int ret = 0; /* Perhaps there is zero transaction */ + tsk_list_item_t *item; + int ret = 0; /* Perhaps there is zero transaction */ - if(!self || !dialog){ - TSK_DEBUG_WARN("Invalid parameter."); - return -1; - } - - tsk_safeobj_lock(self); + if(!self || !dialog) { + TSK_DEBUG_WARN("Invalid parameter."); + return -1; + } + + tsk_safeobj_lock(self); again: - tsk_list_foreach(item, self->transactions){ - if(tsk_object_cmp(dialog, TSIP_TRANSAC_GET_DIALOG(item->data)) == 0){ - if((ret = tsip_transac_fsm_act(TSIP_TRANSAC(item->data), tsip_atype_cancel, tsk_null))){ /* will call tsip_transac_layer_remove() if succeed */ - /* break; */ - } - else{ - /* we cannot continue because an item has been removed from the list while we are looping through */ - goto again; - } - } - } - tsk_safeobj_unlock(self); - - return 0; + tsk_list_foreach(item, self->transactions) { + if(tsk_object_cmp(dialog, TSIP_TRANSAC_GET_DIALOG(item->data)) == 0) { + if((ret = tsip_transac_fsm_act(TSIP_TRANSAC(item->data), tsip_atype_cancel, tsk_null))) { /* will call tsip_transac_layer_remove() if succeed */ + /* break; */ + } + else { + /* we cannot continue because an item has been removed from the list while we are looping through */ + goto again; + } + } + } + tsk_safeobj_unlock(self); + + return 0; } tsip_transac_t* tsip_transac_layer_find_client(const tsip_transac_layer_t *self, const tsip_response_t* response) { - /* - RFC 3261 - 17.1.3 Matching Responses to Client Transactions - - When the transport layer in the client receives a response, it has to - determine which client transaction will handle the response, so that - the processing of Sections 17.1.1 and 17.1.2 can take place. The - branch parameter in the top Via header field is used for this - purpose. A response matches a client transaction under two - conditions: - - 1. If the response has the same value of the branch parameter in - the top Via header field as the branch parameter in the top - Via header field of the request that created the transaction. - - 2. If the method parameter in the CSeq header field matches the - method of the request that created the transaction. The - method is needed since a CANCEL request constitutes a - different transaction, but shares the same value of the branch - parameter. - */ - tsip_transac_t *ret = tsk_null; - tsip_transac_t *transac; - tsk_list_item_t *item; - - /* Check first Via/CSeq validity. - */ - if(!response->firstVia || !response->CSeq){ - return tsk_null; - } - - tsk_safeobj_lock(self); - - tsk_list_foreach(item, self->transactions){ - transac = item->data; - if( tsk_strequals(transac->branch, response->firstVia->branch) - && tsk_strequals(transac->cseq_method, response->CSeq->method) - ) - { - ret = tsk_object_ref(transac); - break; - } - } - - tsk_safeobj_unlock(self); - - return ret; + /* + RFC 3261 - 17.1.3 Matching Responses to Client Transactions + + When the transport layer in the client receives a response, it has to + determine which client transaction will handle the response, so that + the processing of Sections 17.1.1 and 17.1.2 can take place. The + branch parameter in the top Via header field is used for this + purpose. A response matches a client transaction under two + conditions: + + 1. If the response has the same value of the branch parameter in + the top Via header field as the branch parameter in the top + Via header field of the request that created the transaction. + + 2. If the method parameter in the CSeq header field matches the + method of the request that created the transaction. The + method is needed since a CANCEL request constitutes a + different transaction, but shares the same value of the branch + parameter. + */ + tsip_transac_t *ret = tsk_null; + tsip_transac_t *transac; + tsk_list_item_t *item; + + /* Check first Via/CSeq validity. + */ + if(!response->firstVia || !response->CSeq) { + return tsk_null; + } + + tsk_safeobj_lock(self); + + tsk_list_foreach(item, self->transactions) { + transac = item->data; + if( tsk_strequals(transac->branch, response->firstVia->branch) + && tsk_strequals(transac->cseq_method, response->CSeq->method) + ) { + ret = tsk_object_ref(transac); + break; + } + } + + tsk_safeobj_unlock(self); + + return ret; } tsip_transac_t* tsip_transac_layer_find_server(const tsip_transac_layer_t *self, const tsip_message_t* message) { - /* - RFC 3261 - 17.2.3 Matching Requests to Server Transactions - - When a request is received from the network by the server, it has to - be matched to an existing transaction. This is accomplished in the - following manner. - - The branch parameter in the topmost Via header field of the request - is examined. If it is present and begins with the magic cookie - "z9hG4bK", the request was generated by a client transaction - compliant to this specification. Therefore, the branch parameter - will be unique across all transactions sent by that client. The - request matches a transaction if: - - 1. the branch parameter in the request is equal to the one in the - top Via header field of the request that created the - transaction, and - - 2. the sent-by value in the top Via of the request is equal to the - one in the request that created the transaction, and - - 3. the method of the request matches the one that created the - transaction, except for ACK, where the method of the request - that created the transaction is INVITE. - */ - tsip_transac_t *ret = tsk_null; - tsip_transac_t *transac; - tsk_list_item_t *item; - //const char* sent_by; - - /* Check first Via/CSeq validity */ - if(!message->firstVia || !message->CSeq){ - return tsk_null; - } - - tsk_safeobj_lock(self); - - tsk_list_foreach(item, self->transactions){ - transac = item->data; - if(TSIP_REQUEST_IS_ACK(message) && tsk_strequals(transac->callid, message->Call_ID->value)){ /* 1. ACK branch won't match INVITE's but they MUST have the same CSeq/CallId values */ - // [transac->type == tsip_transac_type_ist] is used to avoid looping in webrtc2sip mode (e.g. browser <->(breaker)<->browser) - // (browser-1) -> INVITE -> (breaker) -> INVITE - (server) -> INVITE -> (breaker) -> (browser-2) - // the breaker will have two transactions (IST and ICT) with same cseq value and call-id (if not changed by the server) - if(transac->type == tsip_transac_type_ist && tsk_striequals(transac->cseq_method, "INVITE") && message->CSeq->seq == transac->cseq_value){ - ret = tsk_object_ref(transac); - break; - } - } - else if(tsk_strequals(transac->branch, message->firstVia->branch) /* 2. Compare branches*/ - && (1 == 1) /* FIXME: compare host:ip */ - ){ - if(tsk_strequals(transac->cseq_method, message->CSeq->method)){ - ret = tsk_object_ref(transac); - break; - } - else if(TSIP_REQUEST_IS_CANCEL(message) || TSIP_RESPONSE_IS_TO_CANCEL(message)){ - ret = tsk_object_ref(transac); - break; - } - } - } - - tsk_safeobj_unlock(self); - - return ret; + /* + RFC 3261 - 17.2.3 Matching Requests to Server Transactions + + When a request is received from the network by the server, it has to + be matched to an existing transaction. This is accomplished in the + following manner. + + The branch parameter in the topmost Via header field of the request + is examined. If it is present and begins with the magic cookie + "z9hG4bK", the request was generated by a client transaction + compliant to this specification. Therefore, the branch parameter + will be unique across all transactions sent by that client. The + request matches a transaction if: + + 1. the branch parameter in the request is equal to the one in the + top Via header field of the request that created the + transaction, and + + 2. the sent-by value in the top Via of the request is equal to the + one in the request that created the transaction, and + + 3. the method of the request matches the one that created the + transaction, except for ACK, where the method of the request + that created the transaction is INVITE. + */ + tsip_transac_t *ret = tsk_null; + tsip_transac_t *transac; + tsk_list_item_t *item; + //const char* sent_by; + + /* Check first Via/CSeq validity */ + if(!message->firstVia || !message->CSeq) { + return tsk_null; + } + + tsk_safeobj_lock(self); + + tsk_list_foreach(item, self->transactions) { + transac = item->data; + if(TSIP_REQUEST_IS_ACK(message) && tsk_strequals(transac->callid, message->Call_ID->value)) { /* 1. ACK branch won't match INVITE's but they MUST have the same CSeq/CallId values */ + // [transac->type == tsip_transac_type_ist] is used to avoid looping in webrtc2sip mode (e.g. browser <->(breaker)<->browser) + // (browser-1) -> INVITE -> (breaker) -> INVITE - (server) -> INVITE -> (breaker) -> (browser-2) + // the breaker will have two transactions (IST and ICT) with same cseq value and call-id (if not changed by the server) + if(transac->type == tsip_transac_type_ist && tsk_striequals(transac->cseq_method, "INVITE") && message->CSeq->seq == transac->cseq_value) { + ret = tsk_object_ref(transac); + break; + } + } + else if(tsk_strequals(transac->branch, message->firstVia->branch) /* 2. Compare branches*/ + && (1 == 1) /* FIXME: compare host:ip */ + ) { + if(tsk_strequals(transac->cseq_method, message->CSeq->method)) { + ret = tsk_object_ref(transac); + break; + } + else if(TSIP_REQUEST_IS_CANCEL(message) || TSIP_RESPONSE_IS_TO_CANCEL(message)) { + ret = tsk_object_ref(transac); + break; + } + } + } + + tsk_safeobj_unlock(self); + + return ret; } @@ -272,31 +267,31 @@ tsip_transac_t* tsip_transac_layer_find_server(const tsip_transac_layer_t *self, **/ int tsip_transac_layer_handle_incoming_msg(const tsip_transac_layer_t *self, const tsip_message_t* message) { - int ret = -1; - tsip_transac_t *transac = tsk_null; - - if(!message){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - //tsk_safeobj_lock(self); - - if(TSIP_MESSAGE_IS_REQUEST(message)){ - transac = tsip_transac_layer_find_server(self, /*TSIP_MESSAGE_AS_REQUEST*/(message)); - } - else{ - transac = tsip_transac_layer_find_client(self, /*TSIP_MESSAGE_AS_RESPONSE*/(message)); - } - - //tsk_safeobj_unlock(self); - - if(transac){ - ret = transac->callback(transac, tsip_transac_incoming_msg, message); - tsk_object_unref(transac); - } - - return ret; + int ret = -1; + tsip_transac_t *transac = tsk_null; + + if(!message) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + //tsk_safeobj_lock(self); + + if(TSIP_MESSAGE_IS_REQUEST(message)) { + transac = tsip_transac_layer_find_server(self, /*TSIP_MESSAGE_AS_REQUEST*/(message)); + } + else { + transac = tsip_transac_layer_find_client(self, /*TSIP_MESSAGE_AS_RESPONSE*/(message)); + } + + //tsk_safeobj_unlock(self); + + if(transac) { + ret = transac->callback(transac, tsip_transac_incoming_msg, message); + tsk_object_unref(transac); + } + + return ret; } @@ -314,39 +309,38 @@ int tsip_transac_layer_handle_incoming_msg(const tsip_transac_layer_t *self, con // static tsk_object_t* tsip_transac_layer_ctor(tsk_object_t * self, va_list * app) { - tsip_transac_layer_t *layer = self; - if(layer){ - layer->stack = va_arg(*app, const tsip_stack_handle_t *); - layer->transactions = tsk_list_create(); - - tsk_safeobj_init(layer); - } - return self; + tsip_transac_layer_t *layer = self; + if(layer) { + layer->stack = va_arg(*app, const tsip_stack_handle_t *); + layer->transactions = tsk_list_create(); + + tsk_safeobj_init(layer); + } + return self; } static tsk_object_t* tsip_transac_layer_dtor(tsk_object_t * self) -{ - tsip_transac_layer_t *layer = self; - if(layer){ - TSK_OBJECT_SAFE_FREE(layer->transactions); +{ + tsip_transac_layer_t *layer = self; + if(layer) { + TSK_OBJECT_SAFE_FREE(layer->transactions); - tsk_safeobj_deinit(layer); + tsk_safeobj_deinit(layer); - TSK_DEBUG_INFO("*** Transaction Layer destroyed ***"); - } - return self; + TSK_DEBUG_INFO("*** Transaction Layer destroyed ***"); + } + return self; } static int tsip_transac_layer_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2) { - return -1; + return -1; } -static const tsk_object_def_t tsip_transac_layer_def_s = -{ - sizeof(tsip_transac_layer_t), - tsip_transac_layer_ctor, - tsip_transac_layer_dtor, - tsip_transac_layer_cmp, +static const tsk_object_def_t tsip_transac_layer_def_s = { + sizeof(tsip_transac_layer_t), + tsip_transac_layer_ctor, + tsip_transac_layer_dtor, + tsip_transac_layer_cmp, }; const tsk_object_def_t *tsip_transac_layer_def_t = &tsip_transac_layer_def_s; diff --git a/tinySIP/src/transactions/tsip_transac_nict.c b/tinySIP/src/transactions/tsip_transac_nict.c index c16e503..cdae368 100755 --- a/tinySIP/src/transactions/tsip_transac_nict.c +++ b/tinySIP/src/transactions/tsip_transac_nict.c @@ -2,19 +2,19 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -102,29 +102,27 @@ static int tsip_transac_nict_Any_2_Terminated_X_cancel(va_list *app); /* doubang /* ======================== conds ======================== */ /* ======================== actions ======================== */ -typedef enum _fsm_action_e -{ - _fsm_action_cancel = tsip_atype_cancel, - - _fsm_action_send = 0xFF, - _fsm_action_timerE, - _fsm_action_timerF, - _fsm_action_timerK, - _fsm_action_1xx, - _fsm_action_200_to_699, - _fsm_action_transporterror, - _fsm_action_error, +typedef enum _fsm_action_e { + _fsm_action_cancel = tsip_atype_cancel, + + _fsm_action_send = 0xFF, + _fsm_action_timerE, + _fsm_action_timerF, + _fsm_action_timerK, + _fsm_action_1xx, + _fsm_action_200_to_699, + _fsm_action_transporterror, + _fsm_action_error, } _fsm_action_t; /* ======================== states ======================== */ -typedef enum _fsm_state_e -{ - _fsm_state_Started, - _fsm_state_Trying, - _fsm_state_Proceeding, - _fsm_state_Completed, - _fsm_state_Terminated +typedef enum _fsm_state_e { + _fsm_state_Started, + _fsm_state_Trying, + _fsm_state_Proceeding, + _fsm_state_Completed, + _fsm_state_Terminated } _fsm_state_t; @@ -133,74 +131,71 @@ _fsm_state_t; * Callback function called by the transport layer to alert the transaction for incoming messages * or errors (e.g. transport error). * - * @param [in,out] self A pointer to the NIC transaction. - * @param type The event type. + * @param [in,out] self A pointer to the NIC transaction. + * @param type The event type. * @param [in,out] msg The incoming message. * - * @return Zero if succeed and no-zero error code otherwise. + * @return Zero if succeed and no-zero error code otherwise. **/ int tsip_transac_nict_event_callback(const tsip_transac_nict_t *self, tsip_transac_event_type_t type, const tsip_message_t *msg) -{ - int ret = 0; - - switch(type) - { - case tsip_transac_incoming_msg: - { - if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)){ - if(TSIP_RESPONSE_IS_1XX(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_1xx, msg); - } - else if(TSIP_RESPONSE_IS_23456(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_200_to_699, msg); - } - else{ - TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); - } - } - break; - } - - case tsip_transac_canceled: - case tsip_transac_terminated: - case tsip_transac_timedout: - break; - - case tsip_transac_error: - { - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); - break; - } - - case tsip_transac_transport_error: - { - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); - break; - } - - default: break; - } - - return ret; +{ + int ret = 0; + + switch(type) { + case tsip_transac_incoming_msg: { + if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)) { + if(TSIP_RESPONSE_IS_1XX(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_1xx, msg); + } + else if(TSIP_RESPONSE_IS_23456(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_200_to_699, msg); + } + else { + TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); + } + } + break; + } + + case tsip_transac_canceled: + case tsip_transac_terminated: + case tsip_transac_timedout: + break; + + case tsip_transac_error: { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); + break; + } + + case tsip_transac_transport_error: { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); + break; + } + + default: + break; + } + + return ret; } int tsip_transac_nict_timer_callback(const tsip_transac_nict_t* self, tsk_timer_id_t timer_id) { - int ret = -1; - - if(self){ - if(timer_id == self->timerE.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerE, tsk_null); - } - else if(timer_id == self->timerF.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerF, tsk_null); - } - else if(timer_id == self->timerK.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerK, tsk_null); - } - } - - return ret; + int ret = -1; + + if(self) { + if(timer_id == self->timerE.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerE, tsk_null); + } + else if(timer_id == self->timerF.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerF, tsk_null); + } + else if(timer_id == self->timerK.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerK, tsk_null); + } + } + + return ret; } /** Initializes the transaction. @@ -212,126 +207,126 @@ int tsip_transac_nict_timer_callback(const tsip_transac_nict_t* self, tsk_timer_ **/ int tsip_transac_nict_init(tsip_transac_nict_t *self) { - /* Initialize the state machine. */ - tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), - - /*======================= - * === Started === - */ - // Started -> (Send) -> Trying - TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_send, _fsm_state_Trying, tsip_transac_nict_Started_2_Trying_X_send, "tsip_transac_nict_Started_2_Trying_X_send"), - // Started -> (Any) -> Started - TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_nict_Started_2_Started_X_any"), - - /*======================= - * === Trying === - */ - // Trying -> (timerE) -> Trying - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_timerE, _fsm_state_Trying, tsip_transac_nict_Trying_2_Trying_X_timerE, "tsip_transac_nict_Trying_2_Trying_X_timerE"), - // Trying -> (timerF) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_timerF, _fsm_state_Terminated, tsip_transac_nict_Trying_2_Terminated_X_timerF, "tsip_transac_nict_Trying_2_Terminated_X_timerF"), - // Trying -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nict_Trying_2_Terminated_X_transportError, "tsip_transac_nict_Trying_2_Terminated_X_transportError"), - // Trying -> (1xx) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_nict_Trying_2_Proceedding_X_1xx, "tsip_transac_nict_Trying_2_Proceedding_X_1xx"), - // Trying -> (200 to 699) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_200_to_699, _fsm_state_Completed, tsip_transac_nict_Trying_2_Completed_X_200_to_699, "tsip_transac_nict_Trying_2_Completed_X_200_to_699"), - - /*======================= - * === Proceeding === - */ - // Proceeding -> (timerE) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_timerE, _fsm_state_Proceeding, tsip_transac_nict_Proceeding_2_Proceeding_X_timerE, "tsip_transac_nict_Proceeding_2_Proceeding_X_timerE"), - // Proceeding -> (timerF) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_timerF, _fsm_state_Terminated, tsip_transac_nict_Proceeding_2_Terminated_X_timerF, "tsip_transac_nict_Proceeding_2_Terminated_X_timerF"), - // Proceeding -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nict_Proceeding_2_Terminated_X_transportError, "tsip_transac_nict_Proceeding_2_Terminated_X_transportError"), - // Proceeding -> (1xx) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_nict_Proceeding_2_Proceeding_X_1xx, "tsip_transac_nict_Proceeding_2_Proceeding_X_1xx"), - // Proceeding -> (200 to 699) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_200_to_699, _fsm_state_Completed, tsip_transac_nict_Proceeding_2_Completed_X_200_to_699, "tsip_transac_nict_Proceeding_2_Completed_X_200_to_699"), - - /*======================= - * === Completed === - */ - // Completed -> (timer K) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerK, _fsm_state_Terminated, tsip_transac_nict_Completed_2_Terminated_X_timerK, "tsip_transac_nict_Completed_2_Terminated_X_timerK"), - - /*======================= - * === Any === - */ - // Any -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nict_Any_2_Terminated_X_transportError, "tsip_transac_nict_Any_2_Terminated_X_transportError"), - // Any -> (error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_nict_Any_2_Terminated_X_Error, "tsip_transac_nict_Any_2_Terminated_X_Error"), - // Any -> (cancel) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_nict_Any_2_Terminated_X_cancel, "tsip_transac_nict_Any_2_Terminated_X_cancel"), - - TSK_FSM_ADD_NULL()); - - /* Set callback function to call when new messages arrive or errors happen in - the transport layer. - */ - TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_nict_event_callback); - - /* Timers */ - self->timerE.id = TSK_INVALID_TIMER_ID; - self->timerF.id = TSK_INVALID_TIMER_ID; - self->timerK.id = TSK_INVALID_TIMER_ID; - self->timerE.timeout = TSIP_TIMER_GET(E); - self->timerF.timeout = TSIP_TIMER_GET(F); - - return 0; + /* Initialize the state machine. */ + tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), + + /*======================= + * === Started === + */ + // Started -> (Send) -> Trying + TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_send, _fsm_state_Trying, tsip_transac_nict_Started_2_Trying_X_send, "tsip_transac_nict_Started_2_Trying_X_send"), + // Started -> (Any) -> Started + TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_nict_Started_2_Started_X_any"), + + /*======================= + * === Trying === + */ + // Trying -> (timerE) -> Trying + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_timerE, _fsm_state_Trying, tsip_transac_nict_Trying_2_Trying_X_timerE, "tsip_transac_nict_Trying_2_Trying_X_timerE"), + // Trying -> (timerF) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_timerF, _fsm_state_Terminated, tsip_transac_nict_Trying_2_Terminated_X_timerF, "tsip_transac_nict_Trying_2_Terminated_X_timerF"), + // Trying -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nict_Trying_2_Terminated_X_transportError, "tsip_transac_nict_Trying_2_Terminated_X_transportError"), + // Trying -> (1xx) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_nict_Trying_2_Proceedding_X_1xx, "tsip_transac_nict_Trying_2_Proceedding_X_1xx"), + // Trying -> (200 to 699) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_200_to_699, _fsm_state_Completed, tsip_transac_nict_Trying_2_Completed_X_200_to_699, "tsip_transac_nict_Trying_2_Completed_X_200_to_699"), + + /*======================= + * === Proceeding === + */ + // Proceeding -> (timerE) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_timerE, _fsm_state_Proceeding, tsip_transac_nict_Proceeding_2_Proceeding_X_timerE, "tsip_transac_nict_Proceeding_2_Proceeding_X_timerE"), + // Proceeding -> (timerF) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_timerF, _fsm_state_Terminated, tsip_transac_nict_Proceeding_2_Terminated_X_timerF, "tsip_transac_nict_Proceeding_2_Terminated_X_timerF"), + // Proceeding -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nict_Proceeding_2_Terminated_X_transportError, "tsip_transac_nict_Proceeding_2_Terminated_X_transportError"), + // Proceeding -> (1xx) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_1xx, _fsm_state_Proceeding, tsip_transac_nict_Proceeding_2_Proceeding_X_1xx, "tsip_transac_nict_Proceeding_2_Proceeding_X_1xx"), + // Proceeding -> (200 to 699) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_200_to_699, _fsm_state_Completed, tsip_transac_nict_Proceeding_2_Completed_X_200_to_699, "tsip_transac_nict_Proceeding_2_Completed_X_200_to_699"), + + /*======================= + * === Completed === + */ + // Completed -> (timer K) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerK, _fsm_state_Terminated, tsip_transac_nict_Completed_2_Terminated_X_timerK, "tsip_transac_nict_Completed_2_Terminated_X_timerK"), + + /*======================= + * === Any === + */ + // Any -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nict_Any_2_Terminated_X_transportError, "tsip_transac_nict_Any_2_Terminated_X_transportError"), + // Any -> (error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_nict_Any_2_Terminated_X_Error, "tsip_transac_nict_Any_2_Terminated_X_Error"), + // Any -> (cancel) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_nict_Any_2_Terminated_X_cancel, "tsip_transac_nict_Any_2_Terminated_X_cancel"), + + TSK_FSM_ADD_NULL()); + + /* Set callback function to call when new messages arrive or errors happen in + the transport layer. + */ + TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_nict_event_callback); + + /* Timers */ + self->timerE.id = TSK_INVALID_TIMER_ID; + self->timerF.id = TSK_INVALID_TIMER_ID; + self->timerK.id = TSK_INVALID_TIMER_ID; + self->timerE.timeout = TSIP_TIMER_GET(E); + self->timerF.timeout = TSIP_TIMER_GET(F); + + return 0; } tsip_transac_nict_t* tsip_transac_nict_create(int32_t cseq_value, const char* cseq_method, const char* callid, tsip_transac_dst_t* dst) { - tsip_transac_nict_t* transac = tsk_object_new(tsip_transac_nict_def_t); - if(transac){ - // initialize base class - tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_nict, cseq_value, cseq_method, callid, dst, _fsm_state_Started, _fsm_state_Terminated); - - // init FSM - TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; - tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_nict_OnTerminated), (const void*)transac); - - // initialize NICT object - tsip_transac_nict_init(transac); - } - return transac; + tsip_transac_nict_t* transac = tsk_object_new(tsip_transac_nict_def_t); + if(transac) { + // initialize base class + tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_nict, cseq_value, cseq_method, callid, dst, _fsm_state_Started, _fsm_state_Terminated); + + // init FSM + TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; + tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_nict_OnTerminated), (const void*)transac); + + // initialize NICT object + tsip_transac_nict_init(transac); + } + return transac; } /** * Starts the client transaction. * - * @param [in,out] self The client transaction to start. - * @param [in,out] request The SIP/IMS request to send. + * @param [in,out] self The client transaction to start. + * @param [in,out] request The SIP/IMS request to send. * - * @return Zero if succeed and non-zero error code otherwise. + * @return Zero if succeed and non-zero error code otherwise. **/ int tsip_transac_nict_start(tsip_transac_nict_t *self, const tsip_request_t* request) { - int ret = -1; - if(self && request && !TSIP_TRANSAC(self)->running){ - /* Add branch to the new client transaction - * - CANCEL will have the same Via and Contact headers as the request it cancel - * - Transac will use request branch if exit (e.g. when request received over websocket) - */ - if((request->firstVia && !tsk_strnullORempty(request->firstVia->branch))){ - tsk_strupdate(&TSIP_TRANSAC(self)->branch, (request->firstVia ? request->firstVia->branch : "doubango")); - } - else if((TSIP_TRANSAC(self)->branch = tsk_strdup(TSIP_TRANSAC_MAGIC_COOKIE))){ - tsk_istr_t branch; - tsk_strrandom(&branch); - tsk_strcat_2(&(TSIP_TRANSAC(self)->branch), "-%s", branch); - } - - TSIP_TRANSAC(self)->running = tsk_true; - self->request = tsk_object_ref((void*)request); - - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send, tsk_null); - } - return ret; + int ret = -1; + if(self && request && !TSIP_TRANSAC(self)->running) { + /* Add branch to the new client transaction + * - CANCEL will have the same Via and Contact headers as the request it cancel + * - Transac will use request branch if exit (e.g. when request received over websocket) + */ + if((request->firstVia && !tsk_strnullORempty(request->firstVia->branch))) { + tsk_strupdate(&TSIP_TRANSAC(self)->branch, (request->firstVia ? request->firstVia->branch : "doubango")); + } + else if((TSIP_TRANSAC(self)->branch = tsk_strdup(TSIP_TRANSAC_MAGIC_COOKIE))) { + tsk_istr_t branch; + tsk_strrandom(&branch); + tsk_strcat_2(&(TSIP_TRANSAC(self)->branch), "-%s", branch); + } + + TSIP_TRANSAC(self)->running = tsk_true; + self->request = tsk_object_ref((void*)request); + + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send, tsk_null); + } + return ret; } @@ -350,304 +345,304 @@ int tsip_transac_nict_start(tsip_transac_nict_t *self, const tsip_request_t* req */ int tsip_transac_nict_Started_2_Trying_X_send(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - //== Send the request - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(self->request)); - - // Now that the first request is sent using the best transport mean we know if it's reliable or not - if(TNET_SOCKET_TYPE_IS_VALID(self->request->dst_net_type)){ - TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(self->request->dst_net_type); - self->timerK.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(K); /* RFC 3261 - 17.1.2.2*/ - } - - /* RFC 3261 - 17.1.2.2 - The "Trying" state is entered when the TU initiates a new client - transaction with a request. When entering this state, the client - transaction SHOULD set timer F to fire in 64*T1 seconds. - */ - TRANSAC_NICT_TIMER_SCHEDULE(F); - - /* RFC 3261 - 17.1.2.2 - If an unreliable transport is in use, the client transaction MUST set timer - E to fire in T1 seconds. - */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_NICT_TIMER_SCHEDULE(E); - } - - return 0; + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + //== Send the request + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(self->request)); + + // Now that the first request is sent using the best transport mean we know if it's reliable or not + if(TNET_SOCKET_TYPE_IS_VALID(self->request->dst_net_type)) { + TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(self->request->dst_net_type); + self->timerK.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(K); /* RFC 3261 - 17.1.2.2*/ + } + + /* RFC 3261 - 17.1.2.2 + The "Trying" state is entered when the TU initiates a new client + transaction with a request. When entering this state, the client + transaction SHOULD set timer F to fire in 64*T1 seconds. + */ + TRANSAC_NICT_TIMER_SCHEDULE(F); + + /* RFC 3261 - 17.1.2.2 + If an unreliable transport is in use, the client transaction MUST set timer + E to fire in T1 seconds. + */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_NICT_TIMER_SCHEDULE(E); + } + + return 0; } /* Trying -> (Timer E) -> Trying */ int tsip_transac_nict_Trying_2_Trying_X_timerE(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ - - //== Send the request - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->request); - - /* RFC 3261 - 17.1.2.2 - If timer E fires while still in this (Trying) state, the timer is reset, but this time with a value of MIN(2*T1, T2). - When the timer fires again, it is reset to a MIN(4*T1, T2). This process continues so that retransmissions occur with an exponentially - increasing interval that caps at T2. The default value of T2 is 4s, and it represents the amount of time a non-INVITE server transaction - will take to respond to a request, if it does not respond immediately. For the default values of T1 and T2, this results in - intervals of 500 ms, 1 s, 2 s, 4 s, 4 s, 4 s, etc. - */ - self->timerE.timeout = TSK_MIN((self->timerE.timeout<<1), TSIP_TIMER_GET(T2)); - TRANSAC_NICT_TIMER_SCHEDULE(E); - - return 0; + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ + + //== Send the request + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->request); + + /* RFC 3261 - 17.1.2.2 + If timer E fires while still in this (Trying) state, the timer is reset, but this time with a value of MIN(2*T1, T2). + When the timer fires again, it is reset to a MIN(4*T1, T2). This process continues so that retransmissions occur with an exponentially + increasing interval that caps at T2. The default value of T2 is 4s, and it represents the amount of time a non-INVITE server transaction + will take to respond to a request, if it does not respond immediately. For the default values of T1 and T2, this results in + intervals of 500 ms, 1 s, 2 s, 4 s, 4 s, 4 s, etc. + */ + self->timerE.timeout = TSK_MIN((self->timerE.timeout<<1), TSIP_TIMER_GET(T2)); + TRANSAC_NICT_TIMER_SCHEDULE(E); + + return 0; } /* Trying -> (Timer F) -> Terminated */ int tsip_transac_nict_Trying_2_Terminated_X_timerF(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ - /* RFC 3261 - 17.1.2.2 - If Timer F fires while the client transaction is still in the - "Trying" state, the client transaction SHOULD inform the TU about the - timeout, and then it SHOULD enter the "Terminated" state. - */ + /* RFC 3261 - 17.1.2.2 + If Timer F fires while the client transaction is still in the + "Trying" state, the client transaction SHOULD inform the TU about the + timeout, and then it SHOULD enter the "Terminated" state. + */ - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_timedout, self->request); + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - return 0; + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_timedout, self->request); + + return 0; } /* Trying -> (Transport Error) -> Terminated */ int tsip_transac_nict_Trying_2_Terminated_X_transportError(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, self->request); + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, self->request); - return 0; + return 0; } /* Trying -> (1xx) -> Proceeding */ int tsip_transac_nict_Trying_2_Proceedding_X_1xx(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - /* RFC 3261 - 17.1.2.2 - If a provisional response is received while in the "Trying" state, the - response MUST be passed to the TU, and then the client transaction - SHOULD move to the "Proceeding" state. - */ - - /* Cancel timers */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(E); - } - TRANSAC_TIMER_CANCEL(F); /* Now it's up to the UAS to update the FSM. */ - - /* Pass the provisional response to the dialog. */ - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); - - return 0; + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + /* RFC 3261 - 17.1.2.2 + If a provisional response is received while in the "Trying" state, the + response MUST be passed to the TU, and then the client transaction + SHOULD move to the "Proceeding" state. + */ + + /* Cancel timers */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(E); + } + TRANSAC_TIMER_CANCEL(F); /* Now it's up to the UAS to update the FSM. */ + + /* Pass the provisional response to the dialog. */ + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); + + return 0; } /* Trying -> (200-699) -> Completed */ int tsip_transac_nict_Trying_2_Completed_X_200_to_699(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* RFC 3261 - 17.1.2.2 - If a final response (status codes 200-699) is received while in the "Trying" state, the response - MUST be passed to the TU, and the client transaction MUST transition - to the "Completed" state. + /* RFC 3261 - 17.1.2.2 + If a final response (status codes 200-699) is received while in the "Trying" state, the response + MUST be passed to the TU, and the client transaction MUST transition + to the "Completed" state. - If Timer K fires while in this state (Completed), the client transaction MUST transition to the "Terminated" state. - */ + If Timer K fires while in this state (Completed), the client transaction MUST transition to the "Terminated" state. + */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(E); - } - TRANSAC_TIMER_CANCEL(F); + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(E); + } + TRANSAC_TIMER_CANCEL(F); - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); - /* SCHEDULE timer K */ - TRANSAC_NICT_TIMER_SCHEDULE(K); + /* SCHEDULE timer K */ + TRANSAC_NICT_TIMER_SCHEDULE(K); - return 0; + return 0; } /* Proceeding -> (TimerE) -> Proceeding */ int tsip_transac_nict_Proceeding_2_Proceeding_X_timerE(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - //== Send the request - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->request); + //== Send the request + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->request); - /* RFC 3261 - 17.1.2.2 - If Timer E fires while in the "Proceeding" state, the request MUST be - passed to the transport layer for retransmission, and Timer E MUST be - reset with a value of T2 seconds. - */ - self->timerE.timeout = TSK_MIN(self->timerE.timeout*2, TSIP_TIMER_GET(T2)); - TRANSAC_NICT_TIMER_SCHEDULE(E); + /* RFC 3261 - 17.1.2.2 + If Timer E fires while in the "Proceeding" state, the request MUST be + passed to the transport layer for retransmission, and Timer E MUST be + reset with a value of T2 seconds. + */ + self->timerE.timeout = TSK_MIN(self->timerE.timeout*2, TSIP_TIMER_GET(T2)); + TRANSAC_NICT_TIMER_SCHEDULE(E); - return 0; + return 0; } /* Proceeding -> (Timer F) -> Proceeding */ int tsip_transac_nict_Proceeding_2_Terminated_X_timerF(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* RFC 3261 - 17.1.2.2 - If timer F fires while in the "Proceeding" state, the TU MUST be informed of a timeout, and the - client transaction MUST transition to the terminated state. - */ + /* RFC 3261 - 17.1.2.2 + If timer F fires while in the "Proceeding" state, the TU MUST be informed of a timeout, and the + client transaction MUST transition to the terminated state. + */ - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); - return 0; + return 0; } /* Proceeding -> (Transport error) -> Terminated */ int tsip_transac_nict_Proceeding_2_Terminated_X_transportError(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + /*const tsip_message_t *message = va_arg(*app, const tsip_message_t *);*/ - /* Timers will be canceles by On */ - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, 0); + /* Timers will be canceles by On */ + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, 0); - return 0; + return 0; } /* Proceeding -> (1xx) -> Proceeding */ int tsip_transac_nict_Proceeding_2_Proceeding_X_1xx(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(E); - } - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(E); + } + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); - return 0; + return 0; } /* Proceeding -> (200-699) -> Completed */ int tsip_transac_nict_Proceeding_2_Completed_X_200_to_699(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - - /* RFC 3261 - 17.1.2.2 - If a final response (status codes 200-699) is received while in the - "Proceeding" state, the response MUST be passed to the TU, and the - client transaction MUST transition to the "Completed" state. - */ - - /* RFC 3261 - 17.1.2.2 - Once the client transaction enters the "Completed" state, it MUST set - Timer K to fire in T4 seconds for unreliable transports, and zero - seconds for reliable transports. The "Completed" state exists to - buffer any additional response retransmissions that may be received - (which is why the client transaction remains there only for - - unreliable transports). T4 represents the amount of time the network - will take to clear messages between client and server transactions. - The default value of T4 is 5s. - */ - - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(E); - } - - tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); - - /* SCHEDULE timer K */ - TRANSAC_NICT_TIMER_SCHEDULE(K); - - return 0; + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + /* RFC 3261 - 17.1.2.2 + If a final response (status codes 200-699) is received while in the + "Proceeding" state, the response MUST be passed to the TU, and the + client transaction MUST transition to the "Completed" state. + */ + + /* RFC 3261 - 17.1.2.2 + Once the client transaction enters the "Completed" state, it MUST set + Timer K to fire in T4 seconds for unreliable transports, and zero + seconds for reliable transports. The "Completed" state exists to + buffer any additional response retransmissions that may be received + (which is why the client transaction remains there only for + + unreliable transports). T4 represents the amount of time the network + will take to clear messages between client and server transactions. + The default value of T4 is 5s. + */ + + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(E); + } + + tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, message); + + /* SCHEDULE timer K */ + TRANSAC_NICT_TIMER_SCHEDULE(K); + + return 0; } /* Completed -> (Timer K) -> Terminated */ int tsip_transac_nict_Completed_2_Terminated_X_timerK(va_list *app) { - //tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + //tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + + /* RFC 3261 - 17.1.2.2 + If Timer K fires while in this state (Completed), the client transaction + MUST transition to the "Terminated" state. + */ - /* RFC 3261 - 17.1.2.2 - If Timer K fires while in this state (Completed), the client transaction - MUST transition to the "Terminated" state. - */ - - /* RFC 3261 - 17.1.2.2 - ONCE THE TRANSACTION IS IN THE TERMINATED STATE, IT MUST BE DESTROYED IMMEDIATELY. - */ + /* RFC 3261 - 17.1.2.2 + ONCE THE TRANSACTION IS IN THE TERMINATED STATE, IT MUST BE DESTROYED IMMEDIATELY. + */ - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - //tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transac_ok, 0); + //tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transac_ok, 0); - return 0; + return 0; } /* Any -> (Transport Error) -> Terminated */ int tsip_transac_nict_Any_2_Terminated_X_transportError(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); } /* Any -> (Error) -> Terminated */ int tsip_transac_nict_Any_2_Terminated_X_Error(va_list *app) { - tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nict_t *self = va_arg(*app, tsip_transac_nict_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); } /* Any -> (cancel) -> Terminated */ int tsip_transac_nict_Any_2_Terminated_X_cancel(va_list *app) { - /* doubango-specific */ - return 0; + /* doubango-specific */ + return 0; } @@ -662,10 +657,10 @@ int tsip_transac_nict_Any_2_Terminated_X_cancel(va_list *app) */ int tsip_transac_nict_OnTerminated(tsip_transac_nict_t *self) { - TSK_DEBUG_INFO("=== NICT terminated ==="); - - /* Remove (and destroy) the transaction from the layer. */ - return tsip_transac_remove(TSIP_TRANSAC(self)); + TSK_DEBUG_INFO("=== NICT terminated ==="); + + /* Remove (and destroy) the transaction from the layer. */ + return tsip_transac_remove(TSIP_TRANSAC(self)); } @@ -688,44 +683,43 @@ int tsip_transac_nict_OnTerminated(tsip_transac_nict_t *self) // static tsk_object_t* tsip_transac_nict_ctor(tsk_object_t * self, va_list * app) { - tsip_transac_nict_t *transac = self; - if(transac){ - } - return self; + tsip_transac_nict_t *transac = self; + if(transac) { + } + return self; } static tsk_object_t* tsip_transac_nict_dtor(tsk_object_t * _self) -{ - tsip_transac_nict_t *self = _self; - if(self){ - /* Cancel timers */ - if(!TSIP_TRANSAC(self)->reliable){ - TRANSAC_TIMER_CANCEL(E); - } - TRANSAC_TIMER_CANCEL(F); - TRANSAC_TIMER_CANCEL(K); - - TSIP_TRANSAC(self)->running = tsk_false; - TSK_OBJECT_SAFE_FREE(self->request); - - /* DeInitialize base class */ - tsip_transac_deinit(TSIP_TRANSAC(self)); - - TSK_DEBUG_INFO("*** NICT destroyed ***"); - } - return _self; +{ + tsip_transac_nict_t *self = _self; + if(self) { + /* Cancel timers */ + if(!TSIP_TRANSAC(self)->reliable) { + TRANSAC_TIMER_CANCEL(E); + } + TRANSAC_TIMER_CANCEL(F); + TRANSAC_TIMER_CANCEL(K); + + TSIP_TRANSAC(self)->running = tsk_false; + TSK_OBJECT_SAFE_FREE(self->request); + + /* DeInitialize base class */ + tsip_transac_deinit(TSIP_TRANSAC(self)); + + TSK_DEBUG_INFO("*** NICT destroyed ***"); + } + return _self; } static int tsip_transac_nict_cmp(const tsk_object_t *t1, const tsk_object_t *t2) { - return tsip_transac_cmp(t1, t2); + return tsip_transac_cmp(t1, t2); } -static const tsk_object_def_t tsip_transac_nict_def_s = -{ - sizeof(tsip_transac_nict_t), - tsip_transac_nict_ctor, - tsip_transac_nict_dtor, - tsip_transac_nict_cmp, +static const tsk_object_def_t tsip_transac_nict_def_s = { + sizeof(tsip_transac_nict_t), + tsip_transac_nict_ctor, + tsip_transac_nict_dtor, + tsip_transac_nict_cmp, }; const tsk_object_def_t *tsip_transac_nict_def_t = &tsip_transac_nict_def_s; diff --git a/tinySIP/src/transactions/tsip_transac_nist.c b/tinySIP/src/transactions/tsip_transac_nist.c index 66424b2..6c99c02 100755 --- a/tinySIP/src/transactions/tsip_transac_nist.c +++ b/tinySIP/src/transactions/tsip_transac_nist.c @@ -2,19 +2,19 @@ * Copyright (C) 2010-2011 Mamadou Diop. * * Contact: Mamadou Diop <diopmamadou(at)doubango[dot]org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. * @@ -60,7 +60,7 @@ | | | +-------------->| Terminated| | | - +-----------+ + +-----------+ =============================================================================*/ @@ -104,183 +104,175 @@ int tsip_transac_nist_Any_2_Terminated_X_cancel(va_list *app); /* doubango-speci /* ======================== conds ======================== */ /* ======================== actions ======================== */ -typedef enum _fsm_action_e -{ - _fsm_action_cancel = tsip_atype_cancel, - - _fsm_action_request = 0xFF, - _fsm_action_send_1xx, - _fsm_action_send_200_to_699, - _fsm_action_timerJ, - _fsm_action_transporterror, - _fsm_action_error, +typedef enum _fsm_action_e { + _fsm_action_cancel = tsip_atype_cancel, + + _fsm_action_request = 0xFF, + _fsm_action_send_1xx, + _fsm_action_send_200_to_699, + _fsm_action_timerJ, + _fsm_action_transporterror, + _fsm_action_error, } _fsm_action_t; /* ======================== states ======================== */ -typedef enum _fsm_state_e -{ - _fsm_state_Started, - _fsm_state_Trying, - _fsm_state_Proceeding, - _fsm_state_Completed, - _fsm_state_Terminated +typedef enum _fsm_state_e { + _fsm_state_Started, + _fsm_state_Trying, + _fsm_state_Proceeding, + _fsm_state_Completed, + _fsm_state_Terminated } _fsm_state_t; int tsip_transac_nist_event_callback(const tsip_transac_nist_t *self, tsip_transac_event_type_t type, const tsip_message_t *msg) { - int ret = -1; - - switch(type) - { - case tsip_transac_incoming_msg: /* From Transport Layer to Transaction Layer */ - { - if(msg && TSIP_MESSAGE_IS_REQUEST(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_request, msg); - } - break; - } - - case tsip_transac_outgoing_msg: /* From TU to Transport Layer */ - { - if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)) - { - if(TSIP_RESPONSE_IS_1XX(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_1xx, msg); - } - else if(TSIP_RESPONSE_IS_23456(msg)){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_200_to_699, msg); - } - } - break; - } - - case tsip_transac_canceled: - case tsip_transac_terminated: - case tsip_transac_timedout: - break; - - case tsip_transac_error: - { - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); - break; - } - - case tsip_transac_transport_error: - { - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); - break; - } - } - - return ret; + int ret = -1; + + switch(type) { + case tsip_transac_incoming_msg: { /* From Transport Layer to Transaction Layer */ + if(msg && TSIP_MESSAGE_IS_REQUEST(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_request, msg); + } + break; + } + + case tsip_transac_outgoing_msg: { /* From TU to Transport Layer */ + if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)) { + if(TSIP_RESPONSE_IS_1XX(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_1xx, msg); + } + else if(TSIP_RESPONSE_IS_23456(msg)) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_send_200_to_699, msg); + } + } + break; + } + + case tsip_transac_canceled: + case tsip_transac_terminated: + case tsip_transac_timedout: + break; + + case tsip_transac_error: { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_error, msg); + break; + } + + case tsip_transac_transport_error: { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_transporterror, msg); + break; + } + } + + return ret; } int tsip_transac_nist_timer_callback(const tsip_transac_nist_t* self, tsk_timer_id_t timer_id) { - int ret = -1; + int ret = -1; - if(self){ - if(timer_id == self->timerJ.id){ - ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerJ, tsk_null); - } - } + if(self) { + if(timer_id == self->timerJ.id) { + ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_timerJ, tsk_null); + } + } - return ret; + return ret; } int tsip_transac_nist_init(tsip_transac_nist_t *self) { - /* Initialize the state machine. - */ - tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), - - /*======================= - * === Started === - */ - // Started -> (receive request) -> Trying - TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_request, _fsm_state_Trying, tsip_transac_nist_Started_2_Trying_X_request, "tsip_transac_nist_Started_2_Trying_X_request"), - // Started -> (Any other) -> Started - TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_nist_Started_2_Started_X_any"), - - /*======================= - * === Trying === - */ - // Trying -> (receive request retransmission) -> Trying - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_request, _fsm_state_Trying, tsk_null, "tsip_transac_nist_Trying_2_Trying_X_request"), - // Trying -> (send 1xx) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_send_1xx, _fsm_state_Proceeding, tsip_transac_nist_Trying_2_Proceeding_X_send_1xx, "tsip_transac_nist_Trying_2_Proceeding_X_send_1xx"), - // Trying -> (send 200 to 699) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_send_200_to_699, _fsm_state_Completed, tsip_transac_nist_Trying_2_Completed_X_send_200_to_699, "tsip_transac_nist_Trying_2_Completed_X_send_200_to_699"), - - /*======================= - * === Proceeding === - */ - // Proceeding -> (send 1xx) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_send_1xx, _fsm_state_Proceeding, tsip_transac_nist_Proceeding_2_Proceeding_X_send_1xx, "tsip_transac_nist_Proceeding_2_Proceeding_X_send_1xx"), - // Proceeding -> (send 200 to 699) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_send_200_to_699, _fsm_state_Completed, tsip_transac_nist_Proceeding_2_Completed_X_send_200_to_699, "tsip_transac_nist_Proceeding_2_Completed_X_send_200_to_699"), - // Proceeding -> (receive request) -> Proceeding - TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_request, _fsm_state_Proceeding, tsip_transac_nist_Proceeding_2_Proceeding_X_request, "tsip_transac_nist_Proceeding_2_Proceeding_X_request"), - - /*======================= - * === Completed === - */ - // Completed -> (receive request) -> Completed - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_request, _fsm_state_Completed, tsip_transac_nist_Completed_2_Completed_X_request, "tsip_transac_nist_Completed_2_Completed_X_request"), - // Completed -> (timer J) -> Terminated - TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerJ, _fsm_state_Terminated, tsip_transac_nist_Completed_2_Terminated_X_tirmerJ, "tsip_transac_nist_Completed_2_Terminated_X_tirmerJ"), - - /*======================= - * === Any === - */ - // Any -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nist_Any_2_Terminated_X_transportError, "tsip_transac_nist_Any_2_Terminated_X_transportError"), - // Any -> (transport error) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_nist_Any_2_Terminated_X_Error, "tsip_transac_nist_Any_2_Terminated_X_Error"), - // Any -> (cancel) -> Terminated - TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_nist_Any_2_Terminated_X_cancel, "tsip_transac_nist_Any_2_Terminated_X_cancel"), - - TSK_FSM_ADD_NULL()); - - /* Set callback function to call when new messages arrive or errors happen at - the transport layer. - */ - TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_nist_event_callback); - - return 0; + /* Initialize the state machine. + */ + tsk_fsm_set(TSIP_TRANSAC_GET_FSM(self), + + /*======================= + * === Started === + */ + // Started -> (receive request) -> Trying + TSK_FSM_ADD_ALWAYS(_fsm_state_Started, _fsm_action_request, _fsm_state_Trying, tsip_transac_nist_Started_2_Trying_X_request, "tsip_transac_nist_Started_2_Trying_X_request"), + // Started -> (Any other) -> Started + TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_nist_Started_2_Started_X_any"), + + /*======================= + * === Trying === + */ + // Trying -> (receive request retransmission) -> Trying + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_request, _fsm_state_Trying, tsk_null, "tsip_transac_nist_Trying_2_Trying_X_request"), + // Trying -> (send 1xx) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_send_1xx, _fsm_state_Proceeding, tsip_transac_nist_Trying_2_Proceeding_X_send_1xx, "tsip_transac_nist_Trying_2_Proceeding_X_send_1xx"), + // Trying -> (send 200 to 699) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Trying, _fsm_action_send_200_to_699, _fsm_state_Completed, tsip_transac_nist_Trying_2_Completed_X_send_200_to_699, "tsip_transac_nist_Trying_2_Completed_X_send_200_to_699"), + + /*======================= + * === Proceeding === + */ + // Proceeding -> (send 1xx) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_send_1xx, _fsm_state_Proceeding, tsip_transac_nist_Proceeding_2_Proceeding_X_send_1xx, "tsip_transac_nist_Proceeding_2_Proceeding_X_send_1xx"), + // Proceeding -> (send 200 to 699) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_send_200_to_699, _fsm_state_Completed, tsip_transac_nist_Proceeding_2_Completed_X_send_200_to_699, "tsip_transac_nist_Proceeding_2_Completed_X_send_200_to_699"), + // Proceeding -> (receive request) -> Proceeding + TSK_FSM_ADD_ALWAYS(_fsm_state_Proceeding, _fsm_action_request, _fsm_state_Proceeding, tsip_transac_nist_Proceeding_2_Proceeding_X_request, "tsip_transac_nist_Proceeding_2_Proceeding_X_request"), + + /*======================= + * === Completed === + */ + // Completed -> (receive request) -> Completed + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_request, _fsm_state_Completed, tsip_transac_nist_Completed_2_Completed_X_request, "tsip_transac_nist_Completed_2_Completed_X_request"), + // Completed -> (timer J) -> Terminated + TSK_FSM_ADD_ALWAYS(_fsm_state_Completed, _fsm_action_timerJ, _fsm_state_Terminated, tsip_transac_nist_Completed_2_Terminated_X_tirmerJ, "tsip_transac_nist_Completed_2_Terminated_X_tirmerJ"), + + /*======================= + * === Any === + */ + // Any -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_transporterror, _fsm_state_Terminated, tsip_transac_nist_Any_2_Terminated_X_transportError, "tsip_transac_nist_Any_2_Terminated_X_transportError"), + // Any -> (transport error) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_error, _fsm_state_Terminated, tsip_transac_nist_Any_2_Terminated_X_Error, "tsip_transac_nist_Any_2_Terminated_X_Error"), + // Any -> (cancel) -> Terminated + TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_cancel, _fsm_state_Terminated, tsip_transac_nist_Any_2_Terminated_X_cancel, "tsip_transac_nist_Any_2_Terminated_X_cancel"), + + TSK_FSM_ADD_NULL()); + + /* Set callback function to call when new messages arrive or errors happen at + the transport layer. + */ + TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK_F(tsip_transac_nist_event_callback); + + return 0; } tsip_transac_nist_t* tsip_transac_nist_create(int32_t cseq_value, const char* cseq_method, const char* callid, tsip_transac_dst_t* dst) { - tsip_transac_nist_t* transac = tsk_object_new(tsip_transac_nist_def_t); - - if(transac){ - // initialize base class - tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_nist, cseq_value, cseq_method, callid, dst, _fsm_state_Started, _fsm_state_Terminated); - - // init FSM - TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; - tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_nist_OnTerminated), (const void*)transac); - - // initialize NICT object - tsip_transac_nist_init(transac); - } - return transac; + tsip_transac_nist_t* transac = tsk_object_new(tsip_transac_nist_def_t); + + if(transac) { + // initialize base class + tsip_transac_init(TSIP_TRANSAC(transac), tsip_transac_type_nist, cseq_value, cseq_method, callid, dst, _fsm_state_Started, _fsm_state_Terminated); + + // init FSM + TSIP_TRANSAC_GET_FSM(transac)->debug = DEBUG_STATE_MACHINE; + tsk_fsm_set_callback_terminated(TSIP_TRANSAC_GET_FSM(transac), TSK_FSM_ONTERMINATED_F(tsip_transac_nist_OnTerminated), (const void*)transac); + + // initialize NICT object + tsip_transac_nist_init(transac); + } + return transac; } int tsip_transac_nist_start(tsip_transac_nist_t *self, const tsip_request_t* request) { - int ret = -1; - - if(self && !TSIP_TRANSAC(self)->running && request){ - TSIP_TRANSAC(self)->running = 1; - if((ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_request, request))){ - // - } - } - return ret; + int ret = -1; + + if(self && !TSIP_TRANSAC(self)->running && request) { + TSIP_TRANSAC(self)->running = 1; + if((ret = tsip_transac_fsm_act(TSIP_TRANSAC(self), _fsm_action_request, request))) { + // + } + } + return ret; } @@ -299,206 +291,206 @@ int tsip_transac_nist_start(tsip_transac_nist_t *self, const tsip_request_t* req */ int tsip_transac_nist_Started_2_Trying_X_request(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - const tsip_request_t *request = va_arg(*app, const tsip_request_t *); - - if(TNET_SOCKET_TYPE_IS_VALID(request->src_net_type)){ - TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(request->src_net_type); - } - - /* Set Timers */ - self->timerJ.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(J); /* RFC 3261 - 17.2.2*/ - - /* RFC 3261 - 17.2.2 - The state machine is initialized in the "Trying" state and is passed - a request other than INVITE or ACK when initialized. This request is - passed up to the TU. Once in the "Trying" state, any further request - retransmissions are discarded. A request is a retransmission if it - matches the same server transaction, using the rules specified in - Section 17.2.3. - */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, request); + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + const tsip_request_t *request = va_arg(*app, const tsip_request_t *); + + if(TNET_SOCKET_TYPE_IS_VALID(request->src_net_type)) { + TSIP_TRANSAC(self)->reliable = TNET_SOCKET_TYPE_IS_STREAM(request->src_net_type); + } + + /* Set Timers */ + self->timerJ.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(J); /* RFC 3261 - 17.2.2*/ + + /* RFC 3261 - 17.2.2 + The state machine is initialized in the "Trying" state and is passed + a request other than INVITE or ACK when initialized. This request is + passed up to the TU. Once in the "Trying" state, any further request + retransmissions are discarded. A request is a retransmission if it + matches the same server transaction, using the rules specified in + Section 17.2.3. + */ + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_i_msg, request); } /* Trying --> (1xx) --> Proceeding */ int tsip_transac_nist_Trying_2_Proceeding_X_send_1xx(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; - - /* RFC 3261 - 17.2.2 - While in the "Trying" state, if the TU passes a provisional response - to the server transaction, the server transaction MUST enter the - "Proceeding" state. The response MUST be passed to the transport - layer for transmission. - */ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - - /* Update last response */ - TRANSAC_NIST_SET_LAST_RESPONSE(self, response); - - return ret; + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; + + /* RFC 3261 - 17.2.2 + While in the "Trying" state, if the TU passes a provisional response + to the server transaction, the server transaction MUST enter the + "Proceeding" state. The response MUST be passed to the transport + layer for transmission. + */ + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + + /* Update last response */ + TRANSAC_NIST_SET_LAST_RESPONSE(self, response); + + return ret; } /* Trying --> (200-699) --> Completed */ int tsip_transac_nist_Trying_2_Completed_X_send_200_to_699(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - /* RFC 3261 - 17.2.2 - When the server transaction enters the "Completed" state, it MUST set - Timer J to fire in 64*T1 seconds for unreliable transports, and zero - seconds for reliable transports. - */ - TRANSAC_NIST_TIMER_SCHEDULE(J); + /* RFC 3261 - 17.2.2 + When the server transaction enters the "Completed" state, it MUST set + Timer J to fire in 64*T1 seconds for unreliable transports, and zero + seconds for reliable transports. + */ + TRANSAC_NIST_TIMER_SCHEDULE(J); - /* Update last response */ - TRANSAC_NIST_SET_LAST_RESPONSE(self, response); + /* Update last response */ + TRANSAC_NIST_SET_LAST_RESPONSE(self, response); - return ret; + return ret; } /* Proceeding --> (1xx) --> Proceeding */ int tsip_transac_nist_Proceeding_2_Proceeding_X_send_1xx(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - /* RFC 3261 - 17.2.2 - Any further provisional responses that are - received from the TU while in the "Proceeding" state MUST be passed - to the transport layer for transmission. - */ - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + /* RFC 3261 - 17.2.2 + Any further provisional responses that are + received from the TU while in the "Proceeding" state MUST be passed + to the transport layer for transmission. + */ + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - /* Update last response */ - TRANSAC_NIST_SET_LAST_RESPONSE(self, response); + /* Update last response */ + TRANSAC_NIST_SET_LAST_RESPONSE(self, response); - return 0; + return 0; } /* Proceeding -> (INCOMING REQUEST) -> Proceeding */ int tsip_transac_nist_Proceeding_2_Proceeding_X_request(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/ - - /* RFC 3261 - 17.2.2 - If a retransmission of the request is received while in the "Proceeding" state, the most - recently sent provisional response MUST be passed to the transport - layer for retransmission. - */ - if(self->lastResponse){ - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); - } - - return 0; + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/ + + /* RFC 3261 - 17.2.2 + If a retransmission of the request is received while in the "Proceeding" state, the most + recently sent provisional response MUST be passed to the transport + layer for retransmission. + */ + if(self->lastResponse) { + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); + } + + return 0; } /* Proceeding --> (200-699) --> Completed */ int tsip_transac_nist_Proceeding_2_Completed_X_send_200_to_699(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - const tsip_response_t *response = va_arg(*app, const tsip_response_t *); - int ret; - - /* RFC 3261 - 17.2.2 - If the TU passes a final response (status - codes 200-699) to the server while in the "Proceeding" state, the - transaction MUST enter the "Completed" state, and the response MUST - be passed to the transport layer for transmission. - */ - ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); - - /* RFC 3261 - 17.2.2 - When the server transaction enters the "Completed" state, it MUST set - Timer J to fire in 64*T1 seconds for unreliable transports, and zero - seconds for reliable transports. - */ - TRANSAC_NIST_TIMER_SCHEDULE(J); - - /* Update last response */ - TRANSAC_NIST_SET_LAST_RESPONSE(self, response); - - return ret; + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + const tsip_response_t *response = va_arg(*app, const tsip_response_t *); + int ret; + + /* RFC 3261 - 17.2.2 + If the TU passes a final response (status + codes 200-699) to the server while in the "Proceeding" state, the + transaction MUST enter the "Completed" state, and the response MUST + be passed to the transport layer for transmission. + */ + ret = tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, TSIP_MESSAGE(response)); + + /* RFC 3261 - 17.2.2 + When the server transaction enters the "Completed" state, it MUST set + Timer J to fire in 64*T1 seconds for unreliable transports, and zero + seconds for reliable transports. + */ + TRANSAC_NIST_TIMER_SCHEDULE(J); + + /* Update last response */ + TRANSAC_NIST_SET_LAST_RESPONSE(self, response); + + return ret; } /* Completed --> (INCOMING REQUEST) --> Completed */ int tsip_transac_nist_Completed_2_Completed_X_request(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/ - - /* RFC 3261 - 17.2.2 - While in the "Completed" state, the server transaction MUST pass the final response to the transport - layer for retransmission whenever a retransmission of the request is received. - */ - if(self->lastResponse){ - tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); - } - - return 0; + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/ + + /* RFC 3261 - 17.2.2 + While in the "Completed" state, the server transaction MUST pass the final response to the transport + layer for retransmission whenever a retransmission of the request is received. + */ + if(self->lastResponse) { + tsip_transac_send(TSIP_TRANSAC(self), TSIP_TRANSAC(self)->branch, self->lastResponse); + } + + return 0; } /* Complete --> (Timer J) --> Terminated */ int tsip_transac_nist_Completed_2_Terminated_X_tirmerJ(va_list *app) { - /*tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *);*/ - /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/ - - /* RFC 3261 - 17.2.2 - The server transaction remains in this state (Completed) until Timer J fires, at - which point it MUST transition to the "Terminated" state. - */ - - /* RFC 3261 - 17.2.2 - THE SERVER TRANSACTION MUST BE DESTROYED THE INSTANT IT ENTERS THE "TERMINATED" STATE. - */ - return 0; + /*tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *);*/ + /*const tsip_response_t *response = va_arg(*app, const tsip_response_t *);*/ + + /* RFC 3261 - 17.2.2 + The server transaction remains in this state (Completed) until Timer J fires, at + which point it MUST transition to the "Terminated" state. + */ + + /* RFC 3261 - 17.2.2 + THE SERVER TRANSACTION MUST BE DESTROYED THE INSTANT IT ENTERS THE "TERMINATED" STATE. + */ + return 0; } /* Any -> (Transport Error) -> Terminated */ int tsip_transac_nist_Any_2_Terminated_X_transportError(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_transport_error, tsk_null); } /* Any -> (Error) -> Terminated */ int tsip_transac_nist_Any_2_Terminated_X_Error(va_list *app) { - tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); - //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); + tsip_transac_nist_t *self = va_arg(*app, tsip_transac_nist_t *); + //const tsip_message_t *message = va_arg(*app, const tsip_message_t *); - /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ + /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); + return tsip_transac_deliver(TSIP_TRANSAC(self), tsip_dialog_error, tsk_null); } /* Any -> (cancel) -> Terminated */ int tsip_transac_nist_Any_2_Terminated_X_cancel(va_list *app) { - /* doubango-specific */ - return 0; + /* doubango-specific */ + return 0; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -513,10 +505,10 @@ int tsip_transac_nist_Any_2_Terminated_X_cancel(va_list *app) */ int tsip_transac_nist_OnTerminated(tsip_transac_nist_t *self) { - TSK_DEBUG_INFO("=== NIST terminated ==="); - - /* Remove (and destroy) the transaction from the layer. */ - return tsip_transac_remove(TSIP_TRANSAC(self)); + TSK_DEBUG_INFO("=== NIST terminated ==="); + + /* Remove (and destroy) the transaction from the layer. */ + return tsip_transac_remove(TSIP_TRANSAC(self)); } @@ -544,40 +536,39 @@ int tsip_transac_nist_OnTerminated(tsip_transac_nist_t *self) // static tsk_object_t* tsip_transac_nist_ctor(tsk_object_t * self, va_list * app) { - tsip_transac_nist_t *transac = self; - if(transac){ - } - return self; + tsip_transac_nist_t *transac = self; + if(transac) { + } + return self; } static tsk_object_t* tsip_transac_nist_dtor(tsk_object_t * _self) -{ - tsip_transac_nist_t *self = _self; - if(self){ - /* Cancel timers */ - TRANSAC_TIMER_CANCEL(J); +{ + tsip_transac_nist_t *self = _self; + if(self) { + /* Cancel timers */ + TRANSAC_TIMER_CANCEL(J); - TSIP_TRANSAC(self)->running = tsk_false; - TSK_OBJECT_SAFE_FREE(self->lastResponse); + TSIP_TRANSAC(self)->running = tsk_false; + TSK_OBJECT_SAFE_FREE(self->lastResponse); - /* DeInitialize base class */ - tsip_transac_deinit(TSIP_TRANSAC(self)); + /* DeInitialize base class */ + tsip_transac_deinit(TSIP_TRANSAC(self)); - TSK_DEBUG_INFO("*** NIST destroyed ***"); - } - return _self; + TSK_DEBUG_INFO("*** NIST destroyed ***"); + } + return _self; } static int tsip_transac_nist_cmp(const tsk_object_t *t1, const tsk_object_t *t2) { - return tsip_transac_cmp(t1, t2); + return tsip_transac_cmp(t1, t2); } -static const tsk_object_def_t tsip_transac_nist_def_s = -{ - sizeof(tsip_transac_nist_t), - tsip_transac_nist_ctor, - tsip_transac_nist_dtor, - tsip_transac_nist_cmp, +static const tsk_object_def_t tsip_transac_nist_def_s = { + sizeof(tsip_transac_nist_t), + tsip_transac_nist_ctor, + tsip_transac_nist_dtor, + tsip_transac_nist_cmp, }; const tsk_object_def_t *tsip_transac_nist_def_t = &tsip_transac_nist_def_s; |