mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-20 12:38:09 +00:00
work in progress
This commit is contained in:
parent
80e14f6a90
commit
0267c3213f
8 changed files with 554 additions and 277 deletions
|
|
@ -21,7 +21,6 @@ liblinphone_la_SOURCES=\
|
|||
sal_eXosip2_sdp.c \
|
||||
sal_eXosip2_presence.c \
|
||||
callbacks.c \
|
||||
exevents.c sdphandler.c\
|
||||
misc.c \
|
||||
address.c \
|
||||
enum.c enum.h \
|
||||
|
|
|
|||
|
|
@ -23,28 +23,301 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
|
||||
static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
|
||||
if (lc->vtable.show)
|
||||
lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Connected."));
|
||||
call->state=LCStateAVRunning;
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_start_media_streams(lc,call);
|
||||
}
|
||||
|
||||
static void call_received(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
char *barmesg;
|
||||
int err;
|
||||
LinphoneCall *call;
|
||||
const char *from,*to;
|
||||
char *tmp;
|
||||
LinphoneAddress *from_parsed;
|
||||
|
||||
/* first check if we can answer successfully to this invite */
|
||||
if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){
|
||||
ms_message("Not present !! presence mode : %d\n",lc->presence_mode);
|
||||
if (lc->presence_mode==LINPHONE_STATUS_BUSY)
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
else if (lc->presence_mode==LINPHONE_STATUS_AWAY
|
||||
||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK
|
||||
||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE
|
||||
||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH
|
||||
||lc->presence_mode==LINPHONE_STATUS_OFFLINE)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
|
||||
sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
|
||||
else
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(op);
|
||||
return;
|
||||
}
|
||||
if (lc->call!=NULL){/*busy*/
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(op);
|
||||
return;
|
||||
}
|
||||
from=sal_op_get_from(op);
|
||||
to=sal_op_get_to(op);
|
||||
|
||||
call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),op);
|
||||
lc->call=call;
|
||||
sal_call_set_local_media_description(op,call->localdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc && sal_media_description_empty(call->resultdesc){
|
||||
sal_call_decline(op,SalReasonMedia,NULL);
|
||||
linphone_call_destroy(call);
|
||||
lc->call=NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
from_parsed=linphone_address_new(sal_op_get_from(op));
|
||||
linphone_address_clean(from_parsed);
|
||||
tmp=linphone_address_as_string(from_parsed);
|
||||
linphone_address_destroy(from_parsed);
|
||||
gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
|
||||
barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,barmesg);
|
||||
|
||||
/* play the ring */
|
||||
if (lc->sound_conf.ring_sndcard!=NULL){
|
||||
ms_message("Starting local ring...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
|
||||
}
|
||||
linphone_call_set_state(call,LCStateRinging);
|
||||
sal_call_notify_ringing(op);
|
||||
|
||||
if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp);
|
||||
ms_free(barmesg);
|
||||
ms_free(tmp);
|
||||
}
|
||||
|
||||
static void call_ringing(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
LinphoneCall *call=lc->call;
|
||||
SalMediaDescription *md;
|
||||
if (call==NULL) return;
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Remote ringing."));
|
||||
md=sal_call_get_final_media_description(h);
|
||||
if (md==NULL){
|
||||
if (lc->ringstream!=NULL) return; /*already ringing !*/
|
||||
if (lc->sound_conf.play_sndcard!=NULL){
|
||||
ms_message("Remote ringing...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard);
|
||||
}
|
||||
}else{
|
||||
/*accept early media */
|
||||
if (lc->audiostream->ticker!=NULL){
|
||||
/*streams already started */
|
||||
ms_message("Early media already started.");
|
||||
return;
|
||||
}
|
||||
sal_media_description_ref(md);
|
||||
call->resultdesc=md;
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Early media."));
|
||||
gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
ms_message("Doing early media...");
|
||||
linphone_core_start_media_streams(lc,call);
|
||||
}
|
||||
call->state=LCStateRinging;
|
||||
}
|
||||
|
||||
static void call_accepted(SalOp *h){
|
||||
static void call_accepted(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
LinphoneCall *call=lc->call;
|
||||
if (call==NULL){
|
||||
ms_warning("No call to accept.");
|
||||
return 0;
|
||||
}
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_accepted: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (call->state==LCStateAVRunning){
|
||||
return 0; /*already accepted*/
|
||||
}
|
||||
if (lc->audiostream->ticker!=NULL){
|
||||
/*case where we accepted early media */
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
|
||||
linphone_connect_incoming(lc,call);
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
|
||||
linphone_core_terminate_call(lc,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_ack(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
LinphoneCall *call=lc->call;
|
||||
if (call==NULL){
|
||||
ms_warning("No call to be ACK'd");
|
||||
return ;
|
||||
}
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_ack: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (lc->audiostream->ticker!=NULL){
|
||||
/*case where we accepted early media */
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
|
||||
linphone_connect_incoming(lc,call);
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP response received in ACK, need to abort the call");
|
||||
linphone_core_terminate_call(lc,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_updated(SalOp *){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
linphone_connect_incoming(lc,call);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_terminated(SalOp *h){
|
||||
static void call_terminated(SalOp *h, const char *from){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_terminated: ignoring.");
|
||||
return;
|
||||
}
|
||||
ms_message("Current call terminated...");
|
||||
if (lc->ringstream!=NULL) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_media_streams(lc,lc->call);
|
||||
lc->vtable.show(lc);
|
||||
lc->vtable.display_status(lc,_("Call terminated."));
|
||||
gstate_new_state(lc, GSTATE_CALL_END, NULL);
|
||||
if (lc->vtable.bye_recv!=NULL){
|
||||
LinphoneAddress *addr=linphone_address_new(from);
|
||||
char *tmp;
|
||||
linphone_address_clean(addr);
|
||||
tmp=linphone_address_as_string(from);
|
||||
lc->vtable.bye_recv(lc,tmp);
|
||||
ms_free(tmp);
|
||||
linphone_address_destroy(addr);
|
||||
}
|
||||
linphone_call_destroy(lc->call);
|
||||
lc->call=NULL;
|
||||
}
|
||||
|
||||
static void call_failure(SalOp *h, SalError error, SalReason reason, const char *details){
|
||||
static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
const char *reason="";
|
||||
char *msg486=_("User is busy.");
|
||||
char *msg480=_("User is temporarily unavailable.");
|
||||
/*char *retrymsg=_("%s. Retry after %i minute(s).");*/
|
||||
char *msg600=_("User does not want to be disturbed.");
|
||||
char *msg603=_("Call declined.");
|
||||
char* tmpmsg=msg486;
|
||||
int code;
|
||||
LinphoneCall *call=lc->call;
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_failure: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
|
||||
if (error==SalErrorNoResponse){
|
||||
if (lc->vtale.display_status)
|
||||
lc->vtable.display_status(lc,_("No response."));
|
||||
}else if (error==SalErrorProtocol){
|
||||
if (lc->vtale.display_status)
|
||||
lc->vtable.display_status(lc, details ? details : _("Error."));
|
||||
}else if (error==SalErrorFailure){
|
||||
switch(sr){
|
||||
case SalReasonDeclined:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg603);
|
||||
break;
|
||||
case SalReasonBusy:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg486);
|
||||
break;
|
||||
case SalReasonRedirect:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Redirected"));
|
||||
break;
|
||||
case SalReasonTemporarilyUnavailable:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg480);
|
||||
break;
|
||||
case SalReasonNotFound:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg404);
|
||||
break;
|
||||
case SalReasonDoNotDisturb:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,msg600);
|
||||
break;
|
||||
case SalReasonMedia:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("No common codecs"));
|
||||
break;
|
||||
default:
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Call failed."));
|
||||
}
|
||||
}
|
||||
if (lc->ringstream!=NULL) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_media_streams(lc);
|
||||
if (call!=NULL) {
|
||||
linphone_call_destroy(call);
|
||||
gstate_new_state(lc, GSTATE_CALL_ERROR, NULL);
|
||||
lc->call=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void auth_requested(SalOp *h, const char *realm, const char *username){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_root(h));
|
||||
LinphoneAuthInfo *ai=linphone_core_find_auth_info(lc);
|
||||
}
|
||||
|
||||
static void auth_success(SalOp *h, const char *realm, const char *username){
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
|
|||
linphone_core_notify_all_friends(call->core,LINPHONE_STATUS_ONTHEPHONE);
|
||||
if (linphone_core_get_firewall_policy(call->core)==LINPHONE_POLICY_USE_STUN)
|
||||
linphone_core_run_stun_tests(call->core,call);
|
||||
call->profile=rtp_profile_new("Call RTP profile");
|
||||
}
|
||||
|
||||
static void discover_mtu(LinphoneCore *lc, const char *remote){
|
||||
|
|
@ -136,6 +135,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
|
|||
LinphoneCall *call=ms_new0(LinphoneCall,1);
|
||||
call->dir=LinphoneCallOutgoing;
|
||||
call->op=sal_op_new(lc->sal);
|
||||
sal_op_set_user_pointer(call->op,lc->call);
|
||||
call->core=lc;
|
||||
linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
|
||||
call->localdesc=create_local_media_description (lc,call->localip,
|
||||
|
|
@ -150,6 +150,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
|
||||
|
||||
call->dir=LinphoneCallIncoming;
|
||||
sal_op_set_user_pointer(op,call);
|
||||
call->op=op;
|
||||
call->core=lc;
|
||||
|
||||
|
|
@ -168,7 +169,6 @@ void linphone_call_destroy(LinphoneCall *obj)
|
|||
linphone_core_notify_all_friends(obj->core,obj->core->prev_mode);
|
||||
linphone_call_log_completed(obj->log,obj);
|
||||
linphone_core_update_allocated_audio_bandwidth(obj->core);
|
||||
if (obj->profile!=NULL) rtp_profile_destroy(obj->profile);
|
||||
if (obj->op!=NULL) sal_op_release(obj->op);
|
||||
if (obj->resultdesc!=NULL) sal_media_description_unref(obj->resultdesc);
|
||||
if (obj->localdesc!=NULL) sal_media_description_unref(obj->localdesc);
|
||||
|
|
@ -910,6 +910,7 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
|
|||
lc->rpc_enable = 0;
|
||||
#endif
|
||||
lc->sal=sal_init();
|
||||
sal_set_user_pointer(lc->sal,lc);
|
||||
if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
|
||||
sal_use_session_timers(lc->sal,200);
|
||||
}
|
||||
|
|
@ -1313,7 +1314,7 @@ void linphone_core_set_sip_port(LinphoneCore *lc,int port)
|
|||
ms_free(msg);
|
||||
return;
|
||||
}
|
||||
apply_user_agent(lc->sal);
|
||||
apply_user_agent(lc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1368,7 +1369,7 @@ static void proxy_update(LinphoneCore *lc, time_t curtime){
|
|||
if (last_check==0 || (curtime-last_check)>=5){
|
||||
sal_get_default_local_ip(lc->sal,
|
||||
lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,
|
||||
,result,LINPHONE_IPADDR_SIZE);
|
||||
result,LINPHONE_IPADDR_SIZE);
|
||||
if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
|
||||
last_status=TRUE;
|
||||
ms_message("Network is up, registering now (%s)",result);
|
||||
|
|
@ -1465,14 +1466,12 @@ static void linphone_core_do_plugin_tasks(LinphoneCore *lc){
|
|||
* other liblinphone methods. In not the case make sure all liblinphone calls are
|
||||
* serialized with a mutex.
|
||||
**/
|
||||
void linphone_core_iterate(LinphoneCore *lc)
|
||||
{
|
||||
eXosip_event_t *ev;
|
||||
bool_t disconnected=FALSE;
|
||||
void linphone_core_iterate(LinphoneCore *lc){
|
||||
int disconnect_timeout = linphone_core_get_nortp_timeout(lc);
|
||||
time_t curtime=time(NULL);
|
||||
int elapsed;
|
||||
bool_t one_second_elapsed=FALSE;
|
||||
bool_t disconnected=FALSE;
|
||||
|
||||
if (curtime-lc->prevtime>=1){
|
||||
lc->prevtime=curtime;
|
||||
|
|
@ -1539,7 +1538,7 @@ void linphone_core_iterate(LinphoneCore *lc)
|
|||
|
||||
bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAddress **real_parsed_url, char **route){
|
||||
enum_lookup_res_t *enumres=NULL;
|
||||
osip_to_t *parsed_url=NULL;
|
||||
LinphoneAddress *parsed_url=NULL;
|
||||
char *enum_domain=NULL;
|
||||
LinphoneProxyConfig *proxy;
|
||||
char *tmpurl;
|
||||
|
|
@ -1590,7 +1589,7 @@ bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAd
|
|||
if (real_parsed_url!=NULL) *real_parsed_url=parsed_url;
|
||||
else linphone_address_destroy(parsed_url);
|
||||
if (tmproute) *route=ms_strdup(tmproute);
|
||||
else *route=guess_route_if_any(lc,*real_parsed_url);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
/* else we could not do anything with url given by user, so display an error */
|
||||
|
|
@ -1742,9 +1741,9 @@ int linphone_core_invite(LinphoneCore *lc, const char *url)
|
|||
if (err<0){
|
||||
ms_warning("Could not initiate call.");
|
||||
lc->vtable.display_status(lc,_("could not call"));
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_call_destroy(call);
|
||||
lc->call=NULL;
|
||||
linphone_core_stop_media_streams(lc);
|
||||
}else gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, url);
|
||||
|
||||
goto end;
|
||||
|
|
@ -1759,7 +1758,6 @@ int linphone_core_refer(LinphoneCore *lc, const char *url)
|
|||
char *real_url=NULL;
|
||||
LinphoneAddress *real_parsed_url=NULL;
|
||||
LinphoneCall *call;
|
||||
osip_message_t *msg=NULL;
|
||||
char *route;
|
||||
if (!linphone_core_interpret_url(lc,url,&real_parsed_url, &route)){
|
||||
/* bad url */
|
||||
|
|
@ -1773,11 +1771,8 @@ int linphone_core_refer(LinphoneCore *lc, const char *url)
|
|||
}
|
||||
lc->call=NULL;
|
||||
real_url=linphone_address_as_string (real_parsed_url);
|
||||
eXosip_call_build_refer(call->did, real_url, &msg);
|
||||
sal_refer(call->op,real_url);
|
||||
ms_free(real_url);
|
||||
eXosip_lock();
|
||||
eXosip_call_send_request(call->did, msg);
|
||||
eXosip_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1793,79 +1788,6 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef VINCENT_MAURY_RSVP
|
||||
/* on=1 for RPC_ENABLE=1...*/
|
||||
int linphone_core_set_rpc_mode(LinphoneCore *lc, int on)
|
||||
{
|
||||
if (on==1)
|
||||
printf("RPC_ENABLE set on\n");
|
||||
else
|
||||
printf("RPC_ENABLE set off\n");
|
||||
lc->rpc_enable = (on==1);
|
||||
/* need to tell eXosip the new setting */
|
||||
if (eXosip_set_rpc_mode (lc->rpc_enable)!=0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* on=1 for RSVP_ENABLE=1...*/
|
||||
int linphone_core_set_rsvp_mode(LinphoneCore *lc, int on)
|
||||
{
|
||||
if (on==1)
|
||||
printf("RSVP_ENABLE set on\n");
|
||||
else
|
||||
printf("RSVP_ENABLE set off\n");
|
||||
lc->rsvp_enable = (on==1);
|
||||
/* need to tell eXosip the new setting */
|
||||
if (eXosip_set_rsvp_mode (lc->rsvp_enable)!=0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* answer : 1 for yes, 0 for no */
|
||||
int linphone_core_change_qos(LinphoneCore *lc, int answer)
|
||||
{
|
||||
char *sdpmesg;
|
||||
if (lc->call==NULL){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lc->rsvp_enable && answer==1)
|
||||
{
|
||||
/* answer is yes, local setting is with qos, so
|
||||
* the user chose to continue with no qos ! */
|
||||
/* so switch in normal mode : ring and 180 */
|
||||
lc->rsvp_enable = 0; /* no more rsvp */
|
||||
eXosip_set_rsvp_mode (lc->rsvp_enable);
|
||||
/* send 180 */
|
||||
eXosip_lock();
|
||||
eXosip_answer_call(lc->call->did,180,NULL);
|
||||
eXosip_unlock();
|
||||
/* play the ring */
|
||||
ms_message("Starting local ring...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.local_ring,
|
||||
2000,ms_snd_card_manager_get_card(ms_snd_card_manager_get(),lc->sound_conf.ring_sndcard));
|
||||
}
|
||||
else if (!lc->rsvp_enable && answer==1)
|
||||
{
|
||||
/* switch to QoS mode on : answer 183 session progress */
|
||||
lc->rsvp_enable = 1;
|
||||
eXosip_set_rsvp_mode (lc->rsvp_enable);
|
||||
/* take the sdp already computed, see osipuacb.c */
|
||||
sdpmesg=lc->call->sdpctx->answerstr;
|
||||
eXosip_lock();
|
||||
eXosip_answer_call_with_body(lc->call->did,183,"application/sdp",sdpmesg);
|
||||
eXosip_unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* decline offer (603) */
|
||||
linphone_core_terminate_call(lc, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call){
|
||||
SalMediaDescription *md=call->localdesc;
|
||||
lc->audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc));
|
||||
|
|
@ -1893,7 +1815,7 @@ void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call){
|
|||
rtp_session_set_transports(lc->audiostream->session,lc->a_rtp,lc->a_rtcp);
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (lc->video_conf.display || lc->video_conf.capture && md->streams[1].port>0)
|
||||
if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0)
|
||||
lc->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc));
|
||||
#else
|
||||
lc->videostream=NULL;
|
||||
|
|
@ -1973,99 +1895,129 @@ static void post_configure_audio_streams(LinphoneCore *lc){
|
|||
}
|
||||
}
|
||||
|
||||
static RtpProfile *make_profile(LinphoneCore *lc, SalStreamDescription *desc, int *used_pt){
|
||||
int bw;
|
||||
MSList *elem;
|
||||
RtpProfile *prof=rtp_profile_new("Call profile");
|
||||
bool_t first=TRUE;
|
||||
if (desc->type==SalAudio){
|
||||
bw=get_min_bandwidth(lc->up_audio_bw,desc->bandwidth);
|
||||
}
|
||||
else bw=get_min_bandwidth(lc->up_video_bw,desc->bandwidth);
|
||||
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
|
||||
PayloadType *pt=(PayloadType*)elem->data;
|
||||
if (bw>0) pt->normal_bitrate=bw*1000;
|
||||
else if (desc->type==SalAudio){
|
||||
pt->normal_bitrate=-1;
|
||||
}
|
||||
if (first) {
|
||||
*used_pt=payload_type_get_number(pt);
|
||||
first=FALSE;
|
||||
}
|
||||
if (desc->ptime>0){
|
||||
char tmp[40];
|
||||
snprintf(tmp,sizeof(tmp),"ptime=%i",desc->ptime);
|
||||
payload_type_append_send_fmtp(pt,tmp);
|
||||
}
|
||||
rtp_profile_set_payload(prof,payload_type_get_number(pt),pt);
|
||||
}
|
||||
return prof;
|
||||
}
|
||||
|
||||
void linphone_core_start_media_streams(LinphoneCore *lc, LinphoneCall *call){
|
||||
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
|
||||
const char *tool="linphone-" LINPHONE_VERSION;
|
||||
char *cname;
|
||||
int used_pt=-1;
|
||||
/* adjust rtp jitter compensation. It must be at least the latency of the sound card */
|
||||
int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp);
|
||||
|
||||
if (call->media_start_time==0) call->media_start_time=time(NULL);
|
||||
|
||||
cname=ortp_strdup_printf("%s@%s",me->url->username,me->url->host);
|
||||
cname=linphone_address_as_string_uri_only(me);
|
||||
{
|
||||
StreamParams *audio_params=&call->audio_params;
|
||||
if (!lc->use_files){
|
||||
MSSndCard *playcard=lc->sound_conf.play_sndcard;
|
||||
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
|
||||
if (playcard==NULL) {
|
||||
ms_warning("No card defined for playback !");
|
||||
goto end;
|
||||
SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalAudio);
|
||||
if (stream){
|
||||
call->audio_profile=make_profile(lc,stream,&used_pt);
|
||||
if (!lc->use_files){
|
||||
MSSndCard *playcard=lc->sound_conf.play_sndcard;
|
||||
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
|
||||
if (playcard==NULL) {
|
||||
ms_warning("No card defined for playback !");
|
||||
goto end;
|
||||
}
|
||||
if (captcard==NULL) {
|
||||
ms_warning("No card defined for capture !");
|
||||
goto end;
|
||||
}
|
||||
audio_stream_start_now(
|
||||
lc->audiostream,
|
||||
call->audio_profile,
|
||||
stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr,
|
||||
stream->port,
|
||||
stream->port+1,
|
||||
used_pt,
|
||||
jitt_comp,
|
||||
playcard,
|
||||
captcard,
|
||||
linphone_core_echo_cancellation_enabled(lc));
|
||||
}else{
|
||||
audio_stream_start_with_files(
|
||||
lc->audiostream,
|
||||
call->audio_profile,
|
||||
stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr,
|
||||
stream->port,
|
||||
stream->port+1,
|
||||
used_pt,
|
||||
100,
|
||||
lc->play_file,
|
||||
lc->rec_file);
|
||||
}
|
||||
if (captcard==NULL) {
|
||||
ms_warning("No card defined for capture !");
|
||||
goto end;
|
||||
}
|
||||
if (audio_params->relay_session_id!=NULL)
|
||||
audio_stream_set_relay_session_id(lc->audiostream,audio_params->relay_session_id);
|
||||
audio_stream_start_now(
|
||||
lc->audiostream,
|
||||
call->profile,
|
||||
audio_params->remoteaddr,
|
||||
audio_params->remoteport,
|
||||
audio_params->remotertcpport,
|
||||
audio_params->pt,
|
||||
jitt_comp,
|
||||
playcard,
|
||||
captcard,
|
||||
linphone_core_echo_cancellation_enabled(lc));
|
||||
}else{
|
||||
audio_stream_start_with_files(
|
||||
lc->audiostream,
|
||||
call->profile,
|
||||
audio_params->remoteaddr,
|
||||
audio_params->remoteport,
|
||||
audio_params->remotertcpport,
|
||||
audio_params->pt,
|
||||
100,
|
||||
lc->play_file,
|
||||
lc->rec_file);
|
||||
}
|
||||
post_configure_audio_streams(lc);
|
||||
audio_stream_set_rtcp_information(lc->audiostream, cname, tool);
|
||||
post_configure_audio_streams(lc);
|
||||
audio_stream_set_rtcp_information(lc->audiostream, cname, tool);
|
||||
}else ms_warning("No audio stream defined ?");
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
{
|
||||
SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalVideo);
|
||||
/* shutdown preview */
|
||||
if (lc->previewstream!=NULL) {
|
||||
video_preview_stop(lc->previewstream);
|
||||
lc->previewstream=NULL;
|
||||
}
|
||||
if (lc->video_conf.display || lc->video_conf.capture) {
|
||||
StreamParams *video_params=&call->video_params;
|
||||
|
||||
if (video_params->remoteport>0){
|
||||
if (video_params->relay_session_id!=NULL)
|
||||
video_stream_set_relay_session_id(lc->videostream,video_params->relay_session_id);
|
||||
video_stream_set_sent_video_size(lc->videostream,linphone_core_get_preferred_video_size(lc));
|
||||
video_stream_enable_self_view(lc->videostream,lc->video_conf.selfview);
|
||||
if (lc->video_conf.display && lc->video_conf.capture)
|
||||
video_stream_start(lc->videostream,
|
||||
call->profile, video_params->remoteaddr, video_params->remoteport,
|
||||
video_params->remotertcpport,
|
||||
video_params->pt, jitt_comp, lc->video_conf.device);
|
||||
else if (lc->video_conf.display)
|
||||
video_stream_recv_only_start(lc->videostream,
|
||||
call->profile, video_params->remoteaddr, video_params->remoteport,
|
||||
video_params->pt, jitt_comp);
|
||||
else if (lc->video_conf.capture)
|
||||
video_stream_send_only_start(lc->videostream,
|
||||
call->profile, video_params->remoteaddr, video_params->remoteport,
|
||||
video_params->remotertcpport,
|
||||
video_params->pt, jitt_comp, lc->video_conf.device);
|
||||
video_stream_set_rtcp_information(lc->videostream, cname,tool);
|
||||
}
|
||||
if (stream && (lc->video_conf.display || lc->video_conf.capture)) {
|
||||
const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr;
|
||||
call->video_profile=make_profile(lc,stream,&used_pt);
|
||||
video_stream_set_sent_video_size(lc->videostream,linphone_core_get_preferred_video_size(lc));
|
||||
video_stream_enable_self_view(lc->videostream,lc->video_conf.selfview);
|
||||
if (lc->video_conf.display && lc->video_conf.capture)
|
||||
video_stream_start(lc->videostream,
|
||||
call->video_profile, addr, stream->port,
|
||||
stream->port+1,
|
||||
used_pt, jitt_comp, lc->video_conf.device);
|
||||
else if (lc->video_conf.display)
|
||||
video_stream_recv_only_start(lc->videostream,
|
||||
call->video_profile, addr, stream->port,
|
||||
used_pt, jitt_comp);
|
||||
else if (lc->video_conf.capture)
|
||||
video_stream_send_only_start(lc->videostream,
|
||||
call->video_profile, addr, stream->port,
|
||||
stream->port+1,
|
||||
used_pt, jitt_comp, lc->video_conf.device);
|
||||
video_stream_set_rtcp_information(lc->videostream, cname,tool);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
goto end;
|
||||
end:
|
||||
ms_free(cname);
|
||||
linphone_address_destroy(me);
|
||||
lc->call->state=LCStateAVRunning;
|
||||
ms_free(cname);
|
||||
linphone_address_destroy(me);
|
||||
lc->call->state=LCStateAVRunning;
|
||||
}
|
||||
|
||||
void linphone_core_stop_media_streams(LinphoneCore *lc){
|
||||
void linphone_core_stop_media_streams(LinphoneCore *lc, LinphoneCall *call){
|
||||
if (lc->audiostream!=NULL) {
|
||||
audio_stream_stop(lc->audiostream);
|
||||
lc->audiostream=NULL;
|
||||
|
|
@ -2086,6 +2038,14 @@ void linphone_core_stop_media_streams(LinphoneCore *lc){
|
|||
}
|
||||
}
|
||||
#endif
|
||||
if (call->audio_profile){
|
||||
rtp_profile_destroy(call->audio_profile);
|
||||
call->audio_profile=NULL;
|
||||
}
|
||||
if (call->video_profile){
|
||||
rtp_profile_destroy(call->video_profile);
|
||||
call->video_profile=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2104,17 +2064,14 @@ void linphone_core_stop_media_streams(LinphoneCore *lc){
|
|||
**/
|
||||
int linphone_core_accept_call(LinphoneCore *lc, const char *url)
|
||||
{
|
||||
char *sdpmesg;
|
||||
osip_message_t *msg=NULL;
|
||||
LinphoneCall *call=lc->call;
|
||||
int err;
|
||||
bool_t offering=FALSE;
|
||||
|
||||
const char *contact=NULL;
|
||||
|
||||
if (call==NULL){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lc->call->state==LCStateAVRunning){
|
||||
if (call->state==LCStateAVRunning){
|
||||
/*call already accepted*/
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -2126,42 +2083,22 @@ int linphone_core_accept_call(LinphoneCore *lc, const char *url)
|
|||
ms_message("ring stopped");
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
/* sends a 200 OK */
|
||||
err=eXosip_call_build_answer(call->tid,200,&msg);
|
||||
if (err<0 || msg==NULL){
|
||||
ms_error("Fail to build answer for call: err=%i",err);
|
||||
return -1;
|
||||
}
|
||||
if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
|
||||
if (call->supports_session_timers) osip_message_set_supported(msg, "timer");
|
||||
}
|
||||
|
||||
/*try to be best-effort in giving real local or routable contact address,
|
||||
except when the user choosed to override the ipaddress */
|
||||
if (linphone_core_get_firewall_policy(lc)!=LINPHONE_POLICY_USE_NAT_ADDRESS)
|
||||
fix_contact(lc,msg,call->localip,NULL);
|
||||
/*if a sdp answer is computed, send it, else send an offer */
|
||||
sdpmesg=call->sdpctx->answerstr;
|
||||
if (sdpmesg==NULL){
|
||||
offering=TRUE;
|
||||
ms_message("generating sdp offer");
|
||||
sdpmesg=sdp_context_get_offer(call->sdpctx);
|
||||
|
||||
if (sdpmesg==NULL){
|
||||
ms_error("fail to generate sdp offer !");
|
||||
return -1;
|
||||
}
|
||||
linphone_set_sdp(msg,sdpmesg);
|
||||
linphone_core_init_media_streams(lc);
|
||||
}else{
|
||||
linphone_set_sdp(msg,sdpmesg);
|
||||
}
|
||||
eXosip_lock();
|
||||
eXosip_call_send_answer(call->tid,200,msg);
|
||||
eXosip_unlock();
|
||||
contact=get_fixed_contact(lc,call->localip,NULL);
|
||||
if (contact)
|
||||
sal_op_set_contact(call->op,contact);
|
||||
|
||||
sal_call_accept(call->op);
|
||||
lc->vtable.display_status(lc,_("Connected."));
|
||||
gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
|
||||
|
||||
if (!offering) linphone_core_start_media_streams(lc, lc->call);
|
||||
call->resultdesc=sal_call_get_final_media_description(call->op);
|
||||
if (call->resultdesc){
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
linphone_core_start_media_streams(lc, call);
|
||||
}
|
||||
ms_message("call answered.");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2181,17 +2118,14 @@ int linphone_core_terminate_call(LinphoneCore *lc, const char *url)
|
|||
return -1;
|
||||
}
|
||||
lc->call=NULL;
|
||||
|
||||
eXosip_lock();
|
||||
eXosip_call_terminate(call->cid,call->did);
|
||||
eXosip_unlock();
|
||||
sal_call_terminate(call->op);
|
||||
|
||||
/*stop ringing*/
|
||||
if (lc->ringstream!=NULL) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_media_streams(lc);
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
lc->vtable.display_status(lc,_("Call ended") );
|
||||
gstate_new_state(lc, GSTATE_CALL_END, NULL);
|
||||
linphone_call_destroy(call);
|
||||
|
|
@ -2243,22 +2177,13 @@ void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,
|
|||
const char *contact,
|
||||
LinphoneOnlineStatus presence_mode)
|
||||
{
|
||||
int contactok=-1;
|
||||
if (minutes_away>0) lc->minutes_away=minutes_away;
|
||||
if (contact!=NULL) {
|
||||
osip_from_t *url;
|
||||
osip_from_init(&url);
|
||||
contactok=osip_from_parse(url,contact);
|
||||
if (contactok>=0) {
|
||||
ms_message("contact url is correct.");
|
||||
}
|
||||
osip_from_free(url);
|
||||
|
||||
}
|
||||
if (contactok>=0){
|
||||
if (lc->alt_contact!=NULL) ms_free(lc->alt_contact);
|
||||
lc->alt_contact=ms_strdup(contact);
|
||||
|
||||
if (lc->alt_contact!=NULL) {
|
||||
ms_free(lc->alt_contact);
|
||||
lc->alt_contact=NULL;
|
||||
}
|
||||
if (contact) lc->alt_contact=ms_strdup(contact);
|
||||
if (lc->presence_mode!=presence_mode){
|
||||
linphone_core_notify_all_friends(lc,presence_mode);
|
||||
/*
|
||||
|
|
@ -2270,7 +2195,6 @@ void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,
|
|||
}
|
||||
lc->prev_mode=lc->presence_mode;
|
||||
lc->presence_mode=presence_mode;
|
||||
|
||||
}
|
||||
|
||||
LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc){
|
||||
|
|
@ -2642,7 +2566,7 @@ bool_t linphone_core_agc_enabled(const LinphoneCore *lc){
|
|||
* @param dtmf The dtmf name specified as a char, such as '0', '#' etc...
|
||||
*
|
||||
**/
|
||||
void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf)
|
||||
void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf)
|
||||
{
|
||||
/*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/
|
||||
if (linphone_core_get_use_rfc2833_for_dtmf(lc)!=0 || linphone_core_get_use_info_for_dtmf(lc)==0)
|
||||
|
|
@ -2656,26 +2580,13 @@ void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf)
|
|||
ms_error("we cannot send RFC2833 dtmf when we are not in communication");
|
||||
}
|
||||
}
|
||||
if (linphone_core_get_use_info_for_dtmf(lc)!=0)
|
||||
{
|
||||
char dtmf_body[1000];
|
||||
char clen[10];
|
||||
osip_message_t *msg=NULL;
|
||||
if (linphone_core_get_use_info_for_dtmf(lc)!=0){
|
||||
/* Out of Band DTMF (use INFO method) */
|
||||
LinphoneCall *call=lc->call;
|
||||
if (call==NULL){
|
||||
return;
|
||||
}
|
||||
eXosip_call_build_info(call->did,&msg);
|
||||
snprintf(dtmf_body, 999, "Signal=%c\r\nDuration=250\r\n", dtmf);
|
||||
osip_message_set_body(msg,dtmf_body,strlen(dtmf_body));
|
||||
osip_message_set_content_type(msg,"application/dtmf-relay");
|
||||
snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body));
|
||||
osip_message_set_content_length(msg,clen);
|
||||
|
||||
eXosip_lock();
|
||||
eXosip_call_send_request(call->did,msg);
|
||||
eXosip_unlock();
|
||||
sal_call_send_dtmf(call->op,dtmf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2742,7 +2653,7 @@ static void apply_nat_settings(LinphoneCore *lc){
|
|||
if (err!=0){
|
||||
wmsg=ortp_strdup_printf(_("Invalid nat address '%s' : %s"),
|
||||
addr, gai_strerror(err));
|
||||
ms_warning(wmsg); // what is this for ?
|
||||
ms_warning("%s",wmsg); // what is this for ?
|
||||
lc->vtable.display_warning(lc, wmsg);
|
||||
ms_free(wmsg);
|
||||
ms_free(tmp);
|
||||
|
|
@ -2756,22 +2667,16 @@ static void apply_nat_settings(LinphoneCore *lc){
|
|||
if (lc->net_conf.firewall_policy==LINPHONE_POLICY_USE_NAT_ADDRESS){
|
||||
if (tmp!=NULL){
|
||||
if (!lc->net_conf.nat_sdp_only){
|
||||
eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,tmp);
|
||||
/* the following does not work in all cases */
|
||||
/*
|
||||
eXosip_masquerade_contact(tmp,lc->sip_conf.sip_port);
|
||||
*/
|
||||
sal_masquerade(lc->sal,tmp);
|
||||
}
|
||||
ms_free(tmp);
|
||||
}
|
||||
else{
|
||||
eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,NULL);
|
||||
eXosip_masquerade_contact("",0);
|
||||
sal_masquerade(lc->sal,NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,NULL);
|
||||
eXosip_masquerade_contact("",0);
|
||||
sal_masquerade(lc->sal,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3197,23 +3102,17 @@ void sip_config_uninit(LinphoneCore *lc)
|
|||
linphone_proxy_config_edit(cfg); /* to unregister */
|
||||
}
|
||||
|
||||
if (exosip_running)
|
||||
{
|
||||
if (lc->sal){
|
||||
int i;
|
||||
for (i=0;i<20;i++)
|
||||
{
|
||||
eXosip_event_t *ev;
|
||||
while((ev=eXosip_event_wait(0,0))!=NULL){
|
||||
linphone_core_process_event(lc,ev);
|
||||
}
|
||||
eXosip_automatic_action();
|
||||
for (i=0;i<20;i++){
|
||||
sal_iterate(lc->sal);
|
||||
#ifndef WIN32
|
||||
usleep(100000);
|
||||
usleep(100000);
|
||||
#else
|
||||
Sleep(100);
|
||||
Sleep(100);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linphone_proxy_config_write_to_config_file(lc->config,NULL,i); /*mark the end */
|
||||
|
||||
|
|
@ -3222,6 +3121,8 @@ void sip_config_uninit(LinphoneCore *lc)
|
|||
linphone_auth_info_write_config(lc->config,ai,i);
|
||||
}
|
||||
linphone_auth_info_write_config(lc->config,NULL,i); /* mark the end */
|
||||
sal_uninit(lc->sal);
|
||||
lc->sal=NULL;
|
||||
}
|
||||
|
||||
void rtp_config_uninit(LinphoneCore *lc)
|
||||
|
|
@ -3341,7 +3242,6 @@ static void linphone_core_uninit(LinphoneCore *lc)
|
|||
linphone_core_free_payload_types();
|
||||
|
||||
ortp_exit();
|
||||
eXosip_quit();
|
||||
exosip_running=FALSE;
|
||||
gstate_new_state(lc, GSTATE_POWER_OFF, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ typedef struct _LinphoneCall
|
|||
SalMediaDescription *localdesc;
|
||||
SalMediaDescription *resultdesc;
|
||||
LinphoneCallDir dir;
|
||||
struct _RtpProfile *profile; /*points to the local_profile or to the remote "guessed" profile*/
|
||||
struct _RtpProfile *audio_profile;
|
||||
struct _RtpProfile *video_profile;
|
||||
struct _LinphoneCallLog *log;
|
||||
SalOp *op;
|
||||
char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
|
||||
|
|
@ -87,7 +88,7 @@ void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call);
|
|||
void linphone_call_log_destroy(LinphoneCallLog *cl);
|
||||
|
||||
|
||||
void linphone_core_init_media_streams(LinphoneCore *lc);
|
||||
void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos);
|
||||
|
||||
|
|
@ -112,8 +113,8 @@ bool_t host_has_ipv6_network();
|
|||
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret);
|
||||
|
||||
static inline int get_min_bandwidth(int dbw, int ubw){
|
||||
if (dbw<0) return ubw;
|
||||
if (ubw<0) return dbw;
|
||||
if (dbw<=0) return ubw;
|
||||
if (ubw<=0) return dbw;
|
||||
return MIN(dbw,ubw);
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +166,7 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char
|
|||
|
||||
/*internal use only */
|
||||
void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
|
||||
void linphone_core_stop_media_streams(LinphoneCore *lc);
|
||||
void linphone_core_stop_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
|
||||
const char * linphone_core_get_identity(LinphoneCore *lc);
|
||||
const char * linphone_core_get_route(LinphoneCore *lc);
|
||||
bool_t linphone_core_interpret_url(LinphoneCore *lc, const char *url, LinphoneAddress **real_parsed_url, char **route);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
SalMediaDescription *sal_media_description_new(){
|
||||
SalMediaDescription *md=ms_new0(SalMediaDescription,1);
|
||||
md->refcount=1;
|
||||
return md;
|
||||
}
|
||||
|
||||
static void sal_media_description_destroy(SalMediaDescription *md){
|
||||
|
|
@ -60,6 +61,14 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool_t sal_media_description_empty(SalMediaDescription *md){
|
||||
int i;
|
||||
for(i=0;i<md->nstreams;++i){
|
||||
SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->port!=0) return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void assign_string(char **str, const char *arg){
|
||||
if (*str){
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ void sal_address_destroy(SalAddress *u);
|
|||
|
||||
Sal * sal_init();
|
||||
void sal_uninit(Sal* sal);
|
||||
void sal_set_user_pointer(Sal *sal, void *user_data);
|
||||
void *sal_get_user_pointer(const Sal *sal);
|
||||
|
||||
typedef enum {
|
||||
SalTransportDatagram,
|
||||
|
|
@ -103,6 +105,7 @@ typedef struct SalMediaDescription{
|
|||
SalMediaDescription *sal_media_description_new();
|
||||
void sal_media_description_ref(SalMediaDescription *md);
|
||||
void sal_media_description_unref(SalMediaDescription *md);
|
||||
bool_t sal_media_description_empty(SalMediaDescription *md);
|
||||
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
|
||||
SalMediaProto proto, SalStreamType type);
|
||||
|
||||
|
|
@ -121,7 +124,7 @@ typedef struct SalOpBase{
|
|||
|
||||
typedef enum SalError{
|
||||
SalErrorNoResponse,
|
||||
SalErrorMedia,
|
||||
SalErrorProtocol,
|
||||
SalErrorFailure, /* see SalReason for more details */
|
||||
SalErrorUnknown
|
||||
} SalError;
|
||||
|
|
@ -133,6 +136,7 @@ typedef enum SalReason{
|
|||
SalReasonTemporarilyUnavailable,
|
||||
SalReasonNotFound,
|
||||
SalReasonDoNotDisturb,
|
||||
SalReasonMedia,
|
||||
SalReasonForbidden,
|
||||
SalReasonUnknown
|
||||
}SalReason;
|
||||
|
|
@ -155,7 +159,7 @@ typedef void (*SalOnCallRinging)(SalOp *op);
|
|||
typedef void (*SalOnCallAccepted)(SalOp *op);
|
||||
typedef void (*SalOnCallAck)(SalOp *op);
|
||||
typedef void (*SalOnCallUpdated)(SalOp *op);
|
||||
typedef void (*SalOnCallTerminated)(SalOp *op);
|
||||
typedef void (*SalOnCallTerminated)(SalOp *op, const char *from);
|
||||
typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details);
|
||||
typedef void (*SalOnAuthRequested)(SalOp *op, const char *realm, const char *username);
|
||||
typedef void (*SalOnAuthSuccess)(SalOp *op, const char *realm, const char *username);
|
||||
|
|
@ -200,6 +204,7 @@ typedef struct SalAuthInfo{
|
|||
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs);
|
||||
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure);
|
||||
void sal_set_user_agent(Sal *ctx, const char *user_agent);
|
||||
void sal_masquerade(Sal *ctx, const char *ip);
|
||||
void sal_use_session_timers(Sal *ctx, int expires);
|
||||
int sal_iterate(Sal *sal);
|
||||
|
||||
|
|
@ -223,9 +228,12 @@ void *sal_op_get_user_pointer(const SalOp *op);
|
|||
/*Call API*/
|
||||
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
|
||||
int sal_call(SalOp *h, const char *from, const char *to);
|
||||
int sal_call_notify_ringing(SalOp *h);
|
||||
int sal_call_accept(SalOp*h);
|
||||
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
|
||||
const SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
|
||||
SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
|
||||
int sal_refer(SalOp *h, const char *refer_to);
|
||||
int sal_call_send_dtmf(SalOp *h, char dtmf);
|
||||
int sal_call_terminate(SalOp *h);
|
||||
|
||||
/*Registration*/
|
||||
|
|
|
|||
|
|
@ -134,6 +134,18 @@ void sal_uninit(Sal* sal){
|
|||
ms_free(sal);
|
||||
}
|
||||
|
||||
void sal_set_user_pointer(Sal *sal, void *user_data){
|
||||
sal->up=user_data;
|
||||
}
|
||||
|
||||
void *sal_get_user_pointer(const Sal *sal){
|
||||
return sal->up;
|
||||
}
|
||||
|
||||
void sal_masquerade(Sal *ctx, const char *ip){
|
||||
eXosip_set_option(EXOSIP_OPT_SET_IPV4_FOR_GATEWAY,ip);
|
||||
}
|
||||
|
||||
static void unimplemented_stub(){
|
||||
ms_warning("Unimplemented SAL callback");
|
||||
}
|
||||
|
|
@ -293,8 +305,16 @@ int sal_call(SalOp *h, const char *from, const char *to){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sal_call_notify_ringing(SalOp *h){
|
||||
eXosip_lock();
|
||||
eXosip_call_send_answer(h->tid,180,NULL);
|
||||
eXosip_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_call_accept(SalOp * h){
|
||||
osip_message_t *msg;
|
||||
const char *contact=sal_op_get_contact(h);
|
||||
/* sends a 200 OK */
|
||||
int err=eXosip_call_build_answer(h->tid,200,&msg);
|
||||
if (err<0 || msg==NULL){
|
||||
|
|
@ -304,6 +324,8 @@ int sal_call_accept(SalOp * h){
|
|||
if (h->base.root->session_expires!=0){
|
||||
if (h->supports_session_timers) osip_message_set_supported(msg, "timer");
|
||||
}
|
||||
|
||||
if (contact) osip_message_set_contact(msg,contact);
|
||||
|
||||
if (h->base.local_media){
|
||||
/*this is the case where we received an invite without SDP*/
|
||||
|
|
@ -320,18 +342,80 @@ int sal_call_accept(SalOp * h){
|
|||
return 0;
|
||||
}
|
||||
|
||||
const SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
|
||||
int sal_call_decline(SalOp *h, SalReason reason, const char *redirect){
|
||||
if (reason==SalReasonBusy){
|
||||
eXosip_lock();
|
||||
eXosip_call_send_answer(h->tid,486,NULL);
|
||||
eXosip_unlock();
|
||||
}
|
||||
else if (reason==SalReasonTemporarilyUnavailable){
|
||||
eXosip_lock();
|
||||
eXosip_call_send_answer(h->tid,480,NULL);
|
||||
eXosip_unlock();
|
||||
}else if (reason==SalReasonDoNotDisturb){
|
||||
eXosip_lock();
|
||||
eXosip_call_send_answer(h->tid,600,NULL);
|
||||
eXosip_unlock();
|
||||
}else if (reason==SalReasonMedia){
|
||||
eXosip_lock();
|
||||
eXosip_call_send_answer(h->tid,415,NULL);
|
||||
eXosip_unlock();
|
||||
}else if (redirect!=NULL && reason==SalReasonRedirect){
|
||||
osip_message_t *msg;
|
||||
int code;
|
||||
if (strstr(redirect,"sip:")!=0) code=302;
|
||||
else code=380;
|
||||
eXosip_lock();
|
||||
eXosip_call_build_answer(h->tid,code,&msg);
|
||||
osip_message_set_contact(msg,redirect);
|
||||
eXosip_call_send_answer(h->tid,code,msg);
|
||||
eXosip_unlock();
|
||||
}else sal_call_terminate(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
|
||||
if (h->base.local_media && h->base.remote_media && !h->result){
|
||||
sdp_process(h);
|
||||
}
|
||||
return h->result;
|
||||
}
|
||||
|
||||
int sal_refer(SalOp *h, const char *refer_to){
|
||||
osip_message_t *msg=NULL;
|
||||
int err=0;
|
||||
eXosip_lock();
|
||||
eXosip_call_build_refer(h->did,refer_to, &msg);
|
||||
if (msg) err=eXosip_call_send_request(h->did, msg);
|
||||
else err=-1;
|
||||
eXosip_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
int sal_call_send_dtmf(SalOp *h, char dtmf){
|
||||
osip_message_t *msg=NULL;
|
||||
char dtmf_body[128];
|
||||
char clen[10];
|
||||
|
||||
eXosip_lock();
|
||||
eXosip_call_build_info(h->did,&msg);
|
||||
if (msg){
|
||||
snprintf(dtmf_body, sizeof(dtmf_body), "Signal=%c\r\nDuration=250\r\n", dtmf);
|
||||
osip_message_set_body(msg,dtmf_body,strlen(dtmf_body));
|
||||
osip_message_set_content_type(msg,"application/dtmf-relay");
|
||||
snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(dtmf_body));
|
||||
osip_message_set_content_length(msg,clen);
|
||||
eXosip_call_send_request(h->did,msg);
|
||||
}
|
||||
eXosip_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sal_call_terminate(SalOp *h){
|
||||
eXosip_lock();
|
||||
eXosip_call_terminate(h->cid,h->did);
|
||||
eXosip_unlock();
|
||||
eXosip_call_set_reference(h->cid,NULL);
|
||||
eXosip_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -494,13 +578,17 @@ static void call_accepted(Sal *sal, eXosip_event_t *ev){
|
|||
|
||||
static void call_terminated(Sal *sal, eXosip_event_t *ev){
|
||||
SalOp *op;
|
||||
char *from;
|
||||
op=(SalOp*)ev->external_reference;
|
||||
if (op==NULL){
|
||||
ms_warning("Call terminated for already closed call ?");
|
||||
return;
|
||||
}
|
||||
osip_from_to_str(ev->request->from,&from);
|
||||
eXosip_call_set_reference(ev->cid,NULL);
|
||||
sal->callbacks.call_terminated(op);
|
||||
op->cid=-1;
|
||||
sal->callbacks.call_terminated(op,from);
|
||||
osip_free(from);
|
||||
}
|
||||
|
||||
static void call_released(Sal *sal, eXosip_event_t *ev){
|
||||
|
|
@ -510,7 +598,7 @@ static void call_released(Sal *sal, eXosip_event_t *ev){
|
|||
return;
|
||||
}
|
||||
eXosip_call_set_reference(ev->cid,NULL);
|
||||
sal->callbacks.call_terminated(op);
|
||||
/*sal->callbacks.call_terminated(op);*/
|
||||
}
|
||||
|
||||
static int get_auth_data(eXosip_event_t *ev, const char **realm, const char **username){
|
||||
|
|
@ -600,7 +688,8 @@ static bool_t call_failure(Sal *sal, eXosip_event_t *ev){
|
|||
sr=SalReasonNotFound;
|
||||
break;
|
||||
case 415:
|
||||
error=SalErrorMedia;
|
||||
error=SalErrorFailure;
|
||||
sr=SalReasonMedia;
|
||||
break;
|
||||
case 422:
|
||||
eXosip_default_action(ev);
|
||||
|
|
@ -1031,11 +1120,9 @@ int sal_iterate(Sal *sal){
|
|||
if (process_event(sal,ev))
|
||||
eXosip_event_free(ev);
|
||||
}
|
||||
if (sal->automatic_action==0) {
|
||||
eXosip_lock();
|
||||
eXosip_automatic_refresh();
|
||||
eXosip_unlock();
|
||||
}
|
||||
eXosip_lock();
|
||||
eXosip_automatic_refresh();
|
||||
eXosip_unlock();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ struct Sal{
|
|||
MSList *in_subscribes;/*MSList of SalOp */
|
||||
int running;
|
||||
int session_expires;
|
||||
int automatic_action;
|
||||
void *up;
|
||||
};
|
||||
|
||||
struct SalOp{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue