]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
compiles the core wow
authorAnthony Minessale <anthm@freeswitch.org>
Fri, 21 Dec 2012 22:57:59 +0000 (16:57 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 1 Apr 2013 02:27:14 +0000 (21:27 -0500)
src/include/switch_core_media.h
src/include/switch_types.h
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c
src/mod/endpoints/mod_sofia/sofia_media.c
src/switch_core_media.c

index 21a80a194f6ab8c1db22ad7e048b6e6cb357ffaa..960ab2e955941515c6598b6d58fad825d81e0f40 100644 (file)
@@ -48,7 +48,8 @@ typedef enum {
        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 {
@@ -125,10 +126,26 @@ typedef struct switch_core_media_params_s {
 
        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);
@@ -170,6 +187,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_sessio
                                                                                                                          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:
index f6ca438a6b4b8bd4090a1550ba32b0097432c206..52885c9a8152fe5c847c6b66f6452cc90c478dc8 100644 (file)
@@ -1290,6 +1290,8 @@ typedef enum {
        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
index 0f07da49157dec2fe983a2ca3819a33b54b3cda0..03d10a8705f866d6230df1aa2e95bc16d8a7cb2a 100644 (file)
@@ -203,7 +203,6 @@ typedef enum {
        PFLAG_RUNNING,
        PFLAG_RESPAWN,
        PFLAG_MULTIREG,
-       PFLAG_SUPPRESS_CNG,
        PFLAG_TLS,
        PFLAG_CHECKUSER,
        PFLAG_SECURE,
@@ -271,8 +270,7 @@ typedef enum {
 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 {
@@ -317,7 +315,6 @@ typedef enum {
        TFLAG_CAPTURE,
        TFLAG_REINVITED,
        TFLAG_PASS_ACK,
-       TFLAG_DROP_DTMF,
        /* No new flags below this line */
        TFLAG_MAX
 } TFLAGS;
@@ -530,7 +527,6 @@ struct sofia_profile {
        uint32_t rtpip_next;
        char *sipip;
        char *extsipip;
-       char *username;
        char *url;
        char *public_url;
        char *bindurl;
@@ -577,6 +573,7 @@ struct sofia_profile {
        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;
@@ -745,8 +742,6 @@ struct private_object {
        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 **/
@@ -1140,9 +1135,7 @@ void sofia_glue_global_siptrace(switch_bool_t on);
 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);
index f4bec11606eac379c16b5e9ae95e2eb7b0ea690b..ebd14049c0446bf36f9fd89a8c177a18b6dc2832 100644 (file)
@@ -3605,7 +3605,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                        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;
@@ -3926,7 +3926,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                                        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")) {
@@ -4165,15 +4165,15 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                                }
                                        } 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)) {
@@ -4183,15 +4183,15 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                                }
                                        } 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)) {
@@ -4324,7 +4324,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                                        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")) {
@@ -5229,37 +5229,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
                                                        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);
                                                }
                                        }
 
@@ -5629,7 +5599,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
 
                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 {
index 9dedfbc672a69fb1dfb48e8e898c0e9ce5bea43b..767400f4d4d02addad136d73fb75a145bc00b0f0 100644 (file)
@@ -178,23 +178,6 @@ void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_optio
 
 }
 
-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)
 {
@@ -279,7 +262,7 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
        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;
@@ -289,6 +272,7 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *
        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);
@@ -318,76 +302,6 @@ const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name)
        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)) {
@@ -1954,6 +1868,12 @@ void sofia_glue_del_profile(sofia_profile_t *profile)
        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) 
 {
 
@@ -2184,6 +2104,8 @@ int sofia_recover_callback(switch_core_session_t *session)
        return r;
 
 }
+#endif
+
 
 int sofia_glue_recover(switch_bool_t flush)
 {
index e0cef9e3236071445ea396bbdc61bc6eb97dc3a0..6b66806b80b0552187cdbfa51ce004965c7169af 100644 (file)
@@ -73,65 +73,6 @@ void sofia_media_tech_absorb_sdp(private_object_t *tech_pvt)
 
 
 
-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;
@@ -507,618 +448,6 @@ switch_status_t sofia_media_tech_media(private_object_t *tech_pvt, const char *r
 }
 
 
-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;
@@ -1459,15 +788,6 @@ void sofia_media_tech_patch_sdp(private_object_t *tech_pvt)
 }
 
 
-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;
index 62b5f10b2164e13ab46916ecb422049ee4da4c4a..3429f014ee37940073a32ee7e7ec3dac97040cea 100644 (file)
@@ -148,6 +148,9 @@ struct switch_media_handle_s {
        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;
 };
 
@@ -373,6 +376,60 @@ SWITCH_DECLARE(switch_t38_options_t *) switch_core_media_extract_t38_options(swi
 
 
 
+//?
+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)
@@ -2721,55 +2778,55 @@ SWITCH_DECLARE(switch_status_t) sofia_glue_ext_address_lookup(switch_core_sessio
 }
 
 
-
-
 //?
-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;
                }
@@ -2791,8 +2848,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_video_port(switch_core_
                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;
@@ -3367,7 +3424,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 
 
                        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));
@@ -3493,6 +3550,718 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 
 }
 
+//?
+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: