c-自由切换支持从传入的3PCC INVITE生成SRTP报价



我在Node.js中使用Freeswitch ESL(事件套接字库(当我收到来自经典SIP端点的SIP.js邀请时,SDP内容是常规RTP。我需要能够使用中间的Freeswitch将RTP端点连接到SRTP端点。为了做到这一点,我们需要能够在没有SDP的情况下在Freeswitch上创建一个端点(3PCC INVITE(,但我们希望这个端点返回SRTP SDP,而不是RTP SDP。

主要问题:Freeswitch是否支持从收到的3PCC INVITE生成SRTP报价

我相信这是在Freeswitch 1.8.5中处理3PCC INVITE的部分:https://github.com/signalwire/freeswitch/blob/v1.8.5/src/mod/endpoints/mod_sofia/sofia.c

if (sofia_test_pflag(profile, PFLAG_3PCC)) {
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No SDP in INVITE and 3pcc=yes cannot work with bypass or proxy media, hanging up.n");
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED");
switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING);
} else {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
switch_core_media_prepare_codecs(session, 1);
switch_channel_set_state(channel, CS_HIBERNATE);
switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0);
sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
if (sofia_use_soa(tech_pvt)) {
nua_respond(tech_pvt->nh, SIP_200_OK,
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
SOATAG_REUSE_REJECTED(1),
SOATAG_AUDIO_AUX("cn telephone-event"),
TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)), TAG_END());
} else {
nua_respond(tech_pvt->nh, SIP_200_OK,
NUTAG_MEDIA_ENABLE(0),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str), TAG_END());
}
}
}

也许可以使用与mod_verto相同的模式:https://github.com/signalwire/freeswitch/blob/v1.8.5/src/mod/endpoints/mod_verto/mod_verto.c

这个函数switch_core_media_gen_local_sdp似乎是创建RTP sdp的函数:https://github.com/signalwire/freeswitch/blob/v1.8.5/src/switch_core_media.c我们如何将其改为SRTP SDP?

static const char *get_media_profile_name(switch_core_session_t *session, int secure)
{
switch_assert(session);
if (switch_channel_test_flag(session->channel, CF_AVPF)) {
if (switch_channel_test_flag(session->channel, CF_DTLS) || secure) {
if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
return "UDP/TLS/RTP/SAVPF";
} else {
return "RTP/SAVPF";
}
} else {
if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
return "UDP/AVPF";
} else {
return "RTP/AVPF";
}
}
}
if (secure) {
return "RTP/SAVP";
}
return "RTP/AVP";
}

启用SRTP有3个条件:

session->channel->flags['CF_AVPF']
(session->channel->flags['CF_DTLS'] || secure)
session->channel->flags['CF_AVPF_MOZ']

设置CF_AVPF标志的条件是调用switch_core_session_set_ice或:

if (is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING) ||
switch_channel_test_flag(session->channel, CF_3PCC)) {
if (!switch_channel_test_flag(session->channel, CF_AVPF) &&
switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) {
switch_channel_set_flag(session->channel, CF_AVPF);
switch_channel_set_flag(session->channel, CF_ICE);
smh->mparams->rtcp_audio_interval_msec = SWITCH_RTCP_AUDIO_INTERVAL_MSEC;
smh->mparams->rtcp_video_interval_msec = SWITCH_RTCP_VIDEO_INTERVAL_MSEC;
}
if (switch_true(switch_channel_get_variable(session->channel, "add_ice_candidates"))) {
switch_channel_set_flag(session->channel, CF_ICE);
}
if ( switch_rtp_has_dtls() && dtls_ok(session)) {
if (switch_channel_test_flag(session->channel, CF_AVPF) ||
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_parse_crypto_prefs(session);
switch_core_session_check_outgoing_crypto(session);
}

放置CF_DTLS标志的条件与上述条件相同(CFR_AVPF(或调用check_ice

if (switch_rtp_has_dtls() && dtls_ok(smh->session) && !strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
char *p;
engine->remote_dtls_fingerprint.type = switch_core_session_strdup(smh->session, attr->a_value);
if ((p = strchr(engine->remote_dtls_fingerprint.type, ' '))) {
*p++ = '';
if (switch_channel_test_flag(smh->session->channel, CF_REINVITE) && !switch_channel_test_flag(smh->session->channel, CF_RECOVERING) &&
!zstr(engine->remote_dtls_fingerprint.str) && !strcmp(engine->remote_dtls_fingerprint.str, p)) {
engine->new_dtls = 0;
} else {
switch_set_string(engine->remote_dtls_fingerprint.str, p);
engine->new_dtls = 1;
engine->new_ice = 1;
}
}
generate_local_fingerprint(smh, type);
switch_channel_set_flag(smh->session->channel, CF_DTLS);
}

secure参数也有可能发送true,但条件很多。

放置CF_AVPF_MOZ标志的条件:

if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/TLS/RTP/SAVPF")) {
switch_channel_set_flag(session->channel, CF_AVPF_MOZ);
}
if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/RTP/AVPF")) {
switch_channel_set_flag(session->channel, CF_AVPF_MOZ);
}

尝试设置media_webrtc=true这应该告诉freeswitch对媒体流使用DTLS,webrtc信号应该单独完成。

<action application="bridge" data="[media_webrtc=true]sofia/internal/100%${sip_profile}"/>

最新更新