diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 477aa3b877..4699cd238f 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -170,6 +170,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_CACHE_SPEECH_HANDLES_OBJ_NAME "__cache_speech_handles_obj__" #define SWITCH_BYPASS_MEDIA_VARIABLE "bypass_media" #define SWITCH_PROXY_MEDIA_VARIABLE "proxy_media" +#define SWITCH_ZRTP_PASSTHRU_VARIABLE "zrtp_passthru" #define SWITCH_ENDPOINT_DISPOSITION_VARIABLE "endpoint_disposition" #define SWITCH_HOLD_MUSIC_VARIABLE "hold_music" #define SWITCH_TEMP_HOLD_MUSIC_VARIABLE "temp_hold_music" @@ -1213,8 +1214,9 @@ typedef enum { CF_VIDEO_REFRESH_REQ, CF_SERVICE_AUDIO, CF_SERVICE_VIDEO, + CF_ZRTP_PASSTHRU_REQ, + CF_ZRTP_PASSTHRU, CF_ZRTP_HASH, - CF_ZRTP_PASS, CF_CHANNEL_SWAP, CF_PICKUP, CF_CONFIRM_BLIND_TRANSFER, diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index ebd009a16d..92a27fd0f2 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2997,6 +2997,7 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t stream->write_function(stream, "NOMEDIA \t%s\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA) ? "true" : "false"); stream->write_function(stream, "LATE-NEG \t%s\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION) ? "true" : "false"); stream->write_function(stream, "PROXY-MEDIA \t%s\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA) ? "true" : "false"); + stream->write_function(stream, "ZRTP-PASSTHRU \t%s\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) ? "true" : "false"); stream->write_function(stream, "AGGRESSIVENAT \t%s\n", sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false"); stream->write_function(stream, "STUN-ENABLED \t%s\n", sofia_test_pflag(profile, PFLAG_STUN_ENABLED) ? "true" : "false"); @@ -3275,6 +3276,7 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl stream->write_function(stream, " %s\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA) ? "true" : "false"); stream->write_function(stream, " %s\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION) ? "true" : "false"); stream->write_function(stream, " %s\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA) ? "true" : "false"); + stream->write_function(stream, " %s\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) ? "true" : "false"); stream->write_function(stream, " %s\n", sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ? "true" : "false"); stream->write_function(stream, " %s\n", @@ -4785,6 +4787,17 @@ static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session sofia_clear_flag(ctech_pvt, TFLAG_ENABLE_SOA); } + if (switch_channel_test_flag(o_channel, CF_ZRTP_PASSTHRU_REQ)) { + const char *x = NULL; + sofia_glue_pass_zrtp_hash2(session, nsession); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting a-leg inherit_codec=true\n"); + switch_channel_set_variable(o_channel, "inherit_codec", "true"); + if ((x = switch_channel_get_variable(o_channel, "ep_codec_string"))) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting b-leg absolute_codec_string='%s'\n", x); + switch_channel_set_variable(nchannel, "absolute_codec_string", x); + } + } + /* SNARK: lets copy this across so we can see if we're the other leg of 3PCC + bypass_media... */ if (sofia_test_flag(ctech_pvt, TFLAG_3PCC) && (switch_channel_test_flag(o_channel, CF_PROXY_MODE) || switch_channel_test_flag(o_channel, CF_PROXY_MEDIA))) { sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index f6e4c1122e..67d513cf27 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -317,6 +317,7 @@ typedef enum { TFLAG_TPORT_LOG, TFLAG_SENT_UPDATE, TFLAG_PROXY_MEDIA, + TFLAG_ZRTP_PASSTHRU, TFLAG_HOLD_LOCK, TFLAG_3PCC_HAS_ACK, TFLAG_PASS_RFC2833, @@ -825,6 +826,11 @@ struct private_object { switch_payload_t ianacodes[SWITCH_MAX_CODECS]; uint32_t session_timeout; enum nua_session_refresher session_refresher; + /** ZRTP **/ + char *local_sdp_audio_zrtp_hash; + char *local_sdp_video_zrtp_hash; + char *remote_sdp_audio_zrtp_hash; + char *remote_sdp_video_zrtp_hash; }; struct callback_t { @@ -932,6 +938,8 @@ void launch_sofia_profile_thread(sofia_profile_t *profile); switch_status_t sofia_presence_chat_send(switch_event_t *message_event); void sofia_glue_tech_absorb_sdp(private_object_t *tech_pvt); +void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session); +void sofia_glue_pass_zrtp_hash(switch_core_session_t *session); /* * \brief Sets the "ep_codec_string" channel variable, parsing r_sdp and taing codec_string in consideration diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index e5d026975d..0621b3b84d 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3321,6 +3321,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_flag(profile, TFLAG_PROXY_MEDIA); } + } else if (!strcasecmp(var, "inbound-zrtp-passthru")) { + if (switch_true(val)) { + sofia_set_flag(profile, TFLAG_ZRTP_PASSTHRU); + } else { + sofia_clear_flag(profile, TFLAG_ZRTP_PASSTHRU); + } } else if (!strcasecmp(var, "inbound-use-callid-as-uuid")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_CALLID_AS_UUID); @@ -3695,6 +3701,10 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } } + if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)) { + sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION); + } + if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) { parse_gateways(profile, gateways_tag); } @@ -4171,6 +4181,8 @@ switch_status_t config_sofia(int reload, char *profile_name) } } else if (!strcasecmp(var, "inbound-proxy-media") && switch_true(val)) { sofia_set_flag(profile, TFLAG_PROXY_MEDIA); + } else if (!strcasecmp(var, "inbound-zrtp-passthru") && switch_true(val)) { + sofia_set_flag(profile, TFLAG_ZRTP_PASSTHRU); } else if (!strcasecmp(var, "force-subscription-expires")) { int tmp = atoi(val); if (tmp > 0) { @@ -4801,6 +4813,10 @@ switch_status_t config_sofia(int reload, char *profile_name) } } + if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)) { + sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION); + } + if ((!profile->cng_pt) && (!sofia_test_pflag(profile, PFLAG_SUPPRESS_CNG))) { profile->cng_pt = SWITCH_RTP_CNG_PAYLOAD; } @@ -8264,6 +8280,10 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ switch_channel_set_flag(channel, CF_PROXY_MEDIA); } + if (sofia_test_flag(tech_pvt, TFLAG_ZRTP_PASSTHRU)) { + switch_channel_set_flag(channel, CF_ZRTP_PASSTHRU_REQ); + } + if (!tech_pvt->call_id && sip->sip_call_id && sip->sip_call_id->i_id) { tech_pvt->call_id = switch_core_session_strdup(session, sip->sip_call_id->i_id); switch_channel_set_variable(channel, "sip_call_id", tech_pvt->call_id); diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0adcce9606..6bb7d3ee5f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -184,7 +184,6 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, int rate; int already_did[128] = { 0 }; int ptime = 0, noptime = 0; - const char *zrtp; switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP", port, secure ? "S" : ""); @@ -344,8 +343,11 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\n", cur_ptime); } - if ((zrtp = switch_channel_get_variable(tech_pvt->channel, "sdp_zrtp_hash_string"))) { - switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n", zrtp); + if (tech_pvt->local_sdp_audio_zrtp_hash) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n", + tech_pvt->local_sdp_audio_zrtp_hash); + switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n", + tech_pvt->local_sdp_audio_zrtp_hash); } if (sr) { @@ -391,7 +393,6 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch switch_event_t *map = NULL, *ptmap = NULL; const char *b_sdp = NULL; int verbose_sdp = 0; - const char *zrtp; sofia_glue_check_dtmf_type(tech_pvt); @@ -545,8 +546,12 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", ptime); } - if ((zrtp = switch_channel_get_variable(tech_pvt->channel, "sdp_zrtp_hash_string"))) { - switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=zrtp-hash:%s\n", zrtp); + + if (tech_pvt->local_sdp_audio_zrtp_hash) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n", + tech_pvt->local_sdp_audio_zrtp_hash); + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=zrtp-hash:%s\n", + tech_pvt->local_sdp_audio_zrtp_hash); } if (sr) { @@ -747,6 +752,13 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch } } + + if (tech_pvt->local_sdp_video_zrtp_hash) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n", + tech_pvt->local_sdp_video_zrtp_hash); + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=zrtp-hash:%s\n", + tech_pvt->local_sdp_video_zrtp_hash); + } } } @@ -3563,9 +3575,11 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); - if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASS)) { + if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_INFO, "Activating ZRTP PROXY MODE\n"); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Disable NOTIMER_DURING_BRIDGE\n"); sofia_clear_flag(tech_pvt, TFLAG_NOTIMER_DURING_BRIDGE); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Activating audio UDPTL mode\n"); switch_rtp_udptl_mode(tech_pvt->rtp_session); } @@ -3752,7 +3766,10 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } } } - + if (switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Activating video UDPTL mode\n"); + switch_rtp_udptl_mode(tech_pvt->video_rtp_session); + } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err)); @@ -3837,7 +3854,93 @@ static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size } +void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session) +{ + switch_channel_t *aleg_channel = switch_core_session_get_channel(aleg_session); + private_object_t *aleg_tech_pvt = switch_core_session_get_private(aleg_session); + switch_channel_t *bleg_channel = switch_core_session_get_channel(bleg_session); + private_object_t *bleg_tech_pvt = switch_core_session_get_private(bleg_session); + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Deciding whether to pass zrtp-hash between a-leg and b-leg\n"); + if (!(switch_channel_test_flag(aleg_tech_pvt->channel, CF_ZRTP_PASSTHRU_REQ))) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "CF_ZRTP_PASSTHRU_REQ not set on a-leg, so not propagating zrtp-hash\n"); + return; + } + if (aleg_tech_pvt->remote_sdp_audio_zrtp_hash) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing a-leg remote zrtp-hash (audio) to b-leg\n"); + bleg_tech_pvt->local_sdp_audio_zrtp_hash = switch_core_session_strdup(bleg_tech_pvt->session, aleg_tech_pvt->remote_sdp_audio_zrtp_hash); + switch_channel_set_variable(bleg_channel, "l_sdp_audio_zrtp_hash", bleg_tech_pvt->local_sdp_audio_zrtp_hash); + } + if (aleg_tech_pvt->remote_sdp_video_zrtp_hash) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing a-leg remote zrtp-hash (video) to b-leg\n"); + bleg_tech_pvt->local_sdp_video_zrtp_hash = switch_core_session_strdup(bleg_tech_pvt->session, aleg_tech_pvt->remote_sdp_video_zrtp_hash); + switch_channel_set_variable(bleg_channel, "l_sdp_video_zrtp_hash", bleg_tech_pvt->local_sdp_video_zrtp_hash); + } + if (bleg_tech_pvt->remote_sdp_audio_zrtp_hash) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing b-leg remote zrtp-hash (audio) to a-leg\n"); + aleg_tech_pvt->local_sdp_audio_zrtp_hash = switch_core_session_strdup(aleg_tech_pvt->session, bleg_tech_pvt->remote_sdp_audio_zrtp_hash); + switch_channel_set_variable(aleg_channel, "l_sdp_audio_zrtp_hash", aleg_tech_pvt->local_sdp_audio_zrtp_hash); + } + if (bleg_tech_pvt->remote_sdp_video_zrtp_hash) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG, "Passing b-leg remote zrtp-hash (video) to a-leg\n"); + aleg_tech_pvt->local_sdp_video_zrtp_hash = switch_core_session_strdup(aleg_tech_pvt->session, bleg_tech_pvt->remote_sdp_video_zrtp_hash); + switch_channel_set_variable(aleg_channel, "l_sdp_video_zrtp_hash", aleg_tech_pvt->local_sdp_video_zrtp_hash); + } +} +void sofia_glue_pass_zrtp_hash(switch_core_session_t *session) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + private_object_t *tech_pvt = switch_core_session_get_private(session); + switch_core_session_t *other_session; + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Deciding whether to pass zrtp-hash between legs\n"); + if (!(switch_channel_test_flag(tech_pvt->channel, CF_ZRTP_PASSTHRU_REQ))) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "CF_ZRTP_PASSTHRU_REQ not set, so not propagating zrtp-hash\n"); + return; + } else if (!(switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS)) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "No partner channel found, so not propagating zrtp-hash\n"); + return; + } else { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Found peer channel; propagating zrtp-hash if set\n"); + sofia_glue_pass_zrtp_hash2(session, other_session); + switch_core_session_rwunlock(other_session); + } +} + +static void find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + private_object_t *tech_pvt = switch_core_session_get_private(session); + sdp_media_t *m; + sdp_attribute_t *attr; + int got_audio = 0, got_video = 0; + + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Looking for zrtp-hash\n"); + for (m = sdp->sdp_media; m; m = m->m_next) { + if (got_audio && got_video) break; + if (m->m_port && ((m->m_type == sdp_media_audio && !got_audio) + || (m->m_type == sdp_media_video && !got_video))) { + for (attr = m->m_attributes; attr; attr = attr->a_next) { + if (zstr(attr->a_name)) continue; + if (strcasecmp(attr->a_name, "zrtp-hash") || !(attr->a_value)) continue; + if (m->m_type == sdp_media_audio) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, + "Found audio zrtp-hash; setting r_sdp_audio_zrtp_hash=%s\n", attr->a_value); + switch_channel_set_variable(channel, "r_sdp_audio_zrtp_hash", attr->a_value); + tech_pvt->remote_sdp_audio_zrtp_hash = switch_core_session_strdup(tech_pvt->session, attr->a_value); + got_audio++; + } else if (m->m_type == sdp_media_video) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, + "Found video zrtp-hash; setting r_sdp_video_zrtp_hash=%s\n", attr->a_value); + switch_channel_set_variable(channel, "r_sdp_video_zrtp_hash", attr->a_value); + tech_pvt->remote_sdp_video_zrtp_hash = switch_core_session_strdup(tech_pvt->session, attr->a_value); + got_video++; + } + switch_channel_set_flag(channel, CF_ZRTP_HASH); + break; + } + } + } +} void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp) { @@ -3887,18 +3990,8 @@ void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, const cha } } - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Looking for zrtp-hash to set sdp_zrtp_hash_string\n"); - for (m = sdp->sdp_media; m; m = m->m_next) { - for (attr = m->m_attributes; attr; attr = attr->a_next) { - if (zstr(attr->a_name)) continue; - if (!strcasecmp(attr->a_name, "zrtp-hash") && attr->a_value) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "Found zrtp-hash, setting sdp_zrtp_hash_string=%s\n", attr->a_value); - switch_channel_set_variable(channel, "sdp_zrtp_hash_string", attr->a_value); - switch_channel_set_flag(channel, CF_ZRTP_HASH); - break; - } - } - } + find_zrtp_hash(session, sdp); + sofia_glue_pass_zrtp_hash(session); for (m = sdp->sdp_media; m; m = m->m_next) { ptime = dptime; @@ -4578,6 +4671,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s switch_channel_set_variable(tech_pvt->channel, "t38_broken_boolean", "true"); } + find_zrtp_hash(session, sdp); + sofia_glue_pass_zrtp_hash(session); + for (m = sdp->sdp_media; m; m = m->m_next) { sdp_connection_t *connection; switch_core_session_t *other_session; @@ -4699,9 +4795,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s ptime = atoi(attr->a_value); } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) { maxptime = atoi(attr->a_value); - } else if (!strcasecmp(attr->a_name, "zrtp-hash") && attr->a_value) { - switch_channel_set_variable(tech_pvt->channel, "sdp_zrtp_hash_string", attr->a_value); - switch_channel_set_flag(tech_pvt->channel, CF_ZRTP_HASH); } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) { int crypto_tag; diff --git a/src/switch_channel.c b/src/switch_channel.c index e06706cbc3..dc983c78cd 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -2955,7 +2955,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_mark_ring_ready_value(swi SWITCH_DECLARE(void) switch_channel_check_zrtp(switch_channel_t *channel) { - if (switch_channel_test_flag(channel, CF_ZRTP_HASH) && !switch_channel_test_flag(channel, CF_ZRTP_PASS)) { + if (!switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU) + && switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU_REQ) + && switch_channel_test_flag(channel, CF_ZRTP_HASH)) { switch_core_session_t *other_session; switch_channel_t *other_channel; int doit = 1; @@ -2963,14 +2965,16 @@ SWITCH_DECLARE(void) switch_channel_check_zrtp(switch_channel_t *channel) if (switch_core_session_get_partner(channel->session, &other_session) == SWITCH_STATUS_SUCCESS) { other_channel = switch_core_session_get_channel(other_session); - if (switch_channel_test_flag(other_channel, CF_ZRTP_HASH) && !switch_channel_test_flag(other_channel, CF_ZRTP_PASS)) { + if (switch_channel_test_flag(other_channel, CF_ZRTP_HASH) && !switch_channel_test_flag(other_channel, CF_ZRTP_PASSTHRU)) { - switch_channel_set_flag(channel, CF_ZRTP_PASS); - switch_channel_set_flag(other_channel, CF_ZRTP_PASS); + switch_channel_set_flag(channel, CF_ZRTP_PASSTHRU); + switch_channel_set_flag(other_channel, CF_ZRTP_PASSTHRU); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO, "%s Activating ZRTP passthru mode.\n", switch_channel_get_name(channel)); + switch_channel_set_variable(channel, "zrtp_passthru_active", "true"); + switch_channel_set_variable(other_channel, "zrtp_passthru_active", "true"); switch_channel_set_variable(channel, "zrtp_secure_media", "false"); switch_channel_set_variable(other_channel, "zrtp_secure_media", "false"); doit = 0; @@ -2980,18 +2984,20 @@ SWITCH_DECLARE(void) switch_channel_check_zrtp(switch_channel_t *channel) } if (doit) { + switch_channel_set_variable(channel, "zrtp_passthru_active", "false"); switch_channel_set_variable(channel, "zrtp_secure_media", "true"); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(channel->session), SWITCH_LOG_INFO, "%s ZRTP not negotiated on both sides; disabling ZRTP passthru mode.\n", switch_channel_get_name(channel)); - switch_channel_clear_flag(channel, CF_ZRTP_PASS); + switch_channel_clear_flag(channel, CF_ZRTP_PASSTHRU); switch_channel_clear_flag(channel, CF_ZRTP_HASH); if (switch_core_session_get_partner(channel->session, &other_session) == SWITCH_STATUS_SUCCESS) { other_channel = switch_core_session_get_channel(other_session); + switch_channel_set_variable(other_channel, "zrtp_passthru_active", "false"); switch_channel_set_variable(other_channel, "zrtp_secure_media", "true"); - switch_channel_clear_flag(other_channel, CF_ZRTP_PASS); + switch_channel_clear_flag(other_channel, CF_ZRTP_PASSTHRU); switch_channel_clear_flag(other_channel, CF_ZRTP_HASH); switch_core_session_rwunlock(other_session); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 56c6e0b3a4..4e43987ecf 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -577,6 +577,10 @@ SWITCH_DECLARE(switch_call_cause_t) switch_core_session_outgoing_channel(switch_ } } + if (switch_channel_test_flag(channel, CF_ZRTP_PASSTHRU_REQ)) { + switch_channel_set_flag(peer_channel, CF_ZRTP_PASSTHRU_REQ); + } + if (profile) { if ((cloned_profile = switch_caller_profile_clone(*new_session, profile)) != 0) { switch_channel_set_originator_caller_profile(peer_channel, cloned_profile); diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 87ff02ec8c..98fed62b34 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1820,7 +1820,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } if (session) { - const char *to_var, *bypass_media = NULL, *proxy_media = NULL; + const char *to_var, *bypass_media = NULL, *proxy_media = NULL, *zrtp_passthru = NULL; caller_channel = switch_core_session_get_channel(session); switch_channel_set_flag(caller_channel, CF_ORIGINATOR); oglobals.session = session; @@ -1833,6 +1833,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess proxy_media = switch_channel_get_variable(caller_channel, SWITCH_PROXY_MEDIA_VARIABLE); bypass_media = switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_VARIABLE); + zrtp_passthru = switch_channel_get_variable(caller_channel, SWITCH_ZRTP_PASSTHRU_VARIABLE); if (!zstr(proxy_media)) { if (switch_true(proxy_media)) { @@ -1842,6 +1843,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess } } + if (!zstr(zrtp_passthru)) { + if (switch_true(zrtp_passthru)) { + switch_channel_set_flag(caller_channel, CF_ZRTP_PASSTHRU_REQ); + } else if (switch_channel_test_flag(caller_channel, CF_ZRTP_PASSTHRU_REQ)) { + switch_channel_clear_flag(caller_channel, CF_ZRTP_PASSTHRU_REQ); + } + } + if (bypass_media && switch_channel_test_flag(caller_channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) { switch_core_session_message_t msg = { 0 };