我在Node.js中使用Freeswitch ESL(事件套接字库)当我从一个经典的sip端点接收到SIP.js的邀请时,SDP内容是常规的RTP.我需要能够在中间使用Freeswitch将RTP端点连接到SRTP端点,为了做到这一点,我们需要能够在Freeswitch上创建一个没有SDP的端点(3PCC INVITE),但我们希望这个端点能够返回SRTP SDP而不是RTP SDP。
主要的问题是:Freeswitch是否支持生成SRTP SDP?Freeswitch是否支持从传入的3PCC INVITE生成SRTP offer?
我相信这是Freeswitch 1.8.5中处理3PCC INVITE的部分。https:/github.comsignalwirefreeswitchblobv1.8.5srcmodendpointsmod_sofiasofia.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.comsignalwirefreeswitchblobv1.8.5srcmodendpointsmod_vertomod_verto.c。
这个函数 switch_core_media_gen_local_sdp. 似乎是创建RTP SDP的那个。https:/github.comsignalwirefreeswitchblobv1.8.5srcswitch_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 旗帜鲜明 开关_核心_会话_设置_冰块 或。
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 标志与上述相同(CF_AVPF)或调用 检查_冰块:
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++ = '\0';
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);
}
也可以将 "true "发送到 "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}"/>