mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 19:18:06 +00:00
SDP offer answer fix: declined streams must remain as inactive in future offers.
This commit is contained in:
parent
2394027f9e
commit
092375c98a
6 changed files with 96 additions and 69 deletions
|
|
@ -74,14 +74,28 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c
|
|||
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){
|
||||
SalMediaDescription *oldmd=call->resultdesc;
|
||||
bool_t all_muted=FALSE;
|
||||
bool_t send_ringbacktone=FALSE;
|
||||
|
||||
linphone_core_stop_ringing(lc);
|
||||
if (new_md!=NULL){
|
||||
sal_media_description_ref(new_md);
|
||||
call->media_pending=FALSE;
|
||||
}else{
|
||||
call->media_pending=TRUE;
|
||||
if (!new_md) {
|
||||
ms_error("linphone_core_update_streams() called with null media description");
|
||||
return;
|
||||
}
|
||||
if (call->biggestdesc==NULL || new_md->n_total_streams>call->biggestdesc->n_total_streams){
|
||||
/*we have been offered and now are ready to proceed, or we added a new stream*/
|
||||
/*store the media description to remember the mapping of calls*/
|
||||
if (call->biggestdesc){
|
||||
sal_media_description_unref(call->biggestdesc);
|
||||
call->biggestdesc=NULL;
|
||||
}
|
||||
if (sal_call_is_offerer(call->op))
|
||||
call->biggestdesc=sal_media_description_ref(call->localdesc);
|
||||
else
|
||||
call->biggestdesc=sal_media_description_ref(sal_call_get_remote_media_description(call->op));
|
||||
}
|
||||
sal_media_description_ref(new_md);
|
||||
call->expect_media_in_ack=FALSE;
|
||||
call->resultdesc=new_md;
|
||||
if ((call->audiostream && call->audiostream->ms.ticker) || (call->videostream && call->videostream->ms.ticker)){
|
||||
/* we already started media: check if we really need to restart it*/
|
||||
|
|
@ -121,23 +135,18 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
|
|||
linphone_call_init_media_streams (call);
|
||||
}
|
||||
|
||||
if (new_md) {
|
||||
bool_t all_muted=FALSE;
|
||||
bool_t send_ringbacktone=FALSE;
|
||||
|
||||
if (call->audiostream==NULL){
|
||||
/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
|
||||
linphone_call_init_media_streams (call);
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
|
||||
send_ringbacktone=TRUE;
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingEarlyMedia ||
|
||||
(call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){
|
||||
all_muted=TRUE;
|
||||
}
|
||||
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
|
||||
if (call->audiostream==NULL){
|
||||
/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
|
||||
linphone_call_init_media_streams (call);
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
|
||||
send_ringbacktone=TRUE;
|
||||
}
|
||||
if (call->state==LinphoneCallIncomingEarlyMedia ||
|
||||
(call->state==LinphoneCallOutgoingEarlyMedia && !call->params.real_early_media)){
|
||||
all_muted=TRUE;
|
||||
}
|
||||
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
|
||||
if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
|
||||
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
|
||||
}
|
||||
|
|
@ -413,10 +422,10 @@ static void call_ack(SalOp *op){
|
|||
ms_warning("No call to be ACK'd");
|
||||
return ;
|
||||
}
|
||||
if (call->media_pending){
|
||||
if (call->expect_media_in_ack){
|
||||
SalMediaDescription *md=sal_call_get_final_media_description(op);
|
||||
if (md && !sal_media_description_empty(md)){
|
||||
linphone_core_update_streams (lc,call,md);
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}else{
|
||||
/*send a bye*/
|
||||
|
|
@ -430,7 +439,7 @@ static void call_ack(SalOp *op){
|
|||
static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
|
||||
SalMediaDescription *md;
|
||||
SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op);
|
||||
if ((rmd!=NULL) && (call->ice_session!=NULL)) {
|
||||
if (rmd!=NULL && call->ice_session!=NULL) {
|
||||
linphone_core_update_ice_from_remote_media_description(call,rmd);
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session);
|
||||
}
|
||||
|
|
@ -492,7 +501,7 @@ static void call_updating(SalOp *op){
|
|||
if (rmd==NULL){
|
||||
/* case of a reINVITE without SDP */
|
||||
call_accept_update(lc,call);
|
||||
call->media_pending=TRUE;
|
||||
call->expect_media_in_ack=TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -229,6 +229,35 @@ static void update_media_description_from_stun(SalMediaDescription *md, const St
|
|||
}
|
||||
}
|
||||
|
||||
static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
|
||||
LinphoneCore *lc=call->core;
|
||||
int i;
|
||||
SalMediaDescription *old_md=call->localdesc;
|
||||
bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0);
|
||||
|
||||
for(i=0; i<md->n_active_streams; i++) {
|
||||
if (md->streams[i].proto == SalProtoRtpSavp) {
|
||||
if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){
|
||||
int j;
|
||||
ms_message("Keeping same crypto keys.");
|
||||
for(j=0;j<SAL_CRYPTO_ALGO_MAX;++j){
|
||||
memcpy(&md->streams[i].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo));
|
||||
}
|
||||
}else{
|
||||
md->streams[i].crypto[0].tag = 1;
|
||||
md->streams[i].crypto[0].algo = AES_128_SHA1_80;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key, SAL_SRTP_KEY_SIZE))
|
||||
md->streams[i].crypto[0].algo = 0;
|
||||
md->streams[i].crypto[1].tag = 2;
|
||||
md->streams[i].crypto[1].algo = AES_128_SHA1_32;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key, SAL_SRTP_KEY_SIZE))
|
||||
md->streams[i].crypto[1].algo = 0;
|
||||
md->streams[i].crypto[2].algo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
|
||||
MSList *l;
|
||||
PayloadType *pt;
|
||||
|
|
@ -237,7 +266,6 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
const char *me;
|
||||
SalMediaDescription *md=sal_media_description_new();
|
||||
LinphoneAddress *addr;
|
||||
bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0);
|
||||
char* local_ip=call->localip;
|
||||
|
||||
linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
|
||||
|
|
@ -250,8 +278,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
|
||||
md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
|
||||
md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
|
||||
md->n_total_streams=(old_md ? old_md->n_total_streams : 1);
|
||||
md->n_active_streams=1;
|
||||
md->n_total_streams=(call->biggestdesc ? call->biggestdesc->n_total_streams : 1);
|
||||
|
||||
strncpy(md->addr,local_ip,sizeof(md->addr));
|
||||
strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username));
|
||||
|
||||
|
|
@ -260,6 +288,7 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
else md->bandwidth=linphone_core_get_download_bandwidth(lc);
|
||||
|
||||
/*set audio capabilities */
|
||||
md->n_active_streams=1;
|
||||
strncpy(md->streams[0].rtp_addr,local_ip,sizeof(md->streams[0].rtp_addr));
|
||||
strncpy(md->streams[0].rtcp_addr,local_ip,sizeof(md->streams[0].rtcp_addr));
|
||||
md->streams[0].rtp_port=call->audio_port;
|
||||
|
|
@ -292,34 +321,15 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
|
|||
for (i = md->n_active_streams; i < md->n_total_streams; i++) {
|
||||
md->streams[i].rtp_port = 0;
|
||||
md->streams[i].rtcp_port = 0;
|
||||
md->streams[i].proto = SalProtoRtpAvp;
|
||||
md->streams[i].type = old_md->streams[i].type;
|
||||
md->streams[i].proto = call->biggestdesc->streams[i].proto;
|
||||
md->streams[i].type = call->biggestdesc->streams[i].type;
|
||||
md->streams[i].dir = SalStreamInactive;
|
||||
l = make_codec_list(lc, lc->codecs_conf.video_codecs, 0, NULL, 1);
|
||||
md->streams[i].payloads = l;
|
||||
}
|
||||
|
||||
for(i=0; i<md->n_active_streams; i++) {
|
||||
if (md->streams[i].proto == SalProtoRtpSavp) {
|
||||
if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){
|
||||
int j;
|
||||
ms_message("Keeping same crypto keys.");
|
||||
for(j=0;j<SAL_CRYPTO_ALGO_MAX;++j){
|
||||
memcpy(&md->streams[i].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo));
|
||||
}
|
||||
}else{
|
||||
md->streams[i].crypto[0].tag = 1;
|
||||
md->streams[i].crypto[0].algo = AES_128_SHA1_80;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key, SAL_SRTP_KEY_SIZE))
|
||||
md->streams[i].crypto[0].algo = 0;
|
||||
md->streams[i].crypto[1].tag = 2;
|
||||
md->streams[i].crypto[1].algo = AES_128_SHA1_32;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key, SAL_SRTP_KEY_SIZE))
|
||||
md->streams[i].crypto[1].algo = 0;
|
||||
md->streams[i].crypto[2].algo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
setup_encryption_keys(call,md);
|
||||
|
||||
update_media_description_from_stun(md,&call->ac,&call->vc);
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_ice(md, call->ice_session);
|
||||
|
|
@ -817,6 +827,10 @@ static void linphone_call_destroy(LinphoneCall *obj)
|
|||
sal_op_release(obj->op);
|
||||
obj->op=NULL;
|
||||
}
|
||||
if (obj->biggestdesc!=NULL){
|
||||
sal_media_description_unref(obj->biggestdesc);
|
||||
obj->biggestdesc=NULL;
|
||||
}
|
||||
if (obj->resultdesc!=NULL) {
|
||||
sal_media_description_unref(obj->resultdesc);
|
||||
obj->resultdesc=NULL;
|
||||
|
|
|
|||
|
|
@ -2558,20 +2558,22 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){
|
|||
audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lc->sip_conf.sdp_200_ack){
|
||||
call->media_pending=TRUE;
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
real_url=linphone_address_as_string(call->log->to);
|
||||
from=linphone_address_as_string(call->log->from);
|
||||
err=sal_call(call->op,from,real_url);
|
||||
call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/
|
||||
|
||||
if (lc->sip_conf.sdp_200_ack){
|
||||
call->media_pending=TRUE;
|
||||
|
||||
if (!lc->sip_conf.sdp_200_ack){
|
||||
/*we are offering, set local media description before sending the call*/
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
err=sal_call(call->op,from,real_url);
|
||||
if (lc->sip_conf.sdp_200_ack){
|
||||
/*we are NOT offering, set local media description after sending the call so that we are ready to
|
||||
process the remote offer when it will arrive*/
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
}
|
||||
|
||||
call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/
|
||||
|
||||
barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
|
||||
if (lc->vtable.display_status!=NULL)
|
||||
lc->vtable.display_status(lc,barmsg);
|
||||
|
|
@ -2954,7 +2956,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
|||
if (propose_early_media || ringback_tone!=NULL){
|
||||
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
|
||||
md=sal_call_get_final_media_description(call->op);
|
||||
linphone_core_update_streams(lc,call,md);
|
||||
if (md) linphone_core_update_streams(lc,call,md);
|
||||
}
|
||||
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
|
||||
linphone_core_accept_call(lc,call);
|
||||
|
|
@ -3329,11 +3331,11 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
|||
lc->current_call=call;
|
||||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||
new_md=sal_call_get_final_media_description(call->op);
|
||||
linphone_core_update_streams(lc, call, new_md);
|
||||
linphone_call_fix_call_parameters(call);
|
||||
if (new_md){
|
||||
linphone_core_update_streams(lc, call, new_md);
|
||||
linphone_call_fix_call_parameters(call);
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}else call->media_pending=TRUE;
|
||||
}else call->expect_media_in_ack=TRUE;
|
||||
|
||||
ms_message("call answered.");
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -158,9 +158,10 @@ struct _LinphoneCall
|
|||
int magic; /*used to distinguish from proxy config*/
|
||||
struct _LinphoneCore *core;
|
||||
int af; /*the address family to prefer for RTP path, guessed from signaling path*/
|
||||
LinphoneCallDir dir;
|
||||
SalMediaDescription *biggestdesc; /*media description with all already proposed streams, used to remember the mapping of streams*/
|
||||
SalMediaDescription *localdesc;
|
||||
SalMediaDescription *resultdesc;
|
||||
LinphoneCallDir dir;
|
||||
struct _RtpProfile *audio_profile;
|
||||
struct _RtpProfile *video_profile;
|
||||
struct _LinphoneCallLog *log;
|
||||
|
|
@ -206,7 +207,7 @@ struct _LinphoneCall
|
|||
int localdesc_changed;
|
||||
|
||||
bool_t refer_pending;
|
||||
bool_t media_pending;
|
||||
bool_t expect_media_in_ack;
|
||||
bool_t audio_muted;
|
||||
bool_t camera_enabled;
|
||||
|
||||
|
|
|
|||
|
|
@ -68,8 +68,9 @@ static void sal_media_description_destroy(SalMediaDescription *md){
|
|||
ms_free(md);
|
||||
}
|
||||
|
||||
void sal_media_description_ref(SalMediaDescription *md){
|
||||
SalMediaDescription * sal_media_description_ref(SalMediaDescription *md){
|
||||
md->refcount++;
|
||||
return md;
|
||||
}
|
||||
|
||||
void sal_media_description_unref(SalMediaDescription *md){
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ typedef struct SalIsComposing {
|
|||
#define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
|
||||
|
||||
SalMediaDescription *sal_media_description_new();
|
||||
void sal_media_description_ref(SalMediaDescription *md);
|
||||
SalMediaDescription * sal_media_description_ref(SalMediaDescription *md);
|
||||
void sal_media_description_unref(SalMediaDescription *md);
|
||||
bool_t sal_media_description_empty(const SalMediaDescription *md);
|
||||
int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue