diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index f92047913..af7d8b6ba 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -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 (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"); } - 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); - } - }else{ - prevstate=call->state; - linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); } /*accept the modification (sends a 200Ok)*/ sal_call_accept(op); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 4490bf451..81eb363d9 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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; } diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 91de86e29..e9f4bcbe4 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -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; diff --git a/coreapi/sal.c b/coreapi/sal.c index 6f80436c6..ec8a6fc6d 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -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;instreams;++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; } /* diff --git a/coreapi/sal.h b/coreapi/sal.h index 2f39c697c..24cc8582a 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -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); diff --git a/coreapi/sal_eXosip2.c b/coreapi/sal_eXosip2.c index e2d528277..7bc79102f 100644 --- a/coreapi/sal_eXosip2.c +++ b/coreapi/sal_eXosip2.c @@ -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"); diff --git a/mediastreamer2 b/mediastreamer2 index 5aab07bfa..0fc8db730 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 5aab07bfaac18302a6af3b38fa7c62d466794941 +Subproject commit 0fc8db73037bab398ece764874192d1d7df6af28