diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index e0b0174ad55134e3f53d7356f2687145ad8952ee..d8fdd8803b081519ee04c5268c7fd77c965f3cd8 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -208,22 +208,23 @@ static void update_media_description_from_stun(SalMediaDescription *md, const St } - -static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, LinphoneCall *call, unsigned int session_id, unsigned int session_ver){ +void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){ MSList *l; PayloadType *pt; + SalMediaDescription *old_md=call->localdesc; int i; const char *me=linphone_core_get_identity(lc); LinphoneAddress *addr=linphone_address_new(me); const char *username=linphone_address_get_username (addr); SalMediaDescription *md=sal_media_description_new(); + bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0); if (call->ping_time>0) { linphone_core_adapt_to_network(lc,call->ping_time,&call->params); } - md->session_id=session_id; - md->session_ver=session_ver; + md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff)); + md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff)); md->nstreams=1; strncpy(md->addr,call->localip,sizeof(md->addr)); strncpy(md->username,username,sizeof(md->username)); @@ -248,8 +249,6 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event")); l=ms_list_append(l,pt); md->streams[0].payloads=l; - - if (call->params.has_video){ md->nstreams++; @@ -263,15 +262,22 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li for(i=0; i<md->nstreams; i++) { if (md->streams[i].proto == SalProtoRtpSavp) { - 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)) - 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)) - md->streams[i].crypto[1].algo = 0; - md->streams[i].crypto[2].algo = 0; + if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){ + int j; + 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)) + 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)) + md->streams[i].crypto[1].algo = 0; + md->streams[i].crypto[2].algo = 0; + } } } update_media_description_from_stun(md,&call->ac,&call->vc); @@ -280,22 +286,8 @@ static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, Li linphone_core_update_ice_state_in_call_stats(call); } linphone_address_destroy(addr); - return md; -} - -void update_local_media_description(LinphoneCore *lc, LinphoneCall *call){ - SalMediaDescription *md=call->localdesc; - if (md== NULL) { - call->localdesc = create_local_media_description(lc,call); - } else { - call->localdesc = _create_local_media_description(lc,call,md->session_id,md->session_ver+1); - sal_media_description_unref(md); - } -} - -SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call){ - unsigned int id=rand() & 0xfff; - return _create_local_media_description(lc,call,id,id); + call->localdesc=md; + if (old_md) sal_media_description_unref(old_md); } static int find_port_offset(LinphoneCore *lc, SalStreamType type){ @@ -1026,11 +1018,11 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS"); linphone_call_send_vfu_request(call); break; - case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED: - ms_message("First video frame decoded successfully"); - if (call->nextVideoFrameDecoded._func != NULL) - call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data); - break; + case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED: + ms_message("First video frame decoded successfully"); + if (call->nextVideoFrameDecoded._func != NULL) + call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data); + break; default: ms_warning("Unhandled event %i", event_id); break; @@ -1039,10 +1031,10 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u #endif void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data) { - call->nextVideoFrameDecoded._func = cb; - call->nextVideoFrameDecoded._user_data = user_data; + call->nextVideoFrameDecoded._func = cb; + call->nextVideoFrameDecoded._user_data = user_data; #ifdef VIDEO_ENABLED - ms_filter_call_method_noarg(call->videostream->decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); + ms_filter_call_method_noarg(call->videostream->decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); #endif } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index f3d0a00302f7910c780b01970ecc82315aec8728..01667ebcb4f7608ae26d367fe7787d3cf487a4e8 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2290,7 +2290,7 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){ linphone_call_init_media_streams(call); if (lc->ringstream==NULL) audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard); - call->localdesc=create_local_media_description(lc,call); + linphone_call_make_local_media_description(lc,call); if (!lc->sip_conf.sdp_200_ack){ call->media_pending=TRUE; sal_call_set_local_media_description(call->op,call->localdesc); @@ -2552,7 +2552,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE); const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc); - call->localdesc=create_local_media_description(lc,call); + linphone_call_make_local_media_description(lc,call); sal_call_set_local_media_description(call->op,call->localdesc); md=sal_call_get_final_media_description(call->op); if (md && sal_media_description_empty(md)){ @@ -2658,7 +2658,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho call->videostream->ice_check_list = NULL; } call->params = *params; - update_local_media_description(lc, call); + linphone_call_make_local_media_description(lc, call); if ((call->ice_session != NULL) && !has_video && call->params.has_video) { /* Defer call update until the ICE candidates gathering process has finished. */ ms_message("Defer call update to gather ICE candidates"); @@ -2769,7 +2769,7 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const } call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(call->op)); call->camera_active=call->params.has_video; - update_local_media_description(lc,call); + linphone_call_make_local_media_description(lc,call); if (call->ice_session != NULL) { linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(call->op)); #ifdef VIDEO_ENABLED @@ -2885,7 +2885,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, call->params=*params; call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(call->op)); call->camera_active=call->params.has_video; - update_local_media_description(lc,call); + linphone_call_make_local_media_description(lc,call); sal_call_set_local_media_description(call->op,call->localdesc); } @@ -3075,7 +3075,7 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) ms_warning("Cannot pause this call, it is not active."); return -1; } - update_local_media_description(lc,call); + linphone_call_make_local_media_description(lc,call); if (call->ice_session != NULL) linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session); if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){ @@ -3154,7 +3154,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) prevents the participants to hear it while the 200OK comes back.*/ if (call->audiostream) audio_stream_play(call->audiostream, NULL); - update_local_media_description(lc,the_call); + linphone_call_make_local_media_description(lc,the_call); if (call->ice_session != NULL) linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session); sal_call_set_local_media_description(call->op,call->localdesc); diff --git a/coreapi/private.h b/coreapi/private.h index 60587dbcd8dc9524e598e9bf85f380401b345a99..5ebe8b5b7611c491970ab3579db576515b6c98ae 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -582,10 +582,7 @@ int linphone_core_set_as_current_call(LinphoneCore *lc, LinphoneCall *call); int linphone_core_get_calls_nb(const LinphoneCore *lc); void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); - -SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call); -void update_local_media_description(LinphoneCore *lc, LinphoneCall *call); - +void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call); void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md); bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, PayloadType *pt, int bandwidth_limit); diff --git a/coreapi/sal.c b/coreapi/sal.c index 229ee577f3a531e3b8c9d3bf85c1312c6d5e03aa..f46d9a556c9b3f4b78be57fe10cf939ed173f868 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -162,6 +162,10 @@ static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){ return TRUE; } +static bool_t is_recv_only(PayloadType *p){ + return (p->flags & PAYLOAD_TYPE_FLAG_CAN_RECV) && ! (p->flags & PAYLOAD_TYPE_FLAG_CAN_SEND); +} + static bool_t payload_list_equals(const MSList *l1, const MSList *l2){ const MSList *e1,*e2; for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){ @@ -170,6 +174,12 @@ static bool_t payload_list_equals(const MSList *l1, const MSList *l2){ if (!payload_type_equals(p1,p2)) return FALSE; } + if (e1!=NULL){ + /*skip possible recv-only payloads*/ + for(;e1!=NULL && is_recv_only((PayloadType*)e1->data);e1=e1->next){ + ms_message("Skipping recv-only payload type..."); + } + } if (e1!=NULL || e2!=NULL){ /*means one list is longer than the other*/ return FALSE;