switch_mutex_unlock(tech_pvt->sofia_mutex);
}
-void sofia_glue_tech_absorb_sdp(private_object_t *tech_pvt)
-{
- const char *sdp_str;
-
- if ((sdp_str = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE))) {
- sdp_parser_t *parser;
- sdp_session_t *sdp;
- sdp_media_t *m;
- sdp_connection_t *connection;
-
- if ((parser = sdp_parse(NULL, sdp_str, (int) strlen(sdp_str), 0))) {
- if ((sdp = sdp_session(parser))) {
- for (m = sdp->sdp_media; m; m = m->m_next) {
- if (m->m_type != sdp_media_audio || !m->m_port) {
- continue;
- }
-
- connection = sdp->sdp_connection;
- if (m->m_connections) {
- connection = m->m_connections;
- }
-
- if (connection) {
- tech_pvt->proxy_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, connection->c_address);
- }
- tech_pvt->proxy_sdp_audio_port = (switch_port_t) m->m_port;
- if (tech_pvt->proxy_sdp_audio_ip && tech_pvt->proxy_sdp_audio_port) {
- break;
- }
- }
- }
- sdp_parser_free(parser);
- }
- sofia_glue_tech_set_local_sdp(tech_pvt, sdp_str, SWITCH_TRUE);
- }
-}
#define add_stat(_i, _s) \
return SWITCH_STATUS_SUCCESS;
}
-switch_status_t sofia_glue_add_crypto(private_object_t *tech_pvt, const char *key_str, switch_rtp_crypto_direction_t direction)
-{
- unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
- switch_rtp_crypto_key_type_t type;
- char *p;
- if (!switch_rtp_ready(tech_pvt->rtp_session)) {
- goto bad;
+static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size_t buflen)
+{
+ int codec_ms = ptime;
+ uint32_t map_bit_rate = 0;
+ char ptstr[20] = "";
+ char ratestr[20] = "";
+ char bitstr[20] = "";
+ switch_codec_fmtp_t codec_fmtp = { 0 };
+
+ if (!codec_ms) {
+ codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
}
- p = strchr(key_str, ' ');
-
- if (p && *p && *(p + 1)) {
- p++;
- if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_32, strlen(SWITCH_RTP_CRYPTO_KEY_32))) {
- type = AES_CM_128_HMAC_SHA1_32;
- } else if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_80, strlen(SWITCH_RTP_CRYPTO_KEY_80))) {
- type = AES_CM_128_HMAC_SHA1_80;
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
- goto bad;
+ map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
+
+ if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
+ ptime = codec_ms = 30;
+ }
+
+ if (zstr(map->rm_fmtp)) {
+ if (!strcasecmp(map->rm_encoding, "ilbc")) {
+ ptime = codec_ms = 30;
+ map_bit_rate = 13330;
}
-
- p = strchr(p, ' ');
- if (p && *p && *(p + 1)) {
- p++;
- if (strncasecmp(p, "inline:", 7)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
- goto bad;
+ } else {
+ if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
+ if (codec_fmtp.bits_per_second) {
+ map_bit_rate = codec_fmtp.bits_per_second;
}
-
- p += 7;
- switch_b64_decode(p, (char *) key, sizeof(key));
-
- if (direction == SWITCH_RTP_CRYPTO_SEND) {
- tech_pvt->crypto_send_type = type;
- memcpy(tech_pvt->local_raw_key, key, SWITCH_RTP_KEY_LEN);
- } else {
- tech_pvt->crypto_recv_type = type;
- memcpy(tech_pvt->remote_raw_key, key, SWITCH_RTP_KEY_LEN);
+ if (codec_fmtp.microseconds_per_packet) {
+ codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
}
- return SWITCH_STATUS_SUCCESS;
}
+ }
+ if (map->rm_rate) {
+ switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
}
- bad:
+ if (codec_ms) {
+ switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
+ }
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Error!\n");
- return SWITCH_STATUS_FALSE;
+ if (map_bit_rate) {
+ switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
+ }
-}
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr);
+}
-switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_flag_t myflags)
+void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session)
{
- const char *err = NULL;
- const char *val = NULL;
- switch_rtp_flag_t flags;
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- char tmp[50];
- uint32_t rtp_timeout_sec = tech_pvt->profile->rtp_timeout_sec;
- uint32_t rtp_hold_timeout_sec = tech_pvt->profile->rtp_hold_timeout_sec;
- char *timer_name = NULL;
- const char *var;
- uint32_t delay = tech_pvt->profile->rtp_digit_delay;
-
- switch_assert(tech_pvt != NULL);
+ switch_channel_t *aleg_channel;
+ private_object_t *aleg_tech_pvt;
+ switch_channel_t *bleg_channel;
+ private_object_t *bleg_tech_pvt;
- if (switch_channel_down(tech_pvt->channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
- return SWITCH_STATUS_FALSE;
+ if (!switch_core_session_compare(aleg_session, bleg_session)) {
+ /* since this digs into channel internals its only compatible with sofia sessions*/
+ return;
}
- switch_mutex_lock(tech_pvt->sofia_mutex);
+ aleg_channel = switch_core_session_get_channel(aleg_session);
+ aleg_tech_pvt = switch_core_session_get_private(aleg_session);
+ bleg_channel = switch_core_session_get_channel(bleg_session);
+ bleg_tech_pvt = switch_core_session_get_private(bleg_session);
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- switch_rtp_reset_media_timer(tech_pvt->rtp_session);
+ switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG1, "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_DEBUG1, "CF_ZRTP_PASSTHRU_REQ not set on a-leg, so not propagating zrtp-hash\n");
+ return;
}
-
- if ((var = switch_channel_get_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE)) && switch_true(var)) {
- sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
+ 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 (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
- status = SWITCH_STATUS_SUCCESS;
- goto end;
+ 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 (!sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- if (sofia_test_flag(tech_pvt, TFLAG_VIDEO) && !switch_rtp_ready(tech_pvt->video_rtp_session)) {
- goto video;
- }
-
- status = SWITCH_STATUS_SUCCESS;
- goto end;
- }
+ 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 ((status = sofia_glue_tech_set_codec(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) {
- goto end;
+ 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);
}
+}
-
- if (myflags) {
- flags = myflags;
- } else if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
- !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT);
+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_DEBUG1, "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_DEBUG1, "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_DEBUG1, "No partner channel found, so not propagating zrtp-hash\n");
+ return;
} else {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT);
+ switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "Found peer channel; propagating zrtp-hash if set\n");
+ sofia_glue_pass_zrtp_hash2(session, other_session);
+ switch_core_session_rwunlock(other_session);
}
+}
+
+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;
- if (sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_RFC2833)
- || ((val = switch_channel_get_variable(tech_pvt->channel, "pass_rfc2833")) && switch_true(val))) {
- sofia_set_flag(tech_pvt, TFLAG_PASS_RFC2833);
+ switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "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)
+{
+ char buf[1024] = { 0 };
+ sdp_media_t *m;
+ sdp_attribute_t *attr;
+ int ptime = 0, dptime = 0;
+ sdp_connection_t *connection;
+ sdp_rtpmap_t *map;
+ short int match = 0;
+ int i;
+ int already_did[128] = { 0 };
+ int num_codecs = 0;
+ char *codec_order[SWITCH_MAX_CODECS];
+ const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS] = { 0 };
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ private_object_t *tech_pvt = switch_core_session_get_private(session);
+ int prefer_sdp = 0;
+ const char *var;
- if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFLUSH)
- || ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_autoflush")) && switch_true(val))) {
- flags |= SWITCH_RTP_FLAG_AUTOFLUSH;
+ if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) {
+ prefer_sdp = 1;
}
-
- if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_REWRITE_TIMESTAMPS) ||
- ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) {
- flags |= SWITCH_RTP_FLAG_RAW_WRITE;
+
+ if (!zstr(codec_string)) {
+ char *tmp_codec_string;
+ if ((tmp_codec_string = strdup(codec_string))) {
+ num_codecs = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS);
+ num_codecs = switch_loadable_module_get_codecs_sorted(codecs, SWITCH_MAX_CODECS, codec_order, num_codecs);
+ switch_safe_free(tmp_codec_string);
+ }
+ } else {
+ num_codecs = switch_loadable_module_get_codecs(codecs, SWITCH_MAX_CODECS);
}
- if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG)) {
- tech_pvt->cng_pt = 0;
- } else if (tech_pvt->cng_pt) {
- flags |= SWITCH_RTP_FLAG_AUTO_CNG;
+ if (!channel || !num_codecs) {
+ return;
}
-#if __BYTE_ORDER == __LITTLE_ENDIAN
- if (!strcasecmp(tech_pvt->read_impl.iananame, "L16")) {
- flags |= SWITCH_RTP_FLAG_BYTESWAP;
- }
-#endif
-
- if ((flags & SWITCH_RTP_FLAG_BYTESWAP) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_byteswap")) && switch_true(val)) {
- flags &= ~SWITCH_RTP_FLAG_BYTESWAP;
+ for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
+ if (zstr(attr->a_name)) {
+ continue;
+ }
+ if (!strcasecmp(attr->a_name, "ptime")) {
+ dptime = atoi(attr->a_value);
+ break;
+ }
}
- if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
- //const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
- //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
- char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
- switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
+ find_zrtp_hash(session, sdp);
+ sofia_glue_pass_zrtp_hash(session);
- if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
- switch_channel_get_name(tech_pvt->channel));
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "%s Set audio receive payload in Re-INVITE for non-matching dynamic PT to %u\n",
- switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
-
- switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt);
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "%s Setting audio receive payload in Re-INVITE to %u\n",
- switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
- switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt);
+ for (m = sdp->sdp_media; m; m = m->m_next) {
+ ptime = dptime;
+ if (m->m_type == sdp_media_image && m->m_port) {
+ switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",t38");
+ } else if (m->m_type == sdp_media_audio && m->m_port) {
+ for (attr = m->m_attributes; attr; attr = attr->a_next) {
+ if (zstr(attr->a_name)) {
+ continue;
+ }
+ if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
+ ptime = atoi(attr->a_value);
+ break;
}
+ }
+ connection = sdp->sdp_connection;
+ if (m->m_connections) {
+ connection = m->m_connections;
+ }
+ if (!connection) {
+ switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
+ break;
}
- goto video;
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
- switch_channel_get_name(tech_pvt->channel),
- remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
- }
- }
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+ if (map->rm_pt > 127 || already_did[map->rm_pt]) {
+ continue;
+ }
- if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n",
- switch_channel_get_name(tech_pvt->channel),
- tech_pvt->local_sdp_audio_ip,
- tech_pvt->local_sdp_audio_port,
- tech_pvt->remote_sdp_audio_ip,
- tech_pvt->remote_sdp_audio_port, tech_pvt->agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
+ for (i = 0; i < num_codecs; i++) {
+ const switch_codec_implementation_t *imp = codecs[i];
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->agreed_pt);
-
- if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
-
- switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt);
- } else {
- switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt);
- }
-
- }
- }
-
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->local_sdp_audio_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->local_sdp_audio_ip);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip);
-
- if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
- const char *rport = NULL;
- switch_port_t remote_rtcp_port = 0;
-
-
-
- if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"))) {
- remote_rtcp_port = (switch_port_t)atoi(rport);
- }
-
- if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port,
- remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
- tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
- !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
- /* Reactivate the NAT buster flag. */
- switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
- }
- }
- goto video;
- }
-
- if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
- sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
- !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT);
- } else {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_DATAWAIT);
- }
- timer_name = NULL;
-
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
- switch_channel_get_name(tech_pvt->channel),
- tech_pvt->local_sdp_audio_ip,
- tech_pvt->local_sdp_audio_port,
- tech_pvt->remote_sdp_audio_ip,
- tech_pvt->remote_sdp_audio_port, tech_pvt->agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
-
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->agreed_pt);
- }
-
- } else {
- timer_name = tech_pvt->profile->timer_name;
-
- if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) {
- timer_name = (char *) var;
- }
- }
-
- if (switch_channel_up(tech_pvt->channel) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
- tech_pvt->rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
- tech_pvt->local_sdp_audio_port,
- tech_pvt->remote_sdp_audio_ip,
- tech_pvt->remote_sdp_audio_port,
- tech_pvt->agreed_pt,
- tech_pvt->read_impl.samples_per_packet,
- tech_pvt->codec_ms * 1000,
- (switch_rtp_flag_t) flags, timer_name, &err, switch_core_session_get_pool(tech_pvt->session));
- }
-
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- uint8_t vad_in = sofia_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0;
- uint8_t vad_out = sofia_test_flag(tech_pvt, TFLAG_VAD_OUT) ? 1 : 0;
- uint8_t inb = sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) ? 0 : 1;
- uint32_t stun_ping = 0;
- const char *ssrc;
-
- if ((ssrc = switch_channel_get_variable(tech_pvt->channel, "rtp_use_ssrc"))) {
- uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
- switch_rtp_set_ssrc(tech_pvt->rtp_session, ssrc_ul);
- }
-
-
- switch_channel_set_flag(tech_pvt->channel, CF_FS_RTP);
-
- switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_pt", "%d", tech_pvt->agreed_pt);
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_enable_vad_in")) && switch_true(val)) {
- vad_in = 1;
- }
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_enable_vad_out")) && switch_true(val)) {
- vad_out = 1;
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_vad_in")) && switch_true(val)) {
- vad_in = 0;
- }
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_vad_out")) && switch_true(val)) {
- vad_out = 0;
- }
-
- if ((tech_pvt->stun_flags & STUN_FLAG_SET) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_stun_ping"))) {
- int ival = atoi(val);
-
- if (ival <= 0) {
- if (switch_true(val)) {
- ival = 6;
- }
- }
-
- stun_ping = (ival * tech_pvt->read_impl.samples_per_second) / tech_pvt->read_impl.samples_per_packet;
- }
-
- tech_pvt->ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session);
- switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_ssrc", "%u", tech_pvt->ssrc);
-
- sofia_set_flag(tech_pvt, TFLAG_RTP);
- sofia_set_flag(tech_pvt, TFLAG_IO);
-
- if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_IGNORE_MARK_BIT) {
- tech_pvt->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT;
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_manual_rtp_bugs"))) {
- sofia_glue_parse_rtp_bugs(&tech_pvt->rtp_bugs, val);
- }
-
- switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs | tech_pvt->profile->manual_rtp_bugs);
-
- if ((vad_in && inb) || (vad_out && !inb)) {
- switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING | SWITCH_VAD_FLAG_EVENTS_TALK | SWITCH_VAD_FLAG_EVENTS_NOTALK);
- sofia_set_flag(tech_pvt, TFLAG_VAD);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n",
- switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : "");
- }
-
- if (stun_ping) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Setting stun ping to %s:%d\n", tech_pvt->stun_ip,
- stun_ping);
- switch_rtp_activate_stun_ping(tech_pvt->rtp_session, tech_pvt->stun_ip, tech_pvt->stun_port, stun_ping,
- (tech_pvt->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0);
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec")) || (val = tech_pvt->profile->rtcp_audio_interval_msec)) {
- const char *rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_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(tech_pvt->rtp_session, -1, remote_port);
- } else {
- int interval = atoi(val);
- if (interval < 100 || interval > 5000) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
- "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval);
- } else {
- switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval, remote_port);
- }
- }
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec")) || (val = tech_pvt->profile->jb_msec)) {
- int jb_msec = atoi(val);
- int maxlen = 0, max_drift = 0;
- char *p, *q;
-
- if ((p = strchr(val, ':'))) {
- p++;
- maxlen = atoi(p);
- if ((q = strchr(p, ':'))) {
- q++;
- max_drift = abs(atoi(q));
- }
- }
-
- if (jb_msec < 20 || jb_msec > 10000) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
- "Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", jb_msec);
- } else {
- int qlen, maxqlen = 50;
-
- qlen = jb_msec / (tech_pvt->read_impl.microseconds_per_packet / 1000);
-
- if (qlen < 1) {
- qlen = 3;
- }
-
- if (maxlen) {
- maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
- }
-
- if (maxqlen < qlen) {
- maxqlen = qlen * 5;
- }
- if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen,
- tech_pvt->read_impl.samples_per_packet,
- tech_pvt->read_impl.samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
- SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
- switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
- if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) {
- switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC);
- }
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
- SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
- }
-
- }
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_timeout_sec"))) {
- int v = atoi(val);
- if (v >= 0) {
- rtp_timeout_sec = v;
- }
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_hold_timeout_sec"))) {
- int v = atoi(val);
- if (v >= 0) {
- rtp_hold_timeout_sec = v;
- }
- }
-
- if (rtp_timeout_sec) {
- tech_pvt->max_missed_packets = (tech_pvt->read_impl.samples_per_second * rtp_timeout_sec) / tech_pvt->read_impl.samples_per_packet;
-
- switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets);
- if (!rtp_hold_timeout_sec) {
- rtp_hold_timeout_sec = rtp_timeout_sec * 10;
- }
- }
-
- if (rtp_hold_timeout_sec) {
- tech_pvt->max_missed_hold_packets = (tech_pvt->read_impl.samples_per_second * rtp_hold_timeout_sec) / tech_pvt->read_impl.samples_per_packet;
- }
-
- if (tech_pvt->te) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", tech_pvt->te);
- switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te);
- switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", tech_pvt->te);
- }
-
- if (tech_pvt->recv_te) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf receive payload to %u\n", tech_pvt->recv_te);
- switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, tech_pvt->recv_te);
- switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", tech_pvt->recv_te);
- }
-
- if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
-
- switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt);
- }
-
- if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) ||
- ((val = switch_channel_get_variable(tech_pvt->channel, "supress_cng")) && switch_true(val)) ||
- ((val = switch_channel_get_variable(tech_pvt->channel, "suppress_cng")) && switch_true(val))) {
- tech_pvt->cng_pt = 0;
- }
-
- if (((val = switch_channel_get_variable(tech_pvt->channel, "rtp_digit_delay")))) {
- int delayi = atoi(val);
- if (delayi < 0) delayi = 0;
- delay = (uint32_t) delayi;
- }
-
-
- if (delay) {
- switch_rtp_set_interdigit_delay(tech_pvt->rtp_session, delay);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "%s Set rtp dtmf delay to %u\n", switch_channel_get_name(tech_pvt->channel), delay);
-
- }
-
- if (tech_pvt->cng_pt && !sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", tech_pvt->cng_pt);
- switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt);
- }
-
- if (tech_pvt->remote_crypto_key && sofia_test_flag(tech_pvt, TFLAG_SECURE)) {
- sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, 1, tech_pvt->crypto_type, tech_pvt->local_raw_key,
- SWITCH_RTP_KEY_LEN);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag, tech_pvt->crypto_type, tech_pvt->remote_raw_key,
- SWITCH_RTP_KEY_LEN);
- switch_channel_set_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE, "true");
- }
-
-
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
-
-
- 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);
- }
-
-
- video:
-
- sofia_glue_check_video_codecs(tech_pvt);
-
- if (sofia_test_flag(tech_pvt, TFLAG_VIDEO) && tech_pvt->video_rm_encoding && tech_pvt->remote_sdp_video_port) {
- /******************************************************************************************/
- if (tech_pvt->video_rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
- //const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
- //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
- char *remote_host = switch_rtp_get_remote_host(tech_pvt->video_rtp_session);
- switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->video_rtp_session);
-
-
-
- if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_video_ip) && remote_port == tech_pvt->remote_sdp_video_port) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n",
- switch_channel_get_name(tech_pvt->channel));
- goto video_up;
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n",
- switch_channel_get_name(tech_pvt->channel),
- remote_host, remote_port, tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port);
- }
- }
-
- if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", switch_channel_get_name(tech_pvt->channel),
- tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_video_port, tech_pvt->remote_sdp_video_ip,
- tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
-
- if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
- switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
- }
- }
-
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->local_sdp_video_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, tmp);
-
-
- if (tech_pvt->video_rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
- const char *rport = NULL;
- switch_port_t remote_rtcp_port = 0;
-
- sofia_clear_flag_locked(tech_pvt, TFLAG_REINVITE);
-
- if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_video_rtcp_port"))) {
- remote_rtcp_port = (switch_port_t)atoi(rport);
- }
-
- if (switch_rtp_set_remote_address
- (tech_pvt->video_rtp_session, tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port, remote_rtcp_port, SWITCH_TRUE,
- &err) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
- tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port);
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
- !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
- /* Reactivate the NAT buster flag. */
- switch_rtp_set_flag(tech_pvt->video_rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
- }
-
- }
- goto video_up;
- }
-
- if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
- sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
- !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT);
- } else {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_DATAWAIT);
- }
- timer_name = NULL;
-
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
- switch_channel_get_name(tech_pvt->channel),
- tech_pvt->local_sdp_audio_ip,
- tech_pvt->local_sdp_video_port,
- tech_pvt->remote_sdp_video_ip,
- tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
-
- if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
- switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
- }
- } else {
- timer_name = tech_pvt->profile->timer_name;
-
- if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) {
- timer_name = (char *) var;
- }
- }
-
- /******************************************************************************************/
-
- if (tech_pvt->video_rtp_session) {
- goto video_up;
- }
-
-
- if (!tech_pvt->local_sdp_video_port) {
- sofia_glue_tech_choose_video_port(tech_pvt, 1);
- }
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
- !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE);
- } else {
- flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE);
- }
-
- if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
- flags |= SWITCH_RTP_FLAG_PROXY_MEDIA;
- }
- sofia_glue_tech_set_video_codec(tech_pvt, 0);
-
- flags &= ~(SWITCH_RTP_FLAG_USE_TIMER | SWITCH_RTP_FLAG_NOBLOCK);
- flags |= SWITCH_RTP_FLAG_VIDEO;
-
- tech_pvt->video_rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
- tech_pvt->local_sdp_video_port,
- tech_pvt->remote_sdp_video_ip,
- tech_pvt->remote_sdp_video_port,
- tech_pvt->video_agreed_pt,
- 1, 90000, (switch_rtp_flag_t) flags, NULL, &err, switch_core_session_get_pool(tech_pvt->session));
-
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
- switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
- switch_channel_get_name(tech_pvt->channel),
- tech_pvt->local_sdp_audio_ip,
- tech_pvt->local_sdp_video_port,
- tech_pvt->remote_sdp_video_ip,
- tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt,
- 0, switch_rtp_ready(tech_pvt->video_rtp_session) ? "SUCCESS" : err);
-
-
- if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
- switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
- }
-
- if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
- const char *ssrc;
- switch_channel_set_flag(tech_pvt->channel, CF_VIDEO);
- if ((ssrc = switch_channel_get_variable(tech_pvt->channel, "rtp_use_video_ssrc"))) {
- uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
- switch_rtp_set_ssrc(tech_pvt->video_rtp_session, ssrc_ul);
- }
-
-
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_manual_video_rtp_bugs"))) {
- sofia_glue_parse_rtp_bugs(&tech_pvt->video_rtp_bugs, val);
- }
-
- switch_rtp_intentional_bugs(tech_pvt->video_rtp_session, tech_pvt->video_rtp_bugs | tech_pvt->profile->manual_video_rtp_bugs);
-
- if (tech_pvt->video_recv_pt != tech_pvt->video_agreed_pt) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
- "%s Set video receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->video_recv_pt);
- switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_recv_pt);
- }
-
- switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_pt", "%d", tech_pvt->video_agreed_pt);
- tech_pvt->video_ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session);
- switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_video_ssrc", "%u", tech_pvt->ssrc);
-
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec"))
- || (val = tech_pvt->profile->rtcp_audio_interval_msec)) {
- const char *rport = switch_channel_get_variable(tech_pvt->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(tech_pvt->rtp_session, -1, remote_port);
- } else {
- int interval = atoi(val);
- if (interval < 100 || interval > 5000) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
- "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval);
- } else {
- switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval, remote_port);
- }
- }
- }
- 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));
- switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
- goto end;
- }
- }
-
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
- switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
- sofia_clear_flag_locked(tech_pvt, TFLAG_IO);
- status = SWITCH_STATUS_FALSE;
- goto end;
- }
-
- video_up:
-
- sofia_set_flag(tech_pvt, TFLAG_IO);
- status = SWITCH_STATUS_SUCCESS;
-
- end:
-
- sofia_clear_flag_locked(tech_pvt, TFLAG_REINVITE);
- switch_core_recovery_track(tech_pvt->session);
-
- switch_mutex_unlock(tech_pvt->sofia_mutex);
-
- return status;
-
-}
-
-static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size_t buflen)
-{
- int codec_ms = ptime;
- uint32_t map_bit_rate = 0;
- char ptstr[20] = "";
- char ratestr[20] = "";
- char bitstr[20] = "";
- switch_codec_fmtp_t codec_fmtp = { 0 };
-
- if (!codec_ms) {
- codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
- }
-
- map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
-
- if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
- ptime = codec_ms = 30;
- }
-
- if (zstr(map->rm_fmtp)) {
- if (!strcasecmp(map->rm_encoding, "ilbc")) {
- ptime = codec_ms = 30;
- map_bit_rate = 13330;
- }
- } else {
- if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
- if (codec_fmtp.bits_per_second) {
- map_bit_rate = codec_fmtp.bits_per_second;
- }
- if (codec_fmtp.microseconds_per_packet) {
- codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
- }
- }
- }
-
- if (map->rm_rate) {
- switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
- }
-
- if (codec_ms) {
- switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
- }
-
- if (map_bit_rate) {
- switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
- }
-
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr);
-
-}
-
-void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session)
-{
- switch_channel_t *aleg_channel;
- private_object_t *aleg_tech_pvt;
- switch_channel_t *bleg_channel;
- private_object_t *bleg_tech_pvt;
-
- if (!switch_core_session_compare(aleg_session, bleg_session)) {
- /* since this digs into channel internals its only compatible with sofia sessions*/
- return;
- }
-
- aleg_channel = switch_core_session_get_channel(aleg_session);
- aleg_tech_pvt = switch_core_session_get_private(aleg_session);
- bleg_channel = switch_core_session_get_channel(bleg_session);
- bleg_tech_pvt = switch_core_session_get_private(bleg_session);
-
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_channel), SWITCH_LOG_DEBUG1, "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_DEBUG1, "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_DEBUG1, "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_DEBUG1, "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_DEBUG1, "No partner channel found, so not propagating zrtp-hash\n");
- return;
- } else {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "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_DEBUG1, "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)
-{
- char buf[1024] = { 0 };
- sdp_media_t *m;
- sdp_attribute_t *attr;
- int ptime = 0, dptime = 0;
- sdp_connection_t *connection;
- sdp_rtpmap_t *map;
- short int match = 0;
- int i;
- int already_did[128] = { 0 };
- int num_codecs = 0;
- char *codec_order[SWITCH_MAX_CODECS];
- const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS] = { 0 };
- switch_channel_t *channel = switch_core_session_get_channel(session);
- private_object_t *tech_pvt = switch_core_session_get_private(session);
- int prefer_sdp = 0;
- const char *var;
-
- if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) {
- prefer_sdp = 1;
- }
-
- if (!zstr(codec_string)) {
- char *tmp_codec_string;
- if ((tmp_codec_string = strdup(codec_string))) {
- num_codecs = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS);
- num_codecs = switch_loadable_module_get_codecs_sorted(codecs, SWITCH_MAX_CODECS, codec_order, num_codecs);
- switch_safe_free(tmp_codec_string);
- }
- } else {
- num_codecs = switch_loadable_module_get_codecs(codecs, SWITCH_MAX_CODECS);
- }
-
- if (!channel || !num_codecs) {
- return;
- }
-
- for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
- if (zstr(attr->a_name)) {
- continue;
- }
- if (!strcasecmp(attr->a_name, "ptime")) {
- dptime = atoi(attr->a_value);
- break;
- }
- }
-
- find_zrtp_hash(session, sdp);
- sofia_glue_pass_zrtp_hash(session);
-
- for (m = sdp->sdp_media; m; m = m->m_next) {
- ptime = dptime;
- if (m->m_type == sdp_media_image && m->m_port) {
- switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",t38");
- } else if (m->m_type == sdp_media_audio && m->m_port) {
- for (attr = m->m_attributes; attr; attr = attr->a_next) {
- if (zstr(attr->a_name)) {
- continue;
- }
- if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
- ptime = atoi(attr->a_value);
- break;
- }
- }
- connection = sdp->sdp_connection;
- if (m->m_connections) {
- connection = m->m_connections;
- }
-
- if (!connection) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
- break;
- }
-
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
- if (map->rm_pt > 127 || already_did[map->rm_pt]) {
- continue;
- }
-
- for (i = 0; i < num_codecs; i++) {
- const switch_codec_implementation_t *imp = codecs[i];
-
- if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
- match = (map->rm_pt == imp->ianacode) ? 1 : 0;
- } else {
- if (map->rm_encoding) {
- match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
- } else {
- match = 0;
- }
- }
-
- if (match) {
- add_audio_codec(map, ptime, buf, sizeof(buf));
- break;
- }
-
- }
- }
-
- } else {
- for (i = 0; i < num_codecs; i++) {
- const switch_codec_implementation_t *imp = codecs[i];
- if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) {
- continue;
- }
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
- if (map->rm_pt > 127 || already_did[map->rm_pt]) {
- continue;
- }
-
- if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
- match = (map->rm_pt == imp->ianacode) ? 1 : 0;
- } else {
- if (map->rm_encoding) {
- match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
- } else {
- match = 0;
- }
- }
-
- if (match) {
- add_audio_codec(map, ptime, buf, sizeof(buf));
- break;
- }
- }
- }
- }
-
- } else if (m->m_type == sdp_media_video && m->m_port) {
- connection = sdp->sdp_connection;
- if (m->m_connections) {
- connection = m->m_connections;
- }
-
- if (!connection) {
- switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
- break;
- }
- for (i = 0; i < num_codecs; i++) {
- const switch_codec_implementation_t *imp = codecs[i];
- if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO || imp->ianacode > 127 || already_did[imp->ianacode]) {
- continue;
- }
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
- if (map->rm_pt > 127 || already_did[map->rm_pt]) {
- continue;
- }
-
- if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
- match = (map->rm_pt == imp->ianacode) ? 1 : 0;
- } else {
- if (map->rm_encoding) {
- match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
- } else {
- match = 0;
- }
- }
-
- if (match) {
- if (ptime > 0) {
- switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate,
- ptime);
- } else {
- switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate);
- }
- already_did[imp->ianacode] = 1;
- break;
- }
- }
- }
- }
- }
- if (buf[0] == ',') {
- switch_channel_set_variable(channel, "ep_codec_string", buf + 1);
- }
-}
-
-switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_sdp)
-{
- uint8_t match = 0;
-
- switch_assert(tech_pvt != NULL);
- switch_assert(r_sdp != NULL);
-
- if (zstr(r_sdp)) {
- return SWITCH_STATUS_FALSE;
- }
-
- if ((match = sofia_glue_negotiate_sdp(tech_pvt->session, r_sdp))) {
- if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
- return SWITCH_STATUS_FALSE;
- }
- if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
- return SWITCH_STATUS_FALSE;
- }
- switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
- sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
- switch_channel_mark_pre_answered(tech_pvt->channel);
- return SWITCH_STATUS_SUCCESS;
- }
-
-
- return SWITCH_STATUS_FALSE;
-}
-
-int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
-{
- int changed = 0;
-
- if (sofia_test_flag(tech_pvt, TFLAG_SLA_BARGE) || sofia_test_flag(tech_pvt, TFLAG_SLA_BARGING)) {
- switch_channel_mark_hold(tech_pvt->channel, sendonly);
- return 0;
- }
-
- if (sendonly && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
- if (!sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
- const char *stream;
- const char *msg = "hold";
-
- if (sofia_test_pflag(tech_pvt->profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
- const char *info = switch_channel_get_variable(tech_pvt->channel, "presence_call_info");
- if (info) {
- if (switch_stristr("private", info)) {
- msg = "hold-private";
- }
- }
- }
-
- sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
- switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
- switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
- changed = 1;
-
- if (tech_pvt->max_missed_hold_packets) {
- switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_hold_packets);
- }
-
- if (!(stream = switch_channel_get_hold_music(tech_pvt->channel))) {
- stream = tech_pvt->profile->hold_music;
- }
-
- if (stream && strcasecmp(stream, "silence")) {
- if (!strcasecmp(stream, "indicate_hold")) {
- switch_channel_set_flag(tech_pvt->channel, CF_SUSPEND);
- switch_channel_set_flag(tech_pvt->channel, CF_HOLD);
- switch_ivr_hold_uuid(switch_channel_get_partner_uuid(tech_pvt->channel), NULL, 0);
- } else {
- switch_ivr_broadcast(switch_channel_get_partner_uuid(tech_pvt->channel), stream,
- SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY);
- switch_yield(250000);
- }
- }
- }
- } else {
- if (sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
- sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD);
- switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
- changed = 1;
- }
-
- sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
-
- if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
- const char *uuid;
- switch_core_session_t *b_session;
-
- switch_yield(250000);
-
- if (tech_pvt->max_missed_packets) {
- switch_rtp_reset_media_timer(tech_pvt->rtp_session);
- switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets);
- }
-
- if ((uuid = switch_channel_get_partner_uuid(tech_pvt->channel)) && (b_session = switch_core_session_locate(uuid))) {
- switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
-
- if (switch_channel_test_flag(tech_pvt->channel, CF_HOLD)) {
- switch_ivr_unhold(b_session);
- switch_channel_clear_flag(tech_pvt->channel, CF_SUSPEND);
- switch_channel_clear_flag(tech_pvt->channel, CF_HOLD);
- } else {
- switch_channel_stop_broadcast(b_channel);
- switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
- }
- switch_core_session_rwunlock(b_session);
- }
-
- sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
- switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
- switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
- changed = 1;
- }
- }
-
- return changed;
-}
-
-void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session)
-{
- switch_channel_t *channel = switch_core_session_get_channel(session);
- switch_t38_options_t *local_t38_options = switch_channel_get_private(channel, "t38_options");
-
- switch_assert(t38_options);
-
- if (!local_t38_options) {
- local_t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
- }
-
- local_t38_options->T38MaxBitRate = t38_options->T38MaxBitRate;
- local_t38_options->T38FaxFillBitRemoval = t38_options->T38FaxFillBitRemoval;
- local_t38_options->T38FaxTranscodingMMR = t38_options->T38FaxTranscodingMMR;
- local_t38_options->T38FaxTranscodingJBIG = t38_options->T38FaxTranscodingJBIG;
- local_t38_options->T38FaxRateManagement = switch_core_session_strdup(session, t38_options->T38FaxRateManagement);
- local_t38_options->T38FaxMaxBuffer = t38_options->T38FaxMaxBuffer;
- local_t38_options->T38FaxMaxDatagram = t38_options->T38FaxMaxDatagram;
- local_t38_options->T38FaxUdpEC = switch_core_session_strdup(session, t38_options->T38FaxUdpEC);
- local_t38_options->T38VendorInfo = switch_core_session_strdup(session, t38_options->T38VendorInfo);
- local_t38_options->remote_ip = switch_core_session_strdup(session, t38_options->remote_ip);
- local_t38_options->remote_port = t38_options->remote_port;
-
-
- switch_channel_set_private(channel, "t38_options", local_t38_options);
-
-}
-
-static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_session_t *sdp, sdp_media_t *m)
-{
- switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
- sdp_attribute_t *attr;
-
- if (!t38_options) {
- t38_options = switch_core_session_alloc(tech_pvt->session, sizeof(switch_t38_options_t));
-
- // set some default value
- t38_options->T38FaxVersion = 0;
- t38_options->T38MaxBitRate = 14400;
- t38_options->T38FaxRateManagement = switch_core_session_strdup(tech_pvt->session, "transferredTCF");
- t38_options->T38FaxUdpEC = switch_core_session_strdup(tech_pvt->session, "t38UDPRedundancy");
- t38_options->T38FaxMaxBuffer = 500;
- t38_options->T38FaxMaxDatagram = 500;
- }
-
- t38_options->remote_port = (switch_port_t)m->m_port;
-
- if (sdp->sdp_origin) {
- t38_options->sdp_o_line = switch_core_session_strdup(tech_pvt->session, sdp->sdp_origin->o_username);
- } else {
- t38_options->sdp_o_line = "unknown";
- }
-
- if (m->m_connections && m->m_connections->c_address) {
- t38_options->remote_ip = switch_core_session_strdup(tech_pvt->session, m->m_connections->c_address);
- } else if (sdp && sdp->sdp_connection && sdp->sdp_connection->c_address) {
- t38_options->remote_ip = switch_core_session_strdup(tech_pvt->session, sdp->sdp_connection->c_address);
- }
-
- for (attr = m->m_attributes; attr; attr = attr->a_next) {
- if (!strcasecmp(attr->a_name, "T38FaxVersion") && attr->a_value) {
- t38_options->T38FaxVersion = (uint16_t) atoi(attr->a_value);
- } else if (!strcasecmp(attr->a_name, "T38MaxBitRate") && attr->a_value) {
- t38_options->T38MaxBitRate = (uint32_t) atoi(attr->a_value);
- } else if (!strcasecmp(attr->a_name, "T38FaxFillBitRemoval")) {
- t38_options->T38FaxFillBitRemoval = switch_safe_atoi(attr->a_value, 1);
- } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingMMR")) {
- t38_options->T38FaxTranscodingMMR = switch_safe_atoi(attr->a_value, 1);
- } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingJBIG")) {
- t38_options->T38FaxTranscodingJBIG = switch_safe_atoi(attr->a_value, 1);
- } else if (!strcasecmp(attr->a_name, "T38FaxRateManagement") && attr->a_value) {
- t38_options->T38FaxRateManagement = switch_core_session_strdup(tech_pvt->session, attr->a_value);
- } else if (!strcasecmp(attr->a_name, "T38FaxMaxBuffer") && attr->a_value) {
- t38_options->T38FaxMaxBuffer = (uint32_t) atoi(attr->a_value);
- } else if (!strcasecmp(attr->a_name, "T38FaxMaxDatagram") && attr->a_value) {
- t38_options->T38FaxMaxDatagram = (uint32_t) atoi(attr->a_value);
- } else if (!strcasecmp(attr->a_name, "T38FaxUdpEC") && attr->a_value) {
- t38_options->T38FaxUdpEC = switch_core_session_strdup(tech_pvt->session, attr->a_value);
- } else if (!strcasecmp(attr->a_name, "T38VendorInfo") && attr->a_value) {
- t38_options->T38VendorInfo = switch_core_session_strdup(tech_pvt->session, attr->a_value);
- }
- }
-
- switch_channel_set_variable(tech_pvt->channel, "has_t38", "true");
- switch_channel_set_private(tech_pvt->channel, "t38_options", t38_options);
- switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
-
- switch_channel_execute_on(tech_pvt->channel, "sip_execute_on_image");
- switch_channel_api_on(tech_pvt->channel, "sip_api_on_image");
-
- return t38_options;
-}
-
-
-switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, switch_event_t **pt)
-{
- sdp_media_t *m;
- sdp_parser_t *parser = NULL;
- sdp_session_t *sdp;
-
- if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
- return SWITCH_STATUS_FALSE;
- }
-
- if (!(sdp = sdp_session(parser))) {
- sdp_parser_free(parser);
- return SWITCH_STATUS_FALSE;
- }
-
- switch_event_create(&(*fmtp), SWITCH_EVENT_REQUEST_PARAMS);
- switch_event_create(&(*pt), SWITCH_EVENT_REQUEST_PARAMS);
-
- for (m = sdp->sdp_media; m; m = m->m_next) {
- if (m->m_proto == sdp_proto_rtp) {
- sdp_rtpmap_t *map;
-
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
- if (map->rm_encoding) {
- char buf[25] = "";
- char key[128] = "";
- char *br = NULL;
-
- if (map->rm_fmtp) {
- if ((br = strstr(map->rm_fmtp, "bitrate="))) {
- br += 8;
+ if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
+ match = (map->rm_pt == imp->ianacode) ? 1 : 0;
+ } else {
+ if (map->rm_encoding) {
+ match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
+ } else {
+ match = 0;
+ }
}
- }
-
- switch_snprintf(buf, sizeof(buf), "%d", map->rm_pt);
- if (br) {
- switch_snprintf(key, sizeof(key), "%s:%s", map->rm_encoding, br);
- } else {
- switch_snprintf(key, sizeof(key), "%s", map->rm_encoding);
- }
+ if (match) {
+ add_audio_codec(map, ptime, buf, sizeof(buf));
+ break;
+ }
- switch_event_add_header_string(*pt, SWITCH_STACK_BOTTOM, key, buf);
-
- if (map->rm_fmtp) {
- switch_event_add_header_string(*fmtp, SWITCH_STACK_BOTTOM, key, map->rm_fmtp);
}
}
- }
- }
- }
-
- sdp_parser_free(parser);
-
- return SWITCH_STATUS_SUCCESS;
-
-}
-
-
-void sofia_glue_proxy_codec(switch_core_session_t *session, const char *r_sdp)
-{
- sdp_media_t *m;
- sdp_parser_t *parser = NULL;
- sdp_session_t *sdp;
- private_object_t *tech_pvt = switch_core_session_get_private(session);
- sdp_attribute_t *attr;
- int ptime = 0, dptime = 0;
-
- if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
- return;
- }
-
- if (!(sdp = sdp_session(parser))) {
- sdp_parser_free(parser);
- return;
- }
-
- switch_assert(tech_pvt != NULL);
-
-
- for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
- if (zstr(attr->a_name)) {
- continue;
- }
-
- if (!strcasecmp(attr->a_name, "ptime")) {
- dptime = atoi(attr->a_value);
- }
- }
-
-
- for (m = sdp->sdp_media; m; m = m->m_next) {
-
- ptime = dptime;
- //maxptime = dmaxptime;
-
- if (m->m_proto == sdp_proto_rtp) {
- sdp_rtpmap_t *map;
- for (attr = m->m_attributes; attr; attr = attr->a_next) {
- if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
- ptime = atoi(attr->a_value);
- } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
- //maxptime = atoi(attr->a_value);
- }
- }
-
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
- tech_pvt->iananame = switch_core_session_strdup(tech_pvt->session, map->rm_encoding);
- tech_pvt->rm_rate = map->rm_rate;
- tech_pvt->codec_ms = ptime;
- sofia_glue_tech_set_codec(tech_pvt, 0);
- break;
- }
-
- break;
- }
- }
-
- sdp_parser_free(parser);
-
-}
-
-switch_t38_options_t *sofia_glue_extract_t38_options(switch_core_session_t *session, const char *r_sdp)
-{
- sdp_media_t *m;
- sdp_parser_t *parser = NULL;
- sdp_session_t *sdp;
- private_object_t *tech_pvt = switch_core_session_get_private(session);
- switch_t38_options_t *t38_options = NULL;
-
- if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
- return 0;
- }
-
- if (!(sdp = sdp_session(parser))) {
- sdp_parser_free(parser);
- return 0;
- }
-
- switch_assert(tech_pvt != NULL);
-
- for (m = sdp->sdp_media; m; m = m->m_next) {
- if (m->m_proto == sdp_proto_udptl && m->m_type == sdp_media_image && m->m_port) {
- t38_options = tech_process_udptl(tech_pvt, sdp, m);
- break;
- }
- }
-
- sdp_parser_free(parser);
-
- return t38_options;
-
-}
-
-switch_status_t sofia_glue_get_offered_pt(private_object_t *tech_pvt, const switch_codec_implementation_t *mimp, switch_payload_t *pt)
-{
- int i = 0;
-
- for (i = 0; i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-
- if (!strcasecmp(imp->iananame, mimp->iananame)) {
- *pt = tech_pvt->ianacodes[i];
-
- return SWITCH_STATUS_SUCCESS;
- }
- }
-
- return SWITCH_STATUS_FALSE;
-}
-
-
-uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_sdp)
-{
- uint8_t match = 0;
- switch_payload_t best_te = 0, te = 0, cng_pt = 0;
- private_object_t *tech_pvt = switch_core_session_get_private(session);
- sdp_media_t *m;
- sdp_attribute_t *attr;
- int first = 0, last = 0;
- int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
- int sendonly = 0, recvonly = 0;
- int greedy = 0, x = 0, skip = 0, mine = 0;
- switch_channel_t *channel = switch_core_session_get_channel(session);
- const char *val;
- const char *crypto = NULL;
- int got_crypto = 0, got_audio = 0, got_avp = 0, got_savp = 0, got_udptl = 0;
- int scrooge = 0;
- sdp_parser_t *parser = NULL;
- sdp_session_t *sdp;
- int reneg = 1;
- const switch_codec_implementation_t **codec_array;
- int total_codecs;
-
-
- codec_array = tech_pvt->codecs;
- total_codecs = tech_pvt->num_codecs;
-
-
- if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
- return 0;
- }
-
- if (!(sdp = sdp_session(parser))) {
- sdp_parser_free(parser);
- return 0;
- }
-
- switch_assert(tech_pvt != NULL);
-
- greedy = !!sofia_test_pflag(tech_pvt->profile, PFLAG_GREEDY);
- scrooge = !!sofia_test_pflag(tech_pvt->profile, PFLAG_SCROOGE);
-
- if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation"))) {
- if (!strcasecmp(val, "generous")) {
- greedy = 0;
- scrooge = 0;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : generous\n" );
- } else if (!strcasecmp(val, "greedy")) {
- greedy = 1;
- scrooge = 0;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : greedy\n" );
- } else if (!strcasecmp(val, "scrooge")) {
- scrooge = 1;
- greedy = 1;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : scrooge\n" );
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation ignored invalid value : '%s' \n", val );
- }
- }
-
- if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
-
- if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833) {
-
- if (strstr(tech_pvt->origin, "CiscoSystemsSIP-GW-UserAgent")) {
- tech_pvt->rtp_bugs |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
- }
- }
-
- if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833) {
- if (strstr(tech_pvt->origin, "Sonus_UAC")) {
- tech_pvt->rtp_bugs |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
- "Hello,\nI see you have a Sonus!\n"
- "FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n"
- "Sadly, my creator had to spend several hours figuring this out so I thought you'd like to know that!\n"
- "Don't worry, DTMF will work but you may want to ask them to fix it......\n");
- }
- }
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_liberal_dtmf")) && switch_true(val)) {
- sofia_set_flag_locked(tech_pvt, TFLAG_LIBERAL_DTMF);
- }
-
- if ((m = sdp->sdp_media) &&
- (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive ||
- (m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")))) {
- sendonly = 2; /* global sendonly always wins */
- }
-
- for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
- if (zstr(attr->a_name)) {
- continue;
- }
-
- if (!strcasecmp(attr->a_name, "sendonly")) {
- sendonly = 1;
- switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "recvonly");
- } else if (!strcasecmp(attr->a_name, "inactive")) {
- sendonly = 1;
- switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "inactive");
- } else if (!strcasecmp(attr->a_name, "recvonly")) {
- switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "sendonly");
- recvonly = 1;
-
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, 0);
- tech_pvt->max_missed_hold_packets = 0;
- tech_pvt->max_missed_packets = 0;
- } else {
- switch_channel_set_variable(tech_pvt->channel, "rtp_timeout_sec", "0");
- switch_channel_set_variable(tech_pvt->channel, "rtp_hold_timeout_sec", "0");
- }
- } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) {
- sendonly = 0;
- } else if (!strcasecmp(attr->a_name, "ptime")) {
- dptime = atoi(attr->a_value);
- } else if (!strcasecmp(attr->a_name, "maxptime")) {
- dmaxptime = atoi(attr->a_value);
- }
- }
-
- if (sendonly != 1 && recvonly != 1) {
- switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", NULL);
- }
-
-
- if (sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_HOLD) ||
- ((val = switch_channel_get_variable(tech_pvt->channel, "sip_disable_hold")) && switch_true(val))) {
- sendonly = 0;
- } else {
-
- if (!tech_pvt->hold_laps) {
- tech_pvt->hold_laps++;
- if (sofia_glue_toggle_hold(tech_pvt, sendonly)) {
- reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_HOLD);
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_hold"))) {
- reneg = switch_true(val);
- }
- }
-
- }
- }
-
- if (reneg) {
- reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE);
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_reinvite"))) {
- reneg = switch_true(val);
- }
- }
-
- if (!reneg && tech_pvt->num_negotiated_codecs) {
- codec_array = tech_pvt->negotiated_codecs;
- total_codecs = tech_pvt->num_negotiated_codecs;
- } else if (reneg) {
- tech_pvt->num_codecs = 0;
- sofia_glue_tech_prepare_codecs(tech_pvt);
- codec_array = tech_pvt->codecs;
- total_codecs = tech_pvt->num_codecs;
- }
-
- if (switch_stristr("T38FaxFillBitRemoval:", r_sdp) || switch_stristr("T38FaxTranscodingMMR:", r_sdp) ||
- switch_stristr("T38FaxTranscodingJBIG:", r_sdp)) {
- 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;
-
- ptime = dptime;
- maxptime = dmaxptime;
-
- if (m->m_proto == sdp_proto_srtp) {
- got_savp++;
- } else if (m->m_proto == sdp_proto_rtp) {
- got_avp++;
- } else if (m->m_proto == sdp_proto_udptl) {
- got_udptl++;
- }
-
- if (got_udptl && m->m_type == sdp_media_image && m->m_port) {
- switch_t38_options_t *t38_options = tech_process_udptl(tech_pvt, sdp, m);
-
- if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_NEGOTIATED)) {
- match = 1;
- goto done;
- }
-
- if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) {
- switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
- match = 0;
- goto done;
} else {
- const char *var = switch_channel_get_variable(channel, "t38_passthru");
- int pass = sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU);
-
-
- if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) {
- sofia_set_flag(tech_pvt, TFLAG_NOREPLY);
- }
-
- if (var) {
- if (!(pass = switch_true(var))) {
- if (!strcasecmp(var, "once")) {
- pass = 2;
- }
- }
- }
-
- if ((pass == 2 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) ||
- !sofia_test_flag(tech_pvt, TFLAG_REINVITE) ||
- switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
- switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) ||
- !switch_rtp_ready(tech_pvt->rtp_session)) {
- pass = 0;
- }
-
- if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
- private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
- switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
- switch_core_session_message_t *msg;
- char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
- switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
- char tmp[32] = "";
-
- if (switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean")) &&
- switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_pass_broken_boolean"))) {
- switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
- }
-
- tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, t38_options->remote_ip);
- tech_pvt->remote_sdp_audio_port = t38_options->remote_port;
-
- if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
- switch_channel_get_name(tech_pvt->channel));
- } else {
- const char *err = NULL;
-
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
- switch_channel_get_name(tech_pvt->channel),
- remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
-
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
-
- if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip,
- tech_pvt->remote_sdp_audio_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
- switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
- }
-
+ for (i = 0; i < num_codecs; i++) {
+ const switch_codec_implementation_t *imp = codecs[i];
+ if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) {
+ continue;
}
-
-
-
- sofia_glue_copy_t38_options(t38_options, other_session);
-
- sofia_set_flag(tech_pvt, TFLAG_T38_PASSTHRU);
- sofia_set_flag(other_tech_pvt, TFLAG_T38_PASSTHRU);
-
- msg = switch_core_session_alloc(other_session, sizeof(*msg));
- msg->message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA;
- msg->from = __FILE__;
- msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp);
- switch_core_session_queue_message(other_session, msg);
- switch_core_session_rwunlock(other_session);
- }
- }
-
-
- /* do nothing here, mod_fax will trigger a response (if it's listening =/) */
- match = 1;
- goto done;
- } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
- sdp_rtpmap_t *map;
-
- for (attr = m->m_attributes; attr; attr = attr->a_next) {
-
- if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
- switch_channel_set_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port", attr->a_value);
- } else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
- ptime = atoi(attr->a_value);
- } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
- maxptime = atoi(attr->a_value);
- } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
- int crypto_tag;
-
- if (!(tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_CRYPTO_IN_AVP) &&
- !switch_true(switch_channel_get_variable(tech_pvt->channel, "sip_allow_crypto_in_avp"))) {
- if (m->m_proto != sdp_proto_srtp) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
- match = 0;
- goto done;
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+ if (map->rm_pt > 127 || already_did[map->rm_pt]) {
+ continue;
}
- }
- crypto = attr->a_value;
- crypto_tag = atoi(crypto);
-
- if (tech_pvt->remote_crypto_key && switch_rtp_ready(tech_pvt->rtp_session)) {
- /* Compare all the key. The tag may remain the same even if key changed */
- if (crypto && !strcmp(crypto, tech_pvt->remote_crypto_key)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
+ if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
+ match = (map->rm_pt == imp->ianacode) ? 1 : 0;
} else {
- const char *a = switch_stristr("AES", tech_pvt->remote_crypto_key);
- const char *b = switch_stristr("AES", crypto);
-
- /* Change our key every time we can */
-
- if (sofia_test_flag(tech_pvt, TFLAG_CRYPTO_RECOVER)) {
- sofia_clear_flag(tech_pvt, TFLAG_CRYPTO_RECOVER);
- } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_32);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), tech_pvt->crypto_type,
- tech_pvt->local_raw_key, SWITCH_RTP_KEY_LEN);
- } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_80);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), tech_pvt->crypto_type,
- tech_pvt->local_raw_key, SWITCH_RTP_KEY_LEN);
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
- }
-
- if (a && b && !strncasecmp(a, b, 23)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
- tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
- switch_channel_set_variable(tech_pvt->channel, "srtp_remote_audio_crypto_key", crypto);
- tech_pvt->crypto_tag = crypto_tag;
-
- if (switch_rtp_ready(tech_pvt->rtp_session) && sofia_test_flag(tech_pvt, TFLAG_SECURE)) {
- sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
- switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag,
- tech_pvt->crypto_type, tech_pvt->remote_raw_key, SWITCH_RTP_KEY_LEN);
- }
- got_crypto++;
+ if (map->rm_encoding) {
+ match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
} else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n");
+ match = 0;
}
}
- } else if (!switch_rtp_ready(tech_pvt->rtp_session)) {
- tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", tech_pvt->remote_crypto_key);
- switch_channel_set_variable(tech_pvt->channel, "srtp_remote_audio_crypto_key", crypto);
- tech_pvt->crypto_tag = crypto_tag;
- got_crypto++;
-
- if (zstr(tech_pvt->local_crypto_key)) {
- if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_32);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
- } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_80);
- sofia_glue_build_crypto(tech_pvt, atoi(crypto), 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");
- }
+
+ if (match) {
+ add_audio_codec(map, ptime, buf, sizeof(buf));
+ break;
}
}
}
}
- if (got_crypto && !got_avp) {
- switch_channel_set_variable(tech_pvt->channel, SOFIA_CRYPTO_MANDATORY_VARIABLE, "true");
- switch_channel_set_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE, "true");
- }
-
+ } else if (m->m_type == sdp_media_video && m->m_port) {
connection = sdp->sdp_connection;
if (m->m_connections) {
connection = m->m_connections;
}
if (!connection) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
- match = 0;
+ switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
break;
}
-
- greed:
- x = 0;
-
- if (tech_pvt->rm_encoding && !(sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))) { // && !sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
- char *remote_host = tech_pvt->remote_sdp_audio_ip;
- switch_port_t remote_port = tech_pvt->remote_sdp_audio_port;
- int same = 0;
-
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
- remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
- }
-
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
- if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
- match = (map->rm_pt == tech_pvt->pt) ? 1 : 0;
- } else {
- match = strcasecmp(switch_str_nil(map->rm_encoding), tech_pvt->iananame) ? 0 : 1;
- }
-
- if (match && connection->c_address && remote_host && !strcmp(connection->c_address, remote_host) && m->m_port == remote_port) {
- same = 1;
- } else {
- same = 0;
- break;
- }
- }
-
- if (same) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
- "Our existing sdp is still good [%s %s:%d], let's keep it.\n",
- tech_pvt->rm_encoding, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
- got_audio = 1;
- } else {
- match = 0;
- got_audio = 0;
- }
- }
-
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
- int32_t i;
- uint32_t near_rate = 0;
- const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
- const char *rm_encoding;
- uint32_t map_bit_rate = 0;
- int codec_ms = 0;
- switch_codec_fmtp_t codec_fmtp = { 0 };
-
- if (x++ < skip) {
- continue;
- }
-
- if (!(rm_encoding = map->rm_encoding)) {
- rm_encoding = "";
- }
-
- if (!strcasecmp(rm_encoding, "telephone-event")) {
- if (!best_te || map->rm_rate == tech_pvt->rm_rate) {
- best_te = (switch_payload_t) map->rm_pt;
- }
- }
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && !cng_pt && !strcasecmp(rm_encoding, "CN")) {
- cng_pt = (switch_payload_t) map->rm_pt;
- if (tech_pvt->rtp_session) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt);
- switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt);
- }
- }
-
- if (match) {
+ for (i = 0; i < num_codecs; i++) {
+ const switch_codec_implementation_t *imp = codecs[i];
+ if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO || imp->ianacode > 127 || already_did[imp->ianacode]) {
continue;
}
-
- if (greedy) {
- first = mine;
- last = first + 1;
- } else {
- first = 0;
- last = tech_pvt->num_codecs;
- }
-
- codec_ms = ptime;
-
- if (maxptime && (!codec_ms || codec_ms > maxptime)) {
- codec_ms = maxptime;
- }
-
- if (!codec_ms) {
- codec_ms = switch_default_ptime(rm_encoding, map->rm_pt);
- }
-
- map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
-
- if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
- codec_ms = 30;
- }
-
- if (zstr(map->rm_fmtp)) {
- if (!strcasecmp(map->rm_encoding, "ilbc")) {
- codec_ms = 30;
- map_bit_rate = 13330;
- }
- } else {
- if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
- if (codec_fmtp.bits_per_second) {
- map_bit_rate = codec_fmtp.bits_per_second;
- }
- if (codec_fmtp.microseconds_per_packet) {
- codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
- }
- }
- }
-
-
- for (i = first; i < last && i < total_codecs; i++) {
- const switch_codec_implementation_t *imp = codec_array[i];
- uint32_t bit_rate = imp->bits_per_second;
- uint32_t codec_rate = imp->samples_per_second;
- if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+ if (map->rm_pt > 127 || already_did[map->rm_pt]) {
continue;
}
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n",
- rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate,
- imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate);
if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
match = (map->rm_pt == imp->ianacode) ? 1 : 0;
} else {
- match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
- }
-
- if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc")) {
- /* if a bit rate is specified and doesn't match, this is not a codec match, except for ILBC */
- match = 0;
+ if (map->rm_encoding) {
+ match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1;
+ } else {
+ match = 0;
+ }
}
- if (match && map->rm_rate && codec_rate && map->rm_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") || !strcasecmp(map->rm_encoding, "pcmu"))) {
- /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n");
- match = 0;
- }
-
if (match) {
- if (scrooge) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
- "Bah HUMBUG! Sticking with %s@%uh@%ui\n",
- imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
+ if (ptime > 0) {
+ switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate,
+ ptime);
} else {
- if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate) {
- near_rate = map->rm_rate;
- near_match = imp;
- match = 0;
- continue;
- }
+ switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate);
}
- mimp = imp;
+ already_did[imp->ianacode] = 1;
break;
}
}
+ }
+ }
+ }
+ if (buf[0] == ',') {
+ switch_channel_set_variable(channel, "ep_codec_string", buf + 1);
+ }
+}
- if (!match && near_match) {
- const switch_codec_implementation_t *search[1];
- char *prefs[1];
- char tmp[80];
- int num;
+switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_sdp)
+{
+ uint8_t match = 0;
- switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second,
- codec_ms);
+ switch_assert(tech_pvt != NULL);
+ switch_assert(r_sdp != NULL);
- prefs[0] = tmp;
- num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1);
+ if (zstr(r_sdp)) {
+ return SWITCH_STATUS_FALSE;
+ }
- if (num) {
- mimp = search[0];
- } else {
- mimp = near_match;
- }
+ if ((match = sofia_glue_negotiate_sdp(tech_pvt->session, r_sdp))) {
+ if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_FALSE;
+ }
+ if (sofia_glue_activate_rtp(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_FALSE;
+ }
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
+ sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
+ switch_channel_mark_pre_answered(tech_pvt->channel);
+ return SWITCH_STATUS_SUCCESS;
+ }
- if (!maxptime || mimp->microseconds_per_packet / 1000 <= maxptime) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh\n",
- mimp->iananame, mimp->microseconds_per_packet / 1000, mimp->samples_per_second);
- match = 1;
- } else {
- mimp = NULL;
- match = 0;
- }
- }
+ return SWITCH_STATUS_FALSE;
+}
- if (!match && greedy) {
- skip++;
- continue;
- }
+int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
+{
+ int changed = 0;
- if (mimp) {
- char tmp[50];
- const char *mirror = switch_channel_get_variable(tech_pvt->channel, "sip_mirror_remote_audio_codec_payload");
-
- tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding);
- tech_pvt->iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
- tech_pvt->pt = (switch_payload_t) map->rm_pt;
- tech_pvt->rm_rate = mimp->samples_per_second;
- tech_pvt->codec_ms = mimp->microseconds_per_packet / 1000;
- tech_pvt->bitrate = mimp->bits_per_second;
- tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(session, (char *) connection->c_address);
- tech_pvt->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
- tech_pvt->remote_sdp_audio_port = (switch_port_t) m->m_port;
- tech_pvt->agreed_pt = (switch_payload_t) map->rm_pt;
- tech_pvt->num_negotiated_codecs = 0;
- tech_pvt->negotiated_codecs[tech_pvt->num_negotiated_codecs++] = mimp;
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
- tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt;
-
- if (!switch_true(mirror) &&
- switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
- (!sofia_test_flag(tech_pvt, TFLAG_REINVITE) || sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE))) {
- sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->audio_recv_pt);
- }
-
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->audio_recv_pt);
- switch_channel_set_variable(tech_pvt->channel, "sip_audio_recv_pt", tmp);
-
- }
-
- if (match) {
- if (sofia_glue_tech_set_codec(tech_pvt, 1) == SWITCH_STATUS_SUCCESS) {
- got_audio = 1;
- } else {
- match = 0;
- }
- }
- }
+ if (sofia_test_flag(tech_pvt, TFLAG_SLA_BARGE) || sofia_test_flag(tech_pvt, TFLAG_SLA_BARGING)) {
+ switch_channel_mark_hold(tech_pvt->channel, sendonly);
+ return 0;
+ }
- if (!best_te && (sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
- "No 2833 in SDP. Liberal DTMF mode adding %d as telephone-event.\n", tech_pvt->profile->te);
- best_te = tech_pvt->profile->te;
- }
+ if (sendonly && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
+ if (!sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
+ const char *stream;
+ const char *msg = "hold";
- if (best_te) {
- if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
- te = tech_pvt->te = (switch_payload_t) best_te;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", best_te);
- if (tech_pvt->rtp_session) {
- switch_rtp_set_telephony_event(tech_pvt->rtp_session, (switch_payload_t) best_te);
- switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", best_te);
- }
- } else {
- te = tech_pvt->recv_te = tech_pvt->te = (switch_payload_t) best_te;
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send/recv payload to %u\n", te);
- if (tech_pvt->rtp_session) {
- switch_rtp_set_telephony_event(tech_pvt->rtp_session, te);
- switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", te);
- switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, te);
- switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", te);
+ if (sofia_test_pflag(tech_pvt->profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
+ const char *info = switch_channel_get_variable(tech_pvt->channel, "presence_call_info");
+ if (info) {
+ if (switch_stristr("private", info)) {
+ msg = "hold-private";
}
}
- } else {
- /* by default, use SIP INFO if 2833 is not in the SDP */
- if (!switch_false(switch_channel_get_variable(channel, "sip_info_when_no_2833"))) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No 2833 in SDP. Disable 2833 dtmf and switch to INFO\n");
- switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "info");
- tech_pvt->dtmf_type = DTMF_INFO;
- te = tech_pvt->recv_te = tech_pvt->te = 0;
- } else {
- switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "none");
- tech_pvt->dtmf_type = DTMF_NONE;
- te = tech_pvt->recv_te = tech_pvt->te = 0;
- }
- }
-
-
- if (!match && greedy && mine < total_codecs) {
- mine++;
- skip = 0;
- goto greed;
}
- } else if (m->m_type == sdp_media_video && m->m_port) {
- sdp_rtpmap_t *map;
- const char *rm_encoding;
- const switch_codec_implementation_t *mimp = NULL;
- int vmatch = 0, i;
- switch_channel_set_variable(tech_pvt->channel, "video_possible", "true");
+ sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+ switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
+ switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
+ changed = 1;
- connection = sdp->sdp_connection;
- if (m->m_connections) {
- connection = m->m_connections;
+ if (tech_pvt->max_missed_hold_packets) {
+ switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_hold_packets);
}
- if (!connection) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
- match = 0;
- break;
+ if (!(stream = switch_channel_get_hold_music(tech_pvt->channel))) {
+ stream = tech_pvt->profile->hold_music;
}
- for (map = m->m_rtpmaps; map; map = map->rm_next) {
-
- for (attr = m->m_attributes; attr; attr = attr->a_next) {
- if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
- //framerate = atoi(attr->a_value);
- }
- if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
- switch_channel_set_variable(tech_pvt->channel, "sip_remote_video_rtcp_port", attr->a_value);
- }
- }
- if (!(rm_encoding = map->rm_encoding)) {
- rm_encoding = "";
+ if (stream && strcasecmp(stream, "silence")) {
+ if (!strcasecmp(stream, "indicate_hold")) {
+ switch_channel_set_flag(tech_pvt->channel, CF_SUSPEND);
+ switch_channel_set_flag(tech_pvt->channel, CF_HOLD);
+ switch_ivr_hold_uuid(switch_channel_get_partner_uuid(tech_pvt->channel), NULL, 0);
+ } else {
+ switch_ivr_broadcast(switch_channel_get_partner_uuid(tech_pvt->channel), stream,
+ SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY);
+ switch_yield(250000);
}
+ }
+ }
+ } else {
+ if (sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
+ sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD);
+ switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
+ changed = 1;
+ }
- for (i = 0; i < total_codecs; i++) {
- const switch_codec_implementation_t *imp = codec_array[i];
-
- if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
- continue;
- }
-
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n",
- rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
- if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
- vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0;
- } else {
- vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
- }
+ sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
+ if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
+ const char *uuid;
+ switch_core_session_t *b_session;
- if (vmatch && (map->rm_rate == imp->samples_per_second)) {
- mimp = imp;
- break;
- } else {
- vmatch = 0;
- }
- }
+ switch_yield(250000);
- if (mimp) {
- if ((tech_pvt->video_rm_encoding = switch_core_session_strdup(session, (char *) rm_encoding))) {
- char tmp[50];
- const char *mirror = switch_channel_get_variable(tech_pvt->channel, "sip_mirror_remote_video_codec_payload");
-
- tech_pvt->video_pt = (switch_payload_t) map->rm_pt;
- tech_pvt->video_rm_rate = map->rm_rate;
- tech_pvt->video_codec_ms = mimp->microseconds_per_packet / 1000;
- tech_pvt->remote_sdp_video_ip = switch_core_session_strdup(session, (char *) connection->c_address);
- tech_pvt->video_rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
- tech_pvt->remote_sdp_video_port = (switch_port_t) m->m_port;
- tech_pvt->video_agreed_pt = (switch_payload_t) map->rm_pt;
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_video_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_VIDEO_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_VIDEO_PORT_VARIABLE, tmp);
- switch_channel_set_variable(tech_pvt->channel, "sip_video_fmtp", tech_pvt->video_rm_fmtp);
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_agreed_pt);
- switch_channel_set_variable(tech_pvt->channel, "sip_video_pt", tmp);
- sofia_glue_check_video_codecs(tech_pvt);
-
- tech_pvt->video_recv_pt = (switch_payload_t)map->rm_pt;
-
- if (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
- sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->video_recv_pt);
- }
+ if (tech_pvt->max_missed_packets) {
+ switch_rtp_reset_media_timer(tech_pvt->rtp_session);
+ switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets);
+ }
- switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_recv_pt);
- switch_channel_set_variable(tech_pvt->channel, "sip_video_recv_pt", tmp);
- if (!match && vmatch) match = 1;
+ if ((uuid = switch_channel_get_partner_uuid(tech_pvt->channel)) && (b_session = switch_core_session_locate(uuid))) {
+ switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
- break;
- } else {
- vmatch = 0;
- }
+ if (switch_channel_test_flag(tech_pvt->channel, CF_HOLD)) {
+ switch_ivr_unhold(b_session);
+ switch_channel_clear_flag(tech_pvt->channel, CF_SUSPEND);
+ switch_channel_clear_flag(tech_pvt->channel, CF_HOLD);
+ } else {
+ switch_channel_stop_broadcast(b_channel);
+ switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
}
+ switch_core_session_rwunlock(b_session);
}
+
+ sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+ switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
+ switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
+ changed = 1;
}
}
- done:
+ return changed;
+}
+
+void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_t38_options_t *local_t38_options = switch_channel_get_private(channel, "t38_options");
- if (parser) {
- sdp_parser_free(parser);
+ switch_assert(t38_options);
+
+ if (!local_t38_options) {
+ local_t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
}
- tech_pvt->cng_pt = cng_pt;
- sofia_set_flag_locked(tech_pvt, TFLAG_SDP);
+ local_t38_options->T38MaxBitRate = t38_options->T38MaxBitRate;
+ local_t38_options->T38FaxFillBitRemoval = t38_options->T38FaxFillBitRemoval;
+ local_t38_options->T38FaxTranscodingMMR = t38_options->T38FaxTranscodingMMR;
+ local_t38_options->T38FaxTranscodingJBIG = t38_options->T38FaxTranscodingJBIG;
+ local_t38_options->T38FaxRateManagement = switch_core_session_strdup(session, t38_options->T38FaxRateManagement);
+ local_t38_options->T38FaxMaxBuffer = t38_options->T38FaxMaxBuffer;
+ local_t38_options->T38FaxMaxDatagram = t38_options->T38FaxMaxDatagram;
+ local_t38_options->T38FaxUdpEC = switch_core_session_strdup(session, t38_options->T38FaxUdpEC);
+ local_t38_options->T38VendorInfo = switch_core_session_strdup(session, t38_options->T38VendorInfo);
+ local_t38_options->remote_ip = switch_core_session_strdup(session, t38_options->remote_ip);
+ local_t38_options->remote_port = t38_options->remote_port;
+
+
+ switch_channel_set_private(channel, "t38_options", local_t38_options);
- return match;
}
/* map sip responses to QSIG cause codes ala RFC4497 section 8.4.4 */
--- /dev/null
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthm@freeswitch.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II <anthm@freeswitch.org>
+ *
+ *
+ * sofia_media.c -- SOFIA SIP Endpoint (sofia media code)
+ *
+ */
+#include "mod_sofia.h"
+
+
+switch_status_t sofia_glue_get_offered_pt(private_object_t *tech_pvt, const switch_codec_implementation_t *mimp, switch_payload_t *pt)
+{
+ int i = 0;
+
+ for (i = 0; i < tech_pvt->num_codecs; i++) {
+ const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+
+ if (!strcasecmp(imp->iananame, mimp->iananame)) {
+ *pt = tech_pvt->ianacodes[i];
+
+ return SWITCH_STATUS_SUCCESS;
+ }
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
+
+void sofia_glue_tech_absorb_sdp(private_object_t *tech_pvt)
+{
+ const char *sdp_str;
+
+ if ((sdp_str = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE))) {
+ sdp_parser_t *parser;
+ sdp_session_t *sdp;
+ sdp_media_t *m;
+ sdp_connection_t *connection;
+
+ if ((parser = sdp_parse(NULL, sdp_str, (int) strlen(sdp_str), 0))) {
+ if ((sdp = sdp_session(parser))) {
+ for (m = sdp->sdp_media; m; m = m->m_next) {
+ if (m->m_type != sdp_media_audio || !m->m_port) {
+ continue;
+ }
+
+ connection = sdp->sdp_connection;
+ if (m->m_connections) {
+ connection = m->m_connections;
+ }
+
+ if (connection) {
+ tech_pvt->proxy_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, connection->c_address);
+ }
+ tech_pvt->proxy_sdp_audio_port = (switch_port_t) m->m_port;
+ if (tech_pvt->proxy_sdp_audio_ip && tech_pvt->proxy_sdp_audio_port) {
+ break;
+ }
+ }
+ }
+ sdp_parser_free(parser);
+ }
+ sofia_glue_tech_set_local_sdp(tech_pvt, sdp_str, SWITCH_TRUE);
+ }
+}
+
+
+
+switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, switch_event_t **pt)
+{
+ sdp_media_t *m;
+ sdp_parser_t *parser = NULL;
+ sdp_session_t *sdp;
+
+ if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!(sdp = sdp_session(parser))) {
+ sdp_parser_free(parser);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_event_create(&(*fmtp), SWITCH_EVENT_REQUEST_PARAMS);
+ switch_event_create(&(*pt), SWITCH_EVENT_REQUEST_PARAMS);
+
+ for (m = sdp->sdp_media; m; m = m->m_next) {
+ if (m->m_proto == sdp_proto_rtp) {
+ sdp_rtpmap_t *map;
+
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+ if (map->rm_encoding) {
+ char buf[25] = "";
+ char key[128] = "";
+ char *br = NULL;
+
+ if (map->rm_fmtp) {
+ if ((br = strstr(map->rm_fmtp, "bitrate="))) {
+ br += 8;
+ }
+ }
+
+ switch_snprintf(buf, sizeof(buf), "%d", map->rm_pt);
+
+ if (br) {
+ switch_snprintf(key, sizeof(key), "%s:%s", map->rm_encoding, br);
+ } else {
+ switch_snprintf(key, sizeof(key), "%s", map->rm_encoding);
+ }
+
+ switch_event_add_header_string(*pt, SWITCH_STACK_BOTTOM, key, buf);
+
+ if (map->rm_fmtp) {
+ switch_event_add_header_string(*fmtp, SWITCH_STACK_BOTTOM, key, map->rm_fmtp);
+ }
+ }
+ }
+ }
+ }
+
+ sdp_parser_free(parser);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+
+void sofia_glue_proxy_codec(switch_core_session_t *session, const char *r_sdp)
+{
+ sdp_media_t *m;
+ sdp_parser_t *parser = NULL;
+ sdp_session_t *sdp;
+ private_object_t *tech_pvt = switch_core_session_get_private(session);
+ sdp_attribute_t *attr;
+ int ptime = 0, dptime = 0;
+
+ if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
+ return;
+ }
+
+ if (!(sdp = sdp_session(parser))) {
+ sdp_parser_free(parser);
+ return;
+ }
+
+ switch_assert(tech_pvt != NULL);
+
+
+ for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
+ if (zstr(attr->a_name)) {
+ continue;
+ }
+
+ if (!strcasecmp(attr->a_name, "ptime")) {
+ dptime = atoi(attr->a_value);
+ }
+ }
+
+
+ for (m = sdp->sdp_media; m; m = m->m_next) {
+
+ ptime = dptime;
+ //maxptime = dmaxptime;
+
+ if (m->m_proto == sdp_proto_rtp) {
+ sdp_rtpmap_t *map;
+ for (attr = m->m_attributes; attr; attr = attr->a_next) {
+ if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
+ ptime = atoi(attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
+ //maxptime = atoi(attr->a_value);
+ }
+ }
+
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+ tech_pvt->iananame = switch_core_session_strdup(tech_pvt->session, map->rm_encoding);
+ tech_pvt->rm_rate = map->rm_rate;
+ tech_pvt->codec_ms = ptime;
+ sofia_glue_tech_set_codec(tech_pvt, 0);
+ break;
+ }
+
+ break;
+ }
+ }
+
+ sdp_parser_free(parser);
+
+}
+
+switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_session_t *sdp, sdp_media_t *m)
+{
+ switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
+ sdp_attribute_t *attr;
+
+ if (!t38_options) {
+ t38_options = switch_core_session_alloc(tech_pvt->session, sizeof(switch_t38_options_t));
+
+ // set some default value
+ t38_options->T38FaxVersion = 0;
+ t38_options->T38MaxBitRate = 14400;
+ t38_options->T38FaxRateManagement = switch_core_session_strdup(tech_pvt->session, "transferredTCF");
+ t38_options->T38FaxUdpEC = switch_core_session_strdup(tech_pvt->session, "t38UDPRedundancy");
+ t38_options->T38FaxMaxBuffer = 500;
+ t38_options->T38FaxMaxDatagram = 500;
+ }
+
+ t38_options->remote_port = (switch_port_t)m->m_port;
+
+ if (sdp->sdp_origin) {
+ t38_options->sdp_o_line = switch_core_session_strdup(tech_pvt->session, sdp->sdp_origin->o_username);
+ } else {
+ t38_options->sdp_o_line = "unknown";
+ }
+
+ if (m->m_connections && m->m_connections->c_address) {
+ t38_options->remote_ip = switch_core_session_strdup(tech_pvt->session, m->m_connections->c_address);
+ } else if (sdp && sdp->sdp_connection && sdp->sdp_connection->c_address) {
+ t38_options->remote_ip = switch_core_session_strdup(tech_pvt->session, sdp->sdp_connection->c_address);
+ }
+
+ for (attr = m->m_attributes; attr; attr = attr->a_next) {
+ if (!strcasecmp(attr->a_name, "T38FaxVersion") && attr->a_value) {
+ t38_options->T38FaxVersion = (uint16_t) atoi(attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "T38MaxBitRate") && attr->a_value) {
+ t38_options->T38MaxBitRate = (uint32_t) atoi(attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "T38FaxFillBitRemoval")) {
+ t38_options->T38FaxFillBitRemoval = switch_safe_atoi(attr->a_value, 1);
+ } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingMMR")) {
+ t38_options->T38FaxTranscodingMMR = switch_safe_atoi(attr->a_value, 1);
+ } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingJBIG")) {
+ t38_options->T38FaxTranscodingJBIG = switch_safe_atoi(attr->a_value, 1);
+ } else if (!strcasecmp(attr->a_name, "T38FaxRateManagement") && attr->a_value) {
+ t38_options->T38FaxRateManagement = switch_core_session_strdup(tech_pvt->session, attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "T38FaxMaxBuffer") && attr->a_value) {
+ t38_options->T38FaxMaxBuffer = (uint32_t) atoi(attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "T38FaxMaxDatagram") && attr->a_value) {
+ t38_options->T38FaxMaxDatagram = (uint32_t) atoi(attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "T38FaxUdpEC") && attr->a_value) {
+ t38_options->T38FaxUdpEC = switch_core_session_strdup(tech_pvt->session, attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "T38VendorInfo") && attr->a_value) {
+ t38_options->T38VendorInfo = switch_core_session_strdup(tech_pvt->session, attr->a_value);
+ }
+ }
+
+ switch_channel_set_variable(tech_pvt->channel, "has_t38", "true");
+ switch_channel_set_private(tech_pvt->channel, "t38_options", t38_options);
+ switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
+
+ switch_channel_execute_on(tech_pvt->channel, "sip_execute_on_image");
+ switch_channel_api_on(tech_pvt->channel, "sip_api_on_image");
+
+ return t38_options;
+}
+
+
+
+
+switch_t38_options_t *sofia_glue_extract_t38_options(switch_core_session_t *session, const char *r_sdp)
+{
+ sdp_media_t *m;
+ sdp_parser_t *parser = NULL;
+ sdp_session_t *sdp;
+ private_object_t *tech_pvt = switch_core_session_get_private(session);
+ switch_t38_options_t *t38_options = NULL;
+
+ if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
+ return 0;
+ }
+
+ if (!(sdp = sdp_session(parser))) {
+ sdp_parser_free(parser);
+ return 0;
+ }
+
+ switch_assert(tech_pvt != NULL);
+
+ for (m = sdp->sdp_media; m; m = m->m_next) {
+ if (m->m_proto == sdp_proto_udptl && m->m_type == sdp_media_image && m->m_port) {
+ t38_options = tech_process_udptl(tech_pvt, sdp, m);
+ break;
+ }
+ }
+
+ sdp_parser_free(parser);
+
+ return t38_options;
+
+}
+
+switch_status_t sofia_glue_add_crypto(private_object_t *tech_pvt, const char *key_str, switch_rtp_crypto_direction_t direction)
+{
+ unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
+ switch_rtp_crypto_key_type_t type;
+ char *p;
+
+
+ if (!switch_rtp_ready(tech_pvt->rtp_session)) {
+ goto bad;
+ }
+
+ p = strchr(key_str, ' ');
+
+ if (p && *p && *(p + 1)) {
+ p++;
+ if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_32, strlen(SWITCH_RTP_CRYPTO_KEY_32))) {
+ type = AES_CM_128_HMAC_SHA1_32;
+ } else if (!strncasecmp(p, SWITCH_RTP_CRYPTO_KEY_80, strlen(SWITCH_RTP_CRYPTO_KEY_80))) {
+ type = AES_CM_128_HMAC_SHA1_80;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
+ goto bad;
+ }
+
+ p = strchr(p, ' ');
+ if (p && *p && *(p + 1)) {
+ p++;
+ if (strncasecmp(p, "inline:", 7)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
+ goto bad;
+ }
+
+ p += 7;
+ switch_b64_decode(p, (char *) key, sizeof(key));
+
+ if (direction == SWITCH_RTP_CRYPTO_SEND) {
+ tech_pvt->crypto_send_type = type;
+ memcpy(tech_pvt->local_raw_key, key, SWITCH_RTP_KEY_LEN);
+ } else {
+ tech_pvt->crypto_recv_type = type;
+ memcpy(tech_pvt->remote_raw_key, key, SWITCH_RTP_KEY_LEN);
+ }
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ }
+
+ bad:
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Error!\n");
+ return SWITCH_STATUS_FALSE;
+
+}
+
+
+
+uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_sdp)
+{
+ uint8_t match = 0;
+ switch_payload_t best_te = 0, te = 0, cng_pt = 0;
+ private_object_t *tech_pvt = switch_core_session_get_private(session);
+ sdp_media_t *m;
+ sdp_attribute_t *attr;
+ int first = 0, last = 0;
+ int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
+ int sendonly = 0, recvonly = 0;
+ int greedy = 0, x = 0, skip = 0, mine = 0;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *val;
+ const char *crypto = NULL;
+ int got_crypto = 0, got_audio = 0, got_avp = 0, got_savp = 0, got_udptl = 0;
+ int scrooge = 0;
+ sdp_parser_t *parser = NULL;
+ sdp_session_t *sdp;
+ int reneg = 1;
+ const switch_codec_implementation_t **codec_array;
+ int total_codecs;
+
+
+ codec_array = tech_pvt->codecs;
+ total_codecs = tech_pvt->num_codecs;
+
+
+ if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
+ return 0;
+ }
+
+ if (!(sdp = sdp_session(parser))) {
+ sdp_parser_free(parser);
+ return 0;
+ }
+
+ switch_assert(tech_pvt != NULL);
+
+ greedy = !!sofia_test_pflag(tech_pvt->profile, PFLAG_GREEDY);
+ scrooge = !!sofia_test_pflag(tech_pvt->profile, PFLAG_SCROOGE);
+
+ if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation"))) {
+ if (!strcasecmp(val, "generous")) {
+ greedy = 0;
+ scrooge = 0;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : generous\n" );
+ } else if (!strcasecmp(val, "greedy")) {
+ greedy = 1;
+ scrooge = 0;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : greedy\n" );
+ } else if (!strcasecmp(val, "scrooge")) {
+ scrooge = 1;
+ greedy = 1;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation overriding sofia inbound-codec-negotiation : scrooge\n" );
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sip_codec_negotiation ignored invalid value : '%s' \n", val );
+ }
+ }
+
+ if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
+
+ if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833) {
+
+ if (strstr(tech_pvt->origin, "CiscoSystemsSIP-GW-UserAgent")) {
+ tech_pvt->rtp_bugs |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
+ }
+ }
+
+ if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833) {
+ if (strstr(tech_pvt->origin, "Sonus_UAC")) {
+ tech_pvt->rtp_bugs |= RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
+ "Hello,\nI see you have a Sonus!\n"
+ "FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n"
+ "Sadly, my creator had to spend several hours figuring this out so I thought you'd like to know that!\n"
+ "Don't worry, DTMF will work but you may want to ask them to fix it......\n");
+ }
+ }
+ }
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_liberal_dtmf")) && switch_true(val)) {
+ sofia_set_flag_locked(tech_pvt, TFLAG_LIBERAL_DTMF);
+ }
+
+ if ((m = sdp->sdp_media) &&
+ (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive ||
+ (m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")))) {
+ sendonly = 2; /* global sendonly always wins */
+ }
+
+ for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
+ if (zstr(attr->a_name)) {
+ continue;
+ }
+
+ if (!strcasecmp(attr->a_name, "sendonly")) {
+ sendonly = 1;
+ switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "recvonly");
+ } else if (!strcasecmp(attr->a_name, "inactive")) {
+ sendonly = 1;
+ switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "inactive");
+ } else if (!strcasecmp(attr->a_name, "recvonly")) {
+ switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", "sendonly");
+ recvonly = 1;
+
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, 0);
+ tech_pvt->max_missed_hold_packets = 0;
+ tech_pvt->max_missed_packets = 0;
+ } else {
+ switch_channel_set_variable(tech_pvt->channel, "rtp_timeout_sec", "0");
+ switch_channel_set_variable(tech_pvt->channel, "rtp_hold_timeout_sec", "0");
+ }
+ } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) {
+ sendonly = 0;
+ } else if (!strcasecmp(attr->a_name, "ptime")) {
+ dptime = atoi(attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "maxptime")) {
+ dmaxptime = atoi(attr->a_value);
+ }
+ }
+
+ if (sendonly != 1 && recvonly != 1) {
+ switch_channel_set_variable(tech_pvt->channel, "media_audio_mode", NULL);
+ }
+
+
+ if (sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_HOLD) ||
+ ((val = switch_channel_get_variable(tech_pvt->channel, "sip_disable_hold")) && switch_true(val))) {
+ sendonly = 0;
+ } else {
+
+ if (!tech_pvt->hold_laps) {
+ tech_pvt->hold_laps++;
+ if (sofia_glue_toggle_hold(tech_pvt, sendonly)) {
+ reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_HOLD);
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_hold"))) {
+ reneg = switch_true(val);
+ }
+ }
+
+ }
+ }
+
+ if (reneg) {
+ reneg = sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE);
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_renegotiate_codec_on_reinvite"))) {
+ reneg = switch_true(val);
+ }
+ }
+
+ if (!reneg && tech_pvt->num_negotiated_codecs) {
+ codec_array = tech_pvt->negotiated_codecs;
+ total_codecs = tech_pvt->num_negotiated_codecs;
+ } else if (reneg) {
+ tech_pvt->num_codecs = 0;
+ sofia_glue_tech_prepare_codecs(tech_pvt);
+ codec_array = tech_pvt->codecs;
+ total_codecs = tech_pvt->num_codecs;
+ }
+
+ if (switch_stristr("T38FaxFillBitRemoval:", r_sdp) || switch_stristr("T38FaxTranscodingMMR:", r_sdp) ||
+ switch_stristr("T38FaxTranscodingJBIG:", r_sdp)) {
+ 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;
+
+ ptime = dptime;
+ maxptime = dmaxptime;
+
+ if (m->m_proto == sdp_proto_srtp) {
+ got_savp++;
+ } else if (m->m_proto == sdp_proto_rtp) {
+ got_avp++;
+ } else if (m->m_proto == sdp_proto_udptl) {
+ got_udptl++;
+ }
+
+ if (got_udptl && m->m_type == sdp_media_image && m->m_port) {
+ switch_t38_options_t *t38_options = tech_process_udptl(tech_pvt, sdp, m);
+
+ if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_NEGOTIATED)) {
+ match = 1;
+ goto done;
+ }
+
+ if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) {
+ switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
+ match = 0;
+ goto done;
+ } else {
+ const char *var = switch_channel_get_variable(channel, "t38_passthru");
+ int pass = sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU);
+
+
+ if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) {
+ sofia_set_flag(tech_pvt, TFLAG_NOREPLY);
+ }
+
+ if (var) {
+ if (!(pass = switch_true(var))) {
+ if (!strcasecmp(var, "once")) {
+ pass = 2;
+ }
+ }
+ }
+
+ if ((pass == 2 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU)) ||
+ !sofia_test_flag(tech_pvt, TFLAG_REINVITE) ||
+ switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
+ switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) ||
+ !switch_rtp_ready(tech_pvt->rtp_session)) {
+ pass = 0;
+ }
+
+ if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
+ private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
+ switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
+ switch_core_session_message_t *msg;
+ char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
+ switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
+ char tmp[32] = "";
+
+ if (switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean")) &&
+ switch_true(switch_channel_get_variable(tech_pvt->channel, "t38_pass_broken_boolean"))) {
+ switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
+ }
+
+ tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(tech_pvt->session, t38_options->remote_ip);
+ tech_pvt->remote_sdp_audio_port = t38_options->remote_port;
+
+ if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
+ switch_channel_get_name(tech_pvt->channel));
+ } else {
+ const char *err = NULL;
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
+ switch_channel_get_name(tech_pvt->channel),
+ remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
+
+ if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip,
+ tech_pvt->remote_sdp_audio_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
+ switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
+ }
+
+ }
+
+
+
+ sofia_glue_copy_t38_options(t38_options, other_session);
+
+ sofia_set_flag(tech_pvt, TFLAG_T38_PASSTHRU);
+ sofia_set_flag(other_tech_pvt, TFLAG_T38_PASSTHRU);
+
+ msg = switch_core_session_alloc(other_session, sizeof(*msg));
+ msg->message_id = SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA;
+ msg->from = __FILE__;
+ msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp);
+ switch_core_session_queue_message(other_session, msg);
+ switch_core_session_rwunlock(other_session);
+ }
+ }
+
+
+ /* do nothing here, mod_fax will trigger a response (if it's listening =/) */
+ match = 1;
+ goto done;
+ } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
+ sdp_rtpmap_t *map;
+
+ for (attr = m->m_attributes; attr; attr = attr->a_next) {
+
+ if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
+ switch_channel_set_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port", attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
+ ptime = atoi(attr->a_value);
+ } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
+ maxptime = atoi(attr->a_value);
+ } else if (!got_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
+ int crypto_tag;
+
+ if (!(tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_CRYPTO_IN_AVP) &&
+ !switch_true(switch_channel_get_variable(tech_pvt->channel, "sip_allow_crypto_in_avp"))) {
+ if (m->m_proto != sdp_proto_srtp) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
+ match = 0;
+ goto done;
+ }
+ }
+
+ crypto = attr->a_value;
+ crypto_tag = atoi(crypto);
+
+ if (tech_pvt->remote_crypto_key && switch_rtp_ready(tech_pvt->rtp_session)) {
+ /* Compare all the key. The tag may remain the same even if key changed */
+ if (crypto && !strcmp(crypto, tech_pvt->remote_crypto_key)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
+ } else {
+ const char *a = switch_stristr("AES", tech_pvt->remote_crypto_key);
+ const char *b = switch_stristr("AES", crypto);
+
+ /* Change our key every time we can */
+
+ if (sofia_test_flag(tech_pvt, TFLAG_CRYPTO_RECOVER)) {
+ sofia_clear_flag(tech_pvt, TFLAG_CRYPTO_RECOVER);
+ } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
+ switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_32);
+ sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
+ switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), tech_pvt->crypto_type,
+ tech_pvt->local_raw_key, SWITCH_RTP_KEY_LEN);
+ } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
+ switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_80);
+ sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_80, SWITCH_RTP_CRYPTO_SEND);
+ switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), tech_pvt->crypto_type,
+ tech_pvt->local_raw_key, SWITCH_RTP_KEY_LEN);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto Setup Failed!.\n");
+ }
+
+ if (a && b && !strncasecmp(a, b, 23)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
+ tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
+ switch_channel_set_variable(tech_pvt->channel, "srtp_remote_audio_crypto_key", crypto);
+ tech_pvt->crypto_tag = crypto_tag;
+
+ if (switch_rtp_ready(tech_pvt->rtp_session) && sofia_test_flag(tech_pvt, TFLAG_SECURE)) {
+ sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
+ switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag,
+ tech_pvt->crypto_type, tech_pvt->remote_raw_key, SWITCH_RTP_KEY_LEN);
+ }
+ got_crypto++;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n");
+ }
+ }
+ } else if (!switch_rtp_ready(tech_pvt->rtp_session)) {
+ tech_pvt->remote_crypto_key = switch_core_session_strdup(tech_pvt->session, crypto);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", tech_pvt->remote_crypto_key);
+ switch_channel_set_variable(tech_pvt->channel, "srtp_remote_audio_crypto_key", crypto);
+ tech_pvt->crypto_tag = crypto_tag;
+ got_crypto++;
+
+ if (zstr(tech_pvt->local_crypto_key)) {
+ if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_32, crypto)) {
+ switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_32);
+ sofia_glue_build_crypto(tech_pvt, atoi(crypto), AES_CM_128_HMAC_SHA1_32, SWITCH_RTP_CRYPTO_SEND);
+ } else if (switch_stristr(SWITCH_RTP_CRYPTO_KEY_80, crypto)) {
+ switch_channel_set_variable(tech_pvt->channel, SOFIA_HAS_CRYPTO_VARIABLE, SWITCH_RTP_CRYPTO_KEY_80);
+ sofia_glue_build_crypto(tech_pvt, atoi(crypto), 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");
+ }
+ }
+ }
+ }
+ }
+
+ if (got_crypto && !got_avp) {
+ switch_channel_set_variable(tech_pvt->channel, SOFIA_CRYPTO_MANDATORY_VARIABLE, "true");
+ switch_channel_set_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE, "true");
+ }
+
+ connection = sdp->sdp_connection;
+ if (m->m_connections) {
+ connection = m->m_connections;
+ }
+
+ if (!connection) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
+ match = 0;
+ break;
+ }
+
+ greed:
+ x = 0;
+
+ if (tech_pvt->rm_encoding && !(sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))) { // && !sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
+ char *remote_host = tech_pvt->remote_sdp_audio_ip;
+ switch_port_t remote_port = tech_pvt->remote_sdp_audio_port;
+ int same = 0;
+
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
+ remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
+ }
+
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+ if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
+ match = (map->rm_pt == tech_pvt->pt) ? 1 : 0;
+ } else {
+ match = strcasecmp(switch_str_nil(map->rm_encoding), tech_pvt->iananame) ? 0 : 1;
+ }
+
+ if (match && connection->c_address && remote_host && !strcmp(connection->c_address, remote_host) && m->m_port == remote_port) {
+ same = 1;
+ } else {
+ same = 0;
+ break;
+ }
+ }
+
+ if (same) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "Our existing sdp is still good [%s %s:%d], let's keep it.\n",
+ tech_pvt->rm_encoding, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
+ got_audio = 1;
+ } else {
+ match = 0;
+ got_audio = 0;
+ }
+ }
+
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+ int32_t i;
+ uint32_t near_rate = 0;
+ const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
+ const char *rm_encoding;
+ uint32_t map_bit_rate = 0;
+ int codec_ms = 0;
+ switch_codec_fmtp_t codec_fmtp = { 0 };
+
+ if (x++ < skip) {
+ continue;
+ }
+
+ if (!(rm_encoding = map->rm_encoding)) {
+ rm_encoding = "";
+ }
+
+ if (!strcasecmp(rm_encoding, "telephone-event")) {
+ if (!best_te || map->rm_rate == tech_pvt->rm_rate) {
+ best_te = (switch_payload_t) map->rm_pt;
+ }
+ }
+
+ if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && !cng_pt && !strcasecmp(rm_encoding, "CN")) {
+ cng_pt = (switch_payload_t) map->rm_pt;
+ if (tech_pvt->rtp_session) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt);
+ switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt);
+ }
+ }
+
+ if (match) {
+ continue;
+ }
+
+ if (greedy) {
+ first = mine;
+ last = first + 1;
+ } else {
+ first = 0;
+ last = tech_pvt->num_codecs;
+ }
+
+ codec_ms = ptime;
+
+ if (maxptime && (!codec_ms || codec_ms > maxptime)) {
+ codec_ms = maxptime;
+ }
+
+ if (!codec_ms) {
+ codec_ms = switch_default_ptime(rm_encoding, map->rm_pt);
+ }
+
+ map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
+
+ if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
+ codec_ms = 30;
+ }
+
+ if (zstr(map->rm_fmtp)) {
+ if (!strcasecmp(map->rm_encoding, "ilbc")) {
+ codec_ms = 30;
+ map_bit_rate = 13330;
+ }
+ } else {
+ if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
+ if (codec_fmtp.bits_per_second) {
+ map_bit_rate = codec_fmtp.bits_per_second;
+ }
+ if (codec_fmtp.microseconds_per_packet) {
+ codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
+ }
+ }
+ }
+
+
+ for (i = first; i < last && i < total_codecs; i++) {
+ const switch_codec_implementation_t *imp = codec_array[i];
+ uint32_t bit_rate = imp->bits_per_second;
+ uint32_t codec_rate = imp->samples_per_second;
+ if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+ continue;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n",
+ rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate,
+ imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate);
+ if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
+ match = (map->rm_pt == imp->ianacode) ? 1 : 0;
+ } else {
+ match = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
+ }
+
+ if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc")) {
+ /* if a bit rate is specified and doesn't match, this is not a codec match, except for ILBC */
+ match = 0;
+ }
+
+ if (match && map->rm_rate && codec_rate && map->rm_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") || !strcasecmp(map->rm_encoding, "pcmu"))) {
+ /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n");
+ match = 0;
+ }
+
+ if (match) {
+ if (scrooge) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "Bah HUMBUG! Sticking with %s@%uh@%ui\n",
+ imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
+ } else {
+ if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate) {
+ near_rate = map->rm_rate;
+ near_match = imp;
+ match = 0;
+ continue;
+ }
+ }
+ mimp = imp;
+ break;
+ }
+ }
+
+ if (!match && near_match) {
+ const switch_codec_implementation_t *search[1];
+ char *prefs[1];
+ char tmp[80];
+ int num;
+
+ switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second,
+ codec_ms);
+
+ prefs[0] = tmp;
+ num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1);
+
+ if (num) {
+ mimp = search[0];
+ } else {
+ mimp = near_match;
+ }
+
+ if (!maxptime || mimp->microseconds_per_packet / 1000 <= maxptime) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh\n",
+ mimp->iananame, mimp->microseconds_per_packet / 1000, mimp->samples_per_second);
+ match = 1;
+ } else {
+ mimp = NULL;
+ match = 0;
+ }
+
+ }
+
+ if (!match && greedy) {
+ skip++;
+ continue;
+ }
+
+ if (mimp) {
+ char tmp[50];
+ const char *mirror = switch_channel_get_variable(tech_pvt->channel, "sip_mirror_remote_audio_codec_payload");
+
+ tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding);
+ tech_pvt->iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
+ tech_pvt->pt = (switch_payload_t) map->rm_pt;
+ tech_pvt->rm_rate = mimp->samples_per_second;
+ tech_pvt->codec_ms = mimp->microseconds_per_packet / 1000;
+ tech_pvt->bitrate = mimp->bits_per_second;
+ tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(session, (char *) connection->c_address);
+ tech_pvt->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
+ tech_pvt->remote_sdp_audio_port = (switch_port_t) m->m_port;
+ tech_pvt->agreed_pt = (switch_payload_t) map->rm_pt;
+ tech_pvt->num_negotiated_codecs = 0;
+ tech_pvt->negotiated_codecs[tech_pvt->num_negotiated_codecs++] = mimp;
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
+ tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt;
+
+ if (!switch_true(mirror) &&
+ switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
+ (!sofia_test_flag(tech_pvt, TFLAG_REINVITE) || sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE))) {
+ sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->audio_recv_pt);
+ }
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->audio_recv_pt);
+ switch_channel_set_variable(tech_pvt->channel, "sip_audio_recv_pt", tmp);
+
+ }
+
+ if (match) {
+ if (sofia_glue_tech_set_codec(tech_pvt, 1) == SWITCH_STATUS_SUCCESS) {
+ got_audio = 1;
+ } else {
+ match = 0;
+ }
+ }
+ }
+
+ if (!best_te && (sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "No 2833 in SDP. Liberal DTMF mode adding %d as telephone-event.\n", tech_pvt->profile->te);
+ best_te = tech_pvt->profile->te;
+ }
+
+ if (best_te) {
+ if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+ te = tech_pvt->te = (switch_payload_t) best_te;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", best_te);
+ if (tech_pvt->rtp_session) {
+ switch_rtp_set_telephony_event(tech_pvt->rtp_session, (switch_payload_t) best_te);
+ switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", best_te);
+ }
+ } else {
+ te = tech_pvt->recv_te = tech_pvt->te = (switch_payload_t) best_te;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send/recv payload to %u\n", te);
+ if (tech_pvt->rtp_session) {
+ switch_rtp_set_telephony_event(tech_pvt->rtp_session, te);
+ switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", te);
+ switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, te);
+ switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", te);
+ }
+ }
+ } else {
+ /* by default, use SIP INFO if 2833 is not in the SDP */
+ if (!switch_false(switch_channel_get_variable(channel, "sip_info_when_no_2833"))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No 2833 in SDP. Disable 2833 dtmf and switch to INFO\n");
+ switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "info");
+ tech_pvt->dtmf_type = DTMF_INFO;
+ te = tech_pvt->recv_te = tech_pvt->te = 0;
+ } else {
+ switch_channel_set_variable(tech_pvt->channel, "dtmf_type", "none");
+ tech_pvt->dtmf_type = DTMF_NONE;
+ te = tech_pvt->recv_te = tech_pvt->te = 0;
+ }
+ }
+
+
+ if (!match && greedy && mine < total_codecs) {
+ mine++;
+ skip = 0;
+ goto greed;
+ }
+
+ } else if (m->m_type == sdp_media_video && m->m_port) {
+ sdp_rtpmap_t *map;
+ const char *rm_encoding;
+ const switch_codec_implementation_t *mimp = NULL;
+ int vmatch = 0, i;
+ switch_channel_set_variable(tech_pvt->channel, "video_possible", "true");
+
+ connection = sdp->sdp_connection;
+ if (m->m_connections) {
+ connection = m->m_connections;
+ }
+
+ if (!connection) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
+ match = 0;
+ break;
+ }
+
+ for (map = m->m_rtpmaps; map; map = map->rm_next) {
+
+ for (attr = m->m_attributes; attr; attr = attr->a_next) {
+ if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
+ //framerate = atoi(attr->a_value);
+ }
+ if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
+ switch_channel_set_variable(tech_pvt->channel, "sip_remote_video_rtcp_port", attr->a_value);
+ }
+ }
+ if (!(rm_encoding = map->rm_encoding)) {
+ rm_encoding = "";
+ }
+
+ for (i = 0; i < total_codecs; i++) {
+ const switch_codec_implementation_t *imp = codec_array[i];
+
+ if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
+ continue;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n",
+ rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
+ if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
+ vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0;
+ } else {
+ vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
+ }
+
+
+ if (vmatch && (map->rm_rate == imp->samples_per_second)) {
+ mimp = imp;
+ break;
+ } else {
+ vmatch = 0;
+ }
+ }
+
+ if (mimp) {
+ if ((tech_pvt->video_rm_encoding = switch_core_session_strdup(session, (char *) rm_encoding))) {
+ char tmp[50];
+ const char *mirror = switch_channel_get_variable(tech_pvt->channel, "sip_mirror_remote_video_codec_payload");
+
+ tech_pvt->video_pt = (switch_payload_t) map->rm_pt;
+ tech_pvt->video_rm_rate = map->rm_rate;
+ tech_pvt->video_codec_ms = mimp->microseconds_per_packet / 1000;
+ tech_pvt->remote_sdp_video_ip = switch_core_session_strdup(session, (char *) connection->c_address);
+ tech_pvt->video_rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
+ tech_pvt->remote_sdp_video_port = (switch_port_t) m->m_port;
+ tech_pvt->video_agreed_pt = (switch_payload_t) map->rm_pt;
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_video_port);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_VIDEO_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_VIDEO_PORT_VARIABLE, tmp);
+ switch_channel_set_variable(tech_pvt->channel, "sip_video_fmtp", tech_pvt->video_rm_fmtp);
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_agreed_pt);
+ switch_channel_set_variable(tech_pvt->channel, "sip_video_pt", tmp);
+ sofia_glue_check_video_codecs(tech_pvt);
+
+ tech_pvt->video_recv_pt = (switch_payload_t)map->rm_pt;
+
+ if (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+ sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->video_recv_pt);
+ }
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->video_recv_pt);
+ switch_channel_set_variable(tech_pvt->channel, "sip_video_recv_pt", tmp);
+ if (!match && vmatch) match = 1;
+
+ break;
+ } else {
+ vmatch = 0;
+ }
+ }
+ }
+ }
+ }
+
+ done:
+
+ if (parser) {
+ sdp_parser_free(parser);
+ }
+
+ tech_pvt->cng_pt = cng_pt;
+ sofia_set_flag_locked(tech_pvt, TFLAG_SDP);
+
+ return match;
+}
+
+
+switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_flag_t myflags)
+{
+ const char *err = NULL;
+ const char *val = NULL;
+ switch_rtp_flag_t flags;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char tmp[50];
+ uint32_t rtp_timeout_sec = tech_pvt->profile->rtp_timeout_sec;
+ uint32_t rtp_hold_timeout_sec = tech_pvt->profile->rtp_hold_timeout_sec;
+ char *timer_name = NULL;
+ const char *var;
+ uint32_t delay = tech_pvt->profile->rtp_digit_delay;
+
+ switch_assert(tech_pvt != NULL);
+
+ if (switch_channel_down(tech_pvt->channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_mutex_lock(tech_pvt->sofia_mutex);
+
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_reset_media_timer(tech_pvt->rtp_session);
+ }
+
+ if ((var = switch_channel_get_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_VARIABLE)) && switch_true(var)) {
+ sofia_set_flag_locked(tech_pvt, TFLAG_SECURE);
+ }
+
+ if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
+ status = SWITCH_STATUS_SUCCESS;
+ goto end;
+ }
+
+
+ if (!sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ if (sofia_test_flag(tech_pvt, TFLAG_VIDEO) && !switch_rtp_ready(tech_pvt->video_rtp_session)) {
+ goto video;
+ }
+
+ status = SWITCH_STATUS_SUCCESS;
+ goto end;
+ }
+ }
+
+ if ((status = sofia_glue_tech_set_codec(tech_pvt, 0)) != SWITCH_STATUS_SUCCESS) {
+ goto end;
+ }
+
+
+ if (myflags) {
+ flags = myflags;
+ } else if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+ !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT);
+ } else {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT);
+ }
+
+ if (sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_RFC2833)
+ || ((val = switch_channel_get_variable(tech_pvt->channel, "pass_rfc2833")) && switch_true(val))) {
+ sofia_set_flag(tech_pvt, TFLAG_PASS_RFC2833);
+ }
+
+
+ if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFLUSH)
+ || ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_autoflush")) && switch_true(val))) {
+ flags |= SWITCH_RTP_FLAG_AUTOFLUSH;
+ }
+
+ if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_REWRITE_TIMESTAMPS) ||
+ ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) {
+ flags |= SWITCH_RTP_FLAG_RAW_WRITE;
+ }
+
+ if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG)) {
+ tech_pvt->cng_pt = 0;
+ } else if (tech_pvt->cng_pt) {
+ flags |= SWITCH_RTP_FLAG_AUTO_CNG;
+ }
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ if (!strcasecmp(tech_pvt->read_impl.iananame, "L16")) {
+ flags |= SWITCH_RTP_FLAG_BYTESWAP;
+ }
+#endif
+
+ if ((flags & SWITCH_RTP_FLAG_BYTESWAP) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_byteswap")) && switch_true(val)) {
+ flags &= ~SWITCH_RTP_FLAG_BYTESWAP;
+ }
+
+ if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
+ //const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
+ //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
+ char *remote_host = switch_rtp_get_remote_host(tech_pvt->rtp_session);
+ switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->rtp_session);
+
+ if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_audio_ip) && remote_port == tech_pvt->remote_sdp_audio_port) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
+ switch_channel_get_name(tech_pvt->channel));
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "%s Set audio receive payload in Re-INVITE for non-matching dynamic PT to %u\n",
+ switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
+
+ switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "%s Setting audio receive payload in Re-INVITE to %u\n",
+ switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
+ switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt);
+ }
+
+ }
+ goto video;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
+ switch_channel_get_name(tech_pvt->channel),
+ remote_host, remote_port, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
+ }
+ }
+
+ if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n",
+ switch_channel_get_name(tech_pvt->channel),
+ tech_pvt->local_sdp_audio_ip,
+ tech_pvt->local_sdp_audio_port,
+ tech_pvt->remote_sdp_audio_ip,
+ tech_pvt->remote_sdp_audio_port, tech_pvt->agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
+
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->agreed_pt);
+
+ if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
+
+ switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt);
+ } else {
+ switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt);
+ }
+
+ }
+ }
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->local_sdp_audio_port);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->local_sdp_audio_ip);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip);
+
+ if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
+ const char *rport = NULL;
+ switch_port_t remote_rtcp_port = 0;
+
+
+
+ if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_rtcp_port"))) {
+ remote_rtcp_port = (switch_port_t)atoi(rport);
+ }
+
+ if (switch_rtp_set_remote_address(tech_pvt->rtp_session, tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port,
+ remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
+ tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
+ if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+ !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
+ /* Reactivate the NAT buster flag. */
+ switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
+ }
+ }
+ goto video;
+ }
+
+ if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
+ sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
+
+ if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+ !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT);
+ } else {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_DATAWAIT);
+ }
+ timer_name = NULL;
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
+ switch_channel_get_name(tech_pvt->channel),
+ tech_pvt->local_sdp_audio_ip,
+ tech_pvt->local_sdp_audio_port,
+ tech_pvt->remote_sdp_audio_ip,
+ tech_pvt->remote_sdp_audio_port, tech_pvt->agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
+
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->agreed_pt);
+ }
+
+ } else {
+ timer_name = tech_pvt->profile->timer_name;
+
+ if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) {
+ timer_name = (char *) var;
+ }
+ }
+
+ if (switch_channel_up(tech_pvt->channel) && !sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+ tech_pvt->rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
+ tech_pvt->local_sdp_audio_port,
+ tech_pvt->remote_sdp_audio_ip,
+ tech_pvt->remote_sdp_audio_port,
+ tech_pvt->agreed_pt,
+ tech_pvt->read_impl.samples_per_packet,
+ tech_pvt->codec_ms * 1000,
+ (switch_rtp_flag_t) flags, timer_name, &err, switch_core_session_get_pool(tech_pvt->session));
+ }
+
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ uint8_t vad_in = sofia_test_flag(tech_pvt, TFLAG_VAD_IN) ? 1 : 0;
+ uint8_t vad_out = sofia_test_flag(tech_pvt, TFLAG_VAD_OUT) ? 1 : 0;
+ uint8_t inb = sofia_test_flag(tech_pvt, TFLAG_OUTBOUND) ? 0 : 1;
+ uint32_t stun_ping = 0;
+ const char *ssrc;
+
+ if ((ssrc = switch_channel_get_variable(tech_pvt->channel, "rtp_use_ssrc"))) {
+ uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
+ switch_rtp_set_ssrc(tech_pvt->rtp_session, ssrc_ul);
+ }
+
+
+ switch_channel_set_flag(tech_pvt->channel, CF_FS_RTP);
+
+ switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_pt", "%d", tech_pvt->agreed_pt);
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_enable_vad_in")) && switch_true(val)) {
+ vad_in = 1;
+ }
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_enable_vad_out")) && switch_true(val)) {
+ vad_out = 1;
+ }
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_vad_in")) && switch_true(val)) {
+ vad_in = 0;
+ }
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_disable_vad_out")) && switch_true(val)) {
+ vad_out = 0;
+ }
+
+ if ((tech_pvt->stun_flags & STUN_FLAG_SET) && (val = switch_channel_get_variable(tech_pvt->channel, "rtp_stun_ping"))) {
+ int ival = atoi(val);
+
+ if (ival <= 0) {
+ if (switch_true(val)) {
+ ival = 6;
+ }
+ }
+
+ stun_ping = (ival * tech_pvt->read_impl.samples_per_second) / tech_pvt->read_impl.samples_per_packet;
+ }
+
+ tech_pvt->ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session);
+ switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_ssrc", "%u", tech_pvt->ssrc);
+
+ sofia_set_flag(tech_pvt, TFLAG_RTP);
+ sofia_set_flag(tech_pvt, TFLAG_IO);
+
+ if (tech_pvt->profile->auto_rtp_bugs & RTP_BUG_IGNORE_MARK_BIT) {
+ tech_pvt->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT;
+ }
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_manual_rtp_bugs"))) {
+ sofia_glue_parse_rtp_bugs(&tech_pvt->rtp_bugs, val);
+ }
+
+ switch_rtp_intentional_bugs(tech_pvt->rtp_session, tech_pvt->rtp_bugs | tech_pvt->profile->manual_rtp_bugs);
+
+ if ((vad_in && inb) || (vad_out && !inb)) {
+ switch_rtp_enable_vad(tech_pvt->rtp_session, tech_pvt->session, &tech_pvt->read_codec, SWITCH_VAD_FLAG_TALKING | SWITCH_VAD_FLAG_EVENTS_TALK | SWITCH_VAD_FLAG_EVENTS_NOTALK);
+ sofia_set_flag(tech_pvt, TFLAG_VAD);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n",
+ switch_channel_get_name(switch_core_session_get_channel(tech_pvt->session)), vad_in ? "in" : "", vad_out ? "out" : "");
+ }
+
+ if (stun_ping) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Setting stun ping to %s:%d\n", tech_pvt->stun_ip,
+ stun_ping);
+ switch_rtp_activate_stun_ping(tech_pvt->rtp_session, tech_pvt->stun_ip, tech_pvt->stun_port, stun_ping,
+ (tech_pvt->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0);
+ }
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec")) || (val = tech_pvt->profile->rtcp_audio_interval_msec)) {
+ const char *rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_audio_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(tech_pvt->rtp_session, -1, remote_port);
+ } else {
+ int interval = atoi(val);
+ if (interval < 100 || interval > 5000) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
+ "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval);
+ } else {
+ switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval, remote_port);
+ }
+ }
+ }
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec")) || (val = tech_pvt->profile->jb_msec)) {
+ int jb_msec = atoi(val);
+ int maxlen = 0, max_drift = 0;
+ char *p, *q;
+
+ if ((p = strchr(val, ':'))) {
+ p++;
+ maxlen = atoi(p);
+ if ((q = strchr(p, ':'))) {
+ q++;
+ max_drift = abs(atoi(q));
+ }
+ }
+
+ if (jb_msec < 20 || jb_msec > 10000) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
+ "Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", jb_msec);
+ } else {
+ int qlen, maxqlen = 50;
+
+ qlen = jb_msec / (tech_pvt->read_impl.microseconds_per_packet / 1000);
+
+ if (qlen < 1) {
+ qlen = 3;
+ }
+
+ if (maxlen) {
+ maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
+ }
+
+ if (maxqlen < qlen) {
+ maxqlen = qlen * 5;
+ }
+ if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen,
+ tech_pvt->read_impl.samples_per_packet,
+ tech_pvt->read_impl.samples_per_second, max_drift) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
+ SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
+ switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
+ if (!switch_false(switch_channel_get_variable(tech_pvt->channel, "sip_jitter_buffer_plc"))) {
+ switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER_PLC);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
+ SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
+ }
+
+ }
+ }
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_timeout_sec"))) {
+ int v = atoi(val);
+ if (v >= 0) {
+ rtp_timeout_sec = v;
+ }
+ }
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_hold_timeout_sec"))) {
+ int v = atoi(val);
+ if (v >= 0) {
+ rtp_hold_timeout_sec = v;
+ }
+ }
+
+ if (rtp_timeout_sec) {
+ tech_pvt->max_missed_packets = (tech_pvt->read_impl.samples_per_second * rtp_timeout_sec) / tech_pvt->read_impl.samples_per_packet;
+
+ switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets);
+ if (!rtp_hold_timeout_sec) {
+ rtp_hold_timeout_sec = rtp_timeout_sec * 10;
+ }
+ }
+
+ if (rtp_hold_timeout_sec) {
+ tech_pvt->max_missed_hold_packets = (tech_pvt->read_impl.samples_per_second * rtp_hold_timeout_sec) / tech_pvt->read_impl.samples_per_packet;
+ }
+
+ if (tech_pvt->te) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", tech_pvt->te);
+ switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te);
+ switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", tech_pvt->te);
+ }
+
+ if (tech_pvt->recv_te) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf receive payload to %u\n", tech_pvt->recv_te);
+ switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, tech_pvt->recv_te);
+ switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", tech_pvt->recv_te);
+ }
+
+ if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "%s Set audio receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->audio_recv_pt);
+
+ switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->audio_recv_pt);
+ }
+
+ if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) ||
+ ((val = switch_channel_get_variable(tech_pvt->channel, "supress_cng")) && switch_true(val)) ||
+ ((val = switch_channel_get_variable(tech_pvt->channel, "suppress_cng")) && switch_true(val))) {
+ tech_pvt->cng_pt = 0;
+ }
+
+ if (((val = switch_channel_get_variable(tech_pvt->channel, "rtp_digit_delay")))) {
+ int delayi = atoi(val);
+ if (delayi < 0) delayi = 0;
+ delay = (uint32_t) delayi;
+ }
+
+
+ if (delay) {
+ switch_rtp_set_interdigit_delay(tech_pvt->rtp_session, delay);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "%s Set rtp dtmf delay to %u\n", switch_channel_get_name(tech_pvt->channel), delay);
+
+ }
+
+ if (tech_pvt->cng_pt && !sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", tech_pvt->cng_pt);
+ switch_rtp_set_cng_pt(tech_pvt->rtp_session, tech_pvt->cng_pt);
+ }
+
+ if (tech_pvt->remote_crypto_key && sofia_test_flag(tech_pvt, TFLAG_SECURE)) {
+ sofia_glue_add_crypto(tech_pvt, tech_pvt->remote_crypto_key, SWITCH_RTP_CRYPTO_RECV);
+ switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_SEND, 1, tech_pvt->crypto_type, tech_pvt->local_raw_key,
+ SWITCH_RTP_KEY_LEN);
+ switch_rtp_add_crypto_key(tech_pvt->rtp_session, SWITCH_RTP_CRYPTO_RECV, tech_pvt->crypto_tag, tech_pvt->crypto_type, tech_pvt->remote_raw_key,
+ SWITCH_RTP_KEY_LEN);
+ switch_channel_set_variable(tech_pvt->channel, SOFIA_SECURE_MEDIA_CONFIRMED_VARIABLE, "true");
+ }
+
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->remote_sdp_audio_port);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, tech_pvt->remote_sdp_audio_ip);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
+
+
+ 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);
+ }
+
+
+ video:
+
+ sofia_glue_check_video_codecs(tech_pvt);
+
+ if (sofia_test_flag(tech_pvt, TFLAG_VIDEO) && tech_pvt->video_rm_encoding && tech_pvt->remote_sdp_video_port) {
+ /******************************************************************************************/
+ if (tech_pvt->video_rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
+ //const char *ip = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
+ //const char *port = switch_channel_get_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
+ char *remote_host = switch_rtp_get_remote_host(tech_pvt->video_rtp_session);
+ switch_port_t remote_port = switch_rtp_get_remote_port(tech_pvt->video_rtp_session);
+
+
+
+ if (remote_host && remote_port && !strcmp(remote_host, tech_pvt->remote_sdp_video_ip) && remote_port == tech_pvt->remote_sdp_video_port) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n",
+ switch_channel_get_name(tech_pvt->channel));
+ goto video_up;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n",
+ switch_channel_get_name(tech_pvt->channel),
+ remote_host, remote_port, tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port);
+ }
+ }
+
+ if (!switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n", switch_channel_get_name(tech_pvt->channel),
+ tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_video_port, tech_pvt->remote_sdp_video_ip,
+ tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
+
+ if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
+ switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
+ }
+ }
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->local_sdp_video_port);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip);
+ switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, tmp);
+
+
+ if (tech_pvt->video_rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) {
+ const char *rport = NULL;
+ switch_port_t remote_rtcp_port = 0;
+
+ sofia_clear_flag_locked(tech_pvt, TFLAG_REINVITE);
+
+ if ((rport = switch_channel_get_variable(tech_pvt->channel, "sip_remote_video_rtcp_port"))) {
+ remote_rtcp_port = (switch_port_t)atoi(rport);
+ }
+
+ if (switch_rtp_set_remote_address
+ (tech_pvt->video_rtp_session, tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port, remote_rtcp_port, SWITCH_TRUE,
+ &err) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
+ tech_pvt->remote_sdp_video_ip, tech_pvt->remote_sdp_video_port);
+ if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+ !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
+ /* Reactivate the NAT buster flag. */
+ switch_rtp_set_flag(tech_pvt->video_rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
+ }
+
+ }
+ goto video_up;
+ }
+
+ if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
+ sofia_glue_tech_proxy_remote_addr(tech_pvt, NULL);
+
+ if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+ !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT);
+ } else {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_PROXY_MEDIA | SWITCH_RTP_FLAG_DATAWAIT);
+ }
+ timer_name = NULL;
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
+ switch_channel_get_name(tech_pvt->channel),
+ tech_pvt->local_sdp_audio_ip,
+ tech_pvt->local_sdp_video_port,
+ tech_pvt->remote_sdp_video_ip,
+ tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt, tech_pvt->read_impl.microseconds_per_packet / 1000);
+
+ if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
+ switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
+ }
+ } else {
+ timer_name = tech_pvt->profile->timer_name;
+
+ if ((var = switch_channel_get_variable(tech_pvt->channel, "rtp_timer_name"))) {
+ timer_name = (char *) var;
+ }
+ }
+
+ /******************************************************************************************/
+
+ if (tech_pvt->video_rtp_session) {
+ goto video_up;
+ }
+
+
+ if (!tech_pvt->local_sdp_video_port) {
+ sofia_glue_tech_choose_video_port(tech_pvt, 1);
+ }
+
+ if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) && !switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
+ !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE);
+ } else {
+ flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_DATAWAIT | SWITCH_RTP_FLAG_RAW_WRITE);
+ }
+
+ if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
+ flags |= SWITCH_RTP_FLAG_PROXY_MEDIA;
+ }
+ sofia_glue_tech_set_video_codec(tech_pvt, 0);
+
+ flags &= ~(SWITCH_RTP_FLAG_USE_TIMER | SWITCH_RTP_FLAG_NOBLOCK);
+ flags |= SWITCH_RTP_FLAG_VIDEO;
+
+ tech_pvt->video_rtp_session = switch_rtp_new(tech_pvt->local_sdp_audio_ip,
+ tech_pvt->local_sdp_video_port,
+ tech_pvt->remote_sdp_video_ip,
+ tech_pvt->remote_sdp_video_port,
+ tech_pvt->video_agreed_pt,
+ 1, 90000, (switch_rtp_flag_t) flags, NULL, &err, switch_core_session_get_pool(tech_pvt->session));
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
+ switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
+ switch_channel_get_name(tech_pvt->channel),
+ tech_pvt->local_sdp_audio_ip,
+ tech_pvt->local_sdp_video_port,
+ tech_pvt->remote_sdp_video_ip,
+ tech_pvt->remote_sdp_video_port, tech_pvt->video_agreed_pt,
+ 0, switch_rtp_ready(tech_pvt->video_rtp_session) ? "SUCCESS" : err);
+
+
+ if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
+ switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
+ }
+
+ if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
+ const char *ssrc;
+ switch_channel_set_flag(tech_pvt->channel, CF_VIDEO);
+ if ((ssrc = switch_channel_get_variable(tech_pvt->channel, "rtp_use_video_ssrc"))) {
+ uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
+ switch_rtp_set_ssrc(tech_pvt->video_rtp_session, ssrc_ul);
+ }
+
+
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_manual_video_rtp_bugs"))) {
+ sofia_glue_parse_rtp_bugs(&tech_pvt->video_rtp_bugs, val);
+ }
+
+ switch_rtp_intentional_bugs(tech_pvt->video_rtp_session, tech_pvt->video_rtp_bugs | tech_pvt->profile->manual_video_rtp_bugs);
+
+ if (tech_pvt->video_recv_pt != tech_pvt->video_agreed_pt) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG,
+ "%s Set video receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->video_recv_pt);
+ switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_recv_pt);
+ }
+
+ switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_pt", "%d", tech_pvt->video_agreed_pt);
+ tech_pvt->video_ssrc = switch_rtp_get_ssrc(tech_pvt->rtp_session);
+ switch_channel_set_variable_printf(tech_pvt->channel, "rtp_use_video_ssrc", "%u", tech_pvt->ssrc);
+
+
+ if ((val = switch_channel_get_variable(tech_pvt->channel, "rtcp_audio_interval_msec"))
+ || (val = tech_pvt->profile->rtcp_audio_interval_msec)) {
+ const char *rport = switch_channel_get_variable(tech_pvt->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(tech_pvt->rtp_session, -1, remote_port);
+ } else {
+ int interval = atoi(val);
+ if (interval < 100 || interval > 5000) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
+ "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval);
+ } else {
+ switch_rtp_activate_rtcp(tech_pvt->rtp_session, interval, remote_port);
+ }
+ }
+ }
+ 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));
+ switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ goto end;
+ }
+ }
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
+ switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ sofia_clear_flag_locked(tech_pvt, TFLAG_IO);
+ status = SWITCH_STATUS_FALSE;
+ goto end;
+ }
+
+ video_up:
+
+ sofia_set_flag(tech_pvt, TFLAG_IO);
+ status = SWITCH_STATUS_SUCCESS;
+
+ end:
+
+ sofia_clear_flag_locked(tech_pvt, TFLAG_REINVITE);
+ switch_core_recovery_track(tech_pvt->session);
+
+ switch_mutex_unlock(tech_pvt->sofia_mutex);
+
+ return status;
+
+}
+
+
+
+void sofia_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp)
+{
+ sdp_parser_t *parser;
+ sdp_session_t *sdp;
+ private_object_t *tech_pvt = switch_core_session_get_private(session);
+
+ if ((parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
+
+ if ((sdp = sdp_session(parser))) {
+ sofia_glue_set_r_sdp_codec_string(session, sofia_glue_get_codec_string(tech_pvt), sdp);
+ }
+
+ sdp_parser_free(parser);
+ }
+
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+