From 87cfb8989a9731b4b95c065e780e712654c71a02 Mon Sep 17 00:00:00 2001 From: bossiel Date: Wed, 17 Mar 2010 01:20:38 +0000 Subject: [PATCH] Begin implementing INVITE Client Transaction (ICT) with Fixes as per draft-sparks-sip-invfix-0. --- trunk/tinySDP/ragel/tsdp_parser_header_A.rl | 2 +- trunk/tinySDP/ragel/tsdp_parser_header_E.rl | 4 +- trunk/tinySDP/ragel/tsdp_parser_header_M.rl | 2 +- trunk/tinySDP/ragel/tsdp_parser_header_R.rl | 2 +- .../tinysip/transactions/tsip_transac_ict.h | 16 +- trunk/tinySIP/include/tinysip/tsip_message.h | 15 + trunk/tinySIP/include/tinysip/tsip_timers.h | 8 + trunk/tinySIP/src/dialogs/tsip_dialog.c | 4 +- .../dialogs/tsip_dialog_subscribe.client.c | 2 +- .../src/transactions/tsip_transac_ict.c | 722 ++++++++++++++++++ .../src/transactions/tsip_transac_nict.c | 65 +- .../src/transactions/tsip_transac_nist.c | 6 +- trunk/tinySIP/src/transports/tsip_transport.c | 2 +- .../src/transports/tsip_transport_ipsec.c | 2 +- trunk/tinySIP/src/tsip_timers.c | 103 ++- trunk/tinySIP/test/test/test_stack.h | 14 +- 16 files changed, 851 insertions(+), 118 deletions(-) diff --git a/trunk/tinySDP/ragel/tsdp_parser_header_A.rl b/trunk/tinySDP/ragel/tsdp_parser_header_A.rl index 6d0fa1e6..5f124c89 100644 --- a/trunk/tinySDP/ragel/tsdp_parser_header_A.rl +++ b/trunk/tinySDP/ragel/tsdp_parser_header_A.rl @@ -21,7 +21,7 @@ */ -/**@file tsdp_header_B.c +/**@file tsdp_header_A.c * @brief SDP "a=" header (Attributes). * * @author Mamadou Diop diff --git a/trunk/tinySDP/ragel/tsdp_parser_header_E.rl b/trunk/tinySDP/ragel/tsdp_parser_header_E.rl index d7035802..7c6146a7 100644 --- a/trunk/tinySDP/ragel/tsdp_parser_header_E.rl +++ b/trunk/tinySDP/ragel/tsdp_parser_header_E.rl @@ -21,8 +21,8 @@ */ -/**@file tsdp_header_I.c - * @brief SDP "i=" header (Session Information). +/**@file tsdp_header_E.c + * @brief SDP "e=" header (Session Information). * * @author Mamadou Diop * diff --git a/trunk/tinySDP/ragel/tsdp_parser_header_M.rl b/trunk/tinySDP/ragel/tsdp_parser_header_M.rl index 2fd57c78..2f0910b4 100644 --- a/trunk/tinySDP/ragel/tsdp_parser_header_M.rl +++ b/trunk/tinySDP/ragel/tsdp_parser_header_M.rl @@ -21,7 +21,7 @@ */ -/**@file tsdp_header_B.c +/**@file tsdp_header_M.c * @brief SDP "m=" header (Media Descriptions). * * @author Mamadou Diop diff --git a/trunk/tinySDP/ragel/tsdp_parser_header_R.rl b/trunk/tinySDP/ragel/tsdp_parser_header_R.rl index 9a2119aa..119216c8 100644 --- a/trunk/tinySDP/ragel/tsdp_parser_header_R.rl +++ b/trunk/tinySDP/ragel/tsdp_parser_header_R.rl @@ -21,7 +21,7 @@ */ -/**@file tsdp_header_C.c +/**@file tsdp_header_R.c * @brief SDP "r=" header (Repeat Times). * * @author Mamadou Diop diff --git a/trunk/tinySIP/include/tinysip/transactions/tsip_transac_ict.h b/trunk/tinySIP/include/tinysip/transactions/tsip_transac_ict.h index b7eed5c4..54f75aeb 100644 --- a/trunk/tinySIP/include/tinysip/transactions/tsip_transac_ict.h +++ b/trunk/tinySIP/include/tinysip/transactions/tsip_transac_ict.h @@ -31,21 +31,33 @@ #define TINYSIP_TRANSAC_ICT_H #include "tinySIP_config.h" + #include "tinySIP/transactions/tsip_transac.h" +#include "tinySIP/tsip_message.h" #include "tsk_fsm.h" TSIP_BEGIN_DECLS +#define TSIP_TRANSAC_ICT_CREATE(stack, reliable, cseq_value, callid) tsk_object_new(tsip_transac_ict_def_t, (const tsip_stack_handle_t *)stack, (unsigned)reliable, (int32_t)cseq_value, (const char*)callid) + +#define TSIP_TRANSAC_ICT(self) ((tsip_transac_ict_t*)(self)) + typedef struct tsip_transac_ict { TSIP_DECLARE_TRANSAC; - + tsk_fsm_t *fsm; + + tsip_request_t* request; + tsip_timer_t timerA; + tsip_timer_t timerB; + tsip_timer_t timerD; + tsip_timer_t timerM; } tsip_transac_ict_t; -int tsip_transac_ict_init(tsip_transac_ict_t *self); +int tsip_transac_ict_start(tsip_transac_ict_t *self, const tsip_request_t* request); TSIP_END_DECLS diff --git a/trunk/tinySIP/include/tinysip/tsip_message.h b/trunk/tinySIP/include/tinysip/tsip_message.h index f5a8f818..430ad2f2 100644 --- a/trunk/tinySIP/include/tinysip/tsip_message.h +++ b/trunk/tinySIP/include/tinysip/tsip_message.h @@ -83,6 +83,20 @@ TSIP_BEGIN_DECLS #define TSIP_MESSAGE_CONTENT_LENGTH(message) (uint32_t)(((message) && (message)->Content_Length) ? (message)->Content_Length->length : 0) #define TSIP_MESSAGE_CONTENT(message) (TSIP_MESSAGE_HAS_CONTENT(message) ? (message)->Content->data : 0) +#define TSIP_REQUEST_IS_ACK(self) ((self) &&((self)->request_type==tsip_ACK)) +#define TSIP_REQUEST_IS_BYE(self) ((self) &&((self)->request_type==tsip_BYE)) +#define TSIP_REQUEST_IS_CANCEL(self) ((self) &&((self)->request_type==tsip_CANCEL)) +#define TSIP_REQUEST_IS_INVITE(self) ((self) &&((self)->request_type==tsip_INVITE)) +#define TSIP_REQUEST_IS_OPTIONS(self) ((self) &&((self)->request_type==tsip_OPTIONS)) +#define TSIP_REQUEST_IS_REGISTER(self) ((self) &&((self)->request_type==tsip_REGISTER)) +#define TSIP_REQUEST_IS_SUBSCRIBE(self) ((self) &&((self)->request_type==tsip_SUBSCRIBE)) +#define TSIP_REQUEST_IS_NOTIFY(self) ((self) &&((self)->request_type==tsip_NOTIFY)) +#define TSIP_REQUEST_IS_REFER(self) ((self) &&((self)->request_type==tsip_REFER)) +#define TSIP_REQUEST_IS_INFO(self) ((self) &&((self)->request_type==tsip_INFO)) +#define TSIP_REQUEST_IS_UPDATE(self) ((self) &&((self)->request_type==tsip_UPDATE)) +#define TSIP_REQUEST_IS_MESSAGE(self) ((self) &&((self)->request_type==tsip_MESSAGE)) +#define TSIP_REQUEST_IS_PUBLISH(self) ((self) &&((self)->request_type==tsip_PUBLISH)) +#define TSIP_REQUEST_IS_PRACK(self) ((self) &&((self)->request_type==tsip_PRACK)) #define TSIP_RESPONSE_IS(self, code) (TSIP_RESPONSE_CODE((self)) == code) #define TSIP_RESPONSE_IS_NXX(self, N) (TSIP_MESSAGE_IS_RESPONSE((self)) && N##00<= TSIP_RESPONSE_CODE((self)) && TSIP_RESPONSE_CODE((self)) <= N##99) @@ -93,6 +107,7 @@ TSIP_BEGIN_DECLS #define TSIP_RESPONSE_IS_5XX(self) TSIP_RESPONSE_IS_NXX(self, 5) #define TSIP_RESPONSE_IS_6XX(self) TSIP_RESPONSE_IS_NXX(self, 6) #define TSIP_RESPONSE_IS_23456(self) (TSIP_MESSAGE_IS_RESPONSE((self)) && 200<= TSIP_RESPONSE_CODE((self)) && TSIP_RESPONSE_CODE((self)) <= 699) +#define TSIP_RESPONSE_IS_3456(self) (TSIP_MESSAGE_IS_RESPONSE((self)) && 300<= TSIP_RESPONSE_CODE((self)) && TSIP_RESPONSE_CODE((self)) <= 699) /** * @enum tsip_message_type_t diff --git a/trunk/tinySIP/include/tinysip/tsip_timers.h b/trunk/tinySIP/include/tinysip/tsip_timers.h index 55c319a3..0e709358 100644 --- a/trunk/tinySIP/include/tinysip/tsip_timers.h +++ b/trunk/tinySIP/include/tinysip/tsip_timers.h @@ -52,6 +52,8 @@ TSIP_BEGIN_DECLS //extern const char *timerI; //extern const char *timerJ; //extern const char *timerK; +//extern const char *timerL; +//extern const char *timerM; typedef struct tsip_timer_s { @@ -76,6 +78,8 @@ typedef struct tsip_timers_s uint32_t I; uint32_t J; uint32_t K; + uint32_t L; + uint32_t M; } tsip_timers_t; @@ -93,6 +97,8 @@ TINYSIP_API void tsip_timers_setH(uint32_t h); TINYSIP_API void tsip_timers_setI(uint32_t i); TINYSIP_API void tsip_timers_setJ(uint32_t j); TINYSIP_API void tsip_timers_setK(uint32_t k); +TINYSIP_API void tsip_timers_setL(uint32_t l); +TINYSIP_API void tsip_timers_setM(uint32_t m); TINYSIP_API uint32_t tsip_timers_getT1(); TINYSIP_API uint32_t tsip_timers_getT2(); @@ -108,6 +114,8 @@ TINYSIP_API uint32_t tsip_timers_getH(); TINYSIP_API uint32_t tsip_timers_getI(); TINYSIP_API uint32_t tsip_timers_getJ(); TINYSIP_API uint32_t tsip_timers_getK(); +TINYSIP_API uint32_t tsip_timers_getL(); +TINYSIP_API uint32_t tsip_timers_getM(); TSIP_END_DECLS diff --git a/trunk/tinySIP/src/dialogs/tsip_dialog.c b/trunk/tinySIP/src/dialogs/tsip_dialog.c index 1ed2c74f..8ff74d02 100644 --- a/trunk/tinySIP/src/dialogs/tsip_dialog.c +++ b/trunk/tinySIP/src/dialogs/tsip_dialog.c @@ -273,7 +273,7 @@ tsip_request_t *tsip_dialog_request_new(const tsip_dialog_t *self, const char* m c) and the values received in the Service-Route header field saved from the 200 (OK) response to the last registration or re-registration of the public user identity with associated contact address. */ - if(request->request_type != tsip_REGISTER) + if(!TSIP_REQUEST_IS_REGISTER(request)) { // According to the above link ==> Initial/Re/De registration do not have routes. if(copy_routes_start != -1) { /* The dialog already have routes ==> copy them. */ @@ -778,7 +778,7 @@ int tsip_dialog_add_common_headers(const tsip_dialog_t *self, tsip_request_t* re case tsip_PUBLISH: case tsip_REGISTER: { - if(!earlyIMS || (earlyIMS && request->request_type == tsip_REGISTER)){ + if(!earlyIMS || (earlyIMS && TSIP_REQUEST_IS_REGISTER(request))){ TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_P_PREFERRED_IDENTITY_VA_ARGS(preferred_identity)); } break; diff --git a/trunk/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c b/trunk/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c index 0dfbd70f..cfa9a9a3 100644 --- a/trunk/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c +++ b/trunk/tinySIP/src/dialogs/tsip_dialog_subscribe.client.c @@ -170,7 +170,7 @@ int tsip_dialog_subscribe_event_callback(const tsip_dialog_subscribe_t *self, ts // // REQUEST // - if(msg->request_type == tsip_NOTIFY){ + if(TSIP_REQUEST_IS_NOTIFY(msg)){ ret = tsk_fsm_act((self)->fsm, _fsm_action_notify, self, msg, self, msg); } } diff --git a/trunk/tinySIP/src/transactions/tsip_transac_ict.c b/trunk/tinySIP/src/transactions/tsip_transac_ict.c index 50eea0e0..fab40f71 100644 --- a/trunk/tinySIP/src/transactions/tsip_transac_ict.c +++ b/trunk/tinySIP/src/transactions/tsip_transac_ict.c @@ -20,6 +20,56 @@ * */ +/*============================================================================= +* IMPORTANT: The INVITE Client Transaction (ICT) implements corrections defined in 'draft-sparks-sip-invfix-02.txt'. +* which fixes RFC 3261. This will alow us to easily suppoort forking. + + |INVITE from TU + Timer A fires |INVITE sent Timer B fired + Reset A, V or Transport Err. + INVITE sent +-----------+ inform TU + +---------| |--------------------------+ + | | Calling | | + +-------->| |-----------+ | + 300-699 +-----------+ 2xx | | + ACK sent | | 2xx to TU | | + resp. to TU | |1xx | | + +-----------------------------+ |1xx to TU | | + | | | | + | 1xx V | | + | 1xx to TU +-----------+ | | + | +---------| | | | + | | |Proceeding | | | + | +-------->| | | | + | +-----------+ 2xx | | + | 300-699 | | 2xx to TU | | + | ACK sent, +--------+ +---------------+ | + | resp. to TU| | | + | | | | + | V V | + | +-----------+ +----------+ | + +------------->| |Transport Err. | | | + | Completed |Inform TU | Accepted | | + +--| |-------+ | |-+ | + 300-699 | +-----------+ | +----------+ | | + ACK sent| ^ | | | ^ | | + | | | | | | | | + +----+ | | | +-----+ | + |Timer D fires | Timer M fires| 2xx | + |- | - | 2xx to TU | + +--------+ | +-----------+ | + NOTE: V V V | + transitions +------------+ | + labeled with | | | + the event | Terminated |<-----------------------+ + over the action | | + to take +------------+ + + + draft-sparks-sip-invfix-02.txt - Figure 3: INVITE client transaction + +=============================================================================*/ + /**@file tsip_transac_ict.c * @brief SIP INVITE Client Transaction as per RFC 3261 subclause 17.1.1. * @@ -29,7 +79,679 @@ */ #include "tinySIP/transactions/tsip_transac_ict.h" +#include "tsk_debug.h" + +#define DEBUG_STATE_MACHINE 1 + +#define TRANSAC_ICT_TIMER_SCHEDULE(TX) TRANSAC_TIMER_SCHEDULE(ict, TX) + +/* ======================== internal functions ======================== */ +int tsip_transac_ict_init(tsip_transac_ict_t *self); +int tsip_transac_ict_send_ack(const tsip_response_t* response); +int tsip_transac_ict_OnTerminated(tsip_transac_ict_t *self); + +/* ======================== transitions ======================== */ +int tsip_transac_ict_Started_2_Calling_X_send(va_list *app); +int tsip_transac_ict_Calling_2_Calling_X_timerA(va_list *app); +int tsip_transac_ict_Calling_2_Terminated_X_timerB(va_list *app); +int tsip_transac_ict_Calling_2_Completed_X_300_to_699(va_list *app); +int tsip_transac_ict_Calling_2_Proceeding_X_1xx(va_list *app); +int tsip_transac_ict_Calling_2_Accepted_X_2xx(va_list *app); +int tsip_transac_ict_Proceeding_2_Proceeding_X_1xx(va_list *app); +int tsip_transac_ict_Proceeding_2_Completed_X_300_to_699(va_list *app); +int tsip_transac_ict_Proceeding_2_Accepted_X_2xx(va_list *app); +int tsip_transac_ict_Completed_2_Completed_X_300_to_699(va_list *app); +int tsip_transac_ict_Completed_2_Terminated_X_timerD(va_list *app); +int tsip_transac_ict_Accepted_2_Accepted_X_1xx(va_list *app); +int tsip_transac_ict_Accepted_2_Terminated_X_timerM(va_list *app); +int tsip_transac_ict_Any_2_Terminated_X_transportError(va_list *app); +int tsip_transac_ict_Any_2_Terminated_X_Error(va_list *app); + +/* ======================== conds ======================== */ + +/* ======================== actions ======================== */ +typedef enum _fsm_action_e +{ + _fsm_action_send, + _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 +} +_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] msg The incoming message. + * + * @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) +{ + int ret = 0; + + switch(type) + { + case tsip_transac_incoming_msg: + { + if(msg && TSIP_MESSAGE_IS_RESPONSE(msg)) + { + if(TSIP_RESPONSE_IS_1XX(msg)){ + ret = tsk_fsm_act(self->fsm, _fsm_action_1xx, self, msg, self, msg); + } + else if(TSIP_RESPONSE_IS_2XX(msg)){ + ret = tsk_fsm_act(self->fsm, _fsm_action_2xx, self, msg, self, msg); + } + else if(TSIP_RESPONSE_IS_3456(msg)){ + ret = tsk_fsm_act(self->fsm, _fsm_action_300_to_699, self, msg, self, 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 = tsk_fsm_act(self->fsm, _fsm_action_error, self, msg, self, msg); + break; + } + + case tsip_transac_transport_error: + { + ret = tsk_fsm_act(self->fsm, _fsm_action_transporterror, self, msg, self, msg); + break; + } + } + + return ret; +} + +int tsip_transac_ict_timer_callback(const tsip_transac_ict_t* self, tsk_timer_id_t timer_id) +{ + int ret = -1; + + if(self) + { + if(timer_id == self->timerA.id){ + ret = tsk_fsm_act(self->fsm, _fsm_action_timerA, self, TSK_NULL, self, TSK_NULL); + } + else if(timer_id == self->timerB.id){ + ret = tsk_fsm_act(self->fsm, _fsm_action_timerB, self, TSK_NULL, self, TSK_NULL); + } + else if(timer_id == self->timerD.id){ + ret = tsk_fsm_act(self->fsm, _fsm_action_timerD, self, TSK_NULL, self, TSK_NULL); + } + else if(timer_id == self->timerM.id){ + ret = tsk_fsm_act(self->fsm, _fsm_action_timerM, self, TSK_NULL, self, TSK_NULL); + } + } + + return ret; +} + + +/** Initializes the transaction. + * + * @author Mamadou + * @date 12/24/2009 + * + * @param [in,out] self The transaction to initialize. +**/ int tsip_transac_ict_init(tsip_transac_ict_t *self) +{ + /* Initialize the state machine. */ + tsk_fsm_set(self->fsm, + + /*======================= + * === 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 -> (1xx) -> Accepted + TSK_FSM_ADD_ALWAYS(_fsm_state_Accepted, _fsm_action_1xx, _fsm_state_Accepted, tsip_transac_ict_Accepted_2_Accepted_X_1xx, "tsip_transac_ict_Accepted_2_Accepted_X_1xx"), + // 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"), + + + 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(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->timerD.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(D); + self->timerM.timeout = TSIP_TIMER_GET(M); + + return 0; +} + +/** + * Starts the client transaction. + * + * @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. +**/ +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. */ + if((TSIP_TRANSAC(self)->branch = tsk_strdup(TSIP_TRANSAC_MAGIC_COOKIE))) + { + tsk_istr_t branch; + tsk_strrandom(&branch); + tsk_strcat(&(TSIP_TRANSAC(self)->branch), branch); + } + + TSIP_TRANSAC(self)->running = 1; + self->request = tsk_object_ref((void*)request); + + ret = tsk_fsm_act(self->fsm, _fsm_action_send, self, TSK_NULL, self, TSK_NULL); + } + return ret; +} + + + + + +//-------------------------------------------------------- +// == STATE MACHINE BEGIN == +//-------------------------------------------------------- + +/* Started -> (send) -> Calling +*/ +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)); + + /* 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 *); + + /* 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. + + 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); + + self->timerA.timeout *= 2; /* Will not raise indefinitely ==> see timer B */ + TRANSAC_ICT_TIMER_SCHEDULE(A); + + 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(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_timedout, TSIP_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; + + /* RFC 3261 - 17.1.1.2 Formal Description + 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. */ + + /* RFC 3261 - 17.1.1.2 Formal Description + The client transaction SHOULD start timer D when it enters the + "Completed" state, 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. + This is equal to Timer H in the INVITE server transaction, whose + + default is 64*T1. However, the client transaction does not know the + value of T1 in use by the server transaction, so an absolute minimum + of 32s is used instead of basing Timer D on T1. + */ + TRANSAC_ICT_TIMER_SCHEDULE(D); /* timerD already have the right value (0 if reliable and non-zero otherwise) */ + + /* Send ACK */ + ret = tsip_transac_ict_send_ack(response); + + /* Pass the response to the dialog. */ + TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_i_msg, response); + + return ret; +} + +/* 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(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_i_msg, response); + + return 0; +} + +/* Calling -> (2xx) -> Accepted +*/ +int tsip_transac_ict_Calling_2_Accepted_X_2xx(va_list *app) { return 0; } + +/* Proceeding -> (1xx) -> Proceeding +*/ +int tsip_transac_ict_Proceeding_2_Proceeding_X_1xx(va_list *app) +{ + return 0; +} + +/* 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; + + /* RFC 3261 - 17.1.1.2 Formal Description + 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. */ + + /* RFC 3261 - 17.1.1.2 Formal Description + The client transaction SHOULD start timer D when it enters the + "Completed" state, 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. + This is equal to Timer H in the INVITE server transaction, whose + + default is 64*T1. However, the client transaction does not know the + value of T1 in use by the server transaction, so an absolute minimum + of 32s is used instead of basing Timer D on T1. + */ + TRANSAC_ICT_TIMER_SCHEDULE(D); /* timerD already have the right value (0 if reliable and non-zero otherwise) */ + + /* Send ACK */ + ret = tsip_transac_ict_send_ack(response); + + /* Pass the response to the dialog. */ + TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_i_msg, response); + + return ret; +} + +/* Proceeding -> (2xx) -> Accepted +*/ +int tsip_transac_ict_Proceeding_2_Accepted_X_2xx(va_list *app) +{ + /* draft-sparks-sip-invfix-02 - 8.5. Pages 134 to 135 + ........ TO BE CONTINUED + */ + return 0; +} + +/* 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 *); + + /* RFC 3261 - 17.1.1.2 Formal Description + Any retransmissions of the final response 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. A retransmission of the response is + defined as any response which would match the same client transaction + based on the rules of Section 17.1.3. + */ + + return tsip_transac_ict_send_ack(response); +} + +/* Completed -> (timerD) -> Terminated +*/ +int tsip_transac_ict_Completed_2_Terminated_X_timerD(va_list *app) +{ + /* RFC 3261 - 17.1.1.2 Formal Description + 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 -> (1xx) -> Accepted +*/ +int tsip_transac_ict_Accepted_2_Accepted_X_1xx(va_list *app) +{ + return 0; +} + +/* Accepted -> (timerM) -> Terminated +*/ +int tsip_transac_ict_Accepted_2_Terminated_X_timerM(va_list *app) +{ + return 0; +} + +/* Any -> (Transport Error) -> Terminated +*/ +int tsip_transac_ict_Any_2_Terminated_X_transportError(va_list *app) +{ + return 0; +} + +/* Any -> (Error) -> Terminated +*/ +int tsip_transac_ict_Any_2_Terminated_X_Error(va_list *app) +{ + return 0; +} + + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// == STATE MACHINE END == +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +/* Send ACK message*/ +int tsip_transac_ict_send_ack(const tsip_response_t* response) +{ + return -1; +} + +/*== TERMINATED +*/ +int tsip_transac_ict_OnTerminated(tsip_transac_ict_t *self) +{ + /* RFC 3261 - 17.1.1.2 Formal Description + The client transaction MUST be destroyed the instant it enters the + "Terminated" state. This is actually necessary to guarantee correct + operation. + */ + + /* 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 = 0; + + TSK_DEBUG_INFO("=== ICT terminated ==="); + + /* Remove (and destroy) the transaction from the layer. */ + return tsip_transac_remove(TSIP_TRANSAC(self)); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +//======================================================== +// ICT object definition +// +static void* tsip_transac_ict_create(void * self, va_list * app) +{ + tsip_transac_ict_t *transac = self; + if(transac) + { + const tsip_stack_handle_t *stack = va_arg(*app, const tsip_stack_handle_t *); + unsigned reliable = va_arg(*app, unsigned); + int32_t cseq_value = va_arg(*app, int32_t); + const char *cseq_method = "INVITE"; + const char *callid = va_arg(*app, const char *); + + /* create FSM */ + transac->fsm = TSK_FSM_CREATE(_fsm_state_Started, _fsm_state_Terminated); + transac->fsm->debug = DEBUG_STATE_MACHINE; + tsk_fsm_set_callback_terminated(transac->fsm, TSK_FSM_ONTERMINATED(tsip_transac_ict_OnTerminated), (const void*)transac); + + /* Initialize base class */ + tsip_transac_init(TSIP_TRANSAC(transac), stack, tsip_ict, reliable, cseq_value, cseq_method, callid); + + /* Initialize ICT object */ + tsip_transac_ict_init(transac); + } + return self; +} + +static void* tsip_transac_ict_destroy(void * self) +{ + tsip_transac_ict_t *transac = self; + if(transac) + { + TSIP_TRANSAC(transac)->running = 0; + TSK_OBJECT_SAFE_FREE(transac->request); + + /* DeInitialize base class */ + tsip_transac_deinit(TSIP_TRANSAC(transac)); + + /* FSM */ + TSK_OBJECT_SAFE_FREE(transac->fsm); + } + return self; +} + +static int tsip_transac_ict_cmp(const tsk_object_t *t1, const tsk_object_t *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_create, + tsip_transac_ict_destroy, + tsip_transac_ict_cmp, +}; +const void *tsip_transac_ict_def_t = &tsip_transac_ict_def_s; \ No newline at end of file diff --git a/trunk/tinySIP/src/transactions/tsip_transac_nict.c b/trunk/tinySIP/src/transactions/tsip_transac_nict.c index 297fcadb..1716d0d9 100644 --- a/trunk/tinySIP/src/transactions/tsip_transac_nict.c +++ b/trunk/tinySIP/src/transactions/tsip_transac_nict.c @@ -131,9 +131,6 @@ _fsm_state_t; * Callback function called by the transport layer to alert the transaction for incoming messages * or errors (e.g. transport error). * - * @author Mamadou - * @date 1/4/2010 - * * @param [in,out] self A pointer to the NIC transaction. * @param type The event type. * @param [in,out] msg The incoming message. @@ -204,10 +201,7 @@ int tsip_transac_nict_timer_callback(const tsip_transac_nict_t* self, tsk_timer_ return ret; } -/** - * @fn int tsip_transac_nict_init(tsip_transac_nict_t *self) - * - * @brief Initializes the transaction. +/** Initializes the transaction. * * @author Mamadou * @date 12/24/2009 @@ -226,7 +220,6 @@ int tsip_transac_nict_init(tsip_transac_nict_t *self) 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 === @@ -241,7 +234,6 @@ int tsip_transac_nict_init(tsip_transac_nict_t *self) 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 === @@ -256,7 +248,6 @@ int tsip_transac_nict_init(tsip_transac_nict_t *self) 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 === @@ -264,7 +255,6 @@ int tsip_transac_nict_init(tsip_transac_nict_t *self) // 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 === */ @@ -277,17 +267,18 @@ int tsip_transac_nict_init(tsip_transac_nict_t *self) TSK_FSM_ADD_NULL()); /* Set callback function to call when new messages arrive or errors happen in - the transport layer. + the transport layer. */ TSIP_TRANSAC(self)->callback = TSIP_TRANSAC_EVENT_CALLBACK(tsip_transac_nict_event_callback); - - 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); - self->timerK.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(K); /* RFC 3261 - 17.1.2.2*/ + /* 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); + self->timerK.timeout = TSIP_TRANSAC(self)->reliable ? 0 : TSIP_TIMER_GET(K); /* RFC 3261 - 17.1.2.2*/ return 0; } @@ -307,7 +298,7 @@ int tsip_transac_nict_start(tsip_transac_nict_t *self, const tsip_request_t* req if(self && request && !TSIP_TRANSAC(self)->running) { /* Add branch to the new client transaction. */ - TSIP_TRANSAC(self)->branch = tsk_strdup(TSIP_TRANSAC_MAGIC_COOKIE); + if((TSIP_TRANSAC(self)->branch = tsk_strdup(TSIP_TRANSAC_MAGIC_COOKIE))) { tsk_istr_t branch; tsk_strrandom(&branch); @@ -339,7 +330,7 @@ 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 *); + //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)); @@ -355,8 +346,7 @@ int tsip_transac_nict_Started_2_Trying_X_send(va_list *app) If an unreliable transport is in use, the client transaction MUST set timer E to fire in T1 seconds. */ - if(!TSIP_TRANSAC(self)->reliable) - { + if(!TSIP_TRANSAC(self)->reliable){ TRANSAC_NICT_TIMER_SCHEDULE(E); } @@ -401,7 +391,7 @@ int tsip_transac_nict_Trying_2_Terminated_X_timerF(va_list *app) /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_transport_error, 0); + TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_timedout, TSIP_NULL); return 0; } @@ -415,7 +405,7 @@ int tsip_transac_nict_Trying_2_Terminated_X_transportError(va_list *app) /* Timers will be canceled by "tsip_transac_nict_OnTerminated" */ - TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_transport_error, 0); + TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_transport_error, TSIP_NULL); return 0; } @@ -434,12 +424,12 @@ int tsip_transac_nict_Trying_2_Proceedding_X_1xx(va_list *app) */ /* Cancel timers */ - if(!TSIP_TRANSAC(self)->reliable) - { + if(!TSIP_TRANSAC(self)->reliable){ TRANSAC_TIMER_CANCEL(E); } - TRANSAC_TIMER_CANCEL(F); + TRANSAC_TIMER_CANCEL(F); /* Now it's up to the UAS to update the FSM. */ + /* Pass the provisional response to the dialog. */ TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_i_msg, message); return 0; @@ -460,8 +450,7 @@ int tsip_transac_nict_Trying_2_Completed_X_200_to_699(va_list *app) If Timer K fires while in this state (Completed), the client transaction MUST transition to the "Terminated" state. */ - if(!TSIP_TRANSAC(self)->reliable) - { + if(!TSIP_TRANSAC(self)->reliable){ TRANSAC_TIMER_CANCEL(E); } TRANSAC_TIMER_CANCEL(F); @@ -479,7 +468,7 @@ int tsip_transac_nict_Trying_2_Completed_X_200_to_699(va_list *app) 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 *); + //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); @@ -500,7 +489,7 @@ int tsip_transac_nict_Proceeding_2_Proceeding_X_timerE(va_list *app) 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 *); + //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 @@ -534,8 +523,7 @@ 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 *); - if(!TSIP_TRANSAC(self)->reliable) - { + if(!TSIP_TRANSAC(self)->reliable){ TRANSAC_TIMER_CANCEL(E); } TSIP_TRANSAC(self)->dialog->callback(TSIP_TRANSAC(self)->dialog, tsip_dialog_i_msg, message); @@ -568,8 +556,7 @@ int tsip_transac_nict_Proceeding_2_Completed_X_200_to_699(va_list *app) The default value of T4 is 5s. */ - if(!TSIP_TRANSAC(self)->reliable) - { + if(!TSIP_TRANSAC(self)->reliable){ TRANSAC_TIMER_CANCEL(E); } @@ -585,8 +572,8 @@ int tsip_transac_nict_Proceeding_2_Completed_X_200_to_699(va_list *app) */ 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 @@ -717,7 +704,7 @@ static void* tsip_transac_nict_destroy(void * self) return self; } -static int tsip_transac_nict_cmp(const void *t1, const void *t2) +static int tsip_transac_nict_cmp(const tsk_object_t *t1, const tsk_object_t *t2) { return tsip_transac_cmp(t1, t2); } diff --git a/trunk/tinySIP/src/transactions/tsip_transac_nist.c b/trunk/tinySIP/src/transactions/tsip_transac_nist.c index a457ef46..2cec7f8d 100644 --- a/trunk/tinySIP/src/transactions/tsip_transac_nist.c +++ b/trunk/tinySIP/src/transactions/tsip_transac_nist.c @@ -198,7 +198,6 @@ int tsip_transac_nist_init(tsip_transac_nist_t *self) 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) -> Started TSK_FSM_ADD_ALWAYS_NOTHING(_fsm_state_Started, "tsip_transac_nist_Started_2_Started_X_any"), - /*======================= * === Trying === @@ -208,7 +207,6 @@ int tsip_transac_nist_init(tsip_transac_nist_t *self) // 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 === */ @@ -219,7 +217,6 @@ int tsip_transac_nist_init(tsip_transac_nist_t *self) // 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 === */ @@ -227,7 +224,6 @@ int tsip_transac_nist_init(tsip_transac_nist_t *self) 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 === @@ -563,7 +559,7 @@ static void* tsip_transac_nist_destroy(void * self) return self; } -static int tsip_transac_nist_cmp(const void *t1, const void *t2) +static int tsip_transac_nist_cmp(const tsk_object_t *t1, const tsk_object_t *t2) { return tsip_transac_cmp(t1, t2); } diff --git a/trunk/tinySIP/src/transports/tsip_transport.c b/trunk/tinySIP/src/transports/tsip_transport.c index 01c668a8..5d247239 100644 --- a/trunk/tinySIP/src/transports/tsip_transport.c +++ b/trunk/tinySIP/src/transports/tsip_transport.c @@ -143,7 +143,7 @@ size_t tsip_transport_send(const tsip_transport_t* self, const char *branch, tsi tsk_buffer_t *buffer = 0; /* Add Via */ - if(TSIP_MESSAGE_IS_REQUEST(msg) && msg->request_type != tsip_CANCEL){ + if(TSIP_MESSAGE_IS_REQUEST(msg) && !TSIP_REQUEST_IS_CANCEL(msg)){ tsip_transport_addvia(self, branch, msg); tsip_transport_msg_update(self, msg); } diff --git a/trunk/tinySIP/src/transports/tsip_transport_ipsec.c b/trunk/tinySIP/src/transports/tsip_transport_ipsec.c index ff727519..94348f83 100644 --- a/trunk/tinySIP/src/transports/tsip_transport_ipsec.c +++ b/trunk/tinySIP/src/transports/tsip_transport_ipsec.c @@ -243,7 +243,7 @@ int tsip_transport_ipsec_updateMSG(tsip_transport_ipsec_t* self, tsip_message_t goto bail; } - asso = (self->asso_temporary && msg->request_type == tsip_REGISTER) ? self->asso_temporary : self->asso_active; + asso = (self->asso_temporary && TSIP_REQUEST_IS_REGISTER(msg)) ? self->asso_temporary : self->asso_active; if(!asso || !asso->ctx){ TSK_DEBUG_ERROR("No IPSec association found."); ret = -2; diff --git a/trunk/tinySIP/src/tsip_timers.c b/trunk/tinySIP/src/tsip_timers.c index cec1c954..fd01f78a 100644 --- a/trunk/tinySIP/src/tsip_timers.c +++ b/trunk/tinySIP/src/tsip_timers.c @@ -84,6 +84,8 @@ //const char *timerI = "timerI"; //const char *timerJ = "timerJ"; //const char *timerK = "timerK"; +//const char *timerL = "timerL"; +//const char *timerM = "timerM"; static uint32_t T1 = TIMER_T1; @@ -100,150 +102,139 @@ static uint32_t H = 64*TIMER_T1; static uint32_t I = TIMER_T4; static uint32_t J = 64*TIMER_T1; static uint32_t K = TIMER_T4; +static uint32_t L = 64*TIMER_T1; // draft-sparks-sip-invfix +static uint32_t M = 64*TIMER_T1; // draft-sparks-sip-invfix -void tsip_timers_setT1(uint32_t t1) -{ +void tsip_timers_setT1(uint32_t t1){ T1 = t1; A = E = G = T1; B = F = H = J = (T1*64); } -void tsip_timers_setT2(uint32_t t2) -{ +void tsip_timers_setT2(uint32_t t2){ T2 = t2; } -void tsip_timers_setT4(uint32_t t4) -{ +void tsip_timers_setT4(uint32_t t4){ T4 = t4; I = K = T4; } -void tsip_timers_setA(uint32_t a) -{ +void tsip_timers_setA(uint32_t a){ A = a; } -void tsip_timers_setB(uint32_t b) -{ +void tsip_timers_setB(uint32_t b){ B = b; } -void tsip_timers_setc(uint32_t c) -{ +void tsip_timers_setc(uint32_t c){ C = c; } -void tsip_timers_setD(uint32_t d) -{ +void tsip_timers_setD(uint32_t d){ D = d; } -void tsip_timers_setE(uint32_t e) -{ +void tsip_timers_setE(uint32_t e){ E = e; } -void tsip_timers_setF(uint32_t f) -{ +void tsip_timers_setF(uint32_t f){ F = f; } -void tsip_timers_setG(uint32_t g) -{ +void tsip_timers_setG(uint32_t g){ G = g; } -void tsip_timers_setH(uint32_t h) -{ +void tsip_timers_setH(uint32_t h){ H = h; } -void tsip_timers_setI(uint32_t i) -{ +void tsip_timers_setI(uint32_t i){ I = i; } -void tsip_timers_setJ(uint32_t j) -{ +void tsip_timers_setJ(uint32_t j){ J = j; } -void tsip_timers_setK(uint32_t k) -{ +void tsip_timers_setK(uint32_t k){ K = k; } +void tsip_timers_setL(uint32_t l){ + L = l; +} -uint32_t tsip_timers_getT1() -{ +void tsip_timers_setM(uint32_t m){ + M = m; +} + +uint32_t tsip_timers_getT1(){ return T1; } -uint32_t tsip_timers_getT2() -{ +uint32_t tsip_timers_getT2(){ return T2; } -uint32_t tsip_timers_getT4() -{ +uint32_t tsip_timers_getT4(){ return T4; } -uint32_t tsip_timers_getA() -{ +uint32_t tsip_timers_getA(){ return A; } -uint32_t tsip_timers_getB() -{ +uint32_t tsip_timers_getB(){ return B; } -uint32_t tsip_timers_getC() -{ +uint32_t tsip_timers_getC(){ return C; } -uint32_t tsip_timers_getD() -{ +uint32_t tsip_timers_getD(){ return D; } -uint32_t tsip_timers_getE() -{ +uint32_t tsip_timers_getE(){ return E; } -uint32_t tsip_timers_getF() -{ +uint32_t tsip_timers_getF(){ return F; } -uint32_t tsip_timers_getG() -{ +uint32_t tsip_timers_getG(){ return G; } -uint32_t tsip_timers_getH() -{ +uint32_t tsip_timers_getH(){ return H; } -uint32_t tsip_timers_getI() -{ +uint32_t tsip_timers_getI(){ return I; } -uint32_t tsip_timers_getJ() -{ +uint32_t tsip_timers_getJ(){ return J; } -uint32_t tsip_timers_getK() -{ +uint32_t tsip_timers_getK(){ return K; } + +uint32_t tsip_timers_getL(){ + return L; +} + +uint32_t tsip_timers_getM(){ + return M; +} diff --git a/trunk/tinySIP/test/test/test_stack.h b/trunk/tinySIP/test/test/test_stack.h index 44d556c5..573a53b6 100644 --- a/trunk/tinySIP/test/test/test_stack.h +++ b/trunk/tinySIP/test/test/test_stack.h @@ -226,8 +226,8 @@ int test_stack_callback(const tsip_event_t *sipevent) void test_stack() { -//#define DOMAIN "ericsson.com" -#define DOMAIN "micromethod.com" +#define DOMAIN "ericsson.com" +//#define DOMAIN "micromethod.com" //#define DOMAIN "ims.inexbee.com" //#define DOMAIN "sip2sip.info" @@ -248,7 +248,7 @@ void test_stack() TSIP_STACK_SET_NETINFO("ADSL;utran-cell-id-3gpp=00000000"), TSIP_STACK_SET_PRIVACY("header;id"), */ -/* + tsip_stack_handle_t *stack = tsip_stack_create(test_stack_callback, TSIP_STACK_SET_DISPLAY_NAME("Mamadou"), TSIP_STACK_SET_PUBLIC_IDENTITY("sip:mamadou@"DOMAIN), @@ -257,7 +257,7 @@ void test_stack() TSIP_STACK_SET_REALM("sip:"DOMAIN), // FIXME: without sip: TSIP_STACK_SET_LOCAL_IP(LOCAL_IP), //TSIP_STACK_SET_DISCOVERY_NAPTR(1), - TSIP_STACK_SET_PROXY_CSCF("192.168.0.11", "udp", 0), + TSIP_STACK_SET_PROXY_CSCF("192.168.0.14", "udp", 0), //TSIP_STACK_SET_PROXY_CSCF("192.168.0.15", "udp", 0), TSIP_STACK_SET_PROXY_CSCF_PORT(5081), //TSIP_STACK_SET_SECAGREE_IPSEC("hmac-md5-96", "null", "trans", "esp"), @@ -265,7 +265,7 @@ void test_stack() TSIP_STACK_SET_DEVICE_ID("dd1289fa-c3d7-47bd-a40d-f1f1b2cc5ffc"), TSIP_STACK_SET_NETINFO("ADSL;utran-cell-id-3gpp=00000000"), TSIP_STACK_SET_PRIVACY("header;id"), -*/ + /* tsip_stack_handle_t *stack = tsip_stack_create(test_stack_callback, TSIP_STACK_SET_DISPLAY_NAME("Mamadou"), @@ -285,7 +285,7 @@ void test_stack() TSIP_STACK_SET_NETINFO("ADSL;utran-cell-id-3gpp=00000000"), TSIP_STACK_SET_PRIVACY("header;id"), */ - +/* tsip_stack_handle_t *stack = tsip_stack_create(test_stack_callback, TSIP_STACK_SET_DISPLAY_NAME("Mamadou"), TSIP_STACK_SET_PUBLIC_IDENTITY("sip:mamadou@"DOMAIN), @@ -302,6 +302,8 @@ void test_stack() TSIP_STACK_SET_DEVICE_ID("dd1289fa-c3d7-47bd-a40d-f1f1b2cc5ffc"), TSIP_STACK_SET_NETINFO("ADSL;utran-cell-id-3gpp=00000000"), TSIP_STACK_SET_PRIVACY("header;id"), +*/ + TSIP_STACK_SET_NULL());