Commit 8647ec6a authored by Simon Morlat's avatar Simon Morlat
Browse files

enhancements for proper pause/resume of calls

parent e69c8b2b
......@@ -303,7 +303,7 @@ static void call_accepted(SalOp *op){
ms_free(msg);
}
linphone_core_update_streams (lc,call,md);
linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
}else{
if (lc->vtable.display_status){
lc->vtable.display_status(lc,_("Call answered - connected."));
......@@ -349,6 +349,7 @@ static void call_ack(SalOp *op){
}
}
/* this callback is called when an incoming re-INVITE modifies the session*/
static void call_updating(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
......@@ -360,32 +361,21 @@ static void call_updating(SalOp *op){
if (md && !sal_media_description_empty(md))
{
if ((call->state==LinphoneCallPausedByRemote || call->state==LinphoneCallPaused) &&
sal_media_description_has_dir(md,SalStreamSendRecv) && strcmp(md->addr,"0.0.0.0")!=0){
/*make sure we can be resumed */
if (lc->current_call!=NULL && lc->current_call!=call){
ms_warning("Attempt to be resumed but already in call with somebody else!");
/*we are actively running another call, reject with a busy*/
sal_call_decline (op,SalReasonBusy,NULL);
return;
}
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We have been resumed..."));
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
}
else if(call->state==LinphoneCallStreamsRunning &&
( sal_media_description_has_dir(md,SalStreamRecvOnly)
|| sal_media_description_has_dir(md,SalStreamInactive)
|| strcmp(md->addr,"0.0.0.0")==0)){
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We are being paused..."));
linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
if (lc->current_call!=call){
ms_error("Inconsitency detected: current call is %p but call %p is being paused !",lc->current_call,call);
if (sal_media_description_has_dir(call->localdesc,SalStreamSendRecv)){
if (sal_media_description_has_dir (md,SalStreamRecvOnly) || sal_media_description_has_dir(md,SalStreamInactive)){
/* we are being paused */
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We are being paused..."));
linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
}else if (!sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && sal_media_description_has_dir(md,SalStreamSendRecv)){
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We have been resumed..."));
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
lc->current_call=call;
}else{
prevstate=call->state;
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
}
}else{
prevstate=call->state;
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
}
/*accept the modification (sends a 200Ok)*/
sal_call_accept(op);
......
......@@ -2204,7 +2204,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Modifying call parameters..."));
sal_call_set_local_media_description (call->op,call->localdesc);
err=sal_call_update(call->op);
err=sal_call_update(call->op,"Media parameters update");
}else{
#ifdef VIDEO_ENABLED
if (call->videostream!=NULL){
......@@ -2431,13 +2431,23 @@ LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc)
int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call)
{
LinphoneCall *call = the_call;
const char *subject=NULL;
if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){
ms_warning("Cannot pause this call, it is not active.");
return -1;
}
if (sal_call_hold(call->op,TRUE) != 0)
if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){
sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
subject="Call on hold";
}else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){
sal_media_description_set_dir(call->localdesc,SalStreamInactive);
subject="Call inactive";
}else{
ms_error("No reason to pause this call, it is already paused or inactive.");
return -1;
}
if (sal_call_update(call->op,subject) != 0)
{
if (lc->vtable.display_warning)
lc->vtable.display_warning(lc,_("Could not pause the call"));
......@@ -2487,14 +2497,14 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call)
return -1;
}
ms_message("Resuming call %p",call);
if(sal_call_hold(call->op,FALSE) != 0){
sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
if(sal_call_update(call->op,"Call resuming") != 0){
return -1;
}
linphone_call_set_state (call,LinphoneCallResuming,"Resuming");
snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call));
if (lc->vtable.display_status)
lc->vtable.display_status(lc,temp);
lc->current_call=call;
return 0;
}
......
......@@ -109,7 +109,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
static SalStreamDir compute_dir(SalStreamDir local, SalStreamDir answered){
static SalStreamDir compute_dir_outgoing(SalStreamDir local, SalStreamDir answered){
SalStreamDir res=local;
if (local==SalStreamSendRecv){
if (answered==SalStreamRecvOnly){
......@@ -124,6 +124,33 @@ static SalStreamDir compute_dir(SalStreamDir local, SalStreamDir answered){
return res;
}
static SalStreamDir compute_dir_incoming(SalStreamDir local, SalStreamDir offered){
SalStreamDir res=SalStreamSendRecv;
if (local==SalStreamSendRecv){
if (offered==SalStreamSendOnly)
res=SalStreamRecvOnly;
if (offered==SalStreamRecvOnly)
res=SalStreamSendOnly;
if (offered==SalStreamInactive)
res=SalStreamInactive;
}else if (local==SalStreamSendOnly){
if (offered==SalStreamSendOnly)
res=SalStreamInactive;
if (offered==SalStreamRecvOnly)
res=SalStreamSendOnly;
if (offered==SalStreamInactive)
res=SalStreamInactive;
}else if (local==SalStreamRecvOnly){
if (offered==SalStreamSendOnly)
res=SalStreamRecvOnly;
if (offered==SalStreamRecvOnly)
res=SalStreamInactive;
if (offered==SalStreamInactive)
res=SalStreamInactive;
}else res=SalStreamInactive;
return res;
}
static void initiate_outgoing(const SalStreamDescription *local_offer,
const SalStreamDescription *remote_answer,
SalStreamDescription *result){
......@@ -131,7 +158,7 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
result->proto=local_offer->proto;
result->type=local_offer->type;
result->dir=compute_dir(local_offer->dir,remote_answer->dir);
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->addr,remote_answer->addr);
......@@ -150,13 +177,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec);
result->proto=local_cap->proto;
result->type=local_cap->type;
if (remote_offer->dir==SalStreamSendOnly)
result->dir=SalStreamRecvOnly;
else if (remote_offer->dir==SalStreamRecvOnly){
result->dir=SalStreamSendOnly;
}else if (remote_offer->dir==SalStreamInactive){
result->dir=SalStreamInactive;
}else result->dir=SalStreamSendRecv;
result->dir=compute_dir_incoming(result->dir,remote_offer->dir);
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->addr,local_cap->addr);
result->port=local_cap->port;
......
......@@ -79,19 +79,41 @@ void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_
}
}
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
static bool_t is_null_address(const char *addr){
return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0;
}
/*check for the presence of at least one stream with requested direction */
static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
int i;
bool_t found=FALSE;
/* we are looking for at least one stream with requested direction, inactive streams are ignored*/
for(i=0;i<md->nstreams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (ss->dir==stream_dir) found=TRUE;
else{
if (ss->dir!=SalStreamInactive) return FALSE;
}
if (ss->dir==stream_dir) return TRUE;
if (stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->addr)))
return TRUE;
}
return found;
return FALSE;
}
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
if (stream_dir==SalStreamRecvOnly){
if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
}else if (stream_dir==SalStreamSendOnly){
if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
}else if (stream_dir==SalStreamSendRecv){
return has_dir(md,SalStreamSendRecv);
}else{
/*SalStreamInactive*/
if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv) || has_dir(md,SalStreamRecvOnly))
return FALSE;
else return TRUE;
}
return FALSE;
}
/*
......
......@@ -293,8 +293,7 @@ int sal_call_notify_ringing(SalOp *h, bool_t early_media);
/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h);
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
int sal_call_hold(SalOp *h, bool_t holdon);
int sal_call_update(SalOp *h);
int sal_call_update(SalOp *h, const char *subject);
SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
int sal_call_refer(SalOp *h, const char *refer_to);
int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h);
......
......@@ -2011,37 +2011,8 @@ int sal_address_get_port_int(const SalAddress *uri) {
}
}
/*
* Send a re-Invite used to hold the current call
*/
int sal_call_hold(SalOp *h, bool_t holdon)
{
int err=0;
osip_message_t *reinvite=NULL;
if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != OSIP_SUCCESS || reinvite==NULL)
return -1;
osip_message_set_subject(reinvite,holdon ? "Phone call hold" : "Phone call resume" );
osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
if (h->base.root->session_expires!=0){
osip_message_set_header(reinvite, "Session-expires", "200");
osip_message_set_supported(reinvite, "timer");
}
//add something to say that the distant sip phone will be in sendonly/sendrecv mode
if (h->base.local_media){
h->sdp_offering=TRUE;
sal_media_description_set_dir(h->base.local_media, holdon ? SalStreamSendOnly : SalStreamSendRecv);
set_sdp_from_desc(reinvite,h->base.local_media);
}else h->sdp_offering=FALSE;
eXosip_lock();
err = eXosip_call_send_request(h->did, reinvite);
eXosip_unlock();
return err;
}
/* sends a reinvite. Local media description may have changed by application since call establishment*/
int sal_call_update(SalOp *h){
int sal_call_update(SalOp *h, const char *subject){
int err=0;
osip_message_t *reinvite=NULL;
......@@ -2051,7 +2022,7 @@ int sal_call_update(SalOp *h){
return -1;
}
eXosip_unlock();
osip_message_set_subject(reinvite,osip_strdup("Phone call parameters updated"));
osip_message_set_subject(reinvite,subject);
osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
if (h->base.root->session_expires!=0){
osip_message_set_header(reinvite, "Session-expires", "200");
......
mediastreamer2 @ 0fc8db73
Subproject commit 5aab07bfaac18302a6af3b38fa7c62d466794941
Subproject commit 0fc8db73037bab398ece764874192d1d7df6af28
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment