From a01ad9a1aafe0039b40f57e5a1391da150fde08e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 2 Feb 2013 00:15:09 -0600 Subject: [PATCH] dtls both ways now --- src/switch_core_media.c | 204 ++++++++++++++++++++++++++-------------- src/switch_rtp.c | 54 ++++++++--- 2 files changed, 173 insertions(+), 85 deletions(-) diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 908dba0e3d..4b5c830ae3 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -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, ); } - - 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) { + 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 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) + + 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) + ); + } } @@ -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) - ); - - - - 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) + 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) + ); + } } @@ -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"); } diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 6dd3b69298..5afb17d3a2 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -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; }