]> sjero.net Git - linphone/commitdiff
Allow update of SRTP crypto keys without restarting the media streams.
authorGhislain MARY <ghislain.mary@belledonne-communications.com>
Fri, 21 Dec 2012 15:31:40 +0000 (16:31 +0100)
committerGhislain MARY <ghislain.mary@belledonne-communications.com>
Fri, 21 Dec 2012 15:31:40 +0000 (16:31 +0100)
coreapi/callbacks.c
coreapi/linphonecall.c
coreapi/private.h
coreapi/sal.c
coreapi/sal.h

index 134c336abe3cc946715746477b40c9b35bbb7e93..f9399553f32512ce76421577977fb2f69f781928 100644 (file)
@@ -104,31 +104,40 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
                /* we already started media: check if we really need to restart it*/
                if (oldmd){
                        int md_changed = media_parameters_changed(call, oldmd, new_md);
-                       if ((md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) && !call->playing_ringbacktone) {
-                               /*as nothing has changed, keep the oldmd */
-                               call->resultdesc=oldmd;
-                               sal_media_description_unref(new_md);
-                               if (call->all_muted){
-                                       ms_message("Early media finished, unmuting inputs...");
-                                       /*we were in early media, now we want to enable real media */
-                                       linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
-                                       if (call->audiostream)
-                                               linphone_core_mute_mic (lc, linphone_core_is_mic_muted(lc));
+                       if ((md_changed & SAL_MEDIA_DESCRIPTION_CODEC_CHANGED) || call->playing_ringbacktone) {
+                               ms_message("Media descriptions are different, need to restart the streams.");
+                       } else {
+                               if (md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) {
+                                       /*as nothing has changed, keep the oldmd */
+                                       call->resultdesc=oldmd;
+                                       sal_media_description_unref(new_md);
+                                       if (call->all_muted){
+                                               ms_message("Early media finished, unmuting inputs...");
+                                               /*we were in early media, now we want to enable real media */
+                                               linphone_call_enable_camera (call,linphone_call_camera_enabled (call));
+                                               if (call->audiostream)
+                                                       linphone_core_mute_mic (lc, linphone_core_is_mic_muted(lc));
 #ifdef VIDEO_ENABLED
-                                       if (call->videostream && call->camera_active)
-                                               video_stream_change_camera(call->videostream,lc->video_conf.device );
+                                               if (call->videostream && call->camera_active)
+                                                       video_stream_change_camera(call->videostream,lc->video_conf.device );
 #endif
+                                       }
+                                       ms_message("No need to restart streams, SDP is unchanged.");
+                                       return;
+                               }
+                               else {
+                                       if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) {
+                                               ms_message("Network parameters have changed, update them.");
+                                               linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
+                                       }
+                                       if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) {
+                                               ms_message("Crypto parameters have changed, update them.");
+                                               linphone_call_update_crypto_parameters(call, oldmd, new_md);
+                                       }
+                                       call->resultdesc = oldmd;
+                                       sal_media_description_unref(new_md);
+                                       return;
                                }
-                               ms_message("No need to restart streams, SDP is unchanged.");
-                               return;
-                       } else if ((md_changed == SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) && !call->playing_ringbacktone) {
-                               call->resultdesc = oldmd;
-                               ms_message("Network parameters have changed, update them.");
-                               linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
-                               sal_media_description_unref(new_md);
-                               return;
-                       }else{
-                               ms_message("Media descriptions are different, need to restart the streams.");
                        }
                }
                linphone_call_stop_media_streams (call);
index ffaf24b5ee8b11fbed0f7abb430f344937ef0688..9ad1e177615eda7cd5c78d45c49e197228cb3c9f 100644 (file)
@@ -1658,6 +1658,52 @@ void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
 #endif
 }
 
+void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) {
+       SalStreamDescription *old_stream;
+       SalStreamDescription *new_stream;
+       int i;
+
+       old_stream = sal_media_description_find_stream(old_md, SalProtoRtpSavp, SalAudio);
+       new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio);
+       if (old_stream && new_stream) {
+               const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalAudio);
+               int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
+               if (crypto_idx >= 0) {
+                       audio_stream_enable_strp(call->audiostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
+                       call->audiostream_encrypted = TRUE;
+               } else {
+                       ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
+                       call->audiostream_encrypted = FALSE;
+               }
+               for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
+                       old_stream->crypto[i].tag = new_stream->crypto[i].tag;
+                       old_stream->crypto[i].algo = new_stream->crypto[i].algo;
+                       strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+               }
+       }
+
+#ifdef VIDEO_ENABLED
+       old_stream = sal_media_description_find_stream(old_md, SalProtoRtpSavp, SalVideo);
+       new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalVideo);
+       if (old_stream && new_stream) {
+               const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalVideo);
+               int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
+               if (crypto_idx >= 0) {
+                       video_stream_enable_strp(call->videostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
+                       call->videostream_encrypted = TRUE;
+               } else {
+                       ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
+                       call->videostream_encrypted = FALSE;
+               }
+               for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
+                       old_stream->crypto[i].tag = new_stream->crypto[i].tag;
+                       old_stream->crypto[i].algo = new_stream->crypto[i].algo;
+                       strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
+               }
+       }
+#endif
+}
+
 void linphone_call_delete_ice_session(LinphoneCall *call){
        if (call->ice_session != NULL) {
                ice_session_destroy(call->ice_session);
index 43e4b2227abb4c899d88852064af3877343b6662..c171fac883d9382a73cab429327787fbf4b2e8d4 100644 (file)
@@ -285,6 +285,7 @@ void linphone_call_stop_video_stream(LinphoneCall *call);
 void linphone_call_stop_media_streams(LinphoneCall *call);
 void linphone_call_delete_ice_session(LinphoneCall *call);
 void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
+void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md);
 
 const char * linphone_core_get_identity(LinphoneCore *lc);
 const char * linphone_core_get_route(LinphoneCore *lc);
index f46d9a556c9b3f4b78be57fe10cf939ed173f868..7a3bbdf7bcdc794f37ddde44303630eabca81d54 100644 (file)
@@ -189,10 +189,18 @@ static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
 
 int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2) {
        int result = SAL_MEDIA_DESCRIPTION_UNCHANGED;
+       int i;
 
        /* A different proto should result in SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED but the encryption change
           needs a stream restart for now, so use SAL_MEDIA_DESCRIPTION_CODEC_CHANGED */
        if (sd1->proto != sd2->proto) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
+       for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
+               if ((sd1->crypto[i].tag != sd2->crypto[i].tag)
+                       || (sd1->crypto[i].algo != sd2->crypto[i].algo)
+                       || (strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) {
+                       result |= SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED;
+               }
+       }
 
        if (sd1->type != sd2->type) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
        if (strcmp(sd1->rtp_addr, sd2->rtp_addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
index daa59217a28bfc75c592a1c8b2fc0a6500606da1..77e43d6b14f64e886fc5a2e52c4ab3a024c72a1a 100644 (file)
@@ -56,7 +56,8 @@ typedef enum {
 #define SAL_MEDIA_DESCRIPTION_UNCHANGED                0x00
 #define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED  0x01
 #define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED    0x02
-#define SAL_MEDIA_DESCRIPTION_CHANGED          (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED)
+#define SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED   0x04
+#define SAL_MEDIA_DESCRIPTION_CHANGED          (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED | SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED)
 
 const char* sal_transport_to_string(SalTransport transport);
 SalTransport sal_transport_parse(const char*);