From 1c120dd2c88dcdffad0c4befd128ed46f00fba50 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 Jan 2013 22:56:02 -0600 Subject: [PATCH] not too shabby audio and vid work both directions but browswer hates our srtcp ... --- src/mod/endpoints/mod_sofia/mod_sofia.c | 17 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- src/switch_core_media.c | 316 +++++++++++++++++------ src/switch_rtp.c | 32 +-- 4 files changed, 261 insertions(+), 106 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index b93e1ef6e3..8fb4b5d194 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -93,10 +93,6 @@ static switch_status_t sofia_on_init(switch_core_session_t *session) } if (sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) { - - switch_core_session_check_outgoing_crypto(session, SOFIA_SECURE_MEDIA_VARIABLE); - - if (sofia_glue_do_invite(session) != SWITCH_STATUS_SUCCESS) { switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); assert(switch_channel_get_state(channel) != CS_INIT); @@ -1250,7 +1246,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } - if ((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) && + if (((var = switch_channel_get_variable(channel, SOFIA_SECURE_MEDIA_VARIABLE)) || + (var = switch_channel_get_variable(channel, "rtp_secure_media"))) && (switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_80))) { switch_channel_set_flag(tech_pvt->channel, CF_SECURE); } @@ -4135,6 +4132,16 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session tech_pvt->dest_to = tech_pvt->dest; } + if ((hval = switch_event_get_header(var_event, "media_webrtc")) && switch_true(hval)) { + switch_channel_set_variable(nchannel, "rtp_secure_media", SWITCH_RTP_CRYPTO_KEY_80); + } + + if ((hval = switch_event_get_header(var_event, SOFIA_SECURE_MEDIA_VARIABLE)) || + (hval = switch_event_get_header(var_event, "rtp_secure_media"))) { + + switch_channel_set_variable(nchannel, "rtp_secure_media", hval); + } + sofia_glue_attach_private(nsession, profile, tech_pvt, dest); if (tech_pvt->local_url) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index f00c63f7b0..a4b4749222 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -77,7 +77,7 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t * switch_assert(session != NULL); switch_assert(profile != NULL); switch_assert(tech_pvt != NULL); - + switch_core_session_add_stream(session, NULL); switch_mutex_lock(tech_pvt->flag_mutex); diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 3a96401ab6..581deeceb2 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -47,6 +47,7 @@ SWITCH_DECLARE(void) switch_core_media_set_r_sdp_codec_string(switch_core_sessio #define MAX_CODEC_CHECK_FRAMES 50//x:mod_sofia.h #define MAX_MISMATCH_FRAMES 5//x:mod_sofia.h +#define type2str(type) type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio" typedef enum { SMF_INIT = (1 << 0), @@ -117,7 +118,7 @@ typedef struct ice_s { char *pwd; char *options; - + } ice_t; @@ -187,6 +188,10 @@ struct switch_media_handle_s { uint32_t session_id; switch_core_media_params_t *mparams; + + char *msid; + char *cname; + }; static void _switch_core_media_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session, switch_media_type_t type) @@ -630,7 +635,7 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh type_str = SWITCH_RTP_CRYPTO_KEY_32; } - +#define SAME_KEY #ifdef SAME_KEY if (switch_channel_test_flag(channel, CF_WEBRTC) && type == SWITCH_MEDIA_TYPE_VIDEO) { if (direction == SWITCH_RTP_CRYPTO_SEND) { @@ -786,8 +791,6 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio if (!session->media_handle) return 0; engine = &session->media_handle->engines[type]; - if (type == SWITCH_MEDIA_TYPE_VIDEO) printf("XXXXXXXXXXXXXXXXXXXXXXXXX\n"); - if (engine->ssec.remote_crypto_key && switch_rtp_ready(engine->rtp_session)) { /* Compare all the key. The tag may remain the same even if key changed */ if (crypto && !strcmp(crypto, engine->ssec.remote_crypto_key)) { @@ -860,10 +863,13 @@ 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)) return; + if (!switch_core_session_media_handle_ready(session) == SWITCH_STATUS_SUCCESS) { + return; + } if ((var = switch_channel_get_variable(channel, sec_var)) && !zstr(var)) { if (switch_true(var) || !strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_32)) { + switch_channel_set_flag(channel, CF_SECURE); switch_core_media_build_crypto(session->media_handle, SWITCH_MEDIA_TYPE_AUDIO, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); @@ -986,6 +992,7 @@ SWITCH_DECLARE(int32_t) switch_media_handle_test_media_flag(switch_media_handle_ SWITCH_DECLARE(switch_status_t) switch_core_session_media_handle_ready(switch_core_session_t *session) { + if (session->media_handle && switch_test_flag(session->media_handle, SMF_INIT)) { return SWITCH_STATUS_SUCCESS; } @@ -1793,6 +1800,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ switch_rtp_engine_t *engine = &smh->engines[type]; sdp_attribute_t *attr; int i = 0; + char tmp[80] = ""; for (attr = m->m_attributes; attr; attr = attr->a_next) { char *data; @@ -1859,7 +1867,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ engine->ice_in.cands[cid].priority = atol(fields[3]); engine->ice_in.cands[cid].con_addr = switch_core_session_strdup(smh->session, fields[4]); engine->ice_in.cands[cid].con_port = atoi(fields[5]); - + j = 6; while(j < argc && fields[j+1]) { @@ -1893,6 +1901,26 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ } } + + if (engine->ice_in.cands[0].con_addr && engine->ice_in.cands[0].con_port) { + engine->codec_params.remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[0].con_addr); + engine->codec_params.remote_sdp_port = (switch_port_t) engine->ice_in.cands[0].con_port; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, + "setting remote %s addr to %s:%d based on candidate\n", type2str(type), + engine->ice_in.cands[0].con_addr, engine->ice_in.cands[0].con_port); + + switch_snprintf(tmp, sizeof(tmp), "%d", engine->codec_params.remote_sdp_port); + switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->codec_params.remote_sdp_ip); + switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); + } + + if (engine->ice_in.cands[1].con_port) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, + "setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type), + engine->ice_in.cands[1].con_addr, engine->ice_in.cands[1].con_port); + engine->remote_rtcp_port = engine->ice_in.cands[1].con_port; + } + } //? @@ -2460,9 +2488,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s a_engine->codec_params.rm_rate = mimp->samples_per_second; a_engine->codec_params.codec_ms = mimp->microseconds_per_packet / 1000; a_engine->codec_params.bitrate = mimp->bits_per_second; + + a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address); - a_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); a_engine->codec_params.remote_sdp_port = (switch_port_t) m->m_port; + a_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); + a_engine->codec_params.agreed_pt = (switch_payload_t) map->rm_pt; smh->num_negotiated_codecs = 0; smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp; @@ -2558,8 +2589,6 @@ 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) { - printf("WTF %s == %s\n", attr->a_name, attr->a_value); - if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) { //framerate = atoi(attr->a_value); } @@ -2629,9 +2658,13 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s v_engine->codec_params.pt = (switch_payload_t) map->rm_pt; v_engine->codec_params.rm_rate = map->rm_rate; v_engine->codec_params.codec_ms = mimp->microseconds_per_packet / 1000; + + v_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address); - v_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); v_engine->codec_params.remote_sdp_port = (switch_port_t) m->m_port; + + v_engine->codec_params.rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp); + v_engine->codec_params.agreed_pt = (switch_payload_t) map->rm_pt; switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->codec_params.remote_sdp_port); switch_channel_set_variable(session->channel, SWITCH_REMOTE_VIDEO_IP_VARIABLE, v_engine->codec_params.remote_sdp_ip); @@ -3213,7 +3246,7 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co { switch_media_handle_t *smh; switch_rtp_engine_t *engine; - char tmp[17] = ""; + char tmp[33] = ""; switch_assert(session); @@ -3222,9 +3255,22 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co } engine = &smh->engines[type]; + + if (!smh->msid) { + switch_stun_random_string(tmp, 32, NULL); + tmp[32] = '\0'; + smh->msid = switch_core_session_strdup(session, tmp); + } + + if (!smh->cname) { + switch_stun_random_string(tmp, 16, NULL); + tmp[16] = '\0'; + smh->cname = switch_core_session_strdup(session, tmp); + } if (!engine->ice_out.ufrag) { switch_stun_random_string(tmp, 16, NULL); + tmp[16] = '\0'; engine->ice_out.ufrag = switch_core_session_strdup(session, tmp); } @@ -3234,8 +3280,8 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co } if (!engine->ice_out.cands[0].foundation) { - tmp[10] = '\0'; switch_stun_random_string(tmp, 10, "0123456789"); + tmp[10] = '\0'; engine->ice_out.cands[0].foundation = switch_core_session_strdup(session, tmp); } @@ -3246,12 +3292,14 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co engine->ice_out.cands[0].priority = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - engine->ice_out.cands[0].component_id); } - if (ip) { + if (!zstr(ip)) { engine->ice_out.cands[0].con_addr = switch_core_session_strdup(session, ip); } + if (port) { engine->ice_out.cands[0].con_port = port; } + engine->ice_out.cands[0].generation = "0"; //add rport stuff later @@ -3505,6 +3553,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10); switch_rtp_set_ssrc(a_engine->rtp_session, ssrc_ul); a_engine->ssrc = ssrc_ul; + } else { + switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc); } @@ -3570,7 +3620,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi if (a_engine->ice_in.cands[0].ready) { - gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, "", 0); + gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Audio ICE\n"); switch_rtp_activate_ice(a_engine->rtp_session, a_engine->ice_in.ufrag, @@ -3600,8 +3652,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi if (!remote_rtcp_port && rport) { remote_rtcp_port = (switch_port_t)atoi(rport); } - + if (!strcasecmp(val, "passthru")) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP PASSTHRU PORT %d\n", remote_rtcp_port); switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_rtcp_port); } else { int interval = atoi(val); @@ -3609,12 +3662,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval); } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP PORT %d\n", remote_rtcp_port); switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_rtcp_port); } } if (a_engine->ice_in.cands[1].ready) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n"); switch_rtp_activate_rtcp_ice(a_engine->rtp_session, a_engine->ice_in.ufrag, @@ -3770,7 +3825,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi } - switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc); + @@ -3937,13 +3992,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10); switch_rtp_set_ssrc(v_engine->rtp_session, ssrc_ul); v_engine->ssrc = ssrc_ul; + } else { + switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc); } if (v_engine->ice_in.cands[0].ready) { - gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, "", 0); + gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Video ICE\n"); + switch_rtp_activate_ice(v_engine->rtp_session, v_engine->ice_in.ufrag, v_engine->ice_out.ufrag, @@ -3969,6 +4028,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi remote_port = (switch_port_t)atoi(rport); } if (!strcasecmp(val, "passthru")) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP PASSTHRU PORT %d\n", remote_port); switch_rtp_activate_rtcp(v_engine->rtp_session, -1, remote_port); } else { int interval = atoi(val); @@ -3976,13 +4036,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval); } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP PORT %d\n", remote_port); switch_rtp_activate_rtcp(v_engine->rtp_session, interval, remote_port); } } if (v_engine->ice_in.cands[1].ready) { - + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n"); switch_rtp_activate_rtcp_ice(v_engine->rtp_session, v_engine->ice_in.ufrag, v_engine->ice_out.ufrag, @@ -4060,7 +4121,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi //? static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, - switch_port_t port, + switch_port_t port, const char *family, const char *ip, int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int verbose_sdp, int secure) { int i = 0; @@ -4070,6 +4131,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO); const char *local_sdp_audio_zrtp_hash; switch_media_handle_t *smh; + switch_rtp_engine_t *a_engine; switch_assert(session); @@ -4077,6 +4139,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, return; } + a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO]; switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP%s", port, secure ? "S" : "", switch_channel_test_flag(session->channel, CF_WEBRTC) ? "F" : ""); @@ -4131,6 +4194,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, memset(already_did, 0, sizeof(already_did)); + for (i = 0; i < smh->mparams->num_codecs; i++) { const switch_codec_implementation_t *imp = smh->codecs[i]; @@ -4193,6 +4257,67 @@ 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 (smh->mparams->rtcp_audio_interval_msec) { + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\n", port + 1, family, ip); + } + + //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", a_engine->ssrc); + + if (a_engine->ice_out.cands[0].ready) { + char tmp1[11] = ""; + char tmp2[11] = ""; + uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1); + uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2); + uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1); + uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2); + ice_t *ice_out; + + tmp1[10] = '\0'; + tmp2[10] = '\0'; + switch_stun_random_string(tmp1, 10, "0123456789"); + switch_stun_random_string(tmp2, 10, "0123456789"); + + gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0); + + ice_out = &a_engine->ice_out; + + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u cname:%s\n", a_engine->ssrc, smh->cname); + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u msid:%s a0\n", a_engine->ssrc, smh->msid); + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u mslabel:%s\n", a_engine->ssrc, smh->msid); + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u label:%sa0\n", a_engine->ssrc, smh->msid); + + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-ufrag:%s\n", ice_out->ufrag); + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd); + + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\n", + tmp1, ice_out->cands[0].transport, c1, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + ); + + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx generation 0\n", + tmp2, ice_out->cands[0].transport, c3, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + ); + + + 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].transport, c2, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + 1 + ); + + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\n", + tmp2, ice_out->cands[0].transport, c4, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + 1 + ); + + + +#ifdef GOOGLE_ICE + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-options:google-ice\n"); +#endif + } + + if (secure) { 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"); @@ -4371,6 +4496,19 @@ 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"))) { + switch_channel_set_flag(session->channel, CF_WEBRTC); + switch_channel_set_flag(session->channel, CF_ICE); + smh->mparams->rtcp_audio_interval_msec = "2500"; + smh->mparams->rtcp_video_interval_msec = "2500"; + } + } + fmtp_out = a_engine->codec_params.fmtp_out; username = smh->mparams->sdp_username; @@ -4495,7 +4633,6 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, ip, port); } - 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" : "", @@ -4584,6 +4721,12 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_stun_random_string(tmp2, 10, "0123456789"); ice_out = &a_engine->ice_out; + + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\n", a_engine->ssrc, smh->cname); + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s a0\n", a_engine->ssrc, smh->msid); + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\n", a_engine->ssrc, smh->msid); + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sa0\n", a_engine->ssrc, smh->msid); switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\n", ice_out->ufrag); switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd); @@ -4644,7 +4787,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess int both = 1; if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE))) { - generate_m(session, buf, SDPBUFLEN, port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1); + generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1); bp = (buf + strlen(buf)); /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/ @@ -4655,7 +4798,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } if (both) { - generate_m(session, bp, SDPBUFLEN - strlen(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0); + generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0); } } else { @@ -4680,7 +4823,7 @@ 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))) { - generate_m(session, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1); + 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)); /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/ @@ -4689,8 +4832,12 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } } + if (switch_channel_test_flag(session->channel, CF_WEBRTC)) { + both = 0; + } + if (both) { - generate_m(session, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0); + generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0); } } @@ -4747,67 +4894,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n"); - - - - if (smh->mparams->rtcp_audio_interval_msec) { - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", v_port + 1, family, ip); - } - - //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", v_engine->ssrc); - + if (v_engine->codec_params.rm_encoding) { const char *of; - - if (v_engine->ice_out.cands[0].ready) { - char tmp1[11] = ""; - char tmp2[11] = ""; - uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1); - uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2); - uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1); - uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2); - - tmp1[10] = '\0'; - tmp2[10] = '\0'; - switch_stun_random_string(tmp1, 10, "0123456789"); - switch_stun_random_string(tmp2, 10, "0123456789"); - - ice_out = &v_engine->ice_out; - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\n", ice_out->ufrag); - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd); - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\n", - tmp1, ice_out->cands[0].transport, c1, - ice_out->cands[0].con_addr, ice_out->cands[0].con_port - ); - - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx generation 0\n", - tmp2, ice_out->cands[0].transport, c3, - ice_out->cands[0].con_addr, ice_out->cands[0].con_port - ); - - - 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].transport, c2, - ice_out->cands[0].con_addr, ice_out->cands[0].con_port + 1 - ); - - 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].transport, c4, - ice_out->cands[0].con_addr, ice_out->cands[0].con_port + 1 - ); - - - -#ifdef GOOGLE_ICE - switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\n"); -#endif - } - - - rate = v_engine->codec_params.rm_rate; switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n", v_engine->codec_params.pt, v_engine->codec_params.rm_encoding, @@ -4884,6 +4974,68 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess } + + + if (smh->mparams->rtcp_audio_interval_msec) { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", v_port + 1, family, ip); + } + + //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\n", v_engine->ssrc); + + if (v_engine->ice_out.cands[0].ready) { + char tmp1[11] = ""; + char tmp2[11] = ""; + uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1); + uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2); + uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1); + uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2); + + tmp1[10] = '\0'; + tmp2[10] = '\0'; + switch_stun_random_string(tmp1, 10, "0123456789"); + switch_stun_random_string(tmp2, 10, "0123456789"); + + ice_out = &v_engine->ice_out; + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\n", v_engine->ssrc, smh->cname); + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\n", v_engine->ssrc, smh->msid); + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\n", v_engine->ssrc, smh->msid); + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sv0\n", v_engine->ssrc, smh->msid); + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\n", ice_out->ufrag); + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\n", ice_out->pwd); + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\n", + tmp1, ice_out->cands[0].transport, c1, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + ); + + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx generation 0\n", + tmp2, ice_out->cands[0].transport, c3, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + ); + + + 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].transport, c2, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + 1 + ); + + 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].transport, c4, + ice_out->cands[0].con_addr, ice_out->cands[0].con_port + 1 + ); + + + +#ifdef GOOGLE_ICE + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\n"); +#endif + } + + + + 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 5054d9a240..3af9f2d1a7 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -672,7 +672,6 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice) if ((ice->type & ICE_VANILLA)) { char sw[128] = ""; - //switch_stun_packet_attribute_add_use_candidate(packet); switch_stun_packet_attribute_add_priority(packet, ice->priority); @@ -683,12 +682,11 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice) switch_stun_packet_attribute_add_controlled(packet); } else { switch_stun_packet_attribute_add_controlling(packet); + switch_stun_packet_attribute_add_use_candidate(packet); } switch_stun_packet_attribute_add_integrity(packet, ice->rpass); switch_stun_packet_attribute_add_fingerprint(packet); - - } @@ -804,7 +802,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d ok = !strcmp(ice->user_ice, username); } - //printf("ICE %s %s ok:%d %d %d\n", rtp_type(rtp_session), ice == &rtp_session->rtcp_ice ? "rtcp" : "rtp", ok, rtp_session->ice.ready, rtp_session->ice.rready); + //printf("XXX ICE %s %s ok:%d %d %d\n", rtp_type(rtp_session), ice == &rtp_session->rtcp_ice ? "rtcp" : "rtp", ok, rtp_session->ice.ready, rtp_session->ice.rready); if ((packet->header.type == SWITCH_STUN_BINDING_REQUEST) && ok) { uint8_t stunbuf[512]; @@ -834,13 +832,6 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d switch_stun_packet_attribute_add_binded_address(rpacket, (char *) remote_ip, switch_sockaddr_get_port(from_addr)); if ((ice->type & ICE_VANILLA)) { - - - //if (!(ice->type && ICE_CONTROLLED)) { - // switch_stun_packet_attribute_add_use_candidate(rpacket); - // switch_stun_packet_attribute_add_priority(rpacket, ice->priority); - //} - switch_stun_packet_attribute_add_integrity(rpacket, ice->pass); switch_stun_packet_attribute_add_fingerprint(rpacket); @@ -1859,7 +1850,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess break; case AES_CM_128_HMAC_SHA1_32: crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy->rtp); - crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy->rtcp); + crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy->rtcp); + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { switch_channel_set_variable(channel, "sip_has_crypto", "AES_CM_128_HMAC_SHA1_32"); @@ -1877,12 +1869,12 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess break; } - policy->next = NULL; policy->key = (uint8_t *) crypto_key->key; + policy->next = NULL; + - - //policy->rtp.sec_serv = sec_serv_conf_and_auth; - //policy->rtcp.sec_serv = sec_serv_conf_and_auth; + policy->rtp.sec_serv = sec_serv_conf_and_auth; + policy->rtcp.sec_serv = sec_serv_conf_and_auth; switch (direction) { case SWITCH_RTP_CRYPTO_RECV: @@ -3581,6 +3573,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } } + + if (poll_status == SWITCH_STATUS_SUCCESS) { if (read_pretriggered) { read_pretriggered = 0; @@ -3738,6 +3732,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } + if (bytes && rtp_session->recv_msg.header.version == 2 && !rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] && rtp_session->recv_msg.header.pt != 13 && @@ -3745,6 +3740,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ (!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) && rtp_session->recv_msg.header.pt != rtp_session->rpayload && !(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS)) { /* drop frames of incorrect payload number and return CNG frame instead */ + return_cng_frame(); } @@ -4015,7 +4011,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ return_cng_frame(); } } - + if (status == SWITCH_STATUS_BREAK || bytes == 0) { if (!(io_flags & SWITCH_IO_FLAG_SINGLE_READ) && rtp_session->flags[SWITCH_RTP_FLAG_DATAWAIT]) { goto do_continue; @@ -4556,7 +4552,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session, if (rtp_session->ice.ice_user && !(rtp_session->ice.rready)) { send = 0; - //printf("skip no stun love %d/%d\n", rtp_session->ice.ready, rtp_session->ice.rready); + //printf("XXX skip no stun love %d/%d\n", rtp_session->ice.ready, rtp_session->ice.rready); }