]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
dtls both ways now
authorAnthony Minessale <anthm@freeswitch.org>
Sat, 2 Feb 2013 06:15:09 +0000 (00:15 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 1 Apr 2013 02:27:22 +0000 (21:27 -0500)
src/switch_core_media.c
src/switch_rtp.c

index 908dba0e3da886515b7bad2c9acc9dc7eec9ec24..4b5c830ae3945869c455e63c6195ac9f959730fc 100644 (file)
@@ -746,7 +746,7 @@ SWITCH_DECLARE(void) switch_core_session_apply_crypto(switch_core_session_t *ses
        engine = &session->media_handle->engines[type];
 
        
-       if (engine->ssec.remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS)) {
+       if (engine->ssec.remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE)) {
                switch_core_media_add_crypto(&engine->ssec, engine->ssec.remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
 
                
@@ -805,8 +805,7 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio
                                switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto);
                                engine->ssec.crypto_tag = crypto_tag;
                                                                
-                               if (switch_rtp_ready(engine->rtp_session) && switch_channel_test_flag(session->channel, CF_SECURE) && 
-                                       !switch_channel_test_flag(session->channel, CF_DTLS)) {
+                               if (switch_rtp_ready(engine->rtp_session) && switch_channel_test_flag(session->channel, CF_SECURE)) {
                                        switch_core_media_add_crypto(&engine->ssec, engine->ssec.remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
                                        switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, engine->ssec.crypto_tag,
                                                                                          engine->ssec.crypto_type, engine->ssec.remote_raw_key, SWITCH_RTP_KEY_LEN);
@@ -845,7 +844,7 @@ SWITCH_DECLARE(void) switch_core_session_check_outgoing_crypto(switch_core_sessi
        switch_channel_t *channel = switch_core_session_get_channel(session);
        const char *var;
 
-       if (!switch_core_session_media_handle_ready(session) == SWITCH_STATUS_SUCCESS || switch_channel_test_flag(channel, CF_DTLS)) {
+       if (!switch_core_session_media_handle_ready(session) == SWITCH_STATUS_SUCCESS) {
                return;
        }
        
@@ -1781,13 +1780,10 @@ static void generate_local_fingerprint(switch_media_handle_t *smh, switch_media_
 {
        switch_rtp_engine_t *engine = &smh->engines[type];
 
-       engine->local_dtls_fingerprint.type = "sha-256";
-       switch_core_cert_gen_fingerprint(DTLS_SRTP_FNAME, &engine->local_dtls_fingerprint);
-
-       
-       //engine->local_dtls_fingerprint.data[];
-       
-       
+       if (!engine->local_dtls_fingerprint.len) {
+               engine->local_dtls_fingerprint.type = "sha-256";
+               switch_core_cert_gen_fingerprint(DTLS_SRTP_FNAME, &engine->local_dtls_fingerprint);
+       }
 }
 
 
@@ -1801,6 +1797,10 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 
        engine->ice_in.chosen = 0;
        engine->ice_in.cand_idx = 0;
+
+       for (attr = m->m_attributes; attr; attr = attr->a_next) {
+
+       }
        
 
        for (attr = m->m_attributes; attr; attr = attr->a_next) {
@@ -1819,9 +1819,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
                        engine->ice_in.pwd = switch_core_session_strdup(smh->session, attr->a_value);
                } else if (!strcasecmp(attr->a_name, "ice-options")) {
                        engine->ice_in.options = switch_core_session_strdup(smh->session, attr->a_value);
+                       
                } else if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
-                       //a=fingerprint:sha-256 B6:14:E2:59:58:C9:DD:44:50:91:D4:75:AE:23:9F:67:9F:8E:C2:B3:36:62:C7:9C:F4:25:1F:F3:EF:58:B1:BF
-
                        char *p;
 
                        engine->remote_dtls_fingerprint.type = switch_core_session_strdup(smh->session, attr->a_value);
@@ -1836,14 +1835,14 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
                                engine->local_dtls_fingerprint.type = NULL;
                                engine->remote_dtls_fingerprint.type = NULL;
                        }
-                       
-                       generate_local_fingerprint(smh, type);
 
+
+                       generate_local_fingerprint(smh, type);
                        switch_channel_set_flag(smh->session->channel, CF_DTLS);
 
 #ifdef RTCP_MUX
                } else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
-
+                       engine->remote_rtcp_port = engine->codec_params.remote_sdp_port;
                        engine->rtcp_mux = SWITCH_TRUE;
                        got_rtcp_mux++;
 #endif
@@ -2296,6 +2295,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
                } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
                        sdp_rtpmap_t *map;
 
+                       for (attr = m->m_attributes; attr; attr = attr->a_next) {
+                               if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
+                                       got_crypto = 1;
+                               }
+                       }
+
                        for (attr = m->m_attributes; attr; attr = attr->a_next) {
 
                                if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
@@ -2658,6 +2663,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
 
                        for (map = m->m_rtpmaps; map; map = map->rm_next) {
 
+                               for (attr = m->m_attributes; attr; attr = attr->a_next) {
+                                       if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
+                                               got_video_crypto = 1;
+                                       }
+                               }
+
                                for (attr = m->m_attributes; attr; attr = attr->a_next) {
                                        if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
                                                //framerate = atoi(attr->a_value);
@@ -3695,7 +3706,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 
 
                if (!zstr(a_engine->local_dtls_fingerprint.str)) {
-                       dtls_type_t dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_CLIENT;
+                       dtls_type_t dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
 
                        dtype |= DTLS_TYPE_RTP;
                        if (a_engine->rtcp_mux > 0) dtype |= DTLS_TYPE_RTCP;
@@ -3755,7 +3766,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                        }
 
 
-                       if (a_engine->ice_in.cands[a_engine->ice_in.chosen][1].ready) {
+                       if (a_engine->ice_in.cands[a_engine->ice_in.chosen][1].ready && a_engine->rtcp_mux < 1) {
                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
                                
                                switch_rtp_activate_ice(a_engine->rtp_session, 
@@ -4085,7 +4096,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                        switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
                                }
 
-                               
+                               if (!zstr(v_engine->local_dtls_fingerprint.str)) {
+                                       dtls_type_t dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
+                                       
+                                       dtype |= DTLS_TYPE_RTP;
+                                       if (v_engine->rtcp_mux > 0) dtype |= DTLS_TYPE_RTCP;
+                                       
+                                       switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype);
+                               }
+
                                if (v_engine->ice_in.cands[v_engine->ice_in.chosen][0].ready) {
                                        
                                        gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
@@ -4131,7 +4150,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
                                        }
                                        
 
-                                       if (v_engine->ice_in.cands[v_engine->ice_in.chosen][1].ready) {
+                                       if (v_engine->ice_in.cands[v_engine->ice_in.chosen][1].ready && v_engine->rtcp_mux < 1) {
                                                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
                                                switch_rtp_activate_ice(v_engine->rtp_session, 
                                                                                                v_engine->ice_in.ufrag,
@@ -4349,9 +4368,15 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
                switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", smh->mparams->te, smh->mparams->te);
        }
 
+       if (!zstr(a_engine->local_dtls_fingerprint.type)) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fingerprint:%s %s\n", a_engine->local_dtls_fingerprint.type, 
+                                               a_engine->local_dtls_fingerprint.str);
+       }
+
        if (smh->mparams->rtcp_audio_interval_msec) {
                if (a_engine->rtcp_mux > 0) {
                        switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-mux\n");
+                       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\n", port, family, ip);
                } else {
                        switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\n", port + 1, family, ip);
                }
@@ -4401,21 +4426,24 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
                                                        );
                }
 
+               if (a_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+                       
 
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
-                                               tmp1, ice_out->cands[0][0].transport, c2,
+                       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
+                                                       tmp1, ice_out->cands[0][0].transport, c2,
                                                        ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
-                                               );
-
-               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
-                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
-                       && a_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
-                       
-                       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-                                                       tmp2, ice_out->cands[0][0].transport, c4,
-                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
-                                                       a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
                                                        );
+                       
+                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
+                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
+                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
+                               
+                               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
+                                                               tmp2, ice_out->cands[0][0].transport, c4,
+                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
+                                                               a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
+                                                               );
+                       }
                }
 
                        
@@ -4426,7 +4454,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
        }
 
 
-       if (secure) {
+       if (secure && !zstr(local_audio_crypto_key)) {
                switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
                //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
        }
@@ -4605,8 +4633,6 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
 
        if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
-               switch_core_session_check_outgoing_crypto(session, "rtp_secure_media");
-               local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO);
 
                if (!switch_channel_test_flag(session->channel, CF_WEBRTC) && 
                        switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) {
@@ -4615,6 +4641,20 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        smh->mparams->rtcp_audio_interval_msec = "5000";
                        smh->mparams->rtcp_video_interval_msec = "5000";
                }
+
+               if (switch_channel_test_flag(session->channel, CF_WEBRTC) || switch_true(switch_channel_get_variable(smh->session->channel, "rtp_use_dtls"))) {
+                       switch_channel_set_flag(smh->session->channel, CF_DTLS);
+                       switch_channel_set_flag(smh->session->channel, CF_SECURE);
+                       generate_local_fingerprint(smh, SWITCH_MEDIA_TYPE_AUDIO);
+               }
+
+               switch_core_session_check_outgoing_crypto(session, "rtp_secure_media");
+               local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO);
+
+       } else {
+               if (switch_channel_test_flag(smh->session->channel, CF_DTLS)) {
+                       local_audio_crypto_key = NULL;
+               }
        }
 
        fmtp_out = a_engine->codec_params.fmtp_out;
@@ -4744,7 +4784,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
        if (a_engine->codec_params.rm_encoding) {
                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP%s", 
-                                               port, (!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) ? "S" : "",
+                                               port, ((!zstr(local_audio_crypto_key) || switch_channel_test_flag(session->channel, CF_DTLS)) && 
+                                                          switch_channel_test_flag(session->channel, CF_SECURE)) ? "S" : "",
                                                switch_channel_test_flag(session->channel, CF_WEBRTC) ? "F" : "");
 
 
@@ -4816,6 +4857,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                if (smh->mparams->rtcp_audio_interval_msec) {
                        if (a_engine->rtcp_mux > 0) {
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\n");
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", port, family, ip);
                        } else {
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", port + 1, family, ip);
                        }
@@ -4864,23 +4906,25 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        }
 
 
+                       if (a_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
 
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
-                                                       tmp1, ice_out->cands[0][0].transport, c2,
-                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
-                                                       );
-
-
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
+                                                               tmp1, ice_out->cands[0][0].transport, c2,
+                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
+                                                               );
+                               
 
-                       if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
-                               strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
-                               && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {                    
                                
-                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-                                                               tmp2, ice_out->cands[0][0].transport, c4,
-                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
-                                                               a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
-                                                               );
+                               if (!zstr(a_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) && 
+                                       strcmp(a_engine->codec_params.local_sdp_ip, ice_out->cands[0][0].con_addr)
+                                       && a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {                    
+                                       
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
+                                                                       tmp2, ice_out->cands[0][0].transport, c4,
+                                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
+                                                                       a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
+                                                                       );
+                               }
                        }
                        
                                
@@ -4892,7 +4936,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
 
 
-               if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS)) {
+               if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) {
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
                        //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n");
                }
@@ -4917,7 +4961,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        char *bp = buf;
                        int both = switch_channel_test_flag(session->channel, CF_WEBRTC) ? 0 : 1;
 
-                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE))) {
+                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) || 
+                               switch_channel_test_flag(session->channel, CF_DTLS)) {
                                generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
                                bp = (buf + strlen(buf));
 
@@ -4953,7 +4998,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 
                                        cur_ptime = this_ptime;                 
                                        
-                                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE))) {
+                                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) || 
+                                               switch_channel_test_flag(session->channel, CF_DTLS)) {
                                                generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
                                                bp = (buf + strlen(buf));
 
@@ -4979,6 +5025,13 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
        
        if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) {
                const char *local_video_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_VIDEO);
+
+               if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+                       if (switch_channel_test_flag(smh->session->channel, CF_DTLS)) {
+                               local_video_crypto_key = NULL;
+                       }
+               }
+
                
                if (!v_engine->codec_params.local_sdp_port) {
                        switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 0);
@@ -4991,7 +5044,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        }
 
                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d RTP/%sAVP%s", 
-                                                       v_port, (!zstr(local_video_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) ? "S" : "",
+                                                       v_port, ((!zstr(local_video_crypto_key) || switch_channel_test_flag(session->channel, CF_DTLS)) 
+                                                                        && switch_channel_test_flag(session->channel, CF_SECURE)) ? "S" : "",
                                                        switch_channel_test_flag(session->channel, CF_WEBRTC) ? "F" : "");
 
 
@@ -5105,6 +5159,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                
                        }
 
+                       if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(smh->session->channel, CF_DTLS)) {
+                               generate_local_fingerprint(smh, SWITCH_MEDIA_TYPE_VIDEO);
+                       }
+
 
                        if (!zstr(v_engine->local_dtls_fingerprint.type)) {
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\n", v_engine->local_dtls_fingerprint.type, 
@@ -5115,6 +5173,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                        if (smh->mparams->rtcp_audio_interval_msec) {
                                if (v_engine->rtcp_mux > 0) {
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\n");
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", v_port, family, ip);
                                } else {
                                        switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", v_port + 1, family, ip);
                                }
@@ -5162,23 +5221,25 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                }
 
 
-                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
-                                                               tmp1, ice_out->cands[0][0].transport, c2,
-                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
-                                                               );
-
+                               if (v_engine->rtcp_mux < 1 || switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
 
-                               if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
-                                       strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
-                                       && v_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
-                                       
-                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\n", 
-                                                                       tmp2, ice_out->cands[0][0].transport, c4,
-                                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
-                                                                       v_engine->codec_params.local_sdp_ip, v_engine->codec_params.local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
+                                                                       tmp1, ice_out->cands[0][0].transport, c2,
+                                                                       ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
                                                                        );
-                               }
                                        
+                                       
+                                       if (!zstr(v_engine->codec_params.local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) && 
+                                               strcmp(v_engine->codec_params.local_sdp_ip, ice_out->cands[0][1].con_addr)
+                                               && v_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
+                                               
+                                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\n", 
+                                                                               tmp2, ice_out->cands[0][0].transport, c4,
+                                                                               ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
+                                                                               v_engine->codec_params.local_sdp_ip, v_engine->codec_params.local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
+                                                                               );
+                                       }
+                               }
 
                        
                                
@@ -5190,8 +5251,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                
 
 
-                       if (switch_channel_test_flag(session->channel, CF_SECURE) && !zstr(local_video_crypto_key) && 
-                               !switch_channel_test_flag(session->channel, CF_DTLS)) {
+                       if (switch_channel_test_flag(session->channel, CF_SECURE) && !zstr(local_video_crypto_key)){
                                switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_video_crypto_key);
                                //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
                        }                       
index 6dd3b69298b89bb75db82315693c1db059cffbec..5afb17d3a2de40348f18d13cba183364e1e61f34 100644 (file)
@@ -677,6 +677,9 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
                sock_output = rtp_session->rtcp_sock_output;            
                remote_addr = rtp_session->rtcp_remote_addr;
        }
+       
+
+
 
        switch_assert(rtp_session != NULL);
        switch_assert(ice->ice_user != NULL);
@@ -1936,7 +1939,7 @@ static const char *dtls_state_names(dtls_state_t s)
 }
 
 
-#define dtls_set_state(_dtls, _state) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Changing DTLS state from %s to %s\n", dtls_state_names(_dtls->state), dtls_state_names(_state)); _dtls->state = _state
+#define dtls_set_state(_dtls, _state) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Changing %s DTLS state from %s to %s\n", rtp_type(rtp_session), dtls_state_names(_dtls->state), dtls_state_names(_state)); _dtls->state = _state
 
 static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
 {
@@ -1952,14 +1955,16 @@ static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
        X509 *cert;
        int r = 0;
 
-       if ((cert = SSL_get_peer_certificate(dtls->ssl))) {
+       if ((dtls->type & DTLS_TYPE_SERVER)) {
+               r = 1;
+       } else if ((cert = SSL_get_peer_certificate(dtls->ssl))) {
                switch_core_cert_extract_fingerprint(cert, dtls->remote_fp);
                r = switch_core_cert_verify(dtls->remote_fp);
                X509_free(cert);
        }
 
        if (!r) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Fingerprint Verification Failed!.\n");
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s Fingerprint Verification Failed!\n", rtp_type(rtp_session));
                dtls_set_state(dtls, DS_FAIL);
                return -1;
        } else {
@@ -1967,10 +1972,10 @@ static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
                unsigned char *local_key, *remote_key, *local_salt, *remote_salt;
                unsigned char local_key_buf[cr_kslen] = {0}, remote_key_buf[cr_kslen] = {0};
                
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Fingerprint Verified.\n");
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "%s Fingerprint Verified.\n", rtp_type(rtp_session));
 
                if (!SSL_export_keying_material(dtls->ssl, raw_key_data, sizeof(raw_key_data), "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Key material export failure\n");
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s Key material export failure\n", rtp_type(rtp_session));
                        dtls_set_state(dtls, DS_FAIL);
                        return -1;
                }
@@ -2019,7 +2024,7 @@ static int dtls_state_handshake(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
                case SSL_ERROR_NONE:
                        break;
                default:
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Handshake failure %d\n", ret);
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s Handshake failure %d\n", rtp_type(rtp_session), ret);
                        dtls_set_state(dtls, DS_FAIL);
                        return -1;
                }
@@ -2041,7 +2046,7 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
        if (dtls->bytes) {
                if ((ret = BIO_write(dtls->read_bio, dtls->data, dtls->bytes)) != dtls->bytes) {
                        ret = SSL_get_error(dtls->ssl, ret);
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS packet read err %d\n", ret);
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet read err %d\n", rtp_type(rtp_session), ret);
                        dtls_set_state(dtls, DS_FAIL);
                        return -1;
                }
@@ -2058,7 +2063,7 @@ static int do_dtls(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
                bytes = len;
 
                if (switch_socket_sendto(dtls->sock_output, dtls->remote_addr, 0, data, &bytes ) != SWITCH_STATUS_SUCCESS) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS packet not written\n");
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS packet not written\n", rtp_type(rtp_session));
                } else {
                        if (BIO_reset(dtls->write_bio));
                }
@@ -2089,7 +2094,7 @@ static int cb_verify_peer(int preverify_ok, X509_STORE_CTX *ctx)
 
                X509_free(cert);
        } else {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(dtls->rtp_session->session), SWITCH_LOG_ERROR, "CERT ERR!\n");
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(dtls->rtp_session->session), SWITCH_LOG_ERROR, "%s CERT ERR!\n", rtp_type(dtls->rtp_session));
        }
 
        return r;
@@ -2109,6 +2114,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "INVALID TYPE!\n");
        }
 
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, 
+                                         "Activate %s DTLS %s\n", rtp_type(rtp_session), (type & DTLS_TYPE_SERVER) ? "server" : "cleint");
+
        if (!(dtls = rtp_session->dtls)) {
                dtls = switch_core_alloc(rtp_session->pool, sizeof(*dtls));
 
@@ -2121,8 +2129,11 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
                switch_assert(dtls->ssl_ctx);
 
                SSL_CTX_set_mode(dtls->ssl_ctx, SSL_MODE_AUTO_RETRY);
+
+
                //SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
                SSL_CTX_set_verify(dtls->ssl_ctx, SSL_VERIFY_NONE, NULL); 
+
                SSL_CTX_set_cipher_list(dtls->ssl_ctx, "ALL");
                
 
@@ -2141,22 +2152,23 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, d
                BIO_set_mem_eof_return(dtls->write_bio, -1);
 
                if ((ret=SSL_CTX_use_certificate_file(dtls->ssl_ctx, dtls->rsa, SSL_FILETYPE_PEM)) != 1) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS cert err [%d]\n", SSL_get_error(dtls->ssl, ret));
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS cert err [%d]\n", rtp_type(rtp_session), SSL_get_error(dtls->ssl, ret));
                        return SWITCH_STATUS_FALSE;
                }
 
                if ((ret=SSL_CTX_use_PrivateKey_file(dtls->ssl_ctx, dtls->pvt, SSL_FILETYPE_PEM)) != 1) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS key err [%d]\n", SSL_get_error(dtls->ssl, ret));
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS key err [%d]\n", rtp_type(rtp_session), SSL_get_error(dtls->ssl, ret));
                        return SWITCH_STATUS_FALSE;
                }
 
                if (SSL_CTX_check_private_key(dtls->ssl_ctx) == 0) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS check key failed\n");
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS check key failed\n", rtp_type(rtp_session));
                        return SWITCH_STATUS_FALSE;
                }
 
                if (!zstr(dtls->ca) && (ret=SSL_CTX_load_verify_locations(dtls->ssl_ctx, dtls->ca, NULL)) != 1) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "DTLS check chain cert failed [%d]\n", 
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "%s DTLS check chain cert failed [%d]\n",
+                                                         rtp_type(rtp_session) ,
                                                          SSL_get_error(dtls->ssl, ret));
                        return SWITCH_STATUS_FALSE;
                }
@@ -3520,8 +3532,19 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
                } else {
                        rtp_session->dtls->bytes = 0;
                        rtp_session->dtls->data = NULL;
+                       
+                       if (*b != 0 && *b != 1 && rtp_session->dtls->state != DS_READY) {
+                               *bytes = 0;
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Drop %s packet %ld bytes (dtls not ready!)\n", rtp_type(rtp_session), *bytes);
+                       }
+
                }
+
                do_dtls(rtp_session, rtp_session->dtls);
+
+               if (rtp_session->dtls->bytes) {
+                       *bytes = 0;
+               }
        }
        
        if (status == SWITCH_STATUS_SUCCESS && *bytes) { 
@@ -3843,6 +3866,10 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
                }
 
                do_dtls(rtp_session, rtp_session->rtcp_dtls);
+
+               if (rtp_session->rtcp_dtls->bytes) {
+                       *bytes = 0;
+               }
        }
 
 
@@ -5057,6 +5084,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
        }
 
        if (rtp_session->dtls && rtp_session->dtls->state != DS_READY) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Skip sending %s packet %ld bytes (dtls not ready!)\n", rtp_type(rtp_session), bytes);
                send = 0;
        }