diff options
Diffstat (limited to 'tinySIP/src/transactions/tsip_transac_ict.c')
-rwxr-xr-x | tinySIP/src/transactions/tsip_transac_ict.c | 1180 |
1 files changed, 586 insertions, 594 deletions
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; |