diff --git a/src/switch_core_media.c b/src/switch_core_media.c index c24a2b05d1..253edbcf8a 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -608,8 +608,8 @@ SWITCH_DECLARE(void) switch_core_media_parse_rtp_bugs(switch_rtp_bug_flag_t *fla static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh, - switch_secure_settings_t *ssec, - int index, switch_rtp_crypto_key_type_t type, switch_rtp_crypto_direction_t direction) + switch_media_type_t type, + int index, switch_rtp_crypto_key_type_t ctype, switch_rtp_crypto_direction_t direction) { unsigned char b64_key[512] = ""; const char *type_str; @@ -617,24 +617,42 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh const char *val; switch_channel_t *channel; char *p; + switch_rtp_engine_t *engine; switch_assert(smh); channel = switch_core_session_get_channel(smh->session); - if (type == AES_CM_128_HMAC_SHA1_80) { + engine = &smh->engines[type]; + + if (ctype == AES_CM_128_HMAC_SHA1_80) { type_str = SWITCH_RTP_CRYPTO_KEY_80; } else { type_str = SWITCH_RTP_CRYPTO_KEY_32; } - if (direction == SWITCH_RTP_CRYPTO_SEND) { - key = ssec->local_raw_key; + +#ifdef SAME_KEY + if (switch_channel_test_flag(channel, CF_WEBRTC) && type == SWITCH_MEDIA_TYPE_VIDEO) { + if (direction == SWITCH_RTP_CRYPTO_SEND) { + memcpy(engine->ssec.local_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.local_raw_key, SWITCH_RTP_KEY_LEN); + key = engine->ssec.local_raw_key; + } else { + memcpy(engine->ssec.remote_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.remote_raw_key, SWITCH_RTP_KEY_LEN); + key = engine->ssec.remote_raw_key; + } } else { - key = ssec->remote_raw_key; - +#endif + if (direction == SWITCH_RTP_CRYPTO_SEND) { + key = engine->ssec.local_raw_key; + } else { + key = engine->ssec.remote_raw_key; + } + + switch_rtp_get_random(key, SWITCH_RTP_KEY_LEN); +#ifdef SAME_KEY } +#endif - switch_rtp_get_random(key, SWITCH_RTP_KEY_LEN); switch_b64_encode(key, SWITCH_RTP_KEY_LEN, b64_key, sizeof(b64_key)); p = strrchr((char *) b64_key, '='); @@ -642,14 +660,16 @@ static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh *p-- = '\0'; } - ssec->local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, type_str, b64_key); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local Key [%s]\n", ssec->local_crypto_key); + + + engine->ssec.local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, type_str, b64_key); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local Key [%s]\n", engine->ssec.local_crypto_key); if (!(smh->mparams->ndlb & SM_NDLB_DISABLE_SRTP_AUTH) && !((val = switch_channel_get_variable(channel, "NDLB_support_asterisk_missing_srtp_auth")) && switch_true(val))) { - ssec->crypto_type = type; + engine->ssec.crypto_type = ctype; } else { - ssec->crypto_type = AES_CM_128_NULL_AUTH; + engine->ssec.crypto_type = AES_CM_128_NULL_AUTH; } return SWITCH_STATUS_SUCCESS; @@ -783,12 +803,12 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) { switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_32); - switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); + switch_core_media_build_crypto(session->media_handle, type, crypto_tag, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), engine->ssec.crypto_type, engine->ssec.local_raw_key, SWITCH_RTP_KEY_LEN); } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) { switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_80); - switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); + switch_core_media_build_crypto(session->media_handle, type, crypto_tag, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), engine->ssec.crypto_type, engine->ssec.local_raw_key, SWITCH_RTP_KEY_LEN); } else { @@ -821,10 +841,10 @@ SWITCH_DECLARE(int) switch_core_session_check_incoming_crypto(switch_core_sessio if (zstr(engine->ssec.local_crypto_key)) { if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) { switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_32); - switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); + switch_core_media_build_crypto(session->media_handle, type, crypto_tag, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) { switch_channel_set_variable(session->channel, varname, SWITCH_RTP_CRYPTO_KEY_80); - switch_core_media_build_crypto(session->media_handle, &engine->ssec, crypto_tag, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); + switch_core_media_build_crypto(session->media_handle, type, crypto_tag, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n"); } @@ -846,15 +866,15 @@ SWITCH_DECLARE(void) switch_core_session_check_outgoing_crypto(switch_core_sessi 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, - &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); + SWITCH_MEDIA_TYPE_AUDIO, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); switch_core_media_build_crypto(session->media_handle, - &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); + SWITCH_MEDIA_TYPE_VIDEO, 1, AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND); } else if (!strcasecmp(var, SWITCH_RTP_CRYPTO_KEY_80)) { switch_channel_set_flag(channel, CF_SECURE); switch_core_media_build_crypto(session->media_handle, - &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); + SWITCH_MEDIA_TYPE_AUDIO, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); switch_core_media_build_crypto(session->media_handle, - &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); + SWITCH_MEDIA_TYPE_VIDEO, 1, AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND); } } @@ -921,7 +941,7 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO] + (uint32_t) time(NULL)); session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssrc = - (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO] + (uint32_t) time(NULL)); + (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO] + (uint32_t) time(NULL) / 2); status = SWITCH_STATUS_SUCCESS; } @@ -1828,7 +1848,9 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "Choose Candidate cid: %d proto: %s type: %s addr: %s\n", cid+1, fields[2], fields[7], fields[4]); + "Choose %s Candidate cid: %d proto: %s type: %s addr: %s\n", + type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio", + cid+1, fields[2], fields[7], fields[4]); engine->ice_in.cands[cid].foundation = switch_core_session_strdup(smh->session, fields[0]); @@ -2068,6 +2090,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s 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"; } if (m->m_proto == sdp_proto_srtp || m->m_proto == sdp_proto_extended_srtp) { @@ -2627,16 +2650,15 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s switch_channel_set_variable(session->channel, "sip_video_recv_pt", tmp); if (!match && vmatch) match = 1; + check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, m); + break; } else { vmatch = 0; } } } - - if (vmatch) { - check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, m); - } + } } @@ -3542,6 +3564,32 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi (smh->mparams->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0); } + + if (a_engine->ice_in.cands[0].ready) { + + gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, "", 0); + + switch_rtp_activate_ice(a_engine->rtp_session, + a_engine->ice_in.ufrag, + a_engine->ice_out.ufrag, + a_engine->ice_out.pwd, + a_engine->ice_in.pwd, + +#ifdef GOOGLE_ICE + ICE_GOOGLE_JINGLE, + 0 +#else + ICE_VANILLA | ICE_CONTROLLED, + a_engine->ice_in.cands[0].priority +#endif + ); + + + + } + + + if ((val = switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec")) || (val = smh->mparams->rtcp_audio_interval_msec)) { const char *rport = switch_channel_get_variable(session->channel, "sip_remote_audio_rtcp_port"); switch_port_t remote_port = 0; @@ -3559,6 +3607,25 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_port); } } + + + if (a_engine->ice_in.cands[1].ready) { + + switch_rtp_activate_rtcp_ice(a_engine->rtp_session, + a_engine->ice_in.ufrag, + a_engine->ice_out.ufrag, + a_engine->ice_out.pwd, + a_engine->ice_in.pwd, +#ifdef GOOGLE_ICE + ICE_GOOGLE_JINGLE, + 0 +#else + ICE_VANILLA | ICE_CONTROLLED, + a_engine->ice_in.cands[1].priority +#endif + ); + } + } if ((val = switch_channel_get_variable(session->channel, "jitterbuffer_msec")) || (val = smh->mparams->jb_msec)) { @@ -3699,53 +3766,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc); + - if (a_engine->ice_in.cands[0].ready) { - - gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, "", 0); - - switch_rtp_activate_ice(a_engine->rtp_session, - a_engine->ice_in.ufrag, - a_engine->ice_out.ufrag, - a_engine->ice_out.pwd, - a_engine->ice_in.pwd, - -#ifdef GOOGLE_ICE - ICE_GOOGLE_JINGLE, - 0 -#else - ICE_VANILLA | ICE_CONTROLLED, - a_engine->ice_in.cands[0].priority -#endif - ); - - - if (a_engine->ice_in.cands[1].ready) { - - switch_rtp_activate_rtcp_ice(a_engine->rtp_session, - a_engine->ice_in.ufrag, - a_engine->ice_out.ufrag, - a_engine->ice_out.pwd, - a_engine->ice_in.pwd, -#ifdef GOOGLE_ICE - ICE_GOOGLE_JINGLE, - 0 -#else - ICE_VANILLA | ICE_CONTROLLED, - a_engine->ice_in.cands[1].priority -#endif - ); - } - } - - - + video: - + if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { switch_core_media_check_video_codecs(session); } - + if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && v_engine->codec_params.rm_encoding && v_engine->codec_params.remote_sdp_port) { /******************************************************************************************/ if (v_engine->rtp_session && switch_channel_test_flag(session->channel, CF_REINVITE)) { @@ -3903,6 +3932,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi v_engine->ssrc = ssrc_ul; } + if (v_engine->ice_in.cands[0].ready) { gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, "", 0); @@ -3922,7 +3952,28 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi #endif ); - + } + + + if ((val = switch_channel_get_variable(session->channel, "rtcp_video_interval_msec")) || (val = smh->mparams->rtcp_video_interval_msec)) { + const char *rport = switch_channel_get_variable(session->channel, "sip_remote_video_rtcp_port"); + switch_port_t remote_port = 0; + if (rport) { + remote_port = (switch_port_t)atoi(rport); + } + if (!strcasecmp(val, "passthru")) { + switch_rtp_activate_rtcp(v_engine->rtp_session, -1, remote_port); + } else { + int interval = atoi(val); + if (interval < 100 || interval > 5000) { + 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_rtp_activate_rtcp(v_engine->rtp_session, interval, remote_port); + } + } + + if (v_engine->ice_in.cands[1].ready) { switch_rtp_activate_rtcp_ice(v_engine->rtp_session, @@ -3939,9 +3990,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi #endif ); } - } + - + } + + + + if ((val = switch_channel_get_variable(session->channel, "rtp_manual_video_rtp_bugs"))) { switch_core_media_parse_rtp_bugs(&v_engine->rtp_bugs, val); } @@ -3960,26 +4015,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_core_session_apply_crypto(session, SWITCH_MEDIA_TYPE_VIDEO, "rtp_secure_video_confirmed"); - - if ((val = switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec")) - || (val = smh->mparams->rtcp_audio_interval_msec)) { - const char *rport = switch_channel_get_variable(session->channel, "sip_remote_video_rtcp_port"); - switch_port_t remote_port = 0; - if (rport) { - remote_port = (switch_port_t)atoi(rport); - } - if (!strcasecmp(val, "passthru")) { - switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_port); - } else { - int interval = atoi(val); - if (interval < 100 || interval > 5000) { - 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_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_port); - } - } - } + if (switch_channel_test_flag(session->channel, CF_ZRTP_PASSTHRU)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating video UDPTL mode\n"); switch_rtp_udptl_mode(v_engine->rtp_session); @@ -4711,6 +4747,8 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess // 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; diff --git a/src/switch_rtp.c b/src/switch_rtp.c index f132d89416..63dd4bf448 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -55,7 +55,7 @@ #define WRITE_DEC(rtp_session) switch_mutex_unlock(rtp_session->write_mutex); rtp_session->writing-- -#define RTP_DEFAULT_STUNCOUNT 100; +#define RTP_DEFAULT_STUNCOUNT 25; #define rtp_header_len 12 #define RTP_START_PORT 16384 #define RTP_END_PORT 32768 @@ -351,6 +351,11 @@ typedef enum { static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session); + +#define rtp_type(rtp_session) rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio" + + + static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_size_t bytes, int *do_cng) { @@ -794,6 +799,8 @@ 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 %d\n", rtp_type(rtp_session), ok); + if ((packet->header.type == SWITCH_STUN_BINDING_REQUEST) && ok) { uint8_t stunbuf[512]; switch_stun_packet_t *rpacket; @@ -891,7 +898,7 @@ static void zrtp_event_callback(zrtp_stream_t *stream, unsigned event) switch_event_t *fsevent = NULL; const char *type; - type = rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio"; + type = rtp_type(rtp_session) switch (event) { case ZRTP_EVENT_IS_SECURE: @@ -2450,6 +2457,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio { char ice_user[80]; char user_ice[80]; + switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session"); if ((type & ICE_VANILLA)) { switch_snprintf(ice_user, sizeof(ice_user), "%s:%s", login, rlogin); @@ -2459,6 +2467,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio switch_snprintf(user_ice, sizeof(user_ice), "%s%s", rlogin, login); } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating %s ICE: %s\n", rtp_type(rtp_session), ice_user); + + rtp_session->ice.ice_user = switch_core_strdup(rtp_session->pool, ice_user); rtp_session->ice.user_ice = switch_core_strdup(rtp_session->pool, user_ice); rtp_session->ice.type = type; @@ -3208,7 +3219,8 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t #endif #ifdef ENABLE_SRTP - if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && (!rtp_session->ice.ice_user || rtp_session->recv_msg.header.version == 2)) { + if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && rtp_session->recv_msg.header.version == 2) { + //if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && (!rtp_session->ice.ice_user || rtp_session->recv_msg.header.version == 2)) { int sbytes = (int) *bytes; err_status_t stat = 0; @@ -3235,7 +3247,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t if (++rtp_session->srtp_errs >= MAX_SRTP_ERRS) { switch_core_session_t *session = switch_core_memory_pool_get_data(rtp_session->pool, "__session"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, - "Error: SRTP unprotect failed with code %d%s\n", stat, + "Error: SRTP %s unprotect failed with code %d%s\n", rtp_type(rtp_session), stat, stat == err_status_replay_fail ? " (replay check failed)" : stat == err_status_auth_fail ? " (auth check failed)" : ""); return SWITCH_STATUS_FALSE; @@ -4544,11 +4556,12 @@ static int rtp_common_write(switch_rtp_t *rtp_session, send = 0; } +#if 0 if (rtp_session->ice.ice_user && !rtp_session->ice.ready) { - send = 0; + //send = 0; //printf("skip no stun love\n"); } - +#endif if (send) { send_msg->header.seq = htons(++rtp_session->seq);