c732d49e |
#include "tinysip/tsip_ssession.h"
#include "tinysip/tsip_action.h"
#include "tsip.h"
#include "tinysip/tsip_uri.h"
#include "tinysip/parsers/tsip_parser_uri.h"
#include "tinysip/dialogs/tsip_dialog_layer.h"
#include "tinysip/tsip_message.h"
#include "tinymedia/tmedia_defaults.h"
#include "tsk_debug.h"
/**@defgroup tsip_session_group SIP sessions
*/
/* internal function used to create session for server dialogs */
tsip_ssession_handle_t* tsip_ssession_create_2(const tsip_stack_t* stack, const struct tsip_message_s* message)
{
tsip_ssession_t* ss = tsk_null;
if(message){
char *from = tsk_null, *to = tsk_null;
/* From: */
if(message->From && message->From->uri){ /* MUST be not null */
from = tsip_uri_tostring(message->From->uri, tsk_false, tsk_false);
}
/* To: */
if(message->To && message->To->uri){ /* MUST be not null */
to = tsip_uri_tostring(message->To->uri, tsk_false, tsk_false);
}
/* create the "server-side-session" */
if((ss = tsip_ssession_create((tsip_stack_handle_t*)stack, TSIP_SSESSION_SET_NULL()))){
tsip_ssession_set(ss,
/* default values should be in conformance with the swig wrapper */
TSIP_SSESSION_SET_FROM_STR(from),
TSIP_SSESSION_SET_TO_STR(to),
TSIP_SSESSION_SET_NULL());
}
/* in all cases */
TSK_FREE(from);
TSK_FREE(to);
}
/* as the it's a "server-side-session", you are not the owner
* The end-user should call tsip_ssession_have_ownership() to check whether he has the ownership.
* The end-user should also call tsip_ssession_take_ownership() to take the ownership. This will avoid the session to be deleted by the stack
* when the associated dialog ends. */
if(ss){
ss->owner = tsk_false;
}
return ss;
}
int __tsip_ssession_set_To(tsip_ssession_t *self, const char* value)
{
tsip_uri_t* uri;
if(value && (uri = tsip_uri_parse(value, tsk_strlen(value)))){
TSK_OBJECT_SAFE_FREE(self->to);
self->to = uri;
return 0;
}
else{
TSK_DEBUG_ERROR("%s is invalid as 'To' header value", value);
return -1;
}
}
int __tsip_ssession_set_From(tsip_ssession_t *self, const char* value)
{
tsip_uri_t* uri;
if(value && (uri = tsip_uri_parse(value, tsk_strlen(value)))){
TSK_OBJECT_SAFE_FREE(self->from);
self->from = uri;
return 0;
}
else{
TSK_DEBUG_ERROR("%s is invalid as 'From' header value", value);
return -1;
}
}
int __tsip_ssession_set(tsip_ssession_t *self, va_list *app)
{
tsip_ssession_param_type_t sscurr;
tsip_msession_param_type_t mscurr;
tmedia_session_mgr_t* mgr = tsk_null;
int ret = 0;
if(!self){
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
while((sscurr = va_arg(*app, tsip_ssession_param_type_t)) != sstype_null){
switch(sscurr){
//=======
// Sip
//=======
case sstype_header:
case sstype_caps:
{ /* (const char*)NAME_STR, (const char*)VALUE_STR */
const char* name = va_arg(*app, const char *);
const char* value = va_arg(*app, const char *);
if(sscurr == sstype_header){
/* whether to SET or UNSET the header */
if(value == ((const char*)-1)){
tsk_params_remove_param(self->headers, name);
break;
}
/* From */
if(value && tsk_striequals(name, "From")){
if((ret = __tsip_ssession_set_From(self, value))){
goto bail;
}
}
/* To */
else if(value && tsk_striequals(name, "To")){
if((ret = __tsip_ssession_set_To(self, value))){
goto bail;
}
}
/* Expires */
else if(value && tsk_striequals(name, "Expires")){
/* should never happen ==> ...but who know? */
}
/* Any other */
else{
tsk_params_add_param(&self->headers, name, value);
}
}else if(sscurr == sstype_caps){
if(value == ((const char*)-1)){ /* UNSET */
tsk_params_remove_param(self->caps, name);
}
else{ /* SET */
tsk_params_add_param(&self->caps, name, value);
}
}
break;
}
case sstype_userdata:
{ /* (const void*)DATA_PTR */
self->userdata = va_arg(*app, const void *);
break;
}
case sstype_to_str:
{ /* (const char*)URI_STR */
if((ret = __tsip_ssession_set_To(self, va_arg(*app, const char *)))){
goto bail;
}
break;
}
case sstype_from_str:
{ /* (const char*)URI_STR*/
if((ret = __tsip_ssession_set_From(self, va_arg(*app, const char *)))){
goto bail;
}
break;
}
case sstype_to_obj:
{ /* (const tsip_uri_t*)URI_OBJ */
const tsip_uri_t* URI_OBJ = va_arg(*app, const tsip_uri_t *);
//URI_OBJ is the obj that has datas from URI. ej:user_name=example
if(URI_OBJ){
//Free the obj self from intro now obj whit URI_OBJ
TSK_OBJECT_SAFE_FREE(self->to);
self->to = tsk_object_ref((void*)URI_OBJ);
}
break;
}
case sstype_from_obj:
{ /* (const char*)URI_OBJ*/
const tsip_uri_t* URI_OBJ = va_arg(*app, const tsip_uri_t *);
if(URI_OBJ){
TSK_OBJECT_SAFE_FREE(self->from);
self->from = tsk_object_ref((void*)URI_OBJ);
}
break;
}
case sstype_nocontact:
{ /* (tsk_bool_t)ENABLED_BOOL */
self->no_contact = va_arg(*app, tsk_bool_t);
break;
}
case sstype_expires:
{ /* (unsigned)VALUE_UINT */
self->expires = (((int64_t)va_arg(*app, unsigned)) * 1000) /* milliseconds */;
break;
}
case sstype_silent_hangup:
{ /* sstype_silent_hangup, (tsk_bool_t)ENABLED_BOOL */
self->silent_hangup = va_arg(*app, tsk_bool_t);
break;
}
case sstype_sigcomp_id:
{ /* (const char*)COMPARTMENT_ID_STR */
const char* COMPARTMENT_ID_STR = va_arg(*app, const char*);
if(COMPARTMENT_ID_STR == (const char*)-1){
TSK_FREE(self->sigcomp_id);
}
else{
tsk_strupdate(&self->sigcomp_id, COMPARTMENT_ID_STR);
}
break;
}
case sstype_auth_ha1:
{ /* (const char*)AUTH_HA1_STR */
const char* AUTH_HA1_STR = va_arg(*app, const char*);
tsk_strupdate(&self->auth_ha1, AUTH_HA1_STR);
break;
}
case sstype_auth_impi:
{ /* (const char*)AUTH_IMPI_STR */
const char* AUTH_IMPI_STR = va_arg(*app, const char*);
tsk_strupdate(&self->auth_impi, AUTH_IMPI_STR);
break;
}
case sstype_mcptt_mbms_start_manager:
{
self->pttMCPTT.mbms.isStartMbmsManager = va_arg(*app, tsk_bool_t);
break;
}
case sstype_parent_id:
{ /* ((tsip_ssession_id_t)PARENT_ID_SSID) */
self->id_parent = va_arg(*app, tsip_ssession_id_t);
break;
}
case sstype_ws_src:
{ /* (const char*)SRC_HOST_STR, (int32_t)SRC_PORT_INT, (const char*)SRC_PROTO_STR */
const char* SRC_HOST_STR = va_arg(*app, const char*);
int32_t SRC_PORT_INT = va_arg(*app, int32_t);
const char* SRC_PROTO_STR = va_arg(*app, const char*);
tsk_strupdate(&self->ws.src.host, SRC_HOST_STR);
tsk_itoa(SRC_PORT_INT, &self->ws.src.port);
tsk_strupdate(&self->ws.src.proto, SRC_PROTO_STR);
break;
}
case sstype_media:
{
//=========
// Media
//=========
if (!mgr) {
mgr = tsip_session_get_mediamgr(self);
}
while((mscurr = va_arg(*app, tsip_msession_param_type_t)) != mstype_null){
switch(mscurr){
case mstype_set_profile:
// (tmedia_profile_t)PROFILE_ENUM
self->media.profile = va_arg(*app, tmedia_profile_t);
break;
case mstype_set_srtp_mode:
// (tmedia_srtp_mode_t)SRTP_MODE_ENUM
self->media.srtp_mode = va_arg(*app, tmedia_srtp_mode_t);
break;
case mstype_set_avpf_mode:
// (tmedia_mode_t)MEDIA_MODE_ENUM
self->media.avpf_mode = va_arg(*app, tmedia_mode_t);
break;
case mstype_set_100rel: self->media.enable_100rel = va_arg(*app, tsk_bool_t); break;
case mstype_set_ice: self->media.enable_ice = va_arg(*app, tsk_bool_t); break;
case mstype_set_ice_stun: self->media.enable_icestun = va_arg(*app, tsk_bool_t); break;
case mstype_set_ice_turn: self->media.enable_iceturn = va_arg(*app, tsk_bool_t); break;
case mstype_set_rtcp: self->media.enable_rtcp = va_arg(*app, tsk_bool_t); break;
case mstype_set_rtcpmux: self->media.enable_rtcpmux = va_arg(*app, tsk_bool_t); break;
case mstype_set_qos:
{ /* (tmedia_qos_stype_t)TYPE_ENUM, (tmedia_qos_strength_t)STRENGTH_ENUM */
self->media.qos.type = va_arg(*app, tmedia_qos_stype_t);
self->media.qos.strength = va_arg(*app, tmedia_qos_strength_t);
break;
}
case mstype_unset_qos:
{ /* */
self->media.qos.type = tmedia_qos_stype_none;
self->media.qos.strength = tmedia_qos_strength_none;
break;
}
case mstype_set_timers:
{ /* (unsigned)TIMEOUT_UINT, (const char*)REFRESHER_STR */
/* set values */
self->media.timers.timeout = va_arg(*app, unsigned);
tsk_strupdate(&self->media.timers.refresher, va_arg(*app, const char*));
break;
}
case mstype_unset_timers:
{ /* */
/* unset values */
self->media.timers.timeout = 0;
TSK_FREE(self->media.timers.refresher);
break;
}
case mstype_set_codecs:
{/* (signed)CODECS_INT */
self->media.codecs = va_arg(*app, signed);
if(mgr){ // apply now
tmedia_session_mgr_set_codecs_supported(mgr, self->media.codecs);
}
break;
}
case mstype_set_bypass_encoding:
{/* (tsk_bool_t)ENABLED_BOOL */
self->media.bypass_encoding = va_arg(*app, tsk_bool_t);
break;
}
case mstype_set_bypass_decoding:
{/* (tsk_bool_t)ENABLED_BOOL */
self->media.bypass_decoding = va_arg(*app, tsk_bool_t);
break;
}
case mstype_set_rtp_ssrc:
{/* (tmedia_type_t)MEDIA_ENUM, (uint32_t)SSRC_UINT */
tmedia_type_t MEDIA_ENUM = va_arg(*app, tmedia_type_t);
uint32_t SSRC_UINT = va_arg(*app, uint32_t);
switch(MEDIA_ENUM){
case tmedia_audio: self->media.rtp.ssrc.audio = SSRC_UINT; break;
case tmedia_video: self->media.rtp.ssrc.video = SSRC_UINT; break;
default: break;
}
break;
}
case mstype_set_msrp_cb:
{ /* (tmedia_session_msrp_cb_f)TMEDIA_SESSION_MSRP_CB_F */
self->media.msrp.callback = va_arg(*app, tmedia_session_msrp_cb_f);
break;
}
//MCPTT
case mstype_set_mcptt_cb:
{ /* (tmedia_session_mcptt_cb_f)TMEDIA_SESSION_MCPTT_CB_F */
self->media.mcptt.callback = va_arg(*app, tmedia_session_mcptt_cb_f);
break;
} |
c732d49e |
case mstype_set_mcptt_affiliation_cb:
{ /* (tmedia_session_mcptt_affiliation_cb_f)TMEDIA_SESSION_MCPTT_AFFILIATION_CB_F */
self->media.mcptt_affiliation.callback = va_arg(*app, tmedia_session_mcptt_affiliation_cb_f);
break;
}
case mstype_set_stun_server:
{ /* (const char*)HOSTNAME, (uint16_t)PORT */
const char* HOSTNAME = va_arg(*app, const char*);
uint16_t PORT = tsk_va_arg_u16(*app);
tsk_strupdate(&self->media.stun.hostname, HOSTNAME);
self->media.stun.port = PORT;
break;
}
case mstype_set_stun_cred:
{ /* (const char*)USERNAME, (const char*)PASSWORD */
const char* USERNAME = va_arg(*app, const char*);
const char* PASSWORD = va_arg(*app, const char*);
tsk_strupdate(&self->media.stun.username, USERNAME);
tsk_strupdate(&self->media.stun.password, PASSWORD);
break;
}
case mstype_set_video_fps:
{/* (signed)FPS_INT */
self->media.video_fps = va_arg(*app, signed);
break;
}
case mstype_set_video_bw_up:
{/* (signed)BW_INT */
self->media.video_bw_up = va_arg(*app, signed);
break;
}
case mstype_set_video_bw_down:
{/* (signed)BW_INT */
self->media.video_bw_down = va_arg(*app, signed);
break;
}
case mstype_set_video_prefsize:
{/* (tmedia_pref_video_size_t)PREFSIZE_ENUM */
self->media.video_pref_size = va_arg(*app, tmedia_pref_video_size_t);
break;
}
case mstype_set_poc_qoe:
{
self->media.poc_qoe.profile = va_arg(*app, tmedia_poc_qoe_profile_t);
self->media.poc_qoe.strength = va_arg(*app, tmedia_poc_qoe_profile_strength_t);
break;
}
default:{
/* va_list will be unsafe => exit */
TSK_DEBUG_ERROR("%d NOT a valid MEDIA pname", mscurr);
goto bail; }
} /* switch */
} /* while */
break;
} /* case */
default:{
/* va_list will be unsafe => exit */
TSK_DEBUG_ERROR("%d NOT a valid SIP pname", sscurr);
goto bail; }
} /* switch */
} /* while */
bail:
TSK_OBJECT_SAFE_FREE(mgr);
return ret;
}
tsip_ssession_handle_t* tsip_ssession_create(tsip_stack_handle_t *stack, ...)
{ |
c732d49e |
tsip_ssession_t* ss = tsk_null;
va_list ap;
tsip_stack_t* _stack = stack;
if(!_stack){
TSK_DEBUG_ERROR("Invalid Parameter.");
goto bail;
}
if(!(ss = tsk_object_new(tsip_ssession_def_t, stack))){
TSK_DEBUG_ERROR("Failed to create new SIP Session.");
return tsk_null;
}
va_start(ap, stack);
if(__tsip_ssession_set(ss, &ap)){
TSK_DEBUG_ERROR("Failed to set user's parameters.");
TSK_OBJECT_SAFE_FREE(ss);
va_end(ap);
goto bail;
}
va_end(ap);
/* from */
if(!ss->from && _stack->identity.impu){
ss->from = tsip_uri_clone(_stack->identity.impu, tsk_false, tsk_false);
}
/* to */
/* To value will be set by the dialog (whether to use as Request-URI). */
bail:
return ss;
}
int tsip_ssession_set(tsip_ssession_handle_t *self, ...)
{
if(self){
int ret;
va_list ap;
tsip_ssession_t *ss = self;
if(ss->id == TSIP_SSESSION_INVALID_ID){
return -2;
}
va_start(ap, self);
ret = __tsip_ssession_set(ss, &ap);
va_end(ap);
return ret;
}
else{
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
}
tsip_ssession_id_t tsip_ssession_get_id(const tsip_ssession_handle_t *self)
{
if(self){
const tsip_ssession_t *ss = self;
if(ss && ss!=tsk_null){
return ss->id;
}
}
return TSIP_SSESSION_INVALID_ID;
}
tsip_ssession_id_t tsip_ssession_get_id_parent(const tsip_ssession_handle_t *self)
{
if(self){
const tsip_ssession_t *ss = self;
return ss->id_parent;
}
return TSIP_SSESSION_INVALID_ID;
}
int tsip_ssession_take_ownership(tsip_ssession_handle_t *self)
{
if(self){
tsip_ssession_t *ss = self;
if(!ss->owner){
ss->owner = tsk_true;
/* before: only the dialog had a reference to the SIP session */
ss = tsk_object_ref(ss);
/* after: both the end-user and the dialog have their references */
return 0;
}
return -2;
}
else{
TSK_DEBUG_ERROR("Invalid parameter");
return -1;
}
}
tsk_bool_t tsip_ssession_have_ownership(const tsip_ssession_handle_t *self)
{
if(self){
const tsip_ssession_t *ss = self;
return ss->owner;
}
return tsk_false;
}
int tsip_ssession_respond(const tsip_ssession_handle_t *self, short status, const char* phrase, const void* payload, tsk_size_t size, const struct tsip_message_s* request, ...)
{
tsip_response_t *response = tsk_null;
tsip_dialog_t* dialog = tsk_null;
const tsip_ssession_t *ss = self;
int ret = -1;
if(!ss || !request){
goto bail;
}
if(!(dialog = tsip_dialog_layer_find_by_ss(ss->stack->layer_dialog, ss))){
goto bail;
}
if(!(response = tsip_dialog_response_new(TSIP_DIALOG(self), status, phrase, request))){
goto bail;
}
if(payload && size){
if((ret = tsip_message_add_content(response, tsk_null, payload, size))){
goto bail;
}
}
ret = tsip_dialog_response_send(TSIP_DIALOG(self), response);
bail:
TSK_OBJECT_SAFE_FREE(response);
TSK_OBJECT_SAFE_FREE(dialog);
return ret;
}
const void* tsip_ssession_get_userdata(const tsip_ssession_handle_t *self)
{
const tsip_ssession_t* ss = (const tsip_ssession_t*)self;
if(ss){
return ss->userdata;
}
else{
TSK_DEBUG_ERROR("Invalid parameter");
return tsk_null;
}
}
tmedia_type_t tsip_ssession_get_mediatype(const tsip_ssession_handle_t *self)
{
if(self){
return ((const tsip_ssession_t*)self)->media.type;
}
else{
TSK_DEBUG_ERROR("Invalid parameter");
return tmedia_none;
}
}
#include "tinysip/dialogs/tsip_dialog_invite.h"
tmedia_session_mgr_t* tsip_session_get_mediamgr(const tsip_ssession_handle_t *self)
{
tmedia_session_mgr_t* mgr = tsk_null; |