SM_NDLB_ALLOW_BAD_IANANAME = (1 << 0),
SM_NDLB_ALLOW_NONDUP_SDP = (1 << 1),
SM_NDLB_ALLOW_CRYPTO_IN_AVP = (1 << 2),
- SM_NDLB_DISABLE_SRTP_AUTH = (1 << 3)
+ SM_NDLB_DISABLE_SRTP_AUTH = (1 << 3),
+ SM_NDLB_SENDRECV_IN_SESSION = (1 << 4)
} switch_core_media_NDLB_t;
typedef enum {
char *extsipip;
char *local_network;
-
+
+ char *sdp_username;
+
+ switch_mutex_t *mutex;
+
} switch_core_media_params_t;
+static inline const char *switch_media_type2str(switch_media_type_t type)
+{
+ switch(type) {
+ case SWITCH_MEDIA_TYPE_AUDIO:
+ return "audio";
+ case SWITCH_MEDIA_TYPE_VIDEO:
+ return "video";
+ default:
+ return "!ERR";
+
+ }
+}
SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t **smhp, switch_core_session_t *session, switch_core_media_params_t *params);
switch_frame_t *frame, switch_io_flag_t flags, int stream_id, switch_media_type_t type);
SWITCH_DECLARE(int) switch_core_media_check_nat(switch_media_handle_t *smh, const char *network_ip);
+SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_session_t *session, switch_media_type_t type, int force);
+
SWITCH_END_EXTERN_C
#endif
/* For Emacs:
CF_VIDEO_POSSIBLE,//TFLAG_VIDEO
CF_NOTIMER_DURING_BRIDGE,
CF_PASS_RFC2833,
+ CF_T38_PASSTHRU,
+ CF_DROP_DTMF,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
CF_FLAG_MAX
PFLAG_RUNNING,
PFLAG_RESPAWN,
PFLAG_MULTIREG,
- PFLAG_SUPPRESS_CNG,
PFLAG_TLS,
PFLAG_CHECKUSER,
PFLAG_SECURE,
typedef enum {
PFLAG_NDLB_TO_IN_200_CONTACT = (1 << 0),
PFLAG_NDLB_BROKEN_AUTH_HASH = (1 << 1),
- PFLAG_NDLB_SENDRECV_IN_SESSION = (1 << 2),
- PFLAG_NDLB_EXPIRES_IN_REGISTER_RESPONSE = (1 << 6)
+ PFLAG_NDLB_EXPIRES_IN_REGISTER_RESPONSE = (1 << 2)
} sofia_NDLB_t;
typedef enum {
TFLAG_CAPTURE,
TFLAG_REINVITED,
TFLAG_PASS_ACK,
- TFLAG_DROP_DTMF,
/* No new flags below this line */
TFLAG_MAX
} TFLAGS;
uint32_t rtpip_next;
char *sipip;
char *extsipip;
- char *username;
char *url;
char *public_url;
char *bindurl;
switch_core_media_flag_t media_flags[SCMF_MAX];
unsigned int mflags;
unsigned int ndlb;
+ unsigned int mdlb;
uint32_t max_calls;
uint32_t nonce_ttl;
nua_t *nua;
nua_handle_t *nh;
nua_handle_t *nh2;
sip_contact_t *contact;
- uint32_t owner_id;
- uint32_t session_id;
uint32_t max_missed_packets;
uint32_t max_missed_hold_packets;
/** VIDEO **/
void sofia_glue_global_capture(switch_bool_t on);
void sofia_glue_global_watchdog(switch_bool_t on);
void sofia_media_proxy_codec(switch_core_session_t *session, const char *r_sdp);
-switch_status_t sofia_media_sdp_map(const char *r_sdp, switch_event_t **fmtp, switch_event_t **pt);
void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl);
-void sofia_glue_check_dtmf_type(private_object_t *tech_pvt);
char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, nua_handle_t *nh, sofia_dispatch_event_t *de, sofia_nat_parse_t *np);
void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on);
void sofia_process_dispatch_event(sofia_dispatch_event_t **dep);
profile->local_network = "localnet.auto";
sofia_set_flag(profile, TFLAG_ENABLE_SOA);
sofia_set_pflag(profile, PFLAG_CID_IN_1XX);
- profile->ndlb |= SM_NDLB_ALLOW_NONDUP_SDP;
+ profile->mndlb |= SM_NDLB_ALLOW_NONDUP_SDP;
profile->te = 101;
profile->ireg_seconds = IREG_SECONDS;
profile->paid_type = PAID_DEFAULT;
sofia_clear_media_flag(profile, SCMF_DISABLE_RTP_AUTOADJ);
}
} else if (!strcasecmp(var, "NDLB-support-asterisk-missing-srtp-auth") && switch_true(val)) {
- profile->ndlb |= SM_NDLB_DISABLE_SRTP_AUTH;
+ profile->mndlb |= SM_NDLB_DISABLE_SRTP_AUTH;
} else if (!strcasecmp(var, "user-agent-filter")) {
profile->user_agent_filter = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "max-registrations-per-extension")) {
}
} else if (!strcasecmp(var, "NDLB-sendrecv-in-session")) {
if (switch_true(val)) {
- profile->ndlb |= PFLAG_NDLB_SENDRECV_IN_SESSION;
+ profile->mndlb |= SM_NDLB_SENDRECV_IN_SESSION;
} else {
- profile->ndlb &= ~PFLAG_NDLB_SENDRECV_IN_SESSION;
+ profile->mndlb &= ~SM_NDLB_SENDRECV_IN_SESSION;
}
} else if (!strcasecmp(var, "NDLB-allow-bad-iananame")) {
if (switch_true(val)) {
- profile->ndlb |= SM_NDLB_ALLOW_BAD_IANANAME;
+ profile->mndlb |= SM_NDLB_ALLOW_BAD_IANANAME;
} else {
- profile->ndlb &= ~SM_NDLB_ALLOW_BAD_IANANAME;
+ profile->mndlb &= ~SM_NDLB_ALLOW_BAD_IANANAME;
}
} else if (!strcasecmp(var, "NDLB-expires-in-register-response")) {
if (switch_true(val)) {
}
} else if (!strcasecmp(var, "NDLB-allow-crypto-in-avp")) {
if (switch_true(val)) {
- profile->ndlb |= SM_NDLB_ALLOW_CRYPTO_IN_AVP;
+ profile->mndlb |= SM_NDLB_ALLOW_CRYPTO_IN_AVP;
} else {
- profile->ndlb &= ~SM_NDLB_ALLOW_CRYPTO_IN_AVP;
+ profile->mndlb &= ~SM_NDLB_ALLOW_CRYPTO_IN_AVP;
}
} else if (!strcasecmp(var, "NDLB-allow-nondup-sdp")) {
if (switch_true(val)) {
- profile->ndlb |= SM_NDLB_ALLOW_NONDUP_SDP;
+ profile->mndlb |= SM_NDLB_ALLOW_NONDUP_SDP;
} else {
- profile->ndlb &= ~SM_NDLB_ALLOW_NONDUP_SDP;
+ profile->mndlb &= ~SM_NDLB_ALLOW_NONDUP_SDP;
}
} else if (!strcasecmp(var, "pass-rfc2833")) {
if (switch_true(val)) {
profile->codec_flags = SWITCH_CODEC_FLAG_AAL2;
}
} else if (!strcasecmp(var, "username")) {
- profile->username = switch_core_strdup(profile->pool, val);
+ profile->sdp_username = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "context")) {
profile->context = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "apply-nat-acl")) {
switch_core_session_rwunlock(other_session);
goto end;
} else {
- 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] = "";
-
- 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);
- }
- }
-
- switch_core_media_copy_t38_options(t38_options, other_session);
+ switch_core_media_process_t38_passthru(session, other_session, t38_options);
}
}
if (r_sdp) {
- if (!(profile->ndlb & SM_NDLB_ALLOW_NONDUP_SDP) || (!zstr(tech_pvt->remote_sdp_str) && !strcmp(tech_pvt->remote_sdp_str, r_sdp))) {
+ if (!(profile->mndlb & SM_NDLB_ALLOW_NONDUP_SDP) || (!zstr(tech_pvt->remote_sdp_str) && !strcmp(tech_pvt->remote_sdp_str, r_sdp))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Duplicate SDP\n%s\n", r_sdp);
is_dup_sdp = 1;
} else {
}
-void sofia_glue_check_dtmf_type(private_object_t *tech_pvt)
-{
- const char *val;
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "dtmf_type"))) {
- if (!strcasecmp(val, "rfc2833")) {
- tech_pvt->dtmf_type = DTMF_2833;
- } else if (!strcasecmp(val, "info")) {
- tech_pvt->dtmf_type = DTMF_INFO;
- } else if (!strcasecmp(val, "none")) {
- tech_pvt->dtmf_type = DTMF_NONE;
- } else {
- tech_pvt->dtmf_type = tech_pvt->profile->dtmf_type;
- }
- }
-}
-
private_object_t *sofia_glue_new_pvt(switch_core_session_t *session)
{
switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
switch_channel_set_cap(tech_pvt->channel, CC_QUEUEABLE_DTMF_DELAY);
- tech_pvt->mparams->ndlb = tech_pvt->profile->ndlb;
+ tech_pvt->mparams->ndlb = tech_pvt->profile->mndlb;
tech_pvt->mparams->inbound_codec_string = profile->inbound_codec_string;
tech_pvt->mparams->outbound_codec_string = profile->outbound_codec_string;
tech_pvt->mparams->auto_rtp_bugs = profile->auto_rtp_bugs;
tech_pvt->mparams->manual_video_rtp_bugs = profile->manual_video_rtp_bugs;
tech_pvt->mparams->extsipip = profile->extsipip;
tech_pvt->mparams->local_network = profile->local_network;
+ tech_pvt->mparams->mutex = tech_pvt->sofia_mutex;
switch_media_handle_create(&tech_pvt->media_handle, session, &tech_pvt->mparams);
return NULL;
}
-switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int force)
-{
- char *lookup_rtpip = tech_pvt->rtpip; /* Pointer to externally looked up address */
- switch_port_t sdp_port, rtcp_port; /* The external port to be sent in the SDP */
- const char *use_ip = NULL; /* The external IP to be sent in the SDP */
-
- /* Don't do anything if we're in proxy mode or if a (remote) port already has been found */
- if (!force) {
- if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
- switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) || tech_pvt->adv_sdp_audio_port) {
- return SWITCH_STATUS_SUCCESS;
- }
- }
-
- /* Release the local sdp port */
- if (tech_pvt->local_sdp_audio_port) {
- switch_rtp_release_port(tech_pvt->rtpip, tech_pvt->local_sdp_audio_port);
- }
-
- /* Request a local port from the core's allocator */
- if (!(tech_pvt->local_sdp_audio_port = switch_rtp_request_port(tech_pvt->rtpip))) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_CRIT, "No RTP ports available!\n");
- return SWITCH_STATUS_FALSE;
- }
-
- tech_pvt->local_sdp_audio_ip = tech_pvt->rtpip;
-
- sdp_port = tech_pvt->local_sdp_audio_port;
-
- /* Check if NAT is detected */
- if (!zstr(tech_pvt->remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->remote_ip)) {
- /* Yes, map the port through switch_nat */
- switch_nat_add_mapping(tech_pvt->local_sdp_audio_port, SWITCH_NAT_UDP, &sdp_port, SWITCH_FALSE);
- switch_nat_add_mapping(tech_pvt->local_sdp_audio_port + 1, SWITCH_NAT_UDP, &rtcp_port, SWITCH_FALSE);
-
- /* Find an IP address to use */
- if (!(use_ip = switch_channel_get_variable(tech_pvt->channel, "rtp_adv_audio_ip"))
- && !zstr(tech_pvt->profile->extrtpip)) {
- use_ip = tech_pvt->profile->extrtpip;
- }
-
- if (use_ip) {
- if (sofia_glue_ext_address_lookup(tech_pvt->profile, tech_pvt, &lookup_rtpip, &sdp_port,
- use_ip, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
- /* Address lookup was required and fail (external ip was "host:..." or "stun:...") */
- return SWITCH_STATUS_FALSE;
- } else {
- /* Address properly resolved, use it as external ip */
- use_ip = lookup_rtpip;
- }
- } else {
- /* No external ip found, use the profile's rtp ip */
- use_ip = tech_pvt->rtpip;
- }
- } else {
- /* No NAT traversal required, use the profile's rtp ip */
- use_ip = tech_pvt->rtpip;
- }
-
- tech_pvt->adv_sdp_audio_port = sdp_port;
- tech_pvt->adv_sdp_audio_ip = tech_pvt->extrtpip = switch_core_session_strdup(tech_pvt->session, use_ip);
-
- switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->local_sdp_audio_ip);
- switch_channel_set_variable_printf(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, "%d", sdp_port);
- switch_channel_set_variable(tech_pvt->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip);
-
- return SWITCH_STATUS_SUCCESS;
-}
-
-
sofia_transport_t sofia_glue_str2transport(const char *str)
{
if (!strncasecmp(str, "udp", 3)) {
switch_mutex_unlock(mod_sofia_globals.hash_mutex);
}
+#if 1
+int sofia_recover_callback(switch_core_session_t *session)
+{
+ return -1;
+}
+#else
int sofia_recover_callback(switch_core_session_t *session)
{
return r;
}
+#endif
+
int sofia_glue_recover(switch_bool_t flush)
{
-switch_status_t sofia_media_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_media_proxy_codec(switch_core_session_t *session, const char *r_sdp)
{
sdp_media_t *m;
}
-static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen,
- switch_port_t port,
- int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int verbose_sdp, int secure)
-{
- int i = 0;
- int rate;
- int already_did[128] = { 0 };
- int ptime = 0, noptime = 0;
- const char *local_audio_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
- const char *local_sdp_audio_zrtp_hash;
-
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP",
- port, secure ? "S" : "");
-
-
-
- for (i = 0; i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
- int this_ptime = (imp->microseconds_per_packet / 1000);
-
- if (!strcasecmp(imp->iananame, "ilbc")) {
- this_ptime = 20;
- }
-
- if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
- continue;
- }
-
- if (!noptime) {
- if (!cur_ptime) {
-#if 0
- if (ptime) {
- if (ptime != this_ptime) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Codec %s payload %d added to sdp wanting ptime %d but it's already %d (%s:%d:%d), disabling ptime.\n",
- imp->iananame,
- tech_pvt->ianacodes[i],
- this_ptime,
- ptime,
- tech_pvt->codecs[0]->iananame,
- tech_pvt->codecs[0]->ianacode,
- ptime);
- ptime = 0;
- noptime = 1;
- }
- } else {
- ptime = this_ptime;
- }
-#else
- if (!ptime) {
- ptime = this_ptime;
- }
-#endif
- } else {
- if (this_ptime != cur_ptime) {
- continue;
- }
- }
- }
-
- if (tech_pvt->ianacodes[i] < 128) {
- if (already_did[tech_pvt->ianacodes[i]]) {
- continue;
- }
-
- already_did[tech_pvt->ianacodes[i]] = 1;
- }
-
-
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", tech_pvt->ianacodes[i]);
- }
-
- if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", tech_pvt->te);
- }
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && cng_type && use_cng) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", cng_type);
- }
-
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "\n");
-
-
- memset(already_did, 0, sizeof(already_did));
-
- for (i = 0; i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
- char *fmtp = imp->fmtp;
- int this_ptime = imp->microseconds_per_packet / 1000;
-
- if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
- continue;
- }
-
- if (!strcasecmp(imp->iananame, "ilbc")) {
- this_ptime = 20;
- }
-
- if (!noptime) {
- if (!cur_ptime) {
- if (!ptime) {
- ptime = this_ptime;
- }
- } else {
- if (this_ptime != cur_ptime) {
- continue;
- }
- }
- }
-
- if (tech_pvt->ianacodes[i] < 128) {
- if (already_did[tech_pvt->ianacodes[i]]) {
- continue;
- }
-
- already_did[tech_pvt->ianacodes[i]] = 1;
- }
-
-
- rate = imp->samples_per_second;
-
- if (map) {
- char key[128] = "";
- char *check = NULL;
- switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
-
- if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
- fmtp = check;
- }
- }
-
- if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate);
- }
-
- if (fmtp) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->ianacodes[i], fmtp);
- }
- }
-
-
- if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) ||
- switch_channel_test_flag(tech_pvt->channel, CF_LIBERAL_DTMF)) && tech_pvt->te > 95) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
- }
-
- if (secure) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
- //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
- }
-
- if (!cng_type) {
- //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/8000\n", cng_type);
- //} else {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=silenceSupp:off - - - -\n");
- }
-
- if (append_audio) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
- }
-
- if (!cur_ptime) {
- cur_ptime = ptime;
- }
-
- if (!noptime && cur_ptime) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\n", cur_ptime);
- }
-
- local_sdp_audio_zrtp_hash = switch_core_media_get_zrtp_hash(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_TRUE);
-
- if (local_sdp_audio_zrtp_hash) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n", local_sdp_audio_zrtp_hash);
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n", local_sdp_audio_zrtp_hash);
- }
-
- if (!zstr(sr)) {
- switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\n", sr);
- }
-}
-
-
-#define SDPBUFLEN 65536
-void sofia_media_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch_port_t port, const char *sr, int force)
-{
- char *buf;
- int ptime = 0;
- uint32_t rate = 0;
- uint32_t v_port;
- int use_cng = 1;
- const char *val;
- const char *family;
- const char *pass_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_video_fmtp");
- const char *ov_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_force_video_fmtp");
- const char *append_audio = switch_channel_get_variable(tech_pvt->channel, "sip_append_audio_sdp");
- char srbuf[128] = "";
- const char *var_val;
- const char *username = tech_pvt->profile->username;
- const char *fmtp_out = tech_pvt->fmtp_out;
- const char *fmtp_out_var = switch_channel_get_variable(tech_pvt->channel, "sip_force_audio_fmtp");
- switch_event_t *map = NULL, *ptmap = NULL;
- const char *b_sdp = NULL;
- int verbose_sdp = 0;
- const char *local_audio_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
- const char *local_sdp_audio_zrtp_hash = switch_core_media_get_zrtp_hash(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_TRUE);
- const char *local_sdp_video_zrtp_hash = switch_core_media_get_zrtp_hash(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_TRUE);
-
- switch_zmalloc(buf, SDPBUFLEN);
-
- sofia_glue_check_dtmf_type(tech_pvt);
-
- 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))) {
- use_cng = 0;
- tech_pvt->cng_pt = 0;
- }
-
- if (!tech_pvt->payload_space) {
- int i;
-
- tech_pvt->payload_space = 98;
-
- for (i = 0; i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-
- tech_pvt->ianacodes[i] = imp->ianacode;
-
- if (tech_pvt->ianacodes[i] > 64) {
- if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95 && tech_pvt->te == tech_pvt->payload_space) {
- tech_pvt->payload_space++;
- }
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) &&
- tech_pvt->cng_pt && use_cng && tech_pvt->cng_pt == tech_pvt->payload_space) {
- tech_pvt->payload_space++;
- }
- tech_pvt->ianacodes[i] = tech_pvt->payload_space++;
- }
- }
- }
-
- if (fmtp_out_var) {
- fmtp_out = fmtp_out_var;
- }
-
- if ((val = switch_channel_get_variable(tech_pvt->channel, "verbose_sdp")) && switch_true(val)) {
- verbose_sdp = 1;
- }
-
- if (!force && !ip && zstr(sr)
- && (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA))) {
- switch_safe_free(buf);
- return;
- }
-
- if (!ip) {
- if (!(ip = tech_pvt->adv_sdp_audio_ip)) {
- ip = tech_pvt->proxy_sdp_audio_ip;
- }
- }
-
- if (!ip) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO IP!\n", switch_channel_get_name(tech_pvt->channel));
- switch_safe_free(buf);
- return;
- }
-
- if (!port) {
- if (!(port = tech_pvt->adv_sdp_audio_port)) {
- port = tech_pvt->proxy_sdp_audio_port;
- }
- }
-
- if (!port) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO PORT!\n", switch_channel_get_name(tech_pvt->channel));
- switch_safe_free(buf);
- return;
- }
-
- if (!tech_pvt->rm_encoding && (b_sdp = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE))) {
- sofia_media_sdp_map(b_sdp, &map, &ptmap);
- }
-
- if (zstr(sr)) {
- if ((var_val = switch_channel_get_variable(tech_pvt->channel, "media_audio_mode"))) {
- sr = var_val;
- } else {
- sr = "sendrecv";
- }
- }
-
- if (!tech_pvt->owner_id) {
- tech_pvt->owner_id = (uint32_t) switch_epoch_time_now(NULL) - port;
- }
-
- if (!tech_pvt->session_id) {
- tech_pvt->session_id = tech_pvt->owner_id;
- }
-
- if (switch_true(switch_channel_get_variable_dup(tech_pvt->channel, "drop_dtmf", SWITCH_FALSE, -1))) {
- sofia_set_flag(tech_pvt, TFLAG_DROP_DTMF);
- }
-
- tech_pvt->session_id++;
-
- if ((tech_pvt->profile->ndlb & PFLAG_NDLB_SENDRECV_IN_SESSION) ||
- ((var_val = switch_channel_get_variable(tech_pvt->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) {
- if (!zstr(sr)) {
- switch_snprintf(srbuf, sizeof(srbuf), "a=%s\n", sr);
- }
- sr = NULL;
- }
-
- family = strchr(ip, ':') ? "IP6" : "IP4";
- switch_snprintf(buf, SDPBUFLEN,
- "v=0\n"
- "o=%s %010u %010u IN %s %s\n"
- "s=%s\n"
- "c=IN %s %s\n" "t=0 0\n"
- "%s",
- username, tech_pvt->owner_id, tech_pvt->session_id, family, ip, username, family, ip, srbuf);
-
- if (tech_pvt->rm_encoding) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP",
- port, (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) ? "S" : "");
-
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->pt);
-
- if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) ||
- switch_channel_test_flag(tech_pvt->channel, CF_LIBERAL_DTMF)) && tech_pvt->te > 95) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->te);
- }
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->cng_pt);
- }
-
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
-
- rate = tech_pvt->rm_rate;
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate);
- if (fmtp_out) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->agreed_pt, fmtp_out);
- }
-
- if (tech_pvt->read_codec.implementation && !ptime) {
- ptime = tech_pvt->read_codec.implementation->microseconds_per_packet / 1000;
- }
-
-
- if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) ||
- switch_channel_test_flag(tech_pvt->channel, CF_LIBERAL_DTMF))
- && tech_pvt->te > 95) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
- }
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/8000\n", tech_pvt->cng_pt);
- if (!tech_pvt->rm_encoding) {
- tech_pvt->cng_pt = 0;
- }
- } else {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=silenceSupp:off - - - -\n");
- }
-
- if (append_audio) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
- }
-
- if (ptime) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ptime:%d\n", ptime);
- }
-
-
- if (local_sdp_audio_zrtp_hash) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
- local_sdp_audio_zrtp_hash);
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n",
- local_sdp_audio_zrtp_hash);
- }
-
- if (!zstr(sr)) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\n", sr);
- }
-
- if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
- //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n");
- }
-
- } else if (tech_pvt->num_codecs) {
- int i;
- int cur_ptime = 0, this_ptime = 0, cng_type = 0;
- const char *mult;
-
- if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
- cng_type = tech_pvt->cng_pt;
-
- if (!tech_pvt->rm_encoding) {
- tech_pvt->cng_pt = 0;
- }
- }
-
- mult = switch_channel_get_variable(tech_pvt->channel, "sdp_m_per_ptime");
-
- if (mult && switch_false(mult)) {
- char *bp = buf;
- int both = 1;
-
- if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
- generate_m(tech_pvt, buf, SDPBUFLEN, port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
- bp = (buf + strlen(buf));
-
- /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
- if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
- both = 0;
- }
-
- }
-
- if (both) {
- generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
- }
-
- } else {
-
- for (i = 0; i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-
- if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
- continue;
- }
-
- this_ptime = imp->microseconds_per_packet / 1000;
-
- if (!strcasecmp(imp->iananame, "ilbc")) {
- this_ptime = 20;
- }
-
- if (cur_ptime != this_ptime) {
- char *bp = buf;
- int both = 1;
-
- cur_ptime = this_ptime;
-
- if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
- generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
- bp = (buf + strlen(buf));
-
- /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
- if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
- both = 0;
- }
- }
-
- if (both) {
- generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
- }
- }
-
- }
- }
-
- }
-
- if (switch_channel_test_flag(tech_pvt->channel, CF_VIDEO_POSSIBLE)) {
- const char *local_video_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
-
- if (!tech_pvt->local_sdp_video_port) {
- sofia_glue_tech_choose_video_port(tech_pvt, 0);
- }
-
- if ((v_port = tech_pvt->adv_sdp_video_port)) {
-
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d RTP/%sAVP",
- v_port, (!zstr(local_video_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) ? "S" : "");
-
-
- /*****************************/
- if (tech_pvt->video_rm_encoding) {
- switch_core_media_set_video_codec(tech_pvt->session, 0);
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->video_agreed_pt);
- } else if (tech_pvt->num_codecs) {
- int i;
- int already_did[128] = { 0 };
- for (i = 0; i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-
- if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
- continue;
- }
-
- if (tech_pvt->ianacodes[i] < 128) {
- if (already_did[tech_pvt->ianacodes[i]]) {
- continue;
- }
- already_did[tech_pvt->ianacodes[i]] = 1;
- }
-
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->ianacodes[i]);
- if (!ptime) {
- ptime = imp->microseconds_per_packet / 1000;
- }
- }
- }
-
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
-
- if (tech_pvt->video_rm_encoding) {
- const char *of;
- rate = tech_pvt->video_rm_rate;
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n", tech_pvt->video_pt, tech_pvt->video_rm_encoding,
- tech_pvt->video_rm_rate);
-
- if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
- pass_fmtp = tech_pvt->video_rm_fmtp;
- } else {
-
- pass_fmtp = NULL;
-
- if (switch_channel_get_partner_uuid(tech_pvt->channel)) {
- if ((of = switch_channel_get_variable_partner(tech_pvt->channel, "sip_video_fmtp"))) {
- pass_fmtp = of;
- }
- }
-
- if (ov_fmtp) {
- pass_fmtp = ov_fmtp;
- }// else { // seems to break eyebeam at least...
- //pass_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_video_fmtp");
- //}
- }
-
- if (pass_fmtp) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->video_pt, pass_fmtp);
- }
-
- } else if (tech_pvt->num_codecs) {
- int i;
- int already_did[128] = { 0 };
-
- for (i = 0; i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
- char *fmtp = NULL;
- uint32_t ianacode = tech_pvt->ianacodes[i];
-
- if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
- continue;
- }
-
- if (ianacode < 128) {
- if (already_did[ianacode]) {
- continue;
- }
- already_did[ianacode] = 1;
- }
-
- if (!rate) {
- rate = imp->samples_per_second;
- }
-
-
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame,
- imp->samples_per_second);
-
- if (!zstr(ov_fmtp)) {
- fmtp = (char *) ov_fmtp;
- } else {
-
- if (map) {
- fmtp = switch_event_get_header(map, imp->iananame);
- }
-
- if (zstr(fmtp)) fmtp = imp->fmtp;
-
- if (zstr(fmtp)) fmtp = (char *) pass_fmtp;
- }
-
- if (!zstr(fmtp) && strcasecmp(fmtp, "_blank_")) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", ianacode, fmtp);
- }
- }
-
- }
-
- if (switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) {
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_video_crypto_key);
- //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
- }
-
-
-
- if (local_sdp_video_zrtp_hash) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n", local_sdp_video_zrtp_hash);
- switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n", local_sdp_video_zrtp_hash);
- }
- }
- }
-
-
- if (map) {
- switch_event_destroy(&map);
- }
-
- if (ptmap) {
- switch_event_destroy(&ptmap);
- }
-
- sofia_media_tech_set_local_sdp(tech_pvt, buf, SWITCH_TRUE);
-
- switch_safe_free(buf);
-}
-
void sofia_media_tech_prepare_codecs(private_object_t *tech_pvt)
{
const char *abs, *codec_string = NULL;
}
-void sofia_media_tech_set_local_sdp(private_object_t *tech_pvt, const char *sdp_str, switch_bool_t dup)
-{
- switch_mutex_lock(tech_pvt->sofia_mutex);
- tech_pvt->local_sdp_str = dup ? switch_core_session_strdup(tech_pvt->session, sdp_str) : (char *) sdp_str;
- switch_channel_set_variable(tech_pvt->channel, "sip_local_sdp_str", tech_pvt->local_sdp_str);
- switch_mutex_unlock(tech_pvt->sofia_mutex);
-}
-
-
char *sofia_media_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type)
{
char *extra_headers = NULL;
switch_payload_t ianacodes[SWITCH_MAX_CODECS];//x:tp
int video_count;//x:tp
+ uint32_t owner_id;
+ uint32_t session_id;
+
switch_core_media_params_t *mparams;
};
+//?
+SWITCH_DECLARE(switch_status_t) switch_core_media_process_t38_passthru(switch_core_session_t *session,
+ switch_core_session_t *other_session, switch_t38_options_t *t38_options)
+{
+ char *remote_host;
+ switch_port_t remote_port;
+ char tmp[32] = "";
+ switch_rtp_engine_t *a_engine;
+ switch_media_handle_t *smh;
+
+ if (!(smh = session->media_handle)) {
+ return SWITCH_STATUS_FALSE;;
+ }
+
+ a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
+
+ remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
+ remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
+
+ a_engine->codec_params.remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
+ a_engine->codec_params.remote_sdp_port = t38_options->remote_port;
+
+ if (remote_host && remote_port && !strcmp(remote_host, a_engine->codec_params.remote_sdp_ip) &&
+ remote_port == a_engine->codec_params.remote_sdp_port) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "Audio params are unchanged for %s.\n",
+ switch_channel_get_name(session->channel));
+ } else {
+ const char *err = NULL;
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "Audio params changed for %s from %s:%d to %s:%d\n",
+ switch_channel_get_name(session->channel),
+ remote_host, remote_port, a_engine->codec_params.remote_sdp_ip, a_engine->codec_params.remote_sdp_port);
+
+ switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->codec_params.remote_sdp_port);
+ switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, a_engine->codec_params.remote_sdp_ip);
+ switch_channel_set_variable(session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp);
+ if (switch_rtp_set_remote_address(a_engine->rtp_session, a_engine->codec_params.remote_sdp_ip,
+ a_engine->codec_params.remote_sdp_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
+ switch_channel_hangup(session->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
+ }
+ }
+
+ switch_core_media_copy_t38_options(t38_options, other_session);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+
+
+
SWITCH_DECLARE(const char *)switch_core_media_get_codec_string(switch_core_session_t *session)
}
-
-
//?
-SWITCH_DECLARE(switch_status_t) switch_core_media_choose_video_port(switch_core_session_t *session, int force)
+SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_session_t *session, switch_media_type_t type, int force)
{
char *lookup_rtpip; /* Pointer to externally looked up address */
switch_port_t sdp_port; /* The external port to be sent in the SDP */
const char *use_ip = NULL; /* The external IP to be sent in the SDP */
- switch_rtp_engine_t *a_engine, *v_engine;
+ switch_rtp_engine_t *engine;
switch_media_handle_t *smh;
+ const char *tstr = switch_media_type2str(type);
+ char vname[128] = "";
if (!(smh = session->media_handle)) {
return SWITCH_STATUS_FALSE;
}
- a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
- v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+ engine = &smh->engines[type];
lookup_rtpip = smh->mparams->rtpip;
-
/* Don't do anything if we're in proxy mode or if a (remote) port already has been found */
if (!force) {
if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) ||
- switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) || v_engine->codec_params.adv_sdp_port) {
+ switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) || engine->codec_params.adv_sdp_port) {
return SWITCH_STATUS_SUCCESS;
}
}
/* Release the local sdp port */
- if (v_engine->codec_params.local_sdp_port) {
- switch_rtp_release_port(smh->mparams->rtpip, v_engine->codec_params.local_sdp_port);
+ if (engine->codec_params.local_sdp_port) {
+ switch_rtp_release_port(smh->mparams->rtpip, engine->codec_params.local_sdp_port);
}
/* Request a local port from the core's allocator */
- if (!(v_engine->codec_params.local_sdp_port = switch_rtp_request_port(smh->mparams->rtpip))) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "No RTP ports available!\n");
+ if (!(engine->codec_params.local_sdp_port = switch_rtp_request_port(smh->mparams->rtpip))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "No %s RTP ports available!\n", tstr);
return SWITCH_STATUS_FALSE;
}
- sdp_port = v_engine->codec_params.local_sdp_port;
+ sdp_port = engine->codec_params.local_sdp_port;
/* Check if NAT is detected */
if (!zstr(smh->mparams->remote_ip) && switch_core_media_check_nat(smh, smh->mparams->remote_ip)) {
/* Yes, map the port through switch_nat */
- switch_nat_add_mapping(v_engine->codec_params.local_sdp_port, SWITCH_NAT_UDP, &sdp_port, SWITCH_FALSE);
+ switch_nat_add_mapping(engine->codec_params.local_sdp_port, SWITCH_NAT_UDP, &sdp_port, SWITCH_FALSE);
+ switch_snprintf(vname, sizeof(vname), "rtp_adv_%s_ip", tstr);
+
/* Find an IP address to use */
- if (!(use_ip = switch_channel_get_variable(session->channel, "rtp_adv_video_ip"))
+ if (!(use_ip = switch_channel_get_variable(session->channel, vname))
&& !zstr(smh->mparams->extrtpip)) {
use_ip = smh->mparams->extrtpip;
}
use_ip = smh->mparams->rtpip;
}
- v_engine->codec_params.adv_sdp_port = sdp_port;
- switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, a_engine->codec_params.adv_sdp_ip);
+ engine->codec_params.adv_sdp_port = sdp_port;
+ switch_channel_set_variable(session->channel, SWITCH_LOCAL_VIDEO_IP_VARIABLE, engine->codec_params.adv_sdp_ip);
switch_channel_set_variable_printf(session->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, "%d", sdp_port);
return SWITCH_STATUS_SUCCESS;
if (!v_engine->codec_params.local_sdp_port) {
- switch_core_media_choose_video_port(session, 1);
+ switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 1);
}
memset(flags, 0, sizeof(flags));
}
+//?
+static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
+ switch_port_t port,
+ int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int verbose_sdp, int secure)
+{
+ int i = 0;
+ int rate;
+ int already_did[128] = { 0 };
+ int ptime = 0, noptime = 0;
+ const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO);
+ const char *local_sdp_audio_zrtp_hash;
+ switch_media_handle_t *smh;
+
+ if (!(smh = session->media_handle)) {
+ return;
+ }
+
+
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP",
+ port, secure ? "S" : "");
+
+
+
+ for (i = 0; i < smh->num_codecs; i++) {
+ const switch_codec_implementation_t *imp = smh->codecs[i];
+ int this_ptime = (imp->microseconds_per_packet / 1000);
+
+ if (!strcasecmp(imp->iananame, "ilbc")) {
+ this_ptime = 20;
+ }
+
+ if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+ continue;
+ }
+
+ if (!noptime) {
+ if (!cur_ptime) {
+ if (!ptime) {
+ ptime = this_ptime;
+ }
+ } else {
+ if (this_ptime != cur_ptime) {
+ continue;
+ }
+ }
+ }
+
+ if (smh->ianacodes[i] < 128) {
+ if (already_did[smh->ianacodes[i]]) {
+ continue;
+ }
+
+ already_did[smh->ianacodes[i]] = 1;
+ }
+
+
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->ianacodes[i]);
+ }
+
+ if (smh->dtmf_type == DTMF_2833 && smh->te > 95) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->te);
+ }
+
+ if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && cng_type && use_cng) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", cng_type);
+ }
+
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "\n");
+
+
+ memset(already_did, 0, sizeof(already_did));
+
+ for (i = 0; i < smh->num_codecs; i++) {
+ const switch_codec_implementation_t *imp = smh->codecs[i];
+ char *fmtp = imp->fmtp;
+ int this_ptime = imp->microseconds_per_packet / 1000;
+
+ if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+ continue;
+ }
+
+ if (!strcasecmp(imp->iananame, "ilbc")) {
+ this_ptime = 20;
+ }
+
+ if (!noptime) {
+ if (!cur_ptime) {
+ if (!ptime) {
+ ptime = this_ptime;
+ }
+ } else {
+ if (this_ptime != cur_ptime) {
+ continue;
+ }
+ }
+ }
+
+ if (smh->ianacodes[i] < 128) {
+ if (already_did[smh->ianacodes[i]]) {
+ continue;
+ }
+
+ already_did[smh->ianacodes[i]] = 1;
+ }
+
+
+ rate = imp->samples_per_second;
+
+ if (map) {
+ char key[128] = "";
+ char *check = NULL;
+ switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
+
+ if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
+ fmtp = check;
+ }
+ }
+
+ if (smh->ianacodes[i] > 95 || verbose_sdp) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", smh->ianacodes[i], imp->iananame, rate);
+ }
+
+ if (fmtp) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\n", smh->ianacodes[i], fmtp);
+ }
+ }
+
+
+ if ((smh->dtmf_type == DTMF_2833 || switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) ||
+ switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->te > 95) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", smh->te, smh->te);
+ }
+
+ if (secure) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
+ //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
+ }
+
+ if (!cng_type) {
+ //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/8000\n", cng_type);
+ //} else {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=silenceSupp:off - - - -\n");
+ }
+
+ if (append_audio) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
+ }
+
+ if (!cur_ptime) {
+ cur_ptime = ptime;
+ }
+
+ if (!noptime && cur_ptime) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\n", cur_ptime);
+ }
+
+ local_sdp_audio_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_TRUE);
+
+ if (local_sdp_audio_zrtp_hash) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n", local_sdp_audio_zrtp_hash);
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n", local_sdp_audio_zrtp_hash);
+ }
+
+ if (!zstr(sr)) {
+ switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\n", sr);
+ }
+}
+
+//?
+SWITCH_DECLARE(void) switch_core_media_check_dtmf_type(switch_core_session_t *session)
+{
+ const char *val;
+ switch_media_handle_t *smh;
+
+ if (!(smh = session->media_handle)) {
+ return;
+ }
+
+ if ((val = switch_channel_get_variable(session->channel, "dtmf_type"))) {
+ if (!strcasecmp(val, "rfc2833")) {
+ smh->dtmf_type = DTMF_2833;
+ } else if (!strcasecmp(val, "info")) {
+ smh->dtmf_type = DTMF_INFO;
+ } else if (!strcasecmp(val, "none")) {
+ smh->dtmf_type = DTMF_NONE;
+ }
+ }
+}
+
+//?
+switch_status_t switch_core_media_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;
+
+}
+
+//?
+SWITCH_DECLARE(void)switch_core_media_set_local_sdp(switch_core_session_t *session, const char *sdp_str, switch_bool_t dup)
+{
+ switch_media_handle_t *smh;
+
+ if (!(smh = session->media_handle)) {
+ return;
+ }
+
+ if (smh->mparams->mutex) switch_mutex_lock(smh->mparams->mutex);
+ smh->mparams->local_sdp_str = dup ? switch_core_session_strdup(session, sdp_str) : (char *) sdp_str;
+ switch_channel_set_variable(session->channel, "sip_local_sdp_str", smh->mparams->local_sdp_str);
+ if (smh->mparams->mutex) switch_mutex_unlock(smh->mparams->mutex);
+}
+
+
+
+
+
+//?
+#define SDPBUFLEN 65536
+void sofia_media_set_local_sdp(switch_core_session_t *session, const char *ip, switch_port_t port, const char *sr, int force)
+{
+ char *buf;
+ int ptime = 0;
+ uint32_t rate = 0;
+ uint32_t v_port;
+ int use_cng = 1;
+ const char *val;
+ const char *family;
+ const char *pass_fmtp = switch_channel_get_variable(session->channel, "sip_video_fmtp");
+ const char *ov_fmtp = switch_channel_get_variable(session->channel, "sip_force_video_fmtp");
+ const char *append_audio = switch_channel_get_variable(session->channel, "sip_append_audio_sdp");
+ char srbuf[128] = "";
+ const char *var_val;
+ const char *username;
+ const char *fmtp_out;
+ const char *fmtp_out_var = switch_channel_get_variable(session->channel, "sip_force_audio_fmtp");
+ switch_event_t *map = NULL, *ptmap = NULL;
+ const char *b_sdp = NULL;
+ int verbose_sdp = 0;
+ const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO);
+ const char *local_sdp_audio_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_TRUE);
+ const char *local_sdp_video_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_TRUE);
+ switch_rtp_engine_t *a_engine, *v_engine;
+ switch_media_handle_t *smh;
+
+ if (!(smh = session->media_handle)) {
+ return;
+ }
+
+ a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
+ v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+
+ fmtp_out = a_engine->codec_params.fmtp_out;
+ username = smh->mparams->sdp_username;
+
+
+ switch_zmalloc(buf, SDPBUFLEN);
+
+ switch_core_media_check_dtmf_type(session);
+
+ if (switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) ||
+ ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
+ ((val = switch_channel_get_variable(session->channel, "suppress_cng")) && switch_true(val))) {
+ use_cng = 0;
+ smh->cng_pt = 0;
+ }
+
+ if (!smh->payload_space) {
+ int i;
+
+ smh->payload_space = 98;
+
+ for (i = 0; i < smh->num_codecs; i++) {
+ const switch_codec_implementation_t *imp = smh->codecs[i];
+
+ smh->ianacodes[i] = imp->ianacode;
+
+ if (smh->ianacodes[i] > 64) {
+ if (smh->dtmf_type == DTMF_2833 && smh->te > 95 && smh->te == smh->payload_space) {
+ smh->payload_space++;
+ }
+ if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) &&
+ smh->cng_pt && use_cng && smh->cng_pt == smh->payload_space) {
+ smh->payload_space++;
+ }
+ smh->ianacodes[i] = smh->payload_space++;
+ }
+ }
+ }
+
+ if (fmtp_out_var) {
+ fmtp_out = fmtp_out_var;
+ }
+
+ if ((val = switch_channel_get_variable(session->channel, "verbose_sdp")) && switch_true(val)) {
+ verbose_sdp = 1;
+ }
+
+ if (!force && !ip && zstr(sr)
+ && (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA))) {
+ switch_safe_free(buf);
+ return;
+ }
+
+ if (!ip) {
+ if (!(ip = a_engine->codec_params.adv_sdp_ip)) {
+ ip = a_engine->codec_params.proxy_sdp_ip;
+ }
+ }
+
+ if (!ip) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO IP!\n", switch_channel_get_name(session->channel));
+ switch_safe_free(buf);
+ return;
+ }
+
+ if (!port) {
+ if (!(port = a_engine->codec_params.adv_sdp_port)) {
+ port = a_engine->codec_params.proxy_sdp_port;
+ }
+ }
+
+ if (!port) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO PORT!\n", switch_channel_get_name(session->channel));
+ switch_safe_free(buf);
+ return;
+ }
+
+ if (!a_engine->codec_params.rm_encoding && (b_sdp = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
+ switch_core_media_sdp_map(b_sdp, &map, &ptmap);
+ }
+
+ if (zstr(sr)) {
+ if ((var_val = switch_channel_get_variable(session->channel, "media_audio_mode"))) {
+ sr = var_val;
+ } else {
+ sr = "sendrecv";
+ }
+ }
+
+ if (!smh->owner_id) {
+ smh->owner_id = (uint32_t) switch_epoch_time_now(NULL) - port;
+ }
+
+ if (!smh->session_id) {
+ smh->session_id = smh->owner_id;
+ }
+
+ if (switch_true(switch_channel_get_variable_dup(session->channel, "drop_dtmf", SWITCH_FALSE, -1))) {
+ switch_channel_set_flag(session->channel, CF_DROP_DTMF);
+ }
+
+ smh->session_id++;
+
+ if ((smh->mparams->ndlb & SM_NDLB_SENDRECV_IN_SESSION) ||
+ ((var_val = switch_channel_get_variable(session->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) {
+ if (!zstr(sr)) {
+ switch_snprintf(srbuf, sizeof(srbuf), "a=%s\n", sr);
+ }
+ sr = NULL;
+ }
+
+ family = strchr(ip, ':') ? "IP6" : "IP4";
+ switch_snprintf(buf, SDPBUFLEN,
+ "v=0\n"
+ "o=%s %010u %010u IN %s %s\n"
+ "s=%s\n"
+ "c=IN %s %s\n" "t=0 0\n"
+ "%s",
+ username, smh->owner_id, smh->session_id, family, ip, username, family, ip, srbuf);
+
+ if (a_engine->codec_params.rm_encoding) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP",
+ port, (!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) ? "S" : "");
+
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", a_engine->codec_params.pt);
+
+ if ((smh->dtmf_type == DTMF_2833 || switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) ||
+ switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->te > 95) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->te);
+ }
+
+ if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->cng_pt && use_cng) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->cng_pt);
+ }
+
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
+
+ rate = a_engine->codec_params.rm_rate;
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", a_engine->codec_params.agreed_pt, a_engine->codec_params.rm_encoding, rate);
+ if (fmtp_out) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", a_engine->codec_params.agreed_pt, fmtp_out);
+ }
+
+ if (a_engine->read_codec.implementation && !ptime) {
+ ptime = a_engine->read_codec.implementation->microseconds_per_packet / 1000;
+ }
+
+
+ if ((smh->dtmf_type == DTMF_2833 || switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) ||
+ switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF))
+ && smh->te > 95) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", smh->te, smh->te);
+ }
+ if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->cng_pt && use_cng) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/8000\n", smh->cng_pt);
+ if (!a_engine->codec_params.rm_encoding) {
+ smh->cng_pt = 0;
+ }
+ } else {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=silenceSupp:off - - - -\n");
+ }
+
+ if (append_audio) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
+ }
+
+ if (ptime) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ptime:%d\n", ptime);
+ }
+
+
+ if (local_sdp_audio_zrtp_hash) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
+ local_sdp_audio_zrtp_hash);
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n",
+ local_sdp_audio_zrtp_hash);
+ }
+
+ if (!zstr(sr)) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\n", sr);
+ }
+
+ if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
+ //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n");
+ }
+
+ } else if (smh->num_codecs) {
+ int i;
+ int cur_ptime = 0, this_ptime = 0, cng_type = 0;
+ const char *mult;
+
+ if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->cng_pt && use_cng) {
+ cng_type = smh->cng_pt;
+
+ if (!a_engine->codec_params.rm_encoding) {
+ smh->cng_pt = 0;
+ }
+ }
+
+ mult = switch_channel_get_variable(session->channel, "sdp_m_per_ptime");
+
+ if (mult && switch_false(mult)) {
+ char *bp = buf;
+ int both = 1;
+
+ if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE))) {
+ generate_m(session, buf, SDPBUFLEN, port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
+ bp = (buf + strlen(buf));
+
+ /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
+ if (switch_true(switch_channel_get_variable(session->channel, "sdp_secure_savp_only"))) {
+ both = 0;
+ }
+
+ }
+
+ if (both) {
+ generate_m(session, bp, SDPBUFLEN - strlen(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
+ }
+
+ } else {
+
+ for (i = 0; i < smh->num_codecs; i++) {
+ const switch_codec_implementation_t *imp = smh->codecs[i];
+
+ if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+ continue;
+ }
+
+ this_ptime = imp->microseconds_per_packet / 1000;
+
+ if (!strcasecmp(imp->iananame, "ilbc")) {
+ this_ptime = 20;
+ }
+
+ if (cur_ptime != this_ptime) {
+ char *bp = buf;
+ int both = 1;
+
+ cur_ptime = this_ptime;
+
+ if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE))) {
+ generate_m(session, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
+ bp = (buf + strlen(buf));
+
+ /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
+ if (switch_true(switch_channel_get_variable(session->channel, "sdp_secure_savp_only"))) {
+ both = 0;
+ }
+ }
+
+ if (both) {
+ generate_m(session, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
+ }
+ }
+
+ }
+ }
+
+ }
+
+ if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) {
+ const char *local_video_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_VIDEO);
+
+ if (!v_engine->codec_params.local_sdp_port) {
+ switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_VIDEO, 0);
+ }
+
+ if ((v_port = v_engine->codec_params.adv_sdp_port)) {
+
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d RTP/%sAVP",
+ v_port, (!zstr(local_video_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) ? "S" : "");
+
+
+ /*****************************/
+ if (v_engine->codec_params.rm_encoding) {
+ switch_core_media_set_video_codec(session, 0);
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", v_engine->codec_params.agreed_pt);
+ } else if (smh->num_codecs) {
+ int i;
+ int already_did[128] = { 0 };
+ for (i = 0; i < smh->num_codecs; i++) {
+ const switch_codec_implementation_t *imp = smh->codecs[i];
+
+ if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
+ continue;
+ }
+
+ if (smh->ianacodes[i] < 128) {
+ if (already_did[smh->ianacodes[i]]) {
+ continue;
+ }
+ already_did[smh->ianacodes[i]] = 1;
+ }
+
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->ianacodes[i]);
+ if (!ptime) {
+ ptime = imp->microseconds_per_packet / 1000;
+ }
+ }
+ }
+
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
+
+ if (v_engine->codec_params.rm_encoding) {
+ const char *of;
+ rate = v_engine->codec_params.rm_rate;
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n",
+ v_engine->codec_params.pt, v_engine->codec_params.rm_encoding,
+ v_engine->codec_params.rm_rate);
+
+ if (switch_channel_test_flag(session->channel, CF_RECOVERING)) {
+ pass_fmtp = v_engine->codec_params.rm_fmtp;
+ } else {
+
+ pass_fmtp = NULL;
+
+ if (switch_channel_get_partner_uuid(session->channel)) {
+ if ((of = switch_channel_get_variable_partner(session->channel, "sip_video_fmtp"))) {
+ pass_fmtp = of;
+ }
+ }
+
+ if (ov_fmtp) {
+ pass_fmtp = ov_fmtp;
+ }// else { // seems to break eyebeam at least...
+ //pass_fmtp = switch_channel_get_variable(session->channel, "sip_video_fmtp");
+ //}
+ }
+
+ if (pass_fmtp) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", v_engine->codec_params.pt, pass_fmtp);
+ }
+
+ } else if (smh->num_codecs) {
+ int i;
+ int already_did[128] = { 0 };
+
+ for (i = 0; i < smh->num_codecs; i++) {
+ const switch_codec_implementation_t *imp = smh->codecs[i];
+ char *fmtp = NULL;
+ uint32_t ianacode = smh->ianacodes[i];
+
+ if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
+ continue;
+ }
+
+ if (ianacode < 128) {
+ if (already_did[ianacode]) {
+ continue;
+ }
+ already_did[ianacode] = 1;
+ }
+
+ if (!rate) {
+ rate = imp->samples_per_second;
+ }
+
+
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame,
+ imp->samples_per_second);
+
+ if (!zstr(ov_fmtp)) {
+ fmtp = (char *) ov_fmtp;
+ } else {
+
+ if (map) {
+ fmtp = switch_event_get_header(map, imp->iananame);
+ }
+
+ if (zstr(fmtp)) fmtp = imp->fmtp;
+
+ if (zstr(fmtp)) fmtp = (char *) pass_fmtp;
+ }
+
+ if (!zstr(fmtp) && strcasecmp(fmtp, "_blank_")) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", ianacode, fmtp);
+ }
+ }
+
+ }
+
+ if (switch_channel_test_flag(session->channel, CF_SECURE)) {
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_video_crypto_key);
+ //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
+ }
+
+
+
+ if (local_sdp_video_zrtp_hash) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n", local_sdp_video_zrtp_hash);
+ switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n", local_sdp_video_zrtp_hash);
+ }
+ }
+ }
+
+
+ if (map) {
+ switch_event_destroy(&map);
+ }
+
+ if (ptmap) {
+ switch_event_destroy(&ptmap);
+ }
+
+ switch_core_media_set_local_sdp(session, buf, SWITCH_TRUE);
+
+ switch_safe_free(buf);
+}
+
/* For Emacs:
* Local Variables: