General update
This commit is contained in:
parent
7540a04ffa
commit
f56dc3b0dc
|
@ -338,9 +338,6 @@ const tsdp_header_M_t* tdav_session_audio_get_lo(tmedia_session_t* self)
|
|||
TSK_OBJECT_SAFE_FREE(self->neg_codecs);
|
||||
self->neg_codecs = neg_codecs;
|
||||
}
|
||||
else{
|
||||
return tsk_null;
|
||||
}
|
||||
|
||||
/* from codecs to sdp */
|
||||
tmedia_codec_to_sdp(self->neg_codecs ? self->neg_codecs : self->codecs, self->M.lo);
|
||||
|
@ -392,8 +389,6 @@ int tdav_session_audio_set_ro(tmedia_session_t* self, const tsdp_header_M_t* m)
|
|||
/* update negociated codecs */
|
||||
TSK_OBJECT_SAFE_FREE(self->neg_codecs);
|
||||
self->neg_codecs = neg_codecs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
return -1;
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
# --pay hello world
|
||||
|
||||
#send INVITE
|
||||
#++a --to sip:bob@$$(domain) >>(inv_audio_sid)
|
||||
#++a --to sip:alice@$$(domain) >>(inv_audio_sid)
|
||||
#++sleep --sec -1
|
||||
#++ho --sid $$(inv_audio_sid)
|
||||
#++sleep --sec -1
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef enum _fsm_action_e
|
|||
_fsm_action_iBYE,
|
||||
_fsm_action_iREFER,
|
||||
|
||||
_fsm_action_timer100rel,
|
||||
_fsm_action_timerRefresh,
|
||||
_fsm_action_timerRSVP,
|
||||
|
||||
|
|
|
@ -49,7 +49,9 @@ typedef struct tsip_dialog_invite
|
|||
uint32_t rseq;
|
||||
|
||||
tsip_timer_t timershutdown;
|
||||
|
||||
tsip_timer_t timer100rel;
|
||||
|
||||
tsip_response_t* last_o1xxrel;
|
||||
tsip_request_t* last_iInvite;
|
||||
tsip_request_t* last_oInvite;
|
||||
tmedia_session_mgr_t* msession_mgr; /**< Media session Manager. */
|
||||
|
@ -66,8 +68,18 @@ typedef struct tsip_dialog_invite
|
|||
enum tmedia_qos_stype_e type;
|
||||
enum tmedia_qos_strength_e strength;
|
||||
} qos;
|
||||
/* 100rel */
|
||||
unsigned enable_100rel:1;
|
||||
|
||||
struct{
|
||||
unsigned _100rel:1;
|
||||
unsigned precondition:1;
|
||||
unsigned timer:1;
|
||||
} supported;
|
||||
|
||||
struct{
|
||||
unsigned _100rel:1;
|
||||
unsigned precondition:1;
|
||||
unsigned timer:1;
|
||||
} require;
|
||||
}
|
||||
tsip_dialog_invite_t;
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ typedef struct tsip_header_s
|
|||
}
|
||||
tsip_header_t;
|
||||
|
||||
#define TSIP_DECLARE_HEADER tsip_header_t header
|
||||
#define TSIP_DECLARE_HEADER tsip_header_t __header__
|
||||
typedef tsk_list_t tsip_headers_L_t; /**< List of @ref tsip_header_t elements. */
|
||||
/*
|
||||
================================*/
|
||||
|
|
|
@ -459,6 +459,9 @@ int tsip_dialog_response_send(const tsip_dialog_t *self, tsip_response_t* respon
|
|||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -221,6 +221,9 @@ int tsip_dialog_invite_timer_callback(const tsip_dialog_invite_t* self, tsk_time
|
|||
if(timer_id == self->stimers.timer.id){
|
||||
ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_timerRefresh, tsk_null, tsk_null);
|
||||
}
|
||||
else if(timer_id == self->timer100rel.id){
|
||||
ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_timer100rel, tsk_null, tsk_null);
|
||||
}
|
||||
else if(timer_id == self->qos.timer.id){
|
||||
ret = tsip_dialog_fsm_act(TSIP_DIALOG(self), _fsm_action_timerRSVP, tsk_null, tsk_null);
|
||||
}
|
||||
|
@ -315,8 +318,8 @@ int tsip_dialog_invite_init(tsip_dialog_invite_t *self)
|
|||
TSIP_DIALOG(self)->callback = TSIP_DIALOG_EVENT_CALLBACK_F(tsip_dialog_invite_event_callback);
|
||||
|
||||
/* Timers */
|
||||
//self->timerrefresh.id = TSK_INVALID_TIMER_ID;
|
||||
//self->timerrefresh.timeout = ;
|
||||
self->timer100rel.id = TSK_INVALID_TIMER_ID;
|
||||
self->stimers.timer.id = TSK_INVALID_TIMER_ID;
|
||||
self->timershutdown.id = TSK_INVALID_TIMER_ID;
|
||||
self->timershutdown.timeout = TSIP_DIALOG_SHUTDOWN_TIMEOUT;
|
||||
|
||||
|
@ -666,12 +669,23 @@ int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bo
|
|||
|
||||
/* Session timers */
|
||||
if(self->stimers.timer.timeout){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_SESSION_EXPIRES_VA_ARGS(self->stimers.timer.timeout, tsk_striequals(self->stimers.refresher, "uas")),
|
||||
TSIP_HEADER_SUPPORTED_VA_ARGS("timer"),
|
||||
tsk_null
|
||||
);
|
||||
if(self->require.timer){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_SESSION_EXPIRES_VA_ARGS(self->stimers.timer.timeout, tsk_striequals(self->stimers.refresher, "uas")),
|
||||
TSIP_HEADER_REQUIRE_VA_ARGS("timer"),
|
||||
tsk_null
|
||||
);
|
||||
}
|
||||
else if(self->supported.timer){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_SESSION_EXPIRES_VA_ARGS(self->stimers.timer.timeout, tsk_striequals(self->stimers.refresher, "uas")),
|
||||
TSIP_HEADER_SUPPORTED_VA_ARGS("timer"),
|
||||
tsk_null
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(self->stimers.minse){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_MIN_SE_VA_ARGS(self->stimers.minse),
|
||||
|
@ -680,7 +694,13 @@ int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bo
|
|||
}
|
||||
|
||||
/* 100rel */
|
||||
if(self->enable_100rel){
|
||||
if(self->require._100rel){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_REQUIRE_VA_ARGS("100rel"),
|
||||
tsk_null
|
||||
);
|
||||
}
|
||||
else if(self->supported._100rel){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_SUPPORTED_VA_ARGS("100rel"),
|
||||
tsk_null
|
||||
|
@ -688,20 +708,19 @@ int send_INVITEorUPDATE(tsip_dialog_invite_t *self, tsk_bool_t is_INVITE, tsk_bo
|
|||
}
|
||||
|
||||
/* QoS */
|
||||
if(self->qos.type != tmedia_qos_stype_none){
|
||||
if(self->qos.strength == tmedia_qos_strength_mandatory){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_REQUIRE_VA_ARGS("precondition"),
|
||||
tsk_null
|
||||
);
|
||||
}
|
||||
else{
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_SUPPORTED_VA_ARGS("precondition"),
|
||||
tsk_null
|
||||
);
|
||||
}
|
||||
if(self->require.precondition){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_REQUIRE_VA_ARGS("precondition"),
|
||||
tsk_null
|
||||
);
|
||||
}
|
||||
else if(self->supported.precondition){
|
||||
tsip_message_add_headers(request,
|
||||
TSIP_HEADER_SUPPORTED_VA_ARGS("precondition"),
|
||||
tsk_null
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* Always added headers */
|
||||
// Explicit Communication Transfer (3GPP TS 24.629)
|
||||
|
@ -973,6 +992,28 @@ int send_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t* request, sho
|
|||
);
|
||||
}
|
||||
|
||||
/* 180 Ringing */
|
||||
/* 183 Session in Progress */
|
||||
if(code == 180 || code == 183){
|
||||
if(self->require._100rel){
|
||||
tsip_message_add_headers(response,
|
||||
TSIP_HEADER_REQUIRE_VA_ARGS("100rel"),
|
||||
TSIP_HEADER_RSEQ_VA_ARGS(self->rseq),
|
||||
tsk_null
|
||||
);
|
||||
TSK_OBJECT_SAFE_FREE(self->last_o1xxrel);
|
||||
self->last_o1xxrel = tsk_object_ref(response);
|
||||
|
||||
/* No-Initial reliable 1xx will use tsip_dialog_response_send() instead of this function
|
||||
* ==> can reseset timeout value and make initial schedule */
|
||||
TSIP_DIALOG_TIMER_CANCEL(100rel);
|
||||
self->timer100rel.timeout = tsip_timers_getA();
|
||||
TSIP_DIALOG_INVITE_TIMER_SCHEDULE(100rel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* SDP content */
|
||||
if(self->msession_mgr && force_sdp){
|
||||
const tsdp_message_t* sdp_lo;
|
||||
char* sdp;
|
||||
|
@ -995,6 +1036,28 @@ int send_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t* request, sho
|
|||
return ret;
|
||||
}
|
||||
|
||||
int send_ERROR(tsip_dialog_invite_t* self, const tsip_request_t* request, short code, const char* phrase, const char* reason)
|
||||
{
|
||||
tsip_response_t *response;
|
||||
|
||||
if(!self){
|
||||
TSK_DEBUG_ERROR("Invalid parameter");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((response = tsip_dialog_response_new(TSIP_DIALOG(self), code, phrase, request))){
|
||||
// Add UnSupported header
|
||||
tsip_message_add_headers(response,
|
||||
TSIP_HEADER_DUMMY_VA_ARGS("Reason", reason),
|
||||
tsk_null
|
||||
);
|
||||
|
||||
tsip_dialog_response_send(TSIP_DIALOG(self), response);
|
||||
TSK_OBJECT_SAFE_FREE(response);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tsip_dialog_invite_OnTerminated(tsip_dialog_invite_t *self)
|
||||
{
|
||||
TSK_DEBUG_INFO("=== INVITE Dialog terminated ===");
|
||||
|
@ -1063,6 +1126,7 @@ static tsk_object_t* tsip_dialog_invite_dtor(tsk_object_t * _self)
|
|||
tsip_dialog_invite_stimers_cancel(self);
|
||||
tsip_dialog_invite_qos_timer_cancel(self);
|
||||
TSIP_DIALOG_TIMER_CANCEL(shutdown);
|
||||
TSIP_DIALOG_TIMER_CANCEL(100rel);
|
||||
|
||||
/* DeInitialize base class */
|
||||
tsip_dialog_deinit(TSIP_DIALOG(self));
|
||||
|
@ -1071,6 +1135,7 @@ static tsk_object_t* tsip_dialog_invite_dtor(tsk_object_t * _self)
|
|||
TSK_OBJECT_SAFE_FREE(self->msession_mgr);
|
||||
TSK_OBJECT_SAFE_FREE(self->last_oInvite);
|
||||
TSK_OBJECT_SAFE_FREE(self->last_iInvite);
|
||||
TSK_OBJECT_SAFE_FREE(self->last_o1xxrel);
|
||||
TSK_FREE(self->stimers.refresher);
|
||||
//...
|
||||
|
||||
|
|
|
@ -133,6 +133,7 @@ int c0000_Started_2_Outgoing_X_oINVITE(va_list *app)
|
|||
if(TSIP_DIALOG_GET_SS(self)->media.timers.timeout){
|
||||
self->stimers.timer.timeout = TSIP_DIALOG_GET_SS(self)->media.timers.timeout;
|
||||
tsk_strupdate(&self->stimers.refresher, TSIP_DIALOG_GET_SS(self)->media.timers.refresher);
|
||||
self->supported.timer = tsk_true;
|
||||
}
|
||||
|
||||
/* QoS
|
||||
|
@ -143,9 +144,11 @@ int c0000_Started_2_Outgoing_X_oINVITE(va_list *app)
|
|||
self->qos.type = TSIP_DIALOG_GET_SS(self)->media.qos.type;
|
||||
self->qos.strength = TSIP_DIALOG_GET_SS(self)->media.qos.strength;
|
||||
tmedia_session_mgr_set_qos(self->msession_mgr, self->qos.type, self->qos.strength);
|
||||
self->supported.precondition = (self->qos.strength == tmedia_qos_strength_optional);
|
||||
self->require.precondition = (self->qos.strength == tmedia_qos_strength_mandatory);
|
||||
|
||||
/* 100rel */
|
||||
self->enable_100rel = TSIP_DIALOG_GET_SS(self)->media.enable_100rel;
|
||||
self->supported._100rel = TSIP_DIALOG_GET_SS(self)->media.enable_100rel;
|
||||
|
||||
/* send the request */
|
||||
ret = send_INVITE(self, tsk_false);
|
||||
|
@ -180,8 +183,7 @@ int c0000_Outgoing_2_Connected_X_i2xxINVITE(va_list *app)
|
|||
ret = send_ACK(self, r2xxINVITE);
|
||||
}
|
||||
|
||||
/* Determine whether the remote party support UPDATE
|
||||
* FIXME: do the same in server side */
|
||||
/* Determine whether the remote party support UPDATE */
|
||||
self->support_update = tsip_message_allowed(r2xxINVITE, "UPDATE");
|
||||
|
||||
/* Session Timers */
|
||||
|
|
|
@ -35,16 +35,22 @@
|
|||
|
||||
#include "tinysip/headers/tsip_header_Dummy.h"
|
||||
#include "tinysip/headers/tsip_header_Min_SE.h"
|
||||
#include "tinysip/headers/tsip_header_RAck.h"
|
||||
#include "tinysip/headers/tsip_header_Require.h"
|
||||
#include "tinysip/headers/tsip_header_Session_Expires.h"
|
||||
|
||||
#include "tsk_debug.h"
|
||||
|
||||
static const char* supported_options[] = { "100rel", "precondition8", "timer" };
|
||||
static const char* supported_options[] = { "100rel", "precondition", "timer" };
|
||||
|
||||
/* ======================== external functions ======================== */
|
||||
extern int send_RESPONSE(tsip_dialog_invite_t *self, const tsip_request_t* request, short code, const char* phrase, tsk_bool_t force_sdp);
|
||||
extern int tsip_dialog_invite_process_ro(tsip_dialog_invite_t *self, const tsip_message_t* message);
|
||||
extern int tsip_dialog_invite_stimers_schedule(tsip_dialog_invite_t* self, uint64_t timeout);
|
||||
extern tsk_bool_t tsip_dialog_invite_stimers_isRefresher(tsip_dialog_invite_t* self);
|
||||
extern int send_ERROR(tsip_dialog_invite_t* self, const tsip_request_t* request, short code, const char* phrase, const char* reason);
|
||||
|
||||
extern int tsip_dialog_invite_timer_callback(const tsip_dialog_invite_t* self, tsk_timer_id_t timer_id);
|
||||
|
||||
/* ======================== internal functions ======================== */
|
||||
int send_UNSUPPORTED(tsip_dialog_invite_t* self, const tsip_request_t* request, const char* option);
|
||||
|
@ -63,6 +69,7 @@ int s0000_Ringing_2_Ringing_X_iPRACK(va_list *app); // Alert user
|
|||
int s0000_Ringing_2_Connected_X_Accept(va_list *app);
|
||||
int s0000_Ringing_2_Terminated_X_Reject(va_list *app);
|
||||
int s0000_Ringing_2_Terminated_X_iCANCEL(va_list *app);
|
||||
int s0000_Any_2_Any_X_timer100rel(va_list *app);
|
||||
|
||||
/* ======================== conds ======================== */
|
||||
static tsk_bool_t _fsm_cond_bad_extension(tsip_dialog_invite_t* self, tsip_message_t* message)
|
||||
|
@ -72,7 +79,7 @@ static tsk_bool_t _fsm_cond_bad_extension(tsip_dialog_invite_t* self, tsip_messa
|
|||
tsk_size_t i, j;
|
||||
|
||||
/* Check if we support all extensions */
|
||||
for(i = 0; (requireHdr = (const tsip_header_Require_t*)tsip_message_get_header(message, tsip_htype_Require)); i++){
|
||||
for(i = 0; (requireHdr = (const tsip_header_Require_t*)tsip_message_get_headerAt(message, tsip_htype_Require, i)); i++){
|
||||
tsk_bool_t bad_extension = tsk_false;
|
||||
const tsk_string_t* option = tsk_null;
|
||||
tsk_list_foreach(item, requireHdr->options){
|
||||
|
@ -105,7 +112,7 @@ static tsk_bool_t _fsm_cond_bad_content(tsip_dialog_invite_t* self, tsip_message
|
|||
|
||||
/* Check remote offer */
|
||||
if((ret = tsip_dialog_invite_process_ro(self, message))){
|
||||
send_RESPONSE(self, message, 488, "Not Acceptable", tsk_false);
|
||||
ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
|
||||
return tsk_true;
|
||||
}
|
||||
/* generate local offer and check it's validity */
|
||||
|
@ -113,7 +120,7 @@ static tsk_bool_t _fsm_cond_bad_content(tsip_dialog_invite_t* self, tsip_message
|
|||
/* check that we have at least one codec */
|
||||
}
|
||||
else{
|
||||
send_RESPONSE(self, message, 488, "Not Acceptable", tsk_false);
|
||||
ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
|
||||
return tsk_true;
|
||||
}
|
||||
|
||||
|
@ -142,7 +149,6 @@ static tsk_bool_t _fsm_cond_toosmall(tsip_dialog_invite_t* self, tsip_message_t*
|
|||
}
|
||||
return tsk_false;
|
||||
}
|
||||
|
||||
static tsk_bool_t _fsm_cond_supports_100rel(tsip_dialog_invite_t* self, tsip_message_t* message)
|
||||
{
|
||||
if(tsip_message_supported(message, "100rel") || tsip_message_required(message, "100rel")){
|
||||
|
@ -150,7 +156,22 @@ static tsk_bool_t _fsm_cond_supports_100rel(tsip_dialog_invite_t* self, tsip_mes
|
|||
}
|
||||
return tsk_false;
|
||||
}
|
||||
static tsk_bool_t _fsm_cond_prack_match(tsip_dialog_invite_t* self, tsip_message_t* message)
|
||||
{
|
||||
const tsip_header_RAck_t* RAck;
|
||||
|
||||
if(!self->last_o1xxrel){
|
||||
return tsk_false;
|
||||
}
|
||||
|
||||
if((RAck = (const tsip_header_RAck_t*)tsip_message_get_header(message, tsip_htype_RAck))){
|
||||
return (RAck->seq == self->rseq) &&
|
||||
(tsk_striequals(RAck->method, self->last_o1xxrel->CSeq->method)) &&
|
||||
(RAck->cseq == self->last_o1xxrel->CSeq->seq);
|
||||
}
|
||||
|
||||
return tsk_false;
|
||||
}
|
||||
static tsk_bool_t _fsm_cond_supports_preconditions(tsip_dialog_invite_t* self, tsip_message_t* message)
|
||||
{
|
||||
// supports or require
|
||||
|
@ -187,7 +208,7 @@ int tsip_dialog_invite_server_init(tsip_dialog_invite_t *self)
|
|||
// InProgress ->(iPRACK with QoS) -> InProgress
|
||||
TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_iPRACK, _fsm_cond_supports_preconditions, _fsm_state_InProgress, s0000_InProgress_2_InProgress_X_iPRACK, "s0000_InProgress_2_InProgress_X_iPRACK"),
|
||||
// InProgress ->(iPRACK without QoS) -> Ringing
|
||||
TSK_FSM_ADD_ALWAYS(_fsm_state_InProgress, _fsm_action_iPRACK, _fsm_state_Ringing, s0000_InProgress_2_Ringing_X_iPRACK, "s0000_InProgress_2_Ringing_X_iPRACK"),
|
||||
TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_iPRACK, _fsm_cond_prack_match, _fsm_state_Ringing, s0000_InProgress_2_Ringing_X_iPRACK, "s0000_InProgress_2_Ringing_X_iPRACK"),
|
||||
// InProgress ->(iUPDATE but cannot resume) -> InProgress
|
||||
TSK_FSM_ADD(_fsm_state_InProgress, _fsm_action_iUPDATE, _fsm_cond_cannotresume, _fsm_state_InProgress, s0000_InProgress_2_InProgress_X_iUPDATE, "s0000_InProgress_2_InProgress_X_iUPDATE"),
|
||||
// InProgress ->(iUPDATE can resume) -> Ringing
|
||||
|
@ -200,7 +221,7 @@ int tsip_dialog_invite_server_init(tsip_dialog_invite_t *self)
|
|||
* === Ringing ===
|
||||
*/
|
||||
// Ringing -> (iPRACK) -> Ringing
|
||||
TSK_FSM_ADD_ALWAYS(_fsm_state_Ringing, _fsm_action_iUPDATE, _fsm_state_Ringing, s0000_Ringing_2_Ringing_X_iPRACK, "s0000_Ringing_2_Ringing_X_iPRACK"),
|
||||
TSK_FSM_ADD(_fsm_state_Ringing, _fsm_action_iPRACK, _fsm_cond_prack_match, _fsm_state_Ringing, s0000_Ringing_2_Ringing_X_iPRACK, "s0000_Ringing_2_Ringing_X_iPRACK"),
|
||||
// Ringing -> (oAccept) -> Connected
|
||||
TSK_FSM_ADD_ALWAYS(_fsm_state_Ringing, _fsm_action_accept, _fsm_state_Connected, s0000_Ringing_2_Connected_X_Accept, "s0000_Ringing_2_Connected_X_Accept"),
|
||||
// Ringing -> (oReject) -> Terminated
|
||||
|
@ -208,6 +229,14 @@ int tsip_dialog_invite_server_init(tsip_dialog_invite_t *self)
|
|||
// Ringing ->(iCANCEL) -> Terminated
|
||||
TSK_FSM_ADD_ALWAYS(_fsm_state_Ringing, _fsm_action_iCANCEL, _fsm_state_Terminated, s0000_Ringing_2_Terminated_X_iCANCEL, "s0000_Ringing_2_Terminated_X_iCANCEL"),
|
||||
|
||||
|
||||
/*=======================
|
||||
* === ANY ===
|
||||
*/
|
||||
// Any ->(timer100rel) -> Any
|
||||
TSK_FSM_ADD_ALWAYS(tsk_fsm_state_any, _fsm_action_timer100rel, tsk_fsm_state_any, s0000_Any_2_Any_X_timer100rel, "s0000_Any_2_Any_X_timer100rel"),
|
||||
|
||||
|
||||
TSK_FSM_ADD_NULL());
|
||||
}
|
||||
|
||||
|
@ -271,27 +300,91 @@ int s0000_Started_2_Ringing_X_iINVITE(va_list *app)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Started -> (100rel or QoS, ther later need the first) -> InProgress */
|
||||
/* Started -> (100rel or QoS, the later need the first) -> InProgress */
|
||||
int s0000_Started_2_InProgress_X_iINVITE(va_list *app)
|
||||
{
|
||||
tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
|
||||
tsip_request_t *request = va_arg(*app, tsip_request_t *);
|
||||
|
||||
/* We are not the client */
|
||||
self->is_client = tsk_false;
|
||||
|
||||
/* update last INVITE */
|
||||
TSK_OBJECT_SAFE_FREE(self->last_iInvite);
|
||||
self->last_iInvite = tsk_object_ref(request);
|
||||
|
||||
/* Update state */
|
||||
tsip_dialog_update_2(TSIP_DIALOG(self), request);
|
||||
|
||||
/* Send In Progress
|
||||
RFC 3262 - 3 UAS Behavior
|
||||
|
||||
The provisional response to be sent reliably is constructed by the
|
||||
UAS core according to the procedures of Section 8.2.6 of RFC 3261.
|
||||
In addition, it MUST contain a Require header field containing the
|
||||
option tag 100rel, and MUST include an RSeq header field. The value
|
||||
of the header field for the first reliable provisional response in a
|
||||
transaction MUST be between 1 and 2**31 - 1.
|
||||
*/
|
||||
self->rseq = (rand() ^ rand()) % (0x00000001 << 31);
|
||||
self->require._100rel = tsk_true;
|
||||
send_RESPONSE(self, request, 183, "Session in Progress", tsk_true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* InProgress ->(iPRACK with QoS) -> InProgress */
|
||||
int s0000_InProgress_2_InProgress_X_iPRACK(va_list *app)
|
||||
{
|
||||
|
||||
/* Cancel 100rel timer */
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* InProgress ->(iPRACK without QoS) -> Ringing */
|
||||
int s0000_InProgress_2_Ringing_X_iPRACK(va_list *app)
|
||||
{
|
||||
return 0;
|
||||
int ret;
|
||||
|
||||
tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
|
||||
tsip_request_t *request = va_arg(*app, tsip_request_t *);
|
||||
|
||||
/* In all cases: Send 2xx PRACK */
|
||||
ret = send_RESPONSE(self, request, 200, "OK", tsk_false);
|
||||
|
||||
/*
|
||||
1. Alice sends an initial INVITE without offer
|
||||
2. Bob's answer is sent in the first reliable provisional response, in this case it's a 1xx INVITE response
|
||||
3. Alice's answer is sent in the PRACK response
|
||||
*/
|
||||
if(!self->msession_mgr->sdp.ro){
|
||||
if(TSIP_MESSAGE_HAS_CONTENT(request)){
|
||||
if((ret = tsip_dialog_invite_process_ro(self, request))){
|
||||
/* Send Error and break the FSM */
|
||||
ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Bad content\"");
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
else{
|
||||
/* 488 INVITE */
|
||||
ret = send_ERROR(self, self->last_iInvite, 488, "Not Acceptable", "SIP; cause=488; text=\"Offer expected in the PRACK\"");
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cancel 100rel timer */
|
||||
TSIP_DIALOG_TIMER_CANCEL(100rel);
|
||||
|
||||
/* Send Ringing */
|
||||
send_RESPONSE(self, self->last_iInvite, 180, "Ringing", tsk_false);
|
||||
|
||||
/* Alert the user (session) */
|
||||
TSIP_DIALOG_INVITE_SIGNAL(self, tsip_i_newcall,
|
||||
tsip_event_code_dialog_request_incoming, "Incoming Request.", request);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* InProgress ->(iUPDATE but cannot resume) -> InProgress */
|
||||
|
@ -315,7 +408,23 @@ int s0000_Inprogress_2_Terminated_X_iCANCEL(va_list *app)
|
|||
/* Ringing -> (iPRACK) -> Ringing */
|
||||
int s0000_Ringing_2_Ringing_X_iPRACK(va_list *app)
|
||||
{
|
||||
return 0;
|
||||
int ret;
|
||||
|
||||
tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
|
||||
tsip_request_t *request = va_arg(*app, tsip_request_t *);
|
||||
|
||||
if(!self->last_iInvite){
|
||||
/* silently ignore */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cancel 100rel timer */
|
||||
TSIP_DIALOG_TIMER_CANCEL(100rel);
|
||||
|
||||
/* Send 2xx PRACK */
|
||||
ret = send_RESPONSE(self, request, 200, "OK", tsk_false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Ringing -> (oAccept) -> Connected */
|
||||
|
@ -333,6 +442,9 @@ int s0000_Ringing_2_Connected_X_Accept(va_list *app)
|
|||
/* Update current action */
|
||||
tsip_dialog_set_curr_action(TSIP_DIALOG(self), action);
|
||||
|
||||
/* Determine whether the remote party support UPDATE */
|
||||
self->support_update = tsip_message_allowed(self->last_iInvite, "UPDATE");
|
||||
|
||||
/* start session manager */
|
||||
if(self->msession_mgr && !self->msession_mgr->started){
|
||||
ret = tmedia_session_mgr_start(self->msession_mgr);
|
||||
|
@ -341,15 +453,19 @@ int s0000_Ringing_2_Connected_X_Accept(va_list *app)
|
|||
/* send 2xx OK */
|
||||
ret = send_RESPONSE(self, self->last_iInvite, 200, "OK", tsk_true);
|
||||
|
||||
/* RFC 4825 - 9. UAS Behavior
|
||||
|
||||
UAC supports? refresher parameter refresher parameter
|
||||
in request in response
|
||||
-------------------------------------------------------
|
||||
Y none uas or uac
|
||||
Y uac uac
|
||||
Y uas uas
|
||||
*/
|
||||
/* Session Timers */
|
||||
if(self->stimers.timer.timeout){
|
||||
if(tsip_dialog_invite_stimers_isRefresher(self)){
|
||||
/* RFC 4028 - 9. UAS Behavior
|
||||
It is RECOMMENDED that this refresh be sent oncehalf the session interval has elapsed.
|
||||
Additional procedures for this refresh are described in Section 10.
|
||||
*/
|
||||
tsip_dialog_invite_stimers_schedule(self, (self->stimers.timer.timeout*1000)/2);
|
||||
}
|
||||
else{
|
||||
tsip_dialog_invite_stimers_schedule(self, (self->stimers.timer.timeout*1000));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -366,6 +482,35 @@ int s0000_Ringing_2_Terminated_X_iCANCEL(va_list *app)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Any ->(timer 100rel) -> Any */
|
||||
int s0000_Any_2_Any_X_timer100rel(va_list *app)
|
||||
{
|
||||
tsip_dialog_invite_t *self = va_arg(*app, tsip_dialog_invite_t *);
|
||||
|
||||
int ret;
|
||||
|
||||
if(!self->last_o1xxrel){
|
||||
/* silently ignore */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* resync timer */
|
||||
if((self->timer100rel.timeout *= 2) >= (64 * tsip_timers_getA())){
|
||||
TSK_DEBUG_ERROR("Sending reliable 1xx failed");
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* resend reliable 1xx */
|
||||
if((ret = tsip_dialog_response_send(TSIP_DIALOG(self), self->last_o1xxrel))){
|
||||
return ret;
|
||||
}
|
||||
else{
|
||||
/* schedule timer */
|
||||
TSIP_DIALOG_INVITE_TIMER_SCHEDULE(100rel);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// == STATE MACHINE END ==
|
||||
|
@ -393,3 +538,5 @@ int send_UNSUPPORTED(tsip_dialog_invite_t* self, const tsip_request_t* request,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -264,6 +264,7 @@ int tsip_dialog_invite_stimers_handle(tsip_dialog_invite_t* self, const tsip_mes
|
|||
if(tsk_strnullORempty(self->stimers.refresher)){
|
||||
tsk_strupdate(&self->stimers.refresher, hdr_SessionExpires->refresher_uas ? "uas" : "uac");
|
||||
}
|
||||
self->supported.timer = (self->stimers.timer.timeout != 0);
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
@ -283,6 +284,7 @@ int tsip_dialog_invite_stimers_handle(tsip_dialog_invite_t* self, const tsip_mes
|
|||
without a Session-Expires header field.
|
||||
*/
|
||||
self->stimers.timer.timeout = 0; /* turned-off */
|
||||
self->supported.timer = tsk_false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\thirdparties\win32\include;..\tinySIP\include;..\tinySAK\src;..\tinyNET\src;..\tinyHTTP\include;..\tinySIGCOMP\src;..\tinyIPSec\src;..\tinySDP\include;..\tinyMEDIA\include"
|
||||
PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_INFO;SDS_HACK;WIN32;_DEBUG;_WINDOWS;_USRDLL;TINYSIP_EXPORTS;_WIN32_WINNT 0x0501"
|
||||
PreprocessorDefinitions="DEBUG_LEVEL=DEBUG_LEVEL_INFO;WIN32;_DEBUG;_WINDOWS;_USRDLL;TINYSIP_EXPORTS;_WIN32_WINNT 0x0501"
|
||||
MinimalRebuild="true"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
|
|
Loading…
Reference in New Issue